Ir al contenido

iMessage

Estado: integración nativa de CLI externa. El 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 una sonda exitosa de la API privada.

Acciones de API privada

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

Emparejamiento

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

Mac remoto

Use un contenedor 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 gateway

    Ventana de terminal
    openclaw gateway
  4. Aprobar 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 de 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 / deshacer envío / respuesta en hilo / efectos / operaciones de grupo), la Protección de Integridad del Sistema debe estar deshabilitada; consulte Habilitar la API privada de imsg a continuación. El envío y recepción básico de texto y medios funciona sin ella.
Los envíos del contenedor SSH fallan con AppleEvents -1743

Una configuración remota por SSH puede leer chats, pasar channels status --probe y procesar mensajes entrantes, mientras que los envíos salientes aún fallan con un error de autorización de AppleEvents:

Not authorized to send Apple events to Messages. (-1743)

Verifique la base de datos TCC del usuario de Mac conectado o Configuración del Sistema > Privacidad y seguridad > Automatización. Si la entrada de Automatización se registra para /usr/libexec/sshd-keygen-wrapper en lugar de para imsg o el proceso de shell local, macOS puede no exponer un interruptor utilizable de Messages para ese cliente del lado del servidor SSH:

kTCCServiceAppleEvents | /usr/libexec/sshd-keygen-wrapper | auth_value=0 | com.apple.MobileSMS

En ese estado, repetir tccutil reset AppleEvents o volver a ejecutar imsg send a través del mismo contenedor SSH puede seguir fallando porque el contexto de proceso que necesita la Automatización de Messages es el contenedor SSH, no una aplicación a la que la interfaz de usuario pueda conceder permisos.

Utilice uno de los contextos de proceso compatibles de imsg en su lugar:

  • Ejecute el Gateway, o al menos el puente imsg, en la sesión local del usuario de Messages conectado.
  • Inicie el Gateway con un LaunchAgent para ese usuario después de otorgar Acceso completo al disco y Automatización desde la misma sesión.
  • Si mantiene la topología SSH de dos usuarios, verifique que un envío saliente real de imsg send se realice correctamente a través del contenedor exacto antes de habilitar el canal. Si no se le puede otorgar Automatización, reconfigure para una configuración de imsg de un solo usuario en lugar de confiar en el contenedor SSH para los envíos.

imsg se distribuye en dos modos operativos:

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

Para acceder a 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 respaldado por puente, mutación de mensajes y gestión de chats son opcionales. Requieren que SIP esté deshabilitado y que se inyecte una dylib de ayuda en Messages.app. imsg launch se niega a inyectar cuando SIP está habilitado.

La técnica de inyección de ayuda utiliza la propia dylib de imsg para alcanzar las API privadas de Messages. No hay un servidor de terceros ni tiempo de ejecución de BlueBubbles en la ruta de 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 bridge_version, rpc_methods y selectors por método, para que pueda ver qué admite la compilación actual antes de comenzar.

  2. Deshabilite 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): deshabilite la Validación de biblioteca a través de la Terminal, reinicie en Modo de recuperación, ejecute csrutil disable, reinicie.
    • macOS 11+ (Big Sur y posteriores), Intel: Modo de recuperación (o recuperación de Internet), csrutil disable, reinicie.
    • macOS 11+, Apple Silicon: secuencia de inicio con el botón de encendido para entrar en Recuperación; en versiones recientes de macOS mantenga presionada la tecla Shift izquierdo cuando haga clic en Continuar, luego csrutil disable. Las configuraciones de máquina virtual siguen un flujo separado: tome primero una instantánea de la VM.
    • macOS 26 / Tahoe: las políticas de validación de biblioteca y las comprobaciones de derechos privados imagent se han endurecido 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 importante de macOS, verifique las notas de la versión de imsg antes de asumir que el paso SIP tuvo éxito.

    Siga el flujo del Modo de recuperación de Apple para su Mac para deshabilitar SIP antes de ejecutar imsg launch.

  3. Inyecte el asistente. Con SIP deshabilitado y Messages.app iniciado sesión:

    Ventana de terminal
    imsg launch

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

  4. Verifique el puente desde OpenClaw:

    Ventana de terminal
    openclaw channels status --probe

    La entrada iMessage debe informar works, y imsg status --json | jq '.selectors' debe mostrar retractMessagePart: true además de los selectores de edición / escritura / lectura que exponga su compilación de macOS. El control de puertas 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 ve en la lista de herramientas del agente refleja lo que el puente realmente puede hacer en este host.

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

