Skip to Content

How does Rius read OpenInference conversation id attributes?

Rius reads the OpenInference conversation id, which OpenInference carries as session.id, as the session key and groups the traces that share it into one session. Rius stores the attribute as sent, with no renaming. Set it on every span, and the traces of one conversation appear together in the console.

How it works

  • The attribute name. OpenInference’s conversation key is session.id. Rius lists it with user.id as the OpenInference session and user family, and uses both for session and user grouping.
  • No renaming. Many OpenInference attributes, such as llm.token_count.prompt, are normalized onto gen_ai.* keys at ingest. session.id is not one of them. It is stored as sent, so you search and filter on session.id. The full contract is in the span attribute reference.
  • Read per span. Rius reads the session from each span, not only from the root. A span without session.id falls back to gen_ai.conversation.id, the key the OpenTelemetry GenAI conventions use. If neither is present, the span is grouped by its trace id, so the trace becomes its own session.
  • Users work the same way. user.id marks the user a request served. When it is absent, Rius also reads enduser.id, then enduser.pseudo.id. A span with none of them is anonymous.
  • Everything else is unchanged. The span kind, model, tokens and cost of the same spans are handled as described on the OpenInference page. Session grouping does not depend on them.

Set it up

  1. Send your OpenInference spans to the Rius ingest endpoint. This is the shared wiring from the OpenInference page, which covers it in full:
from opentelemetry.sdk.trace import SpanLimits, TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter from openinference.instrumentation.openai import OpenAIInstrumentor # Raise the attribute limit: see step 4 below. provider = TracerProvider(span_limits=SpanLimits(max_span_attributes=4096)) provider.add_span_processor( BatchSpanProcessor( OTLPSpanExporter( endpoint="https://ingest.eu.console.rius-glassflow.com/v1/traces", headers={"Authorization": "Bearer <your API key>"}, ) ) ) OpenAIInstrumentor().instrument(tracer_provider=provider)
  1. Give every span of a conversation the same session.id value, including the root span. Wrap each turn in OpenInference’s using_session(conversation_id) from openinference-instrumentation, and keep the same value across every turn so the traces group together. using_session only stamps spans OpenInference creates, so a root span you start from a plain OpenTelemetry tracer needs session.id set on it by hand. The trace list shows each trace under the session of its root span. If you send through the Rius SDK instead, rius.session in Python and withSession in TypeScript stamp it for you.
  2. Add user.id to the same spans if you want per-user views. Prefer an opaque id to an email.
  3. Raise the span attribute limit. OpenInference writes one attribute per message field and tool field, and OpenTelemetry keeps only 128 per span by default, so a long agent loop can silently lose attributes. The code above sets it in Python. For any language you can set it through the environment:
export OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT=4096
  1. Run two turns of the same conversation and confirm that both traces show under one session in the console. If you want the whole picture of sender options, Trace LLM calls with OpenTelemetry compares them on one page.

What you get

  • Traces that share a session.id group into one session, so a multi-turn conversation reads as one unit instead of separate traces.
  • Per-user grouping from user.id, with enduser.id and enduser.pseudo.id as fallbacks.
  • A predictable fallback. Spans without session.id use gen_ai.conversation.id, and spans with neither stay grouped by trace.
  • A key you can search and filter on exactly as you sent it, because session.id is stored as sent.
  • The same model analytics, token usage and server-side cost on the same spans, since OpenInference’s LLM attributes are normalized onto gen_ai.* keys at ingest.

When something else fits

  • If your instrumentation follows the OpenTelemetry GenAI conventions, send gen_ai.conversation.id. Rius reads it as the session whenever session.id is absent.
  • If you want each run to stand alone, send no session key. Each trace is then its own session.
  • For the complete list of attributes Rius reads and how each convention is treated, see the interoperability overview.

Still stuck? Get help

Last updated on