PromptABCD
FeaturesLearnHow it worksUse casesFAQGuideBlogContext Blocks
Sign inGet started free
Sign inSign up
PromptABCD

A calm home for your best AI prompts. Save them once, find them in seconds, reuse them forever.

Product

  • Features
  • Chrome Extension
  • Free Courses
  • How it works
  • Use cases
  • Blog
  • Context Blocks
  • Export Anywhere
  • FAQ

Resources

  • User guide
  • Learn prompting
  • Sign in
  • Get started free

© 2026 PromptABCD. All rights reserved.

Privacy PolicyTerms and Conditions
Home/Blog/Agent Loop Engineering/How to Handle Partial Failures Inside the Loop
Agent Loop Engineering

How to Handle Partial Failures Inside the Loop

What happens when one tool call in a batch fails but the rest succeed? Handling agent loop partial failure well is the difference between a resilient agent and one that dies on a hiccup.

August 23, 2026·8 min read
ShareShare
⚡Featured Prompt— copy and use right now
def run_batch(calls):
    results = {}
    for c in calls:
        try:
            results[c.id] = {"ok": True, "value": run_tool(c)}
        except Exception as e:
            results[c.id] = {"ok": False, "error": str(e)}   # isolate, don't raise
    return results        # every call reports its own fate

What should your agent do when it fires five tool calls in a turn and one of them fails? This comes up constantly once agents batch their calls, and the answer separates resilient agents from brittle ones. The brittle agent treats any failure as total failure — one call errors, the whole turn throws, and four successful results get discarded along with the one that broke. Handling agent loop partial failure well means keeping what worked, isolating what didn't, and letting the agent decide how to proceed with a clear picture of both.

A partial failure is any situation where some of the work in a step succeeds and some doesn't. It's the normal case for any agent doing multiple things per turn, and treating it as all-or-nothing throws away good work and makes the agent far more brittle than it needs to be.

What Is an Agent Loop Partial Failure?

An agent loop partial failure happens when a step contains multiple operations and they don't all share the same fate. Three of five lookups return data and two time out. A batch of writes mostly succeeds but one hits a conflict. The step didn't fully succeed, but it didn't fully fail either — and how you handle that middle ground determines whether the agent recovers or collapses.

hljs python
[object Object], ,[object Object],(,[object Object],):
    results = {}
    ,[object Object], c ,[object Object], calls:
        ,[object Object],:
            results[c.,[object Object],] = {,[object Object],: ,[object Object],, ,[object Object],: run_tool(c)}
        ,[object Object], Exception ,[object Object], e:
            results[c.,[object Object],] = {,[object Object],: ,[object Object],, ,[object Object],: ,[object Object],(e)}   ,[object Object],
    ,[object Object], results        ,[object Object],

What this does: runs each call independently and records success or failure per call rather than letting one exception abort the batch — so a single failure never discards the results that succeeded alongside it.

The key move is that one failure doesn't abort the others. Each call reports its own outcome, and the agent gets the full picture: here's what worked, here's what didn't.

That per-call isolation is a small code change with an outsized effect on how the agent feels in production. A batch that fails as a unit gives you a binary — worked or didn't — while a batch that reports per call gives you a gradient the agent can actually navigate. Four of five is a very recoverable position; zero of five is a restart. The isolation is what turns the former into the reported outcome instead of collapsing it into the latter.

Why It Matters

All-or-nothing failure handling wastes work and destabilizes the agent. If four of five expensive lookups succeed and the fifth failing discards all five, you've paid for four results you threw away and the agent has to redo everything — including the four that were fine. Multiply that across a long run and a brittle agent spends most of its budget re-doing work that a single hiccup discarded.

Worse, all-or-nothing handling makes agents fragile in exactly the environment they operate in. Tools time out, rate-limit, and hiccup constantly; an agent that treats every transient failure as fatal will rarely finish a real task. Resilience isn't a nice-to-have here — it's the difference between an agent that works in production and one that only works in the demo where nothing fails.

⚡ Pro tip: Test your agent against injected failures, not just the happy path. Wrap your tools so you can force a chosen call to time out or error on demand, then confirm the agent keeps its other results and recovers. An agent that's never seen a failure in testing will meet its first one in production, which is the worst place to discover the handling is broken.

⚡ Pro tip: Feed partial results back to the model as partial results, explicitly labeled. Tell it "3 of 5 succeeded; here are the 3, and here's what failed and why." The model can often continue with what worked and route around what didn't — but only if you show it the real, mixed picture instead of hiding it behind a blanket error.

Handling Partial Failures Gracefully

Three moves turn a partial failure from a collapse into a recoverable step.

First, isolate — run each operation so one failure can't abort the others, capturing per-operation outcomes. Second, preserve — keep the successful results; never discard good work because something else failed. Third, inform — hand the model a clear account of what succeeded and what failed, so it can decide whether to retry, route around, or proceed.

