Prototype showing gen_ai.conversation_root span attribute to mark the root GenAI span of a conversation - #187
Prototype showing gen_ai.conversation_root span attribute to mark the root GenAI span of a conversation#187wrisa wants to merge 3 commits into
Conversation
|
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. |
Pull request dashboard statusWaiting on the author · refreshed 2026-08-04 14:20 UTC Respond to 5 review items (e.g. link a commit, explain why not, ask a follow-up): Status above doesn't look right?
|
There was a problem hiding this comment.
Pull request overview
Adds a prototype mechanism in opentelemetry-util-genai to mark the outermost conversation-level GenAI span via a new boolean span attribute (gen_ai.conversation_root) on workflow and agent invocations, using an OTel context-scoped attribute marker to detect/propgate “root-ness” without relying on span parentage.
Changes:
- Introduces a
context_attributeshelper module to store “context-scoped attributes” in the OTel context with outermost-writer-wins semantics. - Extends
GenAIInvocation._start()to optionally attach a pre-enriched context alongside the span; emitsgen_ai.conversation_rootwhen set on the invocation. - Adds workflow/agent root auto-detection + propagation and corresponding unit tests.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| util/opentelemetry-util-genai/src/opentelemetry/util/genai/context_attributes.py | New CSA helper for storing/reading GenAI context-scoped attributes. |
| util/opentelemetry-util-genai/src/opentelemetry/util/genai/_invocation.py | Adds conversation_root field, supports extra_context during span attach, emits the span attribute. |
| util/opentelemetry-util-genai/src/opentelemetry/util/genai/_workflow_invocation.py | Detects/propagates conversation root marker for workflow spans. |
| util/opentelemetry-util-genai/src/opentelemetry/util/genai/_agent_invocation.py | Detects/propagates conversation root marker for agent spans. |
| util/opentelemetry-util-genai/tests/test_context_attributes.py | Unit tests for CSA helper semantics (merge + defaults). |
| util/opentelemetry-util-genai/tests/test_handler_workflow.py | Adds workflow-level tests for conversation root detection/emission. |
| util/opentelemetry-util-genai/tests/test_handler_agent.py | Adds agent-level tests for conversation root detection/emission. |
| from opentelemetry.util.genai.context_attributes import ( | ||
| get_context_scoped_attributes, | ||
| set_context_scoped_attributes, | ||
| ) |
| if self.conversation_root is not None: | ||
| self.span.set_attribute( | ||
| "gen_ai.conversation_root", self.conversation_root | ||
| ) |
| from unittest.mock import patch | ||
| from opentelemetry.util.genai.types import ContentCapturingMode |
|
Hi @wrisa — just a friendly reminder that this pull request is waiting on you. There are still items that need your attention. See the dashboard status comment for the full list. You don't need to push a code change to hand it back — replying to move each discussion forward is enough, whether that's answering a question, explaining why no change is needed, or asking a follow-up. The dashboard then automatically routes it back to reviewers. If you believe this pull request is incorrectly routed as waiting on the author, comment |
| # non-GenAI parents (HTTP, gRPC, etc.) — unlike checking OTel span | ||
| # parentage directly. | ||
| csa = get_context_scoped_attributes() | ||
| if "gen_ai.conversation_root" not in csa: |
There was a problem hiding this comment.
I might have missed the discussion for this but is this in genai semconv? If this is a prototype to drive semantic conventions, should this be gated/opt-in?
| @@ -0,0 +1,69 @@ | |||
| # Copyright The OpenTelemetry Authors | |||
There was a problem hiding this comment.
This file should probably be internal?
Description
Fixes # (issue356)
``
Adds
gen_ai.conversation_rootas a boolean span attribute automatically set on `WorkflowInvocation` and `AgentInvocation` spans that are the outermost GenAI span in a trace — i.e., the entry point of a conversation.Detection uses a context-scoped attribute key (following the API shape of open-telemetry/opentelemetry-specification#4931) stored under a private OTel context key rather than raw OTel span parentage. This correctly handles the common production case where a GenAI root span lives under a non-GenAI parent (HTTP, gRPC, queue consumer, etc.) — a plain OTel parent span never writes the key, so it never suppresses conversation_root.
Design
Context-scoped attribute key
A private OTel context key is used to propagate a
gen_ai.conversation_rootmarker through the OTel context:set_context_scoped_attributes uses existing-key-wins semantics (outermost writer wins), matching the CSA spec. This means once the root sets the key, any nested
WorkflowInvocationorAgentInvocationsees it already present and does not mark itself as root.Auto-detection in
WorkflowInvocationandAgentInvocationBefore _start():
Propagate the key so nested invocations do not mark themselves root
The key is attached alongside the span in a single attach() call and automatically detached when the invocation ends (same lifecycle as the span context token), so the next independent conversation starts fresh.
Emission
In GenAIInvocation._finish():
Only emitted when explicitly set — None means "not applicable" and produces no attribute.
Scope
Only
WorkflowInvocationandAgentInvocationparticipate in root detection.InferenceInvocation(chat),ToolInvocation(execute_tool),EmbeddingInvocation, andRetrievalInvocationnever set conversation_root — even when called at the top level with no GenAI parent — because they represent model/tool operations, not conversation-level entry points.Example traces
Agent under HTTP span (common production case):
Workflow wrapping agents:
What this does NOT do
Relation to prior art
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. List any relevant details for your test
configuration.
Checklist
See CONTRIBUTING.md
for the style guide, changelog guidance, and more.