Chapter 10
Error Handling
Categories that decide retryability, the four ways information gets destroyed, and gaps you annotate instead of hide.
10.1
Four categories, four responses
Retryability is not a judgement call — it follows from the category.
| category | looks like | retryable | agent does |
|---|---|---|---|
| transient | timeout, 503, network drop | yes | retry with exponential backoff |
| validation | bad input format, missing required field | no — fix the input | modify the request, then retry |
| business | policy violation, threshold exceeded | no | explain to the user, offer an alternative |
| permission | access denied | no | escalate |
"Retryable" means calling again could ever succeed. A dissolved company is business, not a bug — retrying it a hundred times changes nothing.
10.2
Four ways to destroy information
Each of these leaves the coordinator unable to choose its next move — which is the only thing an error is for.
| anti-pattern | what breaks | instead |
|---|---|---|
| generic status | "search unavailable" — retry? re-query? escalate? no basis | return type, query, partial results, alternatives |
| silent suppression | empty result read as success — "no matches" and "it failed" look identical | distinguish the two explicitly |
| abort everything | one subagent fails, every partial result is thrown away | continue with partials and annotate the gap |
| infinite local retries | latency and spend burn inside the subagent, invisibly | 1–2 local retries, then propagate to the coordinator |
10.3
What a subagent owes the coordinator on failure
Six fields. Together they let the hub decide without re-running the work.
status
partial_failure — not a boolean; partial is its own statefailure_type
timeout — which category, so backoff-vs-escalate is decidableattempted_querywhat was actually tried, so a retry can differ from it
partial_resultswhatever did come back, with relevance — never discarded
alternative_approaches"try a narrower query" · "use another source"
coverage_impact"not covered: AI impact on music production" — the gap, named
10.4
Annotate the gap, never hide it
A report that quietly omits a section reads exactly like a report that had nothing to say.
Final synthesis
## Report: AI Impact on Creative Industries ### Visual Art (FULL COVERAGE) [research results] ### Music (PARTIAL COVERAGE — search agent timeout) [partial results] ⚠️ Coverage limited: the search agent timed out. ### Literature (FULL COVERAGE) [research results]
Partial coverage is a labelled result. Silent omission is a false claim of completeness.
Recall in 60 seconds
- Four categories: transient (retry with backoff), validation (fix input), business (explain), permission (escalate).
- Retryable means calling again could succeed — policy outcomes never qualify.
- A generic error string leaves the coordinator with no recovery decision to make.
- Never let an empty result stand in for a failure — distinguish "no matches" from "search broke".
- One subagent failing must not abort the workflow; keep the partials.
- Retry 1–2 times locally, then propagate upward. No infinite loops inside a subagent.
- A structured failure carries status, type, attempted query, partials, alternatives and coverage impact.
- Gaps get annotated in the final report —
PARTIAL COVERAGEplus the reason.