Skip to main content
Wake words are one global list owned by the Gateway — there are no per-node custom lists. Any node or app UI can edit the list; the Gateway persists the change and broadcasts it to every connected client.
  • macOS: local Voice Wake enable/disable toggle. Requires macOS 26+; see Voice wake (macOS) for runtime/PTT details.
  • iOS: local Voice Wake enable/disable toggle in Settings.
  • Android: local Voice Wake enable/disable toggle and wake-word editor in Settings → Voice. Requires Android on-device speech recognition.

Storage

Wake words and routing rules live in the Gateway state database, ~/.openclaw/state/openclaw.sqlite by default (override with OPENCLAW_STATE_DIR), tables voicewake_triggers, voicewake_routing_config, voicewake_routing_routes. Legacy settings/voicewake.json and settings/voicewake-routing.json are openclaw doctor --fix migration inputs only — runtime never reads them.

Protocol

Trigger list

voicewake.set normalizes input: trims whitespace, drops empty entries, keeps at most 32 triggers, and truncates each to 64 UTF-16 code units without splitting surrogate pairs. An empty result falls back to the built-in defaults (openclaw, claude, computer).

Routing (trigger to target)

Each route target supports exactly one of:
  • { "mode": "current" }
  • { "agentId": "main" }
  • { "sessionKey": "agent:main:main" }
Limits: at most 32 routes, trigger text at most 64 characters. Route triggers are normalized for matching and duplicate detection by lowercasing, stripping leading/trailing punctuation from each word, and collapsing whitespace ("Hey, Bot!!" and "hey bot" match and count as duplicates) — this is a stricter normalization than the plain trim used for the global trigger list above.

Events

Both broadcast to every WebSocket client with read scope (macOS app, WebChat, and similar) and to every connected node. A node also gets both as an initial snapshot push right after it connects.

Client behavior

  • macOS: calls voicewake.set/voicewake.get and listens for voicewake.changed to stay in sync with other clients.
  • iOS: calls voicewake.set/voicewake.get and listens for voicewake.changed to keep local wake-word detection responsive.
  • Android: calls voicewake.set/voicewake.get, listens for voicewake.changed, and advertises voiceWake while enabled. Recognition stays on-device and foreground-only; it pauses while Talk, manual dictation, voice-note capture, or message speech owns audio.