Integración WhatsApp (canal web): login, inbox, respuestas, medios y operaciones.
Estado: Solo soporta WhatsApp Web vía Baileys. Las sesiones son gestionadas por el Gateway.
Inicio Rápido para Principiantes
1. Usa un número de teléfono separado si es posible (recomendado).
2. Configura WhatsApp en ~/.openclaw/openclaw.json.
3. Ejecuta openclaw channels login para escanear código QR (WhatsApp → Settings → Linked Devices).
4. Inicia el Gateway.
Ejemplo de configuración mínima:
{
channels: {
whatsapp: {
dmPolicy: "allowlist",
allowFrom: ["+15551234567"],
},
},
}Objetivos
- Soportar múltiples cuentas de WhatsApp en el mismo proceso Gateway (multi-cuenta).
- Enrutamiento determinístico: mensajes de WhatsApp regresan a WhatsApp (no dejes que el modelo elija canal).
- El modelo puede ver suficiente contexto de cita/respuesta para entender "a qué mensaje estoy respondiendo".
Escrituras de Config
Por defecto, WhatsApp permite actualizaciones de config disparadas por /config set|unset ser escritas de vuelta al archivo de config (requiere commands.config: true).
Deshabilitar:
{
channels: { whatsapp: { configWrites: false } },
}Arquitectura (Quién Hace Qué)
- Gateway maneja el socket Baileys y el loop de inbox.
- CLI / app macOS solo comunica con el Gateway, no usa Baileys directamente.
- El envío saliente requiere listener activo; de lo contrario falla rápido (sin sesión web).
Obtener un Número de Teléfono (Dos Modos)
WhatsApp requiere un número de teléfono real para verificación. Números VoIP/virtuales usualmente son bloqueados. OpenClaw tiene dos formas recomendadas de ejecutar en WhatsApp:
#
Número Dedicado (Recomendado)
Dale a OpenClaw un número separado. Mejor experiencia: enrutamiento claro, sin casos edge raros de "mensajearse a sí mismo". Configuración ideal: teléfono Android de repuesto/antiguo + eSIM, conectado a Wi-Fi y energía, vinculado vía código QR.
WhatsApp Business: Puedes instalar WhatsApp y WhatsApp Business con números diferentes en el mismo dispositivo. Poner OpenClaw en Business es un buen aislamiento.
Ejemplo de config (número dedicado, allowlist de usuario único):
{
channels: {
whatsapp: {
dmPolicy: "allowlist",
allowFrom: ["+15551234567"],
},
},
}Opcional: Modo de Emparejamiento
Si quieres usar emparejamiento en lugar de allowlist, establece channels.whatsapp.dmPolicy a pairing. Remitentes desconocidos recibirán un código de emparejamiento; aprueba con:
openclaw pairing approve whatsapp <code>
#
Número Personal (Fallback)
Fallback: deja que OpenClaw corra en tu propio número. Para pruebas, puedes enviarte mensajes a ti mismo en "Message yourself" de WhatsApp para evitar molestar contactos. Necesitarás leer el código de verificación en tu teléfono principal durante la configuración. Debes habilitar modo self-chat.
Cuando el wizard pida tu número personal de WhatsApp, ingresa el número "des donde enviarás mensajes al asistente" (owner/sender), no "número del asistente" (ya que es el mismo número aquí).
Ejemplo de config (número personal + self-chat):
{
"whatsapp": {
"selfChatMode": true,
"dmPolicy": "allowlist",
"allowFrom": ["+15551234567"]
}
}En modo self-chat, si messages.responsePrefix no está establecido, el prefijo de respuesta por defecto es [{identity.name}] (de lo contrario [openclaw]). Para personalizar o deshabilitar prefijo, establécelo explícitamente (usa "" para remover).
#
Recomendaciones de Fuente de Número
- eSIM local de operador en tu país (más estable)
- Austria: ''hot.at''
- UK: ''giffgaff'' (SIM gratis, sin contrato)
- SIM Prepago — solo necesita recibir un SMS de verificación
Evita: TextNow, Google Voice, la mayoría de servicios "free SMS receive" (WhatsApp bloquea agresivamente).
Tip: El número solo necesita recibir un SMS de verificación. Después de eso, la sesión de WhatsApp Web persiste vía creds.json.
Why Not Twilio?
- Early OpenClaw supported Twilio's WhatsApp Business integration.
- WhatsApp Business numbers aren't suitable for personal assistants.
- Meta enforces 24-hour reply window; Business numbers can't initiate new messages after 24 hours of inactivity.
- High-frequency/chatty use triggers more aggressive blocking because Business accounts aren't meant for sending many personal assistant messages.
- Result: unstable delivery, frequent blocking, so support was removed.
Login and Credentials
- Login command: openclaw channels login (scan QR code: Linked Devices).
- Multi-account login: openclaw channels login --account <id> (<id> = accountId).
- Default account: when --account is omitted, use default if exists, otherwise first configured account id by sort order.
- Credentials storage: ~/.openclaw/credentials/whatsapp/<accountId>/creds.json.
- Backup copy: creds.json.bak (used for recovery if corrupted).
- Legacy compatibility: older installs put Baileys files directly under ~/.openclaw/credentials/.
- Logout: openclaw channels logout (or --account <id>) deletes WhatsApp auth state (but keeps shared oauth.json).
- Unlogged sockets will error and prompt to relink.
Inbound Flow (DM + Groups)
- WhatsApp events come from Baileys' messages.upsert.
- To avoid accumulating event handlers during testing/restarts, inbox listeners are unmounted on shutdown.
- Ignores status/broadcast chats.
- DMs use E.164; groups use group JID.
- DM Policy: channels.whatsapp.dmPolicy controls DM access (default pairing).
- pairing: unknown senders receive pairing code (openclaw pairing approve whatsapp <code>; expires in 1 hour).
- open: requires channels.whatsapp.allowFrom to contain "*".
- Your bound WhatsApp number is implicitly trusted: self-sent messages skip dmPolicy and allowFrom checks.
#
Personal Number Mode (Fallback)
Si ejecutas OpenClaw en tu número personal de WhatsApp, habilita channels.whatsapp.selfChatMode (ver ejemplo arriba).
Behavior:
- Outbound DMs won't trigger pairing replies (avoid spamming contacts).
- Inbound unknown senders still follow channels.whatsapp.dmPolicy.
- self-chat mode (allowFrom contains your own number) avoids automatic read receipts and ignores mention JIDs.
- Non-self-chat DMs send read receipts.
Read Receipts
By default, Gateway marks WhatsApp inbound messages as read (blue checkmarks) after they're accepted.
Global disable:
{
channels: { whatsapp: { sendReadReceipts: false } },
}Per-account disable:
{
channels: {
whatsapp: {
accounts: {
personal: { sendReadReceipts: false },
},
},
},
}Notes:
- self-chat mode always skips read receipts.
WhatsApp FAQ: Messaging and Pairing
Will OpenClaw send messages to random contacts after linking WhatsApp?
No. Default DM policy is pairing: unknown senders only receive a pairing code, their messages won't be processed. OpenClaw only replies to chats it receives, or sends you explicitly trigger (agent/CLI).
How does WhatsApp pairing work?
Pairing is a DM gatekeeper for unknown senders:
- New sender's first DM receives a short code (message not processed).
- Approve: openclaw pairing approve whatsapp <code> (list: openclaw pairing list whatsapp).
- Pairing code expires in 1 hour; default pending request limit per channel is 3.
Can one WhatsApp number be used by multiple people with different OpenClaw instances?
Yes: route different senders to different agents via ''bindings'' (peer ''kind: "dm"'', sender with ''+1555...'' E.164). But replies still come from ''same WhatsApp account'', and DMs fold into each agent's main session, so recommend ''one agent per person''. DM access control (''dmPolicy''/''allowFrom'') is global per WhatsApp account. See ''Multi-Agent Routing''.
Why does wizard ask for my phone number?
Wizard uses it to set your owner/allowlist, ensuring your own DMs are allowed. It won't be used for auto-sending. If you run on personal number, enter same number and enable channels.whatsapp.selfChatMode.
Message Normalization (What Model Sees)
- Body is current message body (with envelope).
- Quote/reply context is always appended:
[Replying to +1555 id:ABC123]
<quoted text or <media:...>>
[/Replying]- Reply metadata is also set:
- ReplyToId = stanzaId
- ReplyToBody = quoted body or media placeholder
- ReplyToSender = E.164 when available
- Pure media inbound messages use placeholder:
- <media:image|video|audio|document|sticker>
Groups
- Group session key: agent:<agentId>:whatsapp:group:<jid>.
- Group policy: channels.whatsapp.groupPolicy = open|disabled|allowlist (default allowlist).
- Trigger modes:
- mention (default): requires @mention or regex match.
- always: always trigger.
- /activation mention|always only available to owner, must be sent as separate message.
- owner = channels.whatsapp.allowFrom (or self E.164 if not set).
- History Injection (pending only):
- Recent unprocessed messages (default 50) inserted into:
[Chat messages since your last reply - for context]
- Current message inserted into:
[Current message - respond to this]
- Sender info appended at end: [from: Name (+E164)]
- Group metadata cached for 5 minutes (subject + members).
Reply Delivery (Threads)
- Current gateway's WhatsApp Web outbound only sends plain messages (no quoted reply threading).
- Reply tags are ignored on this channel.
Ack Reaction (Auto-react on Receive)
WhatsApp can automatically send an emoji reaction immediately after receiving a message (before bot generates reply), letting user know "message received" right away.
Configuration:
{
"whatsapp": {
"ackReaction": {
"emoji": "👀",
"direct": true,
"group": "mentions"
}
}
}Options:
- emoji (string): Emoji for acknowledgment (e.g., "👀", "✅", "📨"). Empty or omitted means disabled.
- direct (boolean): Enable for DMs (default: true).
- group (string|boolean): Enable for groups. "mentions" = only when mentioned; true = always; false = disabled (default: "mentions").