Repository navigation
fix(AIC-3571): visit every child before its parent in reverseTraverse - #147
Merged
Merged
Conversation
reverseTraverse walked up from terminal nodes breadth-first, so a parent was visited as soon as one child was, even when another child sat deeper. It now does a post-order DFS from the root: each node once, every child before its parent, root last. The OpenAI and Claude agents adapters drop an edge whose child is still unbuilt (a cycle back-edge) with a warning instead of throwing or dropping it silently. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
andrewklatzke
approved these changes
Oct 21, 2026
andrewklatzke
approved these changes
Oct 21, 2026
jeffdupont
added a commit
to launchdarkly/go-ai-sdk
that referenced
this pull request
Oct 21, 2026
…#12) Fixes [AIC-3571](https://launchdarkly.atlassian.net/browse/AIC-3571). ## Why `ReverseTraverse` is meant to visit every child before its parent. It walked up breadth-first from the terminal nodes instead, so a parent was visited as soon as one child was. With root → P, P → T1, P → Q, Q → T2 the order was T1, T2, P, Q, root. `ToClaudeAgents` then built P without Q's sub-agent tool and logged nothing, so the model could never reach Q. The Python adapters already use a post-order DFS; this PR makes core match. ## Fix - `aiserver/graph.go`: `ReverseTraverse` is now a post-order DFS from the root with a visited set. Each node is visited once, every child before its parents, root last. Same signature. - `claudeagents/native.go`: a child that is still unbuilt (now only a cycle back-edge) is still dropped, but now with a `Warn` on the SDK logger (`bridge.Logger()`, which follows `aiserver.SetLogger`). - `openaiagents` and `langchainagents` don't build from `ReverseTraverse`, so they need no change. Behaviour changes: - Nodes that can't be reached from the root are no longer visited. - A graph with no terminal nodes (a pure cycle) is now walked from the root. It used to return nil. The `!ok` fallback in `claudeagents/native.go` `execute` is now hit only when there is no root. I left it in place. ## Testing - `make test` (`go test -race ./...`): 845 passed, 0 failed. `go vet ./...` and `make lint`: clean. - New tests: `aiserver.TestReverseTraverseVisitsEveryChildBeforeItsParent` covers the uneven order (expects T1, T2, Q, P, root) and a cycle visited once each. `claudeagents.TestToClaudeAgentsCycleBackEdgeDropped` covers the warning. - With the fix reverted, both fail: `uneven: reverse order = [T1 T2 P Q root]`, and the claudeagents test finds no warning in the log. Related: js launchdarkly/js-ai-sdk#147 · python launchdarkly/python-ai-sdk#189 · go #12 · spec launchdarkly/ai-sdks-monorepo#73 🤖 Generated with [Claude Code](https://claude.com/claude-code) [AIC-3571]: https://launchdarkly.atlassian.net/browse/AIC-3571?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
jeffdupont
added a commit
to launchdarkly/python-ai-sdk
that referenced
this pull request
Oct 21, 2026
#189) Fixes [AIC-3571](https://launchdarkly.atlassian.net/browse/AIC-3571). ## Why `reverse_traverse` is meant to visit every child before its parent. It walked up breadth-first from the terminal nodes instead, so a parent was visited as soon as one child was. With root → P, P → T1, P → Q, Q → T2 the order was T1, T2, P, Q, root: P came before its child Q. Anyone building children first from `reverse_traverse` got a parent without its deeper child. The Python adapters already use their own post-order DFS (`_reverse_traverse` in claude-agents, `_visit` in openai-agents), so core now uses the same approach. ## Fix - `packages/client/src/launchdarkly_ai_server/graph.py`: `reverse_traverse` is now a post-order DFS from the root with a visited set. Each node is visited once, every child before its parents, root last. Same signature. - `packages/openai-agents/.../native_graph.py`: a child that is still unbuilt (a cycle back-edge) is dropped with `logger.warning` instead of raising `ValueError`. - `packages/claude-agents/.../native_graph.py`: the same case used to be skipped silently. It now logs `logger.warning`. - `AGENTS.md` no longer says "reverse BFS". Behaviour changes: - Nodes that can't be reached from the root are no longer visited. - A graph with no terminal nodes (a pure cycle) is now walked from the root. It used to return `None` without visiting anything. ## Testing - `make test`: 2548 passed, 14 skipped. `make typecheck`: no issues in 75 files. `make lint`: all checks passed. - New tests: in client `test_graph.py`, the uneven-depth order (expects T1, T2, Q, P, root) and a cycle visited once each. In openai-agents and claude-agents `test_native_graph.py`, a cycle back-edge dropped with a warning. - With the fix reverted, 3 of the new tests fail: the uneven order (`'T2' != 'T1'` at index 0 after P), the openai-agents cycle test (`ValueError`), and the claude-agents cycle test (no warning). The client cycle test also passes on the old code. It stays as a guard that each node is visited once. Related: js launchdarkly/js-ai-sdk#147 · python #189 · go launchdarkly/go-ai-sdk#12 · spec launchdarkly/ai-sdks-monorepo#73 🤖 Generated with [Claude Code](https://claude.com/claude-code) [AIC-3571]: https://launchdarkly.atlassian.net/browse/AIC-3571?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Merged
jeffdupont
pushed a commit
that referenced
this pull request
Oct 26, 2026
🤖 I have created a release *beep* *boop* --- <details><summary>@launchdarkly/ai-claude-agents: 0.5.0</summary> ## [0.5.0](https://github.com/launchdarkly/js-ai-sdk/compare/@launchdarkly/ai-claude-agents-0.4.0...@launchdarkly/ai-claude-agents-0.5.0) (2026-10-26) ### ⚠ BREAKING CHANGES * forward the same model.parameters keys as the Python SDK ([#118](#118)) * **claude-agents:** accept trusted cwd and settingSources options, and load no host settings by default ([#135](#135)) * **client:** the client no longer loads .env. Add import 'dotenv/config' to your entrypoint (and install dotenv) if you relied on it. ### Features * **AIC-3623:** evals from code ([#143](#143)) ([dc74b48](dc74b48)) * **claude-agents:** accept trusted cwd and settingSources options, and load no host settings by default ([#135](#135)) ([6acd53d](6acd53d)) ### Bug Fixes * **AIC-3571:** visit every child before its parent in reverseTraverse ([#147](#147)) ([a17a2ce](a17a2ce)) * **AIC-3577:** send object tool results to the model as JSON ([#146](#146)) ([be41d87](be41d87)) * **claude-agents:** fail the run when the CLI reports an API error as success ([#138](#138)) ([4637958](4637958)) * **client:** stop loading dotenv from library code ([#69](#69)) ([fea34f3](fea34f3)) * forward the same model.parameters keys as the Python SDK ([#118](#118)) ([f7883ce](f7883ce)) * give native graph spans their LaunchDarkly identity ([#101](#101)) ([4d97cfa](4d97cfa)) ### Dependencies * The following workspace dependencies were updated * dependencies * @launchdarkly/ai-server bumped from ^0.4.0 to ^0.5.0 </details> <details><summary>@launchdarkly/ai-claude-messages: 0.5.0</summary> ## [0.5.0](https://github.com/launchdarkly/js-ai-sdk/compare/@launchdarkly/ai-claude-messages-0.4.0...@launchdarkly/ai-claude-messages-0.5.0) (2026-10-26) ### ⚠ BREAKING CHANGES * forward the same model.parameters keys as the Python SDK ([#118](#118)) * **client:** the client no longer loads .env. Add import 'dotenv/config' to your entrypoint (and install dotenv) if you relied on it. ### Features * **AIC-3623:** evals from code ([#143](#143)) ([dc74b48](dc74b48)) ### Bug Fixes * **AIC-3577:** send object tool results to the model as JSON ([#146](#146)) ([be41d87](be41d87)) * **client:** stop loading dotenv from library code ([#69](#69)) ([fea34f3](fea34f3)) * forward the same model.parameters keys as the Python SDK ([#118](#118)) ([f7883ce](f7883ce)) ### Dependencies * The following workspace dependencies were updated * dependencies * @launchdarkly/ai-server bumped from ^0.4.0 to ^0.5.0 </details> <details><summary>@launchdarkly/ai-langchain-agents: 0.5.0</summary> ## [0.5.0](https://github.com/launchdarkly/js-ai-sdk/compare/@launchdarkly/ai-langchain-agents-0.4.0...@launchdarkly/ai-langchain-agents-0.5.0) (2026-10-26) ### ⚠ BREAKING CHANGES * forward the same model.parameters keys as the Python SDK ([#118](#118)) * **client:** the client no longer loads .env. Add import 'dotenv/config' to your entrypoint (and install dotenv) if you relied on it. ### Features * **AIC-3623:** evals from code ([#143](#143)) ([dc74b48](dc74b48)) ### Bug Fixes * **AIC-3577:** send object tool results to the model as JSON ([#146](#146)) ([be41d87](be41d87)) * **client:** stop loading dotenv from library code ([#69](#69)) ([fea34f3](fea34f3)) * forward the same model.parameters keys as the Python SDK ([#118](#118)) ([f7883ce](f7883ce)) * give native graph spans their LaunchDarkly identity ([#101](#101)) ([4d97cfa](4d97cfa)) ### Dependencies * The following workspace dependencies were updated * dependencies * @launchdarkly/ai-server bumped from ^0.4.0 to ^0.5.0 </details> <details><summary>@launchdarkly/ai-langchain-messages: 0.5.0</summary> ## [0.5.0](https://github.com/launchdarkly/js-ai-sdk/compare/@launchdarkly/ai-langchain-messages-0.4.0...@launchdarkly/ai-langchain-messages-0.5.0) (2026-10-26) ### ⚠ BREAKING CHANGES * forward the same model.parameters keys as the Python SDK ([#118](#118)) * **client:** the client no longer loads .env. Add import 'dotenv/config' to your entrypoint (and install dotenv) if you relied on it. ### Features * **AIC-3623:** evals from code ([#143](#143)) ([dc74b48](dc74b48)) ### Bug Fixes * **AIC-3577:** send object tool results to the model as JSON ([#146](#146)) ([be41d87](be41d87)) * **client:** stop loading dotenv from library code ([#69](#69)) ([fea34f3](fea34f3)) * forward the same model.parameters keys as the Python SDK ([#118](#118)) ([f7883ce](f7883ce)) ### Dependencies * The following workspace dependencies were updated * dependencies * @launchdarkly/ai-server bumped from ^0.4.0 to ^0.5.0 </details> <details><summary>@launchdarkly/ai-litellm-agents: 0.2.0</summary> ## [0.2.0](https://github.com/launchdarkly/js-ai-sdk/compare/@launchdarkly/ai-litellm-agents-0.1.0...@launchdarkly/ai-litellm-agents-0.2.0) (2026-10-26) ### ⚠ BREAKING CHANGES * forward the same model.parameters keys as the Python SDK ([#118](#118)) ### Features * add LiteLLM messages and agents integrations ([#75](#75)) ([127f156](127f156)) ### Bug Fixes * forward the same model.parameters keys as the Python SDK ([#118](#118)) ([f7883ce](f7883ce)) ### Dependencies * The following workspace dependencies were updated * dependencies * @launchdarkly/ai-server bumped from ^0.4.0 to ^0.5.0 </details> <details><summary>@launchdarkly/ai-litellm-messages: 0.2.0</summary> ## [0.2.0](https://github.com/launchdarkly/js-ai-sdk/compare/@launchdarkly/ai-litellm-messages-0.1.0...@launchdarkly/ai-litellm-messages-0.2.0) (2026-10-26) ### ⚠ BREAKING CHANGES * forward the same model.parameters keys as the Python SDK ([#118](#118)) ### Features * add LiteLLM messages and agents integrations ([#75](#75)) ([127f156](127f156)) ### Bug Fixes * forward the same model.parameters keys as the Python SDK ([#118](#118)) ([f7883ce](f7883ce)) ### Dependencies * The following workspace dependencies were updated * dependencies * @launchdarkly/ai-server bumped from ^0.4.0 to ^0.5.0 </details> <details><summary>@launchdarkly/ai-node: 0.4.0</summary> ## [0.4.0](https://github.com/launchdarkly/js-ai-sdk/compare/@launchdarkly/ai-node-0.3.0...@launchdarkly/ai-node-0.4.0) (2026-10-26) ### ⚠ BREAKING CHANGES * **skills:** promote Agent Skills to core ([#159](#159)) * **client:** the client no longer loads .env. Add import 'dotenv/config' to your entrypoint (and install dotenv) if you relied on it. ### Features * **skills:** promote Agent Skills to core ([#159](#159)) ([c7135cd](c7135cd)) ### Bug Fixes * **client:** stop loading dotenv from library code ([#69](#69)) ([fea34f3](fea34f3)) ### Dependencies * The following workspace dependencies were updated * dependencies * @launchdarkly/ai-server bumped from ^0.4.0 to ^0.5.0 </details> <details><summary>@launchdarkly/ai-openai-agents: 0.5.0</summary> ## [0.5.0](https://github.com/launchdarkly/js-ai-sdk/compare/@launchdarkly/ai-openai-agents-0.4.0...@launchdarkly/ai-openai-agents-0.5.0) (2026-10-26) ### ⚠ BREAKING CHANGES * forward the same model.parameters keys as the Python SDK ([#118](#118)) * **client:** the client no longer loads .env. Add import 'dotenv/config' to your entrypoint (and install dotenv) if you relied on it. ### Features * **AIC-3623:** evals from code ([#143](#143)) ([dc74b48](dc74b48)) ### Bug Fixes * **AIC-3571:** visit every child before its parent in reverseTraverse ([#147](#147)) ([a17a2ce](a17a2ce)) * **AIC-3577:** send object tool results to the model as JSON ([#146](#146)) ([be41d87](be41d87)) * **AIC-3586:** propagate tool handler errors instead of sending them to the model ([#139](#139)) ([1f31e85](1f31e85)) * **client:** stop loading dotenv from library code ([#69](#69)) ([fea34f3](fea34f3)) * forward the same model.parameters keys as the Python SDK ([#118](#118)) ([f7883ce](f7883ce)) * give native graph spans their LaunchDarkly identity ([#101](#101)) ([4d97cfa](4d97cfa)) ### Dependencies * The following workspace dependencies were updated * dependencies * @launchdarkly/ai-server bumped from ^0.4.0 to ^0.5.0 </details> <details><summary>@launchdarkly/ai-openai-messages: 0.5.0</summary> ## [0.5.0](https://github.com/launchdarkly/js-ai-sdk/compare/@launchdarkly/ai-openai-messages-0.4.0...@launchdarkly/ai-openai-messages-0.5.0) (2026-10-26) ### ⚠ BREAKING CHANGES * forward the same model.parameters keys as the Python SDK ([#118](#118)) * **client:** the client no longer loads .env. Add import 'dotenv/config' to your entrypoint (and install dotenv) if you relied on it. ### Features * **AIC-3623:** evals from code ([#143](#143)) ([dc74b48](dc74b48)) ### Bug Fixes * **AIC-3577:** send object tool results to the model as JSON ([#146](#146)) ([be41d87](be41d87)) * **client:** stop loading dotenv from library code ([#69](#69)) ([fea34f3](fea34f3)) * forward the same model.parameters keys as the Python SDK ([#118](#118)) ([f7883ce](f7883ce)) ### Dependencies * The following workspace dependencies were updated * dependencies * @launchdarkly/ai-server bumped from ^0.4.0 to ^0.5.0 </details> <details><summary>@launchdarkly/ai-otel: 0.3.0</summary> ## [0.3.0](https://github.com/launchdarkly/js-ai-sdk/compare/@launchdarkly/ai-otel-0.2.0...@launchdarkly/ai-otel-0.3.0) (2026-10-26) ### ⚠ BREAKING CHANGES * **client:** the client no longer loads .env. Add import 'dotenv/config' to your entrypoint (and install dotenv) if you relied on it. ### Bug Fixes * **client:** stop loading dotenv from library code ([#69](#69)) ([fea34f3](fea34f3)) </details> <details><summary>@launchdarkly/ai-server: 0.5.0</summary> ## [0.5.0](https://github.com/launchdarkly/js-ai-sdk/compare/@launchdarkly/ai-server-0.4.0...@launchdarkly/ai-server-0.5.0) (2026-10-26) ### ⚠ BREAKING CHANGES * **skills:** promote Agent Skills to core ([#159](#159)) * forward the same model.parameters keys as the Python SDK ([#118](#118)) * **client:** the client no longer loads .env. Add import 'dotenv/config' to your entrypoint (and install dotenv) if you relied on it. ### Experimental * **evaluations:** hash eventId and contentHash as RFC 8785 canonical JSON, the same in every SDK ([c971649](c971649)) * **evaluations:** Set JSON as standard for output to pass to judge ([#152](#152)) ([330da44](330da44)) ### Features * **AIC-3534:** add a TypeSafe Jev judge handler ([#122](#122)) ([0c1d6b7](0c1d6b7)) * **AIC-3623:** evals from code ([#143](#143)) ([dc74b48](dc74b48)) * **skills:** promote Agent Skills to core ([#159](#159)) ([c7135cd](c7135cd)) ### Bug Fixes * **AIC-3541:** accept a node-server-sdk client in initClient() without a cast ([#128](#128)) ([5819449](5819449)) * **AIC-3570:** re-resolve graph flags on every invoke and stream ([#145](#145)) ([ce4f72e](ce4f72e)) * **AIC-3571:** visit every child before its parent in reverseTraverse ([#147](#147)) ([a17a2ce](a17a2ce)) * **AIC-3576:** record deferred judge scores under the evaluated config ([#148](#148)) ([d9fbee6](d9fbee6)) * **AIC-3577:** send object tool results to the model as JSON ([#146](#146)) ([be41d87](be41d87)) * **AIC-3596:** point the missing-OTel warning and docs at @launchdarkly/ai-otel ([#144](#144)) ([9b5f32e](9b5f32e)) * **client:** show a judge an output of 0, false, {} or [] ([c971649](c971649)) * **client:** stop loading dotenv from library code ([#69](#69)) ([fea34f3](fea34f3)) * forward the same model.parameters keys as the Python SDK ([#118](#118)) ([f7883ce](f7883ce)) * give native graph spans their LaunchDarkly identity ([#101](#101)) ([4d97cfa](4d97cfa)) * **judges:** a judge config's outputFormat must not reach the provider ([#56](#56)) ([8c6f4d2](8c6f4d2)) * **skills:** Correct the HTTP 403 advice now that server-side FDv2 is available to every account ([#141](#141)) ([5b7b732](5b7b732)) * **skills:** default FDv2SkillStore endpoints from LD_BASE_URI and LD_STREAM_URI ([#134](#134)) ([05f77d9](05f77d9)) </details> <details><summary>@launchdarkly/ai-typesafe: 0.2.0</summary> ## [0.2.0](https://github.com/launchdarkly/js-ai-sdk/compare/@launchdarkly/ai-typesafe-0.1.0...@launchdarkly/ai-typesafe-0.2.0) (2026-10-26) ### ⚠ BREAKING CHANGES * forward the same model.parameters keys as the Python SDK ([#118](#118)) ### Features * **AIC-3534:** add a TypeSafe Jev judge handler ([#122](#122)) ([0c1d6b7](0c1d6b7)) * **AIC-3623:** evals from code ([#143](#143)) ([dc74b48](dc74b48)) ### Bug Fixes * forward the same model.parameters keys as the Python SDK ([#118](#118)) ([f7883ce](f7883ce)) ### Dependencies * The following workspace dependencies were updated * dependencies * @launchdarkly/ai-server bumped from ^0.4.0 to ^0.5.0 </details> <details><summary>@launchdarkly/ai-vercel-agents: 0.3.0</summary> ## [0.3.0](https://github.com/launchdarkly/js-ai-sdk/compare/@launchdarkly/ai-vercel-agents-0.2.0...@launchdarkly/ai-vercel-agents-0.3.0) (2026-10-26) ### ⚠ BREAKING CHANGES * forward the same model.parameters keys as the Python SDK ([#118](#118)) ### Features * **AIC-3623:** evals from code ([#143](#143)) ([dc74b48](dc74b48)) ### Bug Fixes * forward the same model.parameters keys as the Python SDK ([#118](#118)) ([f7883ce](f7883ce)) * give native graph spans their LaunchDarkly identity ([#101](#101)) ([4d97cfa](4d97cfa)) ### Dependencies * The following workspace dependencies were updated * dependencies * @launchdarkly/ai-server bumped from ^0.4.0 to ^0.5.0 </details> <details><summary>@launchdarkly/ai-vercel-messages: 0.3.0</summary> ## [0.3.0](https://github.com/launchdarkly/js-ai-sdk/compare/@launchdarkly/ai-vercel-messages-0.2.0...@launchdarkly/ai-vercel-messages-0.3.0) (2026-10-26) ### ⚠ BREAKING CHANGES * forward the same model.parameters keys as the Python SDK ([#118](#118)) ### Features * **AIC-3623:** evals from code ([#143](#143)) ([dc74b48](dc74b48)) ### Bug Fixes * forward the same model.parameters keys as the Python SDK ([#118](#118)) ([f7883ce](f7883ce)) ### Dependencies * The following workspace dependencies were updated * dependencies * @launchdarkly/ai-server bumped from ^0.4.0 to ^0.5.0 </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] > **Overview** > This is a **Release Please** cut that bumps published versions across the monorepo and records what ships in each package—there is no application source in the diff beyond `LD_AI_PACKAGE_VERSION` strings and dependency pins. > > **@launchdarkly/ai-server** goes to **0.5.0**; provider packages move to **0.5.0** (or **0.4.0** / **0.3.0** / **0.2.0** where applicable), `.release-please-manifest.json` is updated, and every adapter’s `package.json` now depends on **`@launchdarkly/ai-server` ^0.5.0**. New **CHANGELOG** sections document the release notes already merged on `main`. > > Reviewers should treat this as publishing **breaking** behavior called out in those changelogs: libraries no longer auto-load **`.env`** (apps need `import 'dotenv/config'` if they relied on it), **`model.parameters`** forwarding is aligned with the Python SDK, **Agent Skills** are promoted from experimental to core, plus features/fixes such as **evals from code**, TypeSafe judge handler, and **claude-agents** defaulting to no host settings unless `cwd` / `settingSources` are passed. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 8c6546c. 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.
Fixes AIC-3571.
Why
reverseTraverseis meant to visit every child before its parent, so adapters can build children first. It walked up breadth-first from the terminal nodes instead, so a parent was visited as soon as one child was. With root → P, P → T1, P → Q, Q → T2 the order was T1, T2, P, Q, root: P came before its child Q.toOpenAIAgentsthen threwChild agent "Q" was not built before parent "P", andtoClaudeAgentsbuilt P without Q's tool and said nothing. The Python adapters already use a post-order DFS (_reverse_traversein claude-agents,_visitin openai-agents); this PR makes core match.Fix
packages/client/src/graph.ts:reverseTraverseis now a post-order DFS from the root with a visited set. Each node is visited once, every child before its parent, root last. Same signature.packages/openai-agents/src/native-graph.ts: a child that is still unbuilt (only possible on a cycle back-edge now) is dropped with aconsole.warninstead of throwing.packages/claude-agents/src/native-graph.ts: the same case used to be dropped silently by.filter(Boolean). It now logs aconsole.warn.types.tsandAGENTS.mdno longer say "reverse BFS".Behaviour changes:
undefinedwithout visiting anything.Testing
yarn build,yarn typecheck,yarn code:check,yarn api:check(client): all pass.yarn test: 2335 passed, 11 skipped, 0 failed across 11 suites (openai-agents: 128 passed).resolveGraphandreverseTraverse(no mock), plus the cycle back-edge dropped with a warning. In claude-agents, the cycle back-edge warning.Qout of order), the openai-agents uneven test (Child agent "Q" was not built before parent "P"), and the claude-agents cycle test (no warning). The client cycle test also passes on the old code. It stays as a guard that each node is visited once.setGlobalTracerProvider: vi.fn()because the realinitClient(BYOC path) registers a tracer provider.Related: js #147 · python launchdarkly/python-ai-sdk#189 · go launchdarkly/go-ai-sdk#12 · spec https://github.com/launchdarkly/ai-sdks-monorepo/pull/73
🤖 Generated with Claude Code
Note
Overview
reverseTraversein the core client no longer walks upward breadth-first from leaves. It now does a post-order DFS from the root: each node is visited once, every descendant before its parent, root last. That matches Python adapters and fixes uneven graphs where a parent was visited before a deeper child (e.g.PbeforeQ), which broketoOpenAIAgentsand lefttoClaudeAgentswith missing child tools.Semantics shift: only nodes reachable from the root are visited; a graph with no leaves but a cycle from the root is traversed instead of returning without visiting anything.
Native graph adapters (
toOpenAIAgents,toClaudeAgents) drop cycle back-edges when the child agent/tool was not built yet, emitting[LaunchDarkly] Dropping cyclic edge "…" -> "…"viaconsole.warninstead of throwing (OpenAI) or failing silently (Claude).Docs/comments in
types.tsandAGENTS.mddescribe post-order rather than “reverse BFS.” Tests cover uneven depth order, single visit in cycles, and end-to-end adapter builds with realresolveGraph.Reviewed by Cursor Bugbot for commit 2fb274a. Bugbot is set up for automated code reviews on this repo. Configure here.