You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- **iMessage group warnings:** suppress the false drop-all startup warning when an effective group sender allowlist can admit groups, and point true empty-allowlist configurations at the correct remedy. (#100046)
|`channels.bluebubbles.allowFrom`|`channels.imessage.allowFrom`| Same handle formats (`+15555550123`, `[email protected]`). Pairing-store approvals do not transfer — see below. |
|`channels.bluebubbles.groupAllowFrom`|`channels.imessage.groupAllowFrom`| Same. Does not fall back to `allowFrom` — an empty `groupAllowFrom`under `groupPolicy: "allowlist"` drops all groups regardless of `allowFrom`. |
102
+
|`channels.bluebubbles.groupAllowFrom`|`channels.imessage.groupAllowFrom`| Same. When unset, iMessage falls back to `allowFrom`; an explicitly empty `groupAllowFrom: []` blocks all groups under `groupPolicy: "allowlist"`.|
103
103
|`channels.bluebubbles.groups`|`channels.imessage.groups`| Copy the `"*"` wildcard entry verbatim; re-key per-group entries by numeric iMessage `chat_id` — see "Group registry footgun". `requireMention`, `tools`, `toolsBySender`, `systemPrompt` carry over. |
104
104
|`channels.bluebubbles.sendReadReceipts`|`channels.imessage.sendReadReceipts`| Default `true`. With the bundled plugin this only fires when the private API probe is up. |
105
105
|`channels.bluebubbles.includeAttachments`|`channels.imessage.includeAttachments`| Same shape, same off-by-default. If attachments flowed on BlueBubbles, set this explicitly — inbound photos/media are silently dropped (no `Inbound message` log line) until you do. |
@@ -117,38 +117,35 @@ Multi-account configs (`channels.bluebubbles.accounts.*`) translate one-to-one t
117
117
118
118
The bundled iMessage plugin runs two group gates back to back. A group message must pass both to reach the agent:
119
119
120
-
1.**Sender / chat-target allowlist** (`channels.imessage.groupAllowFrom`) — matches the sender handle or the chat target (`chat_id:`, `chat_guid:`, `chat_identifier:` entries). Does not fall back to `allowFrom`: with `groupPolicy: "allowlist"` and an empty `groupAllowFrom`, every group message drops here regardless of `allowFrom`.
120
+
1.**Sender / chat-target allowlist** (`channels.imessage.groupAllowFrom`) — matches the sender handle or the chat target (`chat_id:`, `chat_guid:`, `chat_identifier:` entries). When `groupAllowFrom` is unset, this gate falls back to `allowFrom`; an explicit `groupAllowFrom: []` disables that fallback and drops every group message under `groupPolicy: "allowlist"`.
121
121
2.**Group registry** (`channels.imessage.groups`) — keyed by numeric iMessage `chat_id`:
122
-
- No `groups` block (or an empty one): groups pass this gate as long as gate 1 has a non-empty `groupAllowFrom`; sender filtering governs access. The gateway still logs a startup warning nudging you to add a `groups` block.
122
+
- No `groups` block (or an empty one): groups pass this gate as long as gate 1 has a non-empty effective sender allowlist; sender filtering governs access and no drop-all startup warning fires.
123
123
-`groups` with entries but no `"*"`: only the listed `chat_id` keys pass. Listing any group turns the registry into an allowlist even under `groupPolicy: "open"`.
124
124
-`groups: { "*": { ... } }`: every group passes this gate.
125
125
126
126
The migration trap: BlueBubbles keyed `groups` entries by chat GUID / chat identifier, while the iMessage registry keys by numeric `chat_id`. Per-group entries copied verbatim create a non-empty registry whose keys never match, so every group message drops at gate 2. Copy the `"*"` wildcard verbatim; re-key specific group entries with `chat_id` values from `imsg chats`.
127
127
128
128
Both drop paths are visible at the default log level via `warn` lines:
129
129
130
-
- Once per account at startup, when `groupPolicy: "allowlist"` is set and `channels.imessage.groups`is empty: `imessage: groupPolicy="allowlist" but channels.imessage.groups is empty for account "<id>"`.
130
+
- Once per account at startup, when `groupPolicy: "allowlist"` is set and the effective group sender allowlist is empty: `imessage: groupPolicy="allowlist" for account "<id>" but no group sender allowlist is configured ...`. Set `groupAllowFrom` (or `allowFrom`) to admit senders; adding `groups` alone does not satisfy the sender gate.
131
131
- Once per `chat_id` at runtime, when the registry drops a group: `imessage: dropping group message from chat_id=<id> ... not in channels.imessage.groups allowlist`, naming the exact key to add.
132
132
133
133
DMs keep working either way — they take a different code path, so DM success does not prove group routing.
134
134
135
-
The safe minimum with `groupPolicy: "allowlist"`:
135
+
The minimum sender-scoped config with `groupPolicy: "allowlist"`:
`requireMention: true` under `"*"` is harmless when no mention patterns are configured: the runtime cannot detect mentions without patterns and skips the mention drop. With `agents.list[].groupChat.mentionPatterns` (fallback `messages.groupChat.mentionPatterns`) configured, mention gating applies as expected.
148
+
This admits the configured senders in any group. Add `groups` entries to scope allowed chats or set per-chat options such as `requireMention`; copy the BlueBubbles `"*"` entry verbatim, but re-key specific entries with numeric iMessage `chat_id` values.
152
149
153
150
## Step-by-step
154
151
@@ -182,7 +179,7 @@ The safe minimum with `groupPolicy: "allowlist"`:
182
179
183
180
3.**Verify DMs.** Send the agent a direct message; confirm the reply lands.
184
181
185
-
4.**Verify groups separately.** DMs and groups take different code paths — DM success does not prove groups are routing. Send a message in an allowed group chat and confirm the reply lands. If the group goes silent (no agent reply, no error), check the gateway log for the two `warn` lines from "Group registry footgun" above; either one means the `groups` block is missing, empty, or keyed wrong.
182
+
4.**Verify groups separately.** DMs and groups take different code paths — DM success does not prove groups are routing. Send a message in an allowed group chat and confirm the reply lands. If the group goes silent (no agent reply, no error), check the gateway log for the two `warn` lines from "Group registry footgun" above. The startup warning means the effective sender allowlist is empty; a per-`chat_id` warning means a populated `groups` registry does not contain that chat.
186
183
187
184
5.**Verify the action surface.** From a paired DM, ask the agent to react, edit, unsend, reply, send a photo, and (in a group) rename the group or add/remove a participant. Each action should land natively in Messages.app. If any action throws `iMessage <action> requires the imsg private API bridge`, run `imsg launch` again and refresh with `openclaw channels status --probe`.
Copy file name to clipboardExpand all lines: docs/channels/imessage.md
+6-6Lines changed: 6 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -282,13 +282,13 @@ If disabling SIP is not acceptable for your threat model:
282
282
<Warning>
283
283
Group routing under `groupPolicy: "allowlist"` runs **two** gates back-to-back:
284
284
285
-
1. **Sender allowlist** (`channels.imessage.groupAllowFrom`) — handle, `accessGroup:<name>`, `chat_guid`, `chat_identifier`, or `chat_id`. Empty (and no `allowFrom` fallback) means every group message is dropped (`groupPolicy allowlist (empty groupAllowFrom)` in verbose logs).
286
-
2. **Group registry** (`channels.imessage.groups`) — enforced once the map has entries: the chat must match an explicit per-`chat_id` entry or a `groups: { "*": { ... } }` wildcard (`allowAll`). A group chat that matches neither is dropped. When `groups` is empty or missing, the sender allowlist alone decides admission.
285
+
1. **Sender allowlist** (`channels.imessage.groupAllowFrom`) — handle, `accessGroup:<name>`, `chat_guid`, `chat_identifier`, or `chat_id`. An empty effective list (no `groupAllowFrom` and no `allowFrom` fallback) blocks every group sender.
286
+
2. **Group registry** (`channels.imessage.groups`) — enforced once the map has entries: the chat must match an explicit per-`chat_id` entry or a `groups: { "*": { ... } }` wildcard. When `groups` is empty or missing, the sender allowlist alone decides admission.
287
287
288
-
The plugin emits `warn`-level signals at the default log level:
288
+
If no effective group sender allowlist is configured, every group message is dropped before the registry gate. Each gate has its own `warn`-level signal at the default log level, and each names a different fix:
289
289
290
-
- one-time per account at startup when `groups` is empty: `imessage: groupPolicy="allowlist" but channels.imessage.groups is empty for account "<id>"`
291
-
- one-time per `chat_id` when the registry gate drops a chat: `imessage: dropping group message from chat_id=<id> ...`
290
+
- one-time per account at startup, when the effective group sender allowlist is empty: `imessage: groupPolicy="allowlist" for account "<id>" but no group sender allowlist is configured ...` — fix by setting `channels.imessage.groupAllowFrom` (or `allowFrom`); adding `groups` entries alone leaves gate 1 blocking every sender.
291
+
- one-time per `chat_id` at runtime, when a sender passed gate 1 but the chat is missing from a populated `groups` registry: `imessage: dropping group message from chat_id=<id> ...` — fix by adding that `chat_id` (or `"*"`) under `channels.imessage.groups`.
292
292
293
293
DMs are unaffected — they take a different code path.
294
294
@@ -306,7 +306,7 @@ If disabling SIP is not acceptable for your threat model:
306
306
}
307
307
```
308
308
309
-
If the per-`chat_id` drop lines appear in the gateway log, the registry gate is dropping that chat — add it to `groups` (or add the `"*"` wildcard).
309
+
`groupAllowFrom` alone admits those senders in any group; add the `groups` block to scope which chats are allowed (and to set per-chat options like `requireMention`).
0 commit comments