Skip to content

Fix auto compression for tool-heavy sessions - #36626

Closed
franksong2702 wants to merge 1 commit into
NousResearch:mainfrom
franksong2702:franksong2702/fix-auto-compression-tool-heavy-streams
Closed

Fix auto compression for tool-heavy sessions#36626
franksong2702 wants to merge 1 commit into
NousResearch:mainfrom
franksong2702:franksong2702/fix-auto-compression-tool-heavy-streams

Conversation

@franksong2702

Copy link
Copy Markdown

Summary

Long single-turn, tool-heavy sessions could repeatedly auto-compress without materially reducing context. Completed tool results in the protected tail could remain large, internal context-compaction markers could be treated like real user anchors, and repeated no-op compression could continue until the provider rejected the oversized context.

This PR makes auto compression fail explicitly when it is exhausted and demotes completed tool results to concise evidence summaries, including completed tool results at the current tail before the next LLM call.

Changes

  • Demotes completed tool result bodies to concise evidence summaries even when they sit in the current protected tail.
  • Keeps provider-legal assistant/tool pairing while replacing only completed raw tool bodies.
  • Skips context-compaction reference markers when finding the latest real user tail anchor.
  • Tracks repeated ineffective compression attempts and marks them as compression_exhausted.
  • Returns an explicit failed/partial/compression_exhausted result during preflight when compression leaves messages/tokens effectively unchanged.
  • Adds regression tests for tool-heavy tail summarization, marker-anchor handling, ineffective compression exhaustion, and preflight no-op exhaustion.

Verification

  • python -m pytest tests/test_auto_compression_tool_heavy_tail.py tests/run_agent/test_1630_context_overflow_loop.py tests/run_agent/test_compression_trigger_excludes_reasoning.py tests/test_ctx_halving_fix.py tests/run_agent/test_compression_persistence.py tests/run_agent/test_compressor_fallback_update.py tests/run_agent/test_compression_boundary.py -q
  • git diff --check

Related

Risks / Follow-ups

  • The branch is currently behind upstream main by one commit; no rebase was performed before publishing to avoid changing the already-validated branch state.
  • Tool result summarization is intentionally limited to completed role=tool messages; running tools have no result row to summarize.

Model Used

AI-assisted implementation with OpenAI GPT-5 Codex in a local coding workflow. The assistant inspected repository code, wrote regression tests, implemented the fix, and ran the verification commands above.

