fix(openai-agents): preserve structural span ancestry - #9674
Conversation
OpenAI Agents 0.14 adds untraced task and turn spans to the default hierarchy. Track those parent links so traced descendants resolve to the nearest Datadog span and errored workflows finish correctly.
Overall package sizeSelf size: 7.86 MB Dependency sizes| name | version | self size | total size | |------|---------|-----------|------------| | import-in-the-middle | 3.3.3 | 125.43 kB | 441.68 kB | | opentracing | 0.14.7 | 194.81 kB | 194.81 kB | | dc-polyfill | 0.1.11 | 25.74 kB | 25.74 kB |🤖 This report was automatically generated by heaviest-objects-in-the-universe |
🎉 All green!🧪 All tests passed 🎯 Code Coverage (details) 🔗 Commit SHA: 1771d9e | Docs | Datadog PR Page | Give us feedback! |
BenchmarksBenchmark execution time: 2026-08-05 17:56:10 Comparing candidate commit 1771d9e in PR branch Found 0 performance improvements and 0 performance regressions! Performance is the same for 2315 metrics, 43 unstable metrics.
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #9674 +/- ##
==========================================
- Coverage 98.53% 98.52% -0.02%
==========================================
Files 955 963 +8
Lines 133293 136017 +2724
Branches 11401 11575 +174
==========================================
+ Hits 131340 134006 +2666
- Misses 1953 2011 +58 Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Retain ended task and turn nodes only while observed descendants remain active, preserving delayed callback ancestry without keeping every completed turn. Benchmark (100k turns, 5 trials, repeated in fresh processes): - turn lifecycle: 9.9-10.2ms -> 7.8-8.1ms - retained heap: 17.26MB -> effectively zero - 100 cross-trace cleanups: 69-71ms -> 0.07ms
Cover concurrent children, retained duplicate ends, and the 32/33-level cleanup boundary. Remove the cleanup walk cap because each iteration deletes a node, which makes pruning self-terminating even when parent links contain a cycle.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cc076401d4
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if (info) { | ||
| info.completionRequested = true | ||
| if (info.activeSpanCount > 0) return | ||
| } |
There was a problem hiding this comment.
Restore LLMObs context while deferring workflow finish
When an earlier agents-core processor delays onSpanEnd (the case this path is meant to handle, e.g. an exporter flush), this returns from onTraceEnd with llmobsStorage still entered on the workflow span until the delayed child callback eventually completes. withTrace can then resolve and user code immediately after Runner.run() in the same async context may create unrelated LLMObs spans as children of the pending workflow; restore info.llmobsParentStore when completion is requested even if finishing the workflow span must wait for activeSpanCount to reach zero.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Addressed in 1771d9e: restored the saved LLMObs parent store on the first workflow completion request, before returning for active children, and stopped restoring it from the delayed child callback context. Added regression coverage that preserves a newer unrelated context when the child completes.
| info.ended = true | ||
| this.#pruneUntracedSpan(oaiSpan.spanId, info) | ||
| this.#spanEnded(info.traceId) |
There was a problem hiding this comment.
Finish workflows when structural root spans error
When @openai/agents 0.14 fails before an agent span exists, for example Runner.run(..., { maxTurns: 0 }), agents-core sets the error on the root task span and does not emit onTraceEnd on the thrown path. Because task/turn ends now go through this structural path instead of endSpan, the orphan-recovery logic for errored top-level spans is skipped, so this only prunes/counts down and leaves the workflow Datadog span open/unreported. Please request workflow completion for errored top-level structural spans as well.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Addressed in 1771d9e: errored top-level structural spans now request workflow completion before ancestry pruning and active-span countdown. Added regression coverage for a root task failing before any agent starts, including workflow error tags and completion.
sabrenner
left a comment
There was a problem hiding this comment.
code overall lgtm! would just be nice to see a screenshot of an llmobs span from a sample app using this just to confirm it still looks ok, otherwise im good to approve
* fix(openai-agents): preserve structural span ancestry - OpenAI Agents 0.14 adds untraced task and turn spans to the default hierarchy. Track those parent links so traced descendants resolve to the nearest Datadog span and errored workflows finish correctly.
* fix(openai-agents): preserve structural span ancestry - OpenAI Agents 0.14 adds untraced task and turn spans to the default hierarchy. Track those parent links so traced descendants resolve to the nearest Datadog span and errored workflows finish correctly.
* fix(openai-agents): preserve structural span ancestry - OpenAI Agents 0.14 adds untraced task and turn spans to the default hierarchy. Track those parent links so traced descendants resolve to the nearest Datadog span and errored workflows finish correctly.
* fix(openai-agents): preserve structural span ancestry - OpenAI Agents 0.14 adds untraced task and turn spans to the default hierarchy. Track those parent links so traced descendants resolve to the nearest Datadog span and errored workflows finish correctly.
What does this PR do?
Updates the OpenAI Agents integration for the structural
taskandturnspans enabled by default in@openai/agents0.14.The plugin continues to omit Datadog spans for those structural nodes. Instead, it records their parent links and resolves descendants to the nearest traced ancestor. This preserves:
It also bumps the three
@openai/agents*test dependencies to 0.14.1 and adds regression coverage for both the 0.14 hierarchy and the pre-0.14 flat hierarchy.Motivation
Dependabot PR #9642 exposed four deterministic failures in the
openai-agentsActions job.@openai/agents0.14 changed the hierarchy fromtrace → agent → ...totrace → task → agent → turn → .... Becausetaskandturnare intentionally untraced, direct parent lookup treated their traced descendants as children of the workflow and could not recover the top-level agent when finalizing an errored workflow.This preserves the new structural ancestry without adding customer-visible spans or weakening existing assertions.
Additional Notes
Validation:
openai-agentsplugin suite: 73 passing, 0 failinggit diff --check: passingnpm run verify:supported-integrationsalso detects unrelated pre-existing drift onmaster(25 stale dependency rows plus Node/runtime rows). This PR intentionally updates only the generated@openai/agentsrow to 0.14.1.