Skip to main content
Evals measure an agent version on a fixed set of cases before it goes live, and compare models, prompts and params without a redeploy. For the concepts and the panel, see Evals. The pieces:
  • A dataset is a list of items: an input, an optional expected answer, metadata, and the holds of the run it came from. Its draft is edited in place; publish freezes the draft into a numbered version (v1, v2…) that never changes.
  • An evaluator scores a run’s output: checks on the output, a field-by-field comparison with the expected answer, or an AI judge.
  • An eval is a dataset + an agent’s capability + a mapping from item to capability input + evaluators + repeats.
  • An experiment runs an eval on one version of the agent (live, previous or a candidate) over the dataset’s latest published version, optionally with a temporary config override (other models, prompts or params), and scores every run. A winning override becomes a candidate version that you promote.
All routes are under /v0/envs/{env}/. Datasets, evaluators and evals are addressed by name; items by i_N, dataset and agent versions by vN, experiments by e_N. Roles. Members and admins read, create and change datasets, items, evaluators and evals, and start, cancel and save experiments. Setting a dataset’s collect rule and making a candidate need the admin role (a candidate is a deploy). Datasets, evaluators and evals can’t be deleted yet.

A complete example

Datasets

string
1–63 lowercase letters, digits and dashes, starting with a letter or digit, unique in the environment. new is reserved. The same rule applies to evaluators and evals.
object | null
An optional JSON Schema (draft 2020-12) that every item’s {input, expected} must fit. An item without an expected answer is checked without the key.
integer
Active items in the draft.
integer
Collected items waiting to be accepted.
array
Published versions, newest first.
Publishing an empty draft is a 409 empty_draft. A published version never changes; editing the draft afterwards only affects the next version.

JSONL import and export

Import one {"input", "expected"?, "metadata"?} per line. Other keys are ignored, so Langfuse and LangSmith exports import as they are. Send it as application/x-ndjson, application/jsonl or text/plain; at most 1,000 lines and 10 MB. It is all or nothing: a 422 names every wrong line and adds none. Export writes the draft’s active items (version=draft, the default) or a published version’s, one {"input", "expected", "metadata"} per line.

Items

Add an item by hand, or copy a run:
A run must have completed (409 not_finished) and not belong to a session (409 session_run). Experiment runs may be added too. The run itself is never changed.
string
hand-written, run, import, collect or experiment.
array
The holds of the run it came from, with their decisions. Experiments hand them to the agent, so it can replay the human step without asking anyone (see Evals).
string
active (in the draft) or candidate (collected, waiting to be accepted).
string
Why a collected candidate doesn’t fit the item schema.
boolean
Its expected answer was changed by hand.
boolean
A suggested answer nobody has confirmed or corrected yet. A PATCH of expected or confirm clears it.

Collect rule

PUT datasets/{name}/collect (admin) turns reviewed production runs into dataset items automatically:
When a run of that capability completes after a person decided at least one of its holds (which: "decided"), or edited at least one item (which: "edited"), it is copied in as an item with source: collect: as a candidate to accept by hand (into: "candidates"), or straight into the draft (into: "draft"). An item that doesn’t fit the item schema is always a candidate, with its problem. Experiment runs and session runs are never collected.

Evaluators

version goes up on every config change; an experiment keeps the configs and versions it started with. Each evaluator gives several named scores per run, each {evaluator, name, passed, value, reason}; passed: null means “no score” (neither pass nor fail). Score and criterion names are 1–63 letters, digits, -, . and _, unique within the evaluator.
1–50 checks, one score each. Paths are output or output.a.b (output.items.0 for a list item).
One score per compared field of the item’s expected answer, named by its path. fields is "all" (every key of the expected answer) or a list of paths like address.city. An expected answer that isn’t an object gives one score, value. Items without an expected answer get no scores from it.
1–10 criteria, rubrics up to 2,000 characters, one score per criterion. The model must be on the environment’s Models page. It makes one call per run at temperature 0, given the input, the whole output and the expected answer (files are named by id, not sent). Its tokens are counted in the experiment’s judge_tokens. When the judge can’t be reached or doesn’t answer JSON, its scores are “no score”.

Evals

The eval names the capability, not a version: any version that has it can be measured. repeats is 1–10 (default 1); at most 20 evaluators. Changing an eval doesn’t change experiments already started.

Mapping

{"input": <template or null>, "expected": <path or null>}. null means as is: the item’s input is the capability’s input, and the item’s expected answer is compared with the whole output.
  • input is a JSON template. A string that is exactly {{ item.<path> }} (item.input.…, item.expected.…, item.metadata.…; list items by index) becomes the value at that path, of any JSON type. Every other string is literal.
  • expected is a path like output.fields: the part of the output that reference evaluators compare with the expected answer.

Fit check

Every item, mapped, checked against the input schema of a version’s capability. Defaults: the live version and the draft.
items is the needs-fix list with each item’s first problem. An experiment refuses to start while any item doesn’t fit.

Suggest answers

POST evals/{name}/suggest runs the agent — usually with a stronger model as an override — on the dataset’s items that have no expected answer, and keeps each output as that item’s answer, marked needs_review until a person confirms (POST …/items/{item_id}/confirm) or corrects it (PATCH its expected).
string
The version that answers; default the live one.
object
A temporary config, as for an experiment.
boolean
default:"false"
Once the answers are in, start the eval’s first experiment on the live version.
It is a labelling run: an experiment with purpose: "label", listed with GET experiments?purpose=label and never compared with scoring experiments. 409 nothing_to_suggest when every item already has an answer.

Experiments

Start an experiment

string
required
The eval’s name.
string
required
The agent’s live, previous or a candidate version (v3).
object
A temporary config: {"models": {role: model}, "prompts": {name: text}, "params": {key: value}}. It may only name keys the version’s config has, and models must be on the Models page. No new version is made.
integer
Runs per item, 1–10; default the eval’s.
The dataset’s latest published version is used, and every item must fit (else 422 items_do_not_fit with the needs-fix list). Each item × repeat runs as an experiment run on that version: it gets the override merged into its config and the item’s recorded holds (see the agent contract), and doesn’t appear in the dashboard, metrics, the runs list or webhooks. An experiment runs a few items at a time.

The experiment object

string
queued, running, completed, failed or cancelled.
integer
Item × repeat rows.
integer
Rows scored so far.
object
Pass rate per "<evaluator>.<score>": passed ÷ (passed + failed) over the runs that produced it; null when none did.
integer
Rows that passed every score.
integer
Rows whose run asked a person (neither pass nor fail).
integer
Rows whose run failed, was cancelled or couldn’t start.
number | null
Model calls of the item’s runs, child runs included, per item run.
integer | null
95th percentile run duration.
integer
Tokens the AI judges used.
boolean
An overridden model that some completed item’s runs never called — usually the agent doesn’t read its model from config.models.
string
The dataset draft its outputs were saved to, once they were.

Item rows

outcome is pending, passed (every score passed), failed (a score failed), asked (the run asked for a person), error (the run failed, was cancelled or couldn’t start; no scores) or no_scores (it completed but no evaluator gave a score). error says why a run couldn’t start.

Cancel

The experiment is cancelled at once; items not started become errors and its unfinished runs are cancelled. 409 experiment_finished once it has ended.

Save outputs as expected

Once the experiment has ended, each item’s input (with its metadata and holds) and its first repeat’s output, as expected, are added to a dataset’s draft with source: experiment. Items whose run didn’t complete are skipped. If an output doesn’t fit the dataset’s item schema, nothing is added. Use it to label a dataset with a strong model, then review the answers.

Make a candidate

When an override wins, make it a version: the experiment’s version with the override merged into its config, the same image, status candidate at once with no build. It is recorded as a deploy of kind config. Promote it with the Deploys API. Admins only.

Errors