OpenClaw iMessage message behaviour
Coalescing a command and its URL preview into one inbound message, and automatic inbound recovery after a bridge or gateway restart with durable replay protection, the rowid cursor, the stale-backlog age fence, the local versus remote windows, the operator log line and the retired catch-up keys
Two things happen to an iMessage before the agent sees it: rows that Apple split get joined back together, and rows that arrived while the gateway was down get replayed, but only the ones worth replaying. The second is where the design shows, because Apple's Push layer can flush hours of stale history the moment a bridge reconnects. Here is the coalescing rule, the recovery mechanism, the two windows, and the log line to watch.
Coalescing split sends
- Apple can store a command and its URL preview as separate physical rows in the chat database, and imsg 0.13.1 and newer coalesces those rows before watch, history or search returns the message, so OpenClaw receives one logical inbound message without adding channel-specific DM latency.
- No coalescing setting is needed: the retired same-sender DM coalescing key is removed by the doctor fix, and the generic inbound debounce remains for deliberately batching rapid text messages across a channel.
- If a command-plus-URL send still arrives as two agent turns, the fix is to update imsg on the Messages Mac through Homebrew.
- Recovery after a bridge or gateway restart is always on, built on durable ingress plus an age fence, and it both recovers messages missed during downtime and suppresses the stale backlog bomb Apple can flush after a Push recovery.
Run the gateway on the Messages Mac for the wider recovery window.
How recovery works
Before advancing the recovery cursor, OpenClaw journals each raw row in the shared SQLite ingress queue with its Apple GUID as the event ID; a completed row leaves a tombstone for about four hours, capped at ten thousand entries, so a replay with the same GUID is dropped even after a restart, and a pending row stays recoverable until dispatch adopts it. On startup the monitor remembers the last durably admitted database rowid, a persisted per-account cursor, and passes it to the watch subscription as the starting rowid, so imsg replays the rows not yet journaled and then tails live, rows journaled before a crash resume from SQLite, and replay is bounded to the most recent five hundred rows and to messages up to about two hours old, with GUID tombstones dropping anything already handled. Rows above the startup boundary are genuinely live, and one whose send date is more than about fifteen minutes older than its arrival is the Push-flush backlog and is suppressed, while replayed rows at or below the boundary use the wider recovery window, so a recently missed message is delivered and ancient history is not.
Windows, signal, migration
- Recovery works over local and remote CLI paths because the rowid replay runs over the same imsg RPC connection, and the difference is the window: when the gateway can read the chat database locally it anchors the startup boundary, caps the replay span and delivers missed messages up to a couple of hours old, whereas over a remote SSH path it cannot read the database, so the replay is uncapped and every row uses the live age fence, still recovering recent misses and suppressing old backlog with the narrower window; running the gateway on the Messages Mac gives the wider window.
- Suppressed backlog is logged at the default level rather than silently dropped, with the account, the send time, a recovery flag showing which window applied, and a running count of suppressed rows since start.
- The catch-up block is deprecated because downtime recovery is automatic: an existing config with catch-up enabled is honoured as a compatibility profile for the replay window, and disabled or unset catch-up blocks are retired and removed by the doctor fix.
OpenClaw on iMessage is the channel post this behaviour belongs to, and OpenClaw iMessage setup where the local and remote paths that decide the window are configured.
Replay what was missed, not what was flushed
The fifteen-minute fence is the whole trick: a message that was sent long before it arrived is not a missed message, it is Apple catching up, and treating it as new would make the agent answer last week's chat. OpenClaw Telegram message behaviour shows the durable queue on Telegram that the same ingress layer serves, and OpenClaw iMessage troubleshooting what to check when inbound stops arriving at all.
On Diali
iMessage is not among the channels Diali connects today: WhatsApp, Telegram, Discord, Slack, Mattermost, Matrix, SMS and voice. Hosted OpenClaw on Diali is the assistant and Diali security describes the boundary that applies to each connected channel.
- Command plus URL is one message once imsg is current.
- GUID tombstones for four hours; five hundred rows and two hours of replay.
- Fifteen minutes older than its arrival means backlog, not a message.
Stop reading about it, build one
Set up an agent, pick a channel, and have it working inside the app you already keep open.
