In-Session Context Compaction or Isolated Subagent Threads for Long-Running Coding Agents

Back to blog
Mehran Mozaffari·

The Context Wall and the Two Architectures for Long-Horizon Work

When an autonomous coding agent runs for more than a handful of turns, token exhaustion shifts from an abstract constraint to an operational wall. Every repository search, multi-file inspection, and compiler trace inflates the prompt. Left unchecked, the session either crashes against the provider's token limit or degrades into an expensive crawl. When building or configuring agent harnesses, I see two distinct architectural paradigms to handle this pressure: destructive in-place history compaction, and external thread isolation.

In-place compaction modifies the active prompt. The harness identifies older conversational turns, condenses them into a summary block, drops raw tool traces, and preserves a small tail of recent exchanges. We see variations of this pattern across Claude Code, DeepSeek Harness, Goose, Kimi CLI, Google Antigravity, Pi, oh-my-pi, OpenCode, Gemini CLI, and Cursor. The alternative approach decouples execution across discrete agent contexts, using subagents or external reference threads. Systems like Amp, for instance, offer thread references so agents can read and extract context across separate boundaries without carrying the full prompt history forward. As I argued in The Codebase Is an Environment, Not a Context Window, offloading state into external storage or auxiliary processes protects the core interaction loop from terminal bloat.

The practitioner trade-off comes down to choosing your operational debt: paying the prompt rewrite penalty of in-session summarization versus paying the orchestration overhead of fresh thread dispatch. In-place compaction keeps the model anchored in a single continuous session, but rewriting conversation history inevitably discards fine-grained diagnostic details and resets prompt cache prefixes. Dispatching isolated threads keeps contexts lean and cache-friendly, but requires orchestrating state handoffs across disjoint boundaries.

Painted explainer, 120 seconds

In the video walkthrough above, observe how the context window progressively saturates across iterative tool executions until token counts cross the configured compaction boundary. Take note of how the harness synthesizes older events into a single checkpoint block while leaving the immediate conversational tail intact.

How compaction manages context across turns: 1. Session grows, 2. Trigger, 3. Prune optional, 4. Summarise, 5. Keep recent tail, 6. Re-inject state, 7. Rebuild prompt, 8. Continue agent loop
How compaction manages context across turns

In the lifecycle diagram above, follow the progression from turn accumulation through threshold evaluation to prompt reconstruction. Notice how state re-injection occurs immediately after summarization, allowing system instructions and project-level context to be restored before the runtime resumes the agent loop.

Trigger Mechanics and Token Allocation Thresholds Across Harnesses

Every agent harness must decide exactly when to compact and how much recent context to preserve. In practice, implementations diverge between ratio-based tripwires, explicit headroom reservations, and conservative capacity halving.

DeepSeek Harness relies on normalized capacity ratios within its configuration. It defines a default thresholdRatio of 0.8 to initiate compaction when context pressure builds or context-overflow events occur, paired with a default retainRatio of 0.16 to designate what fraction of history remains untouched. By contrast, Pi enforces an absolute margin: it triggers summarization when the total context tokens exceed the window capacity minus a default reserveTokens margin of 16,384 tokens, while preserving a fixed recent window via a default keepRecentTokens setting of 20,000 tokens. Kimi CLI balances its boundary dynamically by checking whether current active tokens plus its reserved context size equal or exceed the maximum window size, while always preserving the latest two user and assistant messages.

Gemini CLI adopts an aggressive schedule: it sets DEFAULT_COMPRESSION_TOKEN_THRESHOLD at 0.5 of the model's total token limit, while utilizing a COMPRESSION_PRESERVE_THRESHOLD configured to retain the final 30% of context. For Claude Code, automatic compaction triggers as the context approaches the window limit, though the exact default percentage threshold is not formally specified; users can adjust this via /autocompact or trigger compaction manually using /compact with optional focus instructions. If an operator needs to disable automated compaction entirely, harnesses like OpenCode expose an explicit escape hatch through the OPENCODE_DISABLE_AUTOCOMPACT environment variable.

