Mid · Core path · 7 chapters
Error recovery
Retries with a modified strategy, loop detection, budget caps on steps/tokens/time/money, circuit breakers
Without bounded, observable recovery, one bad tool call can turn an agent into an expensive loop that never returns a useful result.
Read these first
What you will know
Detect a repeating loop and break it
A repeated tool or action state can consume the entire allowance without making progress, so termination must happen before the next duplicate step.
Retry with a changed strategy rather than the same call
Changing the prompt, arguments, tool, or fallback path turns an input-specific or transient failure into a recoverable branch.
Enforce budgets on steps, tokens, time, and money
Each limit catches a different runaway mode, and omitting any one leaves a distinct route to unbounded resource use.
Run a budget-exhaustion test and verify the agent stops, summarises, or hands back safely
A hard ceiling prevents runaway spend, while the return path must preserve enough context for a caller to continue or diagnose the failure.
Reproduce a tool or model failure and verify autonomous recovery without repeating the failed action
The test should inject a failure and capture a successful alternate path, not merely a second attempt that happens to pass.
Chapters
- 1
Backoff answers a transport failure; a bad request needs a new one
A 503 and a 400 reading "invalid date format: expected YYYY-MM-DD" call for opposite responses. The first wants the identical call again after a jittered delay; the second will fail identically forever, and the fix is to return the error text to the model so it can reformat the argument or take another path. Applying the wrong one costs real money — a semantic failure retried on a schedule burns the whole allowance.
- 2
After five consecutive failures, stop calling the tool at all
Retrying with a changed strategy still assumes the dependency will eventually answer. When a search tool has returned 503 five times running, the useful move is to remove it from the rest of the run and tell the model it is unavailable, so the remaining steps route around the outage instead of spending the allowance rediscovering it. Where the breaker's state lives, and when it resets, is decided here.
- 3
Four budgets, because each catches a runaway the others miss
Steps, tokens, wall-clock and money are not four spellings of one limit. A token budget never notices a tool that hangs, where three iterations consume twenty minutes; a step budget never notices a single enormous context. Set actual numbers for an agent drafting 20,000 customer email replies a day at four tool calls each, and for every limit name the specific runaway that only it would catch.
- 4
Hash the call, not the text, to know the agent is stuck
Detection works on the normalised tool name and arguments: hash them, keep the recent set, and terminate before the same state recurs rather than after the allowance is gone. Then meet the false positive that arrives in week two, an agent legitimately polling a build-status endpoint every few seconds. Whitelisting the polling tool silences the alarm and leaves a permanent hole where an infinite wait can hide, which is the problem the next chapter has to solve.
- 5
A stuck run is one where nothing new entered the context
Call identity is the wrong evidence in both directions: a build-status poll repeats itself and is perfectly healthy, while an A-to-B-to-A cycle and a search reworded on every attempt are loops the hash never sees. The signal that separates them is progress — did the tool result change, did any state advance, is the goal measurably closer — and it is also what lets you keep the legitimate poll while still bounding it, by giving the wait its own budget drawn from the run's wall-clock instead of a whitelist entry that exempts it forever. Build the progress check alongside the hash and use the hash as the cheap first filter it is.
- 6
Exhausting a budget mid-task leaves state somebody has to own
Cutting the run off is the easy half. Stopping safely means a terminal result that names the budget which fired and carries the partial work and state, so the caller can continue or diagnose. The hard case is a money cap firing after two external writes have already landed: with no record of what completed, a resume repeats them and the agent becomes the source of the duplicates.
- 7
An agent that always returns something may be recovering badly
A recovery test earns the name only when it injects a specific failure and asserts the agent reached the goal by a different path; a second attempt that happens to pass proves nothing. The same standard applies to the month of zero failed tasks your teammate is proud of. A run that always returns a result may simply be one whose failures were converted into confident wrong output nobody flagged.
External resources
- Factor 9: Compact Errors into Context Windowgithub.com
How to feed failures back so the agent retries with a different strategy.
- Durable Agents: How to Build AI Systems That Survive a Crash with Samuel ColvinVanishing Gradients
Retries, resumption and idempotency for agents that fail mid-run.
- Deterministic Infra for Non-Deterministic AI Agents - Nishant Gupta, Meta Superintelligence LabsAI Engineer
Talk on circuit breakers and guardrails around unpredictable agent loops.