.analyze() is the last step in the evaluation chain. It runs the same durable, multi-stage pipeline as the dashboard’s “Analyze” button: each response is scored by 1-3 LLM judges, then reduced through question- and cluster-level summaries into one final qualitative report, returned as a Report object.
Numeric scores (
average_rating, similarity metrics) are ready right after .finalize(), so you don’t need to wait for .analyze() just to see how the run went. Because .analyze() polls a job until it completes, it can take noticeably longer than a single LLM call for larger runs; progress is shown in the terminal while it waits.Controlling the analysis
Check on a long-running analysis without calling
.analyze() again, even from a separate script execution:
Fields
Each
rating sub-field is one of "high", "medium", "low". recommendations[].category is one of "instructions", "tools", "knowledge", "reasoning", "consistency", "other"; priority is "high", "medium", or "low".
Reading it in your terminal
report.dashboard_url to review the full report, per-question breakdowns, and instruction-change suggestions in the dashboard.
Per-result rows without an analysis
results() returns the scored rows - no analysis job, no extra judge calls - for asserting
on individual results in scripts and CI. Rows are typed RunResultRow objects with snake_case
attributes (dict-style access still works but is deprecated and warns; row.raw keeps the
full wire dict):
rating/justification, a status ("scored", "skipped" when the judge
could not score it - rating stays None, not 0 - or "failed" when the result carried an
error), the linked trace_id, latency_ms and token counts, and the similarity metrics
(cosine_similarity, jaccard_similarity, bleu_score, rouge_score).
client.evaluations.get_run(run_id) fetches the same payload later, from a different process.
