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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions