A session grows until it no longer fits the model’s context window. Compaction is omp’s answer: replace the older half of the transcript with a single summary entry and keep the recent tail verbatim. The next turn sees system, then the summary, then the kept tail — enough recent detail to keep working, plus a digest of everything before. The original entries stay on disk; only the live message stream is rewritten.
What it preserves, what it summarizes
compaction.keepRecentTokens (default 20000) sets the target size of the kept tail. The cut point is chosen at a message boundary inside that window; tool results are never split across the boundary. Metadata entries that precede the cut (model changes, thinking-level changes, labels) are pulled forward into the kept region so the recent turns still parse.
Before the cut, omp may prune large tool outputs first. The default policy protects the newest 40000 tool-output tokens, requires at least 20000 total estimated savings, and never touches skill results or reads of skill files. Pruned outputs are replaced with a [Output truncated - N tokens] placeholder. Everything else older than the cut is collapsed into one summary that records the gist of the conversation plus a <files> tree of paths the session has touched, each marked (Read), (Write), or (RW).
The summary entry is appended to the session as a CompactionEntry with type: "compaction", the verbatim summary, the firstKeptEntryId, and tokensBefore. The pre-compaction entries remain on disk; /tree can still walk back into them.
Manual: /compact [focus]
Run /compact at any point to force compaction on the current branch. The optional argument is free-text passed to the summarizer as extra instructions — use it when the default summary would overweight the wrong thread:
/compact Focus on the API redesign decisions; the migration scripts are scratch work.Manual compaction aborts the current turn first, then summarizes, then writes the entry. It works regardless of compaction.enabled — that setting only gates the automatic paths. Plan mode offers the same primitive through Approve and compact context when accepting a plan.
Automatic triggers
Four automatic paths share the compaction machinery but differ in when they fire and what happens after.
| Trigger | Fires when | After compaction |
| ------------------------------ | ------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| Overflow recovery | The model returns a context-overflow error on the current turn. | Retries the same turn. A larger model in the configured promotion chain is tried first; compaction only runs if promotion is unavailable. |
| Incomplete-output recovery | The model burns its output budget and stops with an incomplete response (no usable deliverable). | Drops the dead turn and retries it. Promotion to a larger model is tried first; compaction only runs if promotion is unavailable. |
| Threshold maintenance | A successful turn | | lands and adjusted context tokens exceed the resolved threshold. | Schedules an auto-continue prompt unless compaction.autoContinue is false. |
| Idle maintenance | Session is idle, not streaming, not already compacting. | Stops. No auto-continue. |
The threshold defaults to contextWindow - max(15% of contextWindow, reserveTokens). Override it with compaction.thresholdPercent or compaction.thresholdTokens; whichever is positive wins.
Non-compaction retry
Not every failure is an overflow. Provider overloads, rate limits, 5xx responses, socket resets, and usage-limit errors are transient — re-sending the same prompt usually works. omp routes those through a separate retry policy that does not compact:
-
The agent classifies the error message against transient patterns (
overloaded,rate limit,429,5xx,connection reset,fetch failed, usage-limit, retry hints). -
Context-overflow errors are explicitly excluded and fall through to compaction instead.
-
The failing assistant entry is stripped from live agent state (still kept in the session file) and the turn is rescheduled after a backoff delay.
Backoff is exponential: retry.baseDelayMs * 2^(attempt - 1), with 75–100% jitter and an 8 s cap. With the default 500 ms base, that’s 0.5 s, 1 s, 2 s, doubling up to the cap. Provider-supplied hints (retry-after, retry-after-ms, x-ratelimit-reset) can override the local delay. If a configured fallback chain (retry.fallbackChains) offers a different model or credential, omp switches and retries immediately with no delay; the original is restored when its cooldown expires unless retry.fallbackRevertPolicy is "never".
retry:
enabled: true
maxRetries: 10
baseDelayMs: 500
maxDelayMs: 300000
fallbackRevertPolicy: cooldown-expiryThe TUI shows Retrying (n/max) in Ns… (esc to cancel) while a retry is pending. Esc cancels the backoff and ends the retry chain; the global abort also cancels in-flight retries. After max attempts the session emits auto_retry_end { success: false, finalError } and the turn surfaces as failed — no automatic compaction, no second attempt.
Inspecting context and compaction
/context prints a per-bucket breakdown of the live window: system prompt, system tools, system context, skills, messages, the auto-compact buffer, and remaining slack. Each bucket gets an ASCII bar and a token count, so it’s obvious which one will overflow first.
/usage reports provider rate-limit headroom against the active credential. When a turn stalls, check /usage before reaching for /compact to rule out a quota wall — the retry path handles that automatically.
Compaction entries are visible in the session file as JSON objects of the form { "type": "compaction", "summary": "…", "firstKeptEntryId": "…", "tokensBefore": N }. The orchestrator’s session_compact hook fires after each one, so extensions can log or react to them.
Settings
In ~/.omp/agent/config.yml:
compaction:
enabled: true # master switch for automatic paths
strategy: context-full # "context-full" | "handoff" | "shake" | "snapcompact" | "off"
reserveTokens: 16384 # headroom kept under the context window
keepRecentTokens: 20000 # target size of the verbatim tail
autoContinue: true # schedule continuation after threshold compaction
idleEnabled: false # run maintenance while idle
thresholdPercent: -1 # explicit % override; -1 = auto
thresholdTokens: -1 # explicit token override; -1 = autoSet autoContinue: false for headless or scripted runs where you want compaction to happen quietly and stop. Set strategy: handoff to start a new session with a handoff document at threshold time instead of writing a compaction entry on the current branch. Set enabled: false to disable the automatic paths entirely; manual /compact still works.