About
Ship OpenHands agent session traces to Sazabi using the OpenHands Software Agent SDK’s built-in OpenTelemetry exporter. The OpenHands CLI runs on the same SDK, so one setup covers CLI sessions and your own SDK programs, with no code changes. Every span becomes a searchable log:conversation.run, conversation.send_message, and agent.step spans, tool-call spans named after the tool action, and LLM request spans with the model and token usage. An exception recorded on a span arrives as its own error log that keeps the span’s trace and span IDs.
Prerequisites
- OpenHands CLI (
openhands) or a Python program built onopenhands-sdk - Your Sazabi intake URL, shown above — open the log source and copy the Intake URL from its setup screen (the public key is embedded in the URL)
Set up in the dashboard
1
Export the trace exporter variables
OpenHands turns tracing on whenOTEL_EXPORTER_OTLP_TRACES_ENDPOINT is set; there is no separate OpenHands telemetry setting. Add the following to the shell profile (or launcher script) that starts OpenHands:~/.zshrc
<your intake URL> with the intake URL shown above, keeping the /v1/traces path. The public key is part of the URL, so OTEL_EXPORTER_OTLP_TRACES_HEADERS is not needed.Keep OTEL_EXPORTER_OTLP_TRACES_PROTOCOL=http/protobuf. Without it, OpenHands sends traces over gRPC, which the intake URL does not accept.Leave LMNR_PROJECT_API_KEY and LMNR_BASE_URL unset in this shell. When either is set, OpenHands sends traces to Laminar instead.2
Start a new OpenHands session
OpenHands reads these variables when it starts. Open a new shell (so the exports are present) and startopenhands or your SDK program; telemetry begins with that session, not one that is already running. When OpenHands runs the agent in a Docker or remote sandbox, it passes the OTEL_* variables through.Set up with the CLI
You can also register the OpenHands log source with the Sazabi CLI (installed and authenticated — see CLI reference). Registering the source mints the same intake URL the dashboard shows above (the public key is embedded in its hostname):sazabi log-sources get <log-source-id> at any time to reprint the endpoint, or sazabi log-sources list to see every log source in the project.
Verify
Start OpenHands from a shell that has the exports and run one task. OpenHands sends spans in batches every few seconds and on exit. Open the Intake page in the Sazabi dashboard and confirm logs from the OpenHands source appear within a minute or two. From the CLI,sazabi logs ask "How many OpenHands log lines arrived in the last 15 minutes?" confirms rows are arriving, and sazabi logs ask "Show the latest OpenHands agent.step logs" lists agent steps. In a thread, search by trace ID to see every span from one conversation run.
Troubleshooting
No logs after restarting — Confirm the exports are present in the shell that started OpenHands (env | grep OTEL_), that OTEL_EXPORTER_OTLP_TRACES_PROTOCOL is http/protobuf, and that the endpoint ends in /v1/traces.
Traces still go to Laminar — LMNR_PROJECT_API_KEY or LMNR_BASE_URL is set in that shell. Unset it and start a new OpenHands session.
OpenHands CLI stops with observe() got an unexpected keyword argument 'rollout_entrypoint' — OpenHands CLI 1.16.0 from PyPI fails when tracing is on. This is an OpenHands packaging issue, not a Sazabi one. Until a fixed release ships, install the CLI from source as described in the OpenHands CLI repository, then start a new session.
OpenHands Cloud conversations are missing — This source covers OpenHands processes you run yourself. Conversations that run in OpenHands Cloud are not collected.
No metrics — OpenHands exports traces only. There are no OpenHands metrics or logs signals for Sazabi to store.
Further reading
OpenHands SDK observability
OpenHands’ reference for its OpenTelemetry tracing variables.
Intake
See per-source ingestion volume and health.
Log sources
Browse the full log source catalog.