A minimal experiment
local. agent holds an already configured Adapter instance; connection parameters such as the address and auth of the application under test are passed to the Adapter factory and are not written anywhere else.
Compare two models
One Experiment file is one configuration. To compare two models, write two files and change only themodel line:
model is passed to the Adapter as ctx.model. The Adapter must put it into the request it sends to the application, or the application will not really switch models; see Connect Your Agent.
attempts: 3 runs each eval 3 times. The Agent answers differently every time, so a pass rate from a single run does not say much.
Compare two prompt versions
The prompt version lives inside the application, and NiceEval cannot see it. The approach is the same as A/B testing in a product: the application accepts a flag and switches the prompt based on it; the Experiment assigns the flag’s value.experiments/prompts/v2.ts changes promptVariant to "v2" and is otherwise identical word for word. The less the two configurations differ, the more the score difference can be attributed to the prompt.
The Adapter forwards ctx.flags to the application unchanged:
flags is a flat object whose values can only be strings, finite numbers, or booleans. Nested objects, arrays, null, and explicit undefined are all rejected before the run. Evals can read the same values with t.flags.
When you need to check that flags are valid or fill in defaults, declare a synchronous parseFlags(input: unknown) on the Adapter. Its return value decides the type of flags in the experiment, and the normalized value takes part in the result reuse decision.
The most common mistake is writing the same flags or the same model in both files, for example both reading the default of the same environment variable. Runs and reports look normal, but the two columns compare the same configuration.
Run a group, or just one cell
Positional arguments select Experiments by ID prefix. Directories only organize IDs and batch selection:--dry; see Select and Preview the Run Scope.
See the comparison
After both configurations run, view each in the terminal:Summary lists these items:
Observed is the number of Attempts with results out of the planned number. When the two numbers differ, some Attempts have no result yet, and the pass rate cannot be compared directly with the other side.
Besides the pass rate, look at duration, tokens, cost, and the kinds of failures. A configuration with a slightly higher pass rate at double the cost is not necessarily worth switching to. To compare two Runs side by side, see Compare Pinned Runs; to view in the browser, use niceeval view.
Make the comparison meaningful
- Keep the set of evals unchanged during the comparison; otherwise the two sides are not comparing the same evals.
- For highly non-deterministic Agents, especially Coding Agents, run each configuration at least 3 times.
- Change one variable at a time. If you switch the model and the prompt together, you cannot tell which one deserves the credit.
- Group failures by cause; do not just look at the total score.
Run only some evals
Each Experiment chooses which evals to run withevals, defaulting to all. You can write an array of ID prefixes, or a function:
eval.id is the in-project ID derived from the file path, not an absolute path, so you can test it directly with startsWith.
Common fields
For the full set of fields, see the defineExperiment reference.
Different evals need different environments
A batch of real tasks may need different runtime versions, for example some tasks need Python 3.9. In that case, write the Sandbox directly on the eval, so the task and the environment it needs live together:One application with several models
When the application has different internal roles such as planning, replying, and reviewing, each using its own model, assign them by purpose withmodels:
ctx.models and hands it to the application, and on each model request it writes the matching modelRole in ctx.recordUsage. That way usage and cost can be counted separately by purpose; roles that are never called incur no cost.
models cannot be written together with model or reasoningEffort. Agent-style Adapters use only a single model.
After the run, use niceeval show @<locator> --usage to see each model’s usage and cost in one run. When Judge usage was not reported, it shows as unavailable, and the total cost gives only the known part.