fix: HITL session persistence, tool events, and breakpoint interaction#189
Merged
cristipufu merged 2 commits intomainfrom Feb 21, 2026
Merged
fix: HITL session persistence, tool events, and breakpoint interaction#189cristipufu merged 2 commits intomainfrom
cristipufu merged 2 commits intomainfrom
Conversation
- After HITL resume, checkpoint restore creates separate session copies per executor. Extract the most complete session (highest message count) and persist it to KV storage so the next turn has valid history. - Handle AgentExecutorResponse wrapper in _extract_tool_state_events and _extract_contents so function_result from executor_completed data is properly found. - Emit ToolCallEnd in close_message() for pending tool calls interrupted by HITL suspension (clears stale _pending_tool_calls state). - Track pending tool nodes (STARTED without COMPLETED) across stream iterations and synthesize COMPLETED events on HITL resume. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
27a8882 to
e686eaf
Compare
e686eaf to
6264039
Compare
6264039 to
6cb6f2b
Compare
- Load breakpoint skip counts on HITL resume so the executor passes through without re-firing the breakpoint (prevents the infinite breakpoint → HITL → breakpoint loop on same node) - Clear _last_checkpoint_id after loading breakpoint state to prevent the next fresh turn from being mistaken for a breakpoint resume - Detect stale checkpoints from previous turns by capturing a baseline before workflow.run() and comparing after breakpoint fires - Fall back to _resumed_from_checkpoint_id (instead of None) when no new checkpoint was created, preventing replay from scratch that caused duplicate handoff_to_billing_agent events (4x) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
6cb6f2b to
83c36bf
Compare
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.
Summary
Commit 1: Persist session after HITL resume and emit tool completed events
AgentExecutorResponsewrapper in_extract_tool_state_eventsand_extract_contentssofunction_resultfromexecutor_completeddata is properly found.ToolCallEndinclose_message()for pending tool calls interrupted by HITL suspension (clears stale_pending_tool_callsstate).Commit 2: Prevent breakpoint+HITL infinite loop and duplicate events
_last_checkpoint_idafter loading breakpoint state to prevent the next fresh turn from being mistaken for a breakpoint resume.workflow.run()and comparing after breakpoint fires._resumed_from_checkpoint_id(instead ofNone) when no new checkpoint was created, preventing replay from scratch that caused duplicatehandoff_to_billing_agentevents (4x).Test plan
test_no_duplicate_tool_calls_on_breakpoint_resume— breakpoints=* + HITL: exactly 1handoff_to_billing_agent(was 4x before fix)test_second_turn_after_breakpoint_and_hitl— multi-turn stale checkpoint detection still workstest_breakpoint_then_hitl_does_not_loop— breakpoint + HITL on same node completes without infinite looptest_breakpoint_on_all_nodes_with_hitl— breakpoints=* + HITL completes successfullytest_tool_node_completed_after_hitl_resume— tool nodes emit both STARTED and COMPLETED across HITL🤖 Generated with Claude Code