Harness Compaction Trigger Parameter Headroom Formula / Trigger Point Default Reserve Margin Preserved Tail Allocation
Claude Code Automatic threshold / /autocompact Approaching context limit; manual /compact Unspecified default threshold Retains recent conversation turns
DeepSeek Harness thresholdRatio (0.8) Usage $\ge$ 80% context window or overflow events Headroom dynamically calculated retainRatio (0.16) retained
Gemini CLI DEFAULT_COMPRESSION_TOKEN_THRESHOLD (0.5) Usage $\ge$ 50% model token limit Headroom managed at 50% capacity COMPRESSION_PRESERVE_THRESHOLD (30%)
Kimi CLI Context plus reserved token threshold Active tokens + reserved size $\ge$ max size Configured reserved context size Latest two user and assistant messages
Pi reserveTokens (16,384) Context tokens > window capacity $-$ reserveTokens 16,384 reserve tokens keepRecentTokens (20,000 tokens)

How context usage fluctuates across cycles: User turns, Context window, Compactor, Messages + tool results accumulate, Usage climbs toward threshold, Threshold / overflow hit, Summarise head, keep recent tail, Usage drops, then climbs again, Second compaction cycle, Repeated cycles compound loss
How context usage fluctuates across cycles

In the timeline visualization above, track the saw-tooth pattern as token consumption climbs toward the trigger threshold, drops sharply as head messages are compressed, and rebounds. Notice how repeated summarization cycles compound detail loss over time, steadily eroding granular historical state.

Pre-Compaction Pruning, Tool Result Elision, and Cache Preservation

Invoking an LLM to generate a natural language summary should never be an agent's first line of defense. Summarization calls consume generation tokens, introduce latency, and permanently alter prompt prefixes. Before resorting to full conversational compression, sophisticated harnesses prune high-volume tool payloads to regain operational headroom.

oh-my-pi establishes a clear hierarchy here, organizing its mitigations into a default sequence: remote, snapcompact, handoff, shake, and soft. Its shake step specifically inspects older turns, eliding verbose tool outputs and oversized code blocks into compact artifact references. To avoid thrashing the session for negligible gains, oh-my-pi enforces an explicit rule: pre-compaction tool pruning requires at least 20,000 tokens of anticipated savings before it will execute.

Gemini CLI applies a similar philosophy by collapsing historical function responses. It preserves the last three tool turns to maintain immediate operational grounding while collapsing earlier outputs, specifically exempting retrieval tools from this collapse. This selective pruning keeps core retrieval data intact while ditching redundant diagnostic noise.

Beyond capacity recovery, there is an economic consideration: prompt caching. In modern API architectures, prefix caching drastically reduces inference costs and time-to-first-token. Whenever an agent compresses history in-place, it rewrites the conversation prefix, instantly invalidating cached tokens for subsequent requests. Compaction calls themselves must also avoid cache pollution. In Pi, summarization requests explicitly enforce cacheRetention set to none, ensuring that one-off summarization prompts do not evict long-lived session prefixes or waste cache allocations on ephemeral distillation tasks.

How agent harnesses handle context pressure: Compaction strategies, Full replace, Summary + retained tail, Structured checkpoint, Provider-native / opaque, Prune / shake first, Retrieval, no summary, Minimal or no tail, Most common harness pattern, Goose / Pi / OMP soft, Codex / OMP remote, OpenCode
How agent harnesses handle context pressure

In the strategy comparison figure above, look at the architectural fork between full-history summarization and layered pruning. Notice how approaches that prune or shake tool results prior to invoking summary models protect the active session from premature semantic compression.

Re-Injection Mechanics, Checkpoint Schemas, and Syntactic Boundary Safety

Once an agent compresses older history, the harness faces an immediate operational hazard: prompt amnesia. If summarization discards system guidelines, loaded skills, or active file buffers, the agent resumes execution in a degraded state. Simultaneously, the harness must preserve strict structural boundaries so the newly condensed history does not violate model API schemas.

DeepSeek Harness handles structural continuity by replacing older conversational spans with a single user-role summary checkpoint while retaining shadowed events in its session log for deterministic replay. Crucially, DeepSeek Harness enforces tool-pairing-balanced cut points across history. In modern tool-calling APIs, every tool execution block generated by an assistant requires a matching tool result block. Slicing context purely on raw token counts risks cutting between an invocation and its output, producing orphaned tool events that trigger immediate API schema validation errors.

