Cascading failures occur when one failure triggers additional failures across an agent workflow or a multi-agent system. A bad retrieval result leads to a bad plan, which leads to a wrong tool call, which leads to an incorrect or unsafe final answer.
The practical consequence is that the failure you can see is almost never the failure you need to fix. By the time something throws, the original bad value has been restated, summarized, and used as an argument three times. An agent that reports “I could not complete the transfer because the account is closed” may be reporting the truthful end of a chain that started when a lookup tool returned the wrong account.
Agents are unusually exposed to this because there is no type system between steps. A step’s output is text, the next step accepts text, and nothing between them asserts the text is correct. Later steps trust earlier steps by default.
Key takeaways
- The visible failure is downstream of the cause. Debugging from the error message finds the messenger.
- The dangerous pattern is not an exception propagating, it is a wrong value being accepted as a premise and never questioned again.
- Tool errors get laundered into content. An error string summarized in prose stops looking like an error to every step after it.
- Multi-agent chains amplify this, because a subagent’s malformed or partial output arrives as a confident report and the orchestrator has no way to check it.
- Containment beats detection: validate at boundaries, keep error status typed rather than narrated, and checkpoint before state-changing actions.
The shapes this actually takes
A wrong value becomes the premise
get_account_balance returns 1499. The field is cents, the agent reads dollars, and every subsequent step is internally consistent and wrong: the eligibility check passes, the plan proposes a payment, the confirmation cites a figure the customer knows is false. No span has status ERROR. The failure is a unit mismatch in step two and a customer complaint in step nine.
This version survives review, because each step did exactly what it was designed to do with the input it received.
An error gets laundered into content
A tool returns {"error": "upstream timeout"}. The model reads that string as information, writes “there are currently no transactions on this account,” and continues. The error is now a fact. Every step after it reasons over a confident false statement, and the trace shows a successful session with a wrong answer rather than a failed session.
This one is worth checking for by name. If tool errors reach the model as ordinary text in the same channel as tool results, you will find instances of it. The fix is to make failure a distinct signal the harness handles, not a string the model interprets.
A subagent’s output propagates through a chain
A research subagent returns four findings and a truncated fifth. The parser is lenient, so partial output parses. The orchestrator treats the set as complete, writes a summary, and hands it to a drafting agent that produces a polished document missing the finding that mattered. Nobody’s trace looks broken. This pattern shows up repeatedly in field analysis of how production agents break, and it is a reason strict output contracts between agents earn their cost.
Retries amplify instead of recovering
An agent hits a rate limit, retries immediately, and retries again. The shared quota is now exhausted for every other session using that tool, so unrelated sessions start failing and their agents also retry. This is the classic infrastructure cascade, and agents cause it easily because retry behavior is often implicit in the loop rather than configured with backoff and a cap.
Why the trace is the only place to see it
Each component can be individually healthy while the chain is broken. That is what makes cascades resistant to the tests teams already have: a unit test asserts that get_account_balance returns cents correctly, and it does. Agent tests have to cover failures that component-level tests pass through, which means asserting on the sequence rather than on each function.
Finding the origin is a reading technique. Open the session, start at the first span, and walk forward asking one question at each step: is this output correct given this input? The first no is the origin, and everything after it is consequence. Reading backwards from the exception feels faster and costs more time, because the last five spans all look reasonable given what they were handed.
Two things make this practical. Sessions have to be reconstructable as an ordered trajectory across every service and subagent involved, which is what an agent observability platform provides. And tool spans have to record real inputs and outputs, because a cascade is identified by comparing what a step received against what it produced.
Containment
- Validate at boundaries. Schema-check tool results and subagent output before they enter the next prompt. Reject partial parses instead of accepting them.
- Keep failure typed. Set span status to error and let the harness pick the fallback. Do not hand a raw error payload to the model as if it were data.
- Checkpoint before side effects. Any step that writes, pays, sends, or deletes should be gated on a verification that its inputs came from a validated read.
- Cap the loop. A step limit, a token budget, and capped retries with backoff turn an unbounded cascade into a bounded failure you can page on.
- Assert identifiers and units. The cheapest guard against premise failures is checking that the ID in step nine is the ID from step two.
FAQ
How is a cascading failure different from a single agent failure?
A single failure is one step doing the wrong thing. A cascade is one step doing the wrong thing and every later step accepting it. The distinction matters because the fix location differs: a single failure is fixed where it happened, a cascade is fixed both there and at the boundary that should have caught it.
Is this the same as cascading failure in distributed systems?
It shares the name and half the mechanism. The infrastructure version is load propagation: a slow dependency causes queueing, queueing causes timeouts, retries add load, and the failure spreads sideways to healthy services. Agents produce that too, usually through uncapped retries against a shared quota. The version specific to agents is semantic: nothing is overloaded, and a wrong value simply travels forward as an accepted fact.
How do I find where a cascade started?
Walk the trajectory forward and find the earliest output that is wrong given its input. Two shortcuts help. Search the session for the first appearance of the bad value, such as a wrong ID or figure, since the span that emitted it first is usually the origin. And check whether any tool returned an error the model then narrated as content.
Do retries make cascades better or worse?
Both, depending on what failed. Retrying a transient timeout with backoff is recovery. Retrying a call whose arguments were wrong repeats the same wrong call, spends tokens, and can exhaust a quota other sessions need. Retry policy should depend on error class, which requires the error class to be preserved rather than flattened into text.
Can evaluations catch cascading failures?
Trajectory-level ones can, and final-answer ones structurally cannot. An eval reading the whole sequence can flag a step whose output does not follow from its input, or a final answer citing a value that never appeared in any tool result. An eval that sees only the response records a wrong answer with no information about which of nine steps to fix.