What does a session in OpenHands look like as a trace?
Rius shows one OpenHands conversation as one trace, with the conversation as the root and each agent step, model call and tool call nested below it. Each model call carries its model, tokens, cost, prompt and answer, and each tool call carries its input and output. The conversation id becomes the Rius session, so a multi-turn conversation groups together. OpenHands needs no plugin, only three environment variables.
How it works
One OpenHands conversation is one trace. The OpenHands SDK emits the spans over OpenTelemetry and Rius reads them as they arrive. This is the shape of a run that edits a file, runs it and finishes:
conversation
├── conversation.send_message
└── conversation.run
├── agent.step
│ ├── llm.anthropic/claude-haiku-4-5-20251001
│ │ └── litellm.completion LLM: model, tokens, cost, messages
│ └── FileEditorAction TOOL: file_editor
├── agent.step
│ ├── llm.anthropic/claude-haiku-4-5-20251001
│ │ └── litellm.completion
│ └── TerminalAction TOOL: terminal
└── agent.step
├── …
└── FinishAction TOOL: finishWhat each level holds:
- The conversation is the root. Its id is the Rius session. The agent name comes from
agent.namemetadata, or from the script name if you set none. conversation.send_messageandconversation.runsit directly under the root. Your message is one span, and the run is the parent of every step.- Each
agent.stepis one round of the agent: a model call followed by the tool call it chose. - Each model call is the
litellm.completionspan under thellm.span. It has the model, input and output tokens, cache reads and writes, cost, prompt and answer. - Each tool call (
terminal,file_editor,finishand so on) has its input and output. For a terminal call that includes the command and its exit code.
In one Claude Haiku 4.5 run of a small coding task, the four model calls used 31,091 input tokens and 966 output tokens, for $0.0175 in all. Cost is a list-price estimate in US dollars, worked out by Rius from the token counts. Open any litellm.completion span to see that call’s share.
If you also trace Claude Code, its sessions are shaped differently, with turns and subagents under the session. See Track Claude Code usage and cost across a team.
Set it up
- Set the three OTLP variables in the environment where the OpenHands SDK runs, and clear any Laminar variables, which take precedence over them. The protocol must be
http/protobufand the path must be the full/v1/traces. The space afterBeareris written%20.
export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://ingest.eu.console.rius-glassflow.com/v1/traces
export OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=http/protobuf
export OTEL_EXPORTER_OTLP_TRACES_HEADERS="Authorization=Bearer%20ri_..."
unset $(env | grep -o '^LMNR_[A-Z_]*')- Name the agent and attribute the conversation to a user when you create it.
agent.nameanduser_idreach every span, so the trace shows under the name you chose and under that developer on the Users page.
conversation = Conversation(
agent=agent,
workspace=".",
user_id="dev@example.com",
observability_metadata={"agent.name": "fib-writer"},
)-
Run the script from its own directory, so the service name is not a full file path.
-
Open the trace list in the console. The conversation appears under your agent name within a few seconds. Open it to see the steps, model calls and tool calls in order.
The full install, API key and web-app steps are in the OpenHands guide.
What you get
- One trace per conversation, with every step, model call and tool call in order, so you can go from an expensive or failed conversation to the exact span.
- Tokens and cost on each model call, including cache reads and writes, for Claude and GPT-4o in SDK scripts.
- The command and exit code on each terminal call, plus the input and output of every other tool.
- Sessions and users. The conversation id groups a multi-turn conversation, and
user_idlists each developer on the Users page. - Always-on content. OpenHands sends prompts and answers with every call, unlike the plugin agents, which send content only from folders you enable.
Three gaps to know about:
- OpenAI Responses API models (GPT-4.1, GPT-5) and the web app’s streamed calls carry no token counts or cost. Their spans still show the prompt, answer and tool calls.
- A failed command is not an error span. A non-zero exit code is in the tool output, so the trace can read Ok and error-rate alerts do not count it.
- OpenHands Cloud cannot send to Rius.
The Tool Loop alert still catches a repeated tool call in one of these traces. The Coding agents page compares OpenHands with the other agents Rius traces.
When something else fits
- If you run OpenHands Cloud, which takes no custom environment variables, you cannot send its traces to Rius. Use the OpenHands SDK or the local web app instead.
- If you need token counts for OpenAI Responses API models or the web app’s streamed calls, those traces do not carry them. Cost for those calls is empty.