Skip to Content

I trace the OpenAI API with Helicone. How do I switch to Rius?

Rius traces the OpenAI API from inside your process, so you switch by calling rius.init() and pointing the OpenAI client back at its default base URL. Each call then shows up as a generation with the model, token counts, messages and a computed cost. You can keep the Helicone proxy in place while you compare the two. See Migrate to Rius for the other tools.

How it works

Helicone logs a call as it passes through a proxy: your OpenAI client uses a Helicone base URL and a Helicone-Auth header. Rius works differently. The Rius SDK patches the OpenAI client library inside your process and exports OpenTelemetry spans, so nothing sits between your code and OpenAI.

  • rius.init() detects the installed OpenAI integration and instruments the client process-wide. You use the client exactly as before.
  • The integration patches the library, not the network path, so calls are traced whatever base URL the client uses. That is why you can keep the Helicone gateway and run both tools side by side.
  • If you use Helicone’s async logger instead of the proxy, the swap is one call: remove the logger and call rius.init(). Both register the process-wide OpenTelemetry tracer provider, and only the first registration is kept, so do not run both in one process.

The OpenAI integration page covers the details, and Integrations lists the other libraries and frameworks.

Set it up

  1. Install the SDK with the OpenAI integration and set your key. In Python the extra installs the instrumentation, not openai itself.

    pip install "glassflow-rius[openai]" openai export RIUS_API_KEY="ri_..."

    In TypeScript, install @glassflow-ai/rius, @opentelemetry/api and @arizeai/openinference-instrumentation-openai with npm.

  2. Replace the Helicone client setup. Drop the base URL and the auth header, create the default client, and call init() at startup.

    # Before: through the Helicone proxy import os from openai import OpenAI openai_client = OpenAI( base_url="https://oai.helicone.ai/v1", default_headers={"Helicone-Auth": f"Bearer {os.environ['HELICONE_API_KEY']}"}, )
    # After: direct to OpenAI, traced by Rius import rius from openai import OpenAI rius.init(service_name="my-agent") # reads RIUS_API_KEY openai_client = OpenAI() # default base URL, OPENAI_API_KEY
    // After: direct to OpenAI, traced by Rius import { init } from '@glassflow-ai/rius' import OpenAI from 'openai' const rius = init({ serviceName: 'my-agent' }) // reads RIUS_API_KEY await rius.ready // wait until instrumentation is attached before the first call const openai = new OpenAI() // default base URL, OPENAI_API_KEY

    Call init() before you create the client. If you used helicone_async (or @helicone/async in TypeScript), remove the logger and add only the init() call. If you rely on the proxy for caching, rate limits or fallbacks, or want to compare both tools before cutover, leave the Helicone base URL and headers in place and add init() anyway.

  3. Carry over the values you send as Helicone headers, and remove the headers themselves at cutover. Helicone-Session-Id becomes a session scope and Helicone-User-Id becomes a user scope:

    with rius.session(session_id): with rius.user(request.user_id): with rius.start_as_current_span("support_ticket"): response = openai_client.chat.completions.create( model="gpt-4o-mini", messages=messages, )

    Replace Helicone-Property-* headers with span attributes on the span that wraps the work. Use plain model names such as gpt-4o-mini, not the gateway’s gpt-4o-mini/openai form, or calls show tokens but no cost.

  4. For streamed calls, pass stream_options with include_usage set to true ({"include_usage": True} in Python), or the call has no token counts and no cost.

  5. Run one call and open the trace in the console. Check the model, token counts and cost, then follow the Helicone migration guide for the cutover checklist.

What you get

  • One generation per OpenAI call. It carries the resolved model, input and output tokens (cache reads and writes included) and the input and output messages.
  • Computed cost. Rius prices each call from the model and token counts. These are list-price estimates in US dollars, not billed amounts.
  • A real trace tree. Wrap your handler in observe and the OpenAI call nests inside your agent’s run. The tree comes from how your spans nest, not from a Helicone-Session-Path string, so nest a ticket span with an answer span inside it to keep that structure.
  • Sessions and users. session.id and user.id appear on every span in scope, and the Users page lists each user with traces, failures and cost.
  • Errors. A rejected call, such as a 404 for an unknown model, a 429 or a timeout, is recorded as an ERROR span with error.type naming the error class.
  • Streaming. The Python integration records time to first token on streamed calls. TypeScript streamed completions carry token usage and cost with include_usage, but no time to first token.
  • Privacy control. capture_content=False (captureContent: false in TypeScript) strips prompts and completions at export.

If Helicone served a response from its cache, Rius records it like any other call and prices it from its tokens. While both run, Rius cost is higher than Helicone’s by your cache-hit share.

When something else fits

Rius is not a gateway, so keep the Helicone proxy, or another gateway, if you depend on caching, rate limits, retries or fallbacks. Rius also has no prompt management, scores, datasets or evals, and it cannot import your Helicone history, so keep Helicone for those and start Rius traces from the cutover.

Still stuck? Get help

Last updated on