How do I group spans into sessions with OpenLLMetry?
OpenLLMetry’s conversation helpers stamp gen_ai.conversation.id on every span in scope, and Rius reads that key as the session, so you wrap each conversation in @conversation or call set_conversation_id() before the root span starts. In TypeScript the helper is withConversation(). Without a session key, each trace is its own session.
How it works
Rius reads the session from each span, not from the trace as a whole. It uses the first of these that is set:
session.id, the key to use.gen_ai.conversation.id, the OpenTelemetry GenAI conventions’ session key, which Rius reads whensession.idis absent.- Otherwise the span’s trace id, so each trace is its own session.
Because the value is read per span, set it on every span of the trace, root included. A span without it falls back to the next key in the list, which can split one conversation into several sessions.
OpenLLMetry’s @conversation, set_conversation_id() and withConversation() write gen_ai.conversation.id, so they need no extra setup. OpenLLMetry’s association properties are different: a chat_id or session_id property arrives as traceloop.association.properties.<key>, which you can inspect but which Rius does not read as the session.
The Rius SDK’s session scopes (rius.session in Python, withSession in TypeScript, or RIUS_SESSION_ID for a whole process) stamp session.id for you. They belong to the Rius SDK. An OpenLLMetry exporter is a third-party sender, so it sets the attribute directly.
Set it up
- Point OpenLLMetry at Rius, as on the OpenLLMetry page. This is the whole shared setup:
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>"},
)-
Pick a session value that stays the same for everything you want grouped, such as a conversation id or an agent run id. Use an opaque id, not something personal.
-
Wrap the conversation in
@conversationor callset_conversation_id()(TypeScript:withConversation()) before the root span starts. OpenLLMetry then writesgen_ai.conversation.idon every span in scope. The trace list shows each trace under the session of its root span, so an id set after the root span starts does not group that trace. -
If you also track end users, set
user.idwith the OpenTelemetry API inside your outermost@workflowor@agent, as in How do I attach an end user with OpenLLMetry?. OpenLLMetry does not set it, and a span with no user id counts as anonymous. -
Run two traced calls with the same session value, open the traces in the console, and check that the spans carry
gen_ai.conversation.idand that both traces appear under one session.
If your agent runs long loops on an older OpenLLMetry release, those releases record messages one attribute per field. OpenTelemetry then drops attributes past 128 per span without an error, and session.id can be among them. Raise the limit as described in Attribute count limit.
What you get
- Traces that share a
session.idare grouped into one session, such as a conversation or an agent run, instead of each trace standing alone. - Model, token and cost analytics keep working as before, because Rius normalizes OpenLLMetry’s attribute versions onto its canonical keys.
- No extra attributes to manage: the conversation id OpenLLMetry already writes is the session key Rius reads.
The full list of session and user keys is in the span attribute reference. For the other ways to send traces to Rius, see Trace LLM calls with OpenTelemetry.
When something else fits
- If you would rather not stamp attributes yourself, the Rius SDK sets
session.idfor you through its session scopes, andRIUS_SESSION_IDcovers a whole process. - If every trace is a self-contained request with no conversation to join, leave
session.idunset and each trace stays its own session.