Naar hoofdinhoud gaan
Gebruik voor OpenClaw iMessage-implementaties imsg op een macOS Messages-host waarop is ingelogd. Als je Gateway op Linux of Windows draait, wijs channels.imessage.cliPath naar een SSH-wrapper die imsg op de Mac uitvoert.Inkomend herstel is automatisch. Na een herstart van een bridge of gateway speelt iMessage de berichten opnieuw af die zijn gemist terwijl deze offline was en onderdrukt het de verouderde “backlog bomb” die Apple na een Push-herstel kan wegspoelen, met deduplicatie zodat niets twee keer wordt verzonden. Er is geen configuratie om dit in te schakelen — zie Inkomend herstel na een herstart van een bridge of gateway.
Ondersteuning voor BlueBubbles is verwijderd. Migreer channels.bluebubbles-configuraties naar channels.imessage; OpenClaw ondersteunt iMessage alleen via imsg. Begin met Verwijdering van BlueBubbles en het imsg iMessage-pad voor de korte aankondiging, of Overstappen vanaf BlueBubbles voor de volledige migratietabel.
Status: native externe CLI-integratie. Gateway start imsg rpc en communiceert via JSON-RPC over stdio (geen afzonderlijke daemon/poort). Geavanceerde acties vereisen imsg launch en een geslaagde private API-probe.

Private API-acties

Antwoorden, tapbacks, effecten, peilingen, bijlagen en groepsbeheer.

Koppelen

iMessage-DM’s gebruiken standaard de koppelingsmodus.

Externe Mac

Gebruik een SSH-wrapper wanneer de Gateway niet op de Messages-Mac draait.

Configuratiereferentie

Volledige referentie voor iMessage-velden.

Snelle setup

1

Installeer en verifieer imsg

brew install steipete/tap/imsg
imsg rpc --help
imsg launch
openclaw channels status --probe
2

Configureer OpenClaw

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

Start gateway

openclaw gateway
4

Keur eerste DM-koppeling goed (standaard dmPolicy)

openclaw pairing list imessage
openclaw pairing approve imessage <CODE>
Koppelingsverzoeken verlopen na 1 uur.

Vereisten en machtigingen (macOS)

  • Messages moet zijn ingelogd op de Mac waarop imsg draait.
  • Full Disk Access is vereist voor de procescontext waarin OpenClaw/imsg draait (toegang tot de Messages-database).
  • Automatiseringsmachtiging is vereist om berichten via Messages.app te verzenden.
  • Voor geavanceerde acties (reageren / bewerken / verzenden ongedaan maken / antwoord in thread / effecten / peilingen / groepsbewerkingen) moet System Integrity Protection zijn uitgeschakeld — zie De imsg private API inschakelen hieronder. Basisfunctionaliteit voor tekst en media verzenden/ontvangen werkt zonder dit.
Machtigingen worden per procescontext verleend. Als gateway headless draait (LaunchAgent/SSH), voer dan een eenmalige interactieve opdracht uit in diezelfde context om prompts te activeren:
imsg chats --limit 1
# or
imsg send <handle> "test"
Een remote-SSH-setup kan chats lezen, channels status --probe doorstaan en inkomende berichten verwerken terwijl uitgaande verzendingen nog steeds mislukken met een AppleEvents-autorisatiefout:
Not authorized to send Apple events to Messages. (-1743)
Controleer de TCC-database van de ingelogde Mac-gebruiker of System Settings > Privacy & Security > Automation. Als de Automation-vermelding is vastgelegd voor /usr/libexec/sshd-keygen-wrapper in plaats van voor het imsg- of lokale shellproces, toont macOS mogelijk geen bruikbare Messages-schakelaar voor die server-side SSH-client:
kTCCServiceAppleEvents | /usr/libexec/sshd-keygen-wrapper | auth_value=0 | com.apple.MobileSMS
In die toestand kan het blijven mislukken om tccutil reset AppleEvents te herhalen of imsg send opnieuw via dezelfde SSH-wrapper uit te voeren, omdat de procescontext die Messages Automation nodig heeft de SSH-wrapper is, niet een app waaraan de UI toegang kan verlenen.Gebruik in plaats daarvan een van de ondersteunde imsg-procescontexten:
  • Draai de Gateway, of ten minste de imsg-bridge, in de lokale sessie van de ingelogde Messages-gebruiker.
  • Start de Gateway met een LaunchAgent voor die gebruiker nadat Full Disk Access en Automation vanuit dezelfde sessie zijn verleend.
  • Als je de SSH-topologie met twee gebruikers behoudt, verifieer dan dat een echte uitgaande imsg send via exact dezelfde wrapper slaagt voordat je het kanaal inschakelt. Als Automation niet kan worden verleend, configureer dan opnieuw naar een imsg-setup met één gebruiker in plaats van voor verzendingen op de SSH-wrapper te vertrouwen.

