Length recovery
Length recovery is BMO’s same-run continuation path for three pressure cases:
- the model stops with
MaxOutputTokens - prompt-budget preflight says the next turn will not fit
- the provider returns a context-length error
When recovery is enabled, BMO summarizes the current session state and queues a bounded continuation instead of letting the run stop on length alone. The runtime records each attempt as metadata-only recovery evidence so operators can tell whether recovery queued another turn, hit the continuation cap, failed to summarize, or was suppressed by config or cancellation.
Shared recovery lane
Section titled “Shared recovery lane”flowchart TD
trigger["Length pressure"] --> lane{"Shared recovery lane"}
lane --> summary["Summarize or compact current context"]
summary --> outcome{"Terminal outcome"}
outcome --> queued["continuation_queued"]
outcome --> capped["cap_reached"]
outcome --> failed["summarize_failed"]
outcome --> suppressed["suppressed or cancel_suppressed"]
All three triggers use the same recovery lane:
| Trigger | Meaning |
|---|---|
max_output_tokens | The provider stopped because the response hit its output cap. |
prompt_budget_preflight_exceeded | BMO predicted the next turn would overflow before sending it. |
context_length_exceeded | The provider rejected the request for context length. |
The recovery policy is intentionally bounded. BMO does not keep queuing continuations forever; it stops at the configured continuation cap and records that outcome explicitly.
What gets recorded
Section titled “What gets recorded”Each recovery attempt is captured as one bounded lengthrecovery.Episode:
- wall-clock time
- hashed session identifier
- trigger
- continuation number and continuation cap
- summarization engine (
streaming_compaction,legacy_summarize, ornone) - terminal outcome
- optional bounded reason (
summarization_disabled,context_canceled,context_deadline_exceeded)
The episode record is strictly metadata-only. It never stores prompt text, summary text, tool payloads, raw provider error bodies, or full session IDs.
Outcomes
Section titled “Outcomes”| Outcome | Meaning |
|---|---|
continuation_queued | Recovery succeeded and BMO queued the next continuation turn. |
cap_reached | Recovery would have continued, but the configured continuation cap was already reached. |
summarize_failed | The summarization step failed, so no continuation was queued. |
suppressed | Recovery was intentionally skipped or a deadline suppressed queueing before another continuation could be added. |
cancel_suppressed | A cancellation or interruption won before BMO could queue the continuation. |
When streaming compaction is enabled, the recorded engine is
streaming_compaction. Otherwise BMO records legacy_summarize. Suppressed
attempts that never summarize record none.
Operator surfaces
Section titled “Operator surfaces”Every operator surface reads the same shared status family:
| Surface | Purpose |
|---|---|
bmo config show-length-recovery | Config-first summary of the recovery lane. |
bmo config show-length-recovery --format=json | Same snapshot as machine-parseable JSON. |
/length-recovery (aliases /lr, /length_recovery) | In-process operator report with current config, ring stats, and latest recorded episode. |
GET /v1/length-recovery/status | Authenticated HTTP route for the shared JSON snapshot. |
get_length_recovery_status | Native agent tool exposing the same status family. |
bmo_get_length_recovery_status | MCP twin of the native tool. |
The snapshot includes:
- summarization enablement
- continuation cap
- whether streaming compaction is enabled
- custom continuation-message or template-path overrides
- recent-evidence scope (
process_local) - recent recovery ring capacity, count, saturation, and episode tail
Detached CLI reads stay truthful about authority. They report local config and defaults, but they do not pretend to replay another process’s in-memory recent-episode ring.
Sidebar and TUI readout
Section titled “Sidebar and TUI readout”The TUI sidebar exposes the latest live runtime outcome as a short label:
queuedcappedfailedcancelledsuppressed
The full /length-recovery report renders the same shared status snapshot used
by the agent tool, MCP tool, and HTTP route.
Tracing and containment
Section titled “Tracing and containment”Length recovery keeps the existing structured log vocabulary:
length_recovery.firedlength_recovery.action
The recent episode ring complements those logs. Use the logs when you want the chronological event stream; use the status family when you want the bounded current posture plus the newest process-local recovery outcomes in one call.
Scope and non-goals
Section titled “Scope and non-goals”- This feature does not redesign summarization or compaction policy.
- It does not persist raw summaries or transcript fragments in the recovery ring.
- It does not create a second recovery route family; the shared
length_recoverystatus family remains the canonical inspect surface. - Prompt-budget preflight overflow may still interact with broader context-pressure handling, but the length-recovery status family only reports the bounded summarize-and-continue lane described here.
Related
Section titled “Related”- Tools Reference
- Configuration
- Session Compaction
- Adaptive Context
- Maintainer topic: Session compaction topic