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.modelplus thegen_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 thechat,text_completionorgenerate_contentoperation. A span with neither a kind nor an operation counts when it carriesgen_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
LLMwhen it carriesgen_ai.request.model, and as Other when it does not. - Older names. For OpenInference spans, Rius moves the model onto
gen_ai.request.modelat ingest. It takesllm.request.model_namefirst, then themodelmember ofllm.invocation_parameters, thenllm.model_name. A nativegen_ai.request.modelalways wins, and the source keys it mapped are removed. The Rius SDKs apply the same mapping before export, except they skip thellm.model_namefallback, which only the platform applies.
Set it up
-
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 -
Pass the model on the call. In this example the span for the
messages.createcall carriesgen_ai.request.modelwith the valueclaude-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?") -
From a vanilla OpenTelemetry SDK or a collector, set
gen_ai.request.modelon the span of each model call, together withgen_ai.usage.input_tokensandgen_ai.usage.output_tokens. Setgen_ai.operation.nametochatas well, and Rius derives theLLMkind from it. Do not send a cost attribute. -
From OpenInference, keep your instrumentation as it is. Rius fills
gen_ai.request.modelfrom the keys above. -
To find the spans, search or filter on
gen_ai.request.model. Filter on this key and not onllm.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.