How do I set the agent name attribute on an OpenTelemetry span in Python?
Rius reads the agent name from the gen_ai.agent.name attribute, which you set on a span with span.set_attributes from the standard OpenTelemetry Python API. Set it on the invoke_agent span for the agent being invoked, and on each execute_tool span for the agent running the tool. To name the agent your whole process runs, set gen_ai.main_agent.name as a resource attribute. Rius then shows each span under that agent name.
How it works
Rius uses two attributes for agent names, one on spans and one on the process:
gen_ai.agent.nameon aninvoke_agentspan is the agent being invoked.gen_ai.agent.nameon anexecute_toolspan is the agent executing the tool.gen_ai.main_agent.nameis a resource attribute. It names the agent the whole process runs.
Mark the agent span so Rius classifies it. Set gen_ai.operation.name to invoke_agent, or openinference.span.kind to AGENT. Set either one and Rius derives the other. The GenAI conventions name the span as the operation followed by what it acted on, such as invoke_agent planner. Rius does not require it, but the Rius SDKs emit that form, so spans from different senders read alike.
Rius files each span under the first of these that is set and is not a placeholder such as unknown_service:
- the resource
gen_ai.main_agent.name - the resource
rius.main_agent.name(deprecated, but still read) - the resource
gen_ai.agent.name - the span’s
gen_ai.agent.name service.name
So if you set the resource attribute, it decides the agent a span is filed under. A span-level gen_ai.agent.name is used only when none of the resource attributes is set. If you send telemetry without a Rius SDK and want a clear agent name in Rius, set gen_ai.main_agent.name. Keep service.name set as well, because every trace view and filter groups by it.
Set it up
-
Register a tracer provider that exports to Rius. The code below is the standard setup from Vanilla OpenTelemetry SDKs, with a resource added that names the agent. That page also covers the exporter environment variables and the API key header. Rius accepts OTLP over HTTP only, with no gRPC endpoint.
from opentelemetry import trace from opentelemetry.sdk.resources import Resource from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter # The resource names the service and the agent your process runs resource = Resource.create({ "service.name": "my-agent", "gen_ai.main_agent.name": "planner", }) # With no arguments, the exporter reads the OTEL_EXPORTER_OTLP_* variables provider = TracerProvider(resource=resource) provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter())) trace.set_tracer_provider(provider) -
Start the agent span and set its name. Replace
plannerwith your own agent’s name.tracer = trace.get_tracer("my-agent") with tracer.start_as_current_span("invoke_agent planner") as span: span.set_attributes({ "gen_ai.operation.name": "invoke_agent", "openinference.span.kind": "AGENT", "gen_ai.agent.name": "planner", }) # ... run the agent ... -
Set the same name on the tool spans the agent runs. Nest them inside the agent span in the normal OpenTelemetry way so they arrive as one trace. Put the tool’s own name in
gen_ai.tool.name, never in the span name alone.with tracer.start_as_current_span("execute_tool get_weather") as tool_span: tool_span.set_attributes({ "gen_ai.operation.name": "execute_tool", "openinference.span.kind": "TOOL", "gen_ai.tool.name": "get_weather", "gen_ai.agent.name": "planner", }) -
Raise the attribute limit so long spans keep all their attributes. OpenTelemetry drops attributes past 128 per span without an error, and the span attribute reference explains how to lift it. For the wider walkthrough of sending LLM spans from OpenTelemetry, see Trace LLM calls with OpenTelemetry.
What you get
- Spans filed under the agent name you chose, in the trace views and filters that group by agent.
- An agent span that Rius classifies as an agent step, because
invoke_agentand theAGENTkind map to each other. - Tool spans that show which agent ran them and which tool they called.
- A process-level agent name from
gen_ai.main_agent.namethat does not change from span to span. - Cost on your model calls once those spans carry the request model and token counts. Rius computes cost server-side, so you never send a cost attribute.
When something else fits
If your agent is Python and you would rather not set these attributes by hand, the Rius Python SDK glassflow-rius sets the operation, span kind and names for you. A function marked as an agent produces an invoke_agent span named after the agent. If you export from another language, use the same attribute names with that language’s OpenTelemetry API, and see the span attribute reference for the full list.