Skip to Content

How do I see one whole conversation in an agent built with the Claude Agent SDK?

Rius shows a whole Claude Agent SDK conversation as one session: scope each task with rius.session() and the traces for that conversation list together. The SDK’s own session_id makes a natural Rius session id. Each task appears as a trace with a root agent span and one generation for the model turn, with tokens and cost.

How it works

The Claude Agent SDK drives the Claude Code runtime in a separate process, so no model client runs in your process and nothing is recorded on its own. Coverage comes from two pieces you add:

  • An observe wrapper makes each task the root AGENT span.
  • A manual generation wraps the query() loop and is filled from the run’s ResultMessage: token usage, the real model id and the collected answer. Rius computes cost from those, as a list-price estimate in US dollars.

The conversation itself is the third piece. A session groups traces by session.id, so every task you scope to the same session id belongs to the same conversation. Without a session.id, each trace is its own session.

A task looks like this in the trace:

handle-task AGENT 5.0s └─ claude_agent_turn LLM 5.0s claude-haiku-4-5, tokens + cost

The runtime’s inner work, such as tool calls, sub-turns and file operations, happens inside the Claude Code process and produces no spans. The generation records the turn’s totals only. See the Claude Agent SDK integration for the full list of what lands where.

Set it up

  1. Install the SDK next to the Claude Agent SDK. The base package is enough, and the claude CLI must be installed and authenticated.
pip install glassflow-rius claude-agent-sdk
  1. Trace each task with an AGENT root and a generation filled from the result. Use a full model id, not an alias such as haiku, because cost is computed from the requested model and an alias produces a generation with no cost. Keep provider="anthropic" so the cache counts are added to the input tokens for you.
import rius from claude_agent_sdk import ( AssistantMessage, ClaudeAgentOptions, ResultMessage, TextBlock, query, ) from rius import SpanKind rius.init(api_key="ri_...", service_name="my-agent") MODEL = "claude-haiku-4-5" @rius.observe(name="handle-task", kind=SpanKind.AGENT) async def handle_task(task: str) -> str: options = ClaudeAgentOptions(model=MODEL, max_turns=1) parts = [] with rius.start_as_current_generation( "claude_agent_turn", model=MODEL, provider="anthropic", input=task ) as gen: async for message in query(prompt=task, options=options): if isinstance(message, AssistantMessage): parts.extend( b.text for b in message.content if isinstance(b, TextBlock) ) elif isinstance(message, ResultMessage): usage = message.usage or {} gen.set_usage( input_tokens=usage.get("input_tokens"), output_tokens=usage.get("output_tokens"), cache_read_input_tokens=usage.get("cache_read_input_tokens"), # Anthropic's payload still calls the write count "cache creation" cache_write_input_tokens=usage.get("cache_creation_input_tokens"), ) models = list((message.model_usage or {}).keys()) if models: gen.set_response_model(models[0]) answer = "".join(parts) gen.set_output(answer) return answer
  1. Tie the tasks of one conversation together. Call handle_task inside rius.session() with the same id for every task, so every trace of that conversation carries the same session.id. Open the scope before the call, so the root span carries it too. The SDK’s session_id is a natural id for a resumed conversation, but it only arrives with the first task’s messages, so a conversation that starts in your code needs an id you choose up front.

  2. If each process handles exactly one conversation, you can set a process-wide session instead:

export RIUS_SESSION_ID=your-conversation-id
  1. Run a conversation, open Traces in the console and open one trace. The Session link in the trace header opens the Spans tab filtered to that session. You can also paste the session ID into the Spans search box to list every span in it. A generation with no cost means an alias was used as the model id.

What you get

  • One session id that groups every task of a conversation, found from the trace header or the Spans search box. The trace exploration page shows how to read the tree and the span details.
  • Per task, a waterfall with the root AGENT span and one LLM generation showing the model, input and output tokens, cache tokens and estimated cost.
  • Your own session_id as the join key, so a resumed conversation continues the same session.
  • The same traces in the wider views for agents and cost described in Monitor AI agents in production.

The Claude Agent SDK is the one manual integration in the integrations list: the task root, the generation, the usage and the session are all yours to add.

When something else fits

  • If you need the runtime’s tool calls and sub-turns as separate spans, this integration does not record them. Each turn is one generation with totals only.
  • If you want to trace Claude Code sessions themselves rather than an agent you built, the Rius coding-agent plugin does that, and it is a separate setup from this one.

Still stuck? Get help

Last updated on