Skip to main content

openai-agents-opentelemetry

PyPI version CI Compatibility

OpenTelemetry tracing processor for the OpenAI Agents SDK.

Bridges agent traces to any OTLP-compatible backend (Jaeger, Datadog, Honeycomb, Grafana Tempo, Langfuse, etc.).

Installation

pip install openai-agents-opentelemetry

Quick Start

from agents import Agent, Runner, add_trace_processor
from openai_agents_opentelemetry import OpenTelemetryTracingProcessor

# Create and register the OpenTelemetry processor
otel_processor = OpenTelemetryTracingProcessor()
add_trace_processor(otel_processor)

# Now all agent traces will be exported to your configured OTel backend
agent = Agent(name="Assistant", instructions="You are helpful.")
result = await Runner.run(agent, "Hello!")

Using OpenTelemetry Only (No OpenAI Backend)

If you want traces to go only to your OpenTelemetry backend:

from agents import set_trace_processors
from openai_agents_opentelemetry import OpenTelemetryTracingProcessor

# Replace the default processor entirely
otel_processor = OpenTelemetryTracingProcessor()
set_trace_processors([otel_processor])

Span Mapping

The processor maps SDK spans to OpenTelemetry spans following OpenTelemetry Semantic Conventions for GenAI:

SDK Span Type OTel Span Name Key Attributes
Agent agent: {name} agent.name, agent.tools, agent.handoffs
Generation chat {model} gen_ai.operation.name, gen_ai.provider.name, gen_ai.request.model, gen_ai.usage.*
Function execute_tool {name} gen_ai.tool.name, gen_ai.tool.call.arguments, gen_ai.tool.call.result
Handoff handoff: {from} -> {to} agent.handoff.from, agent.handoff.to
Guardrail guardrail: {name} agent.guardrail.triggered
Response gen_ai.response gen_ai.response.id, gen_ai.response.model
Custom custom: {name} custom.name, custom.data.*

Configuration

Content Capture Configuration

Control what content is captured for privacy and compliance using ProcessorConfig:

from openai_agents_opentelemetry import OpenTelemetryTracingProcessor, ProcessorConfig

config = ProcessorConfig(
    capture_prompts=True,        # Capture prompt content as span events
    capture_completions=True,    # Capture completion content as span events
    capture_tool_inputs=True,    # Capture tool input arguments
    capture_tool_outputs=True,   # Capture tool output results
    max_attribute_length=4096,   # Max length for span attributes
    max_event_length=8192,       # Max length for span event attributes
    baggage_keys=["user.id", "session.id"],  # Propagate context to spans
)

processor = OpenTelemetryTracingProcessor(config=config)

Content Filtering / PII Redaction

Apply custom filtering to redact sensitive data before capture:

import re
from openai_agents_opentelemetry import OpenTelemetryTracingProcessor, ProcessorConfig

def redact_pii(content: str, context: str) -> str:
    """Custom PII redaction callback."""
    # Redact SSNs
    content = re.sub(r"\b\d{3}-\d{2}-\d{4}\b", "[SSN REDACTED]", content)
    # Redact email addresses
    content = re.sub(r"\b[\w.-]+@[\w.-]+\.\w+\b", "[EMAIL REDACTED]", content)
    return content

config = ProcessorConfig(
    capture_prompts=True,
    capture_completions=True,
    content_filter=redact_pii,
)

processor = OpenTelemetryTracingProcessor(config=config)

OpenTelemetry SDK Configuration

The processor uses the globally configured OpenTelemetry TracerProvider. Configure it as you normally would:

from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter

# Configure OpenTelemetry
provider = TracerProvider()
processor = BatchSpanProcessor(OTLPSpanExporter(endpoint="http://localhost:4317"))
provider.add_span_processor(processor)
trace.set_tracer_provider(provider)

# Then add the Agents SDK processor
from agents import add_trace_processor
from openai_agents_opentelemetry import OpenTelemetryTracingProcessor

add_trace_processor(OpenTelemetryTracingProcessor())

Resource Helper

Use the create_resource helper for standard resource attributes:

from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from openai_agents_opentelemetry import create_resource

resource = create_resource(
    service_name="my-agent-service",
    service_version="1.0.0",
    additional_attributes={"deployment.environment": "production"},
)

provider = TracerProvider(resource=resource)
trace.set_tracer_provider(provider)

Span Events

The processor automatically adds span events for content capture (controlled by ProcessorConfig):

Span Type Event Name Attributes
Generation gen_ai.content.prompt gen_ai.prompt
Generation gen_ai.content.completion gen_ai.completion
Function gen_ai.tool.input gen_ai.tool.call.arguments
Function gen_ai.tool.output gen_ai.tool.call.result
Guardrail guardrail.evaluated guardrail.name, guardrail.triggered
Handoff handoff.executed handoff.from, handoff.to

Metrics

Enable metrics collection for token usage, operation duration, and agent-specific counters:

from openai_agents_opentelemetry import OpenTelemetryTracingProcessor

# Enable metrics collection
processor = OpenTelemetryTracingProcessor(enable_metrics=True)

Standard OTel GenAI Metrics

Metric Name Type Unit Description
gen_ai.client.token.usage Histogram {token} Token consumption (input/output)
gen_ai.client.operation.duration Histogram s LLM call duration

Agent-Specific Metrics

Metric Name Type Unit Description
agent.tool.invocations Counter {invocation} Tool/function call count by name
agent.handoffs Counter {handoff} Agent handoff count
agent.guardrail.triggers Counter {trigger} Guardrail trigger count by name
agent.errors Counter {error} Error count by type

Configuring Metrics with OpenTelemetry SDK

Use create_metrics_views() to configure histogram bucket boundaries according to the OpenTelemetry Semantic Conventions for GenAI. Without these views, the SDK uses default buckets that are not suitable for GenAI workloads:

  • Token counts can range from 1 to millions (large context windows like GPT-4 128k or Claude 200k)
  • Operation durations follow different patterns than typical HTTP requests
from opentelemetry import metrics
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import OTLPMetricExporter
from openai_agents_opentelemetry import (
    OpenTelemetryTracingProcessor,
    create_metrics_views,
)

# Configure metrics with recommended GenAI histogram buckets
exporter = OTLPMetricExporter(endpoint="http://localhost:4317")
reader = PeriodicExportingMetricReader(exporter)
views = create_metrics_views()  # Returns views with OTel GenAI recommended bucket boundaries
provider = MeterProvider(metric_readers=[reader], views=views)
metrics.set_meter_provider(provider)

# Then enable metrics in the processor
from agents import add_trace_processor

add_trace_processor(OpenTelemetryTracingProcessor(enable_metrics=True))

The create_metrics_views() function configures:

  • gen_ai.client.token.usage: Buckets [1, 4, 16, 64, 256, 1024, 4096, 16384, 65536, 262144, 1048576, 4194304, 16777216, 67108864]
  • gen_ai.client.operation.duration: Buckets [0.01, 0.02, 0.04, 0.08, 0.16, 0.32, 0.64, 1.28, 2.56, 5.12, 10.24, 20.48, 40.96, 81.92]

You can also access these bucket constants directly if needed:

from openai_agents_opentelemetry import TOKEN_BUCKETS, DURATION_BUCKETS

Context Propagation (Baggage)

Propagate context like user IDs or session IDs across all agent spans using OpenTelemetry baggage:

from opentelemetry import baggage, context
from openai_agents_opentelemetry import OpenTelemetryTracingProcessor, ProcessorConfig

# Configure which baggage keys to read and add as span attributes
config = ProcessorConfig(
    baggage_keys=["user.id", "session.id", "tenant.id"]
)
processor = OpenTelemetryTracingProcessor(config=config)

# Set baggage before running agents
ctx = baggage.set_baggage("user.id", "user-123")
ctx = baggage.set_baggage("session.id", "session-456", context=ctx)

with context.attach(ctx):
    # All spans created during this agent run will have user.id and session.id attributes
    result = await Runner.run(agent, "Hello!")

This enables filtering traces by user, session, or tenant in your observability backend.

Compatibility

This package is tested weekly against the latest OpenAI Agents SDK to ensure compatibility.

License

MIT

Metadata

Release files for openai-agents-opentelemetry 0.4.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for openai-agents-opentelemetry 0.4.1
File Size Uploaded
openai_agents_opentelemetry-0.4.1.tar.gz 156.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for openai-agents-opentelemetry 0.4.1
File Interpreter ABI Platform
openai_agents_opentelemetry-0.4.1-py3-none-any.whl Python 3 none any Details

Total release size: 176.2 kB

Release files / openai_agents_opentelemetry-0.4.1.tar.gz

Download URL openai_agents_opentelemetry-0.4.1.tar.gz
Size 156.5 kB
Tags Source
SHA-256 checksum
How to use checksums
c74b9ae8be006c8fd106dbeef746995716a7d08b16e291c665ff9657ae63741e
BLAKE2b-256 checksum
How to use checksums
1f33d3ebddb05accf02237e2c8731ee118068ff88c6c2aedeb1d709506da3795
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.21 {"installer":{"name":"uv","version":"0.12.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / openai_agents_opentelemetry-0.4.1-py3-none-any.whl

Download URL openai_agents_opentelemetry-0.4.1-py3-none-any.whl
Size 19.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
395352544462696b136be0307ab0e4fb03e89e22e705f91bea7585c009e72d32
BLAKE2b-256 checksum
How to use checksums
40b0976b23da1dad654d46c7fe81d61176ac6005e1daa658a3b33daa8a3f9465
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.21 {"installer":{"name":"uv","version":"0.12.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.4.1 This release

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page