De imsg private API inschakelen

imsg wordt geleverd in twee operationele modi:
  • Basismodus (standaard, geen SIP-wijzigingen nodig): uitgaande tekst en media via send, inkomende watch/history, chatlijst. Dit krijg je direct na een nieuwe brew install steipete/tap/imsg plus de standaard macOS-machtigingen hierboven.
  • Private API-modus: imsg injecteert een helper-dylib in Messages.app om interne IMCore-functies aan te roepen. Dit ontgrendelt react, edit, unsend, reply (threaded), sendWithEffect, poll en poll-vote (native Messages-peilingen), renameGroup, setGroupIcon, addParticipant, removeParticipant, leaveGroup, plus type-indicatoren en leesbevestigingen.
Om het geavanceerde actieoppervlak te bereiken dat deze kanaalpagina documenteert, heb je Private API-modus nodig. De imsg README is expliciet over de vereiste:
Geavanceerde functies zoals read, typing, launch, bridge-backed rijke verzending, berichtmutatie en chatbeheer zijn opt-in. Ze vereisen dat SIP is uitgeschakeld en dat een helper-dylib in Messages.app wordt geïnjecteerd. imsg launch weigert te injecteren wanneer SIP is ingeschakeld.
De helper-injectietechniek gebruikt de eigen dylib van imsg om Messages private APIs te bereiken. Er is geen externe server of BlueBubbles-runtime in het OpenClaw iMessage-pad.
SIP uitschakelen is een echte beveiligingsafweging. SIP is een van de kernbeschermingen van macOS tegen het uitvoeren van gewijzigde systeemcode; het systeembreed uitschakelen opent extra aanvalsvlak en bijwerkingen. Met name het uitschakelen van SIP op Apple Silicon-Macs schakelt ook de mogelijkheid uit om iOS-apps op je Mac te installeren en uit te voeren.Behandel dit als een bewuste operationele keuze, niet als standaard. Als je dreigingsmodel niet kan tolereren dat SIP uit staat, is gebundelde iMessage beperkt tot basismodus — alleen tekst en media verzenden/ontvangen, geen reacties / bewerken / verzenden ongedaan maken / effecten / groepsbewerkingen.

