How do I switch from Langfuse to Rius when I trace Pydantic AI?
Rius traces Pydantic AI through the framework’s own OpenTelemetry spans, so you replace your Langfuse setup with rius.init() and one call to Agent.instrument_all(True). Your agent code does not change. Runs arrive with a root span per agent run, a generation per model request with tokens and cost, and a span per tool call. You can run both backends side by side until you are ready to cut over.
How it works
Pydantic AI is OpenTelemetry-native and emits spans for agent runs, model requests and tool calls. rius.init() installs the global OpenTelemetry tracer provider, and Agent.instrument_all(True) tells Pydantic AI to emit its spans through it. Rius reads the framework’s GenAI attributes directly and computes cost on its servers, so you never send a cost value. No extra install is needed beyond the base SDK.
This means the Rius side of the switch is small: the code that sends Pydantic AI spans to Langfuse today is replaced, not ported. Where your Langfuse setup uses the Langfuse SDK, the Langfuse migration guide maps each call to its Rius equivalent. Where it sends OTLP to Langfuse, you can keep the instrumentation and re-point the exporter at Rius instead. The Migrate to Rius guide covers both routes and the other tools it has guides for.
Set it up
-
Create a Rius workspace and an API key. Keys start with
ri_. -
Install the SDK next to Pydantic AI. No extra is needed:
pip install glassflow-rius pydantic-ai -
Remove the Langfuse client setup, or the OTLP exporter variables that point at Langfuse, from the code that starts your agent. Then initialize Rius and switch on Pydantic AI instrumentation:
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) -
Swap your Langfuse session and user scoping.
propagate_attributes(session_id=...)becomeswith rius.session(session_id):, andpropagate_attributes(user_id=...)becomeswith rius.user(user_id):. Reuse your conversation id as the session id. Each user’s traces, failures and cost then appear on the Users page. -
Run one request that calls a tool, then open the trace in the console and check the points under the next heading.
-
To compare before you cut over, keep Langfuse reporting while Rius receives the same traffic. If you send OTLP through a Collector, add Rius as a second exporter, as the Langfuse guide shows. If another tracer provider is the global one in your process,
RIUS_BRIDGE_FOREIGN_PROVIDER=truealso sends its spans to Rius. When the numbers match, remove the Langfuse setup and revoke its keys.
The Pydantic AI integration page has the full recipe, and the integrations overview lists the other frameworks and libraries the SDK covers.
What you get
Spans are named after your agents, models and tools, and tool calls appear without any wrapping:
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- Root span: each agent run is a root span named
invoke_agent <agent name>. - Generations: each model request is a generation named
chat <model>, with tokens and cost. Cost is a list-price estimate in US dollars, computed by Rius. Time to first token needsglassflow-rius1.0.1 or later, and reasoning tokens need 1.0.2 or later. - Tool spans: each tool call is a span named
execute_tool <tool name>. - Sessions and users: traces group by the session you set, and each user’s cost and failures show per user.
Two behaviors to expect. Successful spans arrive with an unset status rather than OK, while the trace status still reads Ok. What the spans carry (prompts, completions, tool arguments) is controlled first by Pydantic AI’s InstrumentationSettings, for example include_content, and then by the SDK’s own privacy controls.
What does not carry over: scores and annotation queues, evals, datasets, prompt management and self-hosting. Rius is a managed service only. Existing traces stay in Langfuse, and Rius starts from the first span you send it.
When something else fits
- If scores, evals, datasets or prompt management are part of how you work, keep Langfuse for those and send your traces to both tools. Rius does not offer them.
- If you want to keep a plain OpenTelemetry setup for Pydantic AI, you can point it at Rius instead of using the SDK, and the Langfuse guide shows the exporter change.