Error recovery mid-loop#
How the kernel reacts to a failure surfacing mid-turn — a model-provider error, or a tool-provider (plugin) crash. Both are loop-level behavior and belong here rather than in the category protocol that defines the error taxonomy itself.
Model-provider errors#
Per model/conformance.md#error-taxonomy, the kernel's reaction to each error category is:
rate_limited/overloaded: the kernel MUST retry with exponential backoff and jitter. Base retry delays vary by more than an order of magnitude across surveyed harnesses, with no convergent "correct" value — the kernel MUST make the base delay and backoff factor configurable, shipping with canonical defaults rather than requiring configuration before first use:base_delay_ms = 500,backoff_factor = 2,max_retries = 5(configuration/blocks-reference.md'ssettings{}block). These are a reasonable midpoint of the observed range across harnesses, not derived from any single one — operator-overridable, not load-bearing precision. The kernel MUST honor a suppliedretry_after_secondswhen present (bothModelError.retry_after_secondsand, where the transport surfaces raw HTTP headers,retry-after/retry-after-msforms). Per-attempt and per-session retry caps MUST be tracked separately — a session-wide retry ceiling prevents an endlessly-retrying single call from silently consuming the entire wall-clock/cost budget (turn-algorithm.md#independent-bound-dimensions) without ever advancing the turn counter.context_length_exceeded: the kernel MUST NOT blindly retry the same request. This MUST instead trigger a context-reduction path on the nextcontext-assemblepass (compaction/pruning mechanics are context- and memory-provider concerns — seecontext/README.mdandmemory/README.md, not specified here) or, if no context provider can shrink further, fail the turn cleanly with a distinguishable status rather than looping.auth_error/invalid_request: the kernel MUST NOT retry and MUST NOT silently fall back to another model in a routing chain — both are configuration/programming errors that retrying cannot fix and that fallback would only mask.content_filtered: the kernel MUST surface this distinctly (already required bymodel/conformance.md#error-taxonomy) so apost-model-responseobserver or the frontend can react differently than to a generic failure.
Tool-provider (plugin) crashes#
Denial surfaces as tool-result text in every surveyed open-source harness, letting the model observe and adapt rather than the session dying — this generalizes cleanly to plugin crashes even though the two failure modes aren't identical. A single Invoke failure SHOULD be surfaced as an error-flagged tool_result content block for that call (not a session-ending fault), giving the model the same observe-and-adapt opportunity a denial gets. Repeated crashes from the same provider within a session SHOULD trip the same circuit-breaker mechanism described for denials in plan-apply-gate.md#circuit-breaker-on-repeated-denials, since an infinite crash-retry loop is the failure-mode analog of a denial storm. This is a design recommendation reasoned by analogy from the denial pattern rather than a pattern directly established for crashes specifically — see conformance.md#open-questions.
A crashed plugin subprocess surfaces as the process_crashed error category — the kernel does not treat a crashed plugin as a silent hang; it fails the in-flight call promptly, which is what makes the SHOULD-level tool-result-error handling above possible in the first place.