How an evaluation suite is built and kept alive
- Collect casesreal failures, logs, experts, edge cases
- Label and splitreference answers; dev vs held-out
- Grade each trialcode, model and human graders
- Read transcriptsare the failures fair?
New failures from review or production become new test cases
Where the test cases come from
Anthropic's guidance on evals starts with one principle: be task-specific. The dataset should mirror the real distribution of inputs the system will see, edge cases included. A set of tidy examples someone wrote on day one measures how well the system handles tidy examples.
Anthropic's engineering team recommends starting early and small: 20–50 simple tasks drawn from real failures beats waiting until you have hundreds. Good sources are the checks people already do by hand before a release, and the bug tracker and support queue — each reported failure is a ready-made test case with a known wrong answer.
| Slice of the dataset | Example (support assistant) | Why it's there |
|---|---|---|
| Representative traffic | A sample of last month's real questions, anonymised | Keeps the score honest about typical use |
| Known failures | Tickets where the old bot gave a wrong refund policy | Proves the fix, then guards against regression |
| Edge cases | Empty input, very long input, typos, ambiguous asks | The docs list these as cases to include deliberately |
| Should-not cases | Questions that must be declined or escalated | Balances the set so over-triggering is caught too |
| Adversarial | Emails and documents with embedded instructions | Measures security, not just quality |
Two quality rules apply to every case. First, it should be unambiguous: Anthropic's test is that two domain experts would independently reach the same pass or fail verdict. Second, it should be solvable — writing a reference answer or solution proves that. If experts disagree about a case, the case is measuring your specification, not your system.
Balance matters as much as coverage. Anthropic describes building web-search evals for Claude.ai in both directions: questions that need a search (a weather forecast) and questions that don't (who founded a well-known company). An eval that only tests “should search” rewards a system that searches for everything.
Splits and suites
Keep a held-out set that nobody tunes prompts against. If you iterate on the same fifty cases for a month, the prompt learns those fifty cases, and the score stops telling you how it will do on the fifty-first. Use a development set for iteration, and check the held-out set when deciding to ship.
Anthropic also separates two kinds of suite. A capability eval asks what the system can do well and starts with a low pass rate — it is a target. A regression eval asks whether it still does everything it used to, and should sit near 100%; any drop is a break. Capability tasks graduate into the regression suite once they pass reliably. Watch for saturation: when the system passes every solvable task, the suite can no longer show improvement and needs harder cases.
Two suites, two questions
Capability suite
- Asks “what can it do well?”
- Starts with a low pass rate
- Used to steer improvement work
- Needs harder cases once saturated
Regression suite
- Asks “does it still do what it did?”
- Should stay close to 100%
- Runs on every prompt or model change
- Grows as capability tasks graduate
Mixed methodologies: which grader for which check
“Mixed methodologies” means using each kind of grader where it is strongest, often several on the same task. Anthropic's comparison is consistent across its docs and engineering writing:
| Grader | Strengths | Weaknesses | Use it for |
|---|---|---|---|
| Code-based | Fast, cheap, objective, reproducible, easy to debug | Brittle to valid variations; no nuance | Labels, values, formats, database state, which tools were called |
| Model-based (LLM-as-judge) | Flexible, scalable, handles open-ended output | Non-deterministic, costs calls, must be calibrated | Tone, relevance, groundedness, rubric criteria |
| Human | Gold standard; matches expert judgment | Slow, expensive, hard to scale | High-stakes calls, disputed cases, calibrating the judge |
A single task can carry several graders. Anthropic's own example for a coding-agent task pairs unit tests, a model-graded code-quality rubric, static analysis, a check that the security log recorded the right event, and a check that certain files were read. The same idea, applied to a support agent:
task:
id: refund-late-delivery-017
input: "My order arrived 9 days late. Can I get the shipping fee back?"
graders:
- type: state_check # code: did the outcome happen?
expect: { refunds: { order: "A-1042", amount: 4.99 } }
- type: tool_calls # code: policy looked up before acting
required: [ { tool: get_refund_policy } ]
- type: llm_rubric # model: tone and clarity
rubric: rubrics/support_tone.md
- type: regex_absent # code: never echo a card number
pattern: "\\b\\d{13,16}\\b"Notice what isn't there: no check that the agent took exactly steps one, two and three in order. Anthropic's advice is to grade what the agent produced, not the path it took — agents regularly find valid routes the eval designer didn't anticipate. Check the path only where the path itself is the requirement, such as “looked up the policy before issuing money”.
Checking an LLM-as-judge before trusting it
- Passes: Detailed rubric with anchored scale points“1 = contradictory … 5 = fully logical”
- Passes: Reasons before it scores
- Passes: One judge per dimensionnot one prompt grading everything
- Passes: Can answer “Unknown”a way out instead of a guess
- Check: Agreement with human labels measuredon a sample, and re-checked
- Fails: Same model and prompt as the system under testdocs suggest a different model
JUDGE = """Grade the answer against the rubric.
<rubric>
PASS: every factual claim is supported by the <source>.
FAIL: any claim is missing from, or contradicts, the <source>.
UNKNOWN: the source is too incomplete to decide.
</rubric>
<source>{source}</source>
<answer>{answer}</answer>
Think in <reasoning> tags, then give <verdict>PASS|FAIL|UNKNOWN</verdict>."""
def judge(source: str, answer: str) -> str:
r = client.messages.create(
model=JUDGE_MODEL, # ideally not the model being graded
max_tokens=800,
messages=[{"role": "user",
"content": JUDGE.format(source=source, answer=answer)}],
)
text = next(b.text for b in r.content if b.type == "text")
return text.split("<verdict>")[-1].split("</verdict>")[0].strip()Before the judge's numbers go on a dashboard, have domain experts label a sample and measure how often the judge agrees. Anthropic's engineering guidance is that model graders should be closely calibrated against human experts; if agreement is poor, fix the rubric before trusting the score.
Keep trials clean, and read what happened
Agent evals need an isolated environment per trial. If one trial leaves a file, a database row or a cached result behind, the next trial is no longer independent, and your pass rate measures leftovers. Start every trial from a clean state. Because model output varies, run several trials per task and report the variation, not just the best run.
Then read transcripts. Anthropic's engineers repeat this more than any other advice, and give an example: one model scored 42% on a public benchmark until the team found grading bugs — including a grader that rejected “96.12” when it expected “96.124991…”. With those fixed, the score was 95%. A failing test should look fair when a person reads it. If it doesn't, the grader is broken.
Offline evals are one layer, not the whole framework
Layers that catch different failures
Before release → after release
- Automated evalsfast, repeatable, no user impact
- Manual transcript reviewbuilds intuition; doesn't scale
- Systematic human studiesgold standard; slow and costly
- A/B testingreal user outcomes; takes days or weeks
- Production monitoringreal behaviour at scale; reactive
- User feedbacksurprises; sparse and self-selected
A mixed-methodology framework uses them together. Automated evals gate every change; transcript review keeps the graders honest; human studies calibrate the judges; A/B tests (4.3) confirm that an offline win is a real-world win; production monitoring (4.6) feeds new failures back into the dataset.
Traps the wrong answers are built from
| Tempting but wrong | Do this instead |
|---|---|
| A small, hand-written happy-path test set | Sample real traffic and known failures, then add edge, should-not and adversarial cases. |
| One uncalibrated LLM judge grading every dimension | Use code where possible; one rubric-driven judge per dimension, checked against human labels. |
| Tuning prompts against the same set used for release decisions | Iterate on a development set; decide on a held-out set. |
| Grading the exact sequence of steps an agent took | Grade the outcome and only the steps that are real requirements. |
| Trials that share state | Start every trial from a clean, isolated environment. |
You should now be able to
- Assemble an evaluation dataset from real traffic, known failures, edge cases, should-not cases and adversarial inputs.
- Choose code-based, model-based or human grading for each check, and combine them on one task.
- Design and calibrate an LLM-as-judge with a rubric, reasoning, an “Unknown” option and human agreement checks.
- Separate capability and regression suites, and development and held-out splits.
- Place offline evals within a wider framework of transcript review, A/B tests, monitoring and user feedback.