Agent Observability

Observability for OpenHands agents with Rius.

Send OpenHands traces to Rius. Catch agent tool loops, get root-cause notes, and track cost per model call.

Agent Observability

Observability for OpenHands agents with Rius.

Send OpenHands traces to Rius. Catch agent tool loops, get root-cause notes, and track cost per model call.

Agent Observability

Observability for OpenHands agents with Rius.

Send OpenHands traces to Rius. Catch agent tool loops, get root-cause notes, and track cost per model call.

Written by

Armend Avdijaj

Date added

TL;DR: This tutorial connects OpenHands to Rius, so you can see what your agents actually do. You send an OpenHands conversation's traces to Rius with three environment variables and no code changes. Then you follow a real case: an agent stuck polling a service that never comes up. You'll see Rius show the conversation as a timeline, raise a Tool Loop alert within minutes, write a root-cause note with a suggested fix, and price every model call. You can also query the same traces from Claude or Cursor through the Rius MCP server.

OpenHands is an open-source platform for AI agents that write code, run commands, edit files and decide on their own when a task is done. It already records every conversation as OpenTelemetry traces: each agent step, model call and tool call. Rius is GlassFlow's observability platform for AI agents. It turns those traces into answers: which conversations cost the most, where an agent got stuck, and why. Once you run more than a handful of conversations, you need both: agents that act on their own, and a clear view of what they did.

Watch the walkthrough video of an OpenHands conversation arriving in Rius.

An agent waiting for a deploy

Here is a task that comes up in real life. We asked an OpenHands agent, running in the local web app with Claude Haiku 4.5:

Our staging API should be up on port 8080 after the deploy. Check it with curl -sf http://localhost:8080/health and keep checking until it answers, then tell me it is up. Do not try to start or fix the service yourself, it is deployed separately.

The service never came up. The agent did exactly what it was told. It checked, waited five seconds, and checked again. Nine checks in all, eight of them the identical sleep 5 && curl command.

The OpenHands agent re-running the same health check

Every attempt shows a green check, and from the agent's side, that's correct. The command ran; it's the service that didn't answer. After enough identical steps, OpenHands' built-in stuck detector stepped in and stopped the conversation. That's a good safeguard. It stops the run before the loop gets expensive.

What Rius shows

The conversation arrives in Rius as one trace. Each check is a TerminalAction span with the exact command and what came back: exit code 7, curl's "couldn't connect". The model call before each check is there too, with its prompt and its answer.

The same conversation in Rius, one health check selected

A few minutes later, Rius's Tool Loop alert opens. Tool Loop is one of the pre-defined alerts that ship with every Rius workspace. It fires when a conversation calls the same tool with the same arguments three or more times in a row. Attach a Slack, email or webhook channel, and your team gets notified as it happens, instead of finding it in a transcript after the fact.


The Tool Loop alert on the conversation

Root-cause analysis on the alert

When you turn on Rius's root-cause analysis for your workspace, the alert comes with a written incident note. Rius reads the trace, finds the prompt, and puts its finger on the cause:

The user's prompt instructed the agent to poll indefinitely. [...] This is a behavioral loop driven by a well-formed but unbounded polling instruction.

It also lists the evidence (six identical calls, each about 5.2 seconds, a model call before every one) and suggests the fix: give the agent a retry limit, for example "retry at most N times, then report failure". That's a prompt change anyone on the team can make, and no one needs to open the trace to get there.

The root-cause analysis on the alert

Cost per model call

Rius prices every model call, so the cost of a conversation is never just a number at the end of the month. In an OpenHands SDK run where Claude Haiku 4.5 wrote fib.py, ran it and finished, the three model calls cost $0.0098, $0.0018 and $0.0018: $0.0134 in total. The first call costs five times the others because it writes the prompt cache, which the next two read from. Click any call to see its tokens, its model and its price.

One model call in Rius, with tokens and cost

One model call in Rius, with tokens and cost

What else Rius does for OpenHands

The same traces power more than the loop alert. A few things worth turning on once your conversations are flowing:

  • See what each step added. Open any model call and switch on Since previous llm call. Rius shows only the messages that changed since the last call, so you can read an OpenHands conversation step by step instead of scrolling one long prompt.

  • Catch a context that fills up. The Context rot alert flags a conversation whose model calls get close to the model's context window, where one tool's output takes over the prompt (a huge terminal or file_editor result), or where the output was cut off. It reads token counts, so it works on runs that report them, such as SDK scripts with Claude or GPT-4o. You can also alert on Context usage in a custom alert, next to cost per conversation.

  • Give one service its own error alert. Narrow Consistent Error Pattern to a single OpenHands service or step, with its own thresholds and its own Slack channel, while the rest of the workspace keeps the default.

  • See what one developer went through. Tag conversations with a user, and the Users page shows each developer's traces, failures and cost. With root-cause analysis on, Summarize writes a short account of that user's last seven days.

  • Know before the bill does. Admins get an email when spans pass the plan's included amount, and from twice that amount the notice also goes to your alert channels.

