Skip to Content

How do I switch from Arize Phoenix to Rius for the OpenAI Agents SDK?

Rius replaces your Phoenix register() call with rius.init(), which captures the OpenAI Agents SDK’s model calls, and a few observe wrappers add the run and tool structure. You install one package extra, set one API key and name the service, and the same agent runs produce traces in Rius with model, tokens and cost on every model call. You can run Phoenix alongside Rius while you compare, and cut over when Rius shows what you need.

How it works

The OpenAI Agents SDK drives the OpenAI client underneath, so the Rius openai integration captures each model call without framework-specific code. rius.init() turns on every installed integration, so your Phoenix register() call and the auto_instrument=True flag go away with it, and so do your own OpenAIInstrumentor().instrument() calls.

Two things need a line of code each:

  • Run structure. The agent loop and tool executions run inside the framework, so you wrap your entrypoint and your tool bodies with observe to put them in the trace.
  • The framework’s own tracing. It uploads to the OpenAI platform, independent of OpenTelemetry. Turn it off with set_tracing_disabled(True) if Rius should be your only telemetry path.

Two Phoenix concepts map differently. A Phoenix project becomes an agent in Rius, named by service.name, so set it. If you used separate projects per environment, give each environment its own Rius workspace and API key. Cost is computed by Rius from the model and token counts, so you never send it.

For the full Phoenix concept mapping, including the option of keeping your OpenInference instrumentation and only re-pointing the exporter, see Migrate from Arize Phoenix. The wider picture is in Migrate to Rius.

Set it up

  1. Create a Rius workspace and an API key.

  2. Uninstall arize-phoenix-otel, install the Rius extra for OpenAI next to the Agents SDK, and set your key:

    pip install "glassflow-rius[openai]" openai-agents export RIUS_API_KEY="ri_..."
  3. Replace the Phoenix setup. Before:

    from phoenix.otel import register register(project_name="my-agent", auto_instrument=True)

    After, with the agent, its tool and the entrypoint wrapped:

    import rius from agents import Agent, Runner, function_tool, set_tracing_disabled from rius import SpanKind rius.init(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)

    Keep @function_tool outermost and observe on the function body, because the framework reads the function signature for its tool schema. Use underscores in agent names, since hyphens are rewritten in handoff tool names and the framework warns on every run.

  4. Swap using_session and using_user for rius.session and rius.user, and open them around the call to your entrypoint:

    with rius.session(conversation_id): handle_ticket(message)

    The OpenInference context managers do not stamp spans that observe creates, and those are usually the root. rius.session and rius.user stamp every span in scope, the root included.

  5. Run one request that calls a tool and open the trace. The full integration guide is OpenAI Agents SDK, and every supported library is listed under Integrations.

What you get

A run that crosses a handoff 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 AGENT span is your handle-ticket wrapper.
  • Each model call is an LLM generation with model, tokens, cost and time to first token. Costs are list-price estimates in US dollars.
  • Each function tool is a TOOL span named after the tool.
  • Traces group under the session and user you set, and the agent shows up under your service name. With the API key set, the SDK also sends heartbeats so you see which agent processes are alive.

Three details to know. A handoff has no span of its own and shows only as consecutive generations from different agents. Responses API calls are all named Response. Streamed runs carry token counts only when usage is enabled on the underlying OpenAI client, see the OpenAI integration. If handoff boundaries matter, add an observe wrapper per agent entry.

When something else fits

  • If you want the smallest diff and already run OpenInference instrumentors, keep them and re-point the exporter at Rius, and add Rius as a second span processor to run both backends side by side. The Phoenix migration guide has the code.
  • Rius has no evals, datasets, experiments, annotations or prompt management, and it cannot import historical Phoenix traces. If you depend on those, keep Phoenix for them and send new traces to both.

Still stuck? Get help

Last updated on