Skip to Content

How do I see retries and fallbacks for calls to the OpenAI API?

Rius records each OpenAI chat completion as its own span, so a failed attempt and the retry or fallback after it show up as separate steps in the trace. Failed calls are marked ERROR with the error class, and a run that fails and then recovers is badged recovered. Wrap your retry or fallback logic in observe so the attempts sit together under one span in your agent’s run.

How it works

  • What the integration records. Each chat completion becomes a span for the model call, with the model, token usage and the input and output messages. Rius computes the cost from the model and the tokens.
  • What a failed call looks like. A call OpenAI rejects, such as a 404 for an unknown model, a 429 or a timeout, is recorded as an ERROR span. Its error.type names the error class, for example openai.NotFoundError.
  • The client’s own retries. The OpenAI client retries rate limits, server errors and timeouts by itself (max_retries, 2 by default) inside one create() call, so those attempts make one span, not several. Create the client with OpenAI(max_retries=0) and retry in your own code when you want each attempt as its own span.
  • What needs your own span. The integration records model calls. Your decision to try again or switch models lives in your code, so wrap the function that holds that logic in observe. A bare observe makes a span named after the function, and the model calls inside it nest underneath. Without it, each call shows up as a standalone trace instead of inside your agent’s run. The OpenAI integration page covers what is captured per call.
  • Where it shows. Open the trace on the Traces page. In the waterfall, spans are laid out as a tree on a timeline, and failed spans are highlighted along the path from the root to the error. A fallback to another model appears as a second model-call span, and its Model section shows the requested and response model.
  • Recovered runs. If child spans errored but the root span finished without an error of its own, the trace is badged recovered. The errors are still counted, only the verdict changes.
  • Retry chains. Back-to-back calls of the same tool or step with the same input collapse into one row, such as fetch_article · 3 attempts · recovered, when every attempt but the last failed. Expand the row to see each attempt. Repeated calls that all succeeded stay separate rows.

Set it up

  1. Install the OpenAI instrumentation with pip install "glassflow-rius[openai]" openai and call init() once at startup. The OpenAI integration page has the full setup, including TypeScript, and the Integrations page lists the other libraries.
  2. Put the function that makes the OpenAI call under observe, so every attempt lands inside one span:
import rius from openai import OpenAI rius.init(api_key="ri_...", service_name="my-agent") client = OpenAI() @rius.observe def answer(question: str) -> str: response = client.chat.completions.create( model="gpt-4o-mini", messages=[{"role": "user", "content": question}], ) return response.choices[0].message.content
  1. Keep your retry loop or your fallback to a second model inside that function. In TypeScript, wrap a named function with observe the same way, because an anonymous one traces as anonymous.
  2. For streamed calls, pass stream_options={"include_usage": True} in Python (stream_options: { include_usage: true } in TypeScript). Without it a streamed attempt has no token counts and so no cost.
  3. Run a call that fails, then open Traces. To find attempts across runs, open the Spans tab, choose LLM in the All kinds menu and filter by failed status. Press ]e to jump to the next failed span and ]l to jump to the next LLM span.

What you get

  • One span per OpenAI call, so you can count how many attempts a run made and see which one succeeded.
  • The error class on every failed attempt, so a rate limit, a timeout and an unknown model are told apart at a glance.
  • A recovered badge on runs that failed along the way but finished clean, so you can separate them from genuine failures.
  • Tokens and a list-price cost estimate on each attempt that reports usage. An attempt that reported no token usage shows a blank cost rather than $0.
  • The model on each attempt, so you can check that a fallback actually switched models.

For the wider view of watching agents in production, see Monitor AI agents in production, and for everything the trace page offers, see Exploring traces.

When something else fits

  • If you only need the number of failed calls over time, the aggregate usage view or an alert on error rate fits better than reading individual traces.
  • If your retry logic runs in a layer that sits above several providers, trace that layer with its own integration from the Integrations page, or with your own observe span, so the attempts still nest under one run.

Still stuck? Get help

Last updated on