feat(AIC-3210): support graph().stream() in the Python AI SDK - #104
Merged
Merged
Conversation
…graph-streaming example Co-authored-by: Cursor <cursoragent@cursor.com>
…top claiming the global tracer CI on #104 failed three separate ways. All three are fixed here. 1. `stream_route` was added as a required keyword-only argument to `GraphDefinition.__init__`, which broke every direct construction of the type: 63 tests across claude-agents, langchain-agents and openai-agents failed with `TypeError: missing 1 required keyword-only argument`. Those packages consume a `GraphDefinition` but never build one outside tests, so the fix is at the source rather than in their helpers — none of their test files are touched. `_build_graph` now returns `stream_route` alongside the definition, mirroring `buildGraph`'s `{ def, graphTrackData, streamRoute }` in the JS SDK and keeping `resolve_graph()`'s contract stable. TESTING.md never lists stream_route on the GraphDefinition surface, and A.2's live-vs- disabled key parity still holds. 2. `test_graph_stream.py` called `trace.set_tracer_provider()` at import. That global is first-writer-wins, and claude-agents' `test_handler.py` already claims it at import and collects first alphabetically, so the new file's exporter received nothing and 6 OTel assertions failed on `0 >= 1`. The suite now patches `get_tracer` per test instead — `graph.py` imports `trace` inside its functions, so that is the seam. Both file orders now pass; previously each order broke whichever file lost the race. 3. The two new files were never formatted, failing `ruff format --check`. Verified locally: uv lock, ruff check, ruff format --check, mypy packages/*/src, uv run pytest (1328 passed, 11 skipped), and uv build for every package all exit 0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
jeffdupont
marked this pull request as ready for review
September 23, 2026 22:14
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort 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 b03ceb1. Configure here.
A timeout or task.cancel() was stamping launchdarkly.stream.abandoned on the graph span while handler spans recorded launchdarkly.run.cancelled. Co-authored-by: Cursor <cursoragent@cursor.com>
andrewklatzke
approved these changes
Sep 24, 2026
10 tasks
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.

Summary
graph().stream()with TypeScript-parity event shape (node_start/chunk/node_done/handoff/done), shared handoff routing withinvoke(), call-time conversation binding, andld.ai.graphOTel parenting (including alignedinvoke()span).test_graph_stream.py) and thegraph-streamingexample wired throughmain.py.__handoff_*tool wrappers sync so multi-edge routing can record the chosen edge without awaiting.Follow-ups
graph().stream()callers, so the examples stop hand-rolling the type dispatch: AIC-3465Test plan
pytest packages/client/tests/— 516 passed (the plan originally recorded 515; one more test is in the tree now)graph.pyandtracking.py— no issuesruff format --checkongraph.py,tracking.py,examples/graph_streaming.py, andmain.py— cleanpython main.py graph-streaming travel-agent-flow "I was double charged for my flight": exit 0, model text on stdout, one[conversation]line,[node_start]/[node_done]fortravel-agent-orchestrator, Usage input 892 / output 64 / total 956 matching that node. No handoff, which is valid for a single-node run. No JSON file. stderr had noRuntimeErrororaclosetravel-agent-flow-wrong-key: exit 1, oneError: Agent graph "travel-agent-flow-wrong-key" is disabled, no unhandled rejection, no JSON fileintegration-config.jsongraph-streaminguses those same keys (travel-agent-flow/travel-agent-flow-wrong-key). Nointegration-config-local.jsonoverride.main.pydispatchesgraph-streamingtoexamples.graph_streaming, and both keys were run against that exampleSpec:
TESTING.md§3.15a and Appendix A.13. TypeScript: launchdarkly/js-ai-sdk#84.Jira: AIC-3210