feat: add support for openai agents#161
feat: add support for openai agents#161minimAluminiumalism wants to merge 7 commits intoalibaba:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new LoongSuite/OpenTelemetry instrumentation package for the OpenAI Agents SDK by registering a custom TracingProcessor that converts SDK trace/span callbacks into OTel spans using GenAI semantic conventions.
Changes:
- Introduces
OTelTracingProcessorto translate OpenAI Agents SDK spans/traces into OpenTelemetry spans. - Adds an
OpenAIAgentsInstrumentorthat registers/unregisters the processor via the SDK tracing API. - Adds packaging/docs/tests scaffolding for the new instrumentation distribution.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| instrumentation-loongsuite/loongsuite-instrumentation-openai-agents/src/opentelemetry/instrumentation/openai_agents/_processor.py | Implements the SDK TracingProcessor bridge and span translation logic. |
| instrumentation-loongsuite/loongsuite-instrumentation-openai-agents/src/opentelemetry/instrumentation/openai_agents/init.py | Implements the instrumentor that registers/unregisters the tracing processor. |
| instrumentation-loongsuite/loongsuite-instrumentation-openai-agents/src/opentelemetry/instrumentation/openai_agents/package.py | Declares instrumented dependency metadata for the distribution. |
| instrumentation-loongsuite/loongsuite-instrumentation-openai-agents/src/opentelemetry/instrumentation/openai_agents/version.py | Adds package version for hatch dynamic versioning. |
| instrumentation-loongsuite/loongsuite-instrumentation-openai-agents/tests/test_processor.py | Unit tests validating span creation/attributes for supported SDK span types. |
| instrumentation-loongsuite/loongsuite-instrumentation-openai-agents/tests/test_instrumentor.py | Tests instrumentor lifecycle and processor registration. |
| instrumentation-loongsuite/loongsuite-instrumentation-openai-agents/tests/conftest.py | Pytest fixtures + env configuration for GenAI semconv/content capture. |
| instrumentation-loongsuite/loongsuite-instrumentation-openai-agents/tests/init.py | Marks tests as a package (license header only). |
| instrumentation-loongsuite/loongsuite-instrumentation-openai-agents/tests/requirements.oldest.txt | Pins oldest supported openai-agents version for test matrix. |
| instrumentation-loongsuite/loongsuite-instrumentation-openai-agents/tests/requirements.latest.txt | Uses latest openai-agents for test matrix. |
| instrumentation-loongsuite/loongsuite-instrumentation-openai-agents/README.rst | Adds end-user installation/usage documentation. |
| instrumentation-loongsuite/loongsuite-instrumentation-openai-agents/pyproject.toml | Adds build metadata, deps, and entry point registration. |
| instrumentation-loongsuite/loongsuite-instrumentation-openai-agents/CHANGELOG.md | Introduces initial changelog entry for the new package. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| try: | ||
| from agents.tracing.setup import ( # noqa: PLC0415 | ||
| get_trace_provider, | ||
| ) | ||
|
|
||
| provider = get_trace_provider() | ||
| if hasattr(provider, "_multi_processor"): | ||
| mp = provider._multi_processor | ||
| if hasattr(mp, "_processors"): | ||
| procs = mp._processors | ||
| if processor in procs: | ||
| procs.remove(processor) | ||
| except Exception as e: | ||
| logger.debug("Failed to remove processor: %s", e) | ||
|
|
There was a problem hiding this comment.
_uninstrument() removes the processor by reaching into private SDK internals (provider._multi_processor._processors). This is brittle across SDK versions and may silently fail (leaving the processor registered and causing duplicate spans on re-instrumentation). If the Agents SDK provides a public removal API, prefer that; otherwise consider making the failure mode explicit (e.g., warn once) and/or add defensive checks around processor duplication on _instrument().
| try: | |
| from agents.tracing.setup import ( # noqa: PLC0415 | |
| get_trace_provider, | |
| ) | |
| provider = get_trace_provider() | |
| if hasattr(provider, "_multi_processor"): | |
| mp = provider._multi_processor | |
| if hasattr(mp, "_processors"): | |
| procs = mp._processors | |
| if processor in procs: | |
| procs.remove(processor) | |
| except Exception as e: | |
| logger.debug("Failed to remove processor: %s", e) | |
| removed = False | |
| # Prefer a public removal API from the Agents SDK if available. | |
| try: | |
| from agents.tracing import ( # type: ignore[attr-defined] # noqa: PLC0415 | |
| remove_trace_processor, | |
| ) | |
| except Exception: # ImportError or absence of public API | |
| remove_trace_processor = None # type: ignore[assignment] | |
| if remove_trace_processor is not None: # type: ignore[truthy-function] | |
| try: | |
| remove_trace_processor(processor) # type: ignore[call-arg] | |
| removed = True | |
| except Exception as e: | |
| logger.warning( | |
| "Failed to remove OpenAI Agents tracing processor via " | |
| "public API: %s. Falling back to SDK internals.", | |
| e, | |
| ) | |
| # Fallback: best-effort removal via SDK internals, with explicit warnings | |
| if not removed: | |
| try: | |
| from agents.tracing.setup import ( # noqa: PLC0415 | |
| get_trace_provider, | |
| ) | |
| provider = get_trace_provider() | |
| if hasattr(provider, "_multi_processor"): | |
| mp = provider._multi_processor | |
| if hasattr(mp, "_processors"): | |
| procs = mp._processors | |
| if processor in procs: | |
| procs.remove(processor) | |
| removed = True | |
| if not removed: | |
| logger.warning( | |
| "OpenAI Agents tracing processor could not be " | |
| "located in the trace provider; it may still be " | |
| "registered, which can lead to duplicate spans on " | |
| "re-instrumentation." | |
| ) | |
| except Exception as e: | |
| logger.warning( | |
| "Failed to remove OpenAI Agents tracing processor via " | |
| "trace provider internals; the processor may still be " | |
| "registered, which can lead to duplicate spans on " | |
| "re-instrumentation: %s", | |
| e, | |
| ) |
There was a problem hiding this comment.
The OpenAI Agents SDK does not expose a public API to remove a trace processor. add_trace_processor exists but there is no corresponding remove_trace_processor.
The private attribute fallback with hasattr guards is the only viable approach.
| "OTEL_SEMCONV_STABILITY_OPT_IN", "gen_ai_latest_experimental" | ||
| ) | ||
| os.environ.setdefault( | ||
| "OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT", "true" |
There was a problem hiding this comment.
OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT should be set as SPAN_ONLY.
527e2cf to
d73a674
Compare
|
This PR has been automatically marked as stale because it has not had any activity for 14 days. It will be closed if no further activity occurs within 14 days of this comment. |
Adds openai-agents test/lint envs to tox-loongsuite.ini (envlist, deps, commands) and regenerates the loongsuite workflow YAMLs via `tox -e generate-workflows`, addressing Cirilla-zmh's review request on tests/test_instrumentor.py.
…gent into feat/openai-agents Resolves tox-loongsuite.ini conflict: keeps the openai-agents test/lint deps block and adopts upstream's renamed `agno`/`dify`/`mem0`/etc. deps keys (the `loongsuite-` prefix was dropped on main). Regenerates the loongsuite workflow YAMLs from the resolved tox config.
Description
Add OpenTelemetry instrumentation for the OpenAI Agents SDK, addressing #47.
The OpenAI Agents SDK ships with a built-in
TracingProcessorcallback interface that fires on every agent run, LLM call, and tool execution, etc. Instead of monkey-patching, this instrumentation registers a custom OTelTracingProcessor viaadd_trace_processor()that translates SDK spans into OTel spans following the GenAI semconv.Implementation ref https://github.com/traceloop/openllmetry/tree/main/packages/opentelemetry-instrumentation-openai-agents
Type of change
Please delete options that are not relevant.
How Has This Been Tested?
Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration
Does This PR Require a Core Repo Change?
Checklist:
See contributing.md for styleguide, changelog guidelines, and more.