Handle tool errors in AI agents

Turn API errors into messages the model can act on, handle 401, 403 and 429 differently, retry safely, and put hard limits on the agent loop so it can't run forever.

  • 35 min
  • 3 parts
  • Intermediate
APIs you'll callDictionaryWorld Time

An agent was asked to define "idempotent" for a glossary. The dictionary tool returned a 404. The model, seeing an error it did not understand, tried again with "Idempotent", then "idempotency", then "idempotent (computing)", then went back to the original spelling. Each call was a few credits; the loop had no ceiling; the user's tab had long since closed.

Nothing in that story is a bug in the API or the model. The tool returned an accurate answer ("no entry for that word") in a form the model could not interpret, and the loop around it had no way to stop. Both of those are your code, and both are fixable.

01Errors are now part of the conversation

In the Fundamentals courses, an error from an API went to your code and your code decided: retry, give up, show a message. In an agent there is a second decider. Whatever your tool returns goes back to the model as a tool result, and the model chooses the next step: try other arguments, try another tool, ask the user, or answer without the data.

That gives you a design choice for every failure: does the model need to know about this, and can it do anything useful with it?

  • Some failures are about the input, and the model is the one who chose the input. It should hear about them, in words that point at a fix.
  • Some failures are transient. The model cannot do anything about a busy minute, so your tool layer should absorb them with a bounded retry and only report if that fails.
  • Some failures are fatal for the whole run: a bad key, an empty credit balance. The model cannot fix those either, and telling it invites it to try. Your loop should stop and tell a human.

Model APIs give you a channel for the first group. In the Anthropic Messages API a tool_result can carry is_error: true; in OpenAI's API you return the error text as the tool message content. MCP servers do the same thing: the APIVerve MCP server returns a failed call as tool content with isError: true and the API's own message, rather than a protocol error, precisely so the agent can read it and correct itself.

02Map every status to a decision

Here is how APIVerve's statuses translate into agent behaviour. The first column is what the API says; the last is what the model should see.

StatusWhat it meansWho handles itWhat the model sees
400Invalid or missing parameterModelThe API's message plus "fix the argument"
404Unknown API, or no result for this inputModel"No result for X. Do not retry the same input."
401Missing or unrecognised keyYour loop: haltNothing; the run stops
403Valid key, but not allowed for this call (scoping, IP allow-list)Your loop: haltNothing; the run stops
429 + credits leftPer-minute rate limitTool layer: wait retry-after, retry once or twiceOnly if retries fail: "temporarily unavailable"
429 + x-api-remaining-credits: 0Monthly credits exhaustedYour loop: haltNothing; the run stops
5xx, timeout, networkUpstream troubleTool layer: one retryIf still failing: "temporarily unavailable"

Three rows deserve a closer look.

404 is often an answer, not a failure. The dictionary returns 404 with "word not found" when it has no entry, and World Time returns 404 with "city not found". That is information: the input was understood and nothing matched. The right model behaviour is to stop asking about that input, tell the user, or try a meaningfully different input (a larger nearby city). Retrying the same string is never right.

Try it liveDictionary2 credits
GEThttps://api.apiverve.com/v1/dictionary
curl "https://api.apiverve.com/v1/dictionary?word=retry" \
  -H "x-api-key: YOUR_API_KEY"
Sign in or create a free account to run this with your own key.

A hit returns definitions and definitionCount. Try a technical term such as idempotent: it returns 404, word not found.

When we tried idempotent, the dictionary returned 404. The word is real; this dictionary has no entry for it. Your error text should say exactly that, "no entry in the dictionary", not "invalid word", or the model will tell the user the word does not exist.

Both 429s look the same until you read a header. A rate-limit 429 clears in seconds. A credits 429 does not clear until the billing cycle renews. Check x-api-remaining-credits: if it is 0, no amount of waiting or retrying helps, and every retry is a wasted request. Halt the run and surface it.

403 is about the key, not the request. The agent's sub-key should be scoped to exactly the APIs in its tool list, so a 403 means the two have drifted apart: the agent was given a tool its key can't use. No argument the model picks will fix that. Halt the run so a person can fix the key's scope or remove the tool. Sending the user to sign in again or retrying are both wrong.

Check yourself

Inside an agent run, a tool call returns 429 and the response header x-api-remaining-credits is 0. What should happen?

Run every example on your own key. Free plan, no card.

Scaling up?

Volume pricing, custom SLAs, and dedicated support for high-traffic teams.

Contact sales