Bus Events Reference¶
In a nutshell
Every OVOS component talks to every other one by sending small named messages over the shared messagebus. It works a bit like a group chat where each service watches for the message types it cares about. This page collects the message types documented elsewhere in the manual into one place, grouped by which stage of the utterance lifecycle they belong to, so you don't have to hunt through six different pages to find one event name. Each row links back to the page that documents that event in context. This page does not introduce anything new.
Looking for a message this page does not list?
This page is curated. It covers the events the manual explains in context, not every event
that exists. For the exhaustive machine-generated catalog, browse the
MessageBus Protocol Reference, built
from ovos-pydantic-models. It is searchable and
grouped by subsystem, and it includes deprecated subsystems that this page leaves out.
Its models are generated semi-automatically from source, so entries can be incomplete or out of date. Check the behavior against the code or the formal specifications before you depend on it.
Note
Many events have a legacy mycroft.*/bare name alongside a newer ovos.* name. Only
one of the two goes on the wire, and each connected client's bus library locally
re-dispatches it under the other name too, so a handler on either name receives it
(see Bus Service: namespace migration). Use the
spec name in new code: an open kill-switch pull request
(ovos-bus-client#272)
removes the legacy bridge once the fleet has migrated. The tables below show both
names where applicable.
Listener / wake word¶
Emitted by ovos-dinkum-listener as the audio pipeline runs. See
Speech Service for the full lifecycle.
| Event | Data | Meaning |
|---|---|---|
ovos.listener.record.started (legacy: recognizer_loop:record_begin) |
none | Command recording started |
ovos.listener.record.ended (legacy: recognizer_loop:record_end) |
none | Command recording ended |
recognizer_loop:wakeword |
{"utterance": str, "key_phrase": str, …} |
Wake word detected, capture is opening. Legacy-only: no ovos.listener.* counterpart exists, see Speech Service |
recognizer_loop:speech.recognition.unknown |
none | STT returned nothing (silence / failure) |
ovos.listener.sleep (legacy: recognizer_loop:sleep) |
none | Request the listener enter sleep mode and suspend capture: device-scoped, see Speech Service |
ovos.listener.awoken (legacy: mycroft.awoken) |
none | Listener woke from sleep |
STT / utterance entry point¶
| Event | Data | Meaning |
|---|---|---|
ovos.utterance.handle (legacy: recognizer_loop:utterance) |
{"utterances": [str], "lang"} |
Transcribed command enters the pipeline: see Life of an Utterance and Intent Service |
ovos.utterance.handled |
none | Universal utterance-lifecycle end-marker. See Bus Service |
Intent matching & context¶
Handled by ovos-core's IntentService. See Intent Service.
| Event | Handler | Meaning |
|---|---|---|
ovos.utterance.handle (legacy: recognizer_loop:utterance) |
handle_utterance |
Run an utterance through the pipeline |
add_context / remove_context / clear_context |
handle_add_context / handle_remove_context / handle_clear_context |
Legacy-compat intent context writes (modern emitters mutate the session directly) |
intent.service.intent.get |
handle_get_intent |
Query the best-matching intent without dispatching it |
intent.service.skills.deactivate |
_handle_deactivate |
Remove a skill from active/converse consideration |
intent.service.pipelines.reload |
handle_reload_pipelines |
Reload the configured pipeline plugin stack |
ovos.intent.unmatched (legacy: complete_intent_failure) |
none | No pipeline stage claimed the utterance, including the fallback stages, which run inside the match loop. This is the terminal "nothing handled it" marker, not a hand-off |
IntentService also emits these on a successful match, in order (see Intent Service):
| Event | Meaning |
|---|---|
{skill_id}.activate |
Mark the matched skill active in the session |
ovos.intent.matched |
A pipeline plugin claimed the utterance (notification) |
<skill_id>:<intent_name> |
The dispatch message that invokes the winning skill's intent handler |
ovos.intent.handler.start → ovos.intent.handler.complete / ovos.intent.handler.error |
The orchestrator-owned handler-lifecycle trio around the invocation (§8, not translator-bridged, see Legacy ↔ spec migration). The skill framework separately emits the legacy mycroft.skill.handler.start / .complete / .error trio as a private done-signal, mirroring all three spec legs with the same non-bridged status |
Converse¶
See Converse Pipeline for the full picture.
| Event | Handler | Meaning |
|---|---|---|
intent.service.skills.activate |
handle_activate_skill_request |
Add a skill to the converse-eligible list |
intent.service.skills.deactivate |
handle_deactivate_skill_request |
Remove a skill from the converse-eligible list |
intent.service.active_skills.get |
handle_get_active_skills |
Query the current converse-eligible list |
skill.converse.get_response.enable / .disable |
handle_get_response_enable / handle_get_response_disable |
Toggle the get_response window for a skill |
converse:skill |
handle_converse |
Dispatch an utterance to an active skill's converse |
{skill_id}.converse.get_response |
none | Feed the user's reply back into a pending get_response (see OVOSSkill API) |
Common Query¶
| Event | Meaning |
|---|---|
question:query |
Common query pipeline request broadcast to all skills |
ovos.common_query.ping |
Common query service discovery |
question:action.{skill_id} |
Callback: this skill's answer was selected |
question:action |
Callback: some skill's answer was selected (generic) |
Fallback¶
See Fallback Pipeline.
| Event | Handler | Meaning |
|---|---|---|
ovos.skills.fallback.register |
handle_register_fallback |
Register a skill as a fallback handler |
ovos.skills.fallback.deregister |
handle_deregister_fallback |
Remove a fallback handler |
ovos.skills.fallback.ping |
_handle_fallback_ack (skill-side) |
Fallback service asks every registered skill whether it can handle the utterance |
ovos.skills.fallback.pong |
handle_ack (service-side) |
A skill's reply to the ping, can_handle true/false |
ovos.skills.fallback.{skill_id}.request |
_handle_fallback_request (skill-side) |
Service asks one specific skill to actually process the utterance |
Skill lifecycle¶
Handled by every OVOSSkill instance. See OVOSSkill API.
| Event | Meaning |
|---|---|
ovos.stop (legacy: mycroft.stop) |
Global stop broadcast: every skill subscribes and ceases activity for the inbound session (see below). Only this pair is translator-bridged |
{skill_id}.stop |
Skill-directed stop dispatch. Per-skill topics are not translator-bridged, because the {skill_id}.* shape cannot be a static map key, and the base class subscribes to this form only |
{skill_id}.stop.ping |
Check whether this skill can stop. Same as above: this exact form, not bridged, no spec-namespaced alias |
mycroft.skills.loaded |
Emitted on every successful skill load (any loading path), with the skill id — the general-case loaded event |
mycroft.skills.loading_failure |
Emitted when a skill fails to load ({"path", "id"}); see Skill Manager |
mycroft.skill.loaded |
Additional singular event the Skill Manager emits for plugin-skill loads only, with {"skill_id": ...}; no failure counterpart |
mycroft.skills.train / mycroft.skills.trained |
Pipeline retrain request (fire-and-forget from the manager) and the Padatious pipeline's completion announcement |
mycroft.skill.enable_intent / mycroft.skill.disable_intent |
Enable/disable one of the skill's intents |
mycroft.skill.set_cross_context / mycroft.skill.remove_cross_context |
Manage cross-skill context |
mycroft.skills.settings.changed |
Remote settings update: see Skill Settings for the full change-notification flow |
ovos.skills.settings_changed |
Local settings file changed: see settings_change_callback in Skill Settings (Skill Cookbook recipe 2) for reacting to it from a skill |
homescreen.metadata.get |
Homescreen requesting metadata |
{skill_id}.public_api |
Skill API introspection (see Skill API: Inter-Skill RPC) |
Stop pipeline¶
ovos.stop and the per-skill stop handshake above are driven by the dedicated
Stop Pipeline plugin, not by a generic intent match.
Only the two broadcast topics carry spec names here: ovos.stop (legacy mycroft.stop) and
ovos.stop.pong (legacy skill.stop.pong) are the entries the migration map holds. The
per-skill and match-type topics below have no ovos.* alias — subscribe to the exact names
shown, and do not translate them by analogy:
| Event | Direction | Meaning |
|---|---|---|
<pipeline_id>:global_stop (legacy: stop:global) |
in | Global-stop dispatch: its handler emits the ovos.stop broadcast (and ovos.utterance.handled) |
{skill_id}.stop |
out | Targeted stop dispatch to one skill, produced by a <skill_id>:stop match (legacy: stop:skill) |
{skill_id}.stop.ping |
out | Asks one skill whether it can stop |
ovos.stop.pong (legacy: skill.stop.pong) |
in | Handler's can_handle reply |
ovos.stop (legacy: mycroft.stop) |
out | Universal stop broadcast |
TTS / audio playback¶
Handled by ovos-audio. See Audio Service.
| Event | Meaning |
|---|---|
ovos.utterance.speak (legacy: speak) |
Natural-language response to synthesize and play: the exit point of the utterance lifecycle |
mycroft.audio.queue |
Queue a sound effect / audio file for playback (see play_audio) |
mycroft.audio.play_sound |
Play a sound effect / audio file instantly |
mycroft.audio.speech.stop |
Interrupt in-progress TTS speech (emitted by the @intent_handler(..., stop_tts=True) decorator, among others) |
mycroft.audio.service.play |
Legacy media audioservice: play a track (only relevant when enable_old_audioservice is on) |
recognizer_loop:utterance_start |
Emitted by the playback thread right before spoken audio starts playing |
ovos.audio.output.started (legacy: recognizer_loop:audio_output_start) |
Emitted by the playback thread when audio actually starts playing |
ovos.audio.output.ended (legacy: recognizer_loop:audio_output_end) |
Emitted by the playback thread when audio finishes playing |
GUI forwarding¶
Handled by ovos-gui. See GUI Service.
| Event | Meaning |
|---|---|
gui.value.set |
Write session variables into a skill's GUI namespace |
gui.page.show |
Request one or more QML/HTML pages be shown |
gui.page.delete / gui.page.delete.all |
Remove page(s) from the namespace |
gui.event.send |
Send a custom event into the namespace |
gui.clear.namespace |
Remove a skill's namespace from the active GUI stack |
OCP / media playback¶
Handled by ovos-media's MediaService/OCPPlayer and the ovos-ocp-pipeline-plugin
intent pipeline. All topics live under the ovos.common_play.* namespace, there is no
legacy alias for this surface. For behavior notes on the service-level subset (ping,
status, SEI queries), see
ovos-media: Service-level bus messages.
| Event | Direction | Meaning |
|---|---|---|
ovos.common_play.search |
in | External client (a GUI search box, for example) asks the OCP pipeline plugin to search across skills; the plugin performs the search itself and replies with results |
ovos.common_play.play_search |
in | Skill dispatch label for a matched "play X" intent |
ovos.common_play.play |
in | Start playback of a track or playlist |
ovos.common_play.pause |
in | Pause playback |
ovos.common_play.play_pause |
in | Toggle play/pause |
ovos.common_play.resume |
in | Resume paused playback |
ovos.common_play.stop |
in | Stop playback |
ovos.common_play.next / .previous |
in | Skip to next/previous track |
ovos.common_play.seek |
in | Seek within the current track |
ovos.common_play.get_track_length / .get_track_position / .set_track_position |
in | Query or set playback position |
ovos.common_play.track_info |
in | Query metadata for the current track |
ovos.common_play.playlist.set / .clear / .queue |
in | Manage the active playlist |
ovos.common_play.shuffle.toggle / .set / .unset |
in | Manage shuffle mode |
ovos.common_play.repeat.toggle / .set / .unset |
in | Manage repeat mode |
ovos.common_play.duck / .unduck / .cork / .uncork |
in | Manage playback ducking around TTS/other audio |
ovos.common_play.status |
in | Request a player state sync (also emitted by OCP itself on launch) |
ovos.common_play.status.response |
out | Reply to .status, carries current player state: {playback_type, media_type, player_state, loop_state, media_state, shuffle, playlist_position, playlist_size, title, artist, image} |
ovos.common_play.track.state |
out | {"state": TrackState} playback state changed (loading, playing audio/video, paused, ended) |
ovos.common_play.media.state |
out | Low-level backend media state changed |
ovos.common_play.home |
in | Request the OCP home/media browser view |
ovos.common_play.ping / .pong |
in/out | OCP service discovery handshake |
ovos.common_play.search.start / .search.end |
in | Pipeline plugin brackets a search request; the player uses them to gate busy state |
ovos.common_play.search.stop |
out | Emitted by the player on stop, and by the pipeline plugin, to cancel a search still in flight |
ovos.common_play.announce |
in | A skill registers itself as an OCP media provider |
ovos.common_play.register_keyword / .deregister_keyword |
in | A skill registers/removes its media-type keywords for the pipeline plugin |
ovos.common_play.skills.detach |
in | Remove a skill from the OCP provider list |
ovos.common_play.SEI.get / .SEI.get.response |
out/in | Query a client's available stream extractor plugins |
ovos.common_play.like / .unlike |
in | Mark/unmark the current track as liked |
ovos.common_play.liked_tracks.play |
in | Emitted by the pipeline's favorites intent; no shipped consumer listens to it. Liked-songs playback actually happens through the player's internal liked-songs search provider |
PHAL (hardware abstraction)¶
Handled by the PHAL service (ovos-PHAL) and its plugins. See PHAL.
| Event | Direction | Meaning |
|---|---|---|
system.reboot |
in | Request a device reboot, handled by ovos-PHAL-plugin-system |
system.reboot.start |
out | Reboot is starting |
system.shutdown |
in | Request a device shutdown |
system.shutdown.start |
out | Shutdown is starting |
system.factory.reset |
in | Request a factory reset |
system.factory.reset.register |
in | A plugin registers itself as a factory-reset participant |
system.factory.reset.ping |
out | Ask registered plugins to run their factory-reset step |
system.configure.language |
in | Request a device-wide language change |
system.configure.language.complete |
out | Language change finished |
system.mycroft.service.restart |
in | Request ovos-core be restarted |
system.mycroft.service.restart.start |
out | ovos-core restart is starting |
system.ssh.enable / .disable |
in | Enable/disable the SSH server |
system.ssh.enabled / .disabled |
out | SSH server state changed |
system.ssh.status |
in | Query SSH server state |
system.clock.synced |
in | System clock finished syncing over NTP |
Every PHALPlugin subclass also listens on the same core listener/audio topics documented
above (recognizer_loop:record_begin, recognizer_loop:audio_output_start,
mycroft.awoken, speak, and the enclosure.* display/eyes/mouth topics), so a PHAL
plugin can react to the utterance lifecycle without going through a skill.
Volume / mute¶
Handled by ovos-PHAL-plugin-alsa and ovos-PHAL-plugin-pulseaudio (whichever is loaded
for the platform's audio stack). ovos-audio also emits mycroft.volume.* on its own
startup to normalize the initial volume.
| Event | Direction | Meaning |
|---|---|---|
mycroft.volume.get |
in/out | Query current volume; the same topic carries the reply as a response message with {"percent"} |
mycroft.volume.set |
in | Set volume to {"percent"} |
mycroft.volume.set.gui |
in | Set volume from a GUI slider |
mycroft.volume.increase |
in | Raise volume by a step |
mycroft.volume.decrease |
in | Lower volume by a step |
mycroft.volume.mute |
in | Mute audio output |
mycroft.volume.unmute |
in | Unmute audio output |
mycroft.volume.mute.toggle |
in | Toggle mute state |
mycroft.volume.get.sliding.panel |
in | Query volume for the GUI sliding panel |
Session & skill management¶
See Bus Service: common message types.
| Event | From | To |
|---|---|---|
mycroft.skills.initialized |
ovos-core |
GUI clients, tools |
skillmanager.list |
any client | ovos-core |
ovos.skills.install |
any client | ovos-core |
ovos.session.sync |
new client | ovos-core |
ovos.session.update_default |
ovos-core |
all clients (legacy default-session echo, deprecated) |
mycroft.network.connected / mycroft.internet.connected |
ovos-PHAL |
ovos-core, skills |
Legacy ↔ spec migration¶
OVOS is renaming its bus topics onto the ovos.* spec namespace. During the migration,
ovos-bus-client's receive-side bridge makes legacy and spec names interchangeable, both
directions on by default (see
Bus Service: namespace migration). That bridge is
scheduled for removal by the open kill-switch pull request
ovos-bus-client#272: after it
merges, only the spec names work. Use the table below to move any legacy name in your
code to its spec name ahead of that.
The pairs below are the authoritative rename map (ovos_spec_tools's MIGRATION_MAP). Unless
marked shape-changing, the payload is identical on both topics. Shape-changing pairs are
reshaped best-effort by the translator and may lose fields, so prefer adopting the spec payload
directly.
| Legacy topic | Spec topic | Notes |
|---|---|---|
recognizer_loop:utterance |
ovos.utterance.handle |
transcribed utterance (PIPELINE-1 §9.1) |
speak |
ovos.utterance.speak |
TTS request (PIPELINE-1 §9.6) |
speak:b64_audio |
ovos.utterance.speak.b64 |
inline-audio speak request, handled by ovos-audio's handle_b64_audio |
speak:b64_audio.response |
ovos.audio.speech |
synthesized-audio reply |
recognizer_loop:audio_output_start |
ovos.audio.output.started |
playback began (AUDIO-1 §5.1) |
recognizer_loop:audio_output_end |
ovos.audio.output.ended |
playback ended (AUDIO-1 §5.2) |
mycroft.audio.queue |
ovos.audio.queue |
enqueue a sound {uri} |
mycroft.audio.play_sound |
ovos.audio.play_sound |
play a sound effect {uri} |
mycroft.audio.speak.status |
ovos.audio.is_speaking |
query: is audio-out active |
mycroft.audio.speech.stop |
ovos.audio.stop |
stop audio output |
mycroft.mic.listen |
ovos.mic.listen |
force the listener to start listening (AUDIO-1 §4.4) |
recognizer_loop:record_begin |
ovos.listener.record.started |
command recording started (AUDIO-IN-1 §6.1) |
recognizer_loop:record_end |
ovos.listener.record.ended |
command recording ended (AUDIO-IN-1 §6.2) |
recognizer_loop:sleep |
ovos.listener.sleep |
put listener to sleep (AUDIO-IN-1 §6.3) |
mycroft.awoken |
ovos.listener.awoken |
listener woke from sleep (AUDIO-IN-1 §6.4) |
mycroft.stop |
ovos.stop |
universal stop broadcast (STOP-1 §5.3) |
skill.stop.pong |
ovos.stop.pong |
stoppability reply (STOP-1 §4.2) |
complete_intent_failure |
ovos.intent.unmatched |
no intent claimed the utterance (PIPELINE-1 §9.3) |
detach_skill |
ovos.skill.deregister |
remove a skill's intents {skill_id} |
detach_intent |
ovos.intent.deregister |
shape-changing: remove one intent (INTENT-4 §8.2) |
mycroft.skill.enable_intent |
ovos.intent.enable |
shape-changing: enable an intent (INTENT-4 §8.5) |
mycroft.skill.disable_intent |
ovos.intent.disable |
shape-changing: disable an intent (INTENT-4 §8.5) |
On ovos.intent.register.keyword / .template, ovos.intent.deregister, ovos.skill.deregister, and ovos.intent.enable / .disable, the payload skill_id names the target: the skill whose registration is created, removed, suppressed or re-armed (INTENT-4 §3.2). The context skill_id names the source and is provenance only. A consumer logs the two at DEBUG when they differ and never substitutes one for the other, never rejects on a difference, and never treats an absent context skill_id as malformed. A skill built on ovos-workshop never emits these directly, since the base class already fills both fields.
These topics are alpha-channel only
The orchestrator manifest that answers them first shipped in ovos-core
2.4.0a1, and every release carrying it is a prerelease. The stable channel
pins ovos-core>=1.3.1,<1.4.0 and the testing channel pins >=2.1.1,<3.0.0
without prereleases, so neither has the manifest, these topics, or the
identity rule below. This is not a change a reader on those channels can be
on either side of.
The payload became authoritative in 3.4.4a1, and session-scoped enable and
disable route through the same helper from 3.5.2a1. Four alpha releases in
between behaved differently: 3.4.1a1, 3.4.2a1, 3.4.3a1 and 3.4.3a2
treated the context as authoritative and dropped a message whose payload
named a different skill, logging at WARNING. Before and after that window the
payload is preferred, so only a tool built against those four releases, and
only one relying on the drop as a guard, changes meaning on upgrade.
Write ovos.skill.deregister for a skill removing its own registrations. Sending it with a payload skill_id naming a different skill is not a supported operation, and the deregistration messages a skill emits for itself are unaffected by that.
Enable and disable are also scoped to the session doing the toggling (INTENT-4 §11.3), the same session key every registration carries: they change the enabled state of entries matching (session_id, skill_id, intent_name, lang), so disabling an intent from a satellite's session leaves the same intent enabled under the default session and under every other session that registered it. A pipeline engine that suppresses an intent for every session regardless of which one asked is not honoring this scope.
Not bridged: adopt the spec directly¶
A few areas are deliberately not in the translator, so subscribing on the spec name alone will not transparently receive the legacy traffic, or the other way around. These need real adoption in the producer and consumer, not a topic swap:
- Handler-lifecycle trio.
mycroft.skill.handler.start/.complete/.errorare orchestrator-vs-skill private signals. The orchestrator emits the specovos.intent.handler.start/.complete/.errordirectly. The two namespaces are kept separate by design (PIPELINE-1 §8/§11). The trio is shape-changing, and bridging would double-emit. - Intent/entity registration.
register_vocab+register_intent(Adapt's N legacy messages) do not map 1:1 onto the singleovos.intent.register.keyword/.register.template/ovos.entity.registermessage (INTENT-4 §5), which inlines the vocab descriptors. This requires producers and consumers to adopt INTENT-4, not a rename. -
Per-skill stop. The
{skill_id}.stop/{skill_id}.stop.pinghandshake uses runtime-assembled per-skill topics, which cannot be static map keys. STOP-1 defines the broadcast formsovos.stop/ovos.stop.ping/ovos.stop.pongto replace them, and the migration map carries the two that have a legacy counterpart (mycroft.stop→ovos.stop,skill.stop.pong→ovos.stop.pong).Today the skill base class subscribes to the per-skill forms only —
{skill_id}.stopand{skill_id}.stop.ping, plus the bridgedmycroft.stop. It does not subscribe toovos.stop.ping. A skill that adopts the broadcast ping alone stops answering the stop handshake, so keep the per-skill subscriptions until the base class moves.
Read next: Command-line Tools Related: Bus Service · Life of an Utterance · Intent Service · OVOSSkill API