Watching the Bus: ovos-busmon¶
In a nutshell
ovos-busmon is a small web app that streams every message on the OVOS messagebus live to a
browser tab, so you can watch an utterance move through the pipeline without tailing six
separate log files. This page is the deep dive: install, config, and a walkthrough. For the
staged decision tree that this tool supports, see Troubleshooting &
Debugging.
All the stages in the troubleshooting guide talk to each other over the
messagebus: the listener emits an utterance message, the intent service emits a
match, the skill emits a speak, and so on. ovos-busmon
is a small web app that connects to the bus as a client and streams every one of those messages
live to a browser tab, in one filterable, searchable timeline.
Bus messages, not logs
ovos-busmon shows live bus messages only. It does not parse the log files. It
complements the log tooling (ovos-logs and the
per-service *.log files), it doesn't replace it. For a terminal-based log viewer, use
ovos-tui — bundled by default in
ovos-installer virtualenv installs — which reads the OVOS logs directly.
Zero-install demo
A hosted static build is available at
openvoiceos.github.io/ovos-busmon. No pip
install needed. Because it's the static-page build (not the FastAPI-backed server), the
browser connects straight to the bus itself, so it only works when the browser runs on the
same machine as OVOS. For remote or multi-device use, run the full pip install ovos-busmon
server below.
Internally, it is a FastAPI + WebSocket/SSE service that opens an ovos-bus-client connection to
the messagebus and keeps an in-memory ring buffer of everything it sees. The browser UI lets you:
- filter the live stream by message type (glob patterns, e.g.
ovos.*orrecognizer_loop:*) - full-text search across message type, data, context, and session
- filter by session ID, source, and destination
- pause/resume capture and sort newest/oldest first
- export the captured buffer as JSON/JSONL for later inspection
- inject an arbitrary message onto the bus from the UI (the same trick as
ovos-say-to, but visual) - group the live stream into a timeline: per-session, expandable traces with category badges, so you can follow a single utterance across Stages 2-5 as one interaction instead of scanning the raw feed
- type an utterance into the chat panel (
POST /api/chat). It emits arecognizer_loop:utterancewith a stable session ID (so multi-turn/converse works), letting you replay a failing interaction deterministically without speaking
There is also a zero-install mode: the UI is a single static page that can open a WebSocket straight
to ws://<device>:8181/core with no server component at all. This is useful for a one-off look
without installing anything.
Installing and running it¶
To hack on it (or track dev), install from a clone instead:
By default it binds to http://127.0.0.1:8005 and connects outward to a messagebus at
localhost:8181. Both ends are configurable through environment variables (or a .env file next to
where you run it):
| Variable | Default | Meaning |
|---|---|---|
OVOS_BUS_HOST / OVOS_BUS_PORT |
localhost / 8181 |
Where the target OVOS messagebus is. |
BUSMON_HOST / BUSMON_PORT |
127.0.0.1 / 8005 |
Where busmon's own web UI listens. |
BUSMON_USERNAME / BUSMON_PASSWORD |
(unset) | HTTP Basic auth for the web UI. Auth is off unless set. |
BUSMON_TOKEN |
(unset) | Shared-secret token auth (works with the live SSE UI, unlike HTTP Basic). |
BUFFER_SIZE |
2000 |
How many messages the ring buffer keeps. |
A Docker route is also available (docker compose up --build from the repo), using the image
jarbasai/ovos-busmon:latest. Its bundled compose file binds the container to 127.0.0.1:8005 only
and sets OVOS_BUS_HOST=host.docker.internal so it can reach a bus running on the host.
Local debugging only: never expose this to the internet
ovos-busmon mirrors every message on the bus, including STT transcripts, intent matches,
and skill responses. Authentication is off by default; a non-loopback bind refuses to start
unless BUSMON_TOKEN or BUSMON_USERNAME/BUSMON_PASSWORD is set. Its message-injection
feature also lets anyone who can reach it emit arbitrary commands onto your assistant's bus.
Keep it bound to 127.0.0.1 or your local LAN, set a strong token or password before binding
wider, and never port-forward it to the public internet.
A concrete walkthrough¶
- Start
ovos-busmon. It comes up even if the bus is unreachable: its capture connection auto-reconnects on its own, so you can start it before the OVOS device is up and it begins capturing once the bus becomes reachable, with no restart needed. - Open
http://127.0.0.1:8005in a browser and log in with the configured credentials. - Speak (or trigger) an utterance on the OVOS device.
- Filter by
recognizer_loop:*. The first hit is the raw utterance leaving the listener (Stage 2 of Troubleshooting). If nothing appears here, the problem is upstream of the bus entirely (Stage 1). - Filter by
ovos.intent.matchedandovos.utterance.handled. These tell you which pipeline stage claimed the utterance and confirm the lifecycle actually closed (Stage ⅘ of Troubleshooting). - Filter by
ovos.utterance.speak. Its absence, with everything else present, points at a silent skill handler. Its presence with no audio points at the TTS/playback stage (Stage 6).
Each stage of Troubleshooting & Debugging cites the exact message type to filter on, so this same walkthrough can be repeated stage-by-stage instead of glancing at the whole stream at once.
Read next: Troubleshooting & Debugging Related: Command-line Tools · Bus Service · Debugging Intent Matching