Skip to content

[opentelemetry-instrumentation-genai-langchain] Propagate gen_ai.conversation.id across the LangChain invocation tree - #474

Open
sfc-gh-zeningchen wants to merge 2 commits into
open-telemetry:mainfrom
sfc-gh-zeningchen:conversation-id-propagation
Open

[opentelemetry-instrumentation-genai-langchain] Propagate gen_ai.conversation.id across the LangChain invocation tree#474
sfc-gh-zeningchen wants to merge 2 commits into
open-telemetry:mainfrom
sfc-gh-zeningchen:conversation-id-propagation

Conversation

@sfc-gh-zeningchen

@sfc-gh-zeningchen sfc-gh-zeningchen commented Aug 25, 2026

Copy link
Copy Markdown

Description

gen_ai.conversation.id only ever reached invoke_agent spans. Every chat
and invoke_workflow span was missing it, and WorkflowInvocation had no
conversation_id field at all, so a workflow root could not carry one even in
principle.

It was also applied in AgentInvocation._get_request_attributes, which runs
when the span finishes. The attribute was therefore absent for the entire life
of the span: no SpanProcessor.on_start could see it, and a child span could
not read it from its parent.

semconv defines gen_ai.conversation.id on three spans — inference,
invoke_agent, and invoke_workflow. All three now accept a conversation_id
and set it in the span's creation attributes. WorkflowInvocation gains the
field.

On the LangChain side, the callback handler resolves the id once per run from
the thread_id, session_id, or conversation_id metadata keys, and
_InvocationManager carries it down the invocation tree. Tool, retrieval, and
unclassified chain runs record it for their descendants without putting it on
their own spans, since semconv does not define the attribute for execute_tool
or retrieval. A model call nested under a tool still gets it.

Fixes #475

Type of change

  • Bug fix (non-breaking change which fixes an issue)

How has this been tested?

  • uv run tox -e py314-test-util-genai
  • uv run tox -e py314-test-instrumentation-genai-langchain-latest
  • uv run tox -e typecheck
  • uv run pre-commit run ruff --all-files
  • Live LangChain application, 12 scenarios covering agents, multi-tool
    loops, workflows, retrieval, streaming, and error paths. All 31 eligible
    spans (21 chat, 8 invoke_agent, 2 invoke_workflow) carried
    gen_ai.conversation.id; the 8 execute_tool and 1 retrieval spans
    did not, as intended.

New tests: conversation id on local agent, remote agent, and workflow spans in
util-genai, and its absence when none is supplied.
langchain/tests/test_conversation_id.py builds multi-span trees and asserts
inheritance, including through parents that do not carry the attribute
themselves. Resolution and precedence are covered in test_callback_handler.py,
test_invocation_manager.py, and test_tools.py.

Checklist

See CONTRIBUTING.md
for the style guide, changelog guidance, and more.

  • Followed the style guidelines of this project
  • Changelog updated if the change requires an entry
  • Unit tests added
  • Documentation updated

gen_ai.conversation.id reached invoke_agent spans only, leaving it blank on
the model-call, tool and workflow rows where users look for it first. It was
also applied when the agent span finished, too late for a child span to read
it off its parent at start.

util-genai now accepts conversation_id on the three invocation types semconv
defines the attribute for -- inference, agent and workflow -- and sets it in
the span's creation attributes, so it is available for sampling decisions and
readable while the span is open. WorkflowInvocation gains the field, which it
did not have at all.

The LangChain callback handler resolves the id once per run from the
thread_id, session_id or conversation_id metadata keys, and _InvocationManager
carries it down the invocation tree. Tool, retrieval and span-less chain runs
track it for their descendants even though their own spans do not carry it,
since semconv does not define the attribute for those operations.
Copilot AI lite review requested due to automatic review settings August 25, 2026 05:53
@sfc-gh-zeningchen
sfc-gh-zeningchen requested a review from a team as a code owner August 25, 2026 05:53
@opentelemetry-pr-dashboard

opentelemetry-pr-dashboard Bot commented Aug 25, 2026

