How do I add tracing to my AI agent in Python?
Rius traces a Python agent after you install glassflow-rius, call rius.init() once at startup, and wrap each step of your agent with @rius.observe. Auto-instrumentation records the model calls inside those steps, with model, token counts and cost. Run the agent once and the trace appears in the Traces view. The setup takes about five minutes with an API key in hand.
How it works
- One init call.
rius.init()sets up the exporter, the service name and the API key, and turns on auto-instrumentation for every supported library you have installed. Call it once, as early as possible in your process. - One span per decorated function.
@rius.observetraces each call of the function as a span. Exceptions are recorded on the span with ERROR status anderror.type, then re-raised, so your error handling stays as it was. - Model calls need nothing at the call site. With an extra such as
glassflow-rius[anthropic]installed, each model call becomes its own span inside your function’s span. It carries the model and token counts, and Rius computes the cost from them. You never send a cost value. - Names matter.
service_nameis how you find your agent in filters and cost breakdowns. It defaults tounknown_service, so set it.
The tracing reference covers every span option in depth.
Set it up
-
Get an API key. Sign up, then click Create API key on the Get started page. Keys start with
ri_and are shown once, so copy yours into a secret manager. The quickstart walks through both screens. -
Install the SDK (Python 3.10 or newer). The extra installs the instrumentation for a library, not the library itself, so name both:
pip install "glassflow-rius[anthropic]" anthropicFor OpenAI use glassflow-rius[openai]. glassflow-rius[instruments] covers every supported library. The installation page lists all extras and every init argument.
- Init and wrap your first function. This is a complete agent with one model call. Fill in your two keys and run it:
import anthropic
import rius
rius.init(api_key="ri_...", service_name="my-agent")
claude = anthropic.Anthropic() # reads ANTHROPIC_API_KEY
@rius.observe
def handle(query: str) -> str:
response = claude.messages.create(
model="claude-haiku-4-5-20251001",
max_tokens=200,
messages=[{"role": "user", "content": query}],
)
return response.content[0].text
handle("What should I check when a collector drops spans?")- Add spans for the other steps of your agent. Decorate each function that makes up a step, such as planning, a tool call or a rerank. The default kind is
CHAIN. Passkindto label a step asAGENT,LLM,TOOL,RETRIEVER,RERANKERorEMBEDDING, andnameto set the span name:
import rius
from rius import SpanKind
@rius.observe
def plan(query: str) -> str:
...
@rius.observe(name="rerank", kind=SpanKind.RERANKER, capture_output=False)
def rerank(docs: list[str]) -> list[str]:
...capture_input and capture_output default to true and record arguments and return values. Set capture_output=False for a step whose result you do not want stored.
- Group turns into sessions (optional). Wrap each conversation in a session scope and every span inside carries your id as
session.id:
import rius
with rius.session(conversation_id):
handle_turn(message) # every span of the turn carries session.id- Check the first trace. Open the Traces view in the console. It checks for new traces on its own, so you do not need to reload. Open the trace and read the waterfall: your decorated function is the parent, and the model call sits beneath it with its tokens and cost.
If a library has no auto-instrumentation, trace the call as a generation with rius.start_as_current_generation and pass token usage with set_usage(). Pass tokens only, never cost.
What you get
- A trace for every run, with one span per decorated function and one per model call, nested in the order they ran.
- Model name, input and output token counts, and an estimated cost in US dollars on each model call.
- Failures on the span where they happened, with the exception class in
error.type. - Optional sessions, so the traces of one conversation group together.
- A heartbeat, on by default when you pass an API key, so the Agents view shows whether your process is alive between runs.
From here, Monitor AI agents in production shows how to add alerts on errors and loops.
When something else fits
- If your agent is in TypeScript, the same SDK exists as
@glassflow-ai/rius, withobserve()wrapping functions. - If you already emit OpenTelemetry GenAI traces, you can send them to Rius from any OpenTelemetry SDK or collector without the Rius SDK.
- If a library you call has no auto-instrumentation, trace it with a manual generation rather than waiting for an extra.