spike: gen_ai.conversation_root — native + OTel ingest paths#89
Draft
adityamehra wants to merge 3 commits into
Draft
spike: gen_ai.conversation_root — native + OTel ingest paths#89adityamehra wants to merge 3 commits into
adityamehra wants to merge 3 commits into
Conversation
…t paths Implements initial `gen_ai.conversation_root` detection for both the OTel and native (SplunkAOLogger) span ingestion routes, mirroring the approach from splunk-otel-python-contrib PR #236. OTel path (src/splunk_ao/otel.py): - Add GEN_AI_CONVERSATION_ROOT = "gen_ai.conversation_root" constant. - In start_splunk_ao_span(), capture whether the caller has a valid OTel parent span *before* entering the new span context. If no parent exists and the span is a WorkflowSpan or AgentSpan, set the attribute to True. Native path (src/splunk_ao/schema/logged.py, src/splunk_ao/logger/logger.py): - Add conversation_root: bool | None field to LoggedWorkflowSpan and LoggedAgentSpan for SDK-level introspection. - In add_workflow_span() and add_agent_span(), auto-detect the root: if the current parent is a LoggedTrace (not another GenAI span), set conversation_root=True and mirror it into user_metadata["gen_ai.conversation_root"] so it reaches the backend without requiring a schema migration. Example (examples/agent/langchain-agent-http/): - FastAPI HTTP wrapper around the langchain-agent example. - POST /invoke: single agent call (HTTP span → root WorkflowSpan). - POST /invoke/nested: two sequential agent calls (each trace gets its own root). - Verified end-to-end against rc0 (splunk-ao-rc0 env vars); both routes send traces with conversation_root correctly set. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
src/splunk_ao/otel.py): AddedGEN_AI_CONVERSATION_ROOT = "gen_ai.conversation_root"constant and root-detection instart_splunk_ao_span(). Root status is sampled before entering the new span context, so aWorkflowSpan/AgentSpanwith no valid OTel parent automatically receivesgen_ai.conversation_root = True.src/splunk_ao/schema/logged.py,src/splunk_ao/logger/logger.py):LoggedWorkflowSpanandLoggedAgentSpangain aconversation_root: bool | Nonefield.add_workflow_span()/add_agent_span()auto-detect the root by checking whethercurrent_parent()is aLoggedTrace; if so,conversation_root=Trueis set on the span and mirrored intouser_metadata["gen_ai.conversation_root"]as a bridge until the backend schema is updated.examples/agent/langchain-agent-http/): FastAPI HTTP wrapper around the LangChain agent example (mirrors PR #236 scenarios). Verified end-to-end against rc0.Reference
opentelemetry-util-genaireference implementationWorkflow/AgentInvocationspan is the conversation root if it has no immediate GenAI parent (OTel: no valid parentSpanContext; native: parent isLoggedTrace)What this spike establishes
start_splunk_ao_span)gen_ai.conversation_root = True(OTel attribute)add_workflow_span)current_parent()isLoggedTraceLoggedWorkflowSpan.conversation_root = True+user_metadata["gen_ai.conversation_root"] = "true"add_agent_span)current_parent()isLoggedTraceLoggedAgentSpan.conversation_root = True+user_metadata["gen_ai.conversation_root"] = "true"Test plan
WorkflowSpan(parent =LoggedTrace) →conversation_root=True✓ (verified locally)WorkflowSpan(parent = another span) →conversation_root=None✓ (verified locally)gen_ai.conversation_root=Trueattribute ✓ (verified via in-memory exporter)gen_ai.conversation_rootinuser_metadata✓ (manual run against rc0)user_metadatabridge valueTODOs before full implementation
tests/) covering root vs nested detection for both pathsSplunkAOCallback, LangGraph, CrewAI, etc.) — each framework callback's first GenAI span should be auto-detected as rootconversation_rootas a first-class field (currently bridged viauser_metadata)user_metadatabridge once backend schema is updatedMade with Cursor