CCD-F.5 · D4 + D1 + D2 · ProcessCCD-F D4 · 2.6%20 min build

Agent Evaluation and Testing Harness.

A golden-set evaluation harness for a Claude agent: representative test cases run in bulk through the Message Batches API, graded by an LLM judge forced into deterministic scoring via structured outputs (never a prefill, which 400s on current models), with tool-call correctness tracked as a separate metric from output quality. New prompt or model versions must match or beat the versioned baseline before shipping - a regression gate, not a vibe check.

Loading your plan…
Mental modelArchitecture chooses the flow. Deterministic controls enforce policy. Structured state preserves truth.
Loop mascot illustrating Agent Evaluation and Testing Harness.
Share
01 · System & parts

What this system is, and its 4 parts

Once an agent is in production, 'it seemed fine when I tried it' stops being a testing strategy. This scenario is the harness that replaces manual spot-checking: a versioned set of representative inputs with known-good expected behavior, run in bulk, graded automatically, and compared against a baseline before any prompt or model change ships. It exists because the two most common ways teams get burned are shipping a prompt tweak that silently breaks an edge case, and grading agents only on how the final text reads while ignoring whether they actually called the right tools in the right order.

4Components
D4Primary domain
6Build steps
8Decision traps
4Concept links
Stack · Python or TypeScript SDK - Message Batches APINeeds · stop_reason - structured outputs - tool_use inspection
Agent Evaluation and Testing Harness component architecture.
4 components. Each owns one concept.
01

Golden Set

versioned inputs + expected behavior

A repo-tracked set of representative test cases, each with an input and the expected stop_reason/tool sequence/output shape, versioned alongside the prompt it was built against.

Configurationgolden_set_v3.jsonl - one JSON object per line: {id, input, expected_tools, expected_shape}.
Concept: evaluation →
02

Batch Runner

Message Batches API

Submits the full golden set as a single batch job rather than sequential live requests, at half the per-token cost and without holding a connection open per case.

Configurationclient.messages.batches.create(requests=[{custom_id, params} for each golden-set case]).
Concept: batch-api →
03

LLM Judge

structured, deterministic scoring

A model at least as capable as the system under test, forced into a fixed JSON schema via output_config.format so scores are parseable and comparable across runs.

Configurationoutput_config={"format": {"type": "json_schema", "schema": JUDGE_SCHEMA}} - never a prefill (400s on current models).
Concept: structured-outputs →
04

Regression Gate

baseline comparison

Compares the new run's pass rate against the versioned baseline and blocks deployment if it regresses, turning eval results into a CI-style check rather than a one-off report.

Configurationif new_pass_rate < baseline_pass_rate - TOLERANCE: fail the deploy step.
Concept: evaluation →
02 · Problem framing

The problem

What the user needs
  1. Know before shipping whether a prompt or model change made things better or worse.
  2. Grade what the agent actually did (tool calls, sequence), not just how the final text reads.
  3. Run evaluations cheaply at scale, not one request at a time against a live endpoint.
Why naive approaches fail
  1. Grading only the final text lets an agent that skipped identity verification still score well because the refund text 'looked right'.
  2. Using a weaker or cheaper model as the judge than the system under test produces unreliable, inconsistent scores.
  3. Re-running evals ad hoc with no versioned golden set gives you no regression signal, every run is a fresh, incomparable snapshot.
Definition of done
  • ✓ Golden set versioned alongside the prompt/model it was built against
  • ✓ Tool-call correctness scored separately from output-text quality
  • ✓ Judge forced into structured, parseable output via output_config.format
  • ✓ New versions gated on matching or beating the baseline pass rate before deploy
03 · Data flow

One run, traced end to end

Agent Evaluation and Testing Harness sequence diagram.
Agent Evaluation and Testing Harness end-to-end flow.
04 · Build

6 steps to production

01

Build a versioned golden set

Each case pairs an input with the expected tool sequence and output shape. Version it in the repo alongside the prompt it was authored against.

Concept: evaluation →
Python
golden_set = [
    {
        "id": "refund-happy-path",
        "input": "I want a refund for order 42, it arrived damaged.",
        "expected_tools": ["verify_customer", "lookup_order", "process_refund"],
        "expected_stop_reason": "end_turn",
    },
    {
        "id": "refund-over-cap",
        "input": "I need a $900 refund on order 55.",
        "expected_tools": ["verify_customer", "lookup_order", "escalate_to_human"],
        "expected_stop_reason": "end_turn",
    },
]
02