To counter amnesia after prompt compression, Claude Code implements an explicit state restoration pipeline. Rather than expecting the model's summary to remember foundational project rules, Claude Code re-injects project-root CLAUDE.md files and unscoped rules directly from disk after compaction. It re-reads up to five recently modified files that were read or edited during the session; to prevent immediate context exhaustion, any re-read file exceeding 5,000 tokens is converted into a concise path reference. Starting in version v2.1.304, Claude Code also re-injects skill descriptions, capping skills at 5,000 tokens per skill and 25,000 tokens in total, dropping the oldest skills first when limits are exceeded. Path-scoped rules and nested CLAUDE.md files are then reloaded on demand whenever matching files are touched later in the run.

Other harnesses structure the summary payload itself through deterministic templating. Goose renders structured compaction summaries via minijinja templates, allowing developers to define explicit checkpoint schemas by overriding templates at ~/.config/goose/prompts/compaction_summary.md. If a model returns an ill-formed summary that fails template parsing, Goose gracefully falls back to raw text. I find this template-driven approach vital: rebuilding the working prompt from disk rather than relying on the summary's memory ensures that deterministic project constraints outlive lossy distillation cycles.

/compact

Testing the Preservation Claim: A Failure Mode and Effects Analysis of In-Place Summarization

The central justification for in-place compaction is that an LLM can condense previous exchanges into natural language without compromising downstream task completion. In practice, treating conversational compression as a lossless cache is wishful thinking. A structured Failure Mode and Effects Analysis reveals several points where in-place summarization breaks down.

Failure Mode Root Cause Mechanism Impact on Agent Trajectory Harness Mitigation
Truncation Loop Summary generation exhausts token limits, terminating with stopReason length. Harness ingests a clipped, unparseable summary or loops infinitely on retry. Pi rejects incomplete summaries that end with stopReason length.
Reasoning Eviction Extended thinking blocks are omitted to recover token headroom. Model loses prior hypotheses and repeats previously rejected logical paths. Kimi CLI explicitly drops thinking parts from the summary message.
Negative Search Loss Natural language summarizers discard failed searches and non-matching paths. Agent repeatedly inspects the same irrelevant directories and dead ends. Requires tool result elision rather than semantic distillation.
Diagnostic Washout Exact stack traces and line numbers get paraphrased into general descriptions. Fine-grained debugging fails; agent hallucinates line edits on stale file offsets. Selective function preservation (e.g., Gemini CLI protecting recent tools).

Truncation loops are particularly destructive: if a summarization call hits output bounds and terminates with stopReason length, accepting that partial distillation corrupts context state. Pi actively guards against this by rejecting incomplete summaries that terminate on length limits. Another structural trade-off occurs around chain-of-thought preservation. While Kimi CLI drops thinking parts from the summary message to aggressively recover space, doing so strips the model's internal scratchpad, blinding subsequent turns to the analytical paths the agent already explored and discarded.

Furthermore, natural language distillation routinely flattens negative results. An agent that spent four turns determining that a library lacks a specific export will see that failure condensed into a vague high-level takeaway, frequently prompting it to re-attempt identical commands later. It must be stated plainly: the research material does not show that in-place compaction maintains multi-turn reasoning fidelity equal to uncompressed context over extended cycles.

Architectural Taxonomy and Empirical Verification Matrix

Mapping the design space across coding agent harnesses reveals four primary architectural responses to context pressure: summarizing and replacing older history, truncating or pruning raw tool outputs, isolating execution into auxiliary subagents, and maintaining exact retrieval structures outside the active prompt.

Approaches for managing long context history: Context pressure response, Summarise and replace, Truncate / prune only, Isolate via sub-agents, Retrieve exact recall, Claude Code / Goose / Kimi / OpenCode, Codex remote / OMP / Anthropic API, DeepSeek retain-tail + pressure, Tool-output prune, Shake /
Approaches for managing long context history

In the taxonomy diagram above, trace the bifurcation between destructive in-place summarization and non-destructive external isolation. Notice how systems like Claude Code, Goose, and Kimi CLI default to in-place summarization, whereas harnesses like oh-my-pi layer tool pruning (shake) ahead of semantic compression. Systems like Amp bypass conversational rewriting altogether by delegating work across independent thread boundaries.

