Tools fail — networks blip, inputs are wrong, records don't exist. What separates a brittle agent from a self-healing one is how the failure is reported back. A structured error tells the model exactly what happened and whether trying again could help. Watch an agent recover — or give up — based on the error you hand it.
A good tool error is itself a little tool-result the model can reason over. The pattern the exam expects has three parts:
| Field | Purpose | Example |
|---|---|---|
errorCategory | A machine-readable bucket so the model (and your code) can branch. | "NOT_FOUND", "VALIDATION", "RATE_LIMIT", "AUTH" |
isRetryable | Should the agent try again, or is retrying pointless? | true for a timeout; false for "order doesn't exist" |
message | Human-readable guidance the model uses to decide its next move. | "No order 99999. Confirm the ID with the customer." |
For structured output and tool args, the strongest pattern is a bounded loop: the model produces a call →
your code validates it against the schema → on failure you return a VALIDATION error
naming the exact problem → the model corrects and resubmits. This recovers from malformed JSON and missing
fields automatically. The guardrail (Domain 1) still applies: cap the retries (e.g. 3) so a persistently
confused model doesn't loop forever.
"failed" is the
wrong answer — the model can't tell retry from give up, so it either spins pointlessly or
abandons a recoverable task. The right answer always pairs a category + isRetryable + a
human-readable next step, inside a bounded retry loop.Curated companion: Anthropic — Writing tools for agents.