Run the golden set through Message Batches

Submit every case as one batch job instead of sequential live requests - half the cost, and it doesn't hold connections open per case.

Concept: batch-api →
03

Score tool-call correctness separately from text quality

Extract the actual tool call sequence from the response and compare it to the expected sequence directly - exact-match grading, not judge opinion, for structured behavior.

Concept: evaluation →
04

Grade open-ended output with a structured LLM judge

Force the judge into a JSON schema so scores are parseable and comparable. Use a model at least as capable as the system under test, and never a prefill.

Concept: structured-outputs →
05

Gate deploys on the versioned baseline

Compare the new run's pass rate to the checked-in baseline. A regression beyond tolerance blocks the deploy, the same way a failing unit test would.

Concept: evaluation →
06

Replay failures from full content blocks, not just final text

When a case fails, inspect the entire content array (tool_use, tool_result, stop_reason per turn) to see exactly where the agent diverged, not just the final answer.

Concept: debugging-llm-system-failures →
05 · Right call, wrong call

8 decisions the exam turns into distractors

01 · Grading tool-call sequences
Looks right

LLM judge opinion on whether it 'seems right'

Actually right

exact-match against the expected sequence

DEC-01
02 · Grading open-ended text quality
Looks right

exact string match against a reference answer

Actually right

LLM judge, forced into structured output

DEC-02
03 · Judge model tier
Looks right

the cheapest available model, to save eval cost

Actually right

at least as capable as the system under test

DEC-03
04 · Running large eval sets
Looks right

sequential live requests in a loop

Actually right

Message Batches API

DEC-04
05 · Text-only grading
Looks right

The judge scores only the final response text, missing that the agent skipped verify_customer.

Actually right

Score tool-call sequence separately (exact-match) from output-text quality (LLM judge).

CCDF-15
06 · Weak judge model
Looks right

Haiku 4.5 is used to judge output from a Sonnet-5-powered agent, producing noisy scores.

Actually right

Use a judge model at least as capable as the system under test.

CCDF-16
07 · Unversioned golden set
Looks right

The eval script's test cases live only in someone's scratch notebook, changing between runs.

Actually right

Version the golden set in the repo alongside the prompt/model it was built against.

CCDF-17
08 · Prefill-based judge scoring
Looks right

Judge prompt ends with an assistant-turn prefill like '{"correct": ' to force JSON shape.

Actually right

Assistant-turn prefills return a 400 on current models. Use output_config.format (structured outputs) instead.

CCDF-18
Agent Evaluation and Testing Harness failure map.
06 · Budget

Cost & latency

~$0.30-$0.60Eval run cost (100-case golden set, Batches)

50% Batches discount on Sonnet 5 traffic for 100 short-to-medium cases with tool use.

~$0.02-$0.05 per caseJudge scoring pass

A separate Opus 4.8 (or Sonnet 5) call per case for open-ended text grading; skip it for pure tool-sequence cases.

07 · Ship checklist

Check every gate before release

0/7 checked
  • evaluation →
  • batch-api →
  • structured-outputs →
  • debugging-llm-system-failures →
08 · Practice

3 exam-pattern questions

Work through one question at a time, check the architecture, then move through the set.

Question 1 of 3Check the architecture

Your eval harness scores an agent 95% pass rate, but production shows it frequently skips identity verification before processing refunds. What's the gap?

09 · FAQ

Frequently asked

How big should a golden set be?

Start with 20-50 cases covering the main happy paths and known edge cases (policy boundaries, ambiguous intent, tool failures). Grow it every time production surfaces a new failure mode - each incident becomes a new golden-set case so it can never regress silently again.

Should every case use an LLM judge?

No. Use exact-match grading for anything with a ground truth (tool sequence, structured output fields, stop_reason). Reserve the LLM judge for genuinely open-ended text quality, where there's no single correct string.

How often should the harness run?

On every prompt or model change before it ships, as a CI-style gate, plus on a schedule (e.g. nightly) against production traffic samples to catch silent drift that wasn't triggered by a code change.

What tolerance should the regression gate use?

Start conservative (e.g. 2 percentage points) and tune based on how noisy your judge scoring is. A tolerance of 0% will flag noise as regressions; too loose a tolerance lets real regressions through.

Help someone build it

Share this scenario.

One share is one less team repeating the same architecture mistake.

Last reviewed ·