fix: Fixes agent graph tool calls in fanned out graphs#123
Merged
jsonbailey merged 7 commits intomainfrom Apr 7, 2026
Merged
Conversation
…ring - Add _coalesce_tool_messages_for_openai to fix parallel fan-out causing OpenAI 400 errors when sibling branch tool_calls have no ToolMessages - Add LDMetricsCallbackHandler for per-node token/tool/latency tracking - Add build_structured_tools with async callable support via inspect - Replace fan-out static edges with LLM-driven handoff tools (Command(goto=)) - Switch WorkflowState.messages to add_messages reducer - Add parallel_tool_calls=False when handoff tools present - Remove _coalesce_tool_messages_for_openai (no longer needed with handoffs) - Demote diagnostic logs to debug; exclude handoff tools from LD tracking - Consolidate token extraction to use get_ai_usage_from_response - Fix TestBuildTools to import build_structured_tools; cover async callables Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
a9f1d88 to
7c5d067
Compare
- Remove tool_registry parameter from create_langchain_model (matches main) - Remove _resolve_tools_for_langchain (no longer needed) - Remove BaseMessage import (unused) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Use isinstance(gen, ChatGeneration) to type-narrow in callback handler - Declare model as Any to accommodate Runnable return type from bind_tools - Fix bind_kwargs type annotation Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
packages/ai-providers/server-ai-langchain/src/ldai_langchain/langgraph_agent_graph_runner.py
Show resolved
Hide resolved
…e node A static loop-back edge from the tools node conflicted with Command(goto=child) emitted by handoff tools, causing both to fire as a fan-out. Fix by replacing the static edge with a conditional edge in the mixed case: after the ToolNode runs, route back to the parent only when the last message is from a functional tool; route to END when it is from a handoff (Command already handles routing to the target agent). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 9dec085. Configure here.
packages/ai-providers/server-ai-langchain/src/ldai_langchain/langgraph_agent_graph_runner.py
Show resolved
Hide resolved
- Cache compiled graph in _ensure_compiled() so _build_graph is not called on every run() invocation - Collect node_keys during traversal instead of reaching into _graph._nodes - Fix unconditional break in make_after_tools_router that made reversed() a no-op; replace broken loop with a direct last-message check - Fix duration tracking key collision: key _node_start_ns by run_id instead of node_key so concurrent invocations of the same node don't clobber each other's start times - Warn when a functional-tool node has multiple outgoing edges since only the first edge is reachable after the tool loop exits Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
andrewklatzke
approved these changes
Apr 7, 2026
Merged
jsonbailey
pushed a commit
that referenced
this pull request
Apr 7, 2026
🤖 I have created a release *beep* *boop* --- <details><summary>launchdarkly-server-sdk-ai-langchain: 0.4.1</summary> ## [0.4.1](launchdarkly-server-sdk-ai-langchain-0.4.0...launchdarkly-server-sdk-ai-langchain-0.4.1) (2026-04-07) ### Bug Fixes * Fixes agent graph tool calls in fanned out graphs ([#123](#123)) ([c140410](c140410)) </details> --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Low risk: only version/manifest metadata and changelog updates for a release; no functional code changes are included in this diff. > > **Overview** > Publishes `launchdarkly-server-sdk-ai-langchain` **v0.4.1** by bumping the package version in `pyproject.toml` and updating `.release-please-manifest.json`. > > Updates `CHANGELOG.md` with the 0.4.1 release notes, documenting a bug fix for agent graph tool calls in fanned-out graphs. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 6d8d6b2. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
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.

Note
Medium Risk
Refactors LangGraph graph construction, tool binding, and routing logic; mistakes could break agent execution flow or tracking in graphs with tools and multiple outgoing edges.
Overview
Fixes LangGraph agent graphs where tool calls in nodes with multiple outgoing edges could cause fan-out or incorrect routing.
The runner now builds
StructuredToolwrappers (sync + async) from LD tool definitions, adds explicit per-child handoff tools that returnCommand(goto=...), and adjusts conditional edges so functional tools loop back while handoffs terminate and transfer control.Tracking is reworked to use a new
LDMetricsCallbackHandlerthat collects per-node tokens, durations, tool calls, and execution path via LangChain callbacks, then flushes node metrics to LaunchDarkly trackers after the run; tests are updated/added to cover async invocation, structured tools, callback metrics, and multi-child routing behavior.Reviewed by Cursor Bugbot for commit f28fe5f. Bugbot is set up for automated code reviews on this repo. Configure here.