[PR #6542] fix(langgraph): fix interrupt resume routing for parallel interrupts #5112

Closed
opened 2026-02-20 17:51:14 -05:00 by yindo · 0 comments
Owner

Original Pull Request: https://github.com/langchain-ai/langgraph/pull/6542

State: closed
Merged: No


Summary

Fix interrupt resume routing for parallel interrupts (#6533, #6534).

When multiple interrupt() calls occur within the same task (e.g., parallel tools in ToolNode), they were generating identical interrupt IDs because the ID was derived solely from the checkpoint namespace. This caused resume values to be misrouted between tools.

Problem

When using ToolNode with multiple tools that call interrupt():

@tool
def tool_a(val: str) -> str:
    response = interrupt({"tool": "a"})  # ID: abc123
    return f"A got: {response}"

@tool  
def tool_b(val: str) -> str:
    response = interrupt({"tool": "b"})  # ID: abc123 (SAME!)
    return f"B got: {response}"

Both tools shared the same checkpoint namespace, so both interrupts received identical IDs. When resuming with Command(resume={id: value}), values could be routed to the wrong tool.

Solution

  1. Include interrupt counter in ID generation (types.py):

    # Before
    ns=conf[CONFIG_KEY_CHECKPOINT_NS]
    # After  
    ns=f"{conf[CONFIG_KEY_CHECKPOINT_NS]}|{idx}"
    
  2. Update resume_map lookup (_algo.py):

    • Changed _scratchpad() to iterate through counter indices when looking up resume values
    • Ensures all interrupt-specific resume values are found

Testing

  • Added test_tool_node_parallel_interrupts in prebuilt (regression test for #6533)
  • Added test_interrupt_resume_with_multiple_nodes in langgraph (regression test for #6534)
  • All 189 existing interrupt tests pass

Fixes #6533
Fixes #6534

**Original Pull Request:** https://github.com/langchain-ai/langgraph/pull/6542 **State:** closed **Merged:** No --- ## Summary Fix interrupt resume routing for parallel interrupts (#6533, #6534). When multiple `interrupt()` calls occur within the same task (e.g., parallel tools in ToolNode), they were generating identical interrupt IDs because the ID was derived solely from the checkpoint namespace. This caused resume values to be misrouted between tools. ## Problem When using ToolNode with multiple tools that call `interrupt()`: ```python @tool def tool_a(val: str) -> str: response = interrupt({"tool": "a"}) # ID: abc123 return f"A got: {response}" @tool def tool_b(val: str) -> str: response = interrupt({"tool": "b"}) # ID: abc123 (SAME!) return f"B got: {response}" ``` Both tools shared the same checkpoint namespace, so both interrupts received identical IDs. When resuming with `Command(resume={id: value})`, values could be routed to the wrong tool. ## Solution 1. **Include interrupt counter in ID generation** (`types.py`): ```python # Before ns=conf[CONFIG_KEY_CHECKPOINT_NS] # After ns=f"{conf[CONFIG_KEY_CHECKPOINT_NS]}|{idx}" ``` 2. **Update resume_map lookup** (`_algo.py`): - Changed `_scratchpad()` to iterate through counter indices when looking up resume values - Ensures all interrupt-specific resume values are found ## Testing - Added `test_tool_node_parallel_interrupts` in prebuilt (regression test for #6533) - Added `test_interrupt_resume_with_multiple_nodes` in langgraph (regression test for #6534) - All 189 existing interrupt tests pass Fixes #6533 Fixes #6534
yindo added the pull-request label 2026-02-20 17:51:14 -05:00
yindo closed this issue 2026-02-20 17:51:14 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langchain-ai/langgraph#5112