Skip to Content

How does Rius read OpenInference agent name attributes?

Rius reads an OpenInference agent through openinference.span.kind set to AGENT, and takes the agent’s name from gen_ai.agent.name and the resource agent attributes. Rius classifies the span as an agent step and files it under the agent name it finds. You can send OpenInference spans straight to the ingest endpoint, with or without the Rius SDK.

How it works

Rius combines the OpenInference span kind with the OpenTelemetry GenAI agent attributes.

  • Span kind. openinference.span.kind with the value AGENT classifies the span as an agent span in trace views and per-kind analytics. Set it, or set gen_ai.operation.name to invoke_agent, and Rius derives the other one.
  • Agent name on the span. gen_ai.agent.name on an invoke_agent span is the agent being invoked. On an execute_tool span it is the agent executing the tool.
  • Agent name for the process. Rius files a span under the first of these that is set and is not a placeholder such as unknown_service: the resource’s gen_ai.main_agent.name, the resource’s rius.main_agent.name, the resource’s gen_ai.agent.name, the span’s gen_ai.agent.name, and service.name.
  • Normalization at ingest. The OpenInference attributes Rius moves onto gen_ai.* keys are the LLM detail ones: llm.model_name, llm.provider, llm.token_count.*, llm.invocation_parameters, llm.tools.* and the flattened llm.input_messages.* and llm.output_messages.*. The agent name is not one of them, so send it as gen_ai.agent.name or as a resource attribute. Native gen_ai.* keys always win, and normalization only fills gaps.
  • Span names. Rius does not require it, but the convention is the operation followed by what it acted on, such as invoke_agent planner, which keeps mixed fleets readable.

The full contract is in the span attribute reference, and the overview of every sender path is in Interoperability.

Set it up

  1. Wire your OpenInference instrumentor to the Rius ingest endpoint. This is the only setup this question needs, and the OpenInference page 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. Name the agent on the resource. Set gen_ai.main_agent.name as a resource attribute. If you send nothing else, set service.name, which Rius uses when no agent attribute is present.
  2. Mark each agent step. The OpenAI instrumentor only emits model call spans, so start the agent span yourself around the agent’s work. Give it openinference.span.kind of AGENT, set gen_ai.agent.name to the agent’s name, and name it in the form invoke_agent planner:
tracer = provider.get_tracer(__name__) with tracer.start_as_current_span( "invoke_agent planner", attributes={"openinference.span.kind": "AGENT", "gen_ai.agent.name": "planner"}, ): run_planner(task) # your agent's own code
  1. Keep the agent attributes from being dropped. OpenInference writes one attribute per message and tool field, and OpenTelemetry keeps only 128 attributes per span by default, dropping the rest without an error. Raise the limit through the environment for any language:
export OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT=4096
  1. Run the agent and open the trace in the console to confirm the span kind and the agent name.

What you get

  • Spans with openinference.span.kind of AGENT are classified as agent spans in trace views and per-kind analytics, and their operation is derived as invoke_agent.
  • Each span is filed under the first agent name Rius finds in the order above, so the agent you named is the one you see in the console.
  • Agent steps sit in the same trace as the LLM calls under them. Those calls are normalized from the llm.* attributes, so they get model analytics, token usage and server-side cost like native spans. Cost is a list-price estimate in US dollars.
  • Tool spans that carry gen_ai.agent.name show which agent executed the tool.
  • Search and filter on the stored gen_ai.* keys, such as gen_ai.usage.input_tokens, not on the OpenInference source keys.

For a comparison of every way to send traces, see Trace LLM calls with OpenTelemetry.

When something else fits

  • If your app is Python, the Rius SDK ships the same OpenInference instrumentors as integrations and sets the exporter, the attribute limit and privacy controls for you.
  • If you want control over agent names directly, send the GenAI attributes from a vanilla OpenTelemetry SDK or an OpenTelemetry Collector instead of relying on OpenInference.

Still stuck? Get help

Last updated on