Skip to main content

The defineEval shape

Single-turn evals

t.send() drives one interaction, t.succeeded() and t.calledTool() are scoped assertions, and t.check() is a value assertion recorded immediately.

The Turn object

Multi-turn evals

Use t.newSession() when you need parallel, independent sessions.

Dataset fan-out

One file can export an array of evals:
That generates IDs such as sql/0000, sql/0001, and so on. See Dataset fan-out.

Sandbox workspace

Coding-agent evals are still normal .eval.ts files. test just prepares a Sandbox workspace, sends a task, and inspects the resulting files:
See Fixtures.

Report progress and diagnostics

setup handles this eval’s Fixture. Its second argument is bound to the eval’s setup phase; feedback from inside test(t) is bound to the eval’s run phase:
progress only updates short-lived status while the run is in flight; it never enters the result. diagnostic is committed with the current Attempt into the Record, but it does not replace an assertion or change the verdict on its own: business conclusions still come from t.check / t.require / gates, and you throw when the infrastructure cannot continue.

Eval lifecycle

setup(sandbox, ctx) prepares the Fixture; pair it with a teardown(sandbox, ctx) to clean up. Together they form this eval’s Fixture, and each runs once per Attempt. Execution order: setup runs after the Sandbox lifecycle hooks and the git baseline anchor, and before test(t); teardown is the first link in the Attempt’s teardown chain (eval teardown first, then agent teardown, then Sandbox teardown) — the Sandbox is still alive at this point, so teardown code can read it as usual. Most Fixtures do not need teardown — starting files written into the Sandbox and dependencies installed there disappear automatically when the Sandbox is destroyed. teardown is for Fixtures outside the Sandbox: temporary resources this Attempt created in a shared external service (a temporary repo, bucket, queue topic) that leak unless you clean them up. Multiple Attempts of the same eval (attempts greater than 1, or several experiments in the same batch running the same eval) run concurrently and share the same module, so a setup handle cannot live in a plain module variable — a later concurrent Attempt would overwrite it. Key it off the sandbox instance instead (WeakMap): a sandbox maps one-to-one to an Attempt, so it is a natural per-attempt key:
teardown runs if and only if this Attempt reached setup — a thrown error in setup does not exempt it, so teardown code must guard against resources that may not have been created. If teardown throws, or exceeds its 30-second cleanup budget, that only records a teardown-failed diagnostic; it does not change the verdict this Attempt already produced. To make a cleanup step affect the outcome, throw from setup or test — do not expect teardown to change the verdict.

Naming conventions

Filename

Only .eval.ts files are discovered by the runner.

Directory grouping

evals/billing/refund.eval.ts becomes the ID billing/refund.

Dataset

Good for many cases with the same structure and different inputs.

Sandbox workspace

Good for coding agents that need a real file system, commands, and diffs.