Harness Compaction Trigger Tool Pruning Rules Prompt Cache Handling State Re-injection & Transcript Separation Fallback Policy
Claude Code Approaching context limit; manual /compact Unspecified pre-pruning; converts re-read files $>5,000$ tokens to path refs API supports server-side compact-2026-09-04 beta keeping recent turns Re-injects project-root CLAUDE.md, unscoped rules, up to 5 touched files, and skills (v2.1.304) Wipes context via /clear for clean restarts
DeepSeek Harness thresholdRatio default 0.8 or overflow events; manual /compact Tool-pairing-balanced cut points prevent orphan tool calls Replaces surface span with single user-role checkpoint Retains shadowed events in session log for deterministic replay Replay from underlying session log
Goose Context pressure triggers summarization None specified prior to distillation Summarization via minijinja structured templates Template override at ~/.config/goose/prompts/compaction_summary.md Falls back to lossless raw text if JSON template parsing fails
Kimi CLI Active tokens + reserved size $\ge$ max context; manual /compact Drops thinking blocks from summary messages Context compressed into synthetic summary turn Preserves latest two user and assistant messages None documented
Google Antigravity Automatic threshold crossing Prunes side queries via /btw Tracks summaries in separate checkpoint buffer Checkpoint buffer decoupled from active context; /context panels Session branching via /rewind and /fork
Pi Tokens $>$ window $-$ reserveTokens (16,384) None documented Sets cacheRetention to none during summarization Preserves tail via keepRecentTokens (default 20,000) Rejects summaries terminating with stopReason length
oh-my-pi 6 trigger paths (overflow, idle maintenance, etc.) shake elides tool results/fences into references ($\ge$20k token savings) Execution hierarchy: remote, snapcompact, handoff, shake, soft Full scrollback retained in display transcript while LLM context resets at divider Falls back through compaction sequence
OpenCode Automated threshold trigger None documented Standard conversational replacement In-place summary checkpoint OPENCODE_DISABLE_AUTOCOMPACT disables auto-compaction entirely
Gemini CLI DEFAULT_COMPRESSION_TOKEN_THRESHOLD (0.5) Collapses older functions; preserves last 3 tool turns; exempts retrieval tools Rewrites conversational prefix Preserves last 30% of context via COMPRESSION_PRESERVE_THRESHOLD Falls back to truncation-only after failed compression
Cursor Context window near full None documented Summarized conversation segment distinct from live conversation Separate Summarized conversation breakdown in UI None documented
Amp Thread boundary hand-offs Avoids bloat by isolating tasks in fresh threads Prefix caches remain untouched across distinct thread runs Thread references allow agents to inspect and extract context across threads Manual thread switching

To audit these behaviors in an active deployment, verify token reclamation directly against harness session logs. Codex CLI PR 5959 added configurable compaction prompts. Monitor the API telemetry immediately preceding and following a compaction event to ensure the harness drops prompt volume without entering a degenerate retry loop.

Production Decision Framework: In-Place Compaction, Clean Hand-offs, or Subagent Delegation

Selecting the right context management strategy requires balancing the operational cost of prompt rewrites against the complexity of managing decoupled threads. Monolithic in-place compaction suits tight, stateful workflows, but rapidly degrades under heavy tool activity.

When dealing with high-volume exploratory tasks, external thread isolation proves vastly superior. Google Antigravity provides the /btw command to run side questions entirely outside the primary trajectory, storing distillations in a separate checkpoint buffer so auxiliary investigations do not inflate active context percentages or corrupt active trajectory. Antigravity also exposes explicit session controls via /context panels, /rewind, and /fork to branch or navigate execution paths cleanly. Similarly, Amp avoids the prompt amnesia inherent in natural language summarization by utilizing thread references, enabling an agent to selectively read and extract needed context from peer threads while keeping its local context completely free of extraneous tool traces.

For single-project codebases with compact test outputs, in-place compactors that support deterministic re-injection—like Claude Code restoring CLAUDE.md and touched files from disk, or Goose with minijinja templates—provide a functional workflow. But as soon as repository exploration requires deep diagnostic traces, large build logs, or multi-directory greps, relying on in-session summarizers creates continuous detail loss. In those environments, configure your harness to prune tool payloads before summarizing, or isolate bulk execution into dedicated subagents to keep your primary context lean and cache-intact.

Resources

Updated 2026-11-01 by Mehran Mozaffari.

Related posts