Mainstream messaging
iMessage
Estado: integración nativa con una CLI externa. El Gateway inicia imsg rpc y se comunica mediante JSON-RPC por la entrada y salida estándar, sin un demonio ni un puerto independientes. Se recomienda encarecidamente el modo de API privada para disponer de un canal de iMessage completo; las respuestas, reacciones tapback, efectos, encuestas, respuestas a archivos adjuntos y acciones de grupo requieren imsg launch y una comprobación correcta de la API privada.
Para la configuración local habitual, el asistente de configuración de OpenClaw puede ofrecer una instalación o actualización de imsg mediante Homebrew, previa confirmación del usuario, en el Mac con sesión iniciada en Mensajes. La configuración manual y las topologías con wrapper SSH siguen estando administradas por el operador: instale o actualice imsg en el mismo contexto de usuario que ejecutará el Gateway o el wrapper.
Respuestas, reacciones tapback, efectos, encuestas, archivos adjuntos y administración de grupos.
Los mensajes directos de iMessage usan de forma predeterminada el modo de emparejamiento.
Use un wrapper SSH cuando el Gateway no se ejecute en el Mac de Mensajes.
Referencia completa de los campos de iMessage.
Configuración rápida
Mac local (ruta rápida)
Instalar y verificar imsg
brew install steipete/tap/imsgbrew update && brew upgrade imsgimsg rpc --helpimsg launchopenclaw channels status --probeCuando el asistente de configuración local detecta que falta el comando imsg predeterminado, puede solicitar instalar steipete/tap/imsg mediante Homebrew. Si detecta un imsg administrado por Homebrew, puede solicitar reinstalarlo o actualizarlo. Los wrappers personalizados de cliPath no se modifican.
Configurar OpenClaw
{channels: {imessage: {enabled: true,cliPath: "/usr/local/bin/imsg",dbPath: "/Users/user/Library/Messages/chat.db",},},}Iniciar el Gateway
openclaw gatewayAprobar el emparejamiento del primer mensaje directo (dmPolicy predeterminada)
openclaw pairing list imessageopenclaw pairing approve imessage <CODE>Las solicitudes de emparejamiento caducan después de 1 hora.
Mac remoto mediante SSH
La mayoría de las configuraciones no necesitan SSH. Use esta topología únicamente cuando el Gateway no pueda ejecutarse en el Mac con sesión iniciada en Mensajes. OpenClaw solo requiere un cliPath compatible con la entrada y salida estándar, por lo que puede configurar cliPath para que apunte a un script wrapper que se conecte mediante SSH a un Mac remoto y ejecute imsg.
Instale y actualice imsg en ese Mac remoto, no en el host del Gateway:
ssh messages-mac 'brew install steipete/tap/imsg && brew update && brew upgrade imsg'#!/usr/bin/env bashexec ssh -T messages-mac imsg "$@"Configuración recomendada cuando los archivos adjuntos están habilitados:
{channels: {imessage: { enabled: true, cliPath: "~/.openclaw/scripts/imsg-ssh", remoteHost: "user@gateway-host", // se usa para obtener archivos adjuntos mediante SCP includeAttachments: true, // Opcional: raíces adicionales permitidas para archivos adjuntos (combinadas con la predeterminada // /Users/*/Library/Messages/Attachments). attachmentRoots: ["/Users/*/Library/Messages/Attachments"], remoteAttachmentRoots: ["/Users/*/Library/Messages/Attachments"],},},}Si no se establece remoteHost, OpenClaw intenta detectarlo automáticamente analizando el script wrapper SSH.
remoteHost debe tener el formato host o user@host (sin espacios ni opciones SSH); los valores no seguros se ignoran.
OpenClaw usa una comprobación estricta de la clave del host para SCP, por lo que la clave del host de retransmisión ya debe existir en ~/.ssh/known_hosts.
Las rutas de los archivos adjuntos se validan con respecto a las raíces permitidas (attachmentRoots / remoteAttachmentRoots).
Requisitos y permisos (macOS)
- Debe haber una sesión iniciada en Mensajes en el Mac que ejecuta
imsg. - Se requiere acceso total al disco para el contexto del proceso que ejecuta OpenClaw/
imsg(acceso a la base de datos de Mensajes). - Se requiere permiso de automatización para enviar mensajes mediante Messages.app.
- Para las acciones avanzadas (reaccionar / editar / anular envío / respuesta en hilo / efectos / encuestas / operaciones de grupo), debe deshabilitarse la protección de integridad del sistema; consulte Habilitación de la API privada de imsg. El envío y la recepción básicos de texto y contenido multimedia funcionan sin deshabilitarla.
Los envíos mediante el wrapper SSH fallan con AppleEvents -1743
Una configuración con SSH remoto puede leer chats, superar channels status --probe y procesar mensajes entrantes, mientras que los envíos siguen fallando con un error de autorización de AppleEvents:
No autorizado para enviar eventos de Apple a Mensajes. (-1743)Revise la base de datos TCC del usuario con sesión iniciada en el Mac o System Settings > Privacy & Security > Automation. Si la entrada de Automation se registra para /usr/libexec/sshd-keygen-wrapper en lugar del proceso de imsg o del shell local, es posible que macOS no muestre un control utilizable de Mensajes para ese cliente SSH del lado del servidor:
kTCCServiceAppleEvents | /usr/libexec/sshd-keygen-wrapper | auth_value=0 | com.apple.MobileSMSEn ese estado, repetir tccutil reset AppleEvents o volver a ejecutar imsg send mediante el mismo wrapper SSH puede seguir fallando porque el contexto del proceso que necesita la automatización de Mensajes es el wrapper SSH, no una aplicación a la que la interfaz pueda concedérsela.
Use en su lugar uno de los contextos de proceso compatibles con imsg:
- Ejecute el Gateway, o al menos el puente de
imsg, en la sesión local del usuario con sesión iniciada en Mensajes. - Inicie el Gateway con un LaunchAgent para ese usuario después de conceder acceso total al disco y automatización desde la misma sesión.
- Si conserva la topología SSH de dos usuarios, verifique que un envío saliente real mediante
imsg sendse complete correctamente a través del wrapper exacto antes de habilitar el canal. Si no se le puede conceder automatización, reconfigure el sistema para usarimsgcon un solo usuario en lugar de depender del wrapper SSH para los envíos.
Habilitación de la API privada de imsg
imsg incluye dos modos operativos. Para OpenClaw, el modo de API privada es la configuración recomendada porque proporciona al canal las acciones nativas de iMessage que esperan los usuarios. El modo básico sigue siendo útil para instalaciones de bajo riesgo, la verificación inicial o hosts en los que no se puede deshabilitar SIP.
- Modo básico (predeterminado, no requiere cambios en SIP): texto y contenido multimedia salientes mediante
send, supervisión e historial de mensajes entrantes y lista de chats. Esto es lo que se obtiene de inmediato con una instalación nueva mediantebrew install steipete/tap/imsgy los permisos estándar de macOS indicados anteriormente. - Modo de API privada:
imsginyecta una dylib auxiliar enMessages.apppara llamar a funciones internas deIMCore. Esto habilitareact,edit,unsend,reply(en hilo),sendWithEffect,pollypoll-vote(encuestas nativas de Mensajes),renameGroup,setGroupIcon,addParticipant,removeParticipant,leaveGroup, además de indicadores de escritura y confirmaciones de lectura.
La superficie de acciones recomendada en esta página requiere el modo de API privada. El README de imsg indica explícitamente el requisito:
Las funciones avanzadas como
read,typing,launch, el envío enriquecido respaldado por el puente, la modificación de mensajes y la administración de chats son opcionales. Requieren que SIP esté deshabilitado y que se inyecte una dylib auxiliar enMessages.app.imsg launchse niega a realizar la inyección cuando SIP está habilitado.
La técnica de inyección del componente auxiliar usa la propia dylib de imsg para acceder a las API privadas de Mensajes. No hay ningún servidor de terceros ni entorno de ejecución de BlueBubbles en la ruta de iMessage de OpenClaw.
Configuración
-
Instale (o actualice)
imsgen el Mac que ejecuta Messages.app:bash brew install steipete/tap/imsgbrew update && brew upgrade imsgimsg --versionimsg status --jsonLa salida de
imsg status --jsoninforma debridge_version,rpc_methodsy losselectorsde cada método, para que pueda consultar lo que admite la compilación actual antes de comenzar. -
Deshabilite la protección de integridad del sistema y, en versiones modernas de macOS, la validación de bibliotecas. Para inyectar una dylib auxiliar que no sea de Apple en
Messages.app, firmado por Apple, es necesario deshabilitar SIP y relajar la validación de bibliotecas. El paso para deshabilitar SIP en el modo de recuperación depende de la versión de macOS:- macOS 10.13-10.15 (Sierra-Catalina): deshabilite la validación de bibliotecas mediante Terminal, reinicie en el modo de recuperación, ejecute
csrutil disabley vuelva a reiniciar. - macOS 11+ (Big Sur y posteriores), Intel: acceda al modo de recuperación (o recuperación por Internet), ejecute
csrutil disabley reinicie. - macOS 11+, Apple Silicon: use la secuencia de arranque con el botón de encendido para acceder a Recuperación; en versiones recientes de macOS, mantenga pulsada la tecla Left Shift al hacer clic en Continue y, después, ejecute
csrutil disable. Las configuraciones de máquinas virtuales siguen un procedimiento diferente, por lo que debe crear primero una instantánea de la máquina virtual.
En macOS 11 y versiones posteriores,
csrutil disablepor sí solo normalmente no es suficiente. Apple sigue aplicando la validación de bibliotecas aMessages.appcomo binario de plataforma, por lo que se rechaza un auxiliar firmado de forma ad hoc (Library Validation failed: ... platform binary, but mapped file is not) incluso con SIP desactivado. Después de desactivar SIP, desactive también la validación de bibliotecas y reinicie:bash sudo defaults write /Library/Preferences/com.apple.security.libraryvalidation.plist DisableLibraryValidation -bool truemacOS 26 (Tahoe), verificado en 26.5.1: desactivar SIP más el comando
DisableLibraryValidationanterior es suficiente para inyectar el auxiliar desde 26.0 hasta 26.5.x. No se requieren argumentos de arranque. El plist es el factor decisivo y el paso que se omite con mayor frecuencia cuando falla la inyección en Tahoe:- Con el plist:
imsg launchrealiza la inyección yimsg statusinformaadvanced_features: true. - Sin el plist (incluso con SIP desactivado):
imsg launchfalla conFailed to launch: Timeout waiting for Messages.app to initialize. AMFI rechaza el auxiliar ad hoc durante la carga, por lo que el puente nunca queda listo y el inicio agota el tiempo de espera. Ese tiempo de espera agotado es el síntoma más habitual en Tahoe; la solución es el plist anterior, no una medida más drástica.
Si la inyección de
imsg launcho determinadosselectorsempiezan a devolver falso después de una actualización de macOS, esta restricción suele ser la causa. Compruebe el estado de SIP y de la validación de bibliotecas antes de suponer que el propio paso de SIP falló. Si esos ajustes son correctos y el puente sigue sin poder realizar la inyección, recopileimsg status --jsonjunto con la salida deimsg launche informe al proyectoimsgen lugar de debilitar controles de seguridad adicionales de todo el sistema. - macOS 10.13-10.15 (Sierra-Catalina): deshabilite la validación de bibliotecas mediante Terminal, reinicie en el modo de recuperación, ejecute
-
Inyecte el auxiliar. Con SIP desactivado y la sesión iniciada en Messages.app:
bash imsg launchimsg launchse niega a realizar la inyección si SIP sigue activado, por lo que esto también sirve para confirmar que el paso 2 se aplicó. -
Verifique el puente desde OpenClaw:
bash openclaw channels status --probeLa entrada de iMessage debería informar
works, yimsg status --json | jq '{rpc_methods, selectors}'debería mostrar las capacidades expuestas por su compilación de macOS. La creación de encuestas requiereselectors.pollPayloadMessage; la votación requiere tantoselectors.pollVoteMessagecomo el método RPCpoll.vote. El Plugin de OpenClaw anuncia únicamente las acciones compatibles con la comprobación almacenada en caché, mientras que una caché vacía mantiene una postura optimista y realiza la comprobación en el primer envío.
Si openclaw channels status --probe informa que el canal works, pero determinadas acciones generan "iMessage <action> requires the imsg private API bridge" al enviarse, ejecute imsg launch de nuevo: el auxiliar puede desconectarse (por un reinicio de Messages.app, una actualización del sistema operativo, etc.) y el estado available: true almacenado en caché seguirá anunciando acciones hasta que la siguiente comprobación lo actualice.
Cuando SIP permanece activado
Si desactivar SIP no es aceptable para su modelo de amenazas:
imsgrecurre al modo básico: solo texto, contenido multimedia y recepción.- El Plugin de OpenClaw sigue anunciando el envío de texto/contenido multimedia y la supervisión de mensajes entrantes; oculta
react,edit,unsend,reply,sendWithEffecty las operaciones de grupo de la superficie de acciones (según la restricción de capacidades de cada método). - Puede ejecutar un Mac independiente que no use Apple Silicon (o un Mac dedicado al bot) con SIP desactivado para la carga de trabajo de iMessage, mientras mantiene SIP activado en sus dispositivos principales. Consulte Usuario de macOS dedicado al bot (identidad de iMessage independiente) más adelante.
Control de acceso y enrutamiento
Política de mensajes directos
channels.imessage.dmPolicy controla los mensajes directos:
pairing(valor predeterminado)allowlist(requiere al menos una entrada enallowFrom)open(requiere queallowFromincluya"*")disabled
Campo de lista de permitidos: channels.imessage.allowFrom.
Las entradas de la lista de permitidos deben identificar a los remitentes: identificadores o grupos estáticos de acceso de remitentes (accessGroup:<name>). Use channels.imessage.groupAllowFrom para destinos de chat como chat_id:*, chat_guid:* o chat_identifier:*; use channels.imessage.groups para claves numéricas chat_id del registro.
Política de grupos y menciones
channels.imessage.groupPolicy controla el procesamiento de grupos:
allowlist(valor predeterminado)opendisabled
Lista de remitentes de grupo permitidos: channels.imessage.groupAllowFrom.
Las entradas de groupAllowFrom también pueden hacer referencia a grupos estáticos de acceso de remitentes (accessGroup:<name>).
Alternativa en tiempo de ejecución: si groupAllowFrom no está definido, las comprobaciones de remitentes de grupos de iMessage usan allowFrom; defina groupAllowFrom cuando la admisión de mensajes directos y grupos deba ser distinta. Un valor groupAllowFrom: [] explícitamente vacío no recurre a la alternativa: bloquea a todos los remitentes de grupos bajo allowlist.
Nota sobre el tiempo de ejecución: si falta por completo channels.imessage, el tiempo de ejecución recurre a groupPolicy="allowlist" y registra una advertencia (incluso si se ha definido channels.defaults.groupPolicy).
Restricción por menciones para grupos:
- iMessage no dispone de metadatos nativos de menciones
- la detección de menciones usa patrones de expresiones regulares (
agents.list[].groupChat.mentionPatterns, con alternativa enmessages.groupChat.mentionPatterns) - sin patrones configurados, no se puede aplicar la restricción por menciones
- los comandos de control de remitentes autorizados omiten la restricción por menciones
systemPrompt por grupo:
Cada entrada bajo channels.imessage.groups.* acepta una cadena systemPrompt opcional, que se inyecta en el prompt del sistema del agente en cada turno que procesa un mensaje de ese grupo. La resolución refleja la de channels.whatsapp.groups:
- Prompt del sistema específico del grupo (
groups["<chat_id>"].systemPrompt): se usa cuando la entrada específica del grupo existe en el mapa y su clavesystemPromptestá definida. SisystemPromptes una cadena vacía (""), se suprime el comodín y no se aplica ningún prompt del sistema a ese grupo. - Prompt del sistema comodín para grupos (
groups["*"].systemPrompt): se usa cuando la entrada específica del grupo está completamente ausente del mapa o cuando existe, pero no define ninguna clavesystemPrompt.
{ channels: { imessage: { groupPolicy: "allowlist", groupAllowFrom: ["+15555550123"], groups: { "*": { systemPrompt: "Usa la ortografía británica." }, "8421": { requireMention: true, systemPrompt: "Este es el chat del turno de guardia. Limita las respuestas a menos de 3 frases.", }, "9907": { // supresión explícita: el comodín "Usa la ortografía británica." no se aplica aquí systemPrompt: "", }, }, }, },}Los prompts por grupo solo se aplican a los mensajes de grupo; los mensajes directos no se ven afectados.
Sesiones y respuestas deterministas
- Los mensajes directos usan enrutamiento directo; los grupos usan enrutamiento de grupos.
- Con el valor predeterminado
session.dmScope=main, los mensajes directos de iMessage se agrupan en la sesión principal del agente. - Las sesiones de grupo están aisladas (
agent:<agentId>:imessage:group:<chat_id>). - Las respuestas se devuelven a iMessage mediante los metadatos del canal y destino de origen.
Comportamiento de hilos similares a grupos:
Algunos hilos de iMessage con varios participantes pueden llegar con is_group=false.
Si ese chat_id está configurado explícitamente bajo channels.imessage.groups, OpenClaw lo trata como tráfico de grupo (restricciones de grupo y aislamiento de la sesión de grupo).
Vinculaciones de conversaciones ACP
Los chats de iMessage se pueden vincular a sesiones ACP.
Flujo rápido para operadores:
- Ejecute
/acp spawn codex --bind heredentro del mensaje directo o del chat de grupo permitido. - Los mensajes futuros de esa misma conversación de iMessage se enrutan a la sesión ACP creada.
/newy/resetrestablecen en el mismo lugar la sesión ACP vinculada./acp closecierra la sesión ACP y elimina la vinculación.
Las vinculaciones persistentes configuradas usan entradas bindings[] de nivel superior con type: "acp" y match.channel: "imessage".
match.peer.id puede usar:
- un identificador normalizado de mensaje directo, como
+15555550123ouser@example.com chat_id:<id>(recomendado para vinculaciones de grupo estables)chat_guid:<guid>chat_identifier:<identifier>
Ejemplo:
{ agents: { list: [ { id: "codex", runtime: { type: "acp", acp: { agent: "codex", backend: "acpx", mode: "persistent" }, }, }, ], }, bindings: [ { type: "acp", agentId: "codex", match: { channel: "imessage", accountId: "default", peer: { kind: "group", id: "chat_id:123" }, }, acp: { label: "codex-group" }, }, ],}Consulte Agentes ACP para conocer el comportamiento compartido de las vinculaciones ACP.
Patrones de despliegue
Usuario de macOS dedicado al bot (identidad de iMessage independiente)
Use un Apple ID y un usuario de macOS dedicados para que el tráfico del bot permanezca aislado de su perfil personal de Messages.
Flujo habitual:
- Cree o inicie sesión en un usuario de macOS dedicado.
- Inicie sesión en Messages con el Apple ID del bot en ese usuario.
- Instale
imsgen ese usuario. - Cree un contenedor SSH para que OpenClaw pueda ejecutar
imsgen el contexto de ese usuario. - Dirija
channels.imessage.accounts.<id>.cliPathy.dbPathal perfil de ese usuario.
La primera ejecución puede requerir aprobaciones en la interfaz gráfica (Automatización y acceso total al disco) en la sesión de ese usuario del bot.
Mac remoto mediante Tailscale (ejemplo)
Topología habitual:
- el Gateway se ejecuta en Linux o una máquina virtual
- iMessage y
imsgse ejecutan en un Mac de su red de Tailscale - el contenedor
cliPathusa SSH para ejecutarimsg remoteHosthabilita la obtención de archivos adjuntos mediante SCP
Ejemplo:
{ channels: { imessage: { enabled: true, cliPath: "~/.openclaw/scripts/imsg-ssh", remoteHost: "bot@mac-mini.tailnet-1234.ts.net", includeAttachments: true, dbPath: "/Users/bot/Library/Messages/chat.db", }, },}#!/usr/bin/env bashexec ssh -T bot@mac-mini.tailnet-1234.ts.net imsg "$@"Use claves SSH para que tanto SSH como SCP sean no interactivos.
Asegúrese primero de que la clave del host sea de confianza (por ejemplo, ssh bot@mac-mini.tailnet-1234.ts.net) para que se rellene known_hosts.
Patrón de varias cuentas
iMessage admite configuración por cuenta en channels.imessage.accounts.
Cada cuenta puede sobrescribir campos como cliPath, dbPath, allowFrom, groupPolicy, mediaMaxMb, la configuración del historial y las listas de raíces permitidas para archivos adjuntos.
Historial de mensajes directos
Establezca channels.imessage.dmHistoryLimit para inicializar las nuevas sesiones de mensajes directos con el historial reciente de imsg decodificado para esa conversación. Use channels.imessage.dms["<sender>"].historyLimit para sobrescribirlo por remitente, incluido 0 para desactivar el historial de un remitente.
El historial de mensajes directos de iMessage se obtiene bajo demanda desde imsg. Si no se establece dmHistoryLimit, se desactiva la inicialización global del historial de mensajes directos, pero un valor positivo de channels.imessage.dms["<sender>"].historyLimit sigue activando la inicialización para ese remitente.
Contenido multimedia, fragmentación y destinos de entrega
Archivos adjuntos y contenido multimedia
- la ingesta de archivos adjuntos entrantes está desactivada de forma predeterminada — establezca
channels.imessage.includeAttachments: truepara reenviar fotos, notas de voz, vídeos y otros archivos adjuntos al agente. Si está desactivada, los iMessages que solo contienen archivos adjuntos se descartan antes de llegar al agente y es posible que no generen ninguna línea de registroInbound message. - las rutas remotas de archivos adjuntos se pueden obtener mediante SCP cuando se establece
remoteHost - las rutas de archivos adjuntos deben coincidir con las raíces permitidas:
channels.imessage.attachmentRoots(local)channels.imessage.remoteAttachmentRoots(modo SCP remoto)- las raíces configuradas amplían el patrón de raíz predeterminado
/Users/*/Library/Messages/Attachments(se combinan, no se reemplazan)
- SCP usa una comprobación estricta de la clave del host (
StrictHostKeyChecking=yes) - el tamaño del contenido multimedia saliente usa
channels.imessage.mediaMaxMb(valor predeterminado: 16 MB)
Texto saliente y fragmentación
- límite de fragmentos de texto:
channels.imessage.textChunkLimit(valor predeterminado: 4000) - modo de fragmentación:
channels.imessage.streaming.chunkModelength(valor predeterminado)newline(división prioritaria por párrafos)
- la negrita, cursiva, subrayado y tachado de Markdown saliente se convierten en texto con estilo nativo (los destinatarios con macOS 15+ muestran el formato; los destinatarios con versiones anteriores ven texto sin formato y sin los marcadores); las tablas de Markdown se convierten según el modo de tablas Markdown del canal
channels.imessage.sendTransport(autode forma predeterminada,bridge,applescript) selecciona cómoimsgrealiza los envíos
Formatos de direccionamiento
Destinos explícitos preferidos:
chat_id:123(recomendado para un enrutamiento estable)chat_guid:...chat_identifier:...
También se admiten destinos de identificador:
imessage:+1555...sms:+1555...user@example.com
imsg chats --limit 20Acciones de la API privada
Cuando imsg launch está en ejecución y openclaw channels status --probe informa de privateApi.available: true, la herramienta de mensajes puede usar acciones nativas de iMessage además de los envíos de texto normales.
Todas las acciones están activadas de forma predeterminada; use channels.imessage.actions para desactivar acciones individuales:
{ channels: { imessage: { actions: { reactions: true, edit: true, unsend: true, reply: true, sendWithEffect: true, sendAttachment: true, renameGroup: true, setGroupIcon: true, addParticipant: true, removeParticipant: true, leaveGroup: true, polls: true, }, }, },}Acciones disponibles
- react: Añade o elimina reacciones de iMessage (
messageId,emoji,remove). Las reacciones admitidas corresponden a amor, me gusta, no me gusta, risa, énfasis y pregunta. Al eliminar sin un emoji, se borra la reacción que estuviera establecida. - reply: Envía una respuesta en un hilo a un mensaje existente (
messageId,textomessage, además dechatGuid,chatId,chatIdentifieroto). La respuesta con un archivo adjunto requiere además una compilación deimsgcuyosend-richadmita--file. - sendWithEffect: Envía texto con un efecto de iMessage (
textomessage,effectoeffectId). Nombres cortos: slam, loud, gentle, invisibleink, confetti, lasers, fireworks, balloon, heart, echo, happybirthday, shootingstar, sparkles, spotlight. - edit: Edita un mensaje enviado en versiones compatibles de macOS o de la API privada (
messageId,textonewText). Solo se pueden editar los mensajes enviados por el propio Gateway. - unsend: Retira un mensaje enviado en versiones compatibles de macOS o de la API privada (
messageId). Solo se pueden retirar los mensajes enviados por el propio Gateway. - upload-file: Envía contenido multimedia o archivos (
buffercomo base64 o un valor preparado demedia/path/filePath,filenamey, opcionalmente,asVoice). Alias heredado:sendAttachment. - renameGroup, setGroupIcon, addParticipant, removeParticipant, leaveGroup: Gestionan chats de grupo cuando el destino actual es una conversación grupal. Estas acciones modifican la identidad de Messages del host, por lo que requieren un remitente propietario o un cliente del Gateway con
operator.admin. - poll: Crea una encuesta nativa de Apple Messages (
pollQuestion,pollOptionrepetido de 2 a 12 veces, además dechatGuid,chatId,chatIdentifieroto). Los destinatarios con iOS/iPadOS/macOS 26+ pueden verla y votar de forma nativa; las versiones anteriores del sistema operativo reciben como alternativa el texto "Se envió una encuesta". Requiereselectors.pollPayloadMessage. - poll-vote: Vota en una encuesta existente (
pollIdomessageId, además de exactamente uno depollOptionIndex,pollOptionIdopollOptionText). Requiereselectors.pollVoteMessagey el método RPCpoll.vote.
Las encuestas entrantes aceptadas se muestran al agente con la pregunta, las etiquetas numeradas de las opciones, los recuentos de votos y el ID del mensaje de la encuesta que necesita poll-vote.
ID de mensajes
El contexto de iMessage entrante incluye tanto valores cortos de MessageSid como GUID completos de mensajes (MessageSidFull) cuando están disponibles. Los ID cortos se limitan a la caché reciente de respuestas respaldada por SQLite y se comprueban con respecto al chat actual antes de usarse. Si un ID corto ha caducado o pertenece a otro chat, vuelva a intentarlo con el valor completo de MessageSidFull.
Detección de capacidades
OpenClaw oculta las acciones de la API privada solo cuando el estado de sondeo almacenado en caché indica que el puente no está disponible. Si el estado es desconocido, las acciones permanecen visibles y ejecutan sondeos de forma diferida, de modo que la primera acción pueda realizarse correctamente después de imsg launch sin una actualización manual independiente del estado.
Confirmaciones de lectura e indicador de escritura
Cuando el puente de la API privada está activo, los chats entrantes aceptados se marcan como leídos y los chats directos muestran una burbuja de escritura en cuanto se acepta el turno, mientras el agente prepara el contexto y genera la respuesta. Para desactivar el marcado como leído:
{ channels: { imessage: { sendReadReceipts: false, }, },}Las versiones anteriores de imsg, previas a la lista de capacidades por método, desactivan silenciosamente el indicador de escritura y las confirmaciones de lectura; OpenClaw registra una advertencia una sola vez por reinicio para que pueda atribuirse la ausencia de la confirmación.
Tapbacks entrantes
OpenClaw se suscribe a los tapbacks de iMessage y enruta las reacciones aceptadas como eventos del sistema en lugar de texto de mensaje normal, por lo que el tapback de un usuario no activa un bucle de respuesta normal.
El modo de notificación se controla mediante channels.imessage.reactionNotifications:
"own"(predeterminado): notifica solo cuando los usuarios reaccionan a mensajes escritos por el bot."all": notifica todos los tapbacks entrantes de remitentes autorizados."off": ignora los tapbacks entrantes.
Las anulaciones por cuenta utilizan channels.imessage.accounts.<id>.reactionNotifications.
Reacciones de aprobación (👍 / 👎)
Cuando approvals.exec.enabled o approvals.plugin.enabled es verdadero y la solicitud se enruta a iMessage, el Gateway entrega una solicitud de aprobación de forma nativa y acepta un tapback para resolverla:
👍(tapback de Me gusta) →allow-once👎(tapback de No me gusta) →denyallow-alwayssigue siendo una alternativa manual: envíe/approve <id> allow-alwayscomo respuesta normal.
La gestión de reacciones requiere que el identificador del usuario que reacciona esté incluido explícitamente como aprobador. La lista de aprobadores se lee de channels.imessage.allowFrom (o channels.imessage.accounts.<id>.allowFrom); añada el número de teléfono del usuario en formato E.164 o el correo electrónico de su Apple ID (los destinos de chat como chat_id:* no son entradas de aprobador válidas). Se admite la entrada comodín "*", pero permite que cualquier remitente apruebe; una lista de aprobadores vacía deshabilita por completo el atajo de reacciones. El atajo de reacciones omite intencionadamente reactionNotifications, dmPolicy y groupAllowFrom, porque la lista de permitidos de aprobadores explícitos es el único control relevante para resolver la aprobación.
La autorización del comando de texto /approve utiliza la misma lista: cuando channels.imessage.allowFrom no está vacío, /approve <id> <decision> se autoriza según esa lista de aprobadores (no según la lista de permitidos más amplia de mensajes directos), y los remitentes permitidos en la lista de mensajes directos pero no incluidos en allowFrom reciben una denegación explícita. Cuando allowFrom está vacío, se mantiene la alternativa del mismo chat y /approve autoriza a cualquier persona permitida por la lista de mensajes directos. Añada a allowFrom todos los operadores que deban aprobar, ya sea mediante /approve o mediante reacciones.
Notas para operadores:
- La vinculación de la reacción se almacena tanto en memoria como en el almacén persistente con claves del Gateway (con un TTL que coincide con el vencimiento de la aprobación), y el Gateway también consulta periódicamente las solicitudes pendientes en busca de tapbacks, por lo que un tapback que llegue poco después de reiniciar el Gateway seguirá resolviendo la aprobación.
- El tapback del propio operador con
is_from_me=true(por ejemplo, desde un dispositivo Apple enlazado) resuelve la aprobación cuando ese identificador es un aprobador explícito. - Las solicitudes de aprobación solo se dirigen a una conversación grupal cuando hay aprobadores explícitos configurados; de lo contrario, cualquier miembro del grupo podría aprobar.
- Los tapbacks heredados en formato de texto (
Liked "…"como texto sin formato de clientes Apple muy antiguos) no pueden resolver aprobaciones porque no incluyen ningún GUID de mensaje; la resolución mediante reacciones requiere los metadatos estructurados de tapback que emiten los clientes actuales de macOS/iOS.
Escrituras de configuración
iMessage permite de forma predeterminada las escrituras de configuración iniciadas por el canal (para /config set|unset cuando commands.config: true).
Para deshabilitarlas:
{ channels: { imessage: { configWrites: false, }, },}Agrupación de mensajes directos divididos (comando + URL en una sola composición)
Cuando un usuario escribe juntos un comando y una URL —por ejemplo, Dump https://example.com/article—, la aplicación Mensajes de Apple divide el envío en dos filas independientes de chat.db:
- Un mensaje de texto (
"Dump"). - Un globo de vista previa de URL (
"https://...") con imágenes de vista previa de OG como archivos adjuntos.
Las dos filas llegan a OpenClaw con una separación de ~0.8-2.0 s en la mayoría de las configuraciones. Sin la agrupación, el agente recibe únicamente el comando en el turno 1 (y a menudo responde «envíeme la URL») antes de que la URL llegue en el turno 2. Esto se debe al proceso de envío de Apple, no a nada que introduzcan OpenClaw o imsg.
channels.imessage.coalesceSameSenderDms permite que un MD almacene en búfer filas consecutivas del mismo remitente. Cuando imsg expone el marcador estructural de vista previa de URL balloon_bundle_id: "com.apple.messages.URLBalloonProvider" en una de las filas de origen, OpenClaw combina únicamente ese envío dividido real y mantiene las demás filas almacenadas en búfer como turnos separados. En versiones anteriores de imsg que no emiten ningún metadato de globo, OpenClaw no puede distinguir un envío dividido de varios envíos separados, por lo que recurre a combinar el conjunto. Esto conserva el comportamiento anterior a los metadatos, en lugar de hacer que los envíos divididos Dump <url> vuelvan a convertirse en dos turnos. Los chats grupales siguen procesando cada mensaje por separado para preservar la estructura de turnos de varios usuarios.
Cuándo habilitarlo
Habilítelo cuando:
- Distribuya Skills que esperan
command + payloaden un solo mensaje (volcar, pegar, guardar, poner en cola, etc.). - Los usuarios peguen URL junto con comandos.
- Pueda aceptar la latencia adicional de los turnos de MD (consulte más abajo).
Déjelo deshabilitado cuando:
- Necesite la latencia mínima de los comandos para activadores de MD de una sola palabra.
- Todos los flujos sean comandos de una sola ejecución sin cargas útiles posteriores.
Habilitación
{ channels: { imessage: { coalesceSameSenderDms: true, // habilitación voluntaria (valor predeterminado: false) }, },}Con la opción activada y sin un valor explícito de messages.inbound.byChannel.imessage ni un valor global de messages.inbound.debounceMs, la ventana de antirrebote se amplía a 7000 ms (el valor predeterminado heredado es 0 ms: sin antirrebote). La ventana más amplia es necesaria porque la cadencia de los envíos divididos de vistas previas de URL de Apple puede prolongarse varios segundos mientras Messages.app emite la fila de vista previa.
Para ajustar personalmente la ventana:
{ messages: { inbound: { byChannel: { // 7000 ms cubren los retrasos observados en las vistas previas de URL de Messages.app. imessage: 7000, }, }, },}Consideraciones
- La combinación precisa requiere metadatos actuales en la carga útil de
imsg. Cuandoballoon_bundle_idestá presente, solo se combina el envío dividido real; la combinación de respaldo sin metadatos descrita anteriormente es una medida provisional de compatibilidad con versiones anteriores que se eliminará cuandoimsgcombine los envíos divididos en el origen. - Latencia adicional para los mensajes de MD. Con la opción activada, cada MD (incluidos los comandos de control independientes y los mensajes posteriores de un solo texto) espera hasta que finalice la ventana de antirrebote antes de procesarse, por si llega una fila de vista previa de URL. Los mensajes de chats grupales siguen procesándose al instante.
- La salida combinada tiene límites. El texto combinado se limita a 4000 caracteres e incluye un marcador explícito
…[truncated]; los archivos adjuntos se limitan a 20; las entradas de origen se limitan a 10 (si se supera este límite, se conservan la primera y las más recientes). Cada GUID de origen se registra encoalescedMessageGuidspara la telemetría posterior. - Solo para MD. Los chats grupales pasan al procesamiento por mensaje para que el bot mantenga su capacidad de respuesta cuando varias personas están escribiendo.
- Habilitación voluntaria y por canal. Los demás canales (Discord, Slack, Telegram, WhatsApp, …) no se ven afectados. Las configuraciones heredadas de BlueBubbles que establezcan
channels.bluebubbles.coalesceSameSenderDmsdeben migrar ese valor achannels.imessage.coalesceSameSenderDms.
Situaciones y lo que ve el agente
La columna «Opción activada» muestra el comportamiento en una versión de imsg que emite balloon_bundle_id. En versiones anteriores de imsg que no emiten ningún metadato de globo, las filas indicadas a continuación como «Dos turnos»/«N turnos» recurren en su lugar a una combinación heredada (un turno): OpenClaw no puede distinguir estructuralmente un envío dividido de varios envíos separados, por lo que conserva la combinación anterior a los metadatos. La separación precisa se activa cuando la versión comienza a emitir metadatos de globo.
| El usuario redacta | chat.db produce |
Opción desactivada (predeterminado) | Opción activada + ventana (imsg emite metadatos de globo) |
|---|---|---|---|
Dump https://example.com (un envío) |
2 filas separadas por ~1 s | Dos turnos del agente: «Dump» solo y luego la URL | Un turno: texto combinado Dump https://example.com |
Save this 📎image.jpg caption (archivo adjunto + texto) |
2 filas sin metadatos de globo de URL | Dos turnos | Dos turnos tras observar metadatos; un turno combinado en sesiones antiguas/previas a la detección sin metadatos |
/status (comando independiente) |
1 fila | Procesamiento instantáneo | Espera hasta que finalice la ventana y luego se procesa |
| URL pegada por sí sola | 1 fila | Procesamiento instantáneo | Espera hasta que finalice la ventana y luego se procesa |
| Texto + URL enviados como dos mensajes separados deliberadamente, con minutos de diferencia | 2 filas fuera de la ventana | Dos turnos | Dos turnos (la ventana expira entre ambos) |
| Ráfaga rápida (>10 MD pequeños dentro de la ventana) | N filas sin metadatos de globo de URL | N turnos | N turnos tras observar metadatos; un turno combinado y limitado en sesiones antiguas/previas a la detección sin metadatos |
| Dos personas escribiendo en un chat grupal | N filas de M remitentes | M+ turnos (uno por conjunto de remitente) | M+ turnos: los chats grupales no se combinan |
Recuperación de mensajes entrantes tras reiniciar un puente o el Gateway
iMessage recupera los mensajes perdidos mientras el Gateway estaba inactivo y, al mismo tiempo, suprime la «bomba de mensajes pendientes» obsoletos que Apple puede descargar después de una recuperación de Push. El comportamiento predeterminado está siempre activado y se basa en la deduplicación de mensajes entrantes.
- Deduplicación de reproducción. Cada mensaje entrante procesado se registra mediante su GUID de Apple en el estado persistente del Plugin (
imessage.inbound-dedupe), se reclama durante la ingesta y se confirma después de gestionarlo (se libera tras un fallo transitorio para permitir un nuevo intento). Todo lo que ya se haya gestionado se descarta en lugar de procesarse dos veces. Esto permite que la recuperación reproduzca de forma intensiva sin llevar un registro individual de cada mensaje. - Recuperación del tiempo de inactividad. Al iniciarse, el monitor recuerda el último rowid procesado de
chat.db(un cursor persistente por cuenta) y se lo pasa aimsg watch.subscribecomosince_rowid, por lo que imsg reproduce las filas que llegaron mientras el Gateway estaba inactivo y después continúa siguiendo la actividad en tiempo real. La reproducción se limita a las 500 filas más recientes y a mensajes de hasta ~2 horas de antigüedad, y la deduplicación descarta todo lo que ya se haya gestionado. - Límite de antigüedad para mensajes pendientes obsoletos. Las filas posteriores al límite de inicio son realmente nuevas; si la fecha de envío de una fila es más de ~15 minutos anterior a su llegada, se considera parte de los mensajes pendientes descargados por Push y se suprime. Las filas reproducidas (en el límite o antes de él) utilizan en su lugar la ventana de recuperación más amplia, por lo que se entrega un mensaje perdido recientemente, pero no el historial antiguo.
La recuperación funciona tanto con configuraciones de cliPath locales como remotas, porque la reproducción mediante since_rowid se ejecuta a través de la misma conexión RPC de imsg. La diferencia es la ventana: cuando el Gateway puede leer chat.db (local), fija el límite de rowid de inicio, restringe el intervalo de reproducción y entrega mensajes perdidos de hasta un par de horas de antigüedad. Con un cliPath de SSH remoto no puede leer la base de datos, por lo que la reproducción no tiene límite y cada fila utiliza el límite de antigüedad en tiempo real: sigue recuperando los mensajes perdidos recientemente y suprimiendo los mensajes pendientes antiguos, pero con la ventana en tiempo real más estrecha. Ejecute el Gateway en el Mac con Messages para disponer de la ventana de recuperación más amplia.
Señal visible para el operador
Los mensajes pendientes suprimidos se registran en el nivel predeterminado y nunca se descartan silenciosamente (la marca recovery indica qué ventana se aplicó):
imessage: se suprimieron mensajes entrantes pendientes obsoletos account=<id> sent=<iso> recovery=<bool> (<N> suprimidos desde el inicio)Migración
channels.imessage.catchup.* está obsoleto: la recuperación del tiempo de inactividad es automática y no requiere configuración en las instalaciones nuevas. Las configuraciones existentes con catchup.enabled: true siguen respetándose como perfil de compatibilidad para la ventana de reproducción de recuperación. Los bloques de recuperación deshabilitados (enabled: false o sin enabled: true) se retiran; openclaw doctor --fix los elimina.
Solución de problemas
No se encuentra imsg o RPC no es compatible
Valide el binario y la compatibilidad con RPC:
imsg rpc --helpimsg status --jsonopenclaw channels status --probeSi la comprobación indica que RPC no es compatible, actualice imsg. Si las acciones de la API privada no están disponibles, ejecute imsg launch en la sesión del usuario de macOS que haya iniciado sesión y vuelva a realizar la comprobación. Si el Gateway no se ejecuta en macOS, utilice la configuración de Mac remoto mediante SSH descrita anteriormente en lugar de la ruta local predeterminada de imsg.
Los mensajes se envían, pero los iMessages entrantes no llegan
Primero, compruebe si el mensaje llegó al Mac local. Si chat.db no cambia, OpenClaw no puede recibir el mensaje aunque imsg status --json indique que el puente funciona correctamente.
imsg chats --limit 10 --jsonimsg watch --chat-id <chat-id> --jsonsqlite3 ~/Library/Messages/chat.db \"select datetime(max(date)/1000000000 + 978307200, 'unixepoch', 'localtime'), max(ROWID) from message;"Si los mensajes enviados desde el teléfono no crean filas nuevas, repare la capa de Messages y Apple Push de macOS antes de cambiar la configuración de OpenClaw. Suele bastar con actualizar los servicios una vez:
launchctl kickstart -k system/com.apple.apsdlaunchctl kickstart -k gui/$(id -u)/com.apple.CommCenterlaunchctl kickstart -k gui/$(id -u)/com.apple.identityservicesdlaunchctl kickstart -k gui/$(id -u)/com.apple.imagentimsg launchopenclaw gateway restartEnvíe un iMessage nuevo desde el teléfono y confirme que haya una fila nueva en chat.db o un evento de imsg watch antes de depurar las sesiones de OpenClaw. No ejecute este procedimiento como un bucle periódico de reinicio del puente; ejecutar repetidamente imsg launch y reiniciar el Gateway durante el trabajo activo puede interrumpir las entregas y dejar bloqueadas las ejecuciones del canal en curso.
El Gateway no se ejecuta en macOS
El valor predeterminado cliPath: "imsg" debe ejecutarse en el Mac que tenga una sesión iniciada en Messages. En Linux o Windows, establezca channels.imessage.cliPath en un script contenedor que se conecte por SSH a ese Mac y ejecute imsg "$@".
#!/usr/bin/env bashexec ssh -T messages-mac imsg "$@"A continuación, ejecute:
openclaw channels status --probe --channel imessageLos MD se ignoran
Compruebe:
channels.imessage.dmPolicychannels.imessage.allowFrom- aprobaciones de emparejamiento (
openclaw pairing list imessage)
Los mensajes grupales se ignoran
Compruebe:
channels.imessage.groupPolicychannels.imessage.groupAllowFrom- el comportamiento de la lista de permitidos de
channels.imessage.groups - la configuración de patrones de mención (
agents.list[].groupChat.mentionPatterns)
Los archivos adjuntos remotos fallan
Compruebe:
channels.imessage.remoteHostchannels.imessage.remoteAttachmentRoots- la autenticación con clave SSH/SCP desde el host del Gateway
- que la clave del host exista en
~/.ssh/known_hostsen el host del Gateway - la legibilidad de las rutas remotas en el Mac que ejecuta Messages
No se atendieron las solicitudes de permisos de macOS
Vuelva a ejecutar los comandos en un terminal gráfico interactivo con el mismo contexto de usuario y sesión, y apruebe las solicitudes:
imsg chats --limit 1imsg send <handle> "test"Confirme que se hayan concedido Acceso total al disco y Automatización al contexto del proceso que ejecuta OpenClaw/imsg.
Referencias de configuración
Temas relacionados
- Descripción general de los canales — todos los canales compatibles
- Eliminación de BlueBubbles y la ruta de iMessage mediante imsg — anuncio y resumen de la migración
- Migración desde BlueBubbles — tabla de equivalencias de configuración y transición paso a paso
- Vinculación — autenticación de mensajes directos y flujo de vinculación
- Grupos — comportamiento de los chats grupales y control mediante menciones
- Enrutamiento de canales — enrutamiento de sesiones para mensajes
- Seguridad — modelo de acceso y protección reforzada