Skip to content
Blog

Agent Tracing and Observability: Debugging Every Decision

Master built-in tracing in the OpenAI Agents SDK to debug, visualize, and monitor agent workflows. Learn to create traces, spans, and custom processors for production observability.

Published on September 6, 2026

AI Assistant

When an agent makes a decision, you need to understand why. The OpenAI Agents SDK includes built-in tracing that collects a comprehensive record of events during an agent run: LLM generations, tool calls, handoffs, guardrails, and custom events. Using the Traces dashboard, you can debug, visualize, and monitor your workflows during development and in production.

In this tutorial, you will learn how tracing works in the Agents SDK, how to create custom traces and spans, and how to configure tracing processors for production observability.

How Tracing Works

Tracing is enabled by default. Every Runner.run() call automatically creates a trace that captures the full execution flow.

Traces and Spans

  • Traces represent a single end-to-end operation of a workflow, composed of nested Spans
  • Spans represent operations with start and end times, containing specific data about what happened

A typical trace hierarchy:

trace("Agent workflow")
├── task_span()
│   ├── turn_span()
│   │   ├── agent_span()
│   │   ├── generation_span()  # LLM call
│   │   ├── function_span()    # Tool call
│   │   ├── guardrail_span()   # Input/output validation
│   │   └── handoff_span()     # Agent delegation

Default Tracing

The SDK automatically traces:

  • Runner.run() → wrapped in a trace()
  • Each runner invocation → task_span()
  • Each model turn → turn_span()
  • Each agent execution → agent_span()
  • LLM generations → generation_span()
  • Function tool calls → function_span()
  • Guardrails → guardrail_span()
  • Handoffs → handoff_span()
  • Audio transcription → transcription_span()
  • Audio speech → speech_span()

Custom Traces

For multi-step workflows, wrap the entire operation in a trace() context manager:

from agents import Agent, Runner, trace

async def main():
    agent = Agent(name="Joke generator", instructions="Tell funny jokes.")

    with trace("Joke workflow"):
        first_result = await Runner.run(agent, "Tell me a joke")
        second_result = await Runner.run(
            agent, f"Rate this joke: {first_result.final_output}"
        )
        print(f"Joke: {first_result.final_output}")
        print(f"Rating: {second_result.final_output}")

Both Runner.run calls become part of one overall trace, making it easy to follow the complete workflow.

Creating Custom Spans

Use custom_span() to track specific operations:

from agents import trace, custom_span

async def process_data(data):
    with trace("Data processing"):
        # Custom span for data validation
        with custom_span("validate_data", {"input_size": len(data)}):
            validated = validate(data)

        # Custom span for transformation
        with custom_span("transform", {"records": len(validated)}):
            transformed = transform(validated)

        # Custom span for storage
        with custom_span("store", {"records": len(transformed)}):
            await store(transformed)

Disabling Tracing

You can disable tracing at three levels:

# Globally via environment variable
import os
os.environ["OPENAI_AGENTS_DISABLE_TRACING"] = "1"

# Globally via code
from agents import set_tracing_disabled
set_tracing_disabled(True)

# Per-run via RunConfig
from agents import RunConfig, Runner
result = await Runner.run(
    agent,
    "Hello",
    run_config=RunConfig(tracing_disabled=True),
)

Compact Trace Hierarchy

For a more compact hierarchy, disable automatic task and turn spans:

from agents import RunConfig, Runner

result = await Runner.run(
    agent,
    "Hello",
    run_config=RunConfig(tracing={
        "include_task_and_turn_spans": False
    }),
)

Agent, generation, function, guardrail, handoff, and custom spans are still recorded.

Sensitive Data

The generation_span() captures LLM inputs/outputs, and function_span() captures tool call data. Disable sensitive data capture:

from agents import RunConfig

result = await Runner.run(
    agent,
    "Hello",
    run_config=RunConfig(trace_include_sensitive_data=False),
)

Or via environment variable:

export OPENAI_AGENTS_TRACE_INCLUDE_SENSITIVE_DATA=false

Custom Tracing Processors

By default, the SDK exports traces to the OpenAI backend. For custom or additional destinations, use processors:

Adding a Processor

from agents import add_trace_processor

# Add a secondary processor (keeps OpenAI backend)
add_trace_processor(my_custom_processor)

Replacing Processors

from agents import set_trace_processors

# Replace the default processor entirely
set_trace_processors([my_custom_processor])

Ecosystem Integrations

The Agents SDK integrates with popular observability platforms:

PlatformIntegration
Weights & BiasesW&B Weave
Arize PhoenixPhoenix
MLflowMLflow Tracing
LangSmithLangSmith
LangfuseLangfuse
DatadogDatadog LLM Observability
Pydantic LogfireLogfire
BraintrustBraintrust

Long-Running Workers

The default BatchTraceProcessor exports traces in batches. For long-running workers like Celery or FastAPI background tasks, call flush_traces() for immediate delivery:

from agents import Runner, flush_traces, trace

@celery_app.task
def run_agent_task(prompt: str):
    try:
        with trace("celery_task"):
            result = Runner.run_sync(agent, prompt)
        return result.final_output
    finally:
        flush_traces()

Tracing with Non-OpenAI Models

When using non-OpenAI models, provide an OpenAI API key for the tracing exporter:

from agents import set_tracing_export_api_key, Agent

set_tracing_export_api_key("sk-your-key")

agent = Agent(
    name="Assistant",
    model=AnyLLMModel(
        model="your-provider/your-model-name",
        api_key="your-api-key",
    ),
)

Production Monitoring

With tracing enabled, monitor your agents in production:

  • Error rates: Track failed tool calls and guardrail violations
  • Latency: Identify slow LLM generations and tool executions
  • Token usage: Monitor costs per workflow
  • Handoff patterns: Understand agent delegation flows
  • Tool selection: Verify agents pick the right tools

The Traces dashboard provides real-time visibility into every decision your agents make.

Next Steps

Tracing is the foundation of agent observability. By understanding every decision your agents make, you can debug issues faster, optimize costs, and build trust with your users.