Ir al contenido

iMessage

Estado: integración nativa de CLI externa. Gateway inicia imsg rpc y se comunica a través de JSON-RPC en stdio (sin demonio/puerto separado). Las acciones avanzadas requieren imsg launch y un sondeo exitoso de la API privada.

Acciones de API privada

Respuestas, tapbacks, efectos, archivos adjuntos y gestión de grupos.

Emparejamiento

Los MD de iMessage están en modo de emparejamiento de forma predeterminada.

Mac remoto

Use un envoltorio SSH cuando el Gateway no se esté ejecutando en el Mac de Messages.

Referencia de configuración

Referencia completa de campos de iMessage.

  1. Instalar y verificar imsg

    Ventana de terminal
    brew install steipete/tap/imsg
    imsg rpc --help
    imsg launch
    openclaw channels status --probe
  2. Configurar OpenClaw

    {
    channels: {
    imessage: {
    enabled: true,
    cliPath: "/usr/local/bin/imsg",
    dbPath: "/Users/user/Library/Messages/chat.db",
    },
    },
    }
  3. Iniciar la pasarela

    Ventana de terminal
    openclaw gateway
  4. Aprobar el primer emparejamiento DM (dmPolicy predeterminado)

    Ventana de terminal
    openclaw pairing list imessage
    openclaw pairing approve imessage
    Las solicitudes de emparejamiento caducan después de 1 hora.
  • Se debe iniciar sesión en Messages en el Mac donde se ejecuta imsg.
  • Se requiere acceso completo al disco para el contexto del proceso que ejecuta OpenClaw/imsg (acceso a la base de datos de Messages).
  • Se requiere permiso de automatización para enviar mensajes a través de Messages.app.
  • Para acciones avanzadas (reaccionar / editar / desenviar / respuesta en hilo / efectos / operaciones de grupo), se debe desactivar la Protección de Integridad del Sistema; consulte Habilitar la API privada imsg a continuación. El envío y recepción básico de texto y medios funcionan sin ella.

imsg se envía en dos modos operativos:

  • Modo básico (predeterminado, no se requieren cambios de SIP): texto y medios salientes a través de send, visualización/historial entrante, lista de chats. Esto es lo que obtiene de inmediato con una instalación nueva de brew install steipete/tap/imsg más los permisos estándar de macOS mencionados anteriormente.
  • Modo de API privada: imsg inyecta una dylib auxiliar en Messages.app para llamar a funciones internas de IMCore. Esto es lo que desbloquea react, edit, unsend, reply (en hilo), sendWithEffect, renameGroup, setGroupIcon, addParticipant, removeParticipant, leaveGroup, además de indicadores de escritura y confirmaciones de lectura.

Para alcanzar la superficie de acción avanzada que documenta esta página del canal, necesita el modo de API privada. El README de imsg es explícito sobre el requisito:

Las funciones avanzadas como read, typing, launch, envío enriquecido con puente, mutación de mensajes y gestión de chats son opcionales. Requieren que SIP esté desactivado y que se inyecte una dylib auxiliar en Messages.app. imsg launch se niega a inyectar cuando SIP está activado.

