feat: Implement agent graph definitions#1282
feat: Implement agent graph definitions#1282jsonbailey wants to merge 6 commits intofeat/ai-sdk-next-releasefrom
Conversation
Add AgentGraphDefinition, AgentGraphNode, LDGraphTracker, and LDGraphTrackerImpl per the AIGRAPH and AIGRAPHTRACK specs, along with the agentGraph() and createGraphTracker() methods on LDAIClientImpl. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
@launchdarkly/js-sdk-common size report |
|
@launchdarkly/browser size report |
|
@launchdarkly/js-client-sdk size report |
|
@launchdarkly/js-client-sdk-common size report |
…Impl Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
joker23
left a comment
There was a problem hiding this comment.
I think the bot comments need to be addressed before merging
…pological sort
- Add _hasCycle() DFS validation to agentGraph() — cyclic graphs now return
{ enabled: false } instead of hanging reverseTraverse indefinitely
- Replace _computeLongestPathDepths BFS with Kahn's topological sort + DP,
which is correct for DAGs and terminates in O(V+E)
- Remove dead stores _context and _graphKey from AgentGraphDefinition constructor
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…om terminals Cyclic graphs are valid (supported in the LD UI and by frameworks like LangGraph). Replace depth-sorted reverseTraverse with upward BFS from terminal nodes via getParentNodes(), matching the Python SDK implementation: - Remove _hasCycle() and cycle rejection from agentGraph() — cyclic graphs now pass validation and traverse safely - Drop _computeLongestPathDepths() entirely - reverseTraverse: BFS upward from terminalNodes(), visited set prevents cycles from looping, root is always deferred and invoked last - Fully cyclic graphs (no terminals) return early without invoking fn, same as Python Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| // Defer the root so it is always processed last | ||
| if (key === rootKey) { | ||
| return; | ||
| } |
There was a problem hiding this comment.
reverseTraverse skips nodes in cycles involving root
Medium Severity
When reverseTraverse encounters the root node in the BFS queue, it adds root to visited and returns immediately — deferring fn invocation to after the loop. However, this early return also skips enqueuing root's parents. In cyclic graphs where a node points back to root (e.g., root → [a, b], a → [root], b terminal), node a is a parent of root and is only discoverable through root's parent-edge exploration. Since that exploration is skipped, a is silently never visited despite being a valid, reachable node that passed agentGraph validation. The parent-exploration logic (lines 224–228) needs to run for root before the return, while still deferring the fn call.
Reviewed by Cursor Bugbot for commit 5191c48. Configure here.
Addresses PR feedback: when _ldMeta.enabled is false, agentGraph() was
still returning { enabled: true, graph } despite the AgentGraphDefinition
documenting that enabled graphs are always true. Now returns disabled early
if the flag is explicitly disabled.
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.
There are 2 total unresolved issues (including 1 from previous review).
❌ 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 5cba2c1. Configure here.
| const result = fn(root, executionContext); | ||
| executionContext[rootKey] = result; | ||
| } | ||
| } |
There was a problem hiding this comment.
reverseTraverse doesn't guarantee documented descendant-first ordering
Medium Severity
reverseTraverse documents that "each node is processed only after all of its reachable descendants have been processed," but the BFS-from-terminals algorithm doesn't guarantee this for DAGs where two nodes discovered at the same BFS level have a parent-child relationship. For example, with edges a → b, a → c, b → c, terminal c's parents a and b are enqueued together. a is processed before b, but b is a descendant of a, so b's result won't be in executionContext when fn(a) runs. A proper reverse topological sort (e.g., Kahn's algorithm) is needed.
Reviewed by Cursor Bugbot for commit 5cba2c1. Configure here.


Summary
AgentGraphDefinition,AgentGraphNode, and graph type definitions (LDAgentGraphFlagValue,LDGraphEdge,LDGraphMetricSummary,LDGraphTrackData)LDGraphTrackerinterface andLDGraphTrackerImplwith UUID v4runIdgeneration, at-most-once semantics (with warnings on duplicate calls), multi-fire edge-level methods, and cross-process resumption via URL-safe Base64 tokenagentGraph()andcreateGraphTracker()methods toLDAIClient/LDAIClientImpl; validates graph connectivity, root presence, and that all referenced agent configs are enabled before returning a graphTest plan
yarn workspace @launchdarkly/server-sdk-ai test— 175 tests pass across 8 suitesAgentGraphDefinition.test.ts— 28 tests coveringbuildNodes,collectAllKeys,traverse(BFS order + context mutation),reverseTraverse(longest-path depth), node queries,createTrackerLDGraphTrackerImpl.test.ts— 30 tests coveringrunIdgeneration, resumption token encoding/decoding,fromResumptionTokenround-trip, at-most-once warning behavior, edge-level multi-fireagentGraph.test.ts— 9 tests covering disabled-when-no-root, disconnected-node detection, disabled-child-config, happy-path single- and multi-node graphs, usage event tracking,createGraphTrackerround-trip🤖 Generated with Claude Code
Note
Medium Risk
Adds new public API surface and new tracking payload/token semantics; incorrect validation or token handling could disable graphs or mis-correlate telemetry, but changes are additive and well-covered by new tests.
Overview
Introduces a new agent-graph feature set:
AgentGraphDefinition/AgentGraphNodeplus graph flag types, enabling traversal (forward BFS and reverse-from-terminals) and parent/child/terminal queries over a LaunchDarkly-provided graph config.Extends the public
LDAIClientAPI withagentGraph()(usage-tracked) andcreateGraphTracker(), including validation that the graph is enabled, has a root, is fully connected from the root, and that all referenced agent configs can be fetched and are enabled.Overhauls
LDGraphTrackerImpl/LDGraphTrackerto add per-invocationrunId, resumable tracking via a URL-safe Base64resumptionToken+fromResumptionToken, stricter at-most-once semantics (with warnings) for graph-level metrics, and updated track payloads to includerunIdand optionalvariationKey.Reviewed by Cursor Bugbot for commit 5cba2c1. Bugbot is set up for automated code reviews on this repo. Configure here.