Skip to Content

How do I track failed tool calls in OpenHands?

Rius records every OpenHands tool call as its own span with the tool’s input and output, including a terminal command and its exit code, so you can open a failed command and read what happened. You turn it on with three OTLP environment variables and no plugin. A non-zero exit code appears in the tool output, not in the span status, and the pre-defined Tool Loop alert catches a failing command that repeats.

How it works

OpenHands’ SDK already traces each conversation with OpenTelemetry, and Rius takes that in as one trace per conversation. Inside the trace you see the conversation, each agent.step, and the model and tool calls under it.

  • Each tool call is a span of the Tool kind, such as TerminalAction for the terminal tool, FileEditorAction for file_editor and FinishAction for finish, with its input and output.
  • A terminal call carries the command and its exit code. That is where a failure shows.
  • The exit code is in the tool output, not in the span status. A failed command does not mark its span as an error, so a run whose command failed can still read Ok, and error-rate alerts do not count it.
  • Repeated failures are caught by Tool Loop. This pre-defined alert is on in every workspace. It fires when the same tool is called with the same arguments at least three times in a row in one trace, including a loop OpenHands finished normally. OpenHands’ own stuck detector stops a conversation after four identical action and observation pairs, or when the same action fails more than three times in a row. It tells no one and lets shorter loops finish. With two identical calls no Tool Loop alert opens, because three is the minimum.
  • Failures at the model call are different. If a rotated or expired model key makes every conversation fail at its first model call, those are real errors. The pre-defined Consistent Error Pattern alert fires when the same error shows up at least 3 times across at least 2 runs within 5 minutes.

For the full picture across agents, see Coding agents.

Set it up

  1. Install the OpenHands SDK. It needs Python 3.12 or newer: pip install openhands-sdk openhands-tools in a Python 3.12 virtual environment.
  2. In the Rius console, open Settings → API keys and create a key with the Send telemetry scope. The key is shown once.
  3. Set the three variables in the environment of the process that runs your agent:
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_..."

Get these exactly right, because when one is off, Rius never sees the spans. Use http/protobuf, write the full /v1/traces path, and encode the space after Bearer as %20. Unset any LMNR_* variable, because it takes precedence over the OTEL settings. 4. Run your agent as usual. OpenHands turns tracing on by itself when it finds these variables, and there is no Rius code in the script. Start the script from its own directory and the conversation appears under the agent named after the script, or under the name you pass as agent.name metadata. 5. Optionally pass user_id when you create the Conversation, so the conversation shows under that developer on the Users page. Without it, conversations land in the anonymous row. 6. To get notified, attach a channel (Slack, email or webhook) to the Tool Loop alert.

Full setup, including the local web app, is in the OpenHands guide.

What you get

  • A readable record of each failed command. Open the conversation in the trace list, select the tool span in the waterfall, and read its input and output, with the exit code for a terminal call. Filter the Spans tab to the Tool kind to list tool calls.
  • A notification for a stuck agent. Tool Loop opens an alert such as terminal × 4 a few minutes after the same failing command repeats, and a root-cause finding if root-cause analysis is on for the workspace.
  • Per-agent and per-developer views. The Agents page shows each OpenHands agent’s failed traces, errors and cost. The Users page shows each developer when you pass user_id.
  • Questions over MCP. With the Rius MCP server connected, ask for the last conversation and the command it kept running, or for the top error groups for an agent.

What OpenHands does not report:

  • A failed command is not an error span, so error-rate alerts do not count it.
  • Web-app conversations show every tool call with its input and output, but no tokens or cost, because the web app streams its model calls.
  • OpenHands Cloud cannot send to Rius, because it takes no custom environment variables.

When something else fits

  • If your team uses Claude Code, a failed tool call there is marked as an error on its span. See Track Claude Code usage and cost across a team.
  • If you need an alert on every non-zero exit code, note that Rius records the code in the tool output only, so the signals it offers for repeated failure are Tool Loop and Consistent Error Pattern.

Still stuck? Get help

Last updated on