From fca883f06f63583b728b2db43c8d842d84542311 Mon Sep 17 00:00:00 2001 From: Dom Bejar Date: Mon, 13 Jul 2026 16:37:01 +0000 Subject: [PATCH] fix(compaction): cap post-tool attempts per turn --- agent/conversation_loop.py | 7 ++++- .../test_post_tool_compression_attempt_cap.py | 30 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 tests/run_agent/test_post_tool_compression_attempt_cap.py diff --git a/agent/conversation_loop.py b/agent/conversation_loop.py index a27c084ee77d..0cc8c03ad923 100644 --- a/agent/conversation_loop.py +++ b/agent/conversation_loop.py @@ -5177,7 +5177,12 @@ def run_conversation( messages, tools=agent.tools or None ) - if agent.compression_enabled and _compressor.should_compress(_real_tokens): + if ( + agent.compression_enabled + and compression_attempts < 3 + and _compressor.should_compress(_real_tokens) + ): + compression_attempts += 1 agent._safe_print(" ⟳ compacting context…") messages, active_system_prompt = agent._compress_context( messages, system_message, diff --git a/tests/run_agent/test_post_tool_compression_attempt_cap.py b/tests/run_agent/test_post_tool_compression_attempt_cap.py new file mode 100644 index 000000000000..5d3a9b69e533 --- /dev/null +++ b/tests/run_agent/test_post_tool_compression_attempt_cap.py @@ -0,0 +1,30 @@ +"""Regression guard for the post-tool automatic-compression attempt cap. + +The pre-API and overflow compression paths share ``compression_attempts`` as a +three-pass per-turn backstop. The post-tool path must use the same counter; +otherwise a long tool loop can compact after every tool response for the +lifetime of the turn. +""" +from __future__ import annotations + +import inspect + + +def _post_tool_compression_block() -> str: + from agent import conversation_loop + + source = inspect.getsource(conversation_loop.run_conversation) + start = source.index("# Use real token counts from the API response") + end = source.index("# Save session log incrementally", start) + return source[start:end] + + +def test_post_tool_compression_uses_shared_per_turn_attempt_cap(): + block = _post_tool_compression_block() + + assert "compression_attempts < 3" in block, ( + "post-tool compression must stop after the shared three attempts per turn" + ) + assert "compression_attempts += 1" in block, ( + "post-tool compression must consume one shared per-turn attempt" + )