Run and compare evals
introspection eval run runs a Vitest suite against your local recipe and
saves the run under eval-runs/. eval compare lines up two runs case by case.
This page uses CLI 0.52.0 or later.
You need: a suite (Add cases to an eval) and the model provider key your agent uses.
1. Run a baseline
On the unchanged recipe, from the recipe root:
introspection eval run -p evals/vitest-p takes the suite directory or one .eval.ts file. It exits 0 even when
cases fail. “No test files found” means the recipe’s Vitest config lacks the
settings eval create names.
2. Score each case
Only a case with a score counts. A case with no judge, or whose expect()
throws, is incomplete: it never counts as passed or regressed. Score with a
YAML judge (recipeJudge) or a code judge built with createJudge, which can
give partial credit:
import { expect } from "vitest";
import { createJudge, describeEval } from "vitest-evals";
import { createRecipeHarness, recipeCases, recipeJudge } from "@introspection-ai/vitest-evals";
const CodesRecall = createJudge<unknown, string, { expected: { codes: string[] } }>(
"codes-recall",
({ output, expected }) => {
const found = expected.codes.filter((code) => output.includes(code));
return { score: found.length / expected.codes.length };
},
);
describeEval("Billing codes", {
harness: createRecipeHarness(),
judges: [recipeJudge("cites-policy")], // runs on every case
}, (it) => {
it.for(recipeCases("billing-codes"))("$name", async ({ input, expected }, { run }) => {
const result = await run(input);
await expect(result).toSatisfyJudge(CodesRecall, { expected: expected as { codes: string[] }, threshold: 1 });
});
});Each case scores 0 to 1: the mean of its judges. It passes at 1.
3. Change one thing, run again, compare
introspection eval run -p evals/vitest
introspection eval compare <baseline-run-id> # against the latest run
introspection eval view # open the reportEach case is improved, regressed, unchanged, new, removed, or
incomplete (not measured: no score, or an error). Keep the model, cases and trials
fixed: compare refuses two runs whose cases changed.
4. Keep a baseline
Commit the suite, run it, then promote that complete run and commit
baseline.json so later runs compare against it. Promote refuses a run made
with uncommitted changes:
introspection eval run -p evals/vitest
introspection eval baseline promote <run-id> # writes baseline.json in the suite directory
introspection eval compare --baseline # latest run vs the committed baselineFor the suite above that file is evals/vitest/baseline.json. To gate pull
requests on it, see Gate pull requests.
Verify
The case you fixed is improved and every other case is unchanged.
Per-judge means, trials, and comparing agents
Mean score per judge. One createJudge per field gives one score name per
field:
introspection eval compare --baseline --query candidate.scores
introspection eval compare --baseline --query "{base:base.scores,candidate:candidate.scores}"The full comparison (-o json) also has score.base and score.candidate
(mean over cases complete in both runs), candidate.cases_passed,
candidate.cases_total, and summary (case counts per change).
Flaky cases. Each trial is a separate run:
introspection eval run -p evals/vitest --trials 3
introspection eval compare <trial-1-run-id> <trial-2-run-id> --query "cases[?change!='unchanged'].id" -o table--trials 3 prints three run IDs. A case listed here gave a different result
in the two trials. To keep a baseline, promote one complete trial.
Two agents or models. Run the suite once per agent variant:
introspection eval run -p evals/vitest --agent agent-small
introspection eval run -p evals/vitest --agent agent-large
introspection eval compare <small-run-id> <large-run-id>Editing cases. Any edit to the suite folder (cases, dataset rows, helpers) or its judges changes every case, so compare refuses the old baseline. Commit the edited suite, run it on the unchanged recipe, promote that run, then change the recipe.
Where runs go. Set INTROSPECTION_EVAL_RUNS_DIR (an absolute path) to save
runs somewhere other than eval-runs/. Promote only a complete run of the
whole suite.
Limits
| Not supported | Do this instead |
|---|---|
| Eval history on the platform | Upload eval-runs/ as a CI artifact per commit. |
| A pass rate per case across many trials | Compare trials pairwise (above). |
| Side-by-side human preference | Compare --agent runs and read both outputs in eval view. |
Or ask your agent: “Run the refund-policy eval before and after this change and tell me what regressed.”