Skip to Content

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_agent and execute_tool spans through the global tracer provider, which rius.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

  1. Create a Rius workspace and an API key in the console. Keys start with ri_.

  2. Install the SDK with the openai extra, plus AutoGen:

pip install "glassflow-rius[openai]" "autogen-agentchat" "autogen-ext[openai]"
  1. 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)
  1. 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_tool spans already cover tools.

  2. Map sessions and users. Where you used propagate_attributes(session_id=...), scope the run with with rius.session(...) and reuse your conversation id. Where you set a user, use with rius.user(...).

  3. Run one request that calls a tool and open the trace in the console. Check for the root span, the invoke_agent and execute_tool spans, and the generation with model, tokens and cost.

  4. 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_PROVIDER to 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 observe wrapper.
  • 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.session and rius.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.

Still stuck? Get help

Last updated on