open-telemetry / open-telemetry/opentelemetry-python-genai

openai-agents: run context does not propagate to spans owned by the model SDK instrumentation

Open
#725 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
Python
Stars
39
Forks
63
Avg merge
1d 15h
Merged PRs (30d)
175

Description

Describe your environment

OS: Amazon Linux 2023
Python version: Python 3.14.7
Package version: opentelemetry-instrumentation-genai-openai-agents 1.2b0.dev0, opentelemetry-instrumentation-genai-openai 1.2b0.dev0, opentelemetry-util-genai 1.2b0.dev0 (reproduces on main @ c6b63bd)
GenAI library (e.g. anthropic, openai) and version: openai-agents 0.22.2, openai 3.13.0

What happened?

A trace of an agents run is produced by two independent instrumentation
packages. opentelemetry-instrumentation-genai-openai-agents owns
invoke_workflow, invoke_agent and execute_tool; the chat span is owned by
whichever model SDK instrumentation is installed —
opentelemetry-instrumentation-genai-openai on the default path, or
...-anthropic and friends when the run is routed through LiteLLM, any-llm, or
a caller-supplied Model.

There is no channel between them. Anything the agents instrumentation learns
from the framework stops at the spans it owns, and the model SDK
instrumentation, which only sees an HTTP call to a provider, cannot learn it.
OTel's Span API is write-only, so it cannot read the value off its parent span
either.

gen_ai.conversation.id is the case where this bites today. The agents library
carries a chat-thread identifier on Trace.group_id, set through
RunConfig(group_id=...) or trace(..., group_id=...), and semconv defines the
attribute as conditionally required on inference, invoke_agent and
invoke_workflow. The agents instrumentation receives the Trace in
on_trace_start and ignores group_id, so no span carries the attribute today
— but only the invoke_workflow and invoke_agent halves are a local
oversight. The chat span is unreachable by construction, and that is the part
that needs a decision.

Steps to Reproduce
import asyncio

from agents import Agent, Runner
from agents.run import RunConfig

from opentelemetry.instrumentation.genai.openai import OpenAIInstrumentor
from opentelemetry.instrumentation.genai.openai_agents import (
    OpenAIAgentsInstrumentor,
)
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import SimpleSpanProcessor
from opentelemetry.sdk.trace.export.in_memory_span_exporter import (
    InMemorySpanExporter,
)

exporter = InMemorySpanExporter()
provider = TracerProvider()
provider.add_span_processor(SimpleSpanProcessor(exporter))
OpenAIInstrumentor().instrument(tracer_provider=provider)
OpenAIAgentsInstrumentor().instrument(tracer_provider=provider)

agent = Agent(name="triage", instructions="Answer briefly.", model="gpt-4o-mini")
asyncio.run(
    Runner.run(
        agent,
        "What colour is the sky?",
        run_config=RunConfig(
            workflow_name="probe-workflow", group_id="chat-thread-1"
        ),
    )
)

for span in exporter.get_finished_spans():
    print(span.name, span.attributes.get("gen_ai.conversation.id"))
Expected Result
chat gpt-4o-mini chat-thread-1
invoke_agent triage chat-thread-1
invoke_workflow probe-workflow chat-thread-1
Actual Result
chat gpt-4o-mini None
invoke_agent triage None
invoke_workflow probe-workflow None
Additional context

LangChain hit the same symptom in #474 (issue #475), but not the same problem:
LangChain is a single package that owns its whole tree and merges a run's config
metadata into every descendant, so each callback resolves the id from its own
metadata. Here the value has to cross a package boundary. The agents library
offers nothing to cross it with — group_id lives only on the Trace, and none
of the 14 types in agents.tracing.span_data exposes it.

Would you like to implement a fix?

Yes

Tip

React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding +1 or me too, to help us triage it. Learn more here.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the agents instrumentation's on_trace_start handling of Trace and the agents.tracing.span_data types, then inspect how the OpenAI and other model SDK instrumentations create chat spans. Determine a supported way to carry group_id across the package boundary, and verify that the expected conversation ID appears on invoke_workflow, invoke_agent, and chat spans without breaking alternate model paths.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
observability-sre
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.