OpenClaw 接入 iMessage:BlueBubbles 频道完整配置、访问控制与高级操作指南
OpenClaw 接入 iMessage:BlueBubbles 频道完整配置、访问控制与高级操作指南
BlueBubbles 是 OpenClaw 官方捆绑(bundled)的 iMessage 接入频道,通过 HTTP REST API 与本机 macOS 上的 BlueBubbles 服务器通信,实现收发消息、打字指示、已读回执、Tapback 反应与消息编辑撤回等能力。本文基于 docs/channels/bluebubbles.md 整理完整配置项与操作流程,并结合仓库插件源码说明其底层原理,帮助你在一台 Mac 上把 OpenClaw 打造成真正可用的 iMessage 智能助手。
架构与工作方式:OpenClaw 如何驱动 iMessage
BlueBubbles 频道的核心思路是"代理桥接":iMessage 消息本身由 macOS 端的 BlueBubbles 辅助应用管理,OpenClaw 只通过 HTTP 与它对话。从插件注册代码 extensions/bluebubbles/index.ts 可以看到,插件在运行时做了两件事:注册频道(api.registerChannel)与注册 Webhook HTTP 处理器(api.registerHttpHandler),前者负责出站调用,后者负责接收入站消息。
具体来说,OpenClaw 依赖以下几类 BlueBubbles REST API 端点:
- 连通性探测:
GET /api/v1/ping,用于网关健康检查与openclaw status状态展示(见 probe.ts); - 发送文本:
POST /api/v1/message/text,携带chatGuid、message等参数(见 send.ts); - 会话级操作:
POST /api/v1/chat/:id/*,包括已读(/read)、打字(/typing)、改名(PUT)、增删成员、退群、设置群头像等(见 chat.ts)。
入站方向完全依赖 Webhook:BlueBubbles 服务器把新消息、消息更新、消息反应推送到 OpenClaw 网关;出站方向(回复、打字指示、已读回执、Tapback)则是 OpenClaw 主动发起的 REST 调用。附件与贴纸会被当作入站媒体摄入,并在可能的情况下以媒体占位符形式呈现给 Agent(源码中会将图片/视频/音频分别格式化为 <media:image>、<media:video>、<media:audio> 等占位符,见 monitor.ts)。
从频道能力声明(channel.ts 的 capabilities 字段)看,该频道原生支持私聊(direct)与群聊(group)、媒体(media)、反应(reactions)、编辑(edit)、撤回(unsend)、回复线程(reply)、消息特效(effects)以及群组管理(groupManagement)。相比传统 imsg 频道,其 API 更丰富、配置更简单,因此被标记为 iMessage 集成的推荐方案(preferOver: ["imessage"])。
系统兼容性:推荐且经过验证的系统是 macOS Sequoia(15)。macOS Tahoe(26)可以运行,但编辑功能目前不可用(Apple 在 26 中移除了相关私有 API),群组头像更新可能显示成功但实际不生效。
快速开始:五分钟接入 iMessage
- 在 Mac 上安装 BlueBubbles 服务器应用,并按其官方安装指引完成基础配置;
- 在 BlueBubbles 的配置中启用 Web API 并设置 API 密码;
- 运行
openclaw onboard并选择 BlueBubbles,或手动写入配置:
{
channels: {
bluebubbles: {
enabled: true,
serverUrl: "http://192.168.1.100:1234",
password: "example-password",
webhookPath: "/bluebubbles-webhook",
},
},
}
- 在 BlueBubbles 中把 Webhook 指向你的网关,例如
https://your-gateway-host:3000/bluebubbles-webhook?password=<password>; - 启动网关。网关会注册该 Webhook 处理器并开始配对流程。
其中 serverUrl 是 BlueBubbles REST API 的基地址,源码在 types.ts 的 normalizeBlueBubblesServerUrl 中会做归一化:未带协议时自动补 http://,并去除末尾多余的 /。password 同时用于 API 调用鉴权(以 query 参数形式附加在每个请求上)与 Webhook 回调鉴权,务必妥善保管。
Onboarding:向导与 CLI 两种配置途径
交互式向导:
openclaw onboard
向导会依次询问以下信息(流程实现在 onboarding.ts 中,含 URL 格式校验与密码必填校验):
- Server URL(必填):BlueBubbles 服务器地址,如
http://192.168.1.100:1234,可在 BlueBubbles 应用的 Connection 设置中查看; - Password(必填):BlueBubbles 服务器设置中的 API 密码;
- Webhook path(可选):默认
/bluebubbles-webhook,自定义时必须/开头; - DM policy:
pairing、allowlist、open、disabled; - Allow list:手机号、邮箱或聊天目标(支持逗号或换行分隔多条)。
命令行直接添加:
openclaw channels add bluebubbles --http-url http://192.168.1.100:1234 --password <password>
从 channel.ts 的 setup.validateInput 可见,CLI 方式强制要求 --http-url 与 --password 二者齐全,缺一即报错。此外该频道支持多账号:除默认账号外,可通过 channels.bluebubbles.accounts.<id> 配置多个独立的 BlueBubbles 服务器(如多台 Mac),每个账号可独立设置 serverUrl、password、webhookPath 与各自的访问策略。
访问控制:私聊配对、群组策略与提及门控
私聊(DM)策略
- 默认
channels.bluebubbles.dmPolicy = "pairing",即使用配对码做身份交换; - 未知发送者会收到一个配对码,其消息会被忽略,直到通过审批;配对码 1 小时后过期;
- 审批命令:
openclaw pairing list bluebubbles
openclaw pairing approve bluebubbles <CODE>
- 其他取值:
allowlist(仅允许allowFrom中的发送者)、open(所有人)、disabled(关闭私聊)。完整配对流程见 配对指南。
群组策略
channels.bluebubbles.groupPolicy = open | allowlist | disabled,默认allowlist;- 当为
allowlist时,channels.bluebubbles.groupAllowFrom控制哪些发送者可以触发机器人。
提及门控(Mention Gating)
BlueBubbles 支持群聊提及门控,行为与 iMessage/WhatsApp 一致:
- 使用
agents.list[].groupChat.mentionPatterns(或messages.groupChat.mentionPatterns)检测提及; - 当群组开启
requireMention时,Agent 只在被点名时才回复; - 来自已授权发送者的控制命令可以绕过提及门控。
按群组精细化配置示例:
{
channels: {
bluebubbles: {
groupPolicy: "allowlist",
groupAllowFrom: ["+15555550123"],
groups: {
"*": { requireMention: true }, // 所有群默认需要提及
"iMessage;-;chat123": { requireMention: false }, // 特定群覆盖
},
},
},
}
从 config-schema.ts 可见,每组除 requireMention 外还支持 tools: { allow: [], deny: [] } 做工具策略覆盖。群组 ID 使用 chat_guid 或聊天标识(见后文"目标寻址")。群组消息被 allowlist 拦截时,monitor.ts 会打印明确的引导日志,提示你应将该群 ID 加入 groupAllowFrom。
控制命令门控
控制命令(如 /config、/model)要求发送者授权:私聊依据 allowFrom,群聊依据 groupAllowFrom。已授权发送者在群聊中即使未提及也可执行控制命令。底层发送者校验逻辑在 targets.ts 的 isAllowedBlueBubblesSender 中实现:支持 chat_id、chat_guid、chat_identifier、手机号/邮箱句柄多种匹配方式,通配符 * 放行全部。
打字指示、已读回执与流式分块
- 打字指示:在回复生成期间自动发送打字开始事件,由 BlueBubbles 在发送完成或超时后自动清除(手动发送停止事件并不可靠,源码中
DELETE /typing仅作为降级手段,见 chat.ts); - 已读回执:由
channels.bluebubbles.sendReadReceipts控制,默认true,通过POST /api/v1/chat/:id/read实现。
{
channels: {
bluebubbles: {
sendReadReceipts: false, // 关闭已读回执
},
},
}
Block streaming(分块流式发送)控制回复是"一次性整条发送"还是"按块流式发送",默认关闭(false),需要流式回复时必须开启:
{
channels: {
bluebubbles: {
blockStreaming: true,
},
},
}
开启后,流式生成的文本会以分块形式发送到 iMessage,降低首字延迟感知。
高级消息操作(Advanced Actions)
BlueBubbles 频道支持多种原生级消息操作,通过 channels.bluebubbles.actions 统一开关,默认全部开启:
{
channels: {
bluebubbles: {
actions: {
reactions: true, // Tapback 反应(默认 true)
edit: true, // 编辑已发送消息(macOS 13+,macOS 26 Tahoe 上不可用)
unsend: true, // 撤回消息(macOS 13+)
reply: true, // 按消息 GUID 回复线程
sendWithEffect: true, // 消息特效(slam、loud 等)
renameGroup: true, // 重命名群聊
setGroupIcon: true, // 设置群头像/照片(macOS 26 Tahoe 上不稳定)
addParticipant: true, // 添加群成员
removeParticipant: true, // 移除群成员
leaveGroup: true, // 退出群聊
sendAttachment: true, // 发送附件/媒体
},
},
},
}
各操作所需参数如下:
| 操作 | 参数 | 说明 |
|---|---|---|
react |
messageId、emoji、remove |
添加/移除 Tapback 反应,需 BlueBubbles 私有 API(POST /api/v1/message/react) |
edit |
messageId、text |
编辑已发送消息,macOS 26 Tahoe 上不可用 |
unsend |
messageId |
撤回消息 |
reply |
messageId、text、to |
回复指定消息(线程) |
sendWithEffect |
text、to、effectId |
带 iMessage 特效发送 |
renameGroup |
chatGuid、displayName |
重命名群聊 |
setGroupIcon |
chatGuid、media |
设置群头像(macOS 26 Tahoe 上 API 可能返回成功但不同步) |
addParticipant |
chatGuid、address |
添加群成员 |
removeParticipant |
chatGuid、address |
移除群成员 |
leaveGroup |
chatGuid |
退出群聊 |
sendAttachment |
to、buffer、filename、asVoice |
发送媒体/文件 |
消息特效(sendWithEffect)细节:源码 send.ts 内置了一张 Apple 特效 ID 映射表,支持短名自动归一化(大小写、空格、下划线、连字符均可容忍)。气泡特效包括 slam、loud、gentle、invisible-ink;屏幕特效包括 echo、spotlight、balloons、confetti、love/heart/hearts、lasers、fireworks、celebration。传入未知名称时按原文透传。带特效发送与回复线程都要求 method: "private-api",即需要启用 BlueBubbles 私有 API。
语音消息:sendAttachment 设置 asVoice: true,并提供 MP3 或 CAF 格式音频,即可作为 iMessage 语音消息发送——BlueBubbles 会在发送时自动把 MP3 转换为 CAF。
动作自动隐藏:OpenClaw 会依据 BlueBubbles 服务器上报的 macOS 版本(来自 GET /api/v1/server/info 的 os_version,见 probe.ts)自动隐藏已知不可用的操作(如 macOS 26 上的 edit)。若 edit 在 macOS 26 上仍然出现,可手动关闭:channels.bluebubbles.actions.edit=false。
消息 ID:短 ID 与完整 ID 的选择
为节省 Token,OpenClaw 可能向 Agent 暴露短消息 ID(如 1、2)。要点:
MessageSid/ReplyToId可能是短 ID;MessageSidFull/ReplyToIdFull始终是提供方完整 ID;- 短 ID 保存在进程内存中,重启或缓存淘汰后会失效;
- 操作(react/edit/unsend/reply 等)接受短 ID 或完整 ID,但短 ID 若已失效会直接报错。
从 monitor.ts 的实现看,短 ID 由进程内的双向映射表(blueBubblesShortIdToUuid / blueBubblesUuidToShortId)维护:完整 GUID 按序分配递增数字短 ID,缓存上限 2000 条、TTL 6 小时,过期或超限时双向映射会被同步清理;解析时若发现数字型短 ID 已不在映射表中,且调用方要求必须已知(requireKnownShortId: true),会抛出明确错误"使用 MessageSidFull"。
因此,需要持久化或自动化重放的操作,请一律使用完整 ID:
- 模板变量:
{{MessageSidFull}}、{{ReplyToIdFull}} - 入站上下文:
MessageSidFull/ReplyToIdFull
完整模板变量清单见 网关配置文档。
媒体与消息长度限制
- 入站附件会被下载并存入媒体缓存;
- 媒体大小上限:
channels.bluebubbles.mediaMaxMb,默认 8 MB; - 出站文本分块:
channels.bluebubbles.textChunkLimit,默认 4000 字符; - 分块模式:
channels.bluebubbles.chunkMode:length(默认):仅当超出textChunkLimit时才按长度切分;newline:先按空行(段落边界)切分,再做长度切分,适合保留语义的段落式长文。
另外,入站 Webhook 事件默认带有 500ms 的去抖窗口(monitor.ts),用于合并 BlueBubbles 在发送 URL 文本 + 链接预览气泡时产生的两条独立事件;控制命令不参与去抖,会被立即处理。
配置参考(完整清单)
Provider 选项(默认账号直接写于 channels.bluebubbles,多账号场景下对应字段写入 channels.bluebubbles.accounts.<id>):
channels.bluebubbles.enabled:启用/禁用频道。channels.bluebubbles.serverUrl:BlueBubbles REST API 基地址。channels.bluebubbles.password:API 密码。channels.bluebubbles.webhookPath:Webhook 端点路径(默认/bluebubbles-webhook)。channels.bluebubbles.dmPolicy:pairing | allowlist | open | disabled(默认pairing)。channels.bluebubbles.allowFrom:私聊白名单(句柄、邮箱、E.164 号码、chat_id:*、chat_guid:*)。channels.bluebubbles.groupPolicy:open | allowlist | disabled(默认allowlist)。channels.bluebubbles.groupAllowFrom:群组发送者白名单。channels.bluebubbles.groups:按群组配置(requireMention、tools等)。channels.bluebubbles.sendReadReceipts:发送已读回执(默认true)。channels.bluebubbles.blockStreaming:启用分块流式发送(默认false;流式回复必需)。channels.bluebubbles.textChunkLimit:出站分块字符数(默认 4000)。channels.bluebubbles.chunkMode:length(默认)按长度切分;newline先按段落边界切分。channels.bluebubbles.mediaMaxMb:入站媒体大小上限 MB(默认 8)。channels.bluebubbles.historyLimit:群聊上下文保留的最大消息数(0 表示关闭)。channels.bluebubbles.dmHistoryLimit:私聊历史上限。channels.bluebubbles.actions:按操作启用/禁用。channels.bluebubbles.accounts:多账号配置。
相关全局选项:
agents.list[].groupChat.mentionPatterns(或messages.groupChat.mentionPatterns)。messages.responsePrefix。
完整配置体系见 网关配置文档。
目标寻址与投递目标
发送消息时优先使用 chat_guid 以获得稳定路由:
chat_guid:iMessage;-;+15555550123(群聊首选格式)chat_id:123chat_identifier:...- 直接句柄:
+15555550123、user@example.com
从 targets.ts 的解析实现可以确认三种地址形态的语义:
chat_guid是service;separator;identifier三段结构,其中iMessage;-;handle表示私聊(分隔符为-),iMessage;+;groupId表示群聊(分隔符为+);私聊的chat_guid可被归一化为纯句柄参与白名单匹配;chat_id为数值型聊天 ID(兼容chatid:、chat:前缀);chat_identifier为 GUID 结构中的第三段标识(兼容 UUID/hex/chat<digits>形态),并支持imessage:、sms:、auto:服务前缀强制指定发送渠道。
自动建会话:如果直接句柄尚不存在对应的私聊会话,OpenClaw 会通过 POST /api/v1/chat/new 自动创建(携带 addresses 与首条消息,见 send.ts)。该端点要求启用 BlueBubbles 私有 API,未启用时请求会以 400/403 失败并提示。向不存在的句柄发消息时,建议优先检查 BlueBubbles 的私有 API 开关。
安全建议
- Webhook 请求通过比对 query 参数或请求头中的
guid/password与channels.bluebubbles.password完成鉴权。从 monitor.ts 的handleBlueBubblesWebhookRequest可以看到支持guid、passwordquery 参数以及x-guid、x-password、x-bluebubbles-guid、authorization等请求头;无论回环还是代理拓扑,鉴权始终强制开启,无法匹配时返回 401 并在日志中打码记录来源; - 把 API 密码与 Webhook 端点视为凭据,勿泄露到公共配置或聊天记录;
- 如需将 BlueBubbles 服务器暴露到局域网外,请启用 HTTPS 并配置防火墙规则。
故障排查
- 打字/已读事件不工作:检查 BlueBubbles 的 Webhook 日志,确认网关路径与
channels.bluebubbles.webhookPath一致; - 配对码过期:配对码 1 小时后过期,用
openclaw pairing list bluebubbles与openclaw pairing approve bluebubbles <code>重新审批; - 反应不可用:Tapback 依赖 BlueBubbles 私有 API(
POST /api/v1/message/react),确认服务器版本已暴露该端点; - 编辑/撤回失败:需要 macOS 13+ 与兼容的 BlueBubbles 服务器版本;macOS 26(Tahoe)因私有 API 变更,编辑功能当前不可用;
- 群头像不同步:macOS 26(Tahoe)上 API 可能返回成功但图标不更新,属于已知不稳定的表现;
- 查看健康状态:
openclaw status --all或openclaw status --deep,其中会包含对 BlueBubbles 服务器的 ping 探测结果(probe.ts 的/api/v1/ping)。
延伸阅读
- 频道总览:各频道接入方式与通用流程
- 配对与授权指南:配对码、白名单与授权机制
- 网关配置文档:完整配置项与模板变量
- 插件指南:插件化频道的注册与开发模型
- BlueBubbles 插件源码:发送、Webhook、动作与目标解析的完整实现