--- summary: "iMessage DM 和组策略、提及门控、每组提示、ACP 绑定和配置写入" read_when: - "决定谁可以向机器人发送消息" - "调试忽略的 DM 或忽略的群组消息" - "将 iMessage 聊天绑定到 ACP 会话" title: "iMessage 访问控制和路由" sidebarTitle: "访问控制" --- 谁被允许,消息如何路由到会话,以及哪些聊天可以写入配置。 ## 访问控制与路由 `channels.imessage.dmPolicy` 控制私信: - `pairing`(默认) - `allowlist`(至少需要一个 `allowFrom` 条目) - `open`(要求 `allowFrom` 包含 `"*"`) - `disabled` 允许列表字段:`channels.imessage.allowFrom`。 允许列表条目必须标识发件人:句柄或静态发件人访问组 (`accessGroup:`)。将 `channels.imessage.groupAllowFrom` 用于聊天目标,例如 `chat_id:*`、`chat_guid:*` 或 `chat_identifier:*`;使用 `channels.imessage.groups` 作为数字 `chat_id` 注册表项。 `channels.imessage.groupPolicy` 控制群组处理: - `allowlist` (默认) - `open` - `disabled` 群组发送者允许列表:`channels.imessage.groupAllowFrom`。 `groupAllowFrom` 条目也可以引用静态发送者访问组(`accessGroup:`)。 运行时回退:如果未设置 `groupAllowFrom`,iMessage 群组发送者检查会使用 `allowFrom`;当 DM 和群组准入需要不同设置时,请设置 `groupAllowFrom`。显式空的 `groupAllowFrom: []` 不会回退——它会在 `allowlist` 下阻止所有群组发送者。 运行时说明:如果 `channels.imessage` 完全缺失,运行时会回退到 `groupPolicy="allowlist"` 并记录警告(即使设置了 `channels.defaults.groupPolicy`)。 `groupPolicy: "allowlist"` 下的群组路由会连续运行 **两个** 门控: 1. **发送者允许列表**(`channels.imessage.groupAllowFrom`)——handle、`accessGroup:`、`chat_guid`、`chat_identifier` 或 `chat_id`。空的有效列表(既没有 `groupAllowFrom` 也没有 `allowFrom` 回退)会阻止每个群组发送者。 2. **群组注册表**(`channels.imessage.groups`)——当映射中有条目时才强制执行:聊天必须匹配明确的按 `chat_id` 配置项,或匹配 `groups: { "*": { ... } }` 通配项。当 `groups` 为空或缺失时,仅由发送者允许列表决定是否准入。 如果未配置有效的组发件人允许列表,则每个组消息都会在注册表门之前被丢弃。每个门在默认日志级别都有自己的 `warn`-level 信号,并且每个门都有不同的修复: - 启动时每个账户只记录一次:当有效的群组发送者允许列表为空时,`imessage: groupPolicy="allowlist" for account "" but no group sender allowlist is configured ...` —— 通过设置 `channels.imessage.groupAllowFrom`(或 `allowFrom`)来修复;仅添加 `groups` 条目会让门控 1 继续阻止所有发送者。 - 运行时每个 `chat_id` 的 one-time,当发送者通过门 1 但填充的 `groups` 注册表中缺少聊天时:`imessage: dropping group message from chat_id= ...` — 通过在 `channels.imessage.groups` 下添加 `chat_id`(或 `"*"`)来修复。 私信不受影响——它们走的是不同的代码路径。 在 `groupPolicy: "allowlist"` 下推荐的群组流配置: ```json5 { channels: { imessage: { groupPolicy: "allowlist", groupAllowFrom: ["+15555550123"], groups: { "*": { "requireMention": true } }, }, }, } ``` 仅 `groupAllowFrom` 就能允许这些发送者进入任何群组;再添加 `groups` 块即可限定允许哪些聊天(并设置诸如 `requireMention` 之类的每聊天选项)。 群组提及门控: - iMessage 没有原生提及元数据 - 提及检测使用`agents.entries.*.groupChat.mentionPatterns`,则`messages.groupChat.mentionPatterns`;如果两者均未设置,则模式源自路由代理的 `identity.name` 和 `identity.emoji` - 默认情况下,groups 需要提及,即使没有显式配置模式也是如此;因此,除非包含客服人员的姓名或表情符号,否则可以跳过列入白名单的发件人的消息 - an 在选定的代理或全局级别显式 `mentionPatterns: []` 抑制源自身份的模式;当没有可用模式剩余时,iMessage 无法强制提及门控 - 来自授权发送者的控制命令会绕过提及门控 要处理来自一个组中允许的发件人的每条消息,请将该聊天的 `requireMention` 设置为 `false`: ```json5 { channels: { imessage: { groupPolicy: "allowlist", groupAllowFrom: ["+15555550123", "+15555550124"], groups: { "*": {}, "123": { requireMention: false }, }, }, }, } ``` 将 `123` 替换为 `imsg chats --limit 20 --json` 中的数字聊天 ID。编辑已提供该帐户组策略的映射:`channels.imessage.groups` 或 `channels.imessage.accounts..groups`(当它覆盖根映射时)。这也适用于`accounts.default.groups`;仅仅拥有一个帐户条目并不意味着需要它自己的 `groups` 地图。仅当最多配置一个帐户时,空帐户映射才会继承根映射。 要仅在由 OpenClaw 启动的本机回复线程中允许未提及的后续操作,请在该组条目中将 `requireMentionInBotThreads: false` 与 `requireMention: true` 一起设置。确切的组设置会覆盖 `groups["*"].requireMentionInBotThreads`。将其设置为 `true` 以要求在这些线程中提及,或忽略它以保留正常的提及行为。发件人和群组限制仍然适用。 当提及模式被禁用时,显式的 `requireMentionInBotThreads: true` 仍然强制执行。配置可用的提及模式来解决这些线程中的机器人;否则,除了授权的控制命令外,它们会保持安静。 线程所有权来自本机线程根 GUID 和 OpenClaw 的帐户和会话范围的发送消息缓存。缓存最多可保留 2,000 条消息长达 6 小时,并且在该窗口内重新启动后仍可保留。未知或被驱逐的根保留正常的提及要求。在其他人的线程中回复机器人消息并不会使该线程归机器人所有。 保留现有通配符和每个组的设置,仅更改目标聊天的 `requireMention`。帐户映射会替换整个继承的映射,因此,如果您有意创建特定于帐户的覆盖,请首先复制完整的继承映射,包括所有通配符和每组策略。当之前没有应用地图时,`"*": {}` 保留其他组的入场许可,同时保留其默认提及要求。保持受限地图的限制。 `groupAllowFrom` 仍控制发件人访问。 未提及的跳过消息会在聊天 ID 和 `requireMention: false` 修复的默认日志级别产生警告。同一聊天的重复警告会被有限的内存缓存所抑制;重新启动通道或逐出缓存条目会再次发出警告。 每组 `systemPrompt`: `channels.imessage.groups.*` 下的每个条目都接受一个可选的 `systemPrompt` 字符串,该字符串会在每一轮处理该群组消息时注入到代理的系统提示词中。解析方式与 `channels.whatsapp.groups` 一致: 1. **特定组系统提示**(`groups[""].systemPrompt`):当映射中存在特定组条目**和**时使用,其`systemPrompt`键被定义。如果 `systemPrompt` 是空字符串 (`""`),则禁止通配符,并且不会向该组应用系统提示。 2. **组通配系统提示词**(`groups["*"].systemPrompt`):当特定组条目在映射中完全不存在,或者它存在但未定义 `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: "", }, }, }, }, } ``` 每组提示词仅适用于群组消息——私信不受影响。 - 私信使用直接路由;群组使用群组路由。 - 在默认 `session.dmScope=main` 下,iMessage 私信会合并到代理主会话中。 - 群组会话相互隔离(`agent::imessage:group:`)。 - 回复使用原始 channel/target 元数据路由回 iMessage。 - `chat_id`、`chat_guid` 和 `chat_identifier` 是传递选择器,而不是组标记。出站会话路由通过帐户的消息聊天列表解析聊天:一对一聊天使用规范化句柄的直接会话,群组使用数字聊天 ID。未解析的选择器不会创建猜测的会话。 - 旧版本可能创建了额外的组会话,其中包含用于一对一聊天的传递镜像。此修复可防止新的错误分类镜像;它保留现有的会话历史记录,而不是自动合并或删除这些行。 类群组线程行为: 某些多参与者 iMessage 线程可能会带着 `is_group=false` 到达。 如果该 `chat_id` 在 `channels.imessage.groups` 中被显式配置,OpenClaw 会将其视为群组流量(群组门控 + 群组会话隔离)。 ## ACP 会话绑定 iMessage 聊天可以绑定到 ACP 会话。 快速操作流程: - 在DM或允许的群聊中运行`/acp spawn codex --bind here`。 - 之后同一 iMessage 会话中的消息将路由到生成的 ACP 会话。 - `/new` 和 `/reset` 会就地重置同一个已绑定的 ACP 会话。 - `/acp close` 会关闭 ACP 会话并移除绑定。 已配置的持久绑定使用顶层 `bindings[]` 条目,其中 `type: "acp"` 且 `match.channel: "imessage"`。 `match.peer.id` 可以使用: - 标准化DM手柄,例如`+15555550123`或`user@example.com` - `chat_id:`(推荐用于稳定的群组绑定) - `chat_guid:` - `chat_identifier:` 示例: ```json5 { agents: { entries: { 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" }, }, ], } ``` 有关共享 ACP 绑定行为,请参阅 [ACP Agents](/tools/acp-agents)。 ## 配置写入 iMessage 默认允许由频道发起的配置写入(用于 `/config set|unset`,当 `commands.config: true` 时)。 禁用: ```json5 { channels: { imessage: { configWrites: false, }, }, } ```