Chatbot evaluation is comparatively simple: was the single response correct or not. Agent evaluation is a different problem entirely - an agent takes a sequence of actions, each one conditioned on the last, and a single wrong step early in the trajectory can compound into a completely wrong outcome even when every individual reasoning step looks locally plausible. I spent 2024 as an LLM Evaluator at Turing.com systematically red-teaming frontier models, and the same discipline - structured, adversarial, trajectory-level evaluation - is what separates agents that survive contact with real users from ones that quietly fail in ways nobody catches until a client complains.
Why Standard LLM Evals Don't Cover Agents
Most teams reach for the evaluation tools built for single-turn LLM outputs - exact match, BLEU-style scoring, or an LLM-as-judge grading a final answer. These miss the failure modes that actually matter in agentic systems, because an agent's output is not one response - it's a chain of tool calls, intermediate reasoning, and state changes, any of which can go wrong independently of the final answer looking fine.
| What to Measure | Applies To | Why It Matters |
|---|---|---|
| Final answer correctness | Single LLM call | Necessary but insufficient for agents |
| Trajectory efficiency | Agent-specific | Did it take 3 steps or 30 to reach the answer? |
| Tool selection accuracy | Agent-specific | Did it call the right tool with the right arguments? |
| Recovery from tool failure | Agent-specific | Does it retry sensibly or spiral into repeated errors? |
| Task completion vs. partial completion | Agent-specific | A 90%-complete task often has zero business value |
A Four-Layer Evaluation Framework
Every agent evaluation setup I build for client projects has four layers, run in this order because each layer is cheaper to check than the next:
Layer 1: Schema Validation (near-zero cost)
Does every tool call have valid arguments matching its schema?
│
Layer 2: Trajectory Checks (cheap, deterministic)
Did the agent call tools in a sane order? Any infinite loops? Excess steps?
│
Layer 3: Outcome Verification (moderate cost)
Does the final state match the expected outcome for the task?
│
Layer 4: LLM-as-Judge on Reasoning Quality (most expensive)
Was each intermediate decision justified given the information available at that step?Running them in this order matters for cost control - Layer 1 catches malformed tool calls for pennies before you ever pay for a Layer 4 judge call. Most production failures I've diagnosed for clients get caught at Layer 1 or 2; Layer 4 is reserved for the subset of trajectories that pass the cheap checks but still produced a wrong outcome.
Layer 1 and 2: Deterministic Checks
These don't need an LLM at all - they're plain code, which makes them fast and free to run on every single trajectory:
from pydantic import ValidationError
def validate_trajectory(steps: list[dict], tool_schemas: dict) -> list[str]:
errors = []
seen_states = set()
for i, step in enumerate(steps):
tool_name = step["tool"]
schema = tool_schemas.get(tool_name)
if schema is None:
errors.append(f"Step {i}: unknown tool '{tool_name}'")
continue
try:
schema(**step["arguments"])
except ValidationError as e:
errors.append(f"Step {i}: invalid arguments for '{tool_name}': {e}")
# detect loops: same tool + same arguments repeated
state_key = (tool_name, str(sorted(step["arguments"].items())))
if state_key in seen_states:
errors.append(f"Step {i}: repeated identical call - possible loop")
seen_states.add(state_key)
if len(steps) > 25:
errors.append(f"Trajectory length {len(steps)} exceeds sane bound - inefficient or stuck")
return errorsThe repeated-call loop detector alone catches a surprising fraction of real agent failures. An agent that calls the same search tool with the same query three times in a row isn't reasoning - it's stuck, and this check flags it before a human has to notice the pattern in a log dump.
Layer 3: Outcome Verification Against Ground Truth
This requires a curated eval set - real or realistic tasks with known correct end states. Build this before you need it, not after your first production incident:
eval_cases = [
{
"task": "Find the current CEO of the company at example.com and add them to the CRM",
"expected_final_state": {
"crm_contact_added": True,
"contact_role_matches": "CEO",
},
},
# ... 40-100 more cases spanning the task distribution your agent actually sees
]
def verify_outcome(case: dict, final_state: dict) -> bool:
expected = case["expected_final_state"]
return all(final_state.get(k) == v for k, v in expected.items())The number that matters here is task-level pass rate, not step-level accuracy. A client does not care that 9 of 10 steps were reasoning correctly if the CRM entry that got created has the wrong person in it. I always report outcome-level pass rate as the headline metric in client deliverables - it is the number that maps to actual business value.
Layer 4: LLM-as-Judge for Reasoning Quality
Reserved for trajectories that fail Layer 3 or that need a qualitative diagnosis, not a pass/fail. This is where the red-teaming discipline from evaluating frontier models directly applies - the judge prompt needs to ask for a structured critique, not a score, because a bare number tells you nothing about what to fix.
judge_prompt = """You are auditing an AI agent's trajectory for a failed task.
Task: {task}
Steps taken: {trajectory}
Final outcome: {outcome}
Expected outcome: {expected}
Identify:
1. The exact step where the trajectory diverged from a correct path
2. Whether the agent had the information needed to avoid this error at that step
3. Whether this is a tool-selection error, an argument error, or a reasoning error
4. A one-sentence fix (better tool description, better prompt, or a missing tool)
Do not just say what went wrong - say why the agent's available information
made this decision plausible from its perspective, and what would have prevented it."""That last instruction is the one most eval setups skip. A judge that just says "the agent made an error in step 4" gives you nothing actionable. A judge that says "the agent had no way to know the API returned a paginated response because the tool description doesn't mention pagination" gives you a specific fix to ship.
Failure Modes I See Most Often in Client Agent Systems
- -Confident wrongness on edge-case inputs. The same pattern I documented from frontier model red-teaming shows up in agents built on those models - fluent, confident tool calls that are subtly wrong on inputs slightly outside the common case.
- -Silent partial completion. An agent that completes 3 of 5 required actions and reports success because no single step explicitly failed. Outcome verification against a full expected state catches this; step-level success metrics do not.
- -Tool description drift. A tool's actual behavior changes (an API adds a required parameter) but its description in the agent's tool list doesn't get updated, and the agent keeps calling it the old way until it silently starts failing.
- -Cost blowups from unbounded retries. An agent that retries a failing tool call indefinitely instead of escalating or giving up - invisible until the bill arrives.
Making Evaluation Part of the Deployment Pipeline
Evaluation that only runs once before launch catches launch-day bugs. Evaluation that runs on every deploy catches regressions. The eval set from Layer 3, plus the deterministic checks from Layers 1-2, should run as a CI gate on every agent prompt or tool change - the same way you would not ship a code change without running the test suite.
# CI gate, runs on every PR that touches agent prompts or tools
def run_eval_gate(eval_cases: list[dict], agent) -> bool:
results = [run_and_verify(case, agent) for case in eval_cases]
pass_rate = sum(results) / len(results)
if pass_rate < 0.90: # threshold tuned to task criticality
print(f"Eval gate FAILED: {pass_rate:.1%} pass rate (need 90%)")
return False
return TrueFrequently Asked Questions
How many eval cases do I need before launching an agent?
40-100 cases covering the realistic spread of tasks the agent will see in production is a reasonable starting bar for most single-purpose agents. The number matters less than coverage - five cases that each test a genuinely different failure mode beat fifty near-duplicates of the same happy path.
Can I use an LLM judge for everything instead of building deterministic checks?
You can, but it costs more and catches less. Deterministic checks (schema validation, loop detection, outcome matching) are cheaper, faster, and more reliable for the failure modes they're built to catch. Reserve the LLM judge for the qualitative reasoning-quality analysis that deterministic code genuinely cannot do.
How often should agent evals run once the agent is in production?
On every change to the prompt, tool set, or underlying model - as a CI gate before deploy. Beyond that, a scheduled full eval run weekly against production traffic samples catches drift that wasn't visible in your original eval set, particularly when the tools your agent depends on change behavior upstream.
What's the single highest-leverage evaluation to add first?
Outcome verification against a curated eval set (Layer 3). It's the metric that actually maps to whether the agent delivers business value, and building even 20-30 well-chosen cases surfaces more real problems per hour invested than any other single evaluation layer.
