OPTIMIZE
Move from "looks right" to measured quality —
score your agent locally and see exactly where it's grounded and where it slips. No deployment.
Run the local eval loop: simulate the crisis at scale, then turn the scenarios into a graded eval suite and score the agent with an LLM judge — reading exactly where it's grounded and where it slips, all locally, no deployment. This is the difference between a demo and a production agent.
M4 is about quality, not shipping. You already deployed in M2 — here you evaluate and improve the agent
on your machine with agents-cli eval and an LLM judge, with no redeploy.
Publishing the improved agent happens later.
The Quality Flywheel
The Quality Flywheel is the official loop for agent quality improvement. Each revolution raises quality empirically.
Why This Works
- Simulation creates coverage — many scenarios catch failures your one test query never will
- Graded metrics remove subjectivity — quality becomes a number you can define, measure, and compare
- The weakest case reveals the fix — you target a real failure, not a guess
- Flagged sentences point to the fix — the judge shows exactly which sentences weren't grounded, so you know what to tighten
Example: Per-Case Scores (illustrative)
| Case | hallucinations_v1 | What it means |
|---|---|---|
| cancellation + reroute | 1.00 | every sentence grounded in tool output |
| delay | 0.92 | one mild reassurance not from a tool |
| 503 fallback | 1.00 | correctly defers to station boards |
| grounding trap (platform) | 0.50 | invented a platform no tool returned |
The low score on the grounding trap points straight at the fix — a strict rule to state only
tool-returned facts. In practice you'd make that one change and re-run; here we stop at the measurement to keep
the step fast. Your real numbers come from running adk eval once and reading the score table.
Optimize in 3 Steps
The Local Eval-Fix Loop
Quality improvement for agents is a loop, not a one-time check — and it all runs locally:
- Evaluate — run the agent against many scenarios and score it
- Analyze — find the weakest case and why it failed
- Fix — change the agent's instructions or tool logic to address it
- Re-eval & compare — rerun and prove the score improved
This is how you go from "it works on my one test query" to "it works on every query" — with no deployment in the loop.
Simulate the Crisis at Scale (Breadth)
Test the agent against many scenarios, not just one query. AGY generates diverse commuter requests and an edge case where the disruption feed goes down — and runs them all locally, in parallel.
Expected Result
AGY writes a local parallel runner (e.g. tests/integration/parallel_test.py) and runs all 10
scenarios concurrently (~2–5 min), then prints a report table. Coverage includes:
- Cancellations + reroutes — e.g. cancelled Paris/Amsterdam services, alternatives computed via Brussels/Rotterdam
- Delays — revised departure times with next steps
- Code-exec math — the sandbox computes stats like the cancellation ratio or peak bottleneck hour
- Personalization — home-station recall
- Offline-feed fallback — a 503 outage; the agent falls back to GTFS schedules and tells the user to check station boards
This step is breadth — a qualitative check that the agent resolves sensibly. We turn it into measured scores next.
Grade Your Agent Locally
Now turn the scenarios into a graded eval suite and score the agent with an LLM judge — locally, in one run. The per-case scores show exactly where the agent is solid and where it slips, and the judge quotes the ungrounded sentences so you know what you'd tighten next.
adk eval scores (while you wait)adk eval scores each case against the criteria in
eval_config.json (agents-cli eval wraps it, but its flags vary by build — so we
call adk eval directly). We gate on hallucinations_v1, an LLM judge that scores the
fraction of the answer's sentences grounded in the tool outputs — a continuous 0–1
score that's reference-free (no hand-written answer to game). The other three below exist, but we don't gate on
them here.
| Metric | What it measures | Speed |
|---|---|---|
hallucinations_v1 (gated) | Fraction of sentences grounded in the tool outputs — continuous 0–1, reference-free, so it directly measures "did the agent invent anything?" | LLM judge |
final_response_match_v2 | Semantic match to a reference answer (LLM judge) — but majority-vote binary per single-turn case, so it can't show fine-grained movement here | LLM judge |
response_match_score | Lexical closeness to the reference (ROUGE) — fast, but scores correct-but-free-form answers low, so we don't gate on it | fast |
tool_trajectory_avg_score | Right tools, right order — but an EXACT match on tool name AND args, so it's brittle for a generative agent (re-runs vary the args) and we don't gate on it | not gated |
The run prints a per-case score table to stdout (and writes a full
*.evalset_result.json under app/.adk/eval_history/ with the per-sentence judge
labels you can quote for any low-scoring case).
Docs: ADK evaluation · Criteria reference · User simulation
Expected Result
AGY builds the 4-case evalset, runs adk eval once, and prints the per-case
hallucinations_v1 scores (the fraction of each answer's sentences grounded in the tool outputs).
- Per-case scores — well-grounded cases score near 1.0; a case that slips in an unsupported sentence (an invented platform, or a reassurance no tool returned) scores lower
- Flagged sentences — for any case below the threshold, AGY quotes the exact sentences the judge marked unsupported/contradicted, so you see precisely what isn't grounded
- No fix, no deploy — this step measures; tightening the instruction to ground those sentences is the next turn of the same loop, which you'd run in practice
What just happened: quality became a number, and the fine-grained, reference-free judge pointed at exactly which sentences weren't grounded — the measurement that drives the eval-fix loop. (Improvement isn't guaranteed from one tweak, and the judge is non-deterministic — so in practice you iterate; here we stop at the measurement to keep the step fast.)
Mentor Checkpoint — Done When:
- 10 scenarios were simulated against your agent locally
- A graded eval suite produced per-case scores (
adk eval+hallucinations_v1) - You can see which cases are well-grounded and which slip, with the judge's flagged sentences — no deployment
Module Recap — OPTIMIZE
Beat 1 What You Typed
| Step | The Prompt |
|---|---|
| 4.2 Simulate | "Generate 10 commuter scenarios during a St Pancras signal failure and run them in parallel against my agent locally (incl. a disruption-feed outage). Print a report." |
| 4.3 Grade | "Build a small graded eval and score my agent once with an LLM judge — show me the per-case scores, no deploy." |
Beat 2 What Ran Under the Hood
| Step | What ran |
|---|---|
| 4.2 | A local parallel runner (ADK Runner) executing 10 scenarios concurrently |
| 4.3 | adk eval for scoring (agents-cli eval wraps it), with the hallucinations_v1 LLM judge grading each case's groundedness |
The analysis is done by the coding agent reasoning over the scores — there is no auto-optimize command. You read the per-case scores and the flagged sentences, and you stay in control of any change.
Beat 3 What You Can See Locally
- Eval scores — per-case, per-metric, saved as JSON (and an HTML report)
- Trace viewer —
adk webEval tab: drill into a case and see exactly where the agent went wrong - Per-case scores — the
adk evalscore table plus the judge's flagged sentences, showing exactly where the agent is grounded - Flagged sentences — the judge's per-sentence labels showing what wasn't grounded
Beat 4 Why It Matters
- Empirical quality — measured, not guessed
- Fast local feedback — measure quality without a deploy in the loop
- Pinpoint the weakness — the judge flags the exact ungrounded sentences, so you know precisely what to fix next
- Regression-ready — the eval suite is reusable: re-run it whenever you change the agent to catch quality sliding