Skip to content

feat: Agent graph support#181

Draft
mattrmc1 wants to merge 4 commits into
mmccarthy/AIC-2664/ai-config-tracker-overhaulfrom
mmccarthy/AIC-2837/java-ai-sdk-agent-graph
Draft

feat: Agent graph support#181
mattrmc1 wants to merge 4 commits into
mmccarthy/AIC-2664/ai-config-tracker-overhaulfrom
mmccarthy/AIC-2837/java-ai-sdk-agent-graph

Conversation

@mattrmc1

@mattrmc1 mattrmc1 commented Jun 23, 2026

Copy link
Copy Markdown

Summary

Adds agent graph support — flag evaluation, graph validation, BFS traversal, graph-level tracking, and resumption tokens. Callers fetch a graph definition via agentGraph(graphKey, context, variables), inspect or traverse the node topology, and track graph-level metrics (invocation success/failure, duration, tokens, path) plus edge-level events (redirect, handoff) through AIGraphTracker.

New types

GraphEdge — immutable edge holding target key and optional handoff metadata map (unmodifiable).

AgentGraphNode — wraps a node key, its resolved AIAgentConfig, and outgoing GraphEdge list. isTerminal() returns true when edges are empty.

AgentGraphFlagValue (internal) — parses the graph flag JSON protocol: root, edges adjacency map, and _ldMeta (enabled, variationKey, version). Defensively handles malformed input without throwing.

AgentGraphDefinition — the resolved graph. Key API: isEnabled(), rootNode(), getNode(key), getChildNodes(key), getParentNodes(key), terminalNodes(), createTracker(). BFS traversal via traverse(fn, ctx) (root-to-leaves) and reverseTraverse(fn, ctx) (terminals-to-root, root always processed last). Both are cycle-safe. Node building and key collection via static helpers.

AIGraphTracker — graph-level at-most-once tracking (trackInvocationSuccess/trackInvocationFailure sharing one guard, trackDuration, trackTotalTokens, trackPath) and multi-fire edge-level events (trackRedirect, trackHandoffSuccess, trackHandoffFailure). Uses AtomicReference.compareAndSet(null, value) for at-most-once. Empty token usage doesn't burn the slot. Resumption token via getResumptionToken() / fromResumptionToken(token, client, context) with version clamping.

AIGraphMetricSummary — immutable snapshot of graph tracker state (success, durationMs, tokens, path, resumptionToken). All nullable except resumptionToken.

Client methods

agentGraph(graphKey, context, variables) on LDAIClient — evaluates the graph flag, validates (enabled -> root present -> all nodes reachable from root -> all child configs enabled), fetches each node's AIAgentConfig passing graphKey for tracker correlation. Returns disabled definition on any validation failure. Emits $ld:ai:usage:agent-graph usage event.

createGraphTracker(resumptionToken, context) — reconstructs an AIGraphTracker from a resumption token.

Other changes

  • NoOpAIConfigTracker deleted — no longer needed since all configs get real trackers.
  • ResumptionTokens extended with encodeGraph/decodeGraph for graph-specific tokens (fields: runId, graphKey, variationKey, version). Made public for access from AIGraphTracker.
  • LDAIConfigTrackerImpl updates: null-arg logs downgraded warn -> debug, trackJudgeResult guards blank metricKey and non-finite score, trackMetricsOf stops clock before extractor (duration tracked even if extractor throws).
  • trackerFactory default version changed from 0 to 1.
  • agentConfigs() reordered to emit usage count before fetching configs.
  • Internal evaluate/buildConfig/buildConfigFromDefault gain graphKey parameter for node-level tracker correlation.

Test plan

  • ./gradlew :lib:sdk:server-ai:test passes
  • AIGraphTrackerTest (480 lines): invocation success/failure + shared guard, duration, total tokens (including zero-usage skip), path, redirect/handoff multi-fire, base data correctness, variationKey omission, getSummary, resumption token round-trip, concurrency (20-thread contention for invocation and duration)
  • AgentGraphDefinitionTest (445 lines): buildNodes, collectAllKeys, traverse/reverseTraverse (including cycles, single-node, diamond), rootNode/getNode/getChildNodes/getParentNodes/terminalNodes, disabled graph behavior, createTracker
  • LDAIClientImplTest additions (192 lines): agentGraph usage event, enabled/disabled graph, unreachable node validation, non-enabled child config validation, graphKey threading to child trackers, createGraphTracker delegation
  • AgentGraphFlagValueTest (276 lines): parse root/edges/meta, missing fields, disabled flag, malformed input, handoff metadata, edge with missing key skipped
  • ResumptionTokensTest additions: graph token encode/decode round-trips
  • LDAIConfigTrackerImplTest additions: trackMetricsOf extractor-failure duration tracking, null AIMetrics guard

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.

1 participant