Copy link
Copy Markdown

Pull request dashboard status

Waiting on reviewers · refreshed 2026-08-25 21:19 UTC

Review the latest changes.

Status above doesn't look right?
  • Just replied or pushed? Anything around or after the refresh time above may not be picked up yet — give it a few minutes.
  • Anything look wrong? Report it with what you expected; it helps us improve the dashboard.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request fixes propagation of gen_ai.conversation.id through LangChain callback-driven invocation trees by (a) adding conversation_id to the GenAI util invocation types that semconv defines it for (inference/agent/workflow) and setting it at span creation time, and (b) resolving/inheriting the id per LangChain run via _InvocationManager so descendants receive it even when intermediate nodes do not emit it on their own spans.

Changes:

  • Add conversation_id support to InferenceInvocation, AgentInvocation, and WorkflowInvocation, and thread it through TelemetryHandler factory methods so it is present in sampling attributes at span start.
  • Extend LangChain _InvocationManager to track/inherit conversation id across run nodes (including span-less nodes), and add callback handler resolution precedence (thread_id > session_id > conversation_id).
  • Add/extend unit and integration tests in both opentelemetry-util-genai and the LangChain instrumentation to assert correct resolution, inheritance, and omission on spans where semconv does not define the attribute.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated no comments.

Show a summary per file
File Description
util/opentelemetry-util-genai/src/opentelemetry/util/genai/handler.py Threads conversation_id through inference/agent/workflow factory methods so it’s applied at span creation time.
util/opentelemetry-util-genai/src/opentelemetry/util/genai/_inference_invocation.py Stores conversation_id and includes it in start-time sampling attributes and finish attributes.
util/opentelemetry-util-genai/src/opentelemetry/util/genai/_agent_invocation.py Stores conversation_id from constructor and includes it in start-time sampling attributes (and request attributes).
util/opentelemetry-util-genai/src/opentelemetry/util/genai/_workflow_invocation.py Adds conversation_id to the workflow invocation and sets it at span start (and on finish).
util/opentelemetry-util-genai/tests/test_utils.py Adds assertions that inference spans include conversation id when provided and omit it when not supplied.
util/opentelemetry-util-genai/tests/test_handler_agent.py Adds coverage that agent conversation id is set at construction time and omitted when not provided.
util/opentelemetry-util-genai/tests/test_handler_workflow.py Adds coverage that workflow conversation id is present at construction time and omitted when not provided.
instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/invocation_manager.py Extends invocation state to track/inherit conversation id across parent/child run ids.
instrumentation/opentelemetry-instrumentation-genai-langchain/src/opentelemetry/instrumentation/genai/langchain/callback_handler.py Resolves conversation id once per run from metadata with precedence and propagates it through _InvocationManager; passes it only to semconv-eligible spans.
instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_invocation_manager.py Adds unit tests for storing, inheriting, overriding, and querying conversation id.
instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_callback_handler.py Adds unit tests asserting conversation id resolution/inheritance and correct wiring into telemetry handler calls.
instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_tools.py Adds tests verifying tool spans omit the attribute while still tracking it for descendant inheritance.
instrumentation/opentelemetry-instrumentation-genai-langchain/tests/test_conversation_id.py New integration-style tests building multi-span trees and asserting correct attribute inheritance/omission behavior.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@sfc-gh-zeningchen sfc-gh-zeningchen changed the title Propagate gen_ai.conversation.id across the LangChain invocation tree [opentelemetry-instrumentation-genai-langchain] Propagate gen_ai.conversation.id across the LangChain invocation tree Aug 25, 2026
@sfc-gh-zeningchen sfc-gh-zeningchen changed the title [opentelemetry-instrumentation-genai-langchain] Propagate gen_ai.conversation.id across the LangChain invocation tree [opentelemetry-instrumentation-genai-langchain] Propagate gen_ai.conversation.id across the LangChain invocation tree Aug 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

langchain: gen_ai.conversation.id is set only on invoke_agent spans

2 participants