WhatsApp(Web 通道)集成:登录、收件箱、回复、媒体与运维
状态:仅支持通过 Baileys 接入 WhatsApp Web。会话由 Gateway 统一管理。
新手快速配置
1. 尽量使用 单独的手机号(推荐)。
2. 在 ~/.openclaw/openclaw.json 中配置 WhatsApp。
3. 运行 openclaw channels login 扫码登录(WhatsApp → 设置 → 已链接设备)。
4. 启动 Gateway。
最小配置示例:
{
channels: {
whatsapp: {
dmPolicy: "allowlist",
allowFrom: ["+15551234567"],
},
},
}目标
- 在同一个 Gateway 进程里支持多个 WhatsApp 账号(multi-account)。
- 确定性路由:消息从 WhatsApp 来,就回到 WhatsApp(不让模型选择通道)。
- 模型能看到足够的引用/回复上下文,理解"我在回哪条消息"。
配置写回(Config writes)
默认情况下,WhatsApp 允许把由 /config set|unset 触发的配置更新写回配置文件(需要 commands.config: true)。
禁用:
{
channels: { whatsapp: { configWrites: false } },
}架构(谁负责什么)
- Gateway 负责 Baileys socket 与收件箱循环(inbox loop)。
- CLI / macOS 应用 只与 Gateway 通信,不会直接使用 Baileys。
- 出站发送需要 活跃监听器;否则会快速失败(因为没有 Web 会话)。
获取手机号(两种模式)
WhatsApp 需要真实的手机号码进行验证。VoIP/虚拟号通常会被拦截。OpenClaw 在 WhatsApp 上有两种推荐运行方式:
#
独立号码(推荐)
给 OpenClaw 使用一个 单独号码。体验最好:路由清晰、没有"给自己发消息"的怪异边界情况。理想配置:备用/旧 Android 手机 + eSIM,连上 Wi‑Fi 和电源,通过扫码完成链接。
WhatsApp Business: 同一设备上可以用不同号码同时装 WhatsApp 与 WhatsApp Business。把 OpenClaw 放到 Business 里是很好的隔离方式。
示例配置(独立号码、单用户 allowlist):
{
channels: {
whatsapp: {
dmPolicy: "allowlist",
allowFrom: ["+15551234567"],
},
},
}可选:配对模式(pairing)
如果你想用配对而不是 allowlist,把 channels.whatsapp.dmPolicy 设为 pairing。未知发送者会收到配对码;批准方式:
openclaw pairing approve whatsapp <code>
#
个人号码(兜底)
兜底方案:让 OpenClaw 跑在 你自己的号码 上。测试时可以在 WhatsApp 的 "Message yourself" 里给自己发消息,避免骚扰联系人。配置与实验时你需要在主手机上读取验证码。必须启用 self-chat 模式。
当向导询问你的个人 WhatsApp 号码时,填写"你将从哪个号码给助手发消息"的号码(owner/sender),而不是"助手号码"(因为这里就是同一个号)。
示例配置(个人号 + self-chat):
{
"whatsapp": {
"selfChatMode": true,
"dmPolicy": "allowlist",
"allowFrom": ["+15551234567"]
}
}在 self-chat 模式下,如果没有设置 messages.responsePrefix,回复前缀默认使用 [{identity.name}](否则是 [openclaw])。如需自定义或禁用前缀,请显式设置(用 "" 表示移除)。
#
号码来源建议
- 来自你所在国家运营商的 本地 eSIM(最稳定)
- 奥地利:''hot.at''
- 英国:''giffgaff''(免费 SIM,无合约)
- 预付费 SIM — 只要能接收一次验证短信即可
避免: TextNow、Google Voice、多数"免费短信接收"服务(WhatsApp 封得很狠)。
提示: 号码只需要接收一次验证短信。之后 WhatsApp Web 会话会通过 creds.json 持续存在。
为什么不使用 Twilio?
- 早期 OpenClaw 曾支持 Twilio 的 WhatsApp Business 集成。
- WhatsApp Business 号码并不适合个人助手。
- Meta 强制 24 小时回复窗口;超过 24 小时未互动时,Business 号码无法主动发起新消息。
- 高频/"碎碎念"式使用会触发更激进的封锁,因为 Business 账号并不是用来发送大量个人助手消息的。
- 结果是投递不稳定、封锁频繁,因此已移除支持。
登录与凭据
- 登录命令:openclaw channels login(扫码:Linked Devices)。
- Multi-account login: openclaw channels login --account <id> (<id> = accountId).
- 默认账号:省略 --account 时,若存在 default 则用它,否则按排序取第一个配置的账号 id。
- Credentials storage: ~/.openclaw/credentials/whatsapp/<accountId>/creds.json.
- 备份副本:creds.json.bak(损坏时会用于恢复)。
- 兼容旧版:更早的安装会直接把 Baileys 文件放在 ~/.openclaw/credentials/ 下。
- Logout: openclaw channels logout (or --account <id>) deletes WhatsApp auth state (but keeps shared oauth.json).
- 未登录的 socket 会报错并提示重新链接。
入站流程(私聊 + 群聊)
- WhatsApp 事件来自 Baileys 的 messages.upsert。
- 为避免测试/重启累计事件处理器,关闭时会卸载 inbox listeners。
- 会忽略 status/broadcast chats。
- 私聊使用 E.164;群聊使用 group JID。
- 私聊策略(DM policy):channels.whatsapp.dmPolicy 控制私聊访问(默认 pairing)。
- pairing: unknown senders receive pairing code (openclaw pairing approve whatsapp <code>; expires in 1 hour).
- open:需要 channels.whatsapp.allowFrom 包含 "*"。
- 你自己绑定的 WhatsApp 号码会被隐式信任:自发消息会跳过 dmPolicy 与 allowFrom 校验。
#
个人号模式(兜底)
如果你用 个人 WhatsApp 号码 跑 OpenClaw,启用 channels.whatsapp.selfChatMode(见上面的示例)。
行为:
- 出站私聊不会触发 pairing 回复(避免刷屏联系人)。
- 入站未知发送者仍遵循 channels.whatsapp.dmPolicy。
- self-chat 模式(allowFrom 包含你自己的号)会避免自动已读回执,并忽略 mention JIDs。
- 非 self-chat 私聊会发送已读回执。
已读回执
默认情况下,Gateway 会在消息被接受后把 WhatsApp 入站消息标记为已读(蓝勾)。
全局禁用:
{
channels: { whatsapp: { sendReadReceipts: false } },
}按账号禁用:
{
channels: {
whatsapp: {
accounts: {
personal: { sendReadReceipts: false },
},
},
},
}说明:
- self-chat 模式始终跳过已读回执。
WhatsApp FAQ:发消息与配对
链接 WhatsApp 后,OpenClaw 会给随机联系人发消息吗?
不会。默认私聊策略是 pairing:未知发送者只会收到一个配对码,其消息 不会被处理。OpenClaw 只会回复它收到的聊天,或你显式触发的发送(agent/CLI)。
WhatsApp 的 pairing 是怎么工作的?
pairing 是对未知发送者的私聊门禁:
- 新发送者第一次私聊会收到一个短码(消息不会被处理)。
- Approve: openclaw pairing approve whatsapp <code> (list: openclaw pairing list whatsapp).
- 配对码 1 小时过期;每个通道的待处理请求默认上限是 3 个。
一个 WhatsApp 号能让多人分别使用不同 OpenClaw 实例吗?
可以:通过 ''bindings'' 把不同 sender 路由到不同 agent(peer ''kind: "dm"'',sender 用 ''+1555...'' 这种 E.164)。但回复仍来自 ''同一个 WhatsApp 账号'',且私聊会折叠到各自 agent 的主会话,所以建议 ''一人一个 agent''。私聊访问控制(''dmPolicy''/''allowFrom'')是按 WhatsApp 账号全局生效的。见 ''Multi-Agent Routing''。
向导为什么会问我的手机号?
向导用它来设置你的 owner/allowlist,确保你自己的私聊能被允许。它不会用于自动发送。若你跑在个人号上,就填同一个号码并启用 channels.whatsapp.selfChatMode。
消息归一化(模型看到什么)
- Body 是当前消息正文(带 envelope)。
- 引用/回复上下文会 始终追加:
[Replying to +1555 id:ABC123]
<quoted text or <media:...>>
[/Replying]- 同时会设置 reply 元数据:
- ReplyToId = stanzaId
- ReplyToBody = 引用正文或 media placeholder
- ReplyToSender = 可用时为 E.164
- 纯媒体入站消息会使用占位符:
- <media:image|video|audio|document|sticker>
群聊
- Group session key: agent:<agentId>:whatsapp:group:<jid>.
- 群策略:channels.whatsapp.groupPolicy = open|disabled|allowlist(默认 allowlist)。
- 触发模式:
- mention(默认):需要 @mention 或正则命中。
- always:总是触发。
- /activation mention|always 仅 owner 可用,并且必须作为单独一条消息发送。
- owner = channels.whatsapp.allowFrom(或未设置时用 self E.164)。
- 历史注入(仅 pending):
- 最近未处理消息(默认 50 条)会插入到:
[Chat messages since your last reply - for context]
- 当前消息插入到:
[Current message - respond to this]
- 末尾会追加发送者信息:[from: Name (+E164)]
- 群元数据缓存 5 分钟(主题 + 成员)。
回复投递(线程)
- 当前 gateway 的 WhatsApp Web 出站只发送普通消息(不做 quoted reply 线程化)。
- reply tags 在该通道会被忽略。
确认反应(收到即自动 react)
WhatsApp 可以在收到消息后立刻自动发送一个 emoji 反应(在机器人生成回复之前),让用户马上知道"消息已收到"。
配置:
{
"whatsapp": {
"ackReaction": {
"emoji": "👀",
"direct": true,
"group": "mentions"
}
}
}选项:
- emoji(string):用于确认的 Emoji(如 "👀"、"✅"、"📨")。为空或省略表示禁用。
- direct(boolean):对私聊启用(默认:true)。
- group(string|boolean):对群聊启用。"mentions" = 仅被 @ 时;true = 总是;false = 禁用(默认:"mentions")。