T1 · Intermediate · 6 minStable · Last reviewed: 2026-08-19Early draft

Handling Tool Errors

In one line · Tools fail: an API is down, an input is wrong, a result is empty. The trick is to return the error to the model as clear text instead of breaking the loop.

Glossary:AgentHallucinationTool CallingTrace
Why it matters

If a tool throws and goes silent, the model is blind. Return 'the tool failed because X' and it will often fix the inputs or try another route.

Treat the error like any other result: tell the model about it in plain words. It's smarter at recovering than you'd think — but only if it knows something went wrong.

An analogy

Like a GPS that says 'road closed' so you can reroute — far better than one that stays silent and lets you drive into a wall.

The model calls get_user with a bad email; the tool returns 'no user with that email'. The model replies 'could you double-check the email?' instead of stalling.

How it works

In your code, wrap tool execution in try/catch. On failure, don't break the loop: return the model a tool result flagged as an error, carrying a useful, actionable description ('email not found' beats 'Error 500'). The model then decides: fix the inputs, try another tool, or ask the user. And cap the retries — if a tool fails 3 times straight, stop the loop and give the user a clean reply instead of burning turns on a permanent failure.

Practice

🧪 Try it yourself: a get_invoice tool sometimes times out. Write two versions of the error message returned to the model: a bad one ('Error') and a good one ('invoice lookup exceeded 5 seconds — you may retry once, or tell the user the system is slow'). Test both, watch how the model recovers with each, and decide where the retry cap lives.

Common mistakes

Top mistakes: (1) letting the exception bubble up and crash the whole app. (2) Returning a raw stack trace — it confuses the model and leaks internal system details into a user conversation. (3) A vague error like 'failed' with no cause, so the model retries the exact same wrong call. (4) No retry cap, so you sit in an endless fail-retry loop. (5) Hiding the failure and returning an empty result as if it succeeded — the model then fabricates an answer from data that doesn't exist.

When to use it

Apply this pattern to every tool touching the outside world: network, databases, third-party APIs — anything that can go down or come back empty.

When NOT to use it

Genuine bugs in your own code (a broken handler) don't get sent to the model — those get logged and fixed on your side; the model won't debug your code for you.

LET'S BUILD ITDone reading — now build it yourself.Make the model recover from a failed tool