Here's what the first and fourth look like, shown on a sample support agent. The context growth strip at the top of the trace shows how the input grew from one model call to the next.

A trace in Rius with Since previous llm call on: only the messages added since the last model call, under the context growth strip

A user's page in Rius: traces, failures, cost and sessions over seven days, the agents that served them, and Summarise this user

Ask your traces from Claude or Cursor

The Rius MCP server brings the same data into Claude, Cursor or any MCP client. Ask "which OpenHands conversation looped today, and what command did it keep running?" and the answer comes straight from the spans. The same works for "what are the most common errors in my OpenHands agent this week?" or "which OpenHands conversations cost the most yesterday?". You can also list open alerts and acknowledge them from the chat. If you use Claude Code, the Rius plugin sets it up for you.

Claude Code connected to the Rius MCP server through the Rius plugin

Try it yourself

What you need

  • Python 3.12 or newer. The OpenHands SDK doesn't install on older versions.

  • A Rius account. Sign up at console.rius-glassflow.com. A new organization starts on a free trial.

  • A Rius API key with the Send telemetry scope, created under Settings → API keys in the console.

  • A model key. The example uses Claude Haiku 4.5, and one run costs about two cents.

  • Docker, only if you want the OpenHands web app.

Set it up

Clone the example repo and install it:

git clone https://github.com/glassflow/openhands-rius
cd openhands-rius
python3.12 -m venv .venv && .venv/bin/pip install -r requirements.txt
cp .env.example .env    # add your model key and your Rius key
git clone https://github.com/glassflow/openhands-rius
cd openhands-rius
python3.12 -m venv .venv && .venv/bin/pip install -r requirements.txt
cp .env.example .env    # add your model key and your Rius key
git clone https://github.com/glassflow/openhands-rius
cd openhands-rius
python3.12 -m venv .venv && .venv/bin/pip install -r requirements.txt
cp .env.example .env    # add your model key and your Rius key
git clone https://github.com/glassflow/openhands-rius
cd openhands-rius
python3.12 -m venv .venv && .venv/bin/pip install -r requirements.txt
cp .env.example .env    # add your model key and your Rius key

The three settings that matter are already in .env.example:

OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://ingest.eu.console.rius-glassflow.com/v1/traces
OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=http/protobuf
OTEL_EXPORTER_OTLP_TRACES_HEADERS=Authorization

OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://ingest.eu.console.rius-glassflow.com/v1/traces
OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=http/protobuf
OTEL_EXPORTER_OTLP_TRACES_HEADERS=Authorization

OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://ingest.eu.console.rius-glassflow.com/v1/traces
OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=http/protobuf
OTEL_EXPORTER_OTLP_TRACES_HEADERS=Authorization

OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://ingest.eu.console.rius-glassflow.com/v1/traces
OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=http/protobuf
OTEL_EXPORTER_OTLP_TRACES_HEADERS=Authorization

Leave any LMNR_* variables unset: a Laminar key takes precedence over these.

Run it

set -a; . ./.env; set

set -a; . ./.env; set

set -a; . ./.env; set

set -a; . ./.env; set

Your first OpenHands conversation shows up in the Rius trace list within seconds. To see the Tool Loop alert without spending tokens, the repo has a scripted model that gets stuck on purpose (demo/stuck_llm.py). For the local web app, deploy/docker-run.sh passes the same three values into every agent sandbox through OH_AGENT_SERVER_ENV.

To give an agent its own name in Rius, pass observability_metadata={"agent.name": "deploy-checker"} when you create the Conversation. The full setup, with every trap, is in the Rius docs.

Good to know

  • Works with OpenHands SDK scripts and the local web app. OpenHands Cloud doesn't take custom environment variables yet.

  • Token counts: SDK runs with Claude or GPT-4o come through with model, tokens and cost on every call. The web app streams its model responses, so its traces show every call and its content, but not the tokens.

  • Missing traces fail quietly. OpenHands keeps running when Rius refuses an upload, for example after a trial ends or above the per-minute ingest rate. If traces stop arriving, check Plan & usage in the console first.

Related

Share the article

Two products.
Two starting points.

Tares is open source. Kick the tires, open an issue, and drop a star
if it's useful.
Rius, end to end. Guides for wiring up traces, MCP, and

retention, from first span to production.

Give your agent one place to look. Everything your
systems emit, in one call.

Two commands and a source

you already run.

Ready to give your agents better data and total recall?

Start with Rius

See and debug agents in production.

2026 - Copyright GlassFlow.ai

Ready to give your agents better data and total recall?

Start with Rius

See and debug agents in production.

2026 - Copyright GlassFlow.ai

Ready to give your agents better data and total recall?

Start with Rius

See and debug agents in production.

2026 - Copyright GlassFlow.ai