Skip to Content

What does the gen_ai.input.messages attribute mean in Rius?

In Rius, gen_ai.input.messages holds the prompt a model call received, as a JSON array of messages in the OpenTelemetry GenAI message shape. Rius shows it on the span’s Input / Output tab. Rius reads it from the span for each model call, and it also builds it from older OpenInference and OpenLLMetry message attributes when those are all a span carries. It is content only: cost and token counts come from other attributes.

How it works

What the key holds. The OpenTelemetry GenAI conventions define it as “the chat history provided to the model as an input”, type any, at Development stability. Messages must be in the order they were sent, and upstream warns that the attribute is likely to hold sensitive data, so it is opt-in there. Its registry entry links the definition. The value is a JSON array. Each message is an object with a role and a list of parts. A text part has the type text and a content string. Tool interactions have their own part types, tool_call and tool_call_response. This is the OpenTelemetry GenAI message schema, and it is the same shape as gen_ai.output.messages, which holds the completion.

Which spans carry it. It belongs on the span for each model call. Agent, tool and retrieval spans use other keys. A tool span’s arguments and result are moved to input.value and output.value.

What Rius shows from it. Spans that carry the key render their prompt and completion on the span’s Input / Output tab. A span without it shows “Content not captured” there. Timings, tokens and cost are unaffected, because Rius computes cost from gen_ai.request.model and the gen_ai.usage.* token counts, never from message text.

Context breakdown. When a span has no rius.context.sizes record, Rius estimates how a call’s input tokens divide across its context from the captured messages, gen_ai.system_instructions and the tool definitions. A system prompt sent separately goes in gen_ai.system_instructions, not in this key.

Older names it is read from. If a sender flattens messages into one attribute per field, Rius rebuilds the GenAI shape at ingest and stores the result under gen_ai.input.messages:

  • OpenInference llm.input_messages.* attributes are reassembled into the array. Anthropic’s system parameter becomes the leading system message.
  • OpenLLMetry and Traceloop legacy gen_ai.prompt.* attributes are reassembled the same way.

A native gen_ai.* key always wins. Normalization fills gaps and never overwrites. Search and filter on gen_ai.input.messages, because the source keys are removed after mapping. The full attribute rules are in the span attribute reference.

Set it up

  1. If you export through the Rius SDKs, you do not set the key by hand. The SDK’s set_input() normalizes OpenAI-style message dicts into the GenAI shape. For SDK setup, see Trace LLM calls with OpenTelemetry.
  2. If you emit spans yourself from a plain OpenTelemetry SDK or a collector, set gen_ai.input.messages on each model-call span to a JSON string in this shape. Produce the shape yourself, or the console cannot render the messages:
[ {"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"}] } ]
  1. Send the same span with gen_ai.request.model and the gen_ai.usage.* token counts, so Rius can compute cost. Do not send a cost attribute.
  2. Content capture is on by default in the Rius SDKs, so they send this key. To keep prompts out of Rius, turn it off. The key is stripped at export and the rest of the span is still sent:
export RIUS_CAPTURE_CONTENT=false

Content attributes such as this one are the ones the SDK’s privacy controls cover. Embedded media bytes in messages are replaced by a placeholder that records the media type and size, and credential header attributes are never stored.

What you get

  • The prompt of each model call, readable on the span’s Input / Output tab, including tool calls and tool responses in the conversation.
  • One stored key to search and filter on, whichever convention the sender used. OpenInference and OpenLLMetry messages land under gen_ai.input.messages.
  • Context attribution that can split a call’s input tokens across its parts, estimated from the captured messages when no size record is present.
  • Unchanged cost, token and timing data when content is off. Spans without the key show “Content not captured” and nothing else changes.

When something else fits

  • If you only need structure, tokens and cost, turn content capture off and leave this key out. Rius still traces and prices the call.
  • If your instrumentation already emits OpenInference or OpenLLMetry attributes, keep them. Rius converts them, so you do not need to rewrite them as gen_ai.input.messages.
  • For a tool’s own input and output, use input.value and output.value, not this key.

Still stuck? Get help

Last updated on