Guide

You cannot improve what you do not measure. Build a small eval set of user tasks with expected tool trajectories — not only final answers. Fifty well-chosen cases beat a thousand random chats.

Concept

Before you start: a trajectory is the sequence of tool names and arguments the model emitted, plus the results you returned. Evals are how you gate a schema change.

Three layers, plus policy

  1. Correct tool — Did it pick get_order vs search_orders?
  2. Correct arguments — Right id, filters, date range?
  3. Recovery — Given a not_found or validation error, does the next turn fix the call or ask a clarifying question?

Add policy scores for high-risk tools: "Did it attempt cancel_order without reading status first?" is a binary fail regardless of the final sentence fluency.

Example

Worked scoring on 50 support transcripts. Baseline: 72% correct tool, 61% correct args, 40% recovery after injected errors. After rewriting descriptions and returning structured errors: 91% / 88% / 74%. Final-answer accuracy rose only ~8 points. Most of the product gain was fewer wasted turns and fewer hallucinated order statuses.

Also track online metrics: tools per task, retry rate, approval rate, and cost per successful resolution. A model that "works" by calling search eight times is failing your latency and cost budget.

When you change a description, treat it like an API change: bump a prompt/tool version, run the trajectory suite, and only then roll out. Log the triad (tool_name, args_hash, ok|error) per turn. Spikes in error rates after a schema change are usually your fault, not the model's.

Walking through one case

User: "Cancel ORD-12345 if it hasn't shipped, otherwise give me the tracking link."

FixtureExpect
get_order → processing, cancellable: trueThen cancel_order, then a confirmation sentence
get_order → shipped, tracking_url: …Zero cancel_order calls; answer contains the URL
get_order → not_foundRecovers: asks for a well-formed id, does not invent a status

The shipped fixture is the one teams skip. Fluency on the happy path hides a refund that should never have fired.

Common failure modes

SymptomLikely causeFix
Model never calls toolsWeak descriptions; tool_choice noneStrengthen "when to use"; force tools for facts
Model calls everythingOverlapping toolsMerge tools; add when-not; shrink the set
Invented parameter namesSchema not strictRequired fields; examples; validate before execute
Double side effectsRetries without idempotencyKey on tool_use_id
Context blows upHuge payloadsProject fields; paginate

Common mistakes

  • Scoring only the final sentence. A fluent wrong status still shipped.
  • No recovery cases. Inject not_found on purpose.
  • Silent edits to production tool text without rerunning the suite.

Check yourself

  1. Final-answer accuracy rose 8 points but tool/args/recovery jumped much more. What did the product gain? Fewer wasted turns and fewer invented statuses — the trajectory scores, not the prose.
  2. Why is the shipped fixture a fail if cancel_order fires? The order already shipped. Cancel is a policy violation regardless of the final wording.

Key takeaways

  • Eval tool selection, arguments and error recovery — not only final answers.
  • Add binary policy scores for high-risk writes.
  • Version tool text and rerun the suite before rollout.
  • Online, watch tools per task and cost per successful resolution.

Further learning

Evals, Toolformer (Schick et al.). When many apps need the same tools, package them as an MCP server.