Skip to Content

My Pydantic AI agent is slow to respond. Why?

Rius shows where a slow Pydantic AI run spends its time: open the trace and compare the duration of each chat model request and execute_tool span under the invoke_agent root. The longest child span is where to look first. A custom alert on duration then flags the next slow run.

How it works

Pydantic AI emits its own OpenTelemetry spans for agent runs, model requests and tool calls, and Rius reads them with no wrappers. Each kind of step gets its own span:

  • An agent run is the root span, named invoke_agent <agent name>. Its duration is the whole run.
  • A model request is a span named chat <model>, with tokens and cost.
  • A tool call is a span named execute_tool <tool name>.

The spans nest, so a slow run reads as a timeline. A run that calls one tool looks like this:

invoke_agent support_agent 6.0s ├─ chat gpt-5-mini 3.3s decides to call the tool ├─ execute_tool account_status 0ms └─ chat gpt-5-mini 2.7s answers

Read the pattern in the durations:

  • One long chat span: that model request is the slow step. Check its model and its input tokens.
  • Many chat spans: the agent makes many round trips. Each one adds latency.
  • A long execute_tool span: your own tool code is the slow step, not the model.
  • Back-to-back identical tool calls: when every attempt but the last failed, the trace collapses them into one retry row, such as fetch_article · 3 attempts · recovered. Expand the row to see how much time the attempts took.

The Pydantic AI integration page lists what else lands in the trace.

Set it up

  1. Send Pydantic AI traces to Rius. This is the whole setup, and the Pydantic AI integration page covers it in full. Other frameworks are listed under Integrations.

    pip install glassflow-rius pydantic-ai
    import rius from pydantic_ai import Agent rius.init(api_key="ri_...", service_name="my-agent") Agent.instrument_all(True)
  2. Reproduce the slow request, then open Traces. Each row shows latency, so pick the slow run and open it. The waterfall view puts the spans on a timeline. Find the widest child of the invoke_agent root.

  3. Switch to the Map tab and choose the latency lens. It shows where the time went at a glance, and clicking a node takes you to that node’s spans in the tree.

  4. To compare many runs, open the Spans tab. Use the All kinds menu to pick LLM or Tool, then click the Duration header to sort. The slowest model requests or tool calls across the time range come first.

  5. If the slow chat spans carry large prompts, check the context growth strip above the tree. It plots input tokens per model call in order, so a growing history shows up there. On a chat span, Since previous llm call in the Input / Output tab shows what each step added to the prompt.

  6. For the trend, open the usage and cost view described in Usage and cost. It shows latency percentiles (p50, p95, p99) for finished traces. It also shows time to first token for streamed model calls, which separates a model that is slow to start from one that is slow to finish. Time to first token needs glassflow-rius 1.0.1 or later.

  7. To catch it next time, create a custom alert on duration. Filter it by Service or Agent so it measures whole runs, not single spans. Rules measure only the spans they match. You can also alert on time to first token. Alerts are covered in Monitor AI agents in production.

What you get

  • A named span for every agent run, model request and tool call, with duration on each, so the slow step is identifiable by name.
  • Tokens and cost on each model request. Cost is a list-price estimate in US dollars, computed by Rius from the model and token counts.
  • Latency percentiles and time to first token over 15 minutes to 30 days, so you see whether one run was slow or the whole agent got slower.
  • A duration alert that tells you when it happens again, without you checking the trace list.
  • A shareable view of the failing window. Share on the trace list creates a read-only link with metadata only and no span content. The link expires after 24 hours, 7 days or 30 days.

Each span is described in Exploring traces.

When something else fits

  • If the slow step is inside your own code and not a tool call, wrap that function with rius.observe so it gets its own span. Pydantic AI does not trace code it does not run.
  • If you want to see whether a run is still going or crashed, turn on partial spans so in-flight runs show as running. Heartbeats show that a process is alive, not that it is making progress.
  • Time to first token is measured only on streamed calls. If your agent does not stream, rely on span duration.

Still stuck? Get help

Last updated on