Skip to content

fix(agent): close tool-call sequence on all interrupt aborts (#48879 follow-up) - #52592

Merged
OutThisLife merged 1 commit into
mainfrom
bb/close-interrupt-tool-seq-sibling-paths
Jun 25, 2026
Merged

fix(agent): close tool-call sequence on all interrupt aborts (#48879 follow-up)#52592
OutThisLife merged 1 commit into
mainfrom
bb/close-interrupt-tool-seq-sibling-paths

Conversation

@OutThisLife

Copy link
Copy Markdown
Collaborator

Summary

Bug report: "in profiles, if I send a message, it starts working, I hit stop, and send a new one — it seems to lose context frequently." The attached screenshot shows the agent replying "i dont have context on what 'they' refers 2 or what timing 2 increase" and falling back to a Session Search to recover what it was just doing — classic lost-context-after-stop.

Root cause

This is the #48879 failure mode on sibling code paths. #48879 ("close tool-call sequence on interrupt") added a synthetic assistant turn in finalize_turn so a /stop after a tool no longer persists a raw tool tail. Without it, the next user message lands as … tool → user, a role-alternation violation that strict providers (Gemini, Claude) react to by hallucinating a continuation of the user's message and ignoring prior context.

But finalize_turn is not the only interrupt exit. The retry-wait, error-handling, and post-error retry-wait interrupt aborts in agent/conversation_loop.py return early and never reach finalize_turn, so they still persisted and returned an unclosed tool tail. Interrupting during provider backoff / rate-limiting (common under heavy work like the CI-timing session in the report) hits exactly these paths — hence "frequently".

Fix

  • Extract the close into a single shared helper close_interrupted_tool_sequence(messages, final_response) in agent/message_sanitization.py.
  • Apply it at every interrupt abort: finalize_turn (now delegates to the helper) and the three early returns in conversation_loop.

This fixes the whole bug class rather than the one site, per the contribution rubric ("fix the whole bug class — sibling call paths included").

Test plan

  • New tests/agent/test_close_interrupted_tool_sequence.py — pins the helper contract (tool tail closed with placeholder / preserved interrupt text / blank falls back) and the alternation-safety guarantee (appending a next user turn never yields tool → user); no-ops on assistant/user/empty tails.
  • Existing tests/agent/test_turn_finalizer_interrupt_alternation.py still green (finalize_turn now routes through the helper).
  • Broader interrupt suites green: test_stream_interrupt_retry, test_interrupt_propagation, test_turn_finalizer_cleanup_guard, test_message_sequence_repair, test_empty_response_recovery_persistence.

@github-actions

github-actions Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

🔎 Lint report: bb/close-interrupt-tool-seq-sibling-paths 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: 11268 on HEAD, 11270 on base (✅ -2)

🆕 New issues (1):

Rule Count
invalid-assignment 1
First entries
tests/run_agent/test_credits_notices_toggle.py:76: [invalid-assignment] invalid-assignment: Object of type `None` is not assignable to attribute `_credits_session_start_micros` of type `int`

✅ Fixed issues (2):

Rule Count
unresolved-attribute 2
First entries
tests/run_agent/test_credits_notices_toggle.py:76: [unresolved-attribute] unresolved-attribute: Unresolved attribute `_credits_session_start_micros` on type `AIAgent`
run_agent.py:2989: [unresolved-attribute] unresolved-attribute: Object of type `Self@get_credits_spent_micros` has no attribute `_credits_session_start_micros`

Unchanged: 5941 pre-existing issues carried over.

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

…t finalize_turn

#48879 closed the tool-call sequence on interrupt inside finalize_turn so a
/stop after a tool no longer persists a `tool` tail that the next user message
turns into a `tool -> user` role-alternation violation (which strict providers
like Gemini/Claude react to by hallucinating a continuation and ignoring prior
context — what users see as "lost context after stop").

But the retry-wait, error-handling, and post-error retry-wait interrupt aborts
in conversation_loop return early and never reach finalize_turn, so they still
persisted and returned a raw `tool` tail. Interrupting during provider
backoff/rate-limiting (common under heavy work) hit exactly this path.

Extract the close into a shared close_interrupted_tool_sequence helper and apply
it at every interrupt abort (finalize_turn + the three early returns) so the
whole bug class is fixed, not just the one site.
@OutThisLife
OutThisLife force-pushed the bb/close-interrupt-tool-seq-sibling-paths branch from 2eb9e03 to 2d286a6 Compare June 25, 2026 17:24
@OutThisLife
OutThisLife enabled auto-merge June 25, 2026 17:25
@OutThisLife
OutThisLife merged commit 931a5e9 into main Jun 25, 2026
27 checks passed
@OutThisLife
OutThisLife deleted the bb/close-interrupt-tool-seq-sibling-paths branch June 25, 2026 17:31
@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 sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state labels Jun 25, 2026
waefrebeorn pushed a commit to waefrebeorn/slermes that referenced this pull request Jul 2, 2026
…rrupt-tool-seq-sibling-paths

fix(agent): close tool-call sequence on all interrupt aborts (NousResearch#48879 follow-up)
habarmc1223-sudo pushed a commit to habarmc1223-sudo/hermes-agent-fluxmem that referenced this pull request Jul 8, 2026
…rrupt-tool-seq-sibling-paths

fix(agent): close tool-call sequence on all interrupt aborts (NousResearch#48879 follow-up)
santhreal pushed a commit to santhreal/hermes-agent that referenced this pull request Jul 13, 2026
…rrupt-tool-seq-sibling-paths

fix(agent): close tool-call sequence on all interrupt aborts (NousResearch#48879 follow-up)
Gravezzz pushed a commit to Gravezzz/hermes-agent that referenced this pull request Jul 21, 2026
…rrupt-tool-seq-sibling-paths

fix(agent): close tool-call sequence on all interrupt aborts (NousResearch#48879 follow-up)
leewenjie pushed a commit to leewenjie/hermes-agent that referenced this pull request Aug 7, 2026
…rrupt-tool-seq-sibling-paths

fix(agent): close tool-call sequence on all interrupt aborts (NousResearch#48879 follow-up)
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: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.

2 participants