requiere el puente de la API privada imsg" en el momento del envío, ejecuteimsg launchnuevamente: el auxiliar puede desconectarse (reinicio de Messages.app, actualización del sistema operativo, etc.) y el estado almacenado en cachéavailable: true` seguirá anunciando acciones hasta que la siguiente sonda se actualice.

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

  • imsg vuelve al modo básico: solo texto + medios + recepción.
  • El complemento OpenClaw todavía anuncia el envío de texto/medios y el monitoreo de entrada; simplemente oculta react, edit, unsend, reply, sendWithEffect y las operaciones de grupo de la superficie de acción (según la puerta de capacidad por método).
  • Puedes ejecutar un Mac separado que no sea de Apple Silicon (o un Mac bot dedicado) con SIP desactivado para la carga de trabajo de iMessage, mientras mantienes SIP activado en tus 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 remitentes estáticos (`accessGroup:

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

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

Flujo rápido de operador:

  • Ejecuta /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 el vínculo.

Se admiten vínculos persistentes configurados a través de entradas bindings[] de nivel superior con type: "acp" y match.channel: "imessage".

match.peer.id puede usar:

` (recomendado para vínculos 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" },
},
],
}

Consulta Agentes ACP para conocer el comportamiento de vínculo ACP compartido.

Usuario de macOS dedicado para el bot (identidad de iMessage separada)

Utilice un Apple ID 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 Apple ID del bot en ese usuario.
  3. Instale imsg en ese usuario.
  4. Cree un contenedor (wrapper) SSH para que OpenClaw pueda ejecutar imsg en el contexto de ese usuario.
  5. Apunte `channels.imessage.accounts.

.cliPathy.dbPath` a ese perfil de usuario.

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

Topología común:

  • la puerta de enlace se ejecuta en Linux/VM
  • iMessage + imsg se ejecutan en una Mac en su tailnet
  • el contenedor (wrapper) cliPath usa SSH para ejecutar imsg
  • remoteHost habilita la recuperación de archivos adjuntos vía 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 de historial y listas de permitidos raíz de archivos adjuntos.

Historial de mensajes directos

Configure channels.imessage.dmHistoryLimit para inicializar nuevas sesiones de mensajes directos con el historial reciente decodificado de imsg para esa conversación. Use `channels.imessage.dms[”

“].historyLimitpara anulaciones por remitente, incluyendo0` para desactivar el historial para un remitente.

El historial de MD de iMessage se obtiene bajo demanda desde `imsg`. Dejar `dmHistoryLimit` sin establecer desactiva la inicialización global del historial de MD, pero un valor `channels.imessage.dms["

“].historyLimit` positivo por remitente sigue activando la inicialización para ese remitente.

Medios, fragmentación y objetivos de entrega

Sección titulada «Medios, fragmentación y objetivos de entrega»
Archivos adjuntos y medios
  • la ingesta de archivos adjuntos entrantes está desactivada por defecto — establezca channels.imessage.includeAttachments: true para reenviar fotos, notas de voz, videos y otros archivos adjuntos al agente. Con esto desactivado, los iMessages que solo contienen archivos adjuntos se descartan antes de llegar al agente y pueden no producir ninguna línea de registro Inbound message.
  • las rutas de archivos adjuntos remotos se pueden obtener a través de SCP cuando remoteHost está establecido
  • las rutas de los archivos 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 utiliza verificación estricta de clave de host (StrictHostKeyChecking=yes)
  • el tamaño de los medios salientes utiliza channels.imessage.mediaMaxMb (predeterminado 16 MB)
Fragmentación saliente
  • 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 tipo identificador:

Ventana de terminal
imsg chats --limit 20

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

