Why doesn't retrying fix my agent's tool failures?

Classic retry logic assumes a deterministic call and a transient error: try the same thing, it works. An agent's tool call is non-deterministic and sometimes semantically wrong, so a retry repeats the mistake or duplicates the action.

B

Balagei G Nagarajan

4 MIN READ


When an agent gets stuck, it tends to repeat the same failed action instead of recovering. Rather than trying something different, it loops on the doomed call, burning tokens and time (Early Diagnosis of Wasted Computation in Multi-Agent LLM Systems, arXiv:2606.01365, 2026). Classic retry assumes a transient glitch. An agent's failure is usually the same wrong decision, repeated.

A looping arrow that, instead of returning to the same point, lands somewhere slightly different each pass, while a parallel clean loop returns precisely, contrasting deterministic retry with divergent agent retry
Retry can produce different arguments, a different tool, a different plan.
— from “Why doesn't retrying fix my agent's tool failures?”

Key facts.

  • Stuck agents repeat the same failed action rather than recovering. A blind retry only amplifies this. (arXiv:2606.01365, 2026)
  • Exponential backoff with jitter assumes a deterministic operation and a transient fault. Neither holds for a probabilistic, semantically-failing tool call. (AWS Builders' Library)
  • Retrying a non-idempotent call duplicates its side effect. A side-effecting retry needs an idempotency key and a durable executor that won't replay completed steps.

Why does classic retry logic break here?

Exponential backoff with jitter, the standard pattern, assumes two things: the call is deterministic, and the fault is transient (AWS Builders' Library). Your agent breaks both. The call comes from a probabilistic model. Retry can produce different arguments, a different tool, a different plan. When stuck, agents don't explore alternatives. They loop on the same wrong call. Retry was built to replay a known-good action past a glitch, not to re-roll a probabilistic decision.

What is a semantic failure, and why doesn't retry help?

A semantic failure is a well-formed call with the wrong intent. Right syntax, wrong meaning, a hallucinated tool name, arguments that don't fit the task. There's no transient fault, so retrying the identical call produces the identical wrong result. In a loop, it can hammer indefinitely through a rate limit it'll never clear. When the call has side effects and no idempotency key, a retry doesn't just waste time, it duplicates the action. Second charge. Second email. The server has no way to know this is the same request. One error, two problems.

# Classify before you retry; don't re-run a hallucination or a non-idempotent call
def on_error(err, call):
 if err.transient: return backoff_and_retry(call) # 5xx, timeout
 if err.semantic: return replan_or_escalate(call) # wrong intent / hallucinated tool
 if call.mutating and not call.idempotency_key: return escalate(call) # never blind-retry
 return abort(call)

How do you make retries actually safe?

Split planning from execution. The non-deterministic part, picking the tool and arguments, stays in the planning layer. The side-effecting execution gets idempotency keys, so a repeat replays the first result instead of acting again. Classify every failure before you decide what to do: transient faults get bounded backoff, semantic failures go to a re-plan or escalation, ambiguous ones go to a human. Side-effecting steps run on a durable executor that caches completed steps, restarts don't re-run them. That's it. Retry then does what it's actually good at: recovering from a real glitch.

A two-path diagram: a transient error routed to bounded backoff and a successful retry, and a semantic error routed away from retry into re-plan or escalate, with a gate marking idempotency required before any side-effecting retry

Traditional retry versus agent retry

AssumptionTraditional softwareLLM tool calling
DeterminismSame call, same behaviorRetry can pick a different wrong call
Error typeMostly transientOften semantic, not fixed by retry
IdempotencyUsually designed inMutating tools often lack keys
Correct responseBackoff and retryClassify: backoff, re-plan, or escalate
Loop riskBoundedCan hammer a doomed call

Retry was built for deterministic, transient faults. Your agent's tool calls are neither. Blind retry repeats a semantic error or duplicates a side effect. Classify the failure, re-plan instead of re-rolling, gate every side-effecting retry on idempotency, then recovery works the way you expect. Find where your agent breaks, from the goal, before you build it.

Frequently asked questions

If retries don't fix it, will a smarter model retry better?
Retry assumes a transient fault; the failure is semantic, so a more capable model just repeats the wrong call. (arXiv:2606.01365)

When is a retry actually appropriate?
On a genuinely transient fault, a timeout or 5xx, where the same call can succeed shortly, and only when the call is idempotent so a repeat can't duplicate a side effect. Otherwise re-plan or escalate.

How do I stop an agent looping on the same bad call?
Classify the error. A semantic failure routes to a re-plan or escalation, never an identical retry. Put a hard cap on attempts so a doomed call can't hammer indefinitely.

Does a durable workflow engine replace this?
It gives you exactly-once step replay for restarts. But you still need error classification and idempotency keys on the external mutating calls themselves.


Share this post

Join the discussion

Have a take, a war story, or a question? Sign in with GitHub to comment and react. Comments are powered by GitHub Discussions, ad-free and yours to moderate.

Continue Reading

Find where your agent breaks, before you build it

Faultmap maps where your agent will fail from the goal and your data, then hands you the first test suite it has to pass.