Skip to content

Auto-compaction not triggered during tool-use loops, leading to unrecoverable context overflow #24800

@sunan74385809-ship-it

Description

@sunan74385809-ship-it

Bug Description

When an agent enters a long tool-use loop (many consecutive tool calls without user messages), the context grows steadily but auto-compaction never triggers. The session eventually hits the model's context window limit and becomes permanently stuck with "Context window is full" errors.

Steps to Reproduce

  1. Configure compaction.mode: "safeguard" with reserveTokensFloor: 45000 and a model with contextWindow: 200000
  2. Start a session where the agent performs many consecutive tool calls (e.g., build/deploy workflow with 15+ exec calls)
  3. Observe context growing: 188k → 190k → 194k → 196k → 199k → 200k
  4. At 200k, API returns 400 Context window is full
  5. Auto-compaction attempts to run but also fails because the context is already too full to generate a summary

Expected Behavior

Compaction should trigger proactively when context approaches the limit (e.g., at contextWindow - reserveTokensFloor = 155k), not only reactively after the API returns a context overflow error.

Actual Behavior

  • run.ts only checks for context overflow after the API call fails (line ~528: if (contextOverflowError))
  • During tool-use loops, there is no pre-prompt context size check
  • By the time overflow is detected, the context is already at 100% capacity
  • The compaction attempt itself needs API calls, which also fail due to full context
  • Session becomes permanently stuck — Compactions: 0 despite 200k+ context
  • Only recovery is /new or /reset

Analysis

Looking at the source code:

  • run.ts: Auto-compaction is only triggered in the contextOverflowError handler (reactive, not proactive)
  • compaction-safeguard.ts: Only handles session_before_compact event — it improves compaction quality but doesn't control when compaction triggers
  • reserveTokensFloor: 45000: This setting exists but doesn't appear to trigger proactive compaction during tool loops

The reserveTokensFloor should ideally trigger compaction when currentContextTokens > contextWindow - reserveTokensFloor, but this check doesn't happen between tool-call iterations in the run loop.

Session Data (anonymized)

Last 5 successful API calls before crash:
  input=196,804 tokens (tool call)
  input=197,281 tokens (tool call)  
  input=198,216 tokens (tool call)
  input=199,735 tokens (tool call)
  input=199,960 tokens (tool call) ← last successful
  input=0 (error: "Context window is full")
  
Session stats: Compactions: 0, Context: 200k/200k (100%)

Suggested Fix

Add a proactive context check in the tool-use loop in run.ts, something like:

// Before each tool-call iteration, check if context is approaching the limit
const currentTokens = attempt.usage?.input ?? 0;
const compactionThreshold = ctxInfo.tokens - reserveTokensFloor;
if (currentTokens > compactionThreshold && !proactiveCompactionAttempted) {
  proactiveCompactionAttempted = true;
  log.warn(`Proactive compaction: ${currentTokens}/${ctxInfo.tokens} tokens used`);
  await compactEmbeddedPiSessionDirect({...});
}

Environment

  • OpenClaw version: 2026.2.13
  • Model: Claude Opus 4.6 (contextWindow: 200000)
  • Compaction config: { mode: "safeguard", reserveTokensFloor: 45000 }
  • Context pruning: { mode: "cache-ttl", ttl: "24h" }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions