fix(agent): recover tools from truncated scratchpads - #64306
Conversation
|
CI follow-up: the only failing slice is I reproduced both failures on an untouched checkout at this PR's exact base, |
8144cb6 to
bd63dc1
Compare
|
Refreshed onto current The branch rebased without conflicts. Current-head local verification passes 517 tests across the complete run-agent suite and model-validation suite; Ruff, diff check, public identity, overlap review, metadata scan, and gitleaks also pass. Replacement GitHub CI is running on the refreshed head. |
bd63dc1 to
1d08c51
Compare
|
Rebased onto current The production change composed cleanly. The only manual conflict was the test insertion point, where current main added null-tool-argument coverage; the refreshed branch preserves that regression alongside all three incomplete-scratchpad recovery cases. Current-head verification: the complete |
|
CI slice 8 is currently red on I reproduced the same result in an untouched The focused test-only corrections are #64836 and #64844; both are green. I am keeping this PR scoped to the scratchpad recovery fix and will rebase/revalidate once that base correction lands. |
1d08c51 to
f2dcf69
Compare
|
Refreshed onto current New head: Validation:
The branch is current-main-based, ready for review, and GitHub reports it mergeable. |
|
Thanks for the focused recovery fix. Current main unconditionally retries incomplete scratchpads at Automated hermes-sweeper review. |
SummaryOne PR, #64306, addresses issue #11153 by changing incomplete-scratchpad handling so independently structured tool calls survive truncation while text-only truncation retains the bounded retry and partial-failure behavior. Related pull requests
Suggested consolidationKeep #64306 open with a salvage path, consistent with the automated keep-open review: preserve its narrowly scoped structured-call recovery and three regression tests, with author action to rebase onto main if needed. No competing PR or duplicate is present in this complex. Complex graphflowchart LR
classDef open fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
classDef merged fill:#dcfce7,stroke:#15803d,color:#14532d
classDef closed fill:#e5e7eb,stroke:#6b7280,color:#1f2937
classDef unverified fill:#f3f4f6,stroke:#9ca3af,color:#374151
classDef best stroke-width:3px,stroke:#b45309
classDef target stroke-width:3px,stroke:#4338ca
I11153(["issue #11153 (open)"])
P64306["PR #64306 (open)"]
P64306 -->|best fix| I11153
class I11153 open
class P64306 open
class P64306 best
class P64306 target
click I11153 "https://github.com/NousResearch/hermes-agent/issues/11153"
click P64306 "https://github.com/NousResearch/hermes-agent/pull/64306"
Graph: solid arrow = fixes / best fix, dashed arrow = partial or unverified (see edge label); boxed group = PRs duplicating each other; amber border = best fix; indigo border = target; gray node = closed (state tag in the node label). Cross-PR triage: Reviewed 1 pull request and 1 issue in this complex. Each diff was read against this issue; Assessment working set: 8 kB of PR diffs, 5 kB of issue/PR text, 3 kB of discussion (6 comments), 2 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch. |
Summary
<REASONING_SCRATCHPAD>text is truncatedRoot cause
run_conversation()checked the free-form scratchpad before its structuredassistant_message.tool_calls. Any unclosed scratchpad caused an unconditional retry and discarded the whole response, even when the provider had already returned a complete, independently structured tool call. After the retry, the useful action was gone.The recovery is intentionally narrow: only a non-empty structured tool-call list bypasses the scratchpad retry. Hermes strips the unclosed text tail and then enters its normal tool pipeline. Invalid names and arguments are still rejected there, and tools still require the same configured approvals.
Current-main proof
An isolated mocked response with an unclosed scratchpad plus a complete
web_search({})call produced:After this change, the same proof produces:
The follow-up request contains the tool call and result but no unclosed
REASONING_SCRATCHPADtext.Validation
HERMES_HOMEuv run --extra dev pytest tests/run_agent/test_run_agent.py::TestRunConversation -q(53 passed)uv run --extra dev pytest tests/run_agent/test_run_agent.py -q(425 passed)uv run --extra dev ruff check agent/conversation_loop.py tests/run_agent/test_run_agent.pygit diff --checkOverlap audit
PR #11743 handles false positives from quoted/code-form scratchpad tag mentions. The other open
REASONING_SCRATCHPADmatches affect title sanitization, UI token normalization, trajectory coverage, or list-valued session logging. None handles a true incomplete scratchpad response carrying structured tool calls.Fixes #11153