Skip to Content

What does the gen_ai.request.model attribute mean in Rius?

Rius reads gen_ai.request.model as the model your code asked for on a span, and uses it to compute cost and to count the span as an LLM call. The value is a string, such as the model name you pass to your provider’s client. Rius prices the span from this model plus its token counts, so you never send a cost value. The key comes from the OpenTelemetry GenAI conventions and is listed on the span attribute reference.

How it works

  • What it holds. The requested model, as a string. The provider can report a different model back, and that value lives in gen_ai.response.model.
  • Which spans carry it. The span for each model call. The Rius SDKs and their integrations set it for you. If you send spans from a vanilla OpenTelemetry SDK or a collector, you set it yourself.
  • Cost. Rius computes cost on the server from gen_ai.request.model plus the gen_ai.usage.* token counts: input, output, cache read and cache write, each priced at its own rate. A span needs the model and at least one of those counts. A count it leaves out is read as 0. A span with no model, a model the price catalog does not know, or none of the counts gets no cost, which is an empty cost and not zero. Costs are list-price estimates in US dollars, not billed amounts.
  • LLM call counting. The console and alerts count a span as an LLM call when its kind is LLM, set directly or derived from the chat, text_completion or generate_content operation. A span with neither a kind nor an operation counts when it carries gen_ai.request.model. Agent, tool and retrieval spans are not LLM calls even when they carry a model. Embedding calls are not either, but their cost still appears in the per-model breakdown and the cost totals.
  • Reranking spans. A reranking span shows as LLM when it carries gen_ai.request.model, and as Other when it does not.
  • Older names. For OpenInference spans, Rius moves the model onto gen_ai.request.model at ingest. It takes llm.request.model_name first, then the model member of llm.invocation_parameters, then llm.model_name. A native gen_ai.request.model always wins, and the source keys it mapped are removed. The Rius SDKs apply the same mapping before export, except they skip the llm.model_name fallback, which only the platform applies.

Set it up

  1. With the Rius SDK, set nothing. An installed integration records the model you pass to the call. For example, with Anthropic in Python, install the extra and the library. The SDK setup is covered in Trace LLM calls with OpenTelemetry.

    pip install "glassflow-rius[anthropic]" anthropic
  2. Pass the model on the call. In this example the span for the messages.create call carries gen_ai.request.model with the value claude-haiku-4-5-20251001:

    import anthropic import rius rius.init(api_key="ri_...", service_name="my-agent") claude = anthropic.Anthropic() # reads ANTHROPIC_API_KEY @rius.observe def handle(query: str) -> str: response = claude.messages.create( model="claude-haiku-4-5-20251001", max_tokens=200, messages=[{"role": "user", "content": query}], ) return response.content[0].text handle("What should I check when a collector drops spans?")
  3. From a vanilla OpenTelemetry SDK or a collector, set gen_ai.request.model on the span of each model call, together with gen_ai.usage.input_tokens and gen_ai.usage.output_tokens. Set gen_ai.operation.name to chat as well, and Rius derives the LLM kind from it. Do not send a cost attribute.

  4. From OpenInference, keep your instrumentation as it is. Rius fills gen_ai.request.model from the keys above.

  5. To find the spans, search or filter on gen_ai.request.model. Filter on this key and not on llm.model_name: after normalization the source key is removed and a filter on it matches nothing. It is an OpenTelemetry GenAI convention key, listed in the registry.

What you get

  • Cost per model call, priced from the requested model and the token counts, with cache reads and writes at their own rates.
  • A per-model breakdown and cost totals, including the cost of embedding calls.
  • Correct LLM call counts in the console and in alerts, including spans that have no kind or operation but do have a model.
  • One key to search and filter on, whether the spans came from the Rius SDK, plain OpenTelemetry or OpenInference.
  • Alerts on model spend. Tokens and cost sit on model-call spans, so filter an alert on Model to measure them.

When something else fits

  • If you need the model the provider actually served, read gen_ai.response.model. It is the model the provider reports back and can differ from the one you requested.
  • If a span shows no cost, check that it carries a model name the price catalog knows and at least one gen_ai.usage.* count. Rius does not price a model it cannot find, and it does not accept custom prices.

Still stuck? Get help

Last updated on