Setup

  1. Installeer (of upgrade) imsg op de Mac waarop Messages.app draait:
    brew install steipete/tap/imsg
    imsg --version
    imsg status --json
    
    De uitvoer van imsg status --json rapporteert bridge_version, rpc_methods en per methode selectors, zodat je kunt zien wat de huidige build ondersteunt voordat je begint.
  2. Schakel System Integrity Protection uit, en (op moderne macOS) Library Validation. Het injecteren van een niet-Apple helper-dylib in de door Apple ondertekende Messages.app vereist dat SIP uit staat en dat library validation is versoepeld. De SIP-stap in Recovery-modus is macOS-versiespecifiek:
    • macOS 10.13-10.15 (Sierra-Catalina): schakel Library Validation uit via Terminal, herstart naar Recovery Mode, voer csrutil disable uit, herstart.
    • macOS 11+ (Big Sur en later), Intel: Recovery Mode (of Internet Recovery), csrutil disable, herstart.
    • macOS 11+, Apple Silicon: opstartreeks met de aan/uit-knop om Recovery te openen; houd op recente macOS-versies de Left Shift-toets ingedrukt wanneer je op Continue klikt, daarna csrutil disable. Virtual-machine-setups volgen een aparte flow, dus maak eerst een VM-snapshot.
    Op macOS 11 en later is alleen csrutil disable meestal niet genoeg. Apple handhaaft library validation nog steeds tegen Messages.app als platform binary, waardoor een adhoc-ondertekende helper wordt geweigerd (Library Validation failed: ... platform binary, but mapped file is not), zelfs met SIP uit. Schakel na het uitschakelen van SIP ook library validation uit en herstart:
    sudo defaults write /Library/Preferences/com.apple.security.libraryvalidation.plist DisableLibraryValidation -bool true
    
    macOS 26 (Tahoe), geverifieerd op 26.5.1: SIP uit plus de bovenstaande DisableLibraryValidation-opdracht is voldoende om de helper te injecteren in 26.0 tot en met 26.5.x. Er zijn geen boot-args vereist. De plist is de doorslaggevende factor en de meest voorkomende ontbrekende stap wanneer injectie mislukt op Tahoe:
    • Met de plist: imsg launch injecteert en imsg status rapporteert advanced_features: true.
    • Zonder de plist (zelfs met SIP uit): imsg launch mislukt met Failed to launch: Timeout waiting for Messages.app to initialize. AMFI weigert de adhoc-helper bij het laden, waardoor de bridge nooit gereed wordt en de launch time-out. Die time-out is het symptoom dat de meeste mensen op Tahoe tegenkomen, en de oplossing is de plist hierboven, niet iets ingrijpenders.
    Dit is bevestigd met een gecontroleerde voor/na-test op macOS 26.5.1 (Apple Silicon): met de plist wordt de dylib in Messages.app gemapt en komt de bridge op; verwijder de plist en herstart, en imsg launch produceert de bovenstaande time-outfout zonder dat de dylib wordt gemapt. Als imsg launch-injectie of specifieke selectors na een macOS-upgrade false beginnen terug te geven, is deze gate meestal de oorzaak. Controleer je SIP- en library-validation-status voordat je aanneemt dat de SIP-stap zelf is mislukt. Als die instellingen correct zijn en de bridge nog steeds niet kan injecteren, verzamel dan imsg status --json plus de uitvoer van imsg launch en meld dit aan het imsg-project in plaats van extra systeembrede beveiligingsmaatregelen te verzwakken. Volg Apple’s Recovery-mode-flow voor je Mac om SIP uit te schakelen voordat je imsg launch uitvoert.
  3. Injecteer de helper. Met SIP uitgeschakeld en Messages.app aangemeld:
    imsg launch
    
    imsg launch weigert te injecteren wanneer SIP nog steeds is ingeschakeld, dus dit dient ook als bevestiging dat stap 2 is gelukt.
  4. Verifieer de bridge vanuit OpenClaw:
    openclaw channels status --probe
    
    De iMessage-vermelding zou works moeten rapporteren, en imsg status --json | jq '{rpc_methods, selectors}' zou de mogelijkheden moeten tonen die door je macOS-build worden blootgesteld. Poll-aanmaak vereist selectors.pollPayloadMessage; stemmen vereist zowel selectors.pollVoteMessage als de poll.vote-RPC-methode. De OpenClaw-Plugin adverteert alleen acties die worden ondersteund door de gecachte probe, terwijl een lege cache optimistisch blijft en bij de eerste dispatch probet.
Als openclaw channels status --probe het kanaal als works rapporteert maar specifieke acties tijdens dispatch “iMessage <action> requires the imsg private API bridge” gooien, voer dan imsg launch opnieuw uit — de helper kan wegvallen (herstart van Messages.app, OS-update, enz.) en de gecachte available: true-status blijft acties adverteren totdat de volgende probe wordt vernieuwd.

Wanneer je SIP niet kunt uitschakelen

Als SIP-uitgeschakeld niet acceptabel is voor je dreigingsmodel:
  • imsg valt terug naar basismodus — alleen tekst + media + ontvangen.
  • De OpenClaw-Plugin adverteert nog steeds tekst/media verzenden en inkomende monitoring; hij verbergt alleen react, edit, unsend, reply, sendWithEffect en groepsbewerkingen uit het actieoppervlak (volgens de capability-gate per methode).
  • Je kunt een aparte niet-Apple-Silicon Mac (of een dedicated bot-Mac) met SIP uit gebruiken voor de iMessage-workload, terwijl SIP op je primaire apparaten ingeschakeld blijft. Zie Dedicated bot macOS user (separate iMessage identity) hieronder.

Toegangscontrole en routering

channels.imessage.dmPolicy beheert directe berichten:
  • pairing (standaard)
  • allowlist
  • open (vereist dat allowFrom "*" bevat)
  • disabled
Allowlist-veld: channels.imessage.allowFrom.Allowlist-vermeldingen moeten afzenders identificeren: handles of statische toegangsroepen voor afzenders (accessGroup:<name>). Gebruik channels.imessage.groupAllowFrom voor chatdoelen zoals chat_id:*, chat_guid:* of chat_identifier:*; gebruik channels.imessage.groups voor numerieke chat_id-registersleutels.

ACP-gespreksbindingen

Verouderde iMessage-chats kunnen ook aan ACP-sessies worden gebonden. Snelle operatorflow:
  • Voer /acp spawn codex --bind here uit binnen de DM of toegestane groepschat.
  • Toekomstige berichten in datzelfde iMessage-gesprek worden naar de gespawnde ACP-sessie gerouteerd.
  • /new en /reset resetten dezelfde gebonden ACP-sessie ter plekke.
  • /acp close sluit de ACP-sessie en verwijdert de binding.
