Summary
On OpenClaw 2026.6.5, iMessage inbound messages can be received and processed successfully, but final reply delivery can fail on macOS systems with System Integrity Protection enabled. The delivery layer attempts to send the final response as a threaded/native reply by passing reply_to/replyToId to the iMessage sender. The imsg bridge then refuses because threaded/private Messages.app injection requires SIP to be disabled.
This happens even when channels.imessage.actions.reply is configured as false.
Environment
- OpenClaw: 2026.6.5
- Platform: macOS, LaunchAgent gateway
- iMessage bridge:
imsg 0.9.0
- SIP: enabled
- iMessage private API probe: unavailable, but normal send RPC methods are listed
Observed Behaviour
An iMessage group message was ingested and processed. OpenClaw created iMessage reply-cache/catchup state for the inbound message, then final delivery failed with:
imessage final reply failed: OutboundDeliveryError: System Integrity Protection (SIP) is enabled. Refusing to inject into Messages.app. Disable SIP in Recovery mode before using `imsg launch`.
The channel config had:
{
"channels": {
"imessage": {
"actions": {
"reply": false
}
}
}
}
The iMessage config schema rejects channels.imessage.replyToMode, so there does not appear to be a supported config-level way to force final responses to degrade to plain top-level sends.
Expected Behaviour
If iMessage private API support is unavailable, or channels.imessage.actions.reply is false, OpenClaw should not pass reply_to/replyToId into final iMessage delivery. It should send a normal top-level iMessage instead.
Alternatively, the iMessage schema should expose a supported replyToMode: "off" option if the common channel reply-threading resolver is going to default to reply threading.
Local Hotfix Tested
A local patch in dist/send-DpmbO1o_.js changed:
const resolvedReplyToId = sanitizeReplyToId(opts.replyToId);
to:
const replyActionsEnabled = account.config.actions?.reply !== false;
const resolvedReplyToId = replyActionsEnabled ? sanitizeReplyToId(opts.replyToId) : void 0;
A no-send fake-client check confirmed that when actions.reply === false, the generated send RPC params no longer contain reply_to.
Related
There is an older closed issue about inbound iMessage reply context:
#10872
This issue is separate: outbound final response delivery attempts a SIP-gated native/threaded reply even when normal top-level iMessage delivery should be sufficient.
Related TTS Schema Gap
While testing the workaround with openclaw message send --channel imessage --target chat_id:2, a separate iMessage-specific issue appeared: global messages.tts.auto = "always" caused OpenClaw to send a generated .caf voice attachment before the text message.
This is undesirable for iMessage, and in this workspace iMessage is explicitly meant to stay text-only. However:
messages.tts schema in 2026.6.5 does not expose a per-channel override such as channelOverrides.imessage.auto = "off".
channels.imessage schema also does not expose a channel-level tts object.
Local hotfix tested:
if (params.channel === "imessage") return params.payload;
inserted at the start of maybeApplyTtsToPayload in dist/tts-runtime-B6XTTTyB.js.
A direct runtime check confirmed that an iMessage payload remains text-only even when global TTS auto mode is always.
Summary
On OpenClaw 2026.6.5, iMessage inbound messages can be received and processed successfully, but final reply delivery can fail on macOS systems with System Integrity Protection enabled. The delivery layer attempts to send the final response as a threaded/native reply by passing
reply_to/replyToIdto the iMessage sender. Theimsgbridge then refuses because threaded/private Messages.app injection requires SIP to be disabled.This happens even when
channels.imessage.actions.replyis configured asfalse.Environment
imsg 0.9.0Observed Behaviour
An iMessage group message was ingested and processed. OpenClaw created iMessage reply-cache/catchup state for the inbound message, then final delivery failed with:
The channel config had:
{ "channels": { "imessage": { "actions": { "reply": false } } } }The iMessage config schema rejects
channels.imessage.replyToMode, so there does not appear to be a supported config-level way to force final responses to degrade to plain top-level sends.Expected Behaviour
If iMessage private API support is unavailable, or
channels.imessage.actions.replyisfalse, OpenClaw should not passreply_to/replyToIdinto final iMessage delivery. It should send a normal top-level iMessage instead.Alternatively, the iMessage schema should expose a supported
replyToMode: "off"option if the common channel reply-threading resolver is going to default to reply threading.Local Hotfix Tested
A local patch in
dist/send-DpmbO1o_.jschanged:to:
A no-send fake-client check confirmed that when
actions.reply === false, the generatedsendRPC params no longer containreply_to.Related
There is an older closed issue about inbound iMessage reply context:
#10872
This issue is separate: outbound final response delivery attempts a SIP-gated native/threaded reply even when normal top-level iMessage delivery should be sufficient.
Related TTS Schema Gap
While testing the workaround with
openclaw message send --channel imessage --target chat_id:2, a separate iMessage-specific issue appeared: globalmessages.tts.auto = "always"caused OpenClaw to send a generated.cafvoice attachment before the text message.This is undesirable for iMessage, and in this workspace iMessage is explicitly meant to stay text-only. However:
messages.ttsschema in 2026.6.5 does not expose a per-channel override such aschannelOverrides.imessage.auto = "off".channels.imessageschema also does not expose a channel-levelttsobject.Local hotfix tested:
inserted at the start of
maybeApplyTtsToPayloadindist/tts-runtime-B6XTTTyB.js.A direct runtime check confirmed that an iMessage payload remains text-only even when global TTS auto mode is
always.