Most teams building agentic features spend real effort on tool descriptions and JSON schemas, then let the error path be whatever the underlying library happens to throw. That's a mistake. When a tool call fails, the error message is the next input to the model. It is prompt engineering whether you treat it that way or not. A poorly shaped error doesn't just fail to help: it can lead the model to retry the wrong thing, apologize to the user for no reason, or invent a workaround.
Anthropic's engineering guide "Writing effective tools for agents" makes the same point and gives concrete guidance, which this article draws on. Where I add my own suggestions, I say so.
What the guide says about errors
The guide contrasts unhelpful and helpful error responses. Helpful ones should clearly communicate specific and actionable improvements, not return opaque error codes or raw tracebacks. They can also steer an agent toward more token-efficient behavior, for example by telling it to use a filter or pagination instead of repeating a broad request.
That has a practical consequence. A raw exception string such as KeyError: 'customer_id', or a 500 response with an HTML body, tells the model nothing it can act on.
Give the model an action, not a diagnosis
The instinct is to write errors like a log line for an on-call engineer. A model needs something closer to a support instruction: what to do next.
- "Rate limited, retry after 4000 ms" beats "429 Too Many Requests."
- "
customer_idmust be a UUID, gotcust_882" beats "invalid input." - "Order 1234 was deleted and cannot be changed; tell the user" beats "404."
If a failure is terminal, say so plainly. Otherwise the model will try variations of the same call.
A small schema, applied everywhere (my suggestion)
Two failures that look alike in a stack trace can need opposite responses: a malformed argument should be corrected and retried at once, while a downstream outage should not be retried on the same tool. If your error payload doesn't distinguish them, you're asking the model to guess from noise. A simple, consistent shape for every tool helps:
code: machine-readable, such asinvalid_argument,not_found,rate_limited,upstream_unavailableorpermission_denied.message: one short sentence a person could read.retryable: true or false.suggested_fix: the exact parameter or precondition to change, where relevant.
It costs almost nothing to add and turns each failure into a decision the model can make correctly.
Related lessons from the same guide
The guide's other recommendations apply to the whole tool surface, and they affect how errors arise in the first place:
- Fewer, better tools. "More tools don't always lead to better outcomes." Focus on high-impact workflows instead of wrapping every endpoint.
- Unambiguous parameter names. Use
user_idinstead ofuser. Vague names produce wrong calls, and wrong calls produce errors. - Meaningful return values. Resolving arbitrary alphanumeric IDs to semantically meaningful language significantly improves precision, the guide says.
- Concise and detailed modes. A
response_formatoption lets the agent choose. The guide's example has the concise version at about 72 tokens against 206 for the detailed one, which matters when output competes for context. - Pagination, filtering and truncation with sensible defaults, so a tool can't flood the model's context.
Test the error paths
The guide recommends evaluating tools with realistic tasks that need several tool calls, using programmatic tests and simple agent loops, and measuring both accuracy and efficiency. Add induced failures to that: for each tool, a few cases where the call is rejected, times out or returns nothing. A model that handles your success path well can still loop on retries, fabricate a plausible result, or drop the failure from its final answer when the error shape surprises it. If you haven't tested the error path, you don't know how your agent behaves on it. For a related failure that no error is ever raised for, see Truncated Output Is a Silent Failure.
Treat the error contract like the success contract
Version it, document it, and don't let it drift when the implementation changes. Retries also interact with side effects, which is where idempotency keys come in. The error message is the interface your agent actually works with when things go wrong, and eventually they do.
Comments (0)
No comments yet — be the first.
Sign in to leave a comment.