Geconfigureerde persistente bindingen worden ondersteund via top-level bindings[]-vermeldingen met type: "acp" en match.channel: "imessage". match.peer.id kan het volgende gebruiken:
  • genormaliseerde DM-handle zoals +15555550123 of user@example.com
  • chat_id:<id> (aanbevolen voor stabiele groepsbindingen)
  • chat_guid:<guid>
  • chat_identifier:<identifier>
Voorbeeld:
{
  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" },
    },
  ],
}
Zie ACP-agenten voor gedeeld gedrag van ACP-bindingen.

Deploymentpatronen

Gebruik een dedicated Apple ID en macOS-gebruiker zodat botverkeer is geïsoleerd van je persoonlijke Messages-profiel.Typische flow:
  1. Maak een dedicated macOS-gebruiker aan of meld je daarmee aan.
  2. Meld je in Messages aan met de Apple ID van de bot in die gebruiker.
  3. Installeer imsg in die gebruiker.
  4. Maak een SSH-wrapper zodat OpenClaw imsg in die gebruikerscontext kan uitvoeren.
  5. Wijs channels.imessage.accounts.<id>.cliPath en .dbPath naar dat gebruikersprofiel.
De eerste uitvoering kan GUI-goedkeuringen vereisen (Automation + Full Disk Access) in die botgebruikerssessie.
Veelvoorkomende topologie:
  • Gateway draait op Linux/VM
  • iMessage + imsg draait op een Mac in je tailnet
  • cliPath-wrapper gebruikt SSH om imsg uit te voeren
  • remoteHost schakelt SCP-ophalen van bijlagen in
Voorbeeld:
{
  channels: {
    imessage: {
      enabled: true,
      cliPath: "~/.openclaw/scripts/imsg-ssh",
      remoteHost: "bot@mac-mini.tailnet-1234.ts.net",
      includeAttachments: true,
      dbPath: "/Users/bot/Library/Messages/chat.db",
    },
  },
}
#!/usr/bin/env bash
exec ssh -T bot@mac-mini.tailnet-1234.ts.net imsg "$@"
Gebruik SSH-sleutels zodat zowel SSH als SCP niet-interactief zijn. Zorg dat de hostsleutel eerst wordt vertrouwd (bijvoorbeeld ssh bot@mac-mini.tailnet-1234.ts.net) zodat known_hosts wordt gevuld.
iMessage ondersteunt configuratie per account onder channels.imessage.accounts.Elk account kan velden overschrijven zoals cliPath, dbPath, allowFrom, groupPolicy, mediaMaxMb, geschiedenisinstellingen en allowlists voor hoofdlocaties van bijlagen.
Stel channels.imessage.dmHistoryLimit in om nieuwe direct-message-sessies te seeden met recente gedecodeerde imsg-geschiedenis voor dat gesprek. Gebruik channels.imessage.dms["<sender>"].historyLimit voor overrides per afzender, inclusief 0 om geschiedenis voor een afzender uit te schakelen.iMessage-DM-geschiedenis wordt on demand opgehaald uit imsg. Als dmHistoryLimit niet is ingesteld, wordt globale seeding van DM-geschiedenis uitgeschakeld, maar een positieve per-afzender channels.imessage.dms["<sender>"].historyLimit schakelt seeding voor die afzender nog steeds in.

