How do I see which step was slow in an agent built with Pydantic AI?
Rius shows which step was slow in a Pydantic AI agent as the span with the longest bar in the trace waterfall, with no wrapping code needed. Pydantic AI emits its own spans for the agent run, each model request and each tool call, and Rius records them with their durations. Open the trace, find the longest bar, or sort the Spans tab by duration. Code of your own that Pydantic AI does not trace needs an observe wrapper to show up as its own step.
How it works
The Pydantic AI integration works differently from the client-library ones. rius.init() installs the global OpenTelemetry tracer provider, and Agent.instrument_all(True) tells Pydantic AI to emit its spans through it. The framework supplies the structure itself, so you wrap nothing.
What the integration records on its own:
- The agent run is the root span, named
invoke_agentfollowed by your agent’s name. - Each model request is a generation named
chatfollowed by the model, with tokens and cost. - Each tool call is a span named
execute_toolfollowed by the tool name.
A run that calls one tool looks like this in the tree:
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 answersHere the two model requests account for nearly all of the 6.0 seconds, and the tool is not the problem. Rius also records time to first token and reasoning tokens for Pydantic AI runs, which helps when a model request is the slow step.
What needs a span of your own is work the framework does not trace. Pydantic AI traces the agent, its model requests and its tool calls. A database query, a retrieval helper or a post-processing function you call yourself is not a step in the tree unless you wrap it with observe. Time spent there is part of its parent span’s duration, so the parent looks slow with no child to explain it.
Set it up
-
Install the SDK and turn on Pydantic AI’s instrumentation. No extra is needed beyond
glassflow-rius. The integration page has the full setup.pip install glassflow-rius pydantic-aiimport rius from pydantic_ai import Agent rius.init(api_key="ri_...", service_name="my-agent") Agent.instrument_all(True) -
Run the agent once with a request that calls a tool, then open the trace in the console. You should see the
invoke_agentroot,chatgenerations andexecute_toolspans. -
Read the timing in the trace. Open the trace and look at the waterfall, which lays the spans out as a tree on a timeline. The longest bar is the slow step. The Map tab shows the same trace as a graph with a latency lens, and clicking a node lands you on that node’s spans in the tree. Details are in Exploring traces.
-
To compare steps across many runs, use the Spans tab. Filter by kind with the All kinds menu, for example Tool or LLM, and click the Duration header to sort.
-
If a gap in the waterfall has no span to explain it, wrap your own function with
observe. The name below is yours:@rius.observe def load_customer_history(email: str) -> list[str]: return fetch_history(email)A bare
observemakes a span of kind CHAIN named after the function, so it appears in the trace under its own name and duration. Call it from your tool or around the run, and its time no longer hides inside the parent. -
Scope each run with
rius.session(), reusing your conversation id, so every span of one conversation groups under one session. The Session link in the trace header lists them.
What you get
- A tree of the run with a duration on every agent, model and tool span, so the slow step is visible without reading logs.
- Model requests with token counts, cost and time to first token next to their duration, so you can tell a slow model call from a long prompt or output.
- Tool calls named after your tools, with no wrapping.
- Your own helper functions as named steps once wrapped with
observe. - The Map view’s latency lens and the Spans tab’s Duration sort for finding slow steps across runs.
- The trace’s Compare runs tool, to set a slow run beside another run of the same agent and see where latency moved.
Spans from Pydantic AI arrive with an unset status rather than OK on success. The trace status still reads OK. For the wider picture of watching agents over time, see Monitor AI agents in production.
When something else fits
- If your agent uses another framework or a client library directly, the Integrations page shows what each one records on its own and where you add
observewrappers. - If one slow step keeps recurring and you want to know when it happens, a custom alert on duration is a better fit than reading traces by hand.