I trace AutoGen with Langfuse. How do I switch to Rius?
Rius traces AutoGen with one install line and rius.init(), so you swap the Langfuse setup for the Rius integration and keep your agent code. AutoGen already emits its own OpenTelemetry spans for agents and tools, and the openai integration adds each model call with tokens and cost. You wrap the entrypoint in one observe call, and each unit of work becomes a single trace. This page covers the Python framework (AgentChat).
How it works
The AutoGen integration combines two ways of capturing a run:
- Framework spans. AutoGen emits
create_agent,invoke_agentandexecute_toolspans through the global tracer provider, whichrius.init()installs. Agent and tool structure arrives with no wrappers. - Generations. Model calls go through the OpenAI client from
autogen-ext[openai], and the openai integration records them with model, tokens and cost.
With a default init(), every installed integration turns on automatically, so you do not list AutoGen anywhere. The integrations overview shows where AutoGen sits among the other supported libraries. AutoGen is supported in Python only.
The Langfuse SDK cannot be pointed at Rius, because its exporter and authentication are Langfuse’s own. The Rius SDK has the same shape, with a decorator, context managers and a session scope, so the swap is mostly mechanical. The Langfuse migration guide has the full API mapping, and Migrate to Rius covers the other tools.
Set it up
-
Create a Rius workspace and an API key in the console. Keys start with
ri_. -
Install the SDK with the openai extra, plus AutoGen:
pip install "glassflow-rius[openai]" "autogen-agentchat" "autogen-ext[openai]"- Replace the Langfuse client setup with
rius.init(), and replace the Langfuse@observe()on your entrypoint with@rius.observe. Mark the entrypoint as an agent so it becomes the root span of the trace:
import rius
from autogen_agentchat.agents import AssistantAgent
from autogen_ext.models.openai import OpenAIChatCompletionClient
from rius import SpanKind
rius.init(api_key="ri_...", service_name="my-agent")
def account_status(email: str) -> str:
"""Fetch a customer's account standing by email."""
return lookup(email)
@rius.observe(name="handle-ticket", kind=SpanKind.AGENT)
async def handle_ticket(ticket: str) -> str:
agent = AssistantAgent(
name="support_agent",
model_client=OpenAIChatCompletionClient(model="gpt-5-mini"),
tools=[account_status],
system_message="Answer support questions; check accounts with the tool.",
)
result = await agent.run(task=ticket)
return str(result.messages[-1].content)-
Remove observe wrappers from your AutoGen tool functions. AutoGen runs tools in a detached context, so a wrapper splits off as its own single-span trace. The framework’s
execute_toolspans already cover tools. -
Map sessions and users. Where you used
propagate_attributes(session_id=...), scope the run withwith rius.session(...)and reuse your conversation id. Where you set a user, usewith rius.user(...). -
Run one request that calls a tool and open the trace in the console. Check for the root span, the
invoke_agentandexecute_toolspans, and the generation with model, tokens and cost. -
Once nothing sends to Langfuse, remove its SDK and revoke its keys. While you evaluate, you can keep both running. If Langfuse is the global tracer provider in your process, setting
RIUS_BRIDGE_FOREIGN_PROVIDERto true also sends its spans to Rius.
What you get
A run that calls a tool looks like this (a real trace from the example, autogen-agentchat 0.7.5):
handle-ticket AGENT 2.8s
├─ create_agent support_agent 0ms
└─ invoke_agent support_agent 2.8s
├─ ChatCompletion LLM 2.6s
└─ execute_tool account_status 0ms- One trace per unit of work, rooted at your
observewrapper. - Cost per model call. Rius computes it from the model and token counts as a list-price estimate in US dollars. You never send a cost value.
- Sessions and users from
rius.sessionandrius.user, with each user’s cost, failures and traces on the Users page.
Two quirks to expect: framework spans arrive with an unset status rather than OK on success (the trace status still reads Ok), and generation spans carry the generic name ChatCompletion.
Some Langfuse features do not carry over. Rius has no scores, annotation queues, LLM-as-judge evals, datasets or prompt management. Existing Langfuse traces stay in Langfuse, and Rius starts from the first span you send it.
When something else fits
- If you rely on scores, evals, datasets or prompt management, keep Langfuse for those and send traces to both tools while you decide.
- If your AutoGen code runs in TypeScript, Rius has no AutoGen integration there. Trace those calls with manual generations.
- If you need to self-host your observability backend, Rius does not fit, because it is a managed service only.