Pydantic AI via OpenTelemetry
The same agent as the Pydantic AI Quickstart, traced through OpenTelemetry instead. Nothing from TraceAgent is imported: the agent only exports OpenTelemetry traces to the server. It uses a fake model, so it runs without an API key.
Run
pip
pip install pydantic-ai-slim opentelemetry-sdk opentelemetry-exporter-otlp-proto-httpuv
uv add pydantic-ai-slim opentelemetry-sdk opentelemetry-exporter-otlp-proto-httpStart the TraceAgent server at http://127.0.0.1:8000, save the script below as otel_quickstart.py and run:
python otel_quickstart.py
The Script
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from pydantic_ai import Agent
from pydantic_ai.capabilities import Instrumentation
from pydantic_ai.messages import ModelResponse, TextPart, ToolCallPart
from pydantic_ai.models.function import FunctionModel
from pydantic_ai.models.instrumented import InstrumentationSettings
def fake_model(messages, info):
"""Stands in for an LLM: asks for the tool first, then answers."""
if len(messages) == 1:
return ModelResponse(parts=[ToolCallPart("weather", {"city": "Madrid"})])
return ModelResponse(parts=[TextPart("It is sunny in Madrid, 23 degrees.")])
# 1. Send OpenTelemetry traces to the TraceAgent server. Nothing from TraceAgent is imported.
provider = TracerProvider()
provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter(endpoint="http://127.0.0.1:8000/v1/traces")))
# 2. Your usual agent, with Pydantic AI's own instrumentation.
agent = Agent(
FunctionModel(fake_model), # use a real model string, e.g. "openai:gpt-4o", in your own agent
name="otel-quickstart",
capabilities=[Instrumentation(settings=InstrumentationSettings(tracer_provider=provider))],
)
@agent.tool_plain
def weather(city: str) -> str:
"""Return the weather of a city."""
return f"Sunny, 23 degrees in {city}."
# 3. Use it as always.
result = agent.run_sync("What is the weather in Madrid?")
print(result.output)
# 4. A short script must flush before exiting, or the traces are lost.
provider.shutdown()
Output:
It is sunny in Madrid, 23 degrees.
What It Does
- Configures an OpenTelemetry exporter that points at the TraceAgent server
- Builds a Pydantic AI agent with its own instrumentation
- The fake model asks for the
weathertool, then answers - Flushes the exporter so no span is lost
The server creates the run by itself, named otel-quickstart, with the same events as the hooks version.
Learn More
- OpenTelemetry Ingestion — How spans become a run, attaching to an SDK run, privacy