-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Open
Labels
Description
Describe the bug
Voice agents sample code ends trace early and creates multiple 'parent' spans (spans with parent_id=None).
Note in the screenshot above:
voice_agent_workflowis manually created wrapper trace to display the output on the same chart- Voice Agent should be the root trace, however the invoke_agent spans are NOT nested below it
- Voice Agent trace ends after first interaction/turn, when it should last the entire conversation
Debug information
- Agents SDK version: 0.8.3
- Python version: 3.13.7
Repro steps
Use the Voice agents sample code, modified with:
from agents.tracing import TracingProcessor, set_trace_processors
import logging
logging.basicConfig(level=logging.DEBUG)
class DebugTracingProcessor(TracingProcessor):
def __init__(self):
super().__init__()
self.logger = logging.getLogger(__name__)
self.trace_stack = [] # Track trace hierarchy
self.root_trace_id = None
def _filter(self, span: dict[str, Any] | None) -> dict[str, Any] | None:
if span is None:
return {}
# filter out span_data.input.data to avoid logging large audio data
span_data = span.get("span_data", {})
input_data = span_data.get("input")
if isinstance(input_data, dict) and "data" in input_data:
span["span_data"]["input"]["data"] = "[filtered]"
output_data = span_data.get("output")
if isinstance(output_data, dict) and "data" in output_data:
span["span_data"]["output"]["data"] = "[filtered]"
return span
def on_trace_start(self, trace):
trace_export = trace.export()
trace_id = trace_export.get("id")
# Track the first trace as root
if self.root_trace_id is None:
self.root_trace_id = trace_id
self.logger.debug("ROOT Trace start: %s", trace_export)
else:
self.logger.debug("NESTED Trace start (should be span): %s", trace_export)
self.trace_stack.append(trace_id)
def on_trace_end(self, trace):
trace_export = trace.export()
trace_id = trace_export.get("id")
if trace_id in self.trace_stack:
self.trace_stack.remove(trace_id)
# Only log trace end for the root trace
if trace_id == self.root_trace_id and len(self.trace_stack) == 0:
self.logger.debug("ROOT Trace end: %s", trace_export)
self.root_trace_id = None
else:
self.logger.debug("NESTED Trace end (premature?): %s", trace_export)
def on_span_start(self, span):
span_export = self._filter(span.export())
self.logger.debug("Span start: %s", span_export)
def on_span_end(self, span):
span_export = self._filter(span.export())
self.logger.debug("Span end: %s", span_export)
def shutdown(self):
self.logger.debug("DebugTracingProcessor shutdown called")
def force_flush(self):
self.logger.debug("DebugTracingProcessor force_flush called")
set_trace_processors([DebugTracingProcessor()])You should see logs after the first transcription request such as
DEBUG:__main__:ROOT Trace end: {'object': 'trace', 'id': 'trace_02c45c282ea34f4f86bf1702d37d3e2c', 'workflow_name': 'Voice Agent', 'group_id': 'group_554afae4eb054c84bb56cb51', 'metadata': None}
DEBUG:openai.agents:Resetting current trace
DEBUG:openai.agents:Creating span <agents.tracing.span_data.AgentSpanData object at 0x112e9e170> with id None
DEBUG:__main__:Span start: {'object': 'trace.span', 'id': 'span_fafab093c3a34f848d5ad7b7', 'trace_id': 'trace_02c45c282ea34f4f86bf1702d37d3e2c', 'parent_id': None, 'started_at': '2026-02-11T06:37:55.103214+00:00', 'ended_at': None, 'span_data': {'type': 'agent', 'name': 'Assistant', 'handoffs': ['Spanish'], 'tools': None, 'output_type': 'str'}, 'error': None}
DEBUG:openai.agents:Starting turn 1, current_agent=Assistant
DEBUG:openai.agents:No conversation_id available for request
Expected behavior
- Root trace does not finish until end of conversation
- Child spans all have the root trace as their parent
Reactions are currently unavailable