Skip to content

feat(compression): prune oversized tool results in place before summarization - #85479

Draft
pablo-afterlife wants to merge 1 commit into
NousResearch:mainfrom
pablo-afterlife:pr/tool-result-pruner
Draft

feat(compression): prune oversized tool results in place before summarization#85479
pablo-afterlife wants to merge 1 commit into
NousResearch:mainfrom
pablo-afterlife:pr/tool-result-pruner

Conversation

@pablo-afterlife

@pablo-afterlife pablo-afterlife commented Aug 13, 2026

Copy link
Copy Markdown

Summary

Prunes oversized tool results in their own message node — same position, same role, same tool_call_id — down to head + marker + tail, as a no-LLM pre-pass that runs BEFORE the summarization region is selected. Shrinking oversized tool bodies often makes the transcript fit the tail budget, skipping the summarizer entirely.

Root cause: giant tool outputs (web extraction, terminal dumps) inflate the persisted transcript and force LLM summarization, which invalidates the cached prefix. In-place pruning is the most cache-friendly compaction form: the message count, roles, and call IDs never change — only one node's text shrinks.

Changes

  • agent/context_compressor.py: PRUNE_MARKER (pinned verbatim, also doubles as immunity marker for the demote pass), pure prune_tool_result_content (code-point safe; supports str and multimodal list bodies, pruning only text parts), resolve_tool_result_prune_config (unsatisfiable budget disables the feature), _tool_prune_boundary shared by both passes, integration before region selection
  • agent/agent_init.py: config wiring
  • hermes_cli/config_defaults.py: compression.tool_result_prune defaults — enabled: false (opt-in), threshold_chars: 8192, head_chars: 4096, tail_chars: 1024
  • tests/agent/test_tool_result_prune.py (new): unit coverage of the pure function (threshold, head/tail, marker, unicode, list content, idempotence), config resolution, node-identity/persistence/rollback, and integration before region selection with the feasibility-skip path avoiding the LLM call

Validation

Teste Resultado
pytest tests/agent/test_tool_result_prune.py tests/agent/test_context_compressor.py 164 passed (incl. 136 existing compressor tests)
Default behavior disabled (enabled: false) — conservative, opt-in

…rization

Add compression.tool_result_prune (opt-in, default off): oversized tool
results (role=tool, content > threshold_chars) are pruned in their OWN
message node — same position, same role, same tool_call_id — down to
head_chars + marker + tail_chars, as a no-LLM pre-pass that runs BEFORE
the summarization region is selected in the in-loop compression. Shrinking
oversized tool bodies often makes the transcript fit the tail budget,
skipping the summarizer entirely; the commit rewrites the persisted
history through the same archive_and_compact mechanism as in-place
compaction, so the reclaimed state is durable even when no summarization
follows.

Marker is a standalone line between blank lines:
'[... tool result middle pruned ...]' — pinned verbatim; it also doubles
as the immunity marker that keeps the deterministic demote pass from
re-replacing an already-pruned result.

Conservative by design: enabled defaults to false; an unsatisfiable
budget (head + marker + tail > threshold) disables the feature; string
bodies are sliced by Unicode code point; list bodies prune only text
parts, preserving non-text parts and order; tail protection mirrors the
region selection (recent tool output stays verbatim); a bound session
store without archive_and_compact (or a failed commit) makes the prune a
no-op so the in-memory transcript never drifts from the DB.

Ports the pattern from the deepseek-harness compaction tool-result
pruner. Tests: unit coverage of the pure prune function (threshold,
head/tail, marker, unicode, list content, idempotence), config
resolution, node-identity/persistence/rollback of the prune method, and
integration of the prune running before region selection and the
summarizer (with the feasibility-skip path avoiding the LLM call).
@alt-glitch alt-glitch added type/feature New feature or request comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/cli CLI entry point, hermes_cli/, setup wizard area/compression Context compression and continuation sessions P3 Low — cosmetic, nice to have sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades labels Aug 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/compression Context compression and continuation sessions comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/cli CLI entry point, hermes_cli/, setup wizard P3 Low — cosmetic, nice to have sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants