Skip to main content
defineEval is the main entry point for authoring evals. Each eval file calls it once, passing a description and test(t), and default-exports the result.
Do not provide id or name. NiceEval derives the eval ID from the file path.

defineEval options

id

Derived from the file path; hand-writing it in the definition is not allowed.

description

One-line description, shown in niceeval list and the view; purely informational — it does not affect scheduling or assertion evaluation.

tags

Tags, for the CLI’s --tag filter and view categorization; a filtering dimension independent from ID-prefix filtering.

environment

The environment profile id this eval needs (provider-neutral, e.g. "python-3.9-astropy-4.2"); translated into that provider’s prebuilt artifact via the Sandbox spec’s environments table.

judge

Overrides the project-level Config.judge, taking effect only for this one eval (e.g. to switch to a more expensive judge model).

reporters

Overrides / adds to the project-level Config.reporters, taking effect only for this one eval.

timeoutMs

Overrides the project-level / CLI timeout for a single attempt (milliseconds), taking effect only for this one eval.

metadata

Arbitrary extra metadata, saved as Attempt Provenance; does not participate in scheduling or assertion evaluation, and is meant for custom reporters to consume.

diff

Adjusts the attribution exclusion list for the agent diff (Sandbox agents only; see docs/feature/eval/README.md): both arrays are gitignore-style globs (relative to workdir). By default, .git, node_modules, build artifacts, and package-manager caches are excluded; ignore adds further exclusions on top of the default list; include has the highest priority and explicitly adds matching paths back. The composition rule is fixed as “default ∪ ignore, then punched through by include”; the list is frozen at the ledger’s anchor point.

setup

Eval-level preparation: receives the Sandbox (after the workspace is uploaded and the git baseline is set, before dependencies are installed). Commands default to the environment’s own declared identity (the Docker image USER, the Compose service user:, and so on); when installing system dependencies, pass { user: "root" } to runCommand (e.g. runCommand("apt-get", ["install", …], { user: "root" })) — semantics are consistent across providers. The second parameter is a narrow context bound to eval.setup (ctx.progress / ctx.diagnostic, see docs/feature/eval/README.md). setup returns no value; to pass an artifact through to teardown, key it off the sandbox instance (concurrent attempts share the same module, so a plain module-level variable would get overwritten by other attempts).

teardown

Eval-level cleanup: the first link in the attempt’s teardown chain (eval.teardownagent.teardownsandbox.teardown), with the Sandbox still alive at this point. Runs if and only if eval.setup’s point in time was reached — an error thrown by setup or test does not exempt it, and not declaring setup does not affect whether it fires. An error thrown, or exceeding the 30s cleanup budget, only records a teardown-failed diagnostic and does not change the verdict. Use it for temporary Fixtures outside the Sandbox (a temporary repo / bucket); things inside the Sandbox are reclaimed automatically when it’s destroyed and don’t need this.

test

The eval body: receives the TestContext, drives the conversation / Sandbox operations, and asserts in place.

Test context: t

t (TestContext) is the high-level context the eval author receives. The runner assembles it according to the agent’s actual capabilities — fields like t.sandbox are only meaningful on agents constructed with defineSandboxAgent; the full rule set is in the capabilities reference. All members:

send

Sends a message on the default session (a string or a structured message), returning that turn’s TurnHandle. The events are also accumulated into the default session’s cumulative event stream, for the scoped assertions below to use.

sendFile

Sends a message with an attached file (image, etc. — multimodal input). path is relative to the project root; after reading, it is base64-encoded and handed to the adapter via TurnInput.files.

requireInputRequest

Retrieves a pending HITL input request on the default session; without a filter it requires exactly one, and throws if it can’t get one.

respond

Answers the pending input request(s) on the default session, returning the continuation’s TurnHandle. String form matches requests in order; when multiple requests are paused together and you need to name which one you’re answering, use the RespondAnswer object form (see its type comment).

respondAll

Answers every pending input request on the default session in bulk, using the same optionId.

reply

The assistant’s reply text for the default session’s most recent turn.

sessionId

The adapter-side default session id (only present for agents with a session concept).

events

The default session’s cumulative event stream (across every turn on that session).

newSession

Opens another, independent session line, returning its SessionHandle — not void. This is the key entry point for multi-session isolation: sending and asserting on the new session are isolated from the default session and from every other newSession() session — commonly used for scenarios like “multiple users in parallel conversations” or “one main line plus one side branch.”

signal

The abort signal for this attempt; fires on timeout / EarlyExit / user Ctrl-C, and is passed to the adapter’s long-running calls for cancellation.

model

The model name used for this attempt (decided by the experiment/CLI flag); omitted means the agent’s native default, not “no model.”

reasoningEffort

The reasoning effort for this attempt (e.g. “low”/“medium”/“high”; valid values are decided by the adapter/model).

flags

The experiment flags in effect for this attempt (a read-only view of experiment.flags; an experimental condition, not a command-line switch).

progress

Scoped feedback: reports a long-running step the eval itself is performing (uploading a Fixture, running a build, …). A short-lived status with scope fixed to eval.run; it only reports, it does not assert (see docs/feature/eval/library/context.md, “Reporting long steps back to the run”).

diagnostic

Scoped feedback: reports an issue that should be kept around after the run ends (a permanent event, recorded in the attempt’s diagnostics). Even when level is “error” this does not automatically change the verdict — the test’s conclusion is still decided by assertions.

log

An alias for progress({ message: msg }) (debug logging); does not appear in the final result.

skip

Immediately aborts this eval and forms a skipped Verdict in the niceeval.verdict channel; reason cannot be empty.

check

