How to process interrupts inside a subagent #2777
Replies: 6 comments
|
good questions! |
|
same issue |
|
Hi, I'm facing a similar issue on deepagents==0.5.3. Setup: create_deep_agent with AsyncPostgresSaver on the main agent SubAgent triggers interrupt correctly Expected: Root cause (looking at the code): Has this been resolved? If not, what's the current recommended workaround for HITL on side-effecting SubAgent tools? |
|
i am also facing same issue |
|
This is a known rough edge with LangGraph checkpointing and parallel tool execution. When a The cleanest solution is to avoid running a subagent tool in parallel with other tools in the same 1. Force sequential tool execution by setting 2. Separate the subagent into its own node. Route the LLM output through a conditional edge: if the tool call is the subagent tool, go to a dedicated Option 1 is the quicker fix. Option 2 gives you more control over resumption logic and is better if you need fine-grained human-in-the-loop behavior alongside the subagent. |
|
I think the root cause Izma Aziz (@IzmaAziz) found is the right one, and it goes beyond subagents. LangGraph checkpoints at the ToolNode boundary, not after each individual tool call. So if you fan out N tool calls inside one ToolNode and one of them interrupts, resume has no way to tell which of the other N already finished. It feels less like a subagent bug and more like a missing unit of granularity. There's no record of "this particular call was admitted and we know what happened to it" below the node level. Disabling parallel_tool_calls or putting subagents in their own nodes both work, but mostly because you're reducing the ToolNode to a single call. You're avoiding the granularity problem by removing the concurrency. That's a reasonable tradeoff if you don't need parallelism, but it doesn't really solve the underlying issue if you do want subagents and side-effecting tools running in parallel. Which is probably why this keeps coming back in different forms. The approach that seems more robust to me is keeping a small admission record outside the checkpointer. Before dispatching a tool call, whether it's a subagent or something else, write a durable "intent" record keyed by tool_call_id. The call then marks it completed or failed when it returns. On resume, you check that record before replaying the ToolNode. If it's completed, don't invoke it again. If it's still in progress with no outcome, at least you know the call is ambiguous instead of silently running it twice. That gets around the checkpoint granularity issue because the record isn't tied to where the interrupt happened inside Pregel. Curious if anyone has tried something along those lines as a stopgap specifically for subagents. They seem like the hardest case since they don't have their own checkpointer, so there's no way to know whether the subagent had already partially advanced before the interrupt. Also, did the config propagation gap Izma Aziz (@IzmaAziz) found ever get filed as a separate issue, or is it still just part of this thread? |
Uh oh!
There was an error while loading. Please reload this page.
I have a question about handling interrupts inside a SubAgent and preventing duplicate execution of tools.
A SubAgent is wrapped as a tool, and then grouped together with other tools inside a ToolNode. During a single LLM response, if both a SubAgent call and a normal tool call appear, they will run in parallel.
The problem is:
If the SubAgent encounters an interrupt, when the system resumes the execution it seems to re-run the entire ToolNode, which causes all tools (including the normal ones) to run again. How can this be avoided?
For normal tools, I can work around this by moving the interrupt earlier into the
after_modelstage, but for SubAgents I don’t have a way to intercept or shift the interrupt timing. This means I can’t prevent re-execution if the SubAgent is interrupted.Similarly, if the LLM returns multiple SubAgent calls at once, an interrupt in any one of them will cause all SubAgents to be executed again on resume. How can I prevent one SubAgent’s interrupt from causing all other SubAgents to be re-run?
I previously built a deepagents-like framework using LangGraph. Similar to deepagents, I have a main Agent that includes
FileOperate,TodoWrite, andTasktools. Inside theTasktool, I also include several tools (except Task itself).To avoid duplicate executions during interrupt recovery, I had to separate SubAgent tools from normal tools:
after_modelto prevent re-execution.This workaround does prevent duplicated execution, but the whole solution feels very hacky and unnatural. It doesn’t seem like the intended way to deal with SubAgent interrupts, and managing multiple ToolNodes manually is error-prone and hard to maintain.
Is there a more idiomatic or recommended way to handle SubAgent interrupts without separating tools or manually mapping ToolNodes?
All reactions