Evals
An eval is a scored check that sends messages to your agent and grades what it did. Each eval lives in a .eval.ts file under evals/, and eve eval runs them. Use evals to catch regressions when you change a prompt or a tool.
Evals talk to a real agent server over the same HTTP API as your users, through the TypeScript client. A passing eval means the agent started, accepted a request, and produced the asserted result. To control what tools return, define tool stubs in the eval.
defineEval
The evals/ directory sits at the app root. Each .eval.ts file exports one eval, or an array of evals that runs once per dataset row. The file path is the eval's id, so evals/weather/brooklyn-forecast.eval.ts becomes weather/brooklyn-forecast. Don't add an id or name.
An eval is one async test(t) function. It sends messages and records assertions through t:
test is the only required field; description, judge, tags, metadata, timeoutMs, and reporters are optional. The init template adds evals/**/*.ts to tsconfig.json, so eval code type-checks with the app.
evals.config.ts
Every evals/ directory needs exactly one evals.config.ts at its root. It sets the defaults that all evals share:
Every field is optional:
| Field | Sets |
|---|---|
judge | The model for LLM-as-judge assertions (t.judge(...)). Omit it to use typesafe-ai/jev. |
reporters | Reporters that observe every eval in the run, so one braintrustReporter() here covers all evals. |
maxConcurrency | The concurrent eval limit. |
timeoutMs | The per-eval timeout. |
repeat | How many times each eval runs, to measure repeatability. See Repeat evals. |
setup, teardown | Run-wide hooks before and after the run. See Run setup and teardown. |
CLI flags (--max-concurrency, --timeout, --repeat) and per-eval values take precedence over config defaults.
Run setup and teardown
Use setup to start shared resources or run migrations before eve starts the local agent server. Return shared values from setup, and release resources in teardown:
context is typed from the setup return value. To use that type in an eval file, pass the config's type to defineEval:
setup, every eval, and teardown share one context object in the eve eval process. The agent server never sees it, so class instances and functions work as values. Evals that run at the same time share these resources, so isolate any database records they change.
setup runs once per eve eval command, before the agent server starts. teardown runs after the local server and its sandboxes stop, even when setup, startup, or an eval fails. A teardown failure fails the command. The per-eval timeoutMs doesn't apply to either hook.
setup can return nothing, and teardown works without setup. teardown receives undefined when setup returns nothing or throws, so setup must clean up anything only it can reach.
Deterministic fixture models
mockModel gives a test agent fixed replies, so it runs without calling a model provider. A fixed reply is one line:
Pass a callback when the reply depends on the conversation. It receives lastUserMessage, userMessages, userMessageCount, the available tools, and prior toolResults:
The callback can return { text, toolCalls, usage } for deterministic tool loops or explicit token counts. Use the options form when a fixture also needs a custom model identity:
Omit the response to reply "Mock response". mockModel supports streamed and non-streamed replies and estimates token usage. Its context window is 1,000,000 tokens, so eve never compacts the conversation. To test compaction, set modelContextWindowTokens on the agent.
The model is part of the agent definition, so use mockModel in a separate test agent. That agent stays mocked locally and when you deploy it as an eval target.
The t context
t both sends messages and records assertions, so an eval is ordinary code that sends a message, then asserts on the reply.
- Send:
t.send(...)starts a conversation with its first message and returns the turn.t.session()starts an empty conversation. Send follow-ups withturn.session.send(...), and read the reply fromturn.reply. The full list of session methods is in the drive API. - Assert: use the three surfaces in the next section.
Three assertion surfaces
| Surface | Grades |
|---|---|
Methods such as t.calledTool("get_weather") | What the agent did: on t for the whole run, or on one session or turn. See Assertions. |
t.check(value, assertion) and t.score(…) | Any value, such as turn.reply or parsed JSON, or a 0–1 score you compute. See Assertions. |
t.judge("cites a source") | Quality, graded by a separate judge model. See Judge. |
t.judge grades the reply of the most recently finished turn. Pass { on: turn.session.transcript } to grade a whole conversation.
Gate vs soft
A failed gate marks the eval failed, and eve eval exits non-zero. A soft assertion appears in reports. A soft assertion below its threshold marks the eval scored, which fails the run only under --strict. A soft assertion with no threshold never fails.
t.judge(...), t.score(...), and similarity are soft by default; the rest are gates. Chain .gate(threshold?), .soft(threshold?), or .atLeast(threshold) to change one. See Severity.
Use await t.require(value, assertion) for a gate that must pass before the eval continues. Call t.skip(reason) first to skip an eval on a target that doesn't support it.
Run evals with eve eval
Exit code 0 means every eval passed its gates. See Running evals for the full flag list, exit codes, and CI guidance.
A good baseline
Start with a few small smoke evals: t.succeeded() plus one or two content checks, with dataset files in evals/data/. Add a judge or Braintrust when you need fuzzy grading or a shared place to review results. In CI, run eve eval --strict so soft threshold misses fail the build.
What to read next
- Cases: single-turn evals, scripted multi-turn evals, and dataset fan-out
- Assertions: run-level methods and
t.checkvalue assertions, with matchers and severity - Judge: LLM-as-judge grading and the judge model
- Targets: local vs remote targets for the same eval files
- Reporters: Braintrust experiments and JUnit XML
- Running evals: the
eve evalCLI, exit codes, and artifacts - Tools: the surface most evals assert on
