How do I switch from Langfuse to Rius for the OpenAI Agents SDK?
To switch from Langfuse to Rius, you replace the Langfuse setup with rius.init and the Rius OpenAI Agents SDK integration, which captures every model call. Each call arrives as a generation with model, tokens and cost. You add observe wrappers around your entrypoint and tool functions so the run and its tools show up as spans. The integration is available in Python, and you can keep sending to Langfuse from other services while you compare.
How it works
The OpenAI Agents SDK drives the OpenAI client underneath, so the Rius openai integration captures its model calls without framework-specific code. rius.init() turns on every installed integration, so there is no per-framework hook to configure. This is why the switch is mostly deleting the Langfuse setup and adding two things:
- The run structure. The agent loop and tool executions run inside the framework, and auto-instrumentation only sees the client calls that come out of it. Wrapping your entrypoint and your tool bodies with
observeputs that structure in the trace. - The framework’s built-in tracing. It uploads to the OpenAI platform and is independent of OpenTelemetry. Call
set_tracing_disabled(True)if Rius should be your single telemetry path. Leaving it on reports to two backends but does not interfere with Rius.
If you wrapped functions with the Langfuse @observe() decorator, the Rius equivalent is @rius.observe. Langfuse propagate_attributes(session_id=...) becomes with rius.session(session_id):, and propagate_attributes(user_id=...) becomes with rius.user(user_id):. The Langfuse migration guide has the full mapping, and Migrate to Rius covers the other tools.
Set it up
-
Create a Rius workspace and an API key. Keys start with
ri_. A new organization starts on a trial of 30 days or 500,000 spans, whichever comes first, with no card. -
Install the Rius SDK with the OpenAI extra next to the Agents SDK:
pip install "glassflow-rius[openai]" openai-agents-
Remove what sends this agent’s traces to Langfuse: the Langfuse client setup with its key pair, and any exporter pointed at Langfuse. One
RIUS_API_KEYreplaces the pair. -
Initialize Rius, disable the framework’s own tracing, and wrap the entrypoint and tools. Put
@function_tooloutermost andobserveon the function body, because the framework reads the function signature for its tool schema:
import rius
from agents import Agent, Runner, function_tool, set_tracing_disabled
from rius import SpanKind
rius.init(api_key="ri_...", service_name="my-agent")
set_tracing_disabled(True)
@function_tool
@rius.observe(kind=SpanKind.TOOL)
def account_status(email: str) -> str:
"""Fetch a customer's account standing by email."""
return lookup(email)
support_agent = Agent(
name="support_agent",
instructions="Answer support questions; check accounts with the tool.",
tools=[account_status],
model="gpt-5-mini",
)
@rius.observe(name="handle-ticket", kind=SpanKind.AGENT)
def handle_ticket(ticket: str) -> str:
result = Runner.run_sync(support_agent, ticket)
return str(result.final_output)Here lookup is your own function. Name agents with underscores, not hyphens: the framework rewrites hyphens in the generated handoff tool name and warns on every run.
-
Scope each run with
rius.session(), reusing your conversation or ticket id, so every turn of one conversation groups together. -
Run one request that calls a tool and open the trace in the console. Check for the root agent span, the model generations with tokens and cost, and your named tool spans.
-
Compare before you cut over. You can run the swapped SDK in one service while the rest still report to Langfuse. When Rius shows what you need, remove the Langfuse setup and revoke its keys. The full checklist is in the Langfuse migration guide, and the OpenAI Agents SDK integration page covers the framework in detail.
What you get
After the switch, a run that crosses a handoff, from a triage agent to a billing agent, looks like this:
handle-ticket AGENT 9.8s
├─ Response LLM 2.3s triage decides to hand off
├─ Response LLM 2.8s billing agent decides to call the tool
├─ execute_tool account_status TOOL 0ms
└─ Response LLM 4.6s billing agent answers- The root span is your
observewrapper around the run. - Each model call is a generation with model, tokens, cost and time to first token. Cost is a list-price estimate in US dollars, computed by Rius, so you never send it.
- Each function tool is a tool span named after your function.
- Traces group by session and by user, with each user’s cost, failures and traces on the Users page.
Two blind spots to know, verified against openai-agents 0.22.0. A handoff produces no span of its own, so it shows only as consecutive generations from different agents. To mark handoff boundaries, add an observe wrapper per agent entry, or use the framework’s RunHooks to open spans at agent boundaries. Model calls on the Responses API are all named Response, so the span name does not tell you which agent spoke.
Streamed runs carry token counts only if usage is enabled on the underlying OpenAI client. See the include_usage note on the OpenAI integration page.
When something else fits
Rius has no scores, annotation queues, evals, datasets or prompt management, and existing traces stay in Langfuse because Rius starts from the first span you send. If you rely on those, keep Langfuse for them and send traces to both tools. The OpenAI Agents SDK integration is Python only, so for other languages and frameworks see the integrations list.