Skip to content

Context pruning skips image-containing tool results, causing unrecoverable context overflow in screenshot-heavy sessions #41789

@FoundDream

Description

@FoundDream

Bug Description

pruneContextMessages() in src/agents/pi-extensions/context-pruning/pruner.ts explicitly skips any toolResult message that contains image blocks:

if (hasImageBlocks(msg.content)) {
  continue; // line ~248
}

This means tool results with images (e.g. browser screenshots, read tool reading image files) can never be pruned, even when the context window is full. The comment says "for now" but there is no fallback or tracking issue.

Meanwhile, pruneProcessedHistoryImages() in src/agents/pi-embedded-runner/run/history-image-prune.ts only processes role === "user" messages — it does not touch toolResult images either.

Both pruning mechanisms ignore tool result images, creating a gap where screenshot-heavy sessions accumulate unbounded image data with no recovery path.

Impact

This is particularly severe for browser automation workflows — one of OpenClaw's core use cases. Each browser action can produce a screenshot as a toolResult. In a typical debugging session:

  • 20 browser actions → 20 screenshot tool results
  • Each image ~1200+ tokens (actual base64 data far larger)
  • pruneContextMessages cannot reclaim any of this space
  • Context window fills → session becomes unusable

Unlike user-uploaded images (#19099) or vision-model loops (#29290), this scenario has no workaround — the context pruner is supposed to be the safety net, but it refuses to touch the largest consumers of context space.

Reproduction

  1. Start a session with browser automation enabled
  2. Perform 15-20+ browser actions that produce screenshots
  3. Observe context usage growing monotonically
  4. Context pruning triggers but fails to free meaningful space (images skipped)
  5. Eventually: context overflow or severely degraded performance

Expected Behavior

pruneContextMessages() should be able to prune image-containing tool results, at minimum by replacing image blocks with a text placeholder like [screenshot removed during context pruning] while preserving any accompanying text content.

Suggested Fix

In softTrimToolResultMessage() and the hard-clear phase of pruneContextMessages(), instead of skipping image tool results entirely, replace image blocks with text placeholders:

// Instead of:
if (hasImageBlocks(msg.content)) {
  continue;
}

// Consider:
if (hasImageBlocks(msg.content)) {
  // Replace image blocks with placeholder, keep text blocks
  const prunedContent = msg.content.map(block =>
    block.type === 'image'
      ? asText('[image removed during context pruning]')
      : block
  );
  // ... proceed with pruned content
}

This preserves the message structure and any text descriptions while reclaiming the image data.

Related Issues

Environment

  • OpenClaw: latest main branch
  • Affected files:
    • src/agents/pi-extensions/context-pruning/pruner.ts (skips image tool results)
    • src/agents/pi-embedded-runner/run/history-image-prune.ts (only handles user messages)

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