This page was verified on October 28, 2026 with
pydantic-ai-slim 2.63.0, logfire 5.4.0, anthropic 2.3.0 and the OpenTelemetry Python SDK 1.45.1. GenAI libraries and semantic conventions are evolving rapidly, so package configuration and emitted attributes can change between releases. Keep your instrumentation current and verify the fields emitted by the version you deploy.Prerequisites
- Python 3.11+ and Pydantic AI 2.x
- An LLM provider API key, such as Anthropic or OpenAI
- An OTel Collector configured using Connect OpenTelemetry to Bronto, or a direct OTLP exporter (below)
Instrument Pydantic AI
Choose one of the two options. Both produce the same Pydantic AI spans and metrics.Option 1: OpenTelemetry SDK
InstrumentationSettings(...) to Agent.instrument_all() to change what is recorded, for example include_content=False (see Prompts and responses).
Option 2: Logfire SDK
The Logfire SDK is an OpenTelemetry distribution. Withsend_to_logfire=False it sends only to the OTLP endpoint in your environment:
metrics= option above the token and cost metrics don’t arrive. Traces are not affected.
To send to Logfire and Bronto, leave out send_to_logfire=False and keep the OTEL_EXPORTER_OTLP_* variables set. The Logfire SDK then exports to both. It exports over OTLP/HTTP with protobuf only.
Send traces and metrics to Bronto
Via a Collector: point the application’s OTLP exporter at the Collector, then configure the Collector using Connect OpenTelemetry to Bronto. This is recommended in production. Direct export: point the exporter at the Bronto ingestion endpoint and add your API key. Both options above read these variables:
The SDK appends
/v1/traces and /v1/metrics. Set the temporality to delta: with the Python SDK’s default cumulative temporality, every export repeats the running total, and summing the metric in Bronto counts the same tokens and cost more than once. See API Keys for how to create a key with ingestion permissions.
What you get
Spans
One agent run produces this trace:invoke_agent <agent name> operation to see each run as a waterfall, with the provider call marked as a downstream call. Select a span to see its attributes, including prompts and responses as JSON.
Fields on the Pydantic AI spans:
Metrics
Pydantic AI records two histograms, which appear in Metrics Explorer:
Both carry
gen_ai.operation.name, gen_ai.provider.name, gen_ai.request.model and gen_ai.response.model, plus your resource attributes, which Metrics Explorer lists as Resource:service.name and so on. They don’t carry the agent name.
Provider SDK spans
The Anthropic Python SDK (2.x) creates its ownanthropic.messages.create span for every API call whenever an OpenTelemetry tracer provider is registered. It sits under Pydantic AI’s chat span and adds fields Pydantic AI doesn’t record:
http.response.status_code: the provider’s HTTP status, for example429or529anthropic.request.id: the ID to quote to Anthropic supportgen_ai.response.time_to_first_chunk: time to the first streamed token, in seconds
ANTHROPIC_OPEN_TELEMETRY=false. With the Claude Platform’s own telemetry enabled, the SDK’s trace context also joins Anthropic’s server-side spans to the same trace; see Claude Platform.
Track tokens and cost
Use the metrics for totals. In Metrics Explorer, select the metric, set Calculate to Sum, and group by a field:
With the instrumentation shown here, the metrics count each model request once. Additional provider instrumentation, such as
opentelemetry-instrumentation-openai-v2, can also record gen_ai.client.token.usage; disable the overlapping instrumentation or filter out its token metric stream before calculating totals. On spans, the same tokens can appear three times for one request: on invoke_agent as the run total, on chat, and on the provider SDK span. For one run’s tokens, read gen_ai.aggregated_usage.* on its invoke_agent span; its cost is the sum of operation.cost on its chat spans.
The metrics don’t carry the agent name. To split cost by agent, run each agent in its own service, or set a resource attribute per process with OTEL_RESOURCE_ATTRIBUTES and group by it.
Find failing runs
A failed run ends with an error status on itsinvoke_agent span. In Tracing, the Errors column of the invoke_agent <agent name> operation shows how many runs failed. Select the operation and the Error status filter to list the failed traces, then open one: the root span’s status message names the exception.
A tool call with invalid arguments doesn’t fail the run: the
execute_tool span gets an error status and pydantic_ai.tool.failure_stage = validation, and the model is asked to retry. Output validation retries don’t get a span of their own. The run shows two or more chat spans followed by the error; with content capture on, the rejected output is in gen_ai.output.messages of the earlier chat span.
To stop a runaway agent before it spends more, set limits on the run, for example UsageLimits(request_limit=20, cost_limit=Decimal("0.50")). A run that hits a limit fails with UsageLimitExceeded.
Alert on cost and failures
Monitors evaluate log datasets and metrics, not spans. Create a metric monitor onoperation.cost with Sum over a time window, for example more than $5 in an hour, to be alerted when model spend climbs. A monitor on gen_ai.client.token.usage works the same way for tokens.
Pydantic AI’s metrics don’t record failures: a request that fails emits no token or cost data. To alert on failed runs, export the failures as logs or metrics first, for example by logging the exception your application catches around agent.run() through the OpenTelemetry Python SDK, then create a dataset monitor on those logs.
Prompts and responses
Pydantic AI records prompts, responses, tool arguments and tool results by default. To keep the message structure, roles and tool names but drop the text, passinclude_content=False:
include_content=False to logfire.instrument_pydantic_ai(). The Anthropic SDK spans contain metadata only unless you set ANTHROPIC_OPEN_TELEMETRY_TRACES_CONTENT_MODE=content.
Verify in Bronto
Open Tracing and filter by the service you configured inOTEL_SERVICE_NAME. Each agent run appears as an invoke_agent <agent name> operation. Then open Metrics Explorer and select operation.cost or gen_ai.client.token.usage.
If no traces appear, check that instrumentation is set up before the first agent run, verify the OTLP endpoint and API-key header, and make sure short-lived processes flush their span processor before exit. If traces appear but metrics don’t, check the temporality variable and, with the Logfire SDK, the metrics= option above.
