How do I track usage per developer in OpenHands?
Rius tracks OpenHands usage per developer when you pass user_id to each Conversation, so the Users page shows each developer’s conversations under their own row. Rius turns tracing on from three environment variables, with no plugin and no code changes. Conversations without a user_id land in the anonymous row. Token counts and cost are missing for some OpenHands setups, which limits what each developer’s row can show.
How it works
OpenHands needs no plugin. Its SDK already sends OpenTelemetry, and Rius takes in the traces over OTLP. Each conversation becomes one trace with its model calls and tool calls. The conversation id is the Rius session, so a multi-turn conversation groups together.
When you create a Conversation with a user_id, every span in that conversation carries it. Rius then shows the conversation under that user on the Users page. This differs from the Claude Code plugin, where each developer shows by the email they signed in with. In OpenHands, a developer shows by the user_id you pass.
What each conversation records for that developer:
- Every model call, with its model, input and output tokens, cache reads and writes, cost, prompt and answer.
- Every tool call, such as
terminalorfile_editor, with its input and output, including a terminal command and its exit code. - The agent name, from the script name or from
agent.namemetadata.
Cost is a list-price estimate in US dollars, worked out from the model and token counts. You never send a cost value.
Set it up
- Create a Rius API key in the console under Settings → API keys, with the Send telemetry scope. Then set the three variables that point OpenHands at Rius. Use the full
/v1/tracespath,http/protobuf, and%20afterBearer. AnyLMNR_*variable overrides these settings, so unset them. The full walkthrough is in the OpenHands guide.
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_..."- Pass
user_idwhen you create theConversation. This is the step that gives you usage per developer. Use a value that identifies the developer, and prefer an opaque id to an email.
conversation = Conversation(
agent=agent,
workspace=".",
user_id="dev-0042",
observability_metadata={"agent.name": "fib-writer"},
)-
Run the agent from its own directory. Rius names the agent after the script, and a full path in the command shows up in the service column. The
agent.namemetadata above avoids this. -
Open the Users page in the console. The developer appears with the conversations sent under that
user_id. Each developer’s own SDK script must pass theuser_id, because Rius reads it from the spans.
If you want one workspace to hold the whole team’s sessions, give every developer a key for that workspace. The team guide for Claude Code shows the same one-workspace pattern.
What you get
- A Users row for each developer with their conversations, so you can see who ran what in OpenHands.
- Failed conversations and cost per developer, where the model calls report tokens. Claude and GPT-4o in SDK scripts come through in full.
- An optional readable summary of a developer’s work. With root-cause analysis on, an admin can click Summarise this user on a user’s page, over up to the last 7 days.
- Questions in an MCP client, through the Rius MCP server, such as “What did a given developer run in OpenHands yesterday?”. That question is answered by the
user_activity_summarytool.
What OpenHands does not report:
- No tokens or cost for OpenAI Responses API models such as GPT-4.1 and GPT-5, or for the web app’s streamed calls. Those developers’ rows show conversations but no spend.
- Failed commands are not error spans. A non-zero exit code sits in the tool output, so error-rate figures do not count it.
- OpenHands Cloud cannot send to Rius, because Cloud agents take no custom environment variables.
- Prompts and replies are always sent. Unlike the plugin, OpenHands has no per-folder opt-in for content.
Conversations without a user_id land in the anonymous row.
When something else fits
- If your developers use Claude Code, the Rius plugin records each one by sign-in email with no code to write. See Track Claude Code usage and cost across a team.
- If you run the OpenHands web app, set the variables in
OH_AGENT_SERVER_ENVas the OpenHands guide shows. Its conversations carry no tokens or cost. - To compare all the coding agents Rius traces, start from Coding agents.