@alt-glitch alt-glitch added type/bug Something isn't working comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint P1 High — major feature broken, no workaround labels Jun 1, 2026
@teknium1 teknium1 added sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state sweeper:risk-caching Sweeper risk: may break/degrade prompt caching or cache-key stability (invariant) sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-broad Sweeper blast radius: broad — a core path most sessions hit labels Jun 21, 2026
teknium1 pushed a commit that referenced this pull request Jul 1, 2026
A context-compaction handoff banner is inserted with role="user" when the
protected head ends in an assistant/tool message. On a resumed or
multi-compaction session, _find_last_user_message_idx would return that
banner as the latest user turn, so _ensure_last_user_message_in_tail anchored
the tail to the summary and rolled the genuine last user message into the
next compaction — the exact active-task loss the anchor exists to prevent
(#10896/#22523).

Reuse the existing _is_context_summary_content helper to skip summary banners
when locating the last real user message.

Salvaged from #36626 by Frank Song (issue #36624). The PR's other two changes
(demoting completed tool results inside the protected tail; a preflight
compression_exhausted result) are superseded on current main by the min_tail
floor (#39170), the no-op compression counting (#40803), and the existing
413/disabled terminal-error paths.
@teknium1

teknium1 commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Merged via #56165#56165 (commit ee710db13, your authorship preserved via rebase).

Salvaged the core fix from this PR: _find_last_user_message_idx now skips context-summary handoff banners (via the existing _is_context_summary_content helper), so _ensure_last_user_message_in_tail no longer anchors the tail to a role="user" summary and rolls the real user turn into the next compaction. Nice catch on the active-task-loss path — verified live on current main.

The PR's other two changes were dropped as superseded by work that landed after you opened this:

Thanks for the fix and the clear repro in #36624!

@teknium1 teknium1 closed this Jul 1, 2026
waefrebeorn pushed a commit to waefrebeorn/slermes that referenced this pull request Jul 2, 2026
A context-compaction handoff banner is inserted with role="user" when the
protected head ends in an assistant/tool message. On a resumed or
multi-compaction session, _find_last_user_message_idx would return that
banner as the latest user turn, so _ensure_last_user_message_in_tail anchored
the tail to the summary and rolled the genuine last user message into the
next compaction — the exact active-task loss the anchor exists to prevent
(NousResearch#10896/NousResearch#22523).

Reuse the existing _is_context_summary_content helper to skip summary banners
when locating the last real user message.

Salvaged from NousResearch#36626 by Frank Song (issue NousResearch#36624). The PR's other two changes
(demoting completed tool results inside the protected tail; a preflight
compression_exhausted result) are superseded on current main by the min_tail
floor (NousResearch#39170), the no-op compression counting (NousResearch#40803), and the existing
413/disabled terminal-error paths.
Jasper6439 pushed a commit to Jasper6439/hermes-agent that referenced this pull request Jul 5, 2026
A context-compaction handoff banner is inserted with role="user" when the
protected head ends in an assistant/tool message. On a resumed or
multi-compaction session, _find_last_user_message_idx would return that
banner as the latest user turn, so _ensure_last_user_message_in_tail anchored
the tail to the summary and rolled the genuine last user message into the
next compaction — the exact active-task loss the anchor exists to prevent
(NousResearch#10896/NousResearch#22523).

Reuse the existing _is_context_summary_content helper to skip summary banners
when locating the last real user message.

Salvaged from NousResearch#36626 by Frank Song (issue NousResearch#36624). The PR's other two changes
(demoting completed tool results inside the protected tail; a preflight
compression_exhausted result) are superseded on current main by the min_tail
floor (NousResearch#39170), the no-op compression counting (NousResearch#40803), and the existing
413/disabled terminal-error paths.
habarmc1223-sudo pushed a commit to habarmc1223-sudo/hermes-agent-fluxmem that referenced this pull request Jul 8, 2026
A context-compaction handoff banner is inserted with role="user" when the
protected head ends in an assistant/tool message. On a resumed or
multi-compaction session, _find_last_user_message_idx would return that
banner as the latest user turn, so _ensure_last_user_message_in_tail anchored
the tail to the summary and rolled the genuine last user message into the
next compaction — the exact active-task loss the anchor exists to prevent
(NousResearch#10896/NousResearch#22523).

Reuse the existing _is_context_summary_content helper to skip summary banners
when locating the last real user message.

Salvaged from NousResearch#36626 by Frank Song (issue NousResearch#36624). The PR's other two changes
(demoting completed tool results inside the protected tail; a preflight
compression_exhausted result) are superseded on current main by the min_tail
floor (NousResearch#39170), the no-op compression counting (NousResearch#40803), and the existing
413/disabled terminal-error paths.
santhreal pushed a commit to santhreal/hermes-agent that referenced this pull request Jul 13, 2026
A context-compaction handoff banner is inserted with role="user" when the
protected head ends in an assistant/tool message. On a resumed or
multi-compaction session, _find_last_user_message_idx would return that
banner as the latest user turn, so _ensure_last_user_message_in_tail anchored
the tail to the summary and rolled the genuine last user message into the
next compaction — the exact active-task loss the anchor exists to prevent
(NousResearch#10896/NousResearch#22523).

Reuse the existing _is_context_summary_content helper to skip summary banners
when locating the last real user message.

Salvaged from NousResearch#36626 by Frank Song (issue NousResearch#36624). The PR's other two changes
(demoting completed tool results inside the protected tail; a preflight
compression_exhausted result) are superseded on current main by the min_tail
floor (NousResearch#39170), the no-op compression counting (NousResearch#40803), and the existing
413/disabled terminal-error paths.
Gravezzz pushed a commit to Gravezzz/hermes-agent that referenced this pull request Jul 21, 2026
A context-compaction handoff banner is inserted with role="user" when the
protected head ends in an assistant/tool message. On a resumed or
multi-compaction session, _find_last_user_message_idx would return that
banner as the latest user turn, so _ensure_last_user_message_in_tail anchored
the tail to the summary and rolled the genuine last user message into the
next compaction — the exact active-task loss the anchor exists to prevent
(NousResearch#10896/NousResearch#22523).

Reuse the existing _is_context_summary_content helper to skip summary banners
when locating the last real user message.

Salvaged from NousResearch#36626 by Frank Song (issue NousResearch#36624). The PR's other two changes
(demoting completed tool results inside the protected tail; a preflight
compression_exhausted result) are superseded on current main by the min_tail
floor (NousResearch#39170), the no-op compression counting (NousResearch#40803), and the existing
413/disabled terminal-error paths.
waym0reom3ga pushed a commit to waym0reom3ga/autolycus-agent that referenced this pull request Jul 23, 2026
A context-compaction handoff banner is inserted with role="user" when the
protected head ends in an assistant/tool message. On a resumed or
multi-compaction session, _find_last_user_message_idx would return that
banner as the latest user turn, so _ensure_last_user_message_in_tail anchored
the tail to the summary and rolled the genuine last user message into the
next compaction — the exact active-task loss the anchor exists to prevent
(NousResearch#10896/NousResearch#22523).

Reuse the existing _is_context_summary_content helper to skip summary banners
when locating the last real user message.

Salvaged from NousResearch#36626 by Frank Song (issue NousResearch#36624). The PR's other two changes
(demoting completed tool results inside the protected tail; a preflight
compression_exhausted result) are superseded on current main by the min_tail
floor (NousResearch#39170), the no-op compression counting (NousResearch#40803), and the existing
413/disabled terminal-error paths.
leewenjie pushed a commit to leewenjie/hermes-agent that referenced this pull request Aug 7, 2026
A context-compaction handoff banner is inserted with role="user" when the
protected head ends in an assistant/tool message. On a resumed or
multi-compaction session, _find_last_user_message_idx would return that
banner as the latest user turn, so _ensure_last_user_message_in_tail anchored
the tail to the summary and rolled the genuine last user message into the
next compaction — the exact active-task loss the anchor exists to prevent
(NousResearch#10896/NousResearch#22523).

Reuse the existing _is_context_summary_content helper to skip summary banners
when locating the last real user message.

Salvaged from NousResearch#36626 by Frank Song (issue NousResearch#36624). The PR's other two changes
(demoting completed tool results inside the protected tail; a preflight
compression_exhausted result) are superseded on current main by the min_tail
floor (NousResearch#39170), the no-op compression counting (NousResearch#40803), and the existing
413/disabled terminal-error paths.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint P1 High — major feature broken, no workaround sweeper:blast-broad Sweeper blast radius: broad — a core path most sessions hit sweeper:risk-caching Sweeper risk: may break/degrade prompt caching or cache-key stability (invariant) 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/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants