Skip to Content
DocumentationEvaluateEvaluation Reference

Evaluation Reference

Commands

CommandWhat it does
./manage.py runeval <suite.yaml>Runs the suite and writes its reports.
./manage.py validateeval <suite.yaml>Checks the suite, its cases, mocks and metrics, that every model has a price when a budget is set, and prints the planned run count. Makes no LLM calls.
./manage.py evalschemaPrints the JSON Schema of suite.yaml, for editor completion.
./manage.py listevalmetricsLists the built-in metrics with their value types and params.

runeval options

OptionWhat it does
--model MRuns this suite model (by label) or any Provider:model. Repeatable.
--variant VRuns this variant besides the default. Repeatable.
--prompt-file FAdds the file as a system prompt variant named after the file.
--case ID, --tag TRuns these cases, or the cases with this tag. Repeatable.
--rerun-failed SRuns the cases that failed in a summary.json, a run directory or latest.
--repeats NRuns per case, model and variant.
--baseline SAdds a diff against an earlier run (summary.json, a run directory or latest). When the two runs cover different cases, e.g. with --rerun-failed, the diff compares each case’s status.
--budget USDStops starting runs once this much is spent; overrides budget_usd.
--parallel NRuns this many at once (default 1).
--reports a,bWrites these reports; overrides reports.
--note TEXTRecorded with the run in the history, e.g. what you changed.
--format jsonPrints summary.json to stdout; logs go to stderr.
--historyPrints the suite’s earlier runs and exits.
--allow-real-integrationsLets an existing agent’s unmocked integrations run for real.
--keep-run-dataKeeps the sandbox data set and conversations for inspection.

Exit codes

CodeMeaning
0Every candidate reached min_pass_rate, or the suite sets none.
1At least one candidate is below min_pass_rate.
2The suite or an option is invalid, e.g. a budget with a model that has no price.
3The run stopped early, at the budget or at a call it had no price for; it is marked partial.
4The run crashed.

Suite

Only agent, metrics and cases are required. Suites and Cases walks through each field with examples.

FieldMeaning
name, descriptionThe name defaults to the suite’s directory name.
agent{type: <agent key>, config: {...}} runs in a throwaway sandbox data set; {id: N} runs an existing agent.
kindexecution or conversation; defaults to execution when the agent type has an agentic execution. See Conversations.
execution_keyThe agentic execution to run; needed only when the agent type has several.
integrationsThe mocks, see Mocks.
models{provider, model, label, pricing} each. Left empty, the data set’s configured model runs.
variants{name, system_prompt_file} and/or {name, agent_config}, each compared against default, the agent’s own prompt. agent_config is deep-merged over the agent’s config; lists are replaced whole.
judgeThe model llm_judge and llm_classify ask; it also decides goal_reached.
user_modelThe model playing simulated users in a conversation suite.
repeatsRuns per case, model and variant (default 1).
budget_usdSpending limit for a run.
min_pass_rateMinimum pass rate per candidate, e.g. 0.8. With it, report.md opens with a verdict and a candidate below it exits 1; without it the run reports its results and gives no verdict.
metricsMeasured on every case.
reportsAny of report, results, comparison, cases, metrics, traces, transcripts (default report, results). summary.json is always written.
casesA case file, a directory of them, inline cases, or a list of these.

A candidate is one model and variant, shown as <model label>/<variant>. A model’s pricing (input_per_million, output_per_million, cached_input_per_million) overrides the bundled price table for that model.

Cases

FieldMeaning
idUnique across the suite.
description, tagsShown with the case’s failed runs in report.md; tags also select cases with --tag.
filesAttached to the conversation, relative to the case file: PDFs and images (.png, .jpg).
inputThe execution’s input fields.
user_messagesIn a conversation, the user’s messages, sent in order.
simulated_userIn a conversation, an LLM user: goal, persona, facts, max_turns, or class and params for your own simulator.
expectedWhat metrics compare against, see below.
integrationsOverrides of the suite’s mocks: config is deep-merged, and a method’s behaviour replaces the suite’s.
metricsAdded to the suite’s, or replacing one of the same name.

expected follows these conventions:

  • expected.output.<field>: the execution’s output, read by json_subset, field_match and list_match.
  • expected.mock_calls.<method>[i].<arg>: the arguments of a mock’s i-th call, read by mock_calls. An empty list expects no calls.
  • expected.failure_code: the run should fail with this code; execution_succeeded then checks for that failure.

In cases.csv each row is a case: id, description, tags and files (;-separated, or a JSON list), input.<field>, expected.<dotted.path> (numbers index lists), and any other column, which reaches custom metrics as case.extra. A cell starting with [, { or " is parsed as JSON; any other cell stays text. CSV and YAML cases can be mixed; ids must be unique.

Metrics

Every metric config takes type, name (defaults to the type; required to use a type twice), description (what it checks in plain words; report.md explains its column with it), params, pass_threshold, required and aggregate.

Measured on every run, with no config:

MetricValueMeasures
execution_succeededboolThe run succeeded, or failed with expected.failure_code
failure_codelabelThe run’s failure code; none when it succeeded
attemptsnumberAttempts the validator loop took
first_attempt_successboolThe right outcome without a validator retry
duration_snumberWall-clock seconds
cost_usdnumberThe agent’s LLM cost in USD; the judge’s is judge_cost_usd
input_tokens, output_tokensnumberTokens over every LLM call
llm_calls, tool_callsnumberLLM calls and tool calls the run made

A conversation suite measures conversation_completed, conversation_end, turns, goal_reached and user_cost_usd in place of the first four; see Conversations.

Set in the suite with type:

TypeValueMeasuresParams
json_subset0–1Share of expected.output fields the output matches, see Metricspath, modes per field, coerce
field_matchboolOne output field against its expected valuepath, expected_path, mode, coerce
list_match0–1F1 of an output list against the expected onepath, expected_path, key, fields, coerce
mock_calls0–1F1 of what reached a mock against expected.mock_calls; without arg, of the calls themselves in any ordermethod, arg, key, fields, coerce, skip_failed
json_schemaboolThe output conforms to a JSON Schemaschema or schema_file
tool_calledcountTimes the agent called a tool, optionally with given argumentsname, args, coerce
tool_not_calledboolThe agent never called a toolname
tool_orderboolThe agent called tools in this ordersequence, strict
mock_calledcountTimes a mocked method was called, optionally with given argumentsmethod, args, coerce
trace_eventboolSomething happened during the runevent: retry, tool_error, validator_failed[:code] or stop_execution
llm_judge0–1A judge model grades the run against criteria you writecriteria (name, description, weight), scale (binary, 1-5 or {min, max}), include, samples, prompt/prompt_file, judge
llm_classifylabelA judge model answers a question with one of your labelsquestion, labels, include, prompt/prompt_file, judge
  • Match modes (mode, modes, fields): exact, ci, numeric[:tolerance], fuzzy[:threshold], regex. coerce: true compares "2" and 2 as equal. skip_failed: true leaves out mock calls that raised, so a call the agent fixed and retried scores once.
  • key and fields pair list items by one field and check the others, e.g. key: 0, fields: {1: numeric} for [sku, quantity] pairs. List scores report precision and recall as components and the missing, extra and mismatched items as details.
  • include chooses what the judge sees: input (the case input and file names), outcome (how the run ended and the calls to each mock, so a missing order is stated), output, expected (the case’s answer key), trace_summary (tool calls, mock calls, attempts) and, in a conversation, transcript (each user message and answer, with what each tool called in that turn returned). The default is outcome, output, expected for llm_judge and outcome, output for llm_classify; in a conversation, transcript takes the place of output. llm_judge scores each criterion separately, reports each as a component (shown as success or failure with scale: binary) and keeps the judge’s reasoning per criterion, which report.md, results.csv (<metric>.reasoning), metrics.csv and runs/*.json show.
  • Custom metrics: set type to the dotted path of a BaseMetric subclass, see Add your own metric.

Each metric is explained with an example in Metrics.

Pass thresholds

pass_threshold takes one of equals, in, or min and/or max, e.g. pass_threshold: {min: 0.95}. A bool metric without one needs equals: true. A run passes when it meets every required pass threshold; required: false reports a missed one as a warning. A metric with no value misses its threshold.

Aggregates

Across runs, numbers aggregate as mean, bools as rate and labels as distribution; set aggregate to mean, rate, sum, min, max, p50, p95 or distribution to change it. Each candidate also gets pass_rate, flaky_rate and, in an execution suite, first_attempt_pass_rate. A case is flaky when its repeats both passed and failed.

Results and history

<suite>/results/ keeps one directory per run, latest pointing at the newest, and a .gitignore so results stay out of git. results/history.jsonl gets one line per candidate of each run: the run, git commit, status, spend, note, prompt hash, pass rates and mean cost. runeval --history prints it.

Last updated on