Runs a ValueAssertion against any value, returning an AssertionHandle that can be chained with .gate() / .atLeast(). Assertion evaluation is deferred until finalize at the end of the eval; the call itself is synchronous and never throws — a failure just records a failed assertion, it does not abort the rest of the code. Use require for “abort the eval immediately if this isn’t met.”

require

Runs a ValueAssertion against any value, evaluated immediately (when awaited); if it isn’t met, throws and aborts the rest of the eval’s steps (the assertion is still recorded in the report, and does not affect other already-recorded assertions). The difference from check: check only records and never throws, with assertion evaluation left to the end; require evaluates on the spot and aborts on failure — suited to “if this prerequisite isn’t met, nothing written after it matters.” On success it returns the original value with its type preserved.

group

Groups a set of assertions under a titled section (analogous to vitest’s test('title', ...)). Purely for organization/reporting — it does not change assertion evaluation: every assertion inside the group is still evaluated independently. Can be nested (titles joined with ›).

succeeded

Asserts the default session’s cumulative status is “completed” (across every turn on that session, not just the last one).

parked

Asserts the default session is currently stuck on an HITL input request.

messageIncludes

Asserts the default session’s cumulative assistant replies contain token (across every turn on that session, not just the last one).

calledTool

Asserts the default session has cumulatively called the named tool; match can constrain arguments / count / status.

notCalledTool

Asserts the default session has not cumulatively called the named tool (or not under the match condition).

toolOrder

Asserts the default session’s cumulative tool calls appear in the given order (other calls may be interleaved).

usedNoTools

Asserts the default session has not called any tool so far.

maxToolCalls

Asserts the default session’s cumulative tool call count does not exceed max.

loadedSkill

Asserts the default session has cumulatively loaded the named skill.

noFailedActions

Asserts the default session has no cumulative failed tool calls / commands.

event

Asserts the default session has cumulatively seen an event of the given type; opts.count can constrain the occurrence count.

notEvent

Asserts the default session has not cumulatively seen an event of the given type.

calledSubagent

Asserts the default session has cumulatively called the named subagent; match can constrain count / status / remoteUrl.

eventOrder

Asserts the default session’s cumulative events appear in the given type order (other events may be interleaved).

eventsSatisfy

Asserts against the default session’s whole cumulative event stream using a custom predicate; label is required and becomes the assertion’s title.

sandbox

A restricted Sandbox view: can run commands / read and write files / view the final diff, but cannot stop the Sandbox itself (see SandboxHandle).

usage

The default session’s cumulative token usage and estimated cost.

maxTokens

Asserts the default session’s cumulative token usage does not exceed max.

maxCost

Asserts the default session’s cumulative spend (USD) does not exceed usd.

judge

The available judge namespace (t.judge.autoevals.*).

Judge assertions

t.judge.autoevals currently has three methods: factuality (whether the reply is consistent with the expected facts), closedQA (whether the reply satisfies the given question or rubric), and summarizes (whether the reply is a valid summary of the given source text source). All three directly use scorers from the autoevals (braintrust) library; { on: t.reply } specifies the text being scored.

Turn return type

t.send(...) returns a TurnHandle: convenience fields derived from the event stream, plus a full set of turn-scoped assertions.

events

This turn’s raw event stream (tool calls, message deltas, etc.); all the derived fields below are computed from it.

toolCalls

List of tools called within this turn, derived from events.

status

This turn’s end status: “completed” ended normally, “failed” errored, “waiting” stuck on an HITL input request.

message

The assistant’s final text reply for this turn (the concatenation of the message deltas in events).

data

Structured output attached by the adapter (if any), for outputEquals / outputMatches to compare against.

usage

This turn’s token usage and estimated cost (present only for agents that reported usage).

outputEquals

Asserts data deep-equals the given value.

outputMatches

Asserts data satisfies the given schema (e.g. a zod schema).

messageIncludes

Asserts this turn’s assistant reply contains token (limited to this turn’s event stream, not across turns).

succeeded

Asserts this turn’s status is “completed”.

parked

Asserts this turn is stuck on an HITL input request (status is “waiting”).

calledTool

Asserts this turn called the named tool; match can further constrain arguments / count / status.

notCalledTool

Asserts this turn did not call the named tool (or not under the match condition).

toolOrder

Asserts this turn’s tool calls appear in the given order (other calls may be interleaved).

usedNoTools

Asserts this turn did not call any tool.

maxToolCalls

Asserts this turn’s total tool call count does not exceed max.

loadedSkill

Asserts this turn loaded the named skill.

noFailedActions

Asserts this turn has no failed tool calls / commands.

event

Asserts this turn saw an event of the given type; opts.count can constrain the occurrence count.

notEvent

Asserts this turn did not see an event of the given type.

calledSubagent

Asserts this turn called the named subagent; match can constrain count / status / remoteUrl.

eventOrder

Asserts this turn’s events appear in the given type order (other events may be interleaved).

eventsSatisfy

Asserts against this turn’s whole event stream using a custom predicate; label is required and becomes the assertion’s title (the predicate itself is opaque, so the burden of explanation falls on label).

maxTokens

Asserts this turn’s token usage does not exceed max.

maxCost

Asserts this turn’s spend (USD) does not exceed usd.

judge

The judge namespace available for this turn (t.judge.autoevals.*).

Dataset export

Array exports generate stable IDs: file/0000, file/0001, and so on. When you already have a stable business key, you can instead default-export a Record<string, EvalDef>. For example, the key 15193 in swelancer.eval.ts generates swelancer/15193. A key must be a non-empty single path segment: it cannot be . or .., and cannot contain /, \, or control characters; discovery order is fixed by lexicographic order over the keys.