Skip to content

fix: Fixes agent graph tool calls in fanned out graphs#123

Merged
jsonbailey merged 7 commits intomainfrom
jb/aic-1664/handoff-approach-b
Apr 7, 2026
Merged

fix: Fixes agent graph tool calls in fanned out graphs#123
jsonbailey merged 7 commits intomainfrom
jb/aic-1664/handoff-approach-b

Conversation

@jsonbailey
Copy link
Copy Markdown
Contributor

@jsonbailey jsonbailey commented Apr 6, 2026

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 StructuredTool wrappers (sync + async) from LD tool definitions, adds explicit per-child handoff tools that return Command(goto=...), and adjusts conditional edges so functional tools loop back while handoffs terminate and transfer control.

Tracking is reworked to use a new LDMetricsCallbackHandler that 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.

jsonbailey and others added 2 commits April 6, 2026 12:13
…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>
@jsonbailey jsonbailey force-pushed the jb/aic-1664/handoff-approach-b branch from a9f1d88 to 7c5d067 Compare April 6, 2026 17:28
jsonbailey and others added 2 commits April 6, 2026 12:42
- 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>
@jsonbailey jsonbailey marked this pull request as ready for review April 6, 2026 17:50
@jsonbailey jsonbailey requested a review from a team as a code owner April 6, 2026 17:50
jsonbailey and others added 2 commits April 6, 2026 13:10
…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>
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ 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.

- 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>
@jsonbailey jsonbailey merged commit c140410 into main Apr 7, 2026
46 checks passed
@jsonbailey jsonbailey deleted the jb/aic-1664/handoff-approach-b branch April 7, 2026 17:51
@github-actions github-actions bot mentioned this pull request Apr 7, 2026
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants