0
# Tracing
1
2
The SDK includes built-in distributed tracing that automatically tracks all agent operations, providing visibility into workflow execution, performance, and debugging capabilities. Traces consist of spans for each operation (LLM calls, tool executions, handoffs, etc.) and can be exported to external observability platforms.
3
4
## Capabilities
5
6
### Trace
7
8
Top-level trace object representing an entire workflow.
9
10
```python { .api }
11
class Trace:
12
"""
13
Trace object for workflow.
14
15
Attributes:
16
- trace_id: str - Unique trace identifier
17
- name: str - Trace name (workflow name)
18
- group_id: str | None - Grouping identifier
19
- metadata: dict[str, Any] | None - Additional metadata
20
"""
21
22
def start(mark_as_current: bool = True) -> None:
23
"""
24
Start trace.
25
26
Parameters:
27
- mark_as_current: Set as current active trace
28
"""
29
30
def finish(reset_current: bool = True) -> None:
31
"""
32
Finish trace.
33
34
Parameters:
35
- reset_current: Clear current trace reference
36
"""
37
38
def trace(
39
workflow_name: str,
40
*,
41
trace_id: str | None = None,
42
group_id: str | None = None,
43
metadata: dict[str, Any] | None = None,
44
disabled: bool = False
45
) -> Trace:
46
"""
47
Create new trace.
48
49
Parameters:
50
- workflow_name: Name for the trace
51
- trace_id: Custom trace ID (auto-generated if None)
52
- group_id: Group identifier for related traces
53
- metadata: Additional trace metadata
54
- disabled: Whether tracing is disabled
55
56
Returns:
57
- Trace: Configured trace object
58
"""
59
```
60
61
Usage example:
62
63
```python
64
from agents.tracing import trace
65
66
# Create and start trace
67
my_trace = trace("customer_support_workflow")
68
my_trace.start()
69
70
try:
71
# Run agents
72
result = await Runner.run(agent, "Help request")
73
finally:
74
my_trace.finish()
75
76
# Or use as context manager (Python 3.10+)
77
with trace("my_workflow") as t:
78
result = await Runner.run(agent, "Input")
79
```
80
81
### Span
82
83
Span representing a single operation within a trace.
84
85
```python { .api }
86
class Span[TSpanData]:
87
"""
88
Span within trace.
89
90
Type Parameters:
91
- TSpanData: Type of span-specific data
92
93
Attributes:
94
- span_id: str - Unique span identifier
95
- name: str - Span name
96
- span_data: TSpanData - Span-specific data
97
- parent_span: Span | None - Parent span for nesting
98
"""
99
100
def start(mark_as_current: bool = True) -> None:
101
"""
102
Start span.
103
104
Parameters:
105
- mark_as_current: Set as current active span
106
"""
107
108
def finish(reset_current: bool = True) -> None:
109
"""
110
Finish span.
111
112
Parameters:
113
- reset_current: Clear current span reference
114
"""
115
```
116
117
### Span Types
118
119
Functions for creating typed spans for different operations.
120
121
```python { .api }
122
def agent_span(
123
name: str,
124
*,
125
handoffs: list = None,
126
output_type: type = None
127
) -> Span[AgentSpanData]:
128
"""
129
Create agent span.
130
131
Parameters:
132
- name: Span name
133
- handoffs: Available handoffs
134
- output_type: Agent output type
135
136
Returns:
137
- Span[AgentSpanData]: Agent span
138
"""
139
140
def function_span(
141
name: str,
142
*,
143
input: Any = None,
144
output: Any = None
145
) -> Span[FunctionSpanData]:
146
"""
147
Create function span.
148
149
Parameters:
150
- name: Function name
151
- input: Function input
152
- output: Function output
153
154
Returns:
155
- Span[FunctionSpanData]: Function span
156
"""
157
158
def generation_span(
159
name: str,
160
*,
161
model: str = None,
162
input: list = None,
163
output: list = None,
164
usage: Any = None
165
) -> Span[GenerationSpanData]:
166
"""
167
Create generation span for LLM calls.
168
169
Parameters:
170
- name: Span name
171
- model: Model identifier
172
- input: Input messages
173
- output: Output messages
174
- usage: Token usage
175
176
Returns:
177
- Span[GenerationSpanData]: Generation span
178
"""
179
180
def guardrail_span(
181
name: str,
182
*,
183
guardrail_type: str = None,
184
input: Any = None,
185
output: Any = None
186
) -> Span[GuardrailSpanData]:
187
"""
188
Create guardrail span.
189
190
Parameters:
191
- name: Guardrail name
192
- guardrail_type: Type of guardrail
193
- input: Guardrail input
194
- output: Guardrail output
195
196
Returns:
197
- Span[GuardrailSpanData]: Guardrail span
198
"""
199
200
def handoff_span(
201
name: str,
202
*,
203
from_agent: str = None,
204
to_agent: str = None
205
) -> Span[HandoffSpanData]:
206
"""
207
Create handoff span.
208
209
Parameters:
210
- name: Span name
211
- from_agent: Source agent name
212
- to_agent: Target agent name
213
214
Returns:
215
- Span[HandoffSpanData]: Handoff span
216
"""
217
218
def mcp_tools_span(
219
name: str,
220
*,
221
server_label: str = None,
222
tools: list = None
223
) -> Span[MCPListToolsSpanData]:
224
"""
225
Create MCP tools span.
226
227
Parameters:
228
- name: Span name
229
- server_label: MCP server label
230
- tools: List of tools
231
232
Returns:
233
- Span[MCPListToolsSpanData]: MCP tools span
234
"""
235
236
def custom_span(
237
name: str,
238
*,
239
custom_data: dict = None
240
) -> Span[CustomSpanData]:
241
"""
242
Create custom span.
243
244
Parameters:
245
- name: Span name
246
- custom_data: Custom span data
247
248
Returns:
249
- Span[CustomSpanData]: Custom span
250
"""
251
252
def response_span(
253
name: str,
254
*,
255
response_data: dict = None
256
) -> Span[ResponseSpanData]:
257
"""
258
Create response span.
259
260
Parameters:
261
- name: Span name
262
- response_data: Response data
263
264
Returns:
265
- Span[ResponseSpanData]: Response span
266
"""
267
268
def speech_span(
269
name: str,
270
*,
271
speech_data: dict = None
272
) -> Span[SpeechSpanData]:
273
"""Create speech span."""
274
275
def speech_group_span(
276
name: str,
277
*,
278
group_data: dict = None
279
) -> Span[SpeechGroupSpanData]:
280
"""Create speech group span."""
281
282
def transcription_span(
283
name: str,
284
*,
285
transcription_data: dict = None
286
) -> Span[TranscriptionSpanData]:
287
"""Create transcription span."""
288
```
289
290
### Span Data Types
291
292
Data structures for different span types.
293
294
```python { .api }
295
class SpanData(abc.ABC):
296
"""
297
Abstract base class for all span data types.
298
299
All span data types inherit from this class and must implement
300
the export() method and type property.
301
"""
302
303
@abc.abstractmethod
304
def export() -> dict[str, Any]:
305
"""
306
Export span data as dictionary.
307
308
Returns:
309
- dict[str, Any]: Exported span data
310
"""
311
312
@property
313
@abc.abstractmethod
314
def type() -> str:
315
"""
316
Get span type identifier.
317
318
Returns:
319
- str: Span type string
320
"""
321
322
class AgentSpanData(SpanData):
323
"""
324
Span data for agent.
325
326
Attributes:
327
- agent_name: str
328
- tools: list
329
- handoffs: list
330
- output_type: type | None
331
"""
332
333
class CustomSpanData:
334
"""
335
Custom span data.
336
337
Attributes:
338
- custom_data: dict
339
"""
340
341
class FunctionSpanData:
342
"""
343
Span data for function tool.
344
345
Attributes:
346
- function_name: str
347
- input: Any
348
- output: Any
349
"""
350
351
class GenerationSpanData:
352
"""
353
Span data for LLM generation.
354
355
Attributes:
356
- model: str
357
- input: list
358
- output: list
359
- usage: Usage
360
"""
361
362
class GuardrailSpanData:
363
"""
364
Span data for guardrail.
365
366
Attributes:
367
- guardrail_name: str
368
- guardrail_type: str
369
- input: Any
370
- output: Any
371
"""
372
373
class HandoffSpanData:
374
"""
375
Span data for handoff.
376
377
Attributes:
378
- from_agent: str
379
- to_agent: str
380
"""
381
382
class MCPListToolsSpanData:
383
"""
384
Span data for MCP list tools.
385
386
Attributes:
387
- server_label: str
388
- tools: list
389
"""
390
391
class ResponseSpanData:
392
"""Span data for response."""
393
394
class SpeechSpanData:
395
"""Span data for speech."""
396
397
class SpeechGroupSpanData:
398
"""Span data for speech group."""
399
400
class TranscriptionSpanData:
401
"""Span data for transcription."""
402
403
class SpanError:
404
"""
405
Error in span.
406
407
Attributes:
408
- message: str - Error message
409
- data: dict | None - Error data
410
"""
411
```
412
413
### Current Trace and Span
414
415
Functions to access current active trace and span.
416
417
```python { .api }
418
def get_current_trace() -> Trace | None:
419
"""
420
Get current active trace.
421
422
Returns:
423
- Trace | None: Current trace or None
424
"""
425
426
def get_current_span() -> Span | None:
427
"""
428
Get current active span.
429
430
Returns:
431
- Span | None: Current span or None
432
"""
433
```
434
435
Usage example:
436
437
```python
438
from agents.tracing import get_current_trace, get_current_span, custom_span
439
440
# Within agent execution
441
current_trace = get_current_trace()
442
if current_trace:
443
print(f"Running in trace: {current_trace.trace_id}")
444
445
# Add custom span
446
span = custom_span("custom_operation", custom_data={"key": "value"})
447
span.start()
448
try:
449
# Perform operation
450
result = perform_custom_operation()
451
finally:
452
span.finish()
453
```
454
455
### Tracing Processor
456
457
Interface for custom trace processing and export.
458
459
```python { .api }
460
class TracingProcessor:
461
"""Processor for traces/spans."""
462
463
async def on_trace_start(trace: Trace) -> None:
464
"""
465
Called when trace starts.
466
467
Parameters:
468
- trace: Trace that started
469
"""
470
471
async def on_trace_end(trace: Trace) -> None:
472
"""
473
Called when trace ends.
474
475
Parameters:
476
- trace: Trace that ended
477
"""
478
479
async def on_span_start(span: Span) -> None:
480
"""
481
Called when span starts.
482
483
Parameters:
484
- span: Span that started
485
"""
486
487
async def on_span_end(span: Span) -> None:
488
"""
489
Called when span ends.
490
491
Parameters:
492
- span: Span that ended
493
"""
494
```
495
496
Usage example:
497
498
```python
499
from agents.tracing import TracingProcessor
500
import logging
501
502
class LoggingProcessor(TracingProcessor):
503
"""Log traces and spans."""
504
505
async def on_trace_start(self, trace):
506
logging.info(f"Trace started: {trace.name} ({trace.trace_id})")
507
508
async def on_trace_end(self, trace):
509
logging.info(f"Trace ended: {trace.name}")
510
511
async def on_span_start(self, span):
512
logging.debug(f"Span started: {span.name}")
513
514
async def on_span_end(self, span):
515
logging.debug(f"Span ended: {span.name}")
516
517
# Register processor
518
from agents.tracing import add_trace_processor
519
add_trace_processor(LoggingProcessor())
520
```
521
522
### Trace Provider
523
524
Provider for creating and managing traces.
525
526
```python { .api }
527
class TraceProvider:
528
"""Provider for trace creation."""
529
530
def create_trace(...) -> Trace:
531
"""Create new trace."""
532
533
def create_span(...) -> Span:
534
"""Create new span."""
535
536
def register_processor(processor: TracingProcessor) -> None:
537
"""Register trace processor."""
538
539
def set_processors(processors: list[TracingProcessor]) -> None:
540
"""Set trace processors."""
541
542
def set_disabled(disabled: bool) -> None:
543
"""Enable/disable tracing."""
544
545
def shutdown() -> None:
546
"""Shutdown provider."""
547
548
class DefaultTraceProvider(TraceProvider):
549
"""Default trace provider implementation."""
550
```
551
552
### Global Tracing Functions
553
554
Functions for configuring tracing globally.
555
556
```python { .api }
557
def add_trace_processor(processor: TracingProcessor) -> None:
558
"""
559
Add trace processor.
560
561
Parameters:
562
- processor: Processor to add
563
"""
564
565
def set_trace_processors(processors: list[TracingProcessor]) -> None:
566
"""
567
Set trace processors, replacing existing.
568
569
Parameters:
570
- processors: List of processors
571
"""
572
573
def set_tracing_disabled(disabled: bool) -> None:
574
"""
575
Globally enable/disable tracing.
576
577
Parameters:
578
- disabled: Whether to disable tracing
579
"""
580
581
def set_tracing_export_api_key(api_key: str) -> None:
582
"""
583
Set API key for trace export.
584
585
Parameters:
586
- api_key: API key for export service
587
"""
588
589
def set_trace_provider(provider: TraceProvider) -> None:
590
"""
591
Set trace provider.
592
593
Parameters:
594
- provider: Trace provider to use
595
"""
596
597
def get_trace_provider() -> TraceProvider:
598
"""
599
Get trace provider.
600
601
Returns:
602
- TraceProvider: Current trace provider
603
"""
604
605
def gen_trace_id() -> str:
606
"""
607
Generate trace ID.
608
609
Returns:
610
- str: New trace ID
611
"""
612
613
def gen_span_id() -> str:
614
"""
615
Generate span ID.
616
617
Returns:
618
- str: New span ID
619
"""
620
```
621
622
## Configuration
623
624
### Automatic Tracing
625
626
Tracing is enabled by default for all agent runs:
627
628
```python
629
from agents import Agent, Runner
630
631
agent = Agent(name="Assistant")
632
633
# Automatically traced
634
result = Runner.run_sync(agent, "Hello")
635
```
636
637
### Disable Tracing
638
639
Disable tracing globally or per-run:
640
641
```python
642
from agents.tracing import set_tracing_disabled
643
from agents import RunConfig
644
645
# Globally disable
646
set_tracing_disabled(True)
647
648
# Per-run disable
649
config = RunConfig(tracing_disabled=True)
650
result = Runner.run_sync(agent, "Hello", run_config=config)
651
```
652
653
### Configure Trace Metadata
654
655
Add custom metadata to traces:
656
657
```python
658
from agents import RunConfig
659
660
config = RunConfig(
661
workflow_name="customer_support",
662
trace_metadata={
663
"user_id": "user_123",
664
"session_id": "session_456",
665
"environment": "production"
666
},
667
group_id="support_tickets" # Group related traces
668
)
669
670
result = Runner.run_sync(agent, "Help", run_config=config)
671
```
672
673
### Sensitive Data
674
675
Control whether sensitive data is included in traces:
676
677
```python
678
config = RunConfig(
679
trace_include_sensitive_data=False # Exclude PII from traces
680
)
681
```
682
683
## External Tracing Processors
684
685
The SDK supports integration with external observability platforms:
686
687
- **Logfire**: Pydantic's observability platform
688
- **AgentOps**: Agent-specific monitoring
689
- **Braintrust**: LLM evaluation and monitoring
690
- **Scorecard**: AI observability
691
- **Keywords AI**: LLM analytics
692
693
Example integration:
694
695
```python
696
# Example: Logfire integration
697
import logfire
698
from agents.tracing import add_trace_processor
699
700
logfire.configure()
701
add_trace_processor(logfire.TracingProcessor())
702
703
# All agent runs now export to Logfire
704
result = Runner.run_sync(agent, "Hello")
705
```
706
707
## Best Practices
708
709
1. **Always Use Tracing**: Keep tracing enabled in production for debugging
710
2. **Meaningful Names**: Use descriptive workflow names for traces
711
3. **Metadata**: Add context through trace metadata
712
4. **Sensitive Data**: Set `trace_include_sensitive_data=False` for PII
713
5. **Group Traces**: Use `group_id` to group related workflows
714
6. **Custom Spans**: Add custom spans for important operations
715
7. **Export**: Configure trace export to observability platform
716
8. **Monitor Performance**: Use traces to identify bottlenecks
717
9. **Error Tracking**: Use traces to debug failures
718
10. **Sampling**: Implement sampling for high-volume applications
719