Skip to Content

How does Rius read OpenTelemetry GenAI agent name attributes?

Rius reads the agent name from gen_ai.agent.name on each span and from gen_ai.main_agent.name on the resource, and files each span under the first of these that is set. If none is set, Rius falls back to service.name. Set the names the way the GenAI conventions ask and your traces group by agent without extra configuration. The span attribute reference is the contract for every key mentioned here.

How it works

Rius uses two levels of agent name.

Span level. gen_ai.agent.name has a different meaning depending on the span:

  • On an invoke_agent span, it is the agent being invoked.
  • On an execute_tool span, it is the agent executing the tool.

Rius also derives the span kind from the operation, so invoke_agent and create_agent spans are classified as AGENT. The GenAI conventions name these spans the operation followed by the agent, for example invoke_agent planner.

Resource level. gen_ai.main_agent.name names the agent the whole process runs, and gen_ai.main_agent.description says what it does. rius.main_agent.name is deprecated in favor of gen_ai.main_agent.name. Rius still reads it, so telemetry that sends only that key keeps its agent name.

Rius files a span under the first of these that is set and is not a placeholder such as unknown_service:

  1. the resource gen_ai.main_agent.name
  2. the resource rius.main_agent.name
  3. the resource gen_ai.agent.name
  4. the span’s gen_ai.agent.name
  5. service.name

Normalization. Other conventions are mapped onto the same names at ingest, and native gen_ai.* keys always win:

  • From OpenLLMetry (Traceloop), the decorated entity’s name becomes the invoked agent name or the tool name.
  • From Laminar, lmnr.association.properties.metadata.agent.name becomes the agent name.

Search and filter on the canonical key, not on the source key.

Set it up

  1. Set the process-wide name as a resource attribute. If you send telemetry without the Rius SDK, set gen_ai.main_agent.name on the resource of your OpenTelemetry setup. Always set service.name too, because it is the last fallback.
  2. On each agent run, emit a span with gen_ai.operation.name set to invoke_agent, gen_ai.agent.name set to the agent’s name, and a span name such as invoke_agent planner. If the agent is hosted, add gen_ai.agent.id, and gen_ai.agent.version for the agent definition’s version.
  3. On each tool span, use execute_tool, put the tool’s own name in gen_ai.tool.name, and put the calling agent in gen_ai.agent.name.
  4. If you use the Rius SDK, name the agent once. The SDK sends gen_ai.main_agent.name alongside gen_ai.main_agent.id, and uses the agent name as the id when you configure no id. Set the name with an environment variable:
export RIUS_AGENT_NAME=planner

RIUS_AGENT_NAME is the name the agent is grouped under, and it defaults to the service name. RIUS_MAIN_AGENT_ID and RIUS_MAIN_AGENT_DESCRIPTION set the id and description. 5. To compare releases of the same agent, also set rius.main_agent.version on the resource. With the Rius SDK, set RIUS_MAIN_AGENT_VERSION instead. The GenAI conventions have no equivalent, so this key is not deprecated.

For installing and wiring a sender in full, see Trace LLM calls with OpenTelemetry and the interoperability overview.

What you get

  • Spans group under one agent name in the console, taken from the first set name in the order above, instead of a placeholder service name.
  • Agents are found from traces and heartbeats, with no registration step. The SDKs send service.instance.id in their heartbeats, which joins traces to the Agents view.
  • invoke_agent spans classify as agent spans, and execute_tool spans classify as tool spans, so per-kind views and filters work.
  • Tool calls show which agent ran them, because gen_ai.agent.name sits on the execute_tool span.
  • Traces from OpenLLMetry and Laminar senders carry their agent names onto the same canonical keys, so mixed fleets read alike.
  • With rius.main_agent.version set, you can compare two versions of an agent on traces, failed rate, cost per trace, latency and tokens per trace.

When something else fits

  • If you use the Rius SDK, set the name with RIUS_AGENT_NAME or service_name and let it emit the attributes for you.
  • If you only need to group by service, service.name is enough, because it is the last fallback. Set the agent name keys when one service runs several agents.
  • If your keys come from another convention, read the supported-conventions table in the span attribute reference to see which are normalized.

Still stuck? Get help

Last updated on