{
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 tapbacks de iMessage (messageId, emoji, remove). Los tapbacks admitidos corresponden a me gusta, amor, no me gusta, 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 de macOS/API privada compatibles (messageId, text o newText).
  • unsend: Retirar un mensaje enviado en versiones de macOS/API privada compatibles (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: Administrar chats grupales cuando el objetivo actual es una conversación grupal.
ID de mensajes

El contexto entrante de iMessage incluye tanto valores cortos de MessageSid como GUIDs de mensaje completos cuando están disponibles. Los ID cortos tienen un alcance limitado al caché de respaldas respaldado por SQLite reciente y se verifican contra el chat actual antes de su uso. Si un ID corto ha expirado o pertenece a otro chat, vuelva a intentarlo con el MessageSidFull completo.

Detección de capacidades

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

Read receipts and typing

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 genera. Desactive el marcado de lectura con:

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

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

Reacciones de entrada

OpenClaw se suscribe a las reacciones de iMessage y enruta las reacciones aceptadas como eventos del sistema en lugar de texto de mensaje normal, por lo que una reacción del usuario no activa un bucle de respuesta ordinario.

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

  • "own" (predeterminado): notifica solo cuando los usuarios reaccionan a mensajes creados por el bot.
  • "all": notifica todas las reacciones de entrada de remitentes autorizados.
  • "off": ignora las reacciones de entrada.

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

.reactionNotifications`.

Reacciones de aprobación (👍 / 👎)

Cuando approvals.exec.enabled o approvals.plugin.enabled es verdadero y la solicitud se enruta a iMessage, la puerta de enlace entrega un aviso de aprobación de forma nativa y acepta una respuesta rápida (tapback) para resolverlo:

  • 👍 (Respuesta rápida de Me gusta) → allow-once
  • 👎 (Respuesta rápida de No me gusta) → deny
  • allow-always sigue siendo una alternativa manual: envíe `/approve

allow-always` como una respuesta normal.

El manejo de reacciones requiere que el identificador del usuario que reaccione sea un aprobador explícito. La lista de aprobadores se lee de channels.imessage.allowFrom (o `channels.imessage.accounts.

.allowFrom); añada el número de teléfono del usuario en formato E.164 o su correo electrónico de Apple ID. La entrada comodín ”*“se respeta pero permite a cualquier remitente aprobar. El atajo de reacción omite intencionalmentereactionNotifications, dmPolicyygroupAllowFrom` porque la lista de permitidos de aprobadores explícitos es la única puerta importante para la resolución de aprobaciones.

**Cambio de comportamiento con esta versión:** Cuando `channels.imessage.allowFrom` no está vacío, el comando de texto `/approve

ahora se autoriza contra esa lista de aprobadores (no la lista de permitidos de MD más amplia). Los remitentes permitidos en la lista de permitidos de MD pero que no están enallowFromrecibirán una denegación explícita. Añada cada operador que deba poder aprobar a través de/approve(y a través de reacciones) aallowFrompara preservar el comportamiento anterior. CuandoallowFromestá vacío, la alternativa heredada de "mismo chat" sigue vigente y/approve` continúa autorizando a cualquier persona que la lista de permitidos de MD permita.

Notas del operador:
- El enlace de reacción se almacena tanto en la memoria (con TTL coincidente con la caducidad de la aprobación) como en el almacenamiento persistente con clave de la puerta de enlace, por lo que una respuesta rápida que llegue poco después de un reinicio de la puerta de enlace aún resuelve la aprobación.
- Las respuestas rápidas `is_from_me=true` entre dispositivos (la propia reacción del operador en un dispositivo Apple emparejado) se ignoran intencionalmente para que el bot no pueda autoaprobarse.
- Las respuestas rápidas de estilo de texto heredadas (`Liked "…"` texto plano de clientes de Apple muy antiguos) no pueden resolver aprobaciones porque no llevan ningún GUID de mensaje; la resolución de reacciones requiere los metadatos estructurados de respuesta rápida que los clientes actuales de macOS / iOS emiten.

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

Desactivar:

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

Agrupación de MDs enviadas por partes (comando + URL en una sola redacción)

Sección titulada «Agrupación de MDs enviadas por partes (comando + URL en una sola redacció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 diferencia de ~0.8-2.0 s en la mayoría de las configuraciones. Sin la agrupació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, momento en el cual el contexto del comando ya se ha perdido. Esta es la canalización de envío de Apple, no algo que introduzca OpenClaw o imsg.

channels.imessage.coalesceSameSenderDms habilita que un DM combine filas consecutivas del mismo remitente en un solo turno de agente. Los chats de grupo siguen enviando mensaje por mensaje para preservar la estructura de turnos multiusuario.

Habilitar cuando:

  • Envías habilidades que esperan command + payload en un solo mensaje (volcado, pegar, guardar, cola, etc.).
  • Tus usuarios pegan URL, imágenes o contenido largo junto con comandos.
  • Puedes aceptar la latencia adicional de turno en el DM (ver abajo).

Dejar deshabilitado cuando:

  • Necesitas una latencia mínima de comando para activadores de DM de una sola palabra.
  • Todos tus flujos son comandos de un solo uso sin seguimientos de carga útil.
Usuario componechat.db produceIndicador desactivado (predeterminado)Indicador activado + ventana de 2500 ms
Dump https://example.com (un envío)2 filas a ~1 s de distanciaDos turnos del agente: solo “Dump”, luego URLUn turno: texto combinado Dump https://example.com
Save this 📎image.jpg caption (archivo adjunto + texto)2 filasDos turnos (archivo adjunto eliminado al combinar)Un turno: texto + imagen conservados
/status (comando independiente)1 filaEnvío inmediatoEsperar hasta la ventana, luego enviar
URL pegada sola1 filaEnvío inmediatoEnvío inmediato (solo una entrada en el grupo)
Texto + URL enviados como dos mensajes separados deliberados, a minutos de distancia2 filas fuera de la ventanaDos turnosDos turnos (la ventana expira entre ellos)
Inundación rápida (>10 MD pequeños dentro de la ventana)N filasN turnosUn turno, salida limitada (primero + último, límites de texto/archivos adjuntos aplicados)
Dos personas escribiendo en un chat de grupoN filas de M remitentesM+ turnos (uno por cada cubo de remitente)M+ turnos — los chats de grupo no se unifican

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

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

Cuando la puerta de enlace está desconectada (fallo, reinicio, Mac en reposo, máquina apagada), imsg watch se reanuda desde el estado actual de chat.db una vez que la puerta de enlace vuelve a estar en línea; de forma predeterminada, cualquier cosa que llegue durante el lapso nunca se ve. La función de puesta al día (catchup) reproduce esos mensajes en el siguiente inicio para que el agente no pierda silenciosamente el tráfico entrante.

La puesta al día está deshabilitada 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 pase por cada inicio de monitorIMessageProvider, secuenciado como imsg launch listo → watch.subscribeperformIMessageCatchup → bucle de despacho en vivo. La recuperación en sí utiliza chats.list + messages.history por chat contra el mismo cliente JSON-RPC que usa imsg watch. Todo lo que llega durante el pase de recuperación fluye a través del despacho en vivo normalmente; el caché de deduplicación de entrada existente absorbe cualquier superposición con las filas reproducidas.

Cada fila reproducida se alimenta 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, el caché de eco y las 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 el estado del complemento SQLite:

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

”: 1 } }

- El cursor avanza con cada envío exitoso y se mantiene cuando el envío de una fila falla; el siguiente inicio reintenta la misma fila desde el cursor mantenido.
- Después de que la consulta de recuperación al inicio tenga éxito, las filas manejadas en vivo posteriormente también avanzan el mismo cursor para que un reinicio de la puerta de enlace no reproduzca mensajes que ya se manejaron en vivo. Las escrituras del cursor en vivo no saltan por encima de los fallos de recuperación que todavía están por debajo de `maxFailureRetries`.
- Después de `maxFailureRetries` fallos 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 GUIDs ya descartados se omiten a la vista (sin intento de envío) en ejecuciones posteriores y se contabilizan bajo `skippedGivenUp` en el resumen de la ejecución.
- `openclaw doctor --fix` importa los archivos de cursor `

/imessage/catchup/*.json` heredados al estado del complemento SQLite y archiva los archivos antiguos.

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 único inicio no drenó el retraso completo. Aumente `perRunLimit` (máx. 500) si sus brechas exceden regularmente el paso predeterminado de 50 filas.
### Cuándo dejarlo desactivado
- El Gateway se ejecuta continuamente con reinicio automático del vigilante y las brechas son siempre < unos pocos segundos; lo 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 `firstRunLookbackMinutes` puede enviar un contexto antiguo sorprendente al habilitar por primera vez.
Cuando activas la recuperación, el primer inicio sin cursor solo mira hacia atrás `firstRunLookbackMinutes` (30 min por defecto), no toda la ventana de `maxAgeMinutes`; esto evita reproducir un historial largo de mensajes previos a la activación.
## Solución de problemas
imsg no encontrado o RPC no compatible

Valide el binario y el soporte RPC:

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

Si el sondeo 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 de usuario de macOS iniciada y sondee nuevamente. Si Gateway no se está ejecutando en macOS, use la configuración de Mac remoto a través de SSH anterior en lugar de la ruta local imsg predeterminada.

Gateway no se está ejecutando en macOS
El `cliPath: "imsg"` predeterminado debe ejecutarse en el Mac conectado a Messages. En Linux o Windows, configure `channels.imessage.cliPath` en un script de wrapper 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
Se ignoran los MD

Compruebe:

  • channels.imessage.dmPolicy
  • channels.imessage.allowFrom
  • aprobaciones de emparejamiento (openclaw pairing list imessage)
Se ignoran los mensajes grupales

Verifica:

  • channels.imessage.groupPolicy
  • channels.imessage.groupAllowFrom
  • comportamiento de lista blanca channels.imessage.groups
  • configuración del patrón de mención (agents.list[].groupChat.mentionPatterns)
Fallo de archivos adjuntos remotos

Verifica:

  • 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
Se pasaron por alto los avisos de permisos de macOS

Vuelve a ejecutar en una terminal de GUI interactiva en el mismo contexto de usuario/sesión y aprueba los avisos:

Ventana de terminal
imsg chats --limit 1
imsg send

“test”

Confirma que se hayan otorgado Acceso total al disco + Automatización para el contexto del proceso que ejecuta OpenClaw/`imsg`.