← Multi-Agent Orchestrator
19 min

Failure Modes & Reliability

The multi-agent failure catalogue and the guardrails — budgets, termination, boundary checks — that tame it.

Lesson 7 of 9
0 done
In plain English

Groups of agents fail in their own ways. They go back and forth forever, or stop too early. One agent's made-up fact can be trusted by the next. Limit steps, tokens and time. Say clearly what done means. Check results outside the agent that made them.

Budget
A hard limit on steps, tokens, time or cost.
Termination criteria
The clear rule for when the job is finished.
Partial result
A useful but incomplete answer, labeled honestly.
Picture it
How groups of agents fail, and the fix
1
Going back and forth forever
Limit steps, tokens and time
2
Stopping too early
Say clearly what done means
3
Trusting a made-up fact
Check results outside the agent that made them
4
Runaway cost
Set a budget for every run

Teams of agents fail in ways a single agent does not. Researchers who studied hundreds of real runs from popular multi-agent frameworks found that failures fell into three families. The first is problems in how the task and the roles were set out. The second is problems in how the agents worked together. The third is problems in checking the results and knowing when to stop. None of these is about how smart the model is. They are design problems. That is good news, because design problems have design fixes.

A catalogue of failures

  • Endless loops and ping-pong: agent A asks B, B asks A, forever. Or a critic and a writer never agree.
  • Stopping too early: an agent says it succeeded because it ran out of ideas, not because the goal was met.
  • Spreading inventions: one agent makes up a fact, the next treats it as true, and the final answer states it with confidence.
  • Role confusion and ignored input: an agent drifts out of its role, or ignores a correction from a peer.
  • Lost context at hand-offs: the receiver does not know a limit that the sender knew.
  • Repeated or clashing work: two workers do the same thing, or undo each other's changes.
  • Runaway spawning: a lead starts workers that start more workers, and the bill explodes.
  • Fighting over a tool: parallel agents hit the same service and trigger rate limits or lock clashes.
  • Quiet partial failure: a worker fails, and the system reports success using the rest of the results.

Guardrail 1: hard budgets on everything

Every loop, every fan-out and every run needs a number limit that no prompt can argue with. Budgets are the most valuable reliability feature you can add. They turn failures with no end into failures with a limit, which you can see.

budget.py
from dataclasses import dataclass, field
import time

@dataclass
class Budget:
    max_steps: int = 40
    max_tokens: int = 400_000
    max_seconds: float = 300
    max_spawn_depth: int = 2
    max_workers: int = 8
    steps: int = 0
    tokens: int = 0
    started: float = field(default_factory=time.monotonic)

    def charge(self, tokens: int = 0):
        self.steps += 1
        self.tokens += tokens
        if self.steps > self.max_steps:           raise BudgetExceeded("steps")
        if self.tokens > self.max_tokens:         raise BudgetExceeded("tokens")
        if time.monotonic() - self.started > self.max_seconds:
                                                  raise BudgetExceeded("time")

# Pass the SAME Budget object through the whole run, including into sub-agents.
# On BudgetExceeded: stop, return what you have, flag it as partial.

Guardrail 2: clear ways to stop

Tell each agent what done means in terms you can check. For example: fields filled in, tests passing, or N sources cited. Have a checker outside the agent that made the work confirm it. Finish when you are satisfied invites both stopping too early and polishing forever. Where you can, make the final check plain code: run the tests, check the schema, and check that every claim has a source address.

Guardrail 3: check at the boundaries

  • Check every hand-off and result against its schema. Reject and retry the ones that are malformed.
  • Ask for references or evidence IDs for factual claims. Spot-check that the cited source really says it.
  • Use an independent checker for high-stakes claims, one that does not see how the maker reasoned.
  • Label unchecked facts as unchecked when they cross a boundary, so the agents after them can weigh them.

Guardrail 4: the habits of distributed systems

  • A timeout on every outside call and every worker.
  • Retries with longer waits and a little randomness, only for errors that are really worth retrying.
  • Idempotency keys on side effects, so retries and resumes cannot do the same thing twice.
  • Circuit breakers: after N failures in a row from a service, stop calling it for a while and carry on in a reduced way.
  • Dead-letter handling: work that keeps failing goes to a queue that a person reviews, and does not loop.
  • Graceful degradation: return a partial result with an honest list of gaps, and do not fail the whole run.

Partial results are a feature

Say one of eight workers fails. The right behavior is usually to deliver the seven good results, with a clear note of what is missing and why. Do not retry forever, and do not pretend nothing happened. Design your combining step to accept and report gaps. And make incomplete a proper status for a run.

⚠A debugging tip: the failure you see, a wrong final answer, is rarely where the bug is. Trace backwards through the hand-offs to the first point where a fact became wrong or a limit was dropped. That is why the next path is about observability.
Key takeaways
  • ✓Multi-agent failures fall into three groups: how the task is set up, how the agents coordinate, and how results are checked and stopped.
  • ✓Hard number limits on steps, tokens, time, depth and workers turn failures with no end into failures with a limit.
  • ✓Define stopping in terms you can check, and have a checker outside the maker.
  • ✓Use the habits of distributed systems: timeouts, longer waits, safe repeats and circuit breakers. Deliver honest partial results.
Hands-on exercise

Break your own orchestrator on purpose

  1. Take any multi-agent prototype. Add three faults: a worker that returns broken JSON, a worker that hangs, and a worker that returns a believable but false fact.
  2. See what the system does by default for each one. Be honest about what it hid.
  3. Add a schema check, a timeout and a rule that every claim needs a source, one for each fault.
  4. Run it again. For each fault, record whether the final output flags the problem or hides it.
Check yourself
Q1Name two ways a loop between a writer and a critic can fail to end, and give the fix.show answer

The critic keeps finding new nitpicks, or the writer cannot meet a vague rule. The fix is a concrete checklist, code checks where possible, and a hard limit on rounds with a clear fallback.

Q2One of eight workers fails. What should the final answer do?show answer

Deliver the seven good results, list the gap and the reason, and mark the run as partial. Do not hide it, and do not loop forever.

Q3Why pass one shared Budget object to sub-agents instead of giving each its own?show answer

Separate budgets add up. Ten workers, each with a small budget, can still spend ten times the total. A shared budget limits the whole run.

← Agent Protocols: MCP vs A2ACost, Latency & Evaluation →
0 / 9 finished0%