BlueBubbles (macOS REST)

Estado: plugin incluido que se comunica con el servidor BlueBubbles en macOS por HTTP. Recomendado para la integración con iMessage gracias a su API más completa y configuración más sencilla en comparación con el canal legacy imsg.

Descripción general

  • Se ejecuta en macOS a través de la app auxiliar BlueBubbles (bluebubbles.app).
  • Recomendado/probado: macOS Sequoia (15). macOS Tahoe (26) funciona; la edición no funciona actualmente en Tahoe, y las actualizaciones de icono de grupo pueden indicar éxito pero no sincronizarse.
  • OpenClaw se comunica con él a través de su API REST (GET /api/v1/ping, POST /message/text, POST /chat/:id/*).
  • Los mensajes entrantes llegan por webhooks; las respuestas salientes, los indicadores de escritura, los acuses de lectura y los tapbacks son llamadas REST.
  • Los archivos adjuntos y stickers se procesan como medios entrantes (y se muestran al agente cuando es posible).
  • El emparejamiento/lista de permitidos funciona igual que en otros canales (/channels/pairing, etc.) con channels.bluebubbles.allowFrom + códigos de emparejamiento.
  • Las reacciones se presentan como eventos del sistema al igual que en Slack/Telegram para que los agentes puedan “mencionarlas” antes de responder.
  • Funciones avanzadas: edición, anulación de envío, hilos de respuesta, efectos de mensaje, gestión de grupos.

Inicio rápido

  1. Instala el servidor BlueBubbles en tu Mac (sigue las instrucciones en bluebubbles.app/install).

  2. En la configuración de BlueBubbles, activa la API web y establece una contraseña.

  3. Ejecuta openclaw onboard y selecciona BlueBubbles, o configura manualmente:

    {
      channels: {
        bluebubbles: {
          enabled: true,
          serverUrl: "http://192.168.1.100:1234",
          password: "example-password",
          webhookPath: "/bluebubbles-webhook",
        },
      },
    }
  4. Apunta los webhooks de BlueBubbles a tu gateway (ejemplo: https://your-gateway-host:3000/bluebubbles-webhook?password=<password>).

  5. Inicia el gateway; registrará el manejador de webhook y comenzará el emparejamiento.

Nota de seguridad:

  • Establece siempre una contraseña para el webhook.
  • La autenticación del webhook siempre es obligatoria. OpenClaw rechaza las solicitudes de webhook de BlueBubbles a menos que incluyan un password/guid que coincida con channels.bluebubbles.password (por ejemplo ?password=<password> o x-password), independientemente de la topología loopback/proxy.
  • La autenticación por contraseña se verifica antes de leer/analizar los cuerpos completos del webhook.

Mantener Messages.app activa (VM / configuraciones sin interfaz)

Algunas configuraciones de macOS en VM o siempre encendidas pueden provocar que Messages.app entre en modo “inactivo” (los eventos entrantes se detienen hasta que la app se abre/se pone en primer plano). Una solución sencilla es activar Messages cada 5 minutos usando un AppleScript + LaunchAgent.

1) Guarda el AppleScript

Guárdalo como:

  • ~/Scripts/poke-messages.scpt

Script de ejemplo (no interactivo; no roba el foco):

try
  tell application "Messages"
    if not running then
      launch
    end if

    -- Touch the scripting interface to keep the process responsive.
    set _chatCount to (count of chats)
  end tell
on error
  -- Ignore transient failures (first-run prompts, locked session, etc).
end try

2) Instala un LaunchAgent

Guárdalo como:

  • ~/Library/LaunchAgents/com.user.poke-messages.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>com.user.poke-messages</string>

    <key>ProgramArguments</key>
    <array>
      <string>/bin/bash</string>
      <string>-lc</string>
      <string>/usr/bin/osascript &quot;$HOME/Scripts/poke-messages.scpt&quot;</string>
    </array>

    <key>RunAtLoad</key>
    <true/>

    <key>StartInterval</key>
    <integer>300</integer>

    <key>StandardOutPath</key>
    <string>/tmp/poke-messages.log</string>
    <key>StandardErrorPath</key>
    <string>/tmp/poke-messages.err</string>
  </dict>
</plist>

Notas:

  • Se ejecuta cada 300 segundos y al iniciar sesión.
  • La primera ejecución puede activar solicitudes de Automatización en macOS (osascript → Messages). Apruébalas en la misma sesión de usuario que ejecuta el LaunchAgent.

Cárgalo:

launchctl unload ~/Library/LaunchAgents/com.user.poke-messages.plist 2>/dev/null || true
launchctl load ~/Library/LaunchAgents/com.user.poke-messages.plist

Configuración inicial

BlueBubbles está disponible en el asistente de configuración interactivo:

openclaw onboard

El asistente solicita:

  • URL del servidor (obligatorio): dirección del servidor BlueBubbles (p. ej., http://192.168.1.100:1234)
  • Contraseña (obligatoria): contraseña de la API en la configuración del servidor BlueBubbles
  • Ruta del webhook (opcional): por defecto /bluebubbles-webhook
  • Política de mensajes directos: emparejamiento, lista de permitidos, abierta o desactivada
  • Lista de permitidos: números de teléfono, correos electrónicos o destinatarios de chat

También puedes añadir BlueBubbles por CLI:

openclaw channels add bluebubbles --http-url http://192.168.1.100:1234 --password <password>

Control de acceso (mensajes directos + grupos)

Mensajes directos:

  • Por defecto: channels.bluebubbles.dmPolicy = "pairing".
  • Los remitentes desconocidos reciben un código de emparejamiento; los mensajes se ignoran hasta que se aprueben (los códigos expiran después de 1 hora).
  • Aprueba mediante:
    • openclaw pairing list bluebubbles
    • openclaw pairing approve bluebubbles <CODE>
  • El emparejamiento es el intercambio de tokens predeterminado. Detalles: Emparejamiento

Grupos:

  • channels.bluebubbles.groupPolicy = open | allowlist | disabled (por defecto: allowlist).
  • channels.bluebubbles.groupAllowFrom controla quién puede activar el bot en grupos cuando se establece allowlist.

Control por mención (grupos)

BlueBubbles admite el control por mención en chats de grupo, siguiendo el comportamiento de iMessage/WhatsApp:

  • Usa agents.list[].groupChat.mentionPatterns (o messages.groupChat.mentionPatterns) para detectar menciones.
  • Cuando requireMention está activado para un grupo, el agente solo responde cuando se le menciona.
  • Los comandos de control de remitentes autorizados evitan el control por mención.

Configuración por grupo:

{
  channels: {
    bluebubbles: {
      groupPolicy: "allowlist",
      groupAllowFrom: ["+15555550123"],
      groups: {
        "*": { requireMention: true }, // predeterminado para todos los grupos
        "iMessage;-;chat123": { requireMention: false }, // excepción para un grupo específico
      },
    },
  },
}

Control de comandos

  • Los comandos de control (p. ej., /config, /model) requieren autorización.
  • Usan allowFrom y groupAllowFrom para determinar la autorización de comandos.
  • Los remitentes autorizados pueden ejecutar comandos de control sin mencionar al bot en grupos.

Indicadores de escritura + acuses de lectura

  • Indicadores de escritura: se envían automáticamente antes y durante la generación de respuestas.
  • Acuses de lectura: controlados por channels.bluebubbles.sendReadReceipts (por defecto: true).
  • Indicadores de escritura: OpenClaw envía eventos de inicio de escritura; BlueBubbles limpia la escritura automáticamente al enviar o por tiempo de espera (la detención manual vía DELETE no es confiable).
{
  channels: {
    bluebubbles: {
      sendReadReceipts: false, // desactivar acuses de lectura
    },
  },
}

Acciones avanzadas

BlueBubbles admite acciones avanzadas de mensajes cuando se activan en la configuración:

{
  channels: {
    bluebubbles: {
      actions: {
        reactions: true, // tapbacks (por defecto: true)
        edit: true, // editar mensajes enviados (macOS 13+, no funciona en macOS 26 Tahoe)
        unsend: true, // anular envío de mensajes (macOS 13+)
        reply: true, // hilos de respuesta por GUID del mensaje
        sendWithEffect: true, // efectos de mensaje (slam, loud, etc.)
        renameGroup: true, // renombrar chats de grupo
        setGroupIcon: true, // establecer icono/foto de chat de grupo (inestable en macOS 26 Tahoe)
        addParticipant: true, // añadir participantes a grupos
        removeParticipant: true, // eliminar participantes de grupos
        leaveGroup: true, // salir de chats de grupo
        sendAttachment: true, // enviar archivos adjuntos/medios
      },
    },
  },
}

Acciones disponibles:

  • react: añadir/eliminar reacciones tapback (messageId, emoji, remove)
  • edit: editar un mensaje enviado (messageId, text)
  • unsend: anular el envío de un mensaje (messageId)
  • reply: responder a un mensaje específico (messageId, text, to)
  • sendWithEffect: enviar con efecto iMessage (text, to, effectId)
  • renameGroup: renombrar un chat de grupo (chatGuid, displayName)
  • setGroupIcon: establecer el icono/foto de un chat de grupo (chatGuid, media) — inestable en macOS 26 Tahoe (la API puede devolver éxito pero el icono no se sincroniza).
  • addParticipant: añadir a alguien a un grupo (chatGuid, address)
  • removeParticipant: eliminar a alguien de un grupo (chatGuid, address)
  • leaveGroup: salir de un chat de grupo (chatGuid)
  • sendAttachment: enviar medios/archivos (to, buffer, filename, asVoice)
    • Notas de voz: establece asVoice: true con audio MP3 o CAF para enviar como mensaje de voz de iMessage. BlueBubbles convierte MP3 a CAF al enviar notas de voz.

IDs de mensajes (cortos vs completos)

OpenClaw puede mostrar IDs de mensajes cortos (p. ej., 1, 2) para ahorrar tokens.

  • MessageSid / ReplyToId pueden ser IDs cortos.
  • MessageSidFull / ReplyToIdFull contienen los IDs completos del proveedor.
  • Los IDs cortos están en memoria; pueden expirar al reiniciar o al desalojar la caché.
  • Las acciones aceptan messageId corto o completo, pero los IDs cortos darán error si ya no están disponibles.

Usa IDs completos para automatizaciones y almacenamiento duraderos:

  • Plantillas: {{MessageSidFull}}, {{ReplyToIdFull}}
  • Contexto: MessageSidFull / ReplyToIdFull en los payloads entrantes

Consulta Configuración para las variables de plantilla.

Transmisión por bloques

Controla si las respuestas se envían como un solo mensaje o se transmiten en bloques:

{
  channels: {
    bluebubbles: {
      blockStreaming: true, // activar transmisión por bloques (desactivado por defecto)
    },
  },
}

Medios + límites

  • Los archivos adjuntos entrantes se descargan y almacenan en la caché de medios.
  • Límite de medios a través de channels.bluebubbles.mediaMaxMb para medios entrantes y salientes (por defecto: 8 MB).
  • El texto saliente se fragmenta según channels.bluebubbles.textChunkLimit (por defecto: 4000 caracteres).

Referencia de configuración

Configuración completa: Configuración

Opciones del proveedor:

  • channels.bluebubbles.enabled: activar/desactivar el canal.
  • channels.bluebubbles.serverUrl: URL base de la API REST de BlueBubbles.
  • channels.bluebubbles.password: contraseña de la API.
  • channels.bluebubbles.webhookPath: ruta del endpoint del webhook (por defecto: /bluebubbles-webhook).
  • channels.bluebubbles.dmPolicy: pairing | allowlist | open | disabled (por defecto: pairing).
  • channels.bluebubbles.allowFrom: lista de permitidos para mensajes directos (handles, correos, números E.164, chat_id:*, chat_guid:*).
  • channels.bluebubbles.groupPolicy: open | allowlist | disabled (por defecto: allowlist).
  • channels.bluebubbles.groupAllowFrom: lista de permitidos de remitentes en grupos.
  • channels.bluebubbles.groups: configuración por grupo (requireMention, etc.).
  • channels.bluebubbles.sendReadReceipts: enviar acuses de lectura (por defecto: true).
  • channels.bluebubbles.blockStreaming: activar transmisión por bloques (por defecto: false; necesario para respuestas en streaming).
  • channels.bluebubbles.textChunkLimit: tamaño de fragmento saliente en caracteres (por defecto: 4000).
  • channels.bluebubbles.chunkMode: length (por defecto) divide solo al exceder textChunkLimit; newline divide en líneas en blanco (límites de párrafo) antes de la división por longitud.
  • channels.bluebubbles.mediaMaxMb: límite de medios entrantes/salientes en MB (por defecto: 8).
  • channels.bluebubbles.mediaLocalRoots: lista explícita de directorios locales absolutos permitidos para rutas de medios locales salientes. Los envíos de rutas locales se deniegan por defecto a menos que esté configurado. Excepción por cuenta: channels.bluebubbles.accounts.<accountId>.mediaLocalRoots.
  • channels.bluebubbles.historyLimit: máximo de mensajes de grupo para contexto (0 desactiva).
  • channels.bluebubbles.dmHistoryLimit: límite de historial de mensajes directos.
  • channels.bluebubbles.actions: activar/desactivar acciones específicas.
  • channels.bluebubbles.accounts: configuración multicuenta.

Opciones globales relacionadas:

  • agents.list[].groupChat.mentionPatterns (o messages.groupChat.mentionPatterns).
  • messages.responsePrefix.

Direccionamiento / destinos de entrega

Prefiere chat_guid para un enrutamiento estable:

  • chat_guid:iMessage;-;+15555550123 (preferido para grupos)
  • chat_id:123
  • chat_identifier:...
  • Handles directos: +15555550123, [email protected]
    • Si un handle directo no tiene un chat de mensajes directos existente, OpenClaw creará uno a través de POST /api/v1/chat/new. Esto requiere que la API privada de BlueBubbles esté habilitada.

Seguridad

  • Las solicitudes de webhook se autentican comparando los parámetros de consulta o encabezados guid/password con channels.bluebubbles.password. Las solicitudes desde localhost también se aceptan.
  • Mantén la contraseña de la API y el endpoint del webhook en secreto (trátalos como credenciales).
  • La confianza en localhost significa que un proxy inverso en el mismo host puede evadir involuntariamente la contraseña. Si usas un proxy para el gateway, exige autenticación en el proxy y configura gateway.trustedProxies. Consulta Seguridad del gateway.
  • Habilita HTTPS + reglas de firewall en el servidor BlueBubbles si lo expones fuera de tu red local.

Solución de problemas

  • Si los eventos de escritura/lectura dejan de funcionar, revisa los registros de webhook de BlueBubbles y verifica que la ruta del gateway coincida con channels.bluebubbles.webhookPath.
  • Los códigos de emparejamiento expiran después de una hora; usa openclaw pairing list bluebubbles y openclaw pairing approve bluebubbles <code>.
  • Las reacciones requieren la API privada de BlueBubbles (POST /api/v1/message/react); asegúrate de que la versión del servidor la exponga.
  • Editar/anular envío requiere macOS 13+ y una versión compatible del servidor BlueBubbles. En macOS 26 (Tahoe), la edición no funciona actualmente debido a cambios en la API privada.
  • Las actualizaciones de icono de grupo pueden ser inestables en macOS 26 (Tahoe): la API puede devolver éxito pero el nuevo icono no se sincroniza.
  • OpenClaw oculta automáticamente las acciones que se sabe que no funcionan según la versión de macOS del servidor BlueBubbles. Si la edición sigue apareciendo en macOS 26 (Tahoe), desactívala manualmente con channels.bluebubbles.actions.edit=false.
  • Para información de estado/salud: openclaw status --all o openclaw status --deep.

Para una referencia general del flujo de trabajo de canales, consulta Canales y la guía de Plugins.