fix(langchain): respect version:"v1" in afterModel router's pending tool call path#10443
Merged
Christian Bromann (christian-bromann) merged 3 commits intomainfrom Mar 17, 2026
Merged
Conversation
…ool call path When afterModel middleware was present and an interrupted run was resumed, Send tasks regardless of the `version` option. With version:"v1" this caused the remaining calls to be executed one-per-graph-task instead of in parallel via Promise.all inside a single ToolNode invocation, breaking the user's expectation of parallelism. The fix branches on #toolBehaviorVersion in the pendingToolCalls path: v1 returns the plain TOOLS_NODE_NAME string so ToolNode handles the remaining calls with its existing Promise.all path; v2 keeps the Send-per-call dispatch unchanged. This matches Python LangGraph's behaviour, where the post_model_hook router (the analogous path) is only reachable in v2 and therefore always uses Send. Also expands the version JSDoc to explain when each option is the better choice, particularly calling out the checkpoint serialisation that occurs in v2 when tools invoke sub-graphs.
🦋 Changeset detectedLatest commit: 0ae443b The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Ensure the afterModel router respects the specified version in the pending tool call path.
Hunter Lovell (hntrl)
approved these changes
Mar 17, 2026
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.
createAgentaccepts aversionoption ("v1"|"v2", defaulting to"v2") that controls how tool calls are dispatched. Withversion: "v1"all tool calls from a singleAIMessageare executed concurrently inside oneToolNodeinvocation viaPromise.all, which is important for agents whose tools invoke sub-graphs — the v2 Send-per-task approach can serialize those calls due to LangGraph's per-task checkpoint writes.This PR fixes a bug where
version: "v1"was not fully respected whenafterModelmiddleware was present and an interrupted run was being resumed.Bug
#createAfterModelRoutercontains apendingToolCallsbranch that fires during interrupt resumption — when some tool calls from anAIMessagehave already completed and only a subset remain. That branch unconditionally dispatched each pending call as a separateSendtask regardless of#toolBehaviorVersion:With
version: "v1"this silently switched back to v2-style dispatch for the resumed portion of the run, breaking the parallelism guarantee.Fix
The
pendingToolCallspath now branches on#toolBehaviorVersion:TOOLS_NODE_NAMEas a plain string.ToolNode.run()receives the full message state, filters out already-completed calls internally, and runs the remainder viaPromise.all.Send-per-call dispatch unchanged.This matches the Python LangGraph implementation where the equivalent
post_model_hook_routeronly dispatches viaSendand is structurally unreachable fromversion: "v1".