État : intégration native externe de CLI. La Gateway génère CLIGatewayimsg rpcRPC et communique via JSON-RPC sur stdio (pas de démon/port distinct). Les actions avancées nécessitent imsg launchAPI et une sonde réussie de l’API privée.
Messages doit être connecté sur le Mac exécutant imsg.
L’accès complet au disque est requis pour le contexte de processus exécutant OpenClaw/imsg (accès à la base de données Messages).
L’autorisation d’automatisation est requise pour envoyer des messages via Messages.app.
Pour les actions avancées (réagir / modifier / annuler l’envoi / réponse filée / effets / opérations de groupe), la protection de l’intégrité du système doit être désactivée — voir Activation de l’API privée imsg ci-dessous. L’envoi et la réception de textes et médias de base fonctionnent sans cela.
Les envois via le wrapper SSH échouent avec AppleEvents -1743
Une configuration SSH à distance peut lire les discussions, transmettre channels status --probe et traiter les messages entrants, alors que les envois sortants échouent toujours avec une erreur d’autorisation AppleEvents :
Not authorized to send Apple events to Messages. (-1743)
Vérifiez la base de données TCC de l’utilisateur Mac connecté ou les Réglages système > Confidentialité et sécurité > Automatisation. Si l’entrée d’automatisation est enregistrée pour /usr/libexec/sshd-keygen-wrapper au lieu du imsg ou du processus du shell local, macOS peut ne pas exposer de bascule Messages utilisable pour ce client côté serveur SSH :
Dans cet état, répéter tccutil reset AppleEvents ou relancer imsg send via le même wrapper SSH peut continuer d’échouer car le contexte de processus qui a besoin de l’automatisation Messages est le wrapper SSH, et non une application que l’interface utilisateur peut autoriser.
Utilisez plutôt l’un des contextes de processus imsg pris en charge :
Exécutez le Gateway, ou au moins le pont imsg, dans la session locale de l’utilisateur Messages connecté.
Démarrez le Gateway avec un LaunchAgent pour cet utilisateur après avoir accordé l’accès complet au disque et l’automatisation depuis la même session.
Si vous conservez la topologie SSH à deux utilisateurs, vérifiez qu’un envoi sortant réel imsg send réussit via le wrapper exact avant d’activer le channel. Si l’automatisation ne peut pas lui être accordée, reconfigurez en une configuration imsg à utilisateur unique au lieu de compter sur le wrapper SSH pour les envois.
imsg est fourni avec deux modes de fonctionnement :
Mode basique (par défaut, aucune modification SIP requise) : texte et média sortants via send, surveillance/historique entrants, liste de discussions. C’est ce que vous obtenez directement avec une nouvelle installation de brew install steipete/tap/imsgmacOS plus les permissions macOS standard ci-dessus.
Mode API privée : imsg injecte une dylib d’aide dans Messages.app pour appeler les fonctions internes de IMCore. C’est ce qui déverrouille react, edit, unsend, reply (filés), sendWithEffect, renameGroup, setGroupIcon, addParticipant, removeParticipant, leaveGroup, ainsi que les indicateurs de frappe et les accusés de lecture.
Pour accéder à la surface d’action avancée documentée sur cette page de canal, vous avez besoin du mode API privée. Le README de imsg est explicite concernant cette exigence :
Les fonctionnalités avancées telles que read, typing, launch, l’envi enrichi basé sur un pont, la mutation de messages et la gestion des discussions sont facultatives. Elles nécessitent que SIP soit désactivé et qu’une dylib d’aide soit injectée dans Messages.app. imsg launch refuse d’injecter lorsque SIP est activé.
La technique d’injection d’aide utilise la propre dylib de imsg pour atteindre les privées de Messages. Il n’y a aucun serveur tiers ou runtime BlueBubbles dans le chemin OpenClaw de iMessage.
Installez (ou mettez à niveau) imsg sur le Mac qui exécute Messages.app :
Fenêtre de terminal
brewinstallsteipete/tap/imsg
imsg--version
imsgstatus--json
La sortie imsg status --json signale bridge_version, rpc_methods et selectors par méthode, afin que vous puissiez voir ce que la version actuelle prend en charge avant de commencer.
Désactivez la protection de l’intégrité du système. Cela dépend de la version de macOS car la condition sous-jacente d’Apple dépend du système d’exploitation et du matériel :
macOS 10.13–10.15 (Sierra–Catalina) : désactivez la validation de la bibliothèque via le Terminal, redémarrez en mode récupération, exécutez csrutil disable, redémarrez.
macOS 11+ (Big Sur et versions ultérieures), Intel : Mode récupération (ou récupération Internet), csrutil disable, redémarrez.
macOS 11+, Apple Silicon : séquence de démarrage via le bouton d’alimentation pour entrer en récupération ; sur les versions récentes de macOS, maintenez la touche Maj gauche lorsque vous cliquez sur Continuer, puis csrutil disable. Les configurations de machine virtuelle suivent un processus distinct — prenez d’abord un instantané de la VM.
macOS 26 / Tahoe : les stratégies de validation de bibliothèque et les vérifications d’entitlements privés imagent ont encore été renforcées ; imsg peut nécessiter une version mise à jour pour suivre le rythme. Si l’injection imsg launch ou des selectors spécifiques commencent à renvoyer false après une mise à niveau majeure de macOS, consultez les notes de version de imsg avant de supposer que l’étape SIP a réussi.
Suivez le processus de mode récupération d’Apple pour votre Mac pour désactiver SIP avant d’exécuter imsg launch.
Injecter l’assistant. Avec SIP désactivé et Messages.app connecté :
Fenêtre de terminal
imsglaunch
imsg launch refuse d’injecter lorsque SIP est toujours activé, ce qui constitue également une confirmation que l’étape 2 a été effectuée.
Vérifier le pont depuis OpenClaw :
Fenêtre de terminal
openclawchannelsstatus--probe
L’entrée iMessage doit indiquer works, et imsg status --json | jq '.selectors' doit afficher retractMessagePart: true ainsi que les sélecteurs d’édition / de frappe / de lecture que votre version macOS expose. Le filtrage par méthode du plugin OpenClaw dans actions.ts n’annonce que les actions dont le sélecteur sous-jacent est true ; par conséquent, la surface d’action que vous voyez dans la liste d’outils de l’agent reflète ce que le pont peut réellement faire sur cet hôte.
Si openclaw channels status --probe signale le canal comme works mais que des actions spécifiques renvoient « iMessage `
API nécessite le pont de l'API privée imsg » au moment de l'envoi, exécutez à nouveau imsg launch— l'assistant peut être désactivé (redémarrage de Messages.app, mise à jour du système d'exploitation, etc.) et le statutavailable: true` mis en cache continuera d’annoncer des actions jusqu’à ce que la prochaine sonde actualise.
Si la désactivation de SIP n’est pas acceptable pour votre modèle de menace :
imsg revient en mode basique — texte + média + réception uniquement.
Le plugin OpenClaw annonce toujours l’envoi de texte/médias et la surveillance des messages entrants ; il masque simplement OpenClawreact, edit, unsend, reply, sendWithEffect et les opérations de groupe sur la surface des actions (conformément à la porte de capacité par méthode).
Vous pouvez exécuter un Mac distinct non Apple Silicon (ou un Mac dédié aux bots) avec SIP désactivé pour la charge de travail iMessage, tout en gardant SIP activé sur vos appareils principaux. Voir Utilisateur macOS de bot dédié (identité iMessage distincte) ci-dessous.
channels.imessage.dmPolicy contrôle les messages directs :
pairing (par défaut)
allowlist
open (nécessite que allowFrom inclue "*")
disabled
Champ de liste d’autorisation : channels.imessage.allowFrom.
Les entrées de la liste d’autorisation doivent identifier les expéditeurs : identifiants ou groupes d’accès d’expéditeur statiques (`accessGroup:
). Utilisez channels.imessage.groupAllowFrompour les cibles de chat telles quechat_id:, chat_guid:ouchat_identifier:*; utilisezchannels.imessage.groupspour les clés de registre numériqueschat_id`.
channels.imessage.groupPolicy contrôle la gestion des groupes :
allowlist (par défaut lors de la configuration)
open
disabled
Liste d’autorisation des expéditeurs de groupe : channels.imessage.groupAllowFrom.
Les entrées groupAllowFrom peuvent également faire référence à des groupes d’accès statiques pour les expéditeurs (`accessGroup:
`).
Repli à l'exécution : si `groupAllowFrom`iMessage n'est pas défini, les vérifications d'expéditeur de groupe iMessage utilisent `allowFrom` ; définissez `groupAllowFrom` lorsque l'admission des DM et des groupes doit différer.
Remarque à l'exécution : si `channels.imessage` est complètement manquant, l'exécution revient à `groupPolicy="allowlist"` et enregistre un avertissement (même si `channels.defaults.groupPolicy` est défini).
Filtrage des mentions pour les groupes :
iMessage n’a pas de métadonnées natives de mention
la détection des mentions utilise des modèles regex (agents.list[].groupChat.mentionPatterns, repli messages.groupChat.mentionPatterns)
sans modèles configurés, le filtrage des mentions ne peut pas être appliqué
Les commandes de contrôle des expéditeurs autorisés peuvent contourner le filtrage des mentions dans les groupes.
systemPrompt par groupe :
Chaque entrée sous channels.imessage.groups.* accepte une chaîne systemPrompt facultative. La valeur est injectée dans le prompt système de l’agent à chaque tour gérant un message dans ce groupe. La résolution reflète la résolution du prompt par groupe utilisée par channels.whatsapp.groups :
Prompt système spécifique au groupe (`groups[”
“].systemPrompt) : utilisé lorsque l'entrée de groupe spécifique existe dans la carte **et** que sa clé systemPromptest définie. SisystemPrompt est une chaîne vide (""), le caractère générique est supprimé et aucun prompt système n'est appliqué à ce groupe. 2. **Prompt système générique de groupe** (groups[”*“].systemPrompt) : utilisé lorsque l'entrée de groupe spécifique est totalement absente de la carte, ou lorsqu'elle existe mais ne définit aucune clé 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: "",
},
},
},
},
}
```
Les prompts par groupe s'appliquent uniquement aux messages de groupe — les messages directs dans ce canal ne sont pas affectés.
Les DMs utilisent le routage direct ; les groupes utilisent le routage de groupe.
Avec session.dmScope=main par défaut, les iMessage DMs fusionnent dans la session principale de l’agent.
Les sessions de groupe sont isolées (`agent:
:imessage:group:
`).
- Les réponses sont renvoyées vers iMessage en utilisant les métadonnées de canal/cible d’origine.
Comportement des fils de discussion de type groupe :
Certains fils de discussion iMessage à plusieurs participants peuvent arriver avec `is_group=false`.
Si ce `chat_id` est explicitement configuré sous `channels.imessage.groups`, OpenClaw le traite comme un trafic de groupe (filtrage de groupe + isolation de session de groupe).
Les discussions iMessage héritées peuvent également être liées à des sessions ACP.
Flux rapide pour l’opérateur :
Exécutez /acp spawn codex --bind here dans le DM ou le groupe autorisé.
Les futurs messages de cette même conversation iMessage sont acheminés vers la session ACP générée.
/new et /reset réinitialisent la même session ACP liée sur place.
/acp close ferme la session ACP et supprime la liaison.
Les liaisons persistantes configurées sont prises en charge via des entrées bindings[] de niveau supérieur avec type: "acp" et match.channel: "imessage".
match.peer.id peut utiliser :
un identifiant DM normalisé tel que +15555550123 ou [email protected]
`chat_id:
` (recommandé pour les liaisons de groupe stables)
Utilisez des clés SSH afin que SSH et SCP soient non-interactifs.
Assurez-vous que la clé de l’hôte est approuvée au préalable (par exemple ssh [email protected]) afin que known_hosts soit renseigné.
Modèle multi-compte
iMessage prend en charge la configuration par compte sous channels.imessage.accounts.
Chaque compte peut remplacer des champs tels que cliPath, dbPath, allowFrom, groupPolicy, mediaMaxMb, les paramètres d’historique et les listes d’autorisation des racines de pièces jointes.
Historique des messages directs
Définissez channels.imessage.dmHistoryLimit pour amorcer les nouvelles sessions de messages directs avec l’historique récent décodé des imsg pour cette conversation. Utilisez `channels.imessage.dms[”
“].historyLimitpour des remplacements par expéditeur, y compris0`iMessage pour désactiver l’historique pour un expéditeur.
L'historique des DM iMessage est récupéré à la demande depuis `imsg`. Laisser `dmHistoryLimit` non défini désactive l'amorçage global de l'historique des DM, mais une valeur positive `channels.imessage.dms["
“].historyLimit` par expéditeur active toujours l’amorçage pour cet expéditeur.
l’ingestion des pièces jointes entrantes est désactivée par défaut — définissez channels.imessage.includeAttachments: true pour transférer les photos, mémos vocaux, vidéos et autres pièces jointes à l’agent. Si elle est désactivée, les iMessages contenant uniquement des pièces jointes sont supprimés avant d’atteindre l’agent et peuvent ne produire aucune ligne de journal Inbound message.
les chemins distants des pièces jointes peuvent être récupérés via SCP lorsque remoteHost est défini
les chemins des pièces jointes doivent correspondre aux racines autorisées :
Lorsque imsg launch est en cours d’exécution et que openclaw channels status --probe signale privateApi.available: true, l’outil de message peut utiliser des actions natives iMessage en plus des envois de texte normaux.
{
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,
},
},
},
}
Actions disponibles
react : Ajouter/supprimer des tapbacks iMessage (messageId, emoji, remove). Les tapbacks pris en charge correspondent à cœur, j’aime, je n’aime pas, rire, souligner et question.
reply : Envoyer une réponse en fil à un message existant (messageId, text ou message, plus chatGuid, chatId, chatIdentifier, ou toiMessage).
sendWithEffect : Envoyer du texte avec un effet iMessage (text ou message, effect ou effectIdmacOSAPI).
edit : Modifier un message envoyé sur les versions macOS/API privée prises en charge (messageId, text ou newTextmacOSAPI).
unsend : Retirer un message envoyé sur les versions macOS/API privée prises en charge (messageId).
upload-file : Envoyer des médias/fichiers (buffer en base64 ou un media/path/filePath hydraté, filename, asVoice en option). Alias hérité : sendAttachment.
renameGroup, setGroupIcon, addParticipant, removeParticipant, leaveGroup : Gérer les discussions de groupe lorsque la cible actuelle est une conversation de groupe.
ID de message
Le contexte iMessage entrant inclut à la fois des valeurs MessageSid courtes et des GUID de message complets lorsque disponibles. Les ID courts sont limités au cache de réponse récent soutenu par SQLite et sont vérifiés par rapport à la discussion actuelle avant utilisation. Si un ID court a expiré ou appartient à une autre discussion, réessayez avec le MessageSidFull complet.
Détection des fonctionnalités
OpenClaw masque les actions de l’API privé uniquement lorsque l’état de la sonde en cache indique que le pont est indisponible. Si l’état est inconnu, les actions restent visibles et envoient des sondes de manière différée, afin que la première action puisse réussir après imsg launch sans actualisation manuelle séparée de l’état.
Accusés de lecture et saisie
Lorsque le pont de l’API privé est actif, les conversations entrantes acceptées sont marquées comme lues avant l’expédition et une bulle de saisie est affichée à l’expéditeur pendant que l’agent génère. Désactivez le marquage comme lu avec :
{
channels: {
imessage: {
sendReadReceipts: false,
},
},
}
Les versions plus anciennes de imsg antérieures à la liste des fonctionnalités par méthode bloqueront silencieusement la saisie/lecture ; OpenClaw enregistre un avertissement unique par redémarrage afin que l’accusé de réception manquant soit attribuable.
Tapbacks entrants
OpenClaw s’abonne aux tapbacks iMessage et achemine les réactions acceptées en tant qu’événements système au lieu de texte de message normal, afin qu’un tapback utilisateur ne déclenche pas une boucle de réponse ordinaire.
Le mode de notification est contrôlé par channels.imessage.reactionNotifications :
"own" (par défaut) : notifier uniquement lorsque les utilisateurs réagissent aux messages rédigés par le bot.
"all" : notifier pour tous les tapbacks entrants des expéditeurs autorisés.
"off" : ignorer les tapbacks entrants.
Les substitutions par compte utilisent `channels.imessage.accounts.
.reactionNotifications`.
Réactions d'approbation (👍 / 👎)
Lorsque approvals.exec.enabled ou approvals.plugin.enabled est vrai et que la requête est routée vers iMessage, la passerelle fournit une invite d’approbation en mode natif et accepte un tapback pour la résoudre :
👍 (Tapback J’aime) → allow-once
👎 (Tapback Je n’aime pas) → deny
allow-always reste une solution de repli manuelle : envoyez `/approve
allow-always` comme une réponse normale.
La gestion des réactions exige que l’identifiant de l’utilisateur réagissant soit un approbateur explicite. La liste des approbateurs est lue depuis channels.imessage.allowFrom (ou `channels.imessage.accounts.
.allowFrom) ; ajoutez le numéro de téléphone de l'utilisateur au format E.164 ou son e-mail d'identifiant Apple. L'entrée générique ”*“est respectée mais permet à tout expéditeur d'approuver. Le raccourci de réaction contourne intentionnellementreactionNotifications, dmPolicyetgroupAllowFrom` car la liste d’autorisation des approbateurs explicites est la seule barrière qui compte pour la résolution de l’approbation.
**Changement de comportement avec cette version :** Lorsque `channels.imessage.allowFrom` n'est pas vide, la commande texte `/approve
est désormais autorisée par rapport à cette liste d'approbateurs (et non la liste d'autorisation DM plus large). Les expéditeurs autorisés sur la liste d'autorisation DM mais pas dansallowFromrecevront un refus explicite. Ajoutez chaque opérateur qui doit pouvoir approuver via/approve(et via les réactions) àallowFrompour conserver le comportement précédent. LorsqueallowFromest vide, le « repli même conversation » hérité reste en vigueur et/approve` continue d’autoriser toute personne autorisée par la liste d’autorisation DM.
Notes pour les opérateurs :
- La liaison de réaction est stockée à la fois en mémoire (avec un TTL correspondant à l'expiration de l'approbation) et dans le magasin persistant à clé de la passerelle, de sorte qu'un tapback qui arrive peu après un redémarrage de la passerelle résout toujours l'approbation.
- Les tapbacks `is_from_me=true` inter-appareils (la propre réaction de l'opérateur sur un appareil Apple associé) sont intentionnellement ignorés pour que le bot ne puisse pas s'auto-approuver.
- Les tapbacks de style texte hérités (`Liked "…"` texte brut de très anciens clients Apple) ne peuvent pas résoudre les approbations car ils ne transportent aucun GUID de message ; la résolution des réactions nécessite les métadonnées de tapback structurées que les clients macOS / iOS actuels émettent.
Lorsqu’un utilisateur tape une commande et une URL ensemble — par ex. Dump https://example.com/article — l’application Messages d’Apple divise l’envoi en deux lignes chat.db distinctes :
Un message texte ("Dump").
Un ballon d’aperçu d’URL ("https://...") avec des images d’aperçu OG en pièces jointes.
Les deux lignes arrivent à OpenClaw à environ 0,8 à 2,0 s d’intervalle sur la plupart des configurations. Sans fusion, l’agent reçoit la commande seul au tour 1, répond (souvent « envoyez-moi l’URL »), et ne voit l’URL qu’au tour 2 — moment auquel le contexte de la commande est déjà perdu. C’est le pipeline d’envoi d’Apple, et non quelque chose introduit par OpenClaw ou OpenClawOpenClawimsg.
channels.imessage.coalesceSameSenderDms permet à un DM de fusionner les lignes consécutives du même expéditeur en un seul tour d’agent. Les discussions de groupe continuent d’être distribuées par message afin de préserver la structure des tours multi-utilisateurs.
Activer lorsque :
Vous proposez des compétences qui s’attendent à command + payload en un seul message (dump, paste, save, queue, etc.).
Vos utilisateurs collent des URL, des images ou du contenu long aux côtés des commandes.
Vous pouvez accepter la latence ajoutée au tour de DM (voir ci-dessous).
Laisser désactivé lorsque :
Vous avez besoin d’une latence de commande minimale pour les déclencheurs DM d’un seul mot.
Tous vos flux sont des commandes ponctuelles sans suite de charge utile.
{
channels: {
imessage: {
coalesceSameSenderDms: true, // opt in (default: false)
},
},
}
Avec l’indicateur activé et aucun messages.inbound.byChannel.imessage explicite, la fenêtre de rebond s’élargit à 2500 ms (la valeur par défaut héritée est de 0 ms — aucun rebond). La fenêtre plus large est nécessaire car la cadence d’envoi fractionné d’Apple de 0,8 à 2,0 s ne rentre pas dans une valeur par défaut plus serrée.
Pour ajuster la fenêtre vous-même :
{
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,
},
},
},
}
Latence ajoutée pour les messages DM. Avec l’indicateur activé, chaque DM (y compris les commandes de contrôle autonomes et les suivis de texte unique) attend jusqu’à la fenêtre de debounce avant l’envoi, au cas où une ligne de payload arriverait. Les messages de chat de groupe gardent un envoi instantané.
La sortie fusionnée est limitée. Le texte fusionné est plafonné à 4000 caractères avec un marqueur explicite …[truncated] ; les pièces jointes sont plafonnées à 20 ; les entrées source sont plafonnées à 10 (le premier et le plus récent sont conservés au-delà). Chaque GUID source est suivi dans coalescedMessageGuids pour la télémétrie en aval.
DM uniquement. Les chats de groupe passent à un envoi par message afin que le bot reste réactif lorsque plusieurs personnes écrivent.
Opt-in, par canal. Les autres canaux (Telegram, WhatsApp, Slack, …) ne sont pas affectés. Les configurations BlueBubbles héritées qui définissent channels.bluebubbles.coalesceSameSenderDms doivent migrer cette valeur vers channels.imessage.coalesceSameSenderDms.
Lorsque la passerelle est hors ligne (plantage, redémarrage, mise en veille du Mac, machine éteinte), imsg watch reprend à partir de l’état actuel chat.db une fois la passerelle revenue en ligne — tout ce qui est arrivé pendant l’interruption est, par défaut, jamais vu. Le rattrapage rejoue ces messages au prochain démarrage pour que l’agent ne manque pas silencieusement le trafic entrant.
Le rattrapage est désactivé par défaut. Activez-le par channel :
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)
Une passe par démarrage de monitorIMessageProvider, séquencée comme imsg launch prêt → watch.subscribe → performIMessageCatchup → boucle de distribution en direct. Le rattrapage utilise lui-même chats.list + messages.history par chat sur le même client JSON-RPC utilisé par imsg watch. Tout ce qui arrive pendant la passe de rattrapage traverse la distribution en direct normalement ; le cache de déduplication entrant existant absorbe tout chevauchement avec les lignes rejouées.
Chaque ligne rejouée est acheminée via le chemin de distribution en direct (evaluateIMessageInbound + dispatchInboundMessage), donc les listes autorisées, la stratégie de groupe, le debouncer, le cache d’écho et les accusés de réception se comportent de manière identique sur les messages rejoués et les messages en direct.
Le rattrapage conserve un curseur par compte dans l’état du plugin SQLite :
{
"lastSeenMs": 1717900800000,
"lastSeenRowid": 482910,
"updatedAt": 1717900801234,
"failureRetries": { "<guid>": 1 }
}
Le curseur avance à chaque distribution réussie et est maintenu lorsque la distribution d’une ligne échoue — le prochain démarrage réessaie la même ligne à partir du curseur maintenu.
Une fois la requête de rattrapage au démarrage réussie, les lignes ultérieures gérées en direct avancent également le même curseur pour qu’un redémarrage de la passerelle ne rejoue pas les messages qui ont déjà été gérés en direct. Les écritures du curseur en direct ne sautent pas par-dessus les échecs de rattrapage qui sont encore en dessous de maxFailureRetries.
Après maxFailureRetries échecs consécutifs sur le même guid, le rattrapage enregistre un warn et force l’avancement du curseur après le message bloqué afin que les démarrages suivants puissent progresser.
Les guids déjà abandonnés sont ignorés à la vue (aucune tentative de distribution) lors des exécutions ultérieures et comptabilisés sous skippedGivenUp dans le résumé de l’exécution.
openclaw doctor --fix importe les fichiers de curseur <openclawStateDir>/imessage/catchup/*.json hérités dans l’état du plugin SQLite et archive les anciens fichiers.
imessage catchup: giving up on guid=<guid> after <N> failures; advancing cursor past it
imessage catchup: fetched <X> rows across chats, capped to perRunLimit=<Y>
Une ligne WARN ... capped to perRunLimit signifie qu’un seul démarrage n’a pas pu vider toute l’arriéré. Augmentez perRunLimit (max 500) si vos écarts dépassent régulièrement la passe par défaut de 50 lignes.
Le Gateway tourne en continu avec un redémarrage automatique par chien de garde et les écarts sont toujours < quelques secondes — la valeur par défaut désactivée convient.
Le volume de DM est faible et les messages manqués ne changeraient pas le comportement de l’agent — la fenêtre initiale firstRunLookbackMinutes peut envoyer un ancien contexte surprenant lors de la première activation.
Lorsque vous activez le rattrapage, le premier démarrage sans curseur ne remonte que firstRunLookbackMinutes (30 min par défaut), et non toute la fenêtre maxAgeMinutes — cela évite de rejouer une longue histoire de messages pré-activation.
Si la sonde signale que RPC n’est pas pris en charge, mettez à jour imsg. Si les actions de l’API privée API ne sont pas disponibles, exécutez imsg launchmacOS dans la session utilisateur macOS connecté et sondez à nouveau. Si le Gateway ne tourne pas sur macOS, utilisez la configuration du Mac distant via SSH ci-dessus au lieu du chemin local par défaut imsg.
Gateway ne tourne pas sur macOS
Le `cliPath: "imsg"` par défaut doit tourner sur le Mac connecté à Messages. Sur Linux ou Windows, définissez `channels.imessage.cliPath` sur un script wrapper qui SSH vers ce Mac et exécute `imsg "$@"`.
#!/usr/bin/env bash
execssh-Tmessages-macimsg"$@"
Ensuite, exécutez :
Fenêtre de terminal
openclawchannelsstatus--probe--channelimessage
DMs are ignored
Vérifiez :
channels.imessage.dmPolicy
channels.imessage.allowFrom
approbations d’appariement (openclaw pairing list imessage)
Group messages are ignored
Vérifiez :
channels.imessage.groupPolicy
channels.imessage.groupAllowFrom
comportement de la liste blanche channels.imessage.groups
configuration du modèle de mention (agents.list[].groupChat.mentionPatterns)
Remote attachments fail
Vérifiez :
channels.imessage.remoteHost
channels.imessage.remoteAttachmentRoots
authentification par clé SSH/SCP depuis l’hôte de la passerelle
la clé d’hôte existe dans ~/.ssh/known_hosts sur l’hôte de la passerelle
lisibilité du chemin distant sur le Mac exécutant Messages
macOS permission prompts were missed
Relancez dans un terminal GUI interactif dans le même contexte utilisateur/session et approuvez les invites :
Fenêtre de terminal
imsgchats--limit1
imsgsend
“test”
Confirmez que l'accès complet au disque + l'automatisation sont accordés pour le contexte de processus qui exécute OpenClaw/`imsg`.