How do I see the prompts and responses in an agent built with Pydantic AI?
Rius shows the prompts and responses of a Pydantic AI agent on the Input / Output tab of each model request span, with no wrappers around your code. Pydantic AI emits its own OpenTelemetry spans for agent runs, model requests and tool calls, and Rius reads them. The prompt and completion appear whenever Pydantic AI records content on the span and your Rius privacy controls let it through. This is part of how you monitor AI agents in production.
How it works
The Pydantic AI integration works the other way around from the client-library integrations. There is no auto-instrumentation extra. 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 run root, the model request spans and the tool spans itself, so you add no spans or attributes of your own to see prompts and responses.
What the integration records on its own:
- An agent run becomes the root span, named invoke_agent followed by your agent’s name.
- A model request becomes a span named chat followed by the model name, with tokens and cost. This is the span that holds the prompt and response.
- A tool call becomes a span named execute_tool followed by the tool name.
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 answersTwo settings decide whether content is on those spans. Pydantic AI’s own InstrumentationSettings (for example include_content) controls what the framework puts on its spans: prompts, completions and tool arguments. On top of that, the Rius SDK’s content controls decide what leaves your process. Setting RIUS_CAPTURE_CONTENT to false strips prompt and response content at export, and a mask callable can redact what you do send.
Set it up
- Install the SDK next to the framework with
pip install glassflow-rius pydantic-ai. No extra is needed. - Call
rius.init(), then switch on Pydantic AI’s instrumentation withAgent.instrument_all(True). Define your agent and tools as usual. Scoping the run withrius.session()groups the conversation as one session, and the framework’s spans inherit that scope.
import rius
from pydantic_ai import Agent
rius.init(api_key="ri_...", service_name="my-agent")
Agent.instrument_all(True)
support_agent = Agent(
"openai:gpt-5-mini",
instructions="Answer support questions; check accounts with the tool.",
)
@support_agent.tool_plain
def account_status(email: str) -> str:
"""Fetch a customer's account standing by email."""
return lookup(email)
with rius.session(conversation_id):
result = support_agent.run_sync(ticket)- Run one request that calls a tool, then open the Traces page in the console and select the trace. You should see the invoke_agent root, the chat spans with model, tokens and cost, and the execute_tool span.
- Select a chat span and open its Input / Output tab to read the prompt and the completion. The Raw tab shows the span exactly as ingested, which is where to look if you want to confirm which content attributes arrived.
- If the tab says no content was captured, check
include_contentin Pydantic AI’sInstrumentationSettings, and check thatRIUS_CAPTURE_CONTENTis not set to false and that no mask removes the content.
The exploring traces page covers the rest of the trace view.
What you get
- The prompt and completion for every model request, on the Input / Output tab of its chat span, in the order the agent made them.
- A diff between calls. On a chat span with captured messages, Since previous llm call shows what changed in the input since the trace’s previous model call. Added, removed and changed messages are marked, so a rewritten system prompt or a dropped turn stands out in an agent loop.
- Tool inputs and results in context. Each execute_tool span sits between the chat spans that requested and consumed it, and carries the tool arguments when Pydantic AI records them.
- Step-through reading. Previous and next buttons, or the
jandkkeys, move through spans while keeping the Input / Output tab open, so you can read each call in turn. - Tokens and cost beside the text. The span’s Model section shows provider, requested and response model, tokens and cost. Cost is computed by Rius from the model and token counts, as a list-price estimate in US dollars. Time to first token and reasoning tokens also show up for Pydantic AI runs.
- Content you control. If content is stripped, the tab says so and the timings, tokens and cost still work.
One detail to expect: successful Pydantic AI spans arrive with an unset status rather than OK, and the trace status still reads Ok.
When something else fits
If you strip content on purpose, with Pydantic AI’s settings or RIUS_CAPTURE_CONTENT, Rius shows structure, timings, tokens and cost but no text, and that is the intended result. If you use Pydantic AI without the Rius SDK, any OpenTelemetry setup pointed at the Rius ingest endpoint works, but you then set up the exporter, sessions and privacy controls yourself. For other frameworks and libraries, see the integrations overview.