How does Rius read OpenLLMetry prompt and completion message attributes?
Rius reads the flattened gen_ai.prompt.* and gen_ai.completion.* attributes from older OpenLLMetry releases and reassembles them into the OpenTelemetry GenAI message shape at ingest. The result is stored under gen_ai.input.messages and gen_ai.output.messages. You see the prompt and completion on the span’s Input / Output tab in the console, with no re-instrumentation of your app.
How it works
OpenLLMetry (Traceloop’s SDK) has used several attribute conventions across versions. Rius normalizes all of them at ingest, moving values onto canonical keys and removing the source keys it mapped.
- Older releases write each message as separate attributes under
gen_ai.prompt.*for the prompt andgen_ai.completion.*for the completion. Rius reassembles these into one JSON array of messages, each with a role and a list of parts, and stores it undergen_ai.input.messagesandgen_ai.output.messages. - Current releases already emit OpenTelemetry GenAI (
gen_ai.*) attributes. Rius reads these directly. - Decorator content: for functions you decorate with Traceloop,
traceloop.entity.inputandtraceloop.entity.outputbecomeinput.valueandoutput.value, so the step’s input and output render like any other span’s. - Span kind:
traceloop.span.kind(workflow, task, agent, tool) and the provider span’sllm.request.typebecome the span taxonomy. The decorated function’s name becomes the tool or agent name. - Usage: older spellings such as
gen_ai.usage.prompt_tokens, and the matching completion count, move to the current token keys, for examplegen_ai.usage.input_tokens. Model, token and cost analytics work across versions.
Native gen_ai.* keys always win. Normalization fills gaps and never overwrites a value you sent.
Two things are not mapped yet. The per-completion gen_ai.completion.N.finish_reason of older releases and the flattened tool definitions under llm.request.functions.* are stored under their own names. Keys with no canonical equivalent, such as llm.usage.total_tokens, also keep their own names.
The reassembled messages follow the GenAI message shape, a JSON array like this:
[
{"role": "user", "parts": [{"type": "text", "content": "What is 2+2?"}]},
{
"role": "assistant",
"parts": [
{"type": "tool_call", "id": "call_1", "name": "calculator", "arguments": "{\"expr\": \"2+2\"}"}
]
},
{
"role": "tool",
"parts": [{"type": "tool_call_response", "id": "call_1", "response": "4"}]
}
]Set it up
- Point OpenLLMetry’s exporter at Rius. OpenLLMetry exports OTLP/HTTP protobuf by default, which is what the endpoint expects. The same values can come from OpenLLMetry’s environment variables if you prefer configuration over code. The OpenLLMetry guide covers this setup in full.
from traceloop.sdk import Traceloop
Traceloop.init(
app_name="my-agent",
api_endpoint="https://ingest.eu.console.rius-glassflow.com",
headers={"Authorization": "Bearer <your API key>"},
)- Run one traced LLM call, then open the trace in the console.
- Open the span for the model call and select its Input / Output tab. Check that the span also shows a model name and token counts.
- When you search or filter in trace inspection, use the canonical keys, such as
gen_ai.usage.input_tokens. A filter ongen_ai.usage.prompt_tokensmatches nothing, because Rius removes that key after mapping it. - On an older release that records messages one attribute per field, long agent runs can pass OpenTelemetry’s default limit of 128 attributes per span. The span then loses data without an error. Raise the limit before you export:
export OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT=4096The span attribute reference lists the full mapping in its supported-conventions table. The interoperability overview lists the other sender paths, and Trace LLM calls with OpenTelemetry compares them on one page.
What you get
- The prompt and completion of each model call render on the span’s Input / Output tab, in the same layout as spans from the Rius SDKs.
- Tool calls and tool results inside the messages show as their own parts, so you can follow what the model asked for and what came back.
- Decorated workflow, task, agent and tool steps appear in the span taxonomy with their names, and their input and output are visible.
- Model, token and cost analytics work for spans from every OpenLLMetry version. Cost is a list-price estimate in US dollars that Rius computes from the model name and token counts. You never send a cost attribute.
- A span with no content attributes shows “Content not captured” on that tab. Its timings, tokens and cost are unaffected.
When something else fits
- If you instrument from scratch and want Rius to handle message shapes for you, the Rius Python or TypeScript SDK sets the GenAI message attributes directly.
- If you emit spans yourself without OpenLLMetry, produce the GenAI message shape shown above, so message rendering in the console works.