Skip to Content

I trace AutoGen with Arize Phoenix. How do I switch to Rius?

Rius traces AutoGen after one change: replace Phoenix’s register() call with rius.init(). AutoGen’s own OpenTelemetry spans and the Rius OpenAI integration then produce the full trace. Agent and tool steps arrive from the framework, and each model call arrives as a generation with tokens and cost. See Migrate to Rius for the wider picture.

How it works

  • 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.
  • Model calls. AutoGen sends them through the OpenAI client (autogen-ext[openai]), and the Rius OpenAI integration records each one as a generation with model, tokens and cost.
  • Cost. Rius computes it from the model and token counts, as a list-price estimate in US dollars. You never send a cost value.
  • Instrumentors. rius.init() instruments every supported library it finds installed. Your register() call, the auto_instrument=True flag and any OpenAIInstrumentor().instrument() calls go away with Phoenix’s setup.
  • Projects. A Phoenix project becomes an agent in Rius, named by service_name. If you use separate Phoenix projects per environment, give each environment its own Rius workspace and API key.

The AutoGen integration page covers this setup in full, and the integrations overview lists the other frameworks.

Set it up

  1. Remove arize-phoenix-otel if nothing else in the project uses it. Then install the Rius SDK with the OpenAI integration next to AutoGen, and set your API key:

    pip install "glassflow-rius[openai]" "autogen-agentchat" "autogen-ext[openai]" export RIUS_API_KEY="<your API key>"
  2. Replace register(...) with rius.init(...), and put one observe wrapper on the entrypoint so agent creation and invocation group into a single trace per unit of work:

    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)
  3. Replace using_session with rius.session, reusing your conversation id. One conversation is one session, and rius.session stamps every span in scope, the root included:

    with rius.session(conversation_id): await handle_ticket(ticket)
  4. Leave your tool functions unwrapped. AutoGen runs tools in a detached context, so an observe wrapper on a tool splits off as its own single-span trace. The framework’s execute_tool spans already cover tools.

  5. To evaluate before you switch, send the same spans to both backends instead of steps 1 and 2: keep register() pointed at Phoenix and add Rius as a second span processor, as the Phoenix migration guide shows. Make the swap to rius.init() once Rius shows what you need. The guide also gives the cutover checklist.

What you get

Run one request that calls a tool, then open the trace in the console. It looks like this (a real trace from 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
  • Your entrypoint is the root AGENT span. The framework supplies the create_agent, invoke_agent and execute_tool spans.
  • Each model call is a generation with model, tokens and cost, so you get cost and token analytics per call.
  • Generation spans are named ChatCompletion, and AutoGen’s own span statuses arrive as UNSET on success. The trace status still reads Ok.
  • Rius starts from the first span you send. Existing Phoenix traces stay in Phoenix, and there is no import of historical data.

When something else fits

  • If you want the smallest possible diff, keep your OpenInference instrumentation and re-point the exporter at Rius instead. The Phoenix migration guide shows both paths.
  • Rius has no evals, datasets, annotations or prompt management. If your workflow depends on them, keep those pieces in Phoenix and run both backends side by side rather than cutting over completely.

Still stuck? Get help

Last updated on