La técnica de inyección auxiliar utiliza la propia dylib de imsg para acceder a las API privadas de Messages. No hay servidor de terceros ni tiempo de ejecución de BlueBubbles en la ruta iMessage de OpenClaw.

  1. Instale (o actualice) imsg en el Mac que ejecuta Messages.app:

    Ventana de terminal
    brew install steipete/tap/imsg
    imsg --version
    imsg status --json

    La salida de imsg status --json informa sobre bridge_version, rpc_methods y selectors por método, para que puedas ver qué es compatible con la compilación actual antes de comenzar.

  2. Deshabilita la Protección de Integridad del Sistema. Esto es específico de la versión de macOS porque el requisito subyacente de Apple depende del sistema operativo y el hardware:

    • macOS 10.13–10.15 (Sierra–Catalina): desactiva la validación de bibliotecas (Library Validation) mediante la Terminal, reinicia en modo de recuperación, ejecuta csrutil disable, reinicia.
    • macOS 11+ (Big Sur y posteriores), Intel: Modo de recuperación (o recuperación por internet), csrutil disable, reinicia.
    • macOS 11+, Apple Silicon: secuencia de inicio con el botón de encendido para entrar en recuperación; en versiones recientes de macOS mantén pulsada la tecla Left Shift (Shift izquierdo) al hacer clic en Continuar y luego csrutil disable. Las configuraciones de máquina virtual siguen un flujo separado: toma primero una instantánea de la VM.
    • macOS 26 / Tahoe: las políticas de validación de bibliotecas y las comprobaciones de derechos privados (private-entitlement) de imagent se han ajustado aún más; imsg puede necesitar una compilación actualizada para mantenerse al día. Si la inyección de imsg launch o selectors específicos comienzan a devolver falso después de una actualización mayor de macOS, consulta las notas de la versión de imsg antes de asumir que el paso de SIP se realizó correctamente.

    Sigue el flujo del modo de recuperación de Apple para tu Mac para desactivar SIP antes de ejecutar imsg launch.

  3. Inyecta el asistente. Con SIP deshabilitado y Messages.app iniciado:

    Ventana de terminal
    imsg launch

    imsg launch se niega a inyectar cuando SIP aún está habilitado, por lo que esto también sirve como confirmación de que el paso 2 se realizó.

  4. Verifica el puente desde OpenClaw:

    Ventana de terminal
    openclaw channels status --probe

    La entrada de iMessage debe informar works y imsg status --json | jq '.selectors' debería mostrar retractMessagePart: true además de los selectores de edición / escritura / lectura que exponga tu compilación de macOS. El filtrado por método del complemento OpenClaw en actions.ts solo anuncia acciones cuyo selector subyacente sea true, por lo que la superficie de acción que ves en la lista de herramientas del agente refleja lo que el puente puede hacer realmente en este host.

Si openclaw channels status --probe indica el canal como works pero acciones específicas lanzan “iMessage `

requiere el puente de la API privada imsg" en el momento del envío, ejecuteimsg launchnuevamente: el asistente puede desactivarse (reinicio de Messages.app, actualización del SO, etc.) y el estadoavailable: true` en caché seguirá anunciando acciones hasta que la siguiente sondeo actualice.

Si tener SIP deshabilitado no es aceptable para tu modelo de amenazas:

  • imsg vuelve al modo básico — texto + multimedia + solo recepción.
  • El complemento OpenClaw todavía anuncia el envío de texto/multimedia y la monitoreo de entrada; solo oculta react, edit, unsend, reply, sendWithEffect y operaciones de grupo de la superficie de acción (según la puerta de capacidad por método).
  • Puede ejecutar un Mac separado sin Apple Silicon (o un Mac bot dedicado) con SIP desactivado para la carga de trabajo de iMessage, mientras mantiene SIP habilitado en sus dispositivos principales. Consulte Usuario de macOS de bot dedicado (identidad iMessage separada) a continuación.

channels.imessage.dmPolicy controla los mensajes directos:

  • pairing (predeterminado)
  • allowlist
  • open (requiere que allowFrom incluya "*")
  • disabled

Campo de lista de permitidos: channels.imessage.allowFrom.

Las entradas de la lista de permitidos deben identificar a los remitentes: identificadores o grupos de acceso de remitente estáticos (`accessGroup:

). Use channels.imessage.groupAllowFrompara objetivos de chat comochat_id:, chat_guid:ochat_identifier:*; use channels.imessage.groupspara claves de registro numéricaschat_id`.

Los chats heredados de iMessage también pueden vincularse a sesiones ACP.

Flujo rápido del operador:

  • Ejecute /acp spawn codex --bind here dentro del MD o el chat de grupo permitido.
  • Los mensajes futuros en esa misma conversación de iMessage se enrutan a la sesión ACP generada.
  • /new y /reset restablecen la misma sesión ACP vinculada en su lugar.
  • /acp close cierra la sesión ACP y elimina la vinculación.

Las vinculaciones persistentes configuradas son compatibles a través de entradas bindings[] de nivel superior con type: "acp" y match.channel: "imessage".

match.peer.id puede usar:

` (recomendado para vinculaciones de grupo estables)

  • `chat_guid:

`

  • `chat_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 de vinculación ACP compartida.

Usuario macOS de bot dedicado (identidad de iMessage separada)

Utilice un ID de Apple y un usuario de macOS dedicados para que el tráfico del bot esté aislado de su perfil personal de Mensajes.

Flujo típico:

  1. Cree/inicie sesión en un usuario de macOS dedicado.
  2. Inicie sesión en Mensajes con el ID de Apple del bot en ese usuario.
  3. Instale imsg en ese usuario.
  4. Cree un contenedor SSH para que OpenClaw pueda ejecutar imsg en ese contexto de usuario.
  5. Apunte `channels.imessage.accounts.

.cliPathy.dbPath` a ese perfil de usuario.

La primera ejecución puede requerir aprobaciones de GUI (Automatización + Acceso completo al disco) en esa sesión de usuario del bot.
Mac remoto a través de Tailscale (ejemplo)

Topología común:

  • el gateway se ejecuta en Linux/VM
  • iMessage + imsg se ejecutan en una Mac en su tailnet
  • el wrapper cliPath usa SSH para ejecutar imsg
  • remoteHost habilita la recuperación de adjuntos SCP

Ejemplo:

{
channels: {
imessage: {
enabled: true,
cliPath: "~/.openclaw/scripts/imsg-ssh",
remoteHost: "[email protected]",
includeAttachments: true,
dbPath: "/Users/bot/Library/Messages/chat.db",
},
},
}
#!/usr/bin/env bash
exec ssh -T [email protected] imsg "$@"

Use claves SSH para que tanto SSH como SCP sean no interactivos. Asegúrese de que la clave del host sea confiable primero (por ejemplo ssh [email protected]) para que known_hosts se complete.

Patrón multicuenta

iMessage admite configuración por cuenta bajo channels.imessage.accounts.

Cada cuenta puede anular campos como cliPath, dbPath, allowFrom, groupPolicy, mediaMaxMb, configuración del historial y listas de permitidos de raíz de adjuntos.

Medios, fragmentación y objetivos de entrega

Sección titulada «Medios, fragmentación y objetivos de entrega»
Adjuntos y medios
  • la ingesta de adjuntos entrantes está desactivada por defecto — configure channels.imessage.includeAttachments: true para reenviar fotos, notas de voz, video y otros adjuntos al agente. Con esto deshabilitado, los iMessage que solo contienen adjuntos se descartan antes de llegar al agente y pueden no producir ninguna línea de registro Inbound message.
  • las rutas de adjuntos remotos se pueden recuperar a través de SCP cuando remoteHost está configurado
  • las rutas de los adjuntos deben coincidir con las raíces permitidas:
    • channels.imessage.attachmentRoots (local)
    • channels.imessage.remoteAttachmentRoots (modo SCP remoto)
    • patrón de raíz predeterminado: /Users/*/Library/Messages/Attachments
  • SCP usa verificación estricta de clave de host (StrictHostKeyChecking=yes)
  • el tamaño de medio saliente usa channels.imessage.mediaMaxMb (predeterminado 16 MB)
Fragmentación de salida
  • límite de fragmento de texto: channels.imessage.textChunkLimit (predeterminado 4000)
  • modo de fragmentación: channels.imessage.chunkMode
    • length (predeterminado)
    • newline (división por párrafos primero)
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:

Ventana de terminal
imsg chats --limit 20

Cuando imsg launch se está ejecutando y openclaw channels status --probe informa privateApi.available: true, la herramienta de mensajes puede usar acciones nativas de iMessage además de envíos de texto normales.

{
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,
},
},
},
}
Acciones disponibles
  • react: Añadir/eliminar respuestas rápidas de iMessage (messageId, emoji, remove). Las respuestas rápidas compatibles se corresponden con me gusta, no me gusta, amor, risa, énfasis y pregunta.
  • reply: Enviar una respuesta en hilo a un mensaje existente (messageId, text o message, más chatGuid, chatId, chatIdentifier, o to).
  • sendWithEffect: Enviar texto con un efecto de iMessage (text o message, effect o effectId).
  • edit: Editar un mensaje enviado en versiones compatibles de macOS/private API (messageId, text o newText).
  • unsend: Retirar un mensaje enviado en versiones compatibles de macOS/private API (messageId).
  • upload-file: Enviar medios/archivos (buffer como base64 o un media/path/filePath hidratado, filename, asVoice opcional). Alias heredado: sendAttachment.
  • renameGroup, setGroupIcon, addParticipant, removeParticipant, leaveGroup: Gestionar chats grupales cuando el objetivo actual es una conversación grupal.
ID de mensaje

El contexto entrante de iMessage incluye valores cortos MessageSid y GUID completos de mensajes cuando están disponibles. Los ID cortos están limitados al caché de respuestas en memoria reciente y se verifican contra el chat actual antes de su uso. Si un ID corto ha caducado o pertenece a otro chat, inténtelo de nuevo con el MessageSidFull completo.

Detección de capacidades

OpenClaw oculta las acciones de la API privada solo cuando el estado de la sonda en caché indica que el puente no está disponible. Si el estado es desconocido, las acciones permanecen visibles y envían sondas de forma diferida para que la primera acción pueda tener éxito después de imsg launch sin una actualización manual separada del estado.

Confirmaciones de lectura y escritura

Cuando el puente de la API privada está activo, los chats entrantes aceptados se marcan como leídos antes del envío y se muestra una burbuja de escritura al remitente mientras el agente se genera. Desactive el marcado de lectura con:

{
channels: {
imessage: {
sendReadReceipts: false,
},
},
}

Las versiones antiguas de imsg anteriores a la lista de capacidades por método bloquearán silenciosamente la escritura/lectura; OpenClaw registra una advertencia única por cada reinicio para que la confirmación faltante sea atribuible.

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 un tapback de usuario no activa un bucle de respuesta ordinario.

El modo de notificación se controla mediante channels.imessage.reactionNotifications:

  • "own" (predeterminado): notificar solo cuando los usuarios reaccionan a mensajes creados por el bot.
  • "all": notificar para todos los tapbacks entrantes de remitentes autorizados.
  • "off": ignorar los tapbacks entrantes.

Las anulaciones por cuenta usan `channels.imessage.accounts.

.reactionNotifications`.

iMessage permite escrituras de configuración iniciadas por el canal de forma predeterminada (para /config set|unset cuando commands.config: true).

Desactivar:

{
channels: {
imessage: {
configWrites: false,
},
},
}

Combinación de MDs de envío dividido (comando + URL en una sola composición)

Sección titulada «Combinación de MDs de envío dividido (comando + URL en una sola composición)»

Cuando un usuario escribe un comando y una URL juntos —por ejemplo, Dump https://example.com/article— la aplicación Mensajes de Apple divide el envío en dos filas chat.db separadas:

  1. Un mensaje de texto ("Dump").
  2. Un globo de vista previa de URL ("https://...") con imágenes de vista previa OG como archivos adjuntos.

Las dos filas llegan a OpenClaw con una separación de ~0,8 a 2,0 s en la mayoría de las configuraciones. Sin la fusión, el agente recibe solo el comando en el turno 1, responde (a menudo “envíame la URL”) y solo ve la URL en el turno 2; en ese punto, el contexto del comando ya se ha perdido. Este es el canal de envío de Apple, no algo que introduzca OpenClaw o imsg.

channels.imessage.coalesceSameSenderDms habilita la opción de fusionar filas consecutivas del mismo remitente en un solo turno de agente para un mensaje directo (DM). Los chats grupales siguen enviando mensaje por mensaje para preservar la estructura de turnos de varios usuarios.

Habilite cuando:

  • Implemente habilidades que esperen command + payload en un solo mensaje (volcado, pegar, guardar, cola, etc.).
  • Sus usuarios peguen URL, imágenes o contenido largo junto con comandos.
  • Pueda aceptar la latencia adicional de turno en el DM (ver más abajo).

Deje deshabilitado cuando:

  • Necesite una latencia de comando mínima para activadores de DM de una sola palabra.
  • Todos sus flujos sean comandos de un solo tiro sin seguimientos de carga útil.
Usuario componechat.db produceBandera desactivada (predeterminado)Bandera activada + ventana de 2500 ms
Dump https://example.com (un envío)2 filas a ~1 s de distanciaDos turnos del agente: “Dump” solo, luego la URLUn turno: texto combinado Dump https://example.com
Save this 📎image.jpg caption (archivo adjunto + texto)2 filasDos turnos (archivo adjunto descartado al combinar)Un turno: texto + imagen conservados
/status (comando independiente)1 filaEnvío instantáneoEsperar hasta la ventana, luego enviar
URL pegada sola1 filaEnvío instantáneoEnvío instantáneo (solo una entrada en el cubo)
Texto + URL enviados como dos mensajes separados deliberados, minutos de diferencia2 filas fuera de la ventanaDos turnosDos turnos (la ventana caduca entre ellos)
Inundación rápida (>10 MD pequeños dentro de la ventana)N filasN turnosUn turno, salida limitada (primera + última, límites de texto/archivos adjuntos aplicados)
Dos personas escribiendo en un chat de grupoN filas de M remitentesM+ turnos (uno por cubo de remitente)M+ turnos — los chats de grupo no se combinan

Poniéndose al día después del tiempo de inactividad de la puerta de enlace

Sección titulada «Poniéndose al día después del tiempo de inactividad de la puerta de enlace»

Cuando el gateway está desconectado (fallos, reinicios, suspensión de Mac, apagado de la máquina), imsg watch se reanuda desde el estado actual chat.db una vez que el gateway vuelve a estar en línea; de forma predeterminada, cualquier cosa que haya llegado durante el tiempo de inactividad nunca se ve. La función de recuperación reproduce esos mensajes en el siguiente inicio para que el agente no pierda silenciosamente el tráfico entrante.

La función de puesta al día está desactivada de forma predeterminada. Actívela por canal:

channels: {
imessage: {
catchup: {
enabled: true, // master switch (default: false)
maxAgeMinutes: 120, // skip rows older than now - 2h (default: 120, clamp 1..720)
perRunLimit: 50, // max rows replayed per startup (default: 50, clamp 1..500)
firstRunLookbackMinutes: 30, // first run with no cursor: look back 30 min (default: 30)
maxFailureRetries: 10, // give up on a wedged guid after 10 dispatch failures (default: 10)
},
},
}

Un paso por cada inicio de monitorIMessageProvider, secuenciado como imsg launch listo → watch.subscribeperformIMessageCatchup → bucle de envío en vivo. La recuperación en sí misma utiliza chats.list + messages.history por chat contra el mismo cliente JSON-RPC utilizado por imsg watch. Cualquier cosa que llegue durante el paso de recuperación fluye normalmente a través del envío en vivo; la caché existente de deduplicación de entrada absorbe cualquier solapamiento con las filas reproducidas.

Cada fila reproducida se procesa a través de la ruta de despacho en vivo (evaluateIMessageInbound + dispatchInboundMessage), por lo que las listas de permitidos, la política de grupo, el antirrebote, la caché de eco y los confirmaciones de lectura se comportan de manera idéntica en los mensajes reproducidos y en vivo.

La recuperación mantiene un cursor por cuenta en `

/imessage/catchup/

__

.json(el directorio de estado de OpenClaw predeterminado es~/.openclaw, modificable con OPENCLAW_STATE_DIR`):

{
"lastSeenMs": 1717900800000,
"lastSeenRowid": 482910,
"updatedAt": 1717900801234,
"failureRetries": { "

”: 1 } }

- El cursor avanza en cada despacho exitoso y se mantiene cuando el despacho de una fila falla; el siguiente inicio reintenta la misma fila desde el cursor mantenido.
- Después de `maxFailureRetries` errores consecutivos contra el mismo `guid`, la recuperación registra un `warn` y fuerza el avance del cursor más allá del mensaje bloqueado para que los inicios posteriores puedan progresar.
- Los GUID ya descartados se omiten a la vista (sin intento de despacho) en ejecuciones posteriores y se cuentan bajo `skippedGivenUp` en el resumen de la ejecución.
### Señales visibles para el operador

imessage catchup: replayed=N skippedFromMe=… skippedGivenUp=… failed=… givenUp=… fetchedCount=… imessage catchup: giving up on guid=

after

failures; advancing cursor past it imessage catchup: fetched

rows across chats, capped to perRunLimit=

Una línea `WARN ... capped to perRunLimit` significa que un solo inicio no drenó el retraso completo. Aumente `perRunLimit` (máx. 500) si sus vacíos exceden regularmente el pase predeterminado de 50 filas.
### Cuándo dejarla desactivada
- El Gateway se ejecuta continuamente con watchdog de reinicio automático y las lagunas son siempre de < unos pocos segundos; el valor predeterminado de desactivado está bien.
- El volumen de MD es bajo y los mensajes perdidos no cambiarían el comportamiento del agente: la ventana inicial de `firstRunLookbackMinutes` puede despachar un contexto antiguo sorprendente al habilitar por primera vez.
Cuando activa la recuperación, el primer inicio sin cursor solo mira hacia atrás `firstRunLookbackMinutes` (30 min predeterminado), no la ventana completa de `maxAgeMinutes` — esto evita reproducir una larga historia de mensajes previos a la habilitación.
## Solución de problemas
imsg not found or RPC unsupported

Valide el binario y el soporte RPC:

Ventana de terminal
imsg rpc --help
imsg status --json
openclaw channels status --probe

Si la prueba informa que RPC no es compatible, actualice imsg. Si las acciones de API privada no están disponibles, ejecute imsg launch en la sesión de usuario de macOS conectada y pruebe de nuevo. Si la puerta de enlace no se está ejecutando en macOS, use la configuración remota de Mac a través de SSH anterior en lugar de la ruta local predeterminada imsg.

Gateway is not running on macOS
El `cliPath: "imsg"` predeterminado debe ejecutarse en el Mac conectado a Messages. En Linux o Windows, configure `channels.imessage.cliPath` en un script contenedor que haga SSH a ese Mac y ejecute `imsg "$@"`.
#!/usr/bin/env bash
exec ssh -T messages-mac imsg "$@"
Luego ejecute:
Ventana de terminal
openclaw channels status --probe --channel imessage
DMs are ignored

Verifique:

  • channels.imessage.dmPolicy
  • channels.imessage.allowFrom
  • aprobaciones de emparejamiento (openclaw pairing list imessage)
Group messages are ignored

Verifique:

  • channels.imessage.groupPolicy
  • channels.imessage.groupAllowFrom
  • comportamiento de la lista de permitidos de channels.imessage.groups
  • configuración del patrón de mención (agents.list[].groupChat.mentionPatterns)
Remote attachments fail

Verifique:

  • channels.imessage.remoteHost
  • channels.imessage.remoteAttachmentRoots
  • autenticación de clave SSH/SCP desde el host de la puerta de enlace
  • la clave de host existe en ~/.ssh/known_hosts en el host de la puerta de enlace
  • legibilidad de la ruta remota en el Mac que ejecuta Messages
macOS permission prompts were missed

Vuelva a ejecutar en una terminal de interfaz gráfica interactiva en el mismo contexto de usuario/sesión y apruebe los indicadores:

Ventana de terminal
imsg chats --limit 1
imsg send

“test”

Confirme que se otorguen Acceso total al disco + Automatización para el contexto de proceso que ejecuta OpenClaw/`imsg`.