Media, chunking en bezorgdoelen

  • opname van inkomende bijlagen is standaard uitgeschakeld — stel channels.imessage.includeAttachments: true in om foto’s, spraakmemo’s, video en andere bijlagen door te sturen naar de agent. Als dit is uitgeschakeld, worden iMessages die alleen uit bijlagen bestaan verwijderd voordat ze de agent bereiken en produceren ze mogelijk helemaal geen Inbound message-logregel.
  • externe bijlagepaden kunnen via SCP worden opgehaald wanneer remoteHost is ingesteld
  • bijlagepaden moeten overeenkomen met toegestane roots:
    • channels.imessage.attachmentRoots (lokaal)
    • channels.imessage.remoteAttachmentRoots (externe SCP-modus)
    • standaard rootpatroon: /Users/*/Library/Messages/Attachments
  • SCP gebruikt strikte hostkeycontrole (StrictHostKeyChecking=yes)
  • grootte van uitgaande media gebruikt channels.imessage.mediaMaxMb (standaard 16 MB)
  • limiet voor tekstchunks: channels.imessage.textChunkLimit (standaard 4000)
  • chunkmodus: channels.imessage.chunkMode
    • length (standaard)
    • newline (splitsing waarbij alinea’s eerst worden gebruikt)
Voorkeur voor expliciete doelen:
  • chat_id:123 (aanbevolen voor stabiele routering)
  • chat_guid:...
  • chat_identifier:...
Handledoelen worden ook ondersteund:
  • imessage:+1555...
  • sms:+1555...
  • user@example.com
imsg chats --limit 20

Acties voor private API

Wanneer imsg launch actief is en openclaw channels status --probe privateApi.available: true meldt, kan de berichtentool naast normale tekstverzending ook iMessage-native acties gebruiken.
{
  channels: {
    imessage: {
      actions: {
        reactions: true,
        edit: true,
        unsend: true,
        reply: true,
        sendWithEffect: true,
        sendAttachment: true,
        renameGroup: true,
        setGroupIcon: true,
        addParticipant: true,
        removeParticipant: true,
        leaveGroup: true,
        polls: true,
      },
    },
  },
}
  • react: Voeg iMessage-tapbacks toe of verwijder ze (messageId, emoji, remove). Ondersteunde tapbacks worden gekoppeld aan liefde, leuk, niet leuk, lachen, benadrukken en vraag.
  • reply: Stuur een threaded antwoord op een bestaand bericht (messageId, text of message, plus chatGuid, chatId, chatIdentifier of to).
  • sendWithEffect: Stuur tekst met een iMessage-effect (text of message, effect of effectId).
  • edit: Bewerk een verzonden bericht op ondersteunde macOS-/private API-versies (messageId, text of newText).
  • unsend: Trek een verzonden bericht in op ondersteunde macOS-/private API-versies (messageId).
  • upload-file: Stuur media/bestanden (buffer als base64 of een gehydrateerde media/path/filePath, filename, optioneel asVoice). Legacy-alias: sendAttachment.
  • renameGroup, setGroupIcon, addParticipant, removeParticipant, leaveGroup: Beheer groepschats wanneer het huidige doel een groepsgesprek is.
  • poll: Maak een native Apple Messages-peiling (pollQuestion, pollOption 2 tot 12 keer herhaald, plus chatGuid, chatId, chatIdentifier of to). Ontvangers op iOS/iPadOS/macOS 26+ zien deze native en stemmen native; oudere OS-versies krijgen een tekstfallback “Sent a poll”. Vereist selectors.pollPayloadMessage.
  • poll-vote: Stem op een bestaande peiling (pollId of messageId, plus precies één van pollOptionIndex, pollOptionId of pollOptionText). Vereist selectors.pollVoteMessage en de RPC-methode poll.vote.
Geaccepteerde inkomende peilingen worden voor de agent weergegeven met de vraag, genummerde optielabels, stemtotalen en de bericht-ID van de peiling die nodig is voor poll-vote.
Inkomende iMessage-context bevat zowel korte MessageSid-waarden als volledige bericht-GUID’s wanneer beschikbaar. Korte ID’s zijn beperkt tot de recente SQLite-backed antwoordcache en worden vóór gebruik gecontroleerd tegen de huidige chat. Als een korte ID is verlopen of bij een andere chat hoort, probeer het dan opnieuw met de volledige MessageSidFull.
OpenClaw verbergt private API-acties alleen wanneer de gecachte probestatus zegt dat de bridge niet beschikbaar is. Als de status onbekend is, blijven acties zichtbaar en voeren dispatches probes lazy uit, zodat de eerste actie kan slagen na imsg launch zonder afzonderlijke handmatige statusvernieuwing.
Wanneer de private API-bridge actief is, worden geaccepteerde inkomende chats als gelezen gemarkeerd en tonen directe chats een typballon zodra de turn is geaccepteerd, terwijl de agent context voorbereidt en genereert. Schakel leesmarkering uit met:
{
  channels: {
    imessage: {
      sendReadReceipts: false,
    },
  },
}
Oudere imsg-builds van vóór de mogelijkhedenlijst per methode schakelen typen/lezen stilzwijgend uit; OpenClaw logt één waarschuwing per herstart zodat de ontbrekende bevestiging herleidbaar is.
OpenClaw abonneert zich op iMessage-tapbacks en routeert geaccepteerde reacties als systeemgebeurtenissen in plaats van normale berichttekst, zodat een tapback van een gebruiker geen gewone antwoordlus activeert.Meldingsmodus wordt geregeld door channels.imessage.reactionNotifications:
  • "own" (standaard): meld alleen wanneer gebruikers reageren op berichten die door de bot zijn geschreven.
  • "all": meld alle inkomende tapbacks van geautoriseerde afzenders.
  • "off": negeer inkomende tapbacks.
Overrides per account gebruiken channels.imessage.accounts.<id>.reactionNotifications.
Wanneer approvals.exec.enabled of approvals.plugin.enabled true is en de aanvraag naar iMessage wordt gerouteerd, levert de gateway native een goedkeuringsprompt en accepteert die een tapback om deze op te lossen:
  • 👍 (Like-tapback) → allow-once
  • 👎 (Dislike-tapback) → deny
  • allow-always blijft een handmatige fallback: stuur /approve <id> allow-always als normaal antwoord.
Reactieverwerking vereist dat de handle van de reagerende gebruiker een expliciete goedkeurder is. De lijst met goedkeurders wordt gelezen uit channels.imessage.allowFrom (of channels.imessage.accounts.<id>.allowFrom); voeg het telefoonnummer van de gebruiker toe in E.164-vorm of diens Apple ID-e-mailadres. De wildcardvermelding "*" wordt gehonoreerd, maar staat elke afzender toe om goed te keuren. De reactiesnelkoppeling omzeilt bewust reactionNotifications, dmPolicy en groupAllowFrom, omdat de expliciete allowlist voor goedkeurders de enige gate is die ertoe doet voor het oplossen van goedkeuringen.Gedragswijziging in deze release: Wanneer channels.imessage.allowFrom niet leeg is, wordt de tekstcommand /approve <id> <decision> nu geautoriseerd tegen die lijst met goedkeurders (niet tegen de bredere DM-allowlist). Afzenders die wel op de DM-allowlist staan maar niet in allowFrom, krijgen een expliciete weigering. Voeg elke operator die via /approve (en via reacties) moet kunnen goedkeuren toe aan allowFrom om het eerdere gedrag te behouden. Wanneer allowFrom leeg is, blijft de legacy “same-chat fallback” van kracht en blijft /approve iedereen autoriseren die door de DM-allowlist wordt toegestaan.Operatornotities:
  • De reactiebinding wordt zowel in het geheugen opgeslagen (met een TTL die overeenkomt met de vervaltijd van de goedkeuring) als in de persistente keyed store van de gateway, zodat een tapback die kort na een herstart van de gateway binnenkomt de goedkeuring nog steeds oplost.
  • Cross-device is_from_me=true-tapbacks (de eigen reactie van de operator op een gekoppeld Apple-apparaat) worden bewust genegeerd, zodat de bot zichzelf niet kan goedkeuren.
  • Legacy tekststijl-tapbacks (Liked "…" platte tekst van zeer oude Apple-clients) kunnen geen goedkeuringen oplossen omdat ze geen bericht-GUID dragen; reactieoplossing vereist de gestructureerde tapbackmetadata die huidige macOS-/iOS-clients uitsturen.

Configuratieschrijfacties

iMessage staat standaard door het kanaal geïnitieerde configuratieschrijfacties toe (voor /config set|unset wanneer commands.config: true). Uitschakelen:
{
  channels: {
    imessage: {
      configWrites: false,
    },
  },
}

Split-send-DM’s samenvoegen (command + URL in één compositie)

Wanneer een gebruiker een command en een URL samen typt — bijvoorbeeld Dump https://example.com/article — splitst Apple’s Messages-app de verzending in twee afzonderlijke chat.db-rijen:
  1. Een tekstbericht ("Dump").
  2. Een URL-previewballon ("https://...") met OG-previewafbeeldingen als bijlagen.
De twee rijen komen op de meeste setups ~0,8-2,0 s na elkaar bij OpenClaw aan. Zonder samenvoeging ontvangt de agent alleen het command in turn 1, antwoordt hij (vaak “stuur me de URL”) en ziet hij de URL pas in turn 2 — op dat punt is de commandcontext al verloren. Dit is Apple’s verzendpipeline, niet iets wat OpenClaw of imsg introduceert. channels.imessage.coalesceSameSenderDms laat een DM opeenvolgende rijen van dezelfde afzender bufferen. Wanneer imsg de structurele URL-previewmarkering balloon_bundle_id: "com.apple.messages.URLBalloonProvider" op een van de bronrijen blootlegt, voegt OpenClaw alleen die echte split-send samen en houdt het alle andere gebufferde rijen als afzonderlijke turns. Op oudere imsg-builds die helemaal geen ballonmetadata uitsturen, kan OpenClaw een split-send niet onderscheiden van afzonderlijke verzendingen, dus valt het terug op het samenvoegen van de bucket. Dat behoudt het gedrag van vóór metadata in plaats van Dump <url>-split-sends te laten regresseren naar twee turns. Groepschats blijven per bericht dispatchen zodat de turnstructuur met meerdere gebruikers behouden blijft.
Schakel dit in wanneer:
  • Je skills levert die command + payload in één bericht verwachten (dump, paste, save, queue, enz.).
  • Je gebruikers URL’s naast commands plakken.
  • Je de extra DM-turnlatentie kunt accepteren (zie hieronder).
Laat uitgeschakeld wanneer:
  • Je minimale commandlatentie nodig hebt voor DM-triggers van één woord.
  • Al je flows eenmalige commands zijn zonder payload-follow-ups.

Scenario’s en wat de agent ziet

De kolom “Vlag aan” toont gedrag op een imsg-build die balloon_bundle_id uitstuurt. Op oudere imsg-builds die helemaal geen balloon-metadata uitsturen, vallen de rijen hieronder die zijn gemarkeerd als “Twee beurten” / “N beurten” in plaats daarvan terug op een verouderde samenvoeging (één beurt): OpenClaw kan een gesplitste verzending structureel niet onderscheiden van aparte verzendingen, dus behoudt het de samenvoeging van vóór de metadata. Precieze scheiding wordt actief zodra de build balloon-metadata uitstuurt.
Gebruiker stelt opchat.db produceertVlag uit (standaard)Vlag aan + venster (imsg stuurt balloon-metadata uit)
Dump https://example.com (één verzending)2 rijen met ~1 s ertussenTwee agentbeurten: alleen “Dump”, daarna URLEén beurt: samengevoegde tekst Dump https://example.com
Save this 📎image.jpg caption (bijlage + tekst)2 rijen zonder URL-balloonmetadataTwee beurtenTwee beurten nadat metadata is waargenomen; één samengevoegde beurt in oude/pre-latch sessies zonder metadata
/status (losse opdracht)1 rijDirecte verzendingWacht maximaal tot het venster, verzend daarna
Alleen URL geplakt1 rijDirecte verzendingWacht maximaal tot het venster, verzend daarna
Tekst + URL verzonden als twee bewuste aparte berichten, minuten uit elkaar2 rijen buiten vensterTwee beurtenTwee beurten (venster verloopt ertussen)
Snelle vloed (>10 kleine DM’s binnen venster)N rijen zonder URL-balloonmetadataN beurtenN beurten nadat metadata is waargenomen; één begrensde samengevoegde beurt in oude/pre-latch sessies zonder metadata
Twee mensen typen in een groepschatN rijen van M afzendersM+ beurten (één per afzenderbucket)M+ beurten — groepschats worden niet samengevoegd

Inbound-herstel na een herstart van bridge of Gateway

iMessage herstelt berichten die zijn gemist terwijl de Gateway offline was, en onderdrukt tegelijk de oude “backlogbom” die Apple na een Push-herstel kan doorspoelen. Het standaardgedrag staat altijd aan en is gebouwd op de inbound-dedupe.
  • Replay-dedupe. Elk verzonden inbound-bericht wordt met zijn Apple-GUID vastgelegd in persistente Plugin-status (imessage.inbound-dedupe), geclaimd bij ingestie en vastgelegd na verwerking (vrijgegeven bij een tijdelijke fout zodat het opnieuw kan proberen). Alles wat al is verwerkt, wordt weggegooid in plaats van twee keer verzonden. Hierdoor kan herstel agressief opnieuw afspelen zonder administratie per bericht.
  • Downtime-herstel. Bij het opstarten onthoudt de monitor de laatst verzonden chat.db-rowid (een persistente cursor per account) en geeft die door aan imsg watch.subscribe als since_rowid, zodat imsg de rijen opnieuw afspeelt die binnenkwamen terwijl de Gateway offline was, en daarna live volgt. Replay is begrensd tot de meest recente rijen en tot berichten van maximaal ~2 uur oud, en de dedupe verwijdert alles wat al is verwerkt.
  • Leeftijdsgrens voor oude backlog. Rijen boven de opstartgrens zijn echt live; een rij waarvan de verzenddatum meer dan ~15 minuten ouder is dan de aankomsttijd, is de Push-flush-backlog en wordt onderdrukt. Opnieuw afgespeelde rijen (op of onder de grens) gebruiken in plaats daarvan het bredere herstelvenster, zodat een recent gemist bericht wordt afgeleverd terwijl oude geschiedenis dat niet wordt.
Herstel werkt met zowel lokale als externe cliPath-setups, omdat since_rowid-replay via dezelfde imsg-RPC-verbinding loopt. Het verschil is het venster: wanneer de Gateway chat.db kan lezen (lokaal), verankert deze de opstart-rowid-grens, begrenst de replay-spanne en levert gemiste berichten tot een paar uur oud af. Via een externe SSH-cliPath kan deze de database niet lezen, dus is replay onbeperkt en gebruikt elke rij de live-leeftijdsgrens — het herstelt nog steeds recent gemiste berichten en onderdrukt nog steeds oude backlog, alleen met het smallere livevenster. Voer de Gateway uit op de Messages-Mac voor het bredere herstelvenster.

Operator-zichtbaar signaal

Onderdrukte backlog wordt op het standaardniveau gelogd, nooit stilzwijgend weggegooid (de vlag recovery toont welk venster is toegepast):
imessage: suppressed stale inbound backlog account=<id> sent=<iso> recovery=<bool> (<N> suppressed since start)

Migratie

channels.imessage.catchup.* is verouderd — downtime-herstel is nu automatisch en vereist geen configuratie voor nieuwe setups. Bestaande configuraties met catchup.enabled: true blijven gehonoreerd als compatibiliteitsprofiel voor het herstel-replayvenster. Uitgeschakelde catchup-blokken (enabled: false of geen enabled: true) zijn uitgefaseerd; openclaw doctor --fix verwijdert die.

Probleemoplossing

Valideer de binary en RPC-ondersteuning:
imsg rpc --help
imsg status --json
openclaw channels status --probe
Als de probe meldt dat RPC niet wordt ondersteund, werk imsg bij. Als private-API-acties niet beschikbaar zijn, voer imsg launch uit in de ingelogde macOS-gebruikerssessie en voer de probe opnieuw uit. Als de Gateway niet op macOS draait, gebruik dan de setup Externe Mac via SSH hierboven in plaats van het standaard lokale imsg-pad.
Bewijs eerst of het bericht de lokale Mac heeft bereikt. Als chat.db niet verandert, kan OpenClaw het bericht niet ontvangen, zelfs niet wanneer imsg status --json een gezonde bridge meldt.
imsg chats --limit 10 --json
imsg watch --chat-id <chat-id> --json
sqlite3 ~/Library/Messages/chat.db \
  "select datetime(max(date)/1000000000 + 978307200, 'unixepoch', 'localtime'), max(ROWID) from message;"
Als vanaf de telefoon verzonden berichten geen nieuwe rijen maken, herstel dan de macOS Messages- en Apple Push-laag voordat je de OpenClaw-configuratie wijzigt. Een eenmalige serviceverversing is vaak genoeg:
launchctl kickstart -k system/com.apple.apsd
launchctl kickstart -k gui/$(id -u)/com.apple.CommCenter
launchctl kickstart -k gui/$(id -u)/com.apple.identityservicesd
launchctl kickstart -k gui/$(id -u)/com.apple.imagent
imsg launch
openclaw gateway restart
Verzend een nieuwe iMessage vanaf de telefoon en bevestig een nieuwe chat.db-rij of imsg watch-event voordat je OpenClaw-sessies debugt. Voer dit niet uit als een periodieke bridge-herstartlus; herhaald imsg launch plus Gateway-herstarts tijdens actief werk kunnen afleveringen onderbreken en lopende kanaalruns laten vastlopen.
De standaard cliPath: "imsg" moet draaien op de Mac die bij Messages is aangemeld. Stel op Linux of Windows channels.imessage.cliPath in op een wrapperscript dat via SSH naar die Mac gaat en imsg "$@" uitvoert.
#!/usr/bin/env bash
exec ssh -T messages-mac imsg "$@"
Voer daarna uit:
openclaw channels status --probe --channel imessage
Controleer:
  • channels.imessage.dmPolicy
  • channels.imessage.allowFrom
  • koppelingsgoedkeuringen (openclaw pairing list imessage)
Controleer:
  • channels.imessage.groupPolicy
  • channels.imessage.groupAllowFrom
  • allowlist-gedrag van channels.imessage.groups
  • configuratie van vermeldingspatronen (agents.list[].groupChat.mentionPatterns)
Controleer:
  • channels.imessage.remoteHost
  • channels.imessage.remoteAttachmentRoots
  • SSH/SCP-sleutelauthenticatie vanaf de Gateway-host
  • hostsleutel bestaat in ~/.ssh/known_hosts op de Gateway-host
  • leesbaarheid van externe paden op de Mac waarop Messages draait
Voer opnieuw uit in een interactieve GUI-terminal in dezelfde gebruikers-/sessiecontext en keur prompts goed:
imsg chats --limit 1
imsg send <handle> "test"
Bevestig dat Full Disk Access + Automation zijn toegekend voor de procescontext die OpenClaw/imsg uitvoert.

Verwijzingen naar configuratiereferentie

Gerelateerd