Instalación
openclaw onboard y openclaw channels add --channel whatsapp solicitan instalar el plugin la primera vez que se selecciona; openclaw channels login --channel whatsapp ofrece el mismo flujo de instalación si falta el plugin. Los checkouts de desarrollo utilizan la ruta local del plugin; las instalaciones estables/beta instalan primero @openclaw/whatsapp desde ClawHub y recurren a npm si falla. El entorno de ejecución de WhatsApp se distribuye fuera del paquete npm principal de OpenClaw, por lo que sus dependencias de ejecución permanecen en el plugin externo. Instalación manual:
@openclaw/whatsapp) únicamente como alternativa del registro; fije una versión exacta solo para obtener una instalación reproducible.
Vinculación
Solución de problemas de canales
Configuración del Gateway
Configuración rápida
Configurar la política de acceso
Vincular WhatsApp (QR)
Iniciar el Gateway
Aprobar la primera solicitud de acceso por mensaje directo (modo de vinculación)
Patrones de despliegue
Número dedicado (recomendado)
Número dedicado (recomendado)
- identidad de WhatsApp independiente para OpenClaw
- listas de permitidos de mensajes directos y límites de enrutamiento más claros
- menor probabilidad de confusión con el chat con uno mismo
Alternativa con número personal
Alternativa con número personal
dmPolicy: "allowlist", allowFrom incluido su propio número, selfChatMode: true. Las protecciones del entorno de ejecución para el chat con uno mismo se basan en el número propio vinculado junto con allowFrom.Modelo de ejecución
- El Gateway es responsable del socket de WhatsApp y del bucle de reconexión.
- Un monitor supervisa dos señales de forma independiente: la actividad de transporte sin procesar de WhatsApp Web y la actividad de mensajes de la aplicación. Una sesión inactiva pero conectada no se reinicia solo porque no se haya recibido ningún mensaje recientemente; solo fuerza la reconexión cuando dejan de llegar tramas de transporte durante un intervalo interno fijo (no configurable por el usuario) o los mensajes de la aplicación permanecen inactivos durante más de 4 veces el tiempo de espera normal de mensajes. Inmediatamente después de una reconexión de una sesión activa recientemente, ese primer intervalo utiliza el tiempo de espera normal de mensajes, más corto, en lugar del intervalo de 4 veces. OpenClaw puede responder automáticamente a los mensajes sin conexión que Baileys entrega al principio de esa reconexión, dentro del límite de la duración de la desduplicación de identificadores de mensajes entrantes; el inicio inicial mantiene la protección breve contra el historial obsoleto.
- Los envíos salientes requieren un listener de WhatsApp activo para la cuenta de destino; de lo contrario, fallan de inmediato.
- Los envíos a grupos adjuntan metadatos nativos de menciones para los tokens
@+<digits>y@<digits>(en el texto y en los pies de contenido multimedia) cuando el token coincide con los metadatos actuales de un participante, incluidos los grupos respaldados por LID. - Se ignoran los chats de estado y difusión (
@status,@broadcast). - Los chats directos utilizan las reglas de sesión de mensajes directos (
session.dmScope; el valor predeterminadomainagrupa los mensajes directos en la sesión principal del agente). Las sesiones de grupo se aíslan por JID (agent:<agentId>:whatsapp:group:<jid>). - Los Canales/Boletines de WhatsApp pueden ser destinos salientes explícitos mediante su JID
@newsletternativo, utilizando metadatos de sesión de canal (agent:<agentId>:whatsapp:channel:<jid>) en lugar de la semántica de mensajes directos. - El transporte de WhatsApp Web respeta las variables de entorno de proxy estándar en el host del Gateway (
HTTPS_PROXY,HTTP_PROXY,NO_PROXY, y sus variantes en minúsculas). Se recomienda la configuración del proxy en el host en lugar de ajustes por canal.
Llamar al solicitante actual con MeowCaller (experimental)
El plugin puede exponerwhatsapp_call en los turnos del agente originados en WhatsApp. Utiliza MeowCaller para realizar una llamada de voz de WhatsApp al solicitante autorizado actual y reproducir un mensaje TTS de OpenClaw cuando responda. La herramienta no tiene ningún parámetro de número de destino, por lo que una instrucción no puede redirigir la llamada. Está desactivada de forma predeterminada.
Activar las llamadas experimentales
actions.calls: true a la configuración del canal de WhatsApp y reinicie el Gateway:false, OpenClaw no expone la herramienta whatsapp_call.Instalar la CLI revisada de MeowCaller
meowcaller en el PATH del host del Gateway. Hasta que se fusione el pull request #7 de MeowCaller, compile la rama revisada:$HOME/.local/bin esté en el PATH del servicio del Gateway. Esta revisión incluye comandos explícitos pair y notify de solo envío; notify no abre ningún micrófono, altavoz, dispositivo de vídeo ni captura de diagnóstico. No lo sustituya por el comando play de la CLI de ejemplo del proyecto original.Vincular el dispositivo enlazado de MeowCaller
whatsapp_call informa del directorio de estado específico de la cuenta y del comando de vinculación). Para la cuenta predeterminada:MeowCaller linked device ready. Mantenga wa-voip.db en privado: es la sesión de MeowCaller. Las cuentas no predeterminadas obtienen su propia ruta de almacenamiento mediante la acción de estado; en Windows, ejecute su comando de PowerShell.Configurar TTS y llamar desde WhatsApp
Call me and say the build finished. La herramienta obtiene el remitente a partir del contexto entrante de confianza, sintetiza un archivo WAV privado temporal, ejecuta MeowCaller durante un intervalo de llamada limitado y elimina después el archivo de audio. OpenClaw pasa explícitamente el almacenamiento de la cuenta, espera un estado de salida cero después de responder, reproducir y colgar, y considera que un tiempo de espera agotado o un estado de salida distinto de cero constituyen una llamada fallida de la herramienta.Solicitudes de aprobación
WhatsApp puede representar las solicitudes de aprobación de ejecución y plugins como reacciones👍/👎, controladas mediante la configuración de reenvío de aprobaciones de nivel superior:
approvals.exec y approvals.plugin son independientes; activar WhatsApp como canal solo vincula el transporte y no envía nada a menos que la familia de aprobaciones correspondiente esté activada y enrutada allí. El modo de sesión entrega aprobaciones de emojis nativas únicamente para las aprobaciones que se originan en WhatsApp. El modo de destino utiliza el pipeline de reenvío compartido para destinos explícitos y no crea una distribución independiente a mensajes directos de aprobadores.
Las reacciones de aprobación de WhatsApp requieren aprobadores explícitos en allowFrom (o "*"). defaultTo establece destinos predeterminados para mensajes normales, no una lista de aprobadores. Los comandos manuales /approve siguen pasando por la ruta normal de autorización de remitentes de WhatsApp antes de resolver la aprobación.
Reacciones a preguntas
Para una solicitudask_user con una pregunta no secreta de selección única y entre una y cuatro opciones, WhatsApp muestra desde 1️⃣ hasta 4️⃣ junto a las etiquetas de las opciones. Reaccione a la solicitud entregada con el número correspondiente para responder. OpenClaw asigna el número a la opción canónica mediante el Gateway; se ignoran las pulsaciones obsoletas o duplicadas. Las solicitudes con varias preguntas, selección múltiple o texto libre siguen admitiendo únicamente respuestas de texto. Las reglas normales de admisión de mensajes directos y grupos de WhatsApp autorizan al remitente que reacciona.
Hooks de plugins y privacidad
Los mensajes entrantes de WhatsApp pueden contener información personal, números de teléfono, identificadores de grupos, nombres de remitentes y campos de correlación de sesiones. WhatsApp no difunde a los plugins las cargas útiles entrantes del hookmessage_received salvo que se habilite explícitamente:
channels.whatsapp.accounts.<id>.pluginHooks.messageReceived. Active esta opción únicamente para plugins en los que confíe para gestionar el contenido y los identificadores entrantes de WhatsApp.
Control de acceso y activación
- Política de mensajes directos
- Política de grupos y listas de permitidos
- Menciones y /activation
channels.whatsapp.dmPolicy:allowFrom acepta números con formato E.164 (normalizados internamente). Es únicamente una lista de control de acceso de remitentes de mensajes directos; no restringe los envíos salientes explícitos a JID de grupos ni a JID de canales de @newsletter.Anulación para varias cuentas: channels.whatsapp.accounts.<id>.dmPolicy (y .allowFrom) tienen prioridad sobre los valores predeterminados del canal para esa cuenta.Notas sobre el entorno de ejecución:- los emparejamientos persisten en el almacén de permitidos del canal y se combinan con la configuración de
allowFrom - la automatización programada y la selección alternativa de destinatarios de Heartbeat usan destinos de entrega explícitos o la configuración de
allowFrom; las aprobaciones de emparejamiento de mensajes directos no se convierten implícitamente en destinatarios de Cron/Heartbeat - si no se configura ninguna lista de permitidos, el número propio vinculado se permite de forma predeterminada
- OpenClaw nunca empareja automáticamente los mensajes directos salientes de
fromMe(mensajes que se envían al propio usuario desde el dispositivo vinculado)
Enlaces ACP configurados
WhatsApp admite enlaces ACP persistentes mediantebindings[] en el nivel superior:
Comportamiento del número personal y del chat propio
Cuando el número propio vinculado también está presente enallowFrom, se activan las protecciones para el chat propio: se omiten las confirmaciones de lectura para los turnos del chat propio, se ignora el comportamiento de activación automática mediante el JID de mención que provocaría una mención al propio usuario y las respuestas utilizan de forma predeterminada [{identity.name}] (o [openclaw]) cuando no se establece responsePrefix para el canal o la cuenta.
Normalización de mensajes y contexto
Envoltorio de entrada y contexto de respuesta
Envoltorio de entrada y contexto de respuesta
ReplyToId, ReplyToBody, ReplyToSender, JID/E.164 del remitente) se rellenan cuando están disponibles. Si el destino citado es contenido multimedia descargable, OpenClaw lo guarda mediante el almacén habitual de contenido multimedia entrante y expone MediaPath/MediaType para que el agente pueda inspeccionarlo directamente, en lugar de ver únicamente <media:image>.Marcadores de contenido multimedia y extracción de ubicaciones/contactos
Marcadores de contenido multimedia y extracción de ubicaciones/contactos
<media:image>, <media:video>, <media:audio>, <media:document>, <media:sticker>.Las notas de voz de grupos autorizados se transcriben antes de comprobar las menciones cuando el cuerpo solo contiene <media:audio>, por lo que mencionar al bot en la nota de voz puede activar la respuesta. Si la transcripción sigue sin mencionar al bot, permanece en el historial pendiente del grupo en lugar de conservar el marcador sin procesar.Los cuerpos de ubicación se representan como texto conciso de coordenadas. Las etiquetas o comentarios de ubicación y los detalles de contactos/vCard se representan como metadatos no confiables delimitados, no como texto insertado directamente en el prompt.Inyección del historial pendiente de grupos
Inyección del historial pendiente de grupos
- límite predeterminado:
50 - configuración:
channels.whatsapp.historyLimit, conmessages.groupChat.historyLimitcomo alternativa 0deshabilita esta función
[Chat messages since your last reply - for context] y [Current message - respond to this].Confirmaciones de lectura
Confirmaciones de lectura
channels.whatsapp.accounts.<id>.sendReadReceipts. Los turnos del chat propio omiten las confirmaciones de lectura aunque estén habilitadas globalmente.Entrega, fragmentación y contenido multimedia
Fragmentación de texto
Fragmentación de texto
- límite predeterminado de fragmentos:
channels.whatsapp.textChunkLimit = 4000 channels.whatsapp.streaming.chunkMode = "length" | "newline";newlineprioriza los límites entre párrafos (líneas en blanco) y después recurre a una fragmentación segura según la longitud
Comportamiento del contenido multimedia saliente
Comportamiento del contenido multimedia saliente
- admite cargas de imágenes, vídeos, audio (nota de voz PTT) y documentos
- el audio se envía como carga
audiode Baileys conptt: true, y se representa como una nota de voz de pulsar para hablar;audioAsVoicese conserva en las cargas de respuesta para que la salida de notas de voz de TTS permanezca en esta ruta independientemente del formato de origen del proveedor - el audio Ogg/Opus nativo se envía como
audio/ogg; codecs=opus; cualquier otro formato (incluida la salida MP3/WebM de TTS de Microsoft Edge) se transcodifica medianteffmpega Ogg/Opus mono de 48 kHz antes de la entrega mediante PTT /tts latestenvía la respuesta más reciente del asistente como una sola nota de voz y evita los envíos repetidos de la misma respuesta;/tts chat on|off|defaultcontrola el TTS automático del chat actual- habilitar
gifPlayback: trueen vídeos permite la reproducción como GIF animado forceDocument/asDocumentdirige las imágenes, los GIF y los vídeos salientes a través de la carga de documentos de Baileys para evitar la compresión multimedia de WhatsApp y conservar el nombre de archivo y el tipo MIME resueltos- los pies de contenido se aplican al primer elemento multimedia de una respuesta con varios elementos, excepto en las notas de voz PTT: el audio se envía primero sin pie y después el pie se envía como un mensaje de texto independiente (los clientes de WhatsApp no representan de forma coherente los pies de las notas de voz)
- el origen del contenido multimedia puede ser HTTP(S),
file://o una ruta local
Límites de tamaño del contenido multimedia y comportamiento alternativo
Límites de tamaño del contenido multimedia y comportamiento alternativo
- límite de guardado entrante y de envío saliente:
channels.whatsapp.mediaMaxMb(valor predeterminado:50) - anulación por cuenta:
channels.whatsapp.accounts.<id>.mediaMaxMb - las imágenes se optimizan automáticamente (ajuste de tamaño/calidad) para cumplir los límites, salvo que
forceDocument/asDocumentsolicite la entrega como documento - si falla el envío de contenido multimedia, la alternativa para el primer elemento envía una advertencia de texto en lugar de descartar silenciosamente la respuesta
Citas en respuestas
channels.whatsapp.replyToMode controla las citas nativas en respuestas (las respuestas salientes citan visiblemente el mensaje entrante):
channels.whatsapp.accounts.<id>.replyToMode.
Nivel de reacciones
channels.whatsapp.reactionLevel controla con qué amplitud utiliza el agente las reacciones con emojis:
channels.whatsapp.accounts.<id>.reactionLevel.
Reacciones de confirmación
channels.whatsapp.ackReaction envía una reacción inmediata al recibir un mensaje entrante, condicionada por reactionLevel (se suprime cuando "off"):
ackReaction está presente sin emoji, WhatsApp utiliza el emoji de identidad del agente al que se dirige el mensaje y recurre a ”👀” como alternativa (omita ackReaction o establezca emoji: "" para no enviar confirmación); los errores se registran, pero no bloquean la entrega de la respuesta; el modo de grupo mentions solo reacciona en los turnos activados mediante una mención, mientras que la activación de grupo always omite esa comprobación; WhatsApp solo utiliza channels.whatsapp.ackReaction (el messages.ackReaction heredado no se aplica aquí).
Reacciones de estado del ciclo de vida
Establezcamessages.statusReactions.enabled: true para permitir que WhatsApp sustituya la reacción de confirmación durante un turno en lugar de dejar un emoji de recepción estático, pasando por estados como en cola, pensando, actividad de herramientas, Compaction, finalizado y error:
channels.whatsapp.ackReaction sigue controlando la aptitud para mensajes directos y grupos; el estado en cola utiliza el mismo emoji efectivo que las reacciones de confirmación simples; WhatsApp dispone de un espacio de reacción del bot por mensaje, por lo que las actualizaciones del ciclo de vida sustituyen la reacción actual y restauran la confirmación después del estado final de finalización o error.
Varias cuentas y credenciales
Selección de cuentas y valores predeterminados
Selección de cuentas y valores predeterminados
channels.whatsapp.accounts. La selección de cuenta predeterminada es default si está presente; de lo contrario, se usa el primer identificador de cuenta configurado (ordenado alfabéticamente). Los identificadores de cuenta se normalizan internamente para su búsqueda.Rutas de credenciales y compatibilidad heredada
Rutas de credenciales y compatibilidad heredada
- ruta de autenticación actual:
~/.openclaw/credentials/whatsapp/<accountId>/creds.json(copia de seguridad:creds.json.bak) - la autenticación predeterminada heredada en
~/.openclaw/credentials/todavía se reconoce y migra para los flujos de la cuenta predeterminada
Comportamiento al cerrar sesión
Comportamiento al cerrar sesión
openclaw channels logout --channel whatsapp [--account <id>] borra el estado de autenticación de WhatsApp para esa cuenta. Cuando se puede acceder a un Gateway, el cierre de sesión detiene primero el receptor activo de esa cuenta, de modo que la sesión vinculada deja de recibir mensajes antes del siguiente reinicio. openclaw channels remove --channel whatsapp también detiene el receptor activo antes de deshabilitar o eliminar la configuración de la cuenta.En los directorios de autenticación heredados, se conserva oauth.json mientras se eliminan los archivos de autenticación de Baileys.Herramientas, acciones y escrituras de configuración
- La compatibilidad con herramientas del agente incluye la acción de reacción de WhatsApp (
react). - Controles de acciones:
channels.whatsapp.actions.reactions,channels.whatsapp.actions.polls(el valor predeterminado de las acciones existentes estrue),channels.whatsapp.actions.calls(valor predeterminado:false; consulte MeowCaller más arriba). - Las escrituras de configuración iniciadas por el canal están habilitadas de forma predeterminada; deshabilítelas mediante
channels.whatsapp.configWrites: false.
Solución de problemas
Sin vincular (se requiere un código QR)
Sin vincular (se requiere un código QR)
Vinculado, pero desconectado o en un bucle de reconexión
Vinculado, pero desconectado o en un bucle de reconexión
~/.openclaw/logs/whatsapp-health.log indica Gateway inactive, pero tanto openclaw gateway status como openclaw channels status --probe muestran un estado correcto, ejecute openclaw doctor. En Linux, doctor advierte sobre entradas heredadas de crontab que invocan el script retirado ~/.openclaw/bin/ensure-whatsapp.sh; elimine esas entradas con crontab -e. Cron puede carecer del entorno del bus de usuario de systemd y hacer que ese script antiguo informe incorrectamente del estado del Gateway.El inicio de sesión mediante QR agota el tiempo de espera detrás de un proxy
El inicio de sesión mediante QR agota el tiempo de espera detrás de un proxy
openclaw channels login --channel whatsapp falla antes de mostrar un código QR utilizable con status=408 Request Time-out o con una desconexión del socket TLS.El inicio de sesión de WhatsApp Web utiliza el entorno de proxy estándar del host del Gateway (HTTPS_PROXY, HTTP_PROXY, variantes en minúsculas, NO_PROXY). Verifique que el proceso del Gateway herede el entorno del proxy y que NO_PROXY no coincida con mmg.whatsapp.net.No hay ningún receptor activo al enviar
No hay ningún receptor activo al enviar
La respuesta aparece en la transcripción, pero no en WhatsApp
La respuesta aparece en la transcripción, pero no en WhatsApp
auto-reply delivery failed o auto-reply was not accepted by WhatsApp provider.Los mensajes de grupo se ignoran inesperadamente
Los mensajes de grupo se ignoran inesperadamente
groupPolicy, groupAllowFrom/allowFrom, las entradas de la lista de permitidos de groups, el control de menciones (requireMention + patrones de mención) y las claves duplicadas en openclaw.json (las entradas posteriores de JSON5 sobrescriben las anteriores; mantenga un único groupPolicy por ámbito).Si channels.whatsapp.groups está presente, WhatsApp aún puede observar mensajes de otros grupos, pero OpenClaw los descarta antes del enrutamiento de sesiones. Añada el JID del grupo a channels.whatsapp.groups o añada groups["*"] para admitir todos los grupos y mantener la autorización de remitentes en groupPolicy/groupAllowFrom.Advertencia sobre el entorno de ejecución Bun
Advertencia sobre el entorno de ejecución Bun
node:sqlite utilizada por el almacén de estado canónico, y doctor migra los servicios heredados de Bun a Node.Prompts del sistema
WhatsApp admite prompts del sistema al estilo de Telegram para grupos y chats directos mediante los mapasgroups y direct.
Resolución para mensajes de grupo: primero se determina el mapa groups efectivo; si la cuenta define su propia clave groups, esta sustituye por completo el mapa raíz groups (sin combinación profunda). La búsqueda del prompt se realiza después en ese único mapa resultante:
- Prompt específico del grupo (
groups["<groupId>"].systemPrompt): se utiliza cuando existe la entrada del grupo y está definida su clavesystemPrompt. Una cadena vacía ("") suprime el comodín y no aplica ningún prompt. - Prompt comodín de grupo (
groups["*"].systemPrompt): se utiliza cuando la entrada específica del grupo no existe o existe sin una clavesystemPrompt.
direct y direct["*"].
dms sigue siendo el contenedor ligero de reemplazos del historial por mensaje directo (dms.<id>.historyLimit). Los reemplazos de prompts se encuentran en direct.groups/direct de la cuenta, incluido un objeto vacío explícito, sustituye el mapa raíz. Es diferente de la comprobación de la lista de permitidos para pertenencia a grupos descrita más arriba, que dispone de una protección para cuentas únicas en caso de que groups: {} quede vacío accidentalmente.groups para todas las cuentas de una configuración con varias cuentas (incluso para las cuentas que no tienen su propio groups) para evitar que un bot reciba mensajes de grupos a los que no pertenece. WhatsApp no aplica esa protección: cualquier cuenta sin un reemplazo propio hereda los valores raíz groups/direct, independientemente del número de cuentas. En una configuración de WhatsApp con varias cuentas, defina explícitamente el mapa completo en cada cuenta si desea prompts por cuenta.
Comportamiento importante:
channels.whatsapp.groupses tanto un mapa de configuración por grupo como la lista de permitidos de grupos a nivel de chat. Tanto en el ámbito raíz como en el de la cuenta,groups["*"]significa «se admiten todos los grupos» para ese ámbito.- Añada un comodín
systemPromptsolo cuando ya desee que ese ámbito admita todos los grupos. Para mantener como elegibles únicamente un conjunto fijo de identificadores de grupo, repita el prompt en cada entrada incluida explícitamente en la lista de permitidos en lugar de utilizargroups["*"]. - La admisión de grupos y la autorización de remitentes son comprobaciones independientes.
groups["*"]amplía los grupos que llegan al procesamiento de grupos; no autoriza a todos los remitentes de esos grupos. Esto sigue controlado porgroupPolicy/groupAllowFrom. channels.whatsapp.directno tiene ningún efecto secundario equivalente para los mensajes directos:direct["*"]solo proporciona una configuración predeterminada después de que un mensaje directo ya se haya admitido mediantedmPolicyjunto conallowFromo las reglas del almacén de emparejamientos.