Curriculum › Context Management & Reliability · 15% of the exam

Error propagation in multi-agent systems

What you’ll be able to do

  • Return structured error context (failure type, what was attempted, partial results, alternatives) so the coordinator can choose a recovery
  • Distinguish access failures from valid empty results in what a subagent reports
  • Recover locally from transient failures and propagate only what the subagent cannot resolve
  • Annotate synthesis output with coverage: which findings are well supported and which areas have gaps

What you need to know

The coordinator can only recover from what it can see

In a coordinator–subagent system, the coordinator decides what happens after a failure: retry with a different query, route to another subagent, continue with partial results, or tell the user something is missing. Each of those decisions needs information. If the subagent's report says only "search unavailable," the coordinator can't tell whether the source timed out, rejected the query, or returned partial data before failing, so it can't choose well.

A useful error report carries structured error context:

  • Failure type: timeout, access/permission denied, malformed query, source error.
  • What was attempted: the query, the source, the parameters.
  • Partial results: anything retrieved before the failure.
  • Potential alternatives: a narrower query, a different source, a later retry.
before — the coordinator learns nothing
{"status": "error", "message": "search unavailable"}
after — enough context to choose a recovery
{ "status": "failed", "failure_type": "timeout", "attempted": {"source": "news_search", "query": "EV registrations Brazil 2025"}, "local_retries": 2, "partial_results": [{"title": "...", "url": "...", "date": "2025-11-02"}], "alternatives": ["narrow query to 'Brazil EV registrations Q3'", "try government_stats_search"] }

Access failure is not the same as “nothing found”

These two outcomes look similar (no results) and mean opposite things:

  • Access failure: the query didn't complete because of a timeout, an unreachable source, or a permission error. We don't know whether matching data exists. This needs a retry decision.
  • Valid empty result: the query ran successfully and nothing matched. That is a finding in its own right ("no recalls were filed for this product") and shouldn't be retried.

The subagent's report must make the distinction explicit. If both come back as an empty list, the coordinator will either retry real negatives pointlessly or, worse, report "no evidence found" for a source it never managed to read.

Two opposite anti-patterns

  • Silent suppression. Catching the error and returning an empty result marked as success. The workflow keeps going, but the gap is invisible. The final report confidently omits whatever that source would have contributed, and nothing downstream knows to look.
  • Whole-workflow termination. Letting one subagent's exception propagate to a top-level handler that aborts the run. Nine subagents' good work is discarded because the tenth timed out, when the coordinator could have retried, rerouted, or proceeded with a noted gap.

The right behavior sits between them: surface the failure, with context, to the component that can decide what to do about it.

Recover locally, propagate what you can’t resolve

Not every failure needs to reach the coordinator. A transient failure, like a brief timeout or a momentary source error, is best handled inside the subagent with a small number of local retries. Pushing every hiccup upward clutters the coordinator's context and turns it into a retry loop.

When local recovery doesn't work, the subagent propagates the error, and it includes what it attempted (including the retries it already made) and any partial results. That stops the coordinator from repeating the same retries and lets it use whatever was salvaged. Errors the subagent can't fix at all, such as a permission denial, should be propagated straight away rather than retried.

Make coverage visible in the final output

Error handling doesn't end at the coordinator. If a source stayed unavailable and the system continued with partial results, the synthesized report needs to say so. Structure the synthesis output with coverage annotations: which findings are well supported by multiple sources, and which topic areas have gaps because a source was unavailable.

report excerpt — coverage annotated
## Coverage - Europe, North America: well supported (6 and 4 independent sources) - Southeast Asia: limited (1 source) - Latin America: GAP. Regional registry database timed out after retries; no findings from that source. Treat Latin America conclusions as incomplete.

A reader can then treat the conclusions according to how well each area was covered, instead of assuming everything was checked equally.

Key concept

Subagents retry transient failures locally and propagate only what they can’t resolve, as structured context: failure type, what was attempted, partial results, alternatives. Keep access failures distinct from valid empty results, never disguise a failure as success, never abort the whole run over one failure, and annotate coverage gaps in the final output.

When a scenario shows a report that silently omits an area, look for an error that was converted into an empty success. When a scenario shows a run that died over one timeout, look for propagation straight to a top-level handler.

Practice scenario

ScenarioA multi-agent research system produces a report on electric-vehicle adoption that says "no significant growth was found in Latin America." Logs show the regional registry source timed out on every call. The search subagent catches exceptions and returns {"results": []} with a success status so that "one flaky source doesn't break the run."
Work it through, then open this

The subagent is suppressing an access failure and presenting it as a valid empty result, so the coordinator and synthesis agent reasonably conclude there’s nothing to report about Latin America. The fix is not to abort the run on failure, which is the opposite anti-pattern. Have the subagent retry transient timeouts locally a few times, then propagate a structured error (failure type, attempted query, retries made, partial results, possible alternatives) clearly marked as an access failure. The coordinator can then reroute or proceed, and the synthesis output should carry a coverage annotation flagging Latin America as a gap rather than a negative finding.

Build exercise — Design an error contract for a subagent

Intermediate · 30 min

What you’ll learn

  • Defining a structured error shape a coordinator can act on
  • Separating access failures from valid empty results
  • Carrying coverage gaps through to the final output
  1. For one subagent in a multi-agent design, define the shape of its result for three outcomes: success with results, success with no matches, and failure. The failure shape should include failure type, what was attempted, partial results, and alternatives.

    • Why: If the shape can’t express the difference between those outcomes, the coordinator can’t respond differently to them.
    • You should see: Three distinct shapes, where “no matches” and “failed” can’t be confused.
  2. Decide which failure types the subagent handles locally (e.g. transient timeouts, retried a small fixed number of times) and which it propagates immediately (e.g. permission denied). Record the retries in the propagated error.

    • Why: Local recovery keeps the coordinator’s context for decisions only it can make, and reporting attempts avoids duplicate retries.
    • You should see: A short rule table and an error example showing the local attempts already made.
  3. Simulate one source failing permanently and check the final report.

    • Why: The point of propagation is that the gap survives to the reader.
    • You should see: A coverage section naming the affected topic area as a gap due to an unavailable source, while the rest of the report completes normally.

Exam traps

Returning a generic status such as “search unavailable” that hides what failed and what was tried

The coordinator can’t choose a recovery without the failure type, the attempted query, partial results, and alternatives.

Catching a failure and returning an empty result marked as success

This hides the gap, so downstream agents report missing coverage as a negative finding.

Terminating the entire workflow because one subagent failed

Discards everything else that succeeded. Propagate the error to the coordinator so it can retry, reroute, or proceed with a noted gap.

Treating a timeout and a query with zero matches as the same outcome

A timeout needs a retry decision; a valid empty result is a finding. The report must keep them distinct.

Propagating every transient failure to the coordinator instead of retrying locally first

Transient failures are best retried inside the subagent. Propagate only what local recovery can’t resolve.

Presenting a report built from partial sources as if coverage were complete

Annotate which findings are well supported and which areas have gaps because sources were unavailable.

Sources

Quick check

Two hours into a Claude Code session spent reading files in a large codebase, Claude now describes "the typical repository pattern" instead of naming the OrderRepository class it found earlier, and gives different answers to the same question. What is the best next step?