Evaluations
Tests prove that a route renders and that a generated server honours its wire contract. Evals ask a different question: given a prompt, does the agent actually reach your plugin, and is the outcome the one you claimed? That answer is probabilistic, so the eval runner is built to report honestly rather than to look green.
Suites are typed modules
Eval suites are discovered by convention from evals/**/*.eval.ts, and each one default-exports
defineEvalSuite:
A case names its id, prompt, fixture, hosts (with a pinned model per host), invocation
mode, automatic, explicit, or none, its assertions, and how many trials to run. Case
ids must be unique within a suite. Suite discovery, the runs directory, and the optional semantic
grader are configured under the top-level evals config block; see
Configuration.
Writing an outcome grader
expectOutcome({ script }) names a module that default-exports one grader function. The path is
resolved relative to the suite file and must not climb out of the suite directory (../ past it
is rejected; the check is on the path, so a symlink inside the suite is followed wherever it
points). agent-bundle/eval
exports its contract: EvalGraderFunction takes an
EvalGraderContext and returns an
EvalScriptOutcome, synchronously or as a
promise. This is examples/skills-starter/evals/graders/release-result.ts verbatim; the suite
above names ./graders/status-result.ts, which has the same shape in examples/mcp-app:
The context is the trial the grader is judging:
The outcome is { outcome, detail }: outcome is pass, fail, or inconclusive, the same
three verdicts as every other assertion, and detail is the sentence shown beside the result in
the trial record. A module that does not default-export a function, or returns anything but that
shape, is a grader defect, not plugin evidence: the trial is reported EVAL_GRADER_FAILED and its
result stays inconclusive. Graders run in the eval process with the host's file system, so read the
fixture and the artifact; do not reach into the agent's session.
Three outcomes, not two
Every assertion resolves to pass, fail, or inconclusive, and declares the minimum
evidence it accepts. An assertion that needs stronger evidence than the harness produced is
inconclusive, never silently passed.
Assertion helpers default their minimumEvidence to the strongest bar their evidence can
support: expectExitCode, expectMcpCall, expectNoMcpCall, and expectOutcome default to
observed, while expectSkillActivation and expectNoSkillActivation default to inferred
because not every host publishes an activation event. Raise a default with
minimumEvidence: 'observed' when you want the weaker evidence to read as inconclusive instead
of as a pass.
Because an inconclusive trial produced no evidence, it cannot report success either:
agent-bundle eval exits nonzero when a run has any failing or any inconclusive trial.
Smoke evidence versus a reliability number
Fewer than three trials is reported as smoke evidence rather than a reliability number. One green trial is a signal that the path exists; it is not a rate.
Comparison rows are only aligned when every one of these facets matches: case, fixture, semantic grader identity, harness, host CLI version, invocation, and model. The artifact target digest is deliberately not an alignment facet. It is the thing under comparison. Facets a run did not record are labeled unverified rather than assumed aligned, and an unmatched facet makes the row non-comparable instead of producing a delta nobody should trust.
The optional semantic grader
A semantic grader is configured with exactly one pinned Claude model:
It runs only with agent-bundle eval --harness claude, and only for Claude-pinned cases. After
the primary trace is usable and the deterministic graders finish, Agent Bundle makes one
server-owned, plugin-free Claude grading call. Its fixed result id is claude-semantic, and its
request, raw stream, stderr, and canonical provenance are retained with the trial artifacts. A
malformed or failed semantic grader leaves the trial inconclusive rather than becoming plugin
evidence, a grader that broke is not a plugin that misbehaved.
Semantic grading requires a native Claude harness and a signed-in Claude Code session. Deterministic and Codex selections are refused when it is configured.
Workbench Evals
Open Advanced → Evals → Runs to admit a selected run, follow live progress, or cancel it through the run lifecycle. Each trial exposes its persisted raw evidence when present, plus recorded CLI, invocation, grader, and usage provenance.
Advanced → Evals → Compare shows recorded provenance and usage and only includes aligned case, fixture, harness, invocation, host and model, CLI, and grader facets; unmatched facets are labeled non-comparable or unverified. Trial duration is persisted; provider token usage is shown only when the native stream reported it.
Native harnesses
The deterministic harness needs nothing installed. The native Claude and Codex harnesses run the real host CLI, and the rules there are strict:
- This package never accepts, requests, injects, or persists a model-provider API key.
- Native harnesses use an already installed, signed-in CLI, after provider-key environment variables are removed.
- A missing, incompatible, or unauthenticated CLI is reported as a harness failure, distinct from a plugin failure.
- Native smokes are opt-in and are not part of an ordinary test run.
- Codex exposes no authoritative Skill-activation event, so Codex activation evidence is
inferredand is never reported asobserved.
For a manual authenticated local smoke, complete each CLI's normal interactive sign-in first,
then verify a supported non-prerelease CLI. Claude Code must be at least 2.1.232; Codex must be
at least 0.147.0:
Each Codex trial sets a temporary CODEX_HOME and copies only the installed CLI's opaque
auth.json into it. Your normal Codex home, configuration, and installed-plugin state are not
used as trial state and are left unchanged. The full credential contract is in
Security.
Next
- Distribution: turning a validated artifact into an installable bundle.
- Limitations: what evals and harnesses currently do not prove.