Repository navigation
fix(agent-team): let gate ② track the configurable gate ① for bash / run_python_code - #66
Merged
zhanghanduo merged 1 commit intoOct 13, 2026
Conversation
bash and run_python_code overflow to disk at gate ①, whose cap is TOOL_EXEC_RESULT_MAX_CHARS (8K by default, and the knob the tool-result-truncation A/B actually turns). Their gate ② budgets were hardcoded here at 4K/5K, below gate ①'s own preview, so: * run_python_code lost both the spill path and the exit status on every overflowing result -- at the default cap already, not only when it is raised; * raising the cap gave an agent_team deployment nothing, because gate ② cut the extra room straight back off. The React processor in workflows.stateful_react_agent._runtime already tracks it (_CONFIGURED_EXEC_TOOLS + 2K footer headroom); this wires the same rule in here, which is what the neighbouring grep/glob 10K entries and their comment already argue for. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
D41910
added a commit
to D41910/D41910
that referenced
this pull request
Oct 11, 2026
zhanghanduo
approved these changes
Oct 13, 2026
zhanghanduo
left a comment
Collaborator
There was a problem hiding this comment.
LGTM. Thanks for the fix.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes a gate ① / gate ② budget drift in the agent_team tool-result post-processor.
bashandrun_python_codeoverflow to disk at gate ①, whose cap ismeta.max_result_chars=TOOL_EXEC_RESULT_MAX_CHARS(8K by default, and theknob
docs/tool-result-truncation-ab.mdactually turns between 8000 and 50000).The preview that comes back carries two things at its tail: the
saved read-only at <path>pointer and the verdict (exit status, the pytestsummary line).
SwarmToolResultPostProcessorgave those two tools hardcoded gate ② budgetsof 4K and 5K — below gate ①'s own preview:
Two consequences, both reproduced against the real code path:
1. At the default 8K cap,
run_python_codealready loses both. A 137,967-charresult overflows to a 7,930-char preview naming the spill file; gate ② then cuts
it to 5,116 chars and the pointer and the verdict are gone.
bashsurvivesonly by accident —
_compact_bashhappens to keep the tail.2. Raising the cap buys an agent_team deployment nothing. At 50K, gate ①
returns a 49,933-char preview and gate ② hands the model 4,037 (bash) or 5,116
(run_python_code). The knob only widens the window between two caps.
Why this is an omission, not a decision
ReactToolResultPostProcessorinworkflows/stateful_react_agent/_runtime.pyalready carries the rule, with the reasoning written down:
Three further signs in this file that the two tools were expected to follow the
config, not a literal:
grep_search/glob_searchentries right above were raised to 10K forexactly this reason ("Gate ① overflows these to disk at meta.max_result_chars=8K
and puts the 'saved to , use read_file' pointer at the TAIL … 10K leaves
the 8K body and its footer room to both survive — the value react has carried
for this reason all along");
test_site3_keeps_the_self_pagination_pointeris parametrised over bothprocessors precisely so "a future divergence fails here instead of in a
benchmark trajectory" — but its tool list covers only
read_file,grep_search,glob_search;_compact_bash's docstring already warns that the split "silently degrades to'treat the whole blob as stdout'" if the producers change — this budget is the
other half of that same contract.
So the two processors disagree on exactly the tools whose gate ① is configurable.
The fix
Wire in the same rule the React processor uses — one import, two constants, one
branch:
The
_ELLIPSISwording, the stderr split and the 3K stderr keep window are allleft alone.
Tests
Added to the existing
tests/test_tool_result_truncation.py(no new file),parametrised over both processors via the file's existing
_processors()helper — 4 new cases per processor:
test_the_exec_pointer_survives_the_default_gate_1— a gate-①-sized overflowmust keep both the spill path and the verdict at the default cap.
test_gate_2_follows_a_raised_exec_cap— with the cap at 50K, a 40K body mustcome through uncut, i.e. raising the knob actually widens gate ②.
Validity check — reverting only
subagent_runtime.pyand keeping the newtests fails exactly 3:
Every failure is the
agent_teamparameter. Thestateful_reactparameters passboth before and after — that is the shape of an omission, not a redesign.
Differential fuzz, 2016 cases (12 tools × 4 body shapes × 21 sizes ×
error flag), same probe before and after via
git stash:web_fetch / web_search / collect_reports / delegate_subtask / submit_report /
unknown / empty-name: 0 changes);
is_error=Truecase changed — errors still bypass every cap;Verification
pytest tests/test_tool_result_truncation.pypytest tests/(full, 3896 collected)ruff check(CI's lint gate)pyrightThe single full-suite failure is
tests/test_network_tools.py::test_redirect_hops_are_validated_not_followed_blindly— this sandbox resolves
www.iana.orgto198.18.0.44, so the URL guard refusesit. It fails identically on unmodified
main(git stash→ same 1 failed,17 passed in that file), so it is not from this change.
ruff format --checkreports 2 files needing reformatting, also identically onunmodified
main(this machine's ruff is newer than the repo's pin; the hunksare at
subagent_runtime.py:1357, untouched here). CI's lint gate isruff check, which is clean.Not addressed here
_compact_bashcomputesstdout_budget = max(500, budget - len(stderr_keep) - overhead),so a very large stderr can drive the stdout slice to the 500-char floor and elide
most of it even when the overall budget is generous. That is a separate question
from whether gate ② tracks gate ①, it behaves identically in both processors,
and changing it would alter output shape for the currently-working
bashpath —so I left it alone rather than fold it in.
🤖 Prepared with Claude Code (Claude Opus 4.8, 1M context). Happy to split this
out or reword anything.