hljs python
[object Object], ,[object Object],(,[object Object],):
    ok = {k: r[,[object Object],] ,[object Object], k, r ,[object Object], results.items() ,[object Object], r[,[object Object],]}
    failed = {k: r[,[object Object],] ,[object Object], k, r ,[object Object], results.items() ,[object Object], ,[object Object], r[,[object Object],]}
    note = format_partial(ok, failed)      ,[object Object],
    messages.append(observation(note))
    ,[object Object], ok        ,[object Object],

What this does: splits a mixed batch into successes and failures, preserves the successful values for reuse, and gives the model an explicit summary of both — so the agent continues from real partial progress instead of restarting the whole step.

⚠️ Common mistake: Letting one failed operation raise an exception that aborts the whole step. This is the default behavior of most code — one call throws, the function exits, everything unwinds — and it's exactly wrong for an agent doing batch work. Wrap each operation so failures are captured as data, not raised as control flow. An exception that escapes the batch is good work thrown in the trash because something unrelated hiccupped.

Deciding What to Do After a Partial Failure

Isolating and preserving is half the job; the agent still has to decide how to proceed. Give it a clear policy. For transient failures — timeouts, rate limits — retrying just the failed operations, with backoff, often clears them without redoing the successes. For persistent failures — a bad argument, a missing resource — retrying wastes time, and the agent should route around the failure or report it. The distinction is whether a retry could plausibly succeed.

There's a compounding-risk angle worth planning for, too. On a long agent run with many batched steps, small failure rates add up: if each step has even a modest chance of a partial failure, a twenty-step run is very likely to hit at least one. That's not an edge case to handle defensively — it's the expected path. An agent designed as if failures are rare will, on long runs, spend most of its time in the failure-handling code it treated as an afterthought. Build partial-failure handling as a first-class path, because at any real scale it's the common one.

⚡ Pro tip: Cap retries per operation and escalate after the cap. A transient failure that hasn't cleared after two or three retries is behaving persistently — stop retrying it, surface it to the model as failed, and let the agent route around it. Unbounded retries on a "transient" failure that's actually stuck is just a slow infinite loop wearing a friendlier name.

⚡ Pro tip: Classify failures as transient or persistent before deciding to retry. A

429 rate limit
or
timeout
is worth retrying; a
404 not found
or
invalid argument
is not. Blind retrying of persistent failures burns budget re-hitting a wall, while not retrying transient ones gives up on work a second attempt would have completed.

Common Mistakes

Two more traps recur. Teams retry the whole batch when only part failed, re-running the successful calls needlessly — retry only the failures, and keep the successes you already have. And teams hide partial failures from the model, either swallowing them silently (so the agent proceeds as if it has complete data when it doesn't) or blanket-failing (so it discards everything) — when the resilient path is to show the model the exact mixed outcome and let it decide.

Conclusion

Handling agent loop partial failure well comes down to three moves: isolate operations so one failure can't sink the others, preserve the work that succeeded, and inform the model of the real mixed outcome so it can recover intelligently. Classify failures to retry the transient and route around the persistent, and never discard good results because something unrelated broke. Do this and your agent survives the constant small failures of real environments instead of collapsing on the first one.

The mindset that makes it click is treating failure as data, not as an exception. An exception is control flow — it interrupts, unwinds, and demands to be either caught or fatal. Data is just information the agent reasons over, the same way it reasons over a successful tool result. The whole art of partial-failure handling is refusing to let a failure become control flow: capture it, label it, hand it to the model as one more observation, and let the agent decide. An agent that sees failures as facts to work with is far steadier than one that sees them as emergencies to escape.

The partial-failure handler and the transient/persistent classifier are reusable across every agent that does multiple operations per step. I keep them saved and versioned in PromptABCD next to the loop code, so a new agent is resilient by default — instead of the all-or-nothing default that throws away four good results because the fifth call timed out.

partial failureerror handlingagent loopresilienceai agentsreliability

Continue Reading

The Prompts That Drive Each Loop Step
Agent Loop Engineering

The Prompts That Drive Each Loop Step

One vague system prompt was making an agent loop badly — wrong tools, no stopping, no progress. Great agent loop prompts drive each step deliberately. Here's the teardown and the fix.

August 23, 2026·8 min read
Cost per Loop Iteration: Budgeting Token Spend
Agent Loop Engineering

Cost per Loop Iteration: Budgeting Token Spend

Most teams budget agent loop token cost by the total and miss where it actually goes. Here's a case where the real cost hid in re-sent context, and the fix that cut spend 60%.

August 23, 2026·8 min read
Checkpointing Agent State Between Iterations
Agent Loop Engineering

Checkpointing Agent State Between Iterations

Agent loop checkpointing saves the agent's state each iteration so a crash costs one step, not the whole run. Here's how to checkpoint what matters, cheaply, without slowing the loop.

August 23, 2026·8 min read

Save the prompts from this post

PromptABCD is a free prompt manager. Paste, organize, and reuse your best AI prompts — no more hunting through chat history.

Start free →
← PreviousCheckpointing Agent State Between IterationsNext →Cost per Loop Iteration: Budgeting Token Spend
Share this post:
ShareShare