The Difference Between Retry and Recovery

Retries are useful when the world is temporarily noisy.
A request times out. A model endpoint returns a transient error. A browser action races the page load. A file lock clears a second later. In those cases, doing the same thing again can be the right move. The system did not learn anything new about the task. It only waited for the environment to become ready.
But many agent failures are not temporary noise.
The agent searched the wrong directory. It used a stale assumption. It called the right tool with the wrong argument. It ignored a build warning. It treated a 200 response as proof even though the body was an old app shell. It summarized partial evidence as completion.
Repeating those actions does not make the system more reliable. It just gives the same mistake another chance to look busy.
That is the difference between retry and recovery.
A Retry Repeats the Attempt
A retry says: the operation may have failed for a reason outside the plan.
The request was valid. The target was correct. The preconditions were still true. The failure looks temporary enough that another attempt is reasonable.
This is familiar engineering territory. We add bounded retries around network calls, queue consumers, flaky dependencies, and eventually consistent APIs. We use exponential backoff so the system does not amplify an outage. We cap attempts so a stuck operation does not run forever. We make writes idempotent so repeating the same request does not create duplicate side effects.
For agents, this layer still matters. Tool calls fail. APIs rate-limit. Browsers hang. Sandboxes get slow. A production agent that gives up on every transient failure will feel brittle.
But retry logic only works when the retry is attached to a narrow operation with a stable contract.
If the agent was trying to fetch a known URL and the request timed out, retrying can be appropriate. If it was trying to determine whether a post is live and the first probe returned a generic fallback page, retrying the exact same conclusion is not appropriate. The operation did not merely fail. It revealed that the evidence was insufficient.
Retries handle temporary failure. They do not understand failure.
Recovery Updates the State
Recovery says: the failure changed what the system knows.
That means the next action should not be a blind repeat. It should incorporate the new evidence.
If a build fails because a module cannot be resolved, recovery is not “run the build again” three times. Recovery is inspect the import path, check the package state, repair the dependency, and then rebuild. If a search returns no results, recovery is not always “search again.” It may be to broaden the pattern, inspect the directory structure, or question the assumption that the file exists.
For agents, recovery is especially important because the system is choosing its next step. A failed tool call is not just an exception. It is new context for planning.
The agent should ask:
- What did this failure prove?
- Which assumption is now weaker?
- Which part of the task contract is at risk?
- Is the next safe action still the same?
- What evidence would distinguish a transient failure from a wrong plan?
Those questions do not require exposing private chain-of-thought. They require making decision state explicit enough that the system can change course when the world contradicts it.
A recovery path updates the plan before it acts again.
The Quiet Failure Is Retrying the Wrong Plan
The dangerous version of retry logic in agent systems is not an obvious loop.
It is a polished run where each individual action looks plausible, but the system never absorbs the signal that the plan is wrong.
The agent checks a route and gets 200. It does not inspect the body, so it misses that the route is serving a stale shell. It reports that the page is live. When challenged, it probes the route again, gets another 200, and repeats the claim.
From an infrastructure view, the requests succeeded. From a reliability view, the agent failed to recover. The result did not answer the real question.
The same pattern shows up in local development. The agent runs tests, sees a warning about a missing asset, and reports success because the exit code was zero. It edits a draft without checking the frontmatter convention. It sees a dirty git tree and continues as if every file belongs to the current task.
None of those failures are fixed by “try again.”
They are fixed by changing the acceptance check, preserving the evidence, and forcing the next action to account for what was observed.
Recovery Needs a Boundary
Recovery should not mean improvising forever.
A reliable agent needs boundaries around both retries and recovery. Retrying without a cap can burn time, money, or API quota. Recovering without a boundary can drift into unrelated work, destructive changes, or public side effects.
The boundary depends on the task. A local build repair might allow inspecting package files and changing a missing import. A publishing workflow might allow local drafts and builds, but stop before committing or pushing. A customer support workflow might allow gathering evidence, but require human approval before sending a high-impact response.
Good recovery logic keeps those boundaries visible.
It should know when it is allowed to try a different tool, when it must ask for approval, when it should report a blocker, and when continuing would be worse than stopping. The goal is not an agent that never fails. The goal is an agent that fails in a way the operator can trust.
That means the final answer should distinguish:
- The operation was retried and eventually succeeded.
- The original plan failed, recovery changed the state, and verification passed.
- Recovery was attempted but blocked.
- The next step requires approval.
Those are different outcomes. A reliable system should not compress them into “done.”
Make Recovery Testable
The easiest way to improve recovery is to turn past failures into eval cases.
Take a real trace where the agent repeated the wrong action. Preserve the request, the tool result, the incorrect conclusion, and the safer next step. Then write the eval around the behavior you wanted:
- If a route probe returns
200, inspect the body for the expected content before claiming the page is live. - If the git tree is dirty before editing, preserve unrelated files and mention them in the final state.
- If a build emits a warning tied to the requested artifact, do not summarize the build as clean.
- If an asset is missing, either create it, prepare a brief, or report that the post is not publish-ready.
- If a tool failure changes the available evidence, update the plan instead of repeating the same claim.
These are not abstract reliability principles. They are concrete checks that make recovery observable.
The eval does not need to judge whether the agent sounded thoughtful. It needs to judge whether the agent changed behavior when the evidence required it.
Use Both Loops Deliberately
Production agents need retries. They also need recovery.
A retry is an execution loop: attempt the same bounded operation again because the failure may be temporary. Recovery is a decision loop: update the plan because the failure taught the system something about the task.
Confusing the two leads to agents that look persistent but remain brittle. They keep acting. They keep producing confident summaries. They keep turning incomplete evidence into completion claims.
The practical design rule is simple: retry narrow operations, recover from changed assumptions.
If nothing important has changed, a bounded retry may be enough. If the result changes what the agent knows, the next action should change too.
Reliability is not just getting the system to try harder.
It is getting the system to notice when trying the same thing is no longer the right move.