Skip to content

fix(compressor): count tool_call envelope in tail-budget token estimate (#23767, #28053) - #50751

Merged
kshitijk4poor merged 2 commits into
mainfrom
salvage/toolcall-envelope-budget
Jun 22, 2026
Merged

fix(compressor): count tool_call envelope in tail-budget token estimate (#23767, #28053)#50751
kshitijk4poor merged 2 commits into
mainfrom
salvage/toolcall-envelope-budget

Conversation

@kshitijk4poor

Copy link
Copy Markdown
Collaborator

Summary

The compression tail-protection budget walks estimated each message's tokens from content + function.arguments only — dropping the rest of every tool_call envelope (id, type, function.name, JSON structure). For assistant turns that fan out into parallel tool calls (Hermes's normal case) this undercounted by 2-15×, so the protected tail overshot tail_token_budget and compression ran well below its intended ratio — context kept growing across turns. (Mode A of #23767; fixes #28053.)

Salvage of #43293 by @basilalshukaili, cherry-picked onto current main (authorship preserved) + AUTHOR_MAP follow-up.

Changes

  • agent/context_compressor.py (contributor): new _estimate_msg_budget_tokens(msg) helper counting the full tool_call envelope (len(str(tc))), consolidating the same walk that was duplicated in 3 places — _prune_old_tool_results and the two passes in _find_tail_cut_by_tokens. The three walks can no longer drift apart.
  • tests/agent/test_compressor_tool_call_budget.py (contributor): 5 regression tests.
  • scripts/release.py (maintainer): map the contributor's gmail.com committer email for the attribution check.

Plain-content and image handling are unchanged; only the local pre-compression tail estimate changes. Does not touch the prompt-cache path or alter past context.

Sibling-site audit

The 3 budget walks are the only arguments-only token estimators; the remaining function.arguments reads in the file are legitimate non-budget uses (_truncate_tool_call_args_json, redaction, call-id mapping) — correctly left unchanged.

Validation

Result
tests/agent/test_compressor_tool_call_budget.py 5 passed
tests/agent/test_context_compressor.py + image tokens 124 passed
ruff (diff vs main) clean
E2E (real imports) a 4-tool-call turn: 18 → 150 tokens (8.3×, within the issue's 2-15× range); plain messages unchanged

Part of #23767 (does not close it — modes B/F still pending).

Closes #43293.

Co-authored-by: Basil Al Shukaili basilalshukaili@gmail.com

Infographic

Image generation is unavailable in this environment (FAL_KEY unset, no managed-provider credits); to be attached once available.

basilalshukaili and others added 2 commits June 22, 2026 16:17
…te (#28053)

The tail-protection budget walks estimated an assistant message's tokens from content + function.arguments only, dropping each tool_call's id, type and function.name (plus JSON structure). Assistant turns that fan out into parallel tool calls were undercounted by 2-15x (a 4-tool-call turn measures ~73 vs ~1,090 real tokens), so the protected tail overshot tail_token_budget and compression ran far below its intended ratio — context kept growing.

Consolidate the three duplicated budget walks (_prune_old_tool_results and the two passes in _find_tail_cut_by_tokens) into a single _estimate_msg_budget_tokens() helper that counts the full tool_call envelope via len(str(tc)), consistent with how _estimate_message_chars estimates message size elsewhere.

Tested on Windows: new tests/agent/test_compressor_tool_call_budget.py plus the existing compression suite (test_context_compressor, compressor_image_tokens, cross_session_guard, infinite_compaction_loop) — 209 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Committer email for the salvaged #43293 commit; required by the contributor
attribution check.
@github-actions

Copy link
Copy Markdown
Contributor

🔎 Lint report: salvage/toolcall-envelope-budget vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 11351 on HEAD, 11350 on base (🆕 +1)

🆕 New issues (1):

Rule Count
unresolved-import 1
First entries
tests/agent/test_compressor_tool_call_budget.py:13: [unresolved-import] unresolved-import: Cannot resolve imported module `pytest`

✅ Fixed issues: none

Unchanged: 5966 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint labels Jun 22, 2026
@kshitijk4poor
kshitijk4poor enabled auto-merge (rebase) June 22, 2026 10:55
@kshitijk4poor
kshitijk4poor merged commit b4cb33c into main Jun 22, 2026
34 checks passed
@kshitijk4poor
kshitijk4poor deleted the salvage/toolcall-envelope-budget branch June 22, 2026 10:56
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 P2 Medium — degraded but workaround exists type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: _find_tail_cut_by_tokens underestimates assistant message tokens by 2-15x — tail protection overshoots and compression becomes ineffective

3 participants