Skip to main content
Put a check between an attempt and the next step, and let the check decide what happens: the step runs again with the findings, the run takes another branch, or the run stops. That is what an eval is here. It runs inside the workflow, on this attempt, and its result is the next step, not a report on the side. Use one wherever a model’s first answer isn’t the last word.

Run a test

A command is the plainest eval: no model, no tokens, and no argument about the verdict. Its exit code decides:
examples/command-kickback.ts (excerpt)
A red run carries the command’s captured output to implement as the finding, and the writer runs again with it. A command’s result can also choose the branch that runs next, through passed(name) and failed(name) on the steps that depend on it. Some people call a test run a code eval. Here it’s a test.

Ask a judge

An LLM-as-judge reads the writer’s result and returns a decision with findings. In a workflow(), the judge is a review seat from a different model family than the writer, and the team is refused before any model runs when they share one:
examples/teams/writer-reviewer-pair.ts (excerpt)
The judge’s decision is its reply: the panel reads the first JSON object in it. A rejection goes to write with the findings, as many times as that stage’s retry allows. A reply with no decision is asked for once more, then counted as an engine error, not a rejection.

Ask several

A panel is a judge eval with a threshold. Several reviewers read at once, and agree says how many must accept:
examples/teams/threshold-panel.ts (excerpt)
Set agree to the number of reviewers when one dissent must be enough to fail the step. Below that, the change can pass despite a dissent, and the dissent is still on the record. The judges decide whether the writer runs again.

Pick a winner

A tournament runs the same task several times, in a worktree each, and a judge function scores every candidate that passed:
examples/tournament.ts (excerpt)
The judge reads the files on disk, not the candidate’s report of itself. The highest score lands and the rest leave nothing behind.

Score a condition

A scored eval gates a step on a number. agentCheck asks an engine one question about the evidence and reads back a verdict with a confidence, or a score per dimension you name, and the gate opens when the result clears the threshold you set. confidenceCondition reads a confidence the job wrote in its own text, and minConfidence reads the one on the last outcome. All three are conditions on the graph, so a when or an until can hold a step to them. No example file shows one yet; the graph contract lists them.

Evals vs trace scoring

Both have a place. A dataset tells you how a prompt did last week; an eval here stops a bad attempt from becoming the next step today.

Three shapes, one umbrella

A feedback loop is the umbrella: a check fails a step, the findings travel, the step runs again. Three shapes have their own names, and each lives on its own page: the evaluator-optimizer pair on A writer and a reviewer, the eval loop on A review panel with a threshold, and the refinement loop on Translate and reflect. Feedback loops sets them side by side.

Limits

  • Confidence isn’t correctness. A judge’s confidence is the model’s own number. A high score clears a gate; it doesn’t prove the work is right. Put a test or a person behind the gates that matter most.
  • A judge is a model. Its verdict rests on the material the seat could open, and the runtime uses the identity the engine reports. Cross-family review reduces a model approving its own habits; it doesn’t remove judgement from the loop.
  • Every eval costs its limit. A judge, a panel and a scored condition each spend a call per round. The retry or maxKickbacks on the target caps the rounds, and the run fails with the last findings when it’s spent.

Next steps