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.
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.
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.
Instale (o actualice) imsg en el Mac que ejecuta Messages.app:
Ventana de terminal
brewinstallsteipete/tap/imsg
imsg--version
imsgstatus--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.
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.
Inyecta el asistente. Con SIP deshabilitado y Messages.app iniciado:
Ventana de terminal
imsglaunch
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ó.
Verifica el puente desde OpenClaw:
Ventana de terminal
openclawchannelsstatus--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`.
channels.imessage.groupPolicy controla el manejo de grupos:
allowlist (predeterminado cuando se configura)
open
disabled
Lista blanca de remitentes de grupo: channels.imessage.groupAllowFrom.
Las entradas groupAllowFrom también pueden hacer referencia a grupos de acceso de remitentes estáticos (`accessGroup:
`).
Respaldo en tiempo de ejecución: si `groupAllowFrom` no está configurado, las comprobaciones de remitente de grupo de iMessage usan `allowFrom`; configure `groupAllowFrom` cuando la admisión de MD y grupos deba diferir.
Nota de tiempo de ejecución: si `channels.imessage` falta por completo, el tiempo de ejecución recurre a `groupPolicy="allowlist"` y registra una advertencia (incluso si `channels.defaults.groupPolicy` está configurado).
Filtrado de menciones para grupos:
iMessage no tiene metadatos de mención nativos
la detección de menciones usa patrones de expresiones regulares (agents.list[].groupChat.mentionPatterns, respaldo messages.groupChat.mentionPatterns)
sin patrones configurados, no se puede aplicar el filtrado de menciones
Los comandos de control de remitentes autorizados pueden omitir el filtrado de menciones en grupos.
systemPrompt por grupo:
Cada entrada bajo channels.imessage.groups.* acepta una cadena systemPrompt opcional. El valor se inyecta en el indicador del sistema del agente en cada turno que maneja un mensaje en ese grupo. La resolución refleja la resolución del indicador por grupo utilizada por channels.whatsapp.groups:
Indicador del sistema específico del grupo (`groups[”
“].systemPrompt): se usa cuando existe la entrada específica del grupo en el mapa **y** su clave systemPromptestá definida. SisystemPrompt es una cadena vacía (""), se suprime el comodín y no se aplica ningún indicador del sistema a ese grupo. 2. **Indicador del sistema de comodín de grupo** (groups[”*“].systemPrompt): se usa cuando la entrada específica del grupo falta por completo del mapa, o cuando existe pero no define ninguna clave systemPrompt`.
```json5
{
channels: {
imessage: {
groupPolicy: "allowlist",
groupAllowFrom: ["+15555550123"],
groups: {
"*": { systemPrompt: "Use British spelling." },
"8421": {
requireMention: true,
systemPrompt: "This is the on-call rotation chat. Keep replies under 3 sentences.",
},
"9907": {
// explicit suppression: the wildcard "Use British spelling." does not apply here
systemPrompt: "",
},
},
},
},
}
```
Los indicadores por grupo solo se aplican a mensajes grupales; los mensajes directos en este canal no se ven afectados.
Los MD usan enrutamiento directo; los grupos usan enrutamiento de grupo.
Con el session.dmScope=main predeterminado, los MD de iMessage se colapsan en la sesión principal del agente.
Las sesiones de grupo están aisladas (`agent:
:imessage:group:
`).
- Las respuestas se enrutan de vuelta a iMessage utilizando los metadatos del canal/objetivo de origen.
Comportamiento de hilo tipo grupo:
Algunos hilos de iMessage de 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 (filtrado de grupo + aislamiento de sesión de grupo).
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:
identificador de MD normalizado como +15555550123 o [email protected]
`chat_id:
` (recomendado para vinculaciones de grupo estables)
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.
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:
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.
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:
Un mensaje de texto ("Dump").
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.
{
channels: {
imessage: {
coalesceSameSenderDms: true, // opt in (default: false)
},
},
}
Con el indicador activado y sin messages.inbound.byChannel.imessage explícito, la ventana de antirrebote se amplía a 2500 ms (el valor predeterminado heredado es 0 ms: sin antirrebote). Se requiere la ventana más amplia porque el cadencia de envio dividido de Apple de 0,8 a 2,0 s no cabe en un valor predeterminado más estricto.
Para ajustar la ventana usted mismo:
{
messages: {
inbound: {
byChannel: {
// 2500 ms works for most setups; raise to 4000 ms if your Mac is
// slow or under memory pressure (observed gap can stretch past 2 s
// then).
imessage: 2500,
},
},
},
}
Mayor latencia para los MD. Con la marca activada, cada MD (incluidos los comandos de control independientes y los seguimientos de texto único) espera hasta la ventana de antirrebote antes del envío, por si llega una fila de carga útil. Los mensajes de chat de grupo mantienen el envío instantáneo.
La salida combinada está limitada. El texto combinado se limita a 4000 caracteres con un marcador …[truncated] explícito; los archivos adjuntos se limitan a 20; las entradas de origen se limitan a 10 (se conservan la primera y la más allá de eso). Cada GUID de origen se rastrea en coalescedMessageGuids para telemetría descendente.
Solo para MD. Los chats de grupo pasan al envío por mensaje para que el bot siga respondiendo cuando varias personas estén escribiendo.
Optativo, por canal. Otros canales (Telegram, WhatsApp, Slack, …) no se ven afectados. Las configuraciones heredadas de BlueBubbles que establecen channels.bluebubbles.coalesceSameSenderDms deben migrar ese valor a channels.imessage.coalesceSameSenderDms.
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.subscribe → performIMessageCatchup → 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
imsgrpc--help
imsgstatus--json
openclawchannelsstatus--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
execssh-Tmessages-macimsg"$@"
Luego ejecute:
Ventana de terminal
openclawchannelsstatus--probe--channelimessage
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
imsgchats--limit1
imsgsend
“test”
Confirme que se otorguen Acceso total al disco + Automatización para el contexto de proceso que ejecuta OpenClaw/`imsg`.