WhatsApp(Web 频道)
状态:生产就绪,基于 WhatsApp Web (Baileys)。Gateway 拥有已关联的会话。
- 配对 — 对未知发送者的默认私信策略为配对模式。
- 频道故障排查 — 跨频道诊断与修复指南。
- Gateway 配置 — 完整的频道配置模式与示例。
快速设置
步骤 1:配置 WhatsApp 访问策略
{
channels: {
whatsapp: {
dmPolicy: "pairing",
allowFrom: ["+15551234567"],
groupPolicy: "allowlist",
groupAllowFrom: ["+15551234567"],
},
},
}
步骤 2:关联 WhatsApp(QR 码)
openclaw channels login --channel whatsapp
指定特定账户:
openclaw channels login --channel whatsapp --account work
步骤 3:启动 Gateway
openclaw gateway
步骤 4:批准首次配对请求(如使用配对模式)
openclaw pairing list whatsapp
openclaw pairing approve whatsapp <CODE>
配对请求在 1 小时后过期。待处理请求上限为每个频道 3 个。
注意: OpenClaw 建议尽可能使用独立号码运行 WhatsApp。(频道元数据和引导流程针对该方案优化,但也支持个人号码方案。)
部署模式
独立号码(推荐)
这是最简洁的运维模式:
- OpenClaw 使用独立的 WhatsApp 身份
- 更清晰的私信白名单和路由边界
- 更低的自聊混淆概率
最小策略模式:
```json5
{
channels: {
whatsapp: {
dmPolicy: "allowlist",
allowFrom: ["+15551234567"],
},
},
}
```
个人号码备选方案
引导向导支持个人号码模式,并写入自聊友好的基线配置:
- `dmPolicy: "allowlist"`
- `allowFrom` 包含你的个人号码
- `selfChatMode: true`
运行时,自聊保护基于关联的自身号码和 `allowFrom`。
WhatsApp Web 专属频道范围
当前 OpenClaw 频道架构中,消息平台频道基于 WhatsApp Web(`Baileys`)。
内置聊天频道注册表中没有单独的 Twilio WhatsApp 消息频道。
运行时模型
- Gateway 拥有 WhatsApp socket 和重连循环。
- 出站发送需要目标账户有活跃的 WhatsApp 监听器。
- 状态和广播聊天被忽略(
@status、@broadcast)。 - 私信使用私信会话规则(
session.dmScope;默认main将私信合并到 Agent 主会话)。 - 群组会话隔离(
agent:<agentId>:whatsapp:group:<jid>)。
访问控制与激活
私信策略
`channels.whatsapp.dmPolicy` 控制私信访问:
- `pairing`(默认)
- `allowlist`
- `open`(需要 `allowFrom` 包含 `"*"`)
- `disabled`
`allowFrom` 接受 E.164 格式号码(内部规范化)。
多账户覆盖:`channels.whatsapp.accounts.<id>.dmPolicy`(和 `allowFrom`)优先于该账户的频道级默认值。
运行时行为细节:
- 配对结果会持久化到频道 allow-store 并与配置的 `allowFrom` 合并
- 如果没有配置白名单,默认允许关联的自身号码
- 出站 `fromMe` 私信不会自动配对
群组策略 + 白名单
群组访问有两层:
1. **群组成员白名单**(`channels.whatsapp.groups`)
- 如果省略 `groups`,所有群组都符合条件
- 如果存在 `groups`,它作为群组白名单(允许 `"*"`)
2. **群组发送者策略**(`channels.whatsapp.groupPolicy` + `groupAllowFrom`)
- `open`:绕过发送者白名单
- `allowlist`:发送者必须匹配 `groupAllowFrom`(或 `*`)
- `disabled`:阻止所有群组入站
发送者白名单回退:
- 如果 `groupAllowFrom` 未设置,运行时会在可用时回退到 `allowFrom`
- 发送者白名单在提及/回复激活之前评估
注意:如果完全没有 `channels.whatsapp` 配置块,运行时群组策略回退为 `allowlist`(带警告日志),即使 `channels.defaults.groupPolicy` 已设置。
提及 + /activation
群组回复默认需要提及。
提及检测包括:
- 显式的 WhatsApp Bot 身份提及
- 配置的提及正则模式(`agents.list[].groupChat.mentionPatterns`,备选 `messages.groupChat.mentionPatterns`)
- 隐式的回复 Bot 检测(回复发送者与 Bot 身份匹配)
安全说明:
- 引用/回复仅满足提及门控;它**不**授予发送者授权
- 在 `groupPolicy: "allowlist"` 下,即使非白名单发送者回复了白名单用户的消息,仍然会被阻止
会话级激活命令:
- `/activation mention`
- `/activation always`
`activation` 更新会话状态(非全局配置)。需要所有者权限。
个人号码与自聊行为
当关联的自身号码同时存在于 allowFrom 中时,WhatsApp 自聊保护会激活:
- 跳过自聊轮次的已读回执
- 忽略本会自动 ping 自己的提及 JID 自动触发行为
- 如果
messages.responsePrefix未设置,自聊回复默认使用[{identity.name}]或[openclaw]
消息规范化与上下文
入站信封 + 回复上下文
入站 WhatsApp 消息被包装在共享入站信封中。
如果存在引用回复,上下文会以如下形式附加:
```text
[Replying to <sender> id:<stanzaId>]
<quoted body or media placeholder>
[/Replying]
```
可用时还会填充回复元数据字段(`ReplyToId`、`ReplyToBody`、`ReplyToSender`、发送者 JID/E.164)。
媒体占位符与位置/联系人提取
纯媒体入站消息使用以下占位符规范化:
- `<media:image>`
- `<media:video>`
- `<media:audio>`
- `<media:document>`
- `<media:sticker>`
位置和联系人 payload 在路由前规范化为文本上下文。
待处理群组历史注入
对于群组,未处理的消息可以被缓冲并在 Bot 最终被触发时作为上下文注入。
- 默认限制:`50`
- 配置:`channels.whatsapp.historyLimit`
- 备选:`messages.groupChat.historyLimit`
- `0` 禁用
注入标记:
- `[Chat messages since your last reply - for context]`
- `[Current message - respond to this]`
已读回执
对于已接受的入站 WhatsApp 消息,已读回执默认启用。
全局禁用:
```json5
{
channels: {
whatsapp: {
sendReadReceipts: false,
},
},
}
```
按账户覆盖:
```json5
{
channels: {
whatsapp: {
accounts: {
work: {
sendReadReceipts: false,
},
},
},
},
}
```
即使全局启用,自聊轮次也会跳过已读回执。
投递、分块和媒体
文本分块
- 默认分块限制:`channels.whatsapp.textChunkLimit = 4000`
- `channels.whatsapp.chunkMode = "length" | "newline"`
- `newline` 模式优先在段落边界(空行)处分割,然后回退到长度安全分块
出站媒体行为
- 支持图片、视频、音频(PTT 语音备忘录)和文档 payload
- `audio/ogg` 被重写为 `audio/ogg; codecs=opus` 以兼容语音备忘录
- 通过 `gifPlayback: true` 在视频发送时支持动态 GIF 播放
- 发送多媒体回复 payload 时,字幕应用于第一个媒体项
- 媒体来源可以是 HTTP(S)、`file://` 或本地路径
媒体大小限制和回退行为
- 入站媒体保存上限:`channels.whatsapp.mediaMaxMb`(默认 `50`)
- 出站媒体发送上限:`channels.whatsapp.mediaMaxMb`(默认 `50`)
- 按账户覆盖:`channels.whatsapp.accounts.<accountId>.mediaMaxMb`
- 图片自动优化(调整大小/质量扫描)以适应限制
- 媒体发送失败时,首项回退会发送文本警告而非静默丢弃响应
确认回应
WhatsApp 支持通过 channels.whatsapp.ackReaction 在入站接收时立即发送确认回应。
{
channels: {
whatsapp: {
ackReaction: {
emoji: "👀",
direct: true,
group: "mentions", // always | mentions | never
},
},
},
}
行为说明:
- 在入站被接受后立即发送(回复之前)
- 失败会被记录但不会阻塞正常回复投递
- 群组模式
mentions在提及触发的轮次时发送回应;群组激活always可绕过此检查 - WhatsApp 使用
channels.whatsapp.ackReaction(旧版messages.ackReaction在此不适用)
多账户与凭据
账户选择与默认值
- 账户 ID 来自 `channels.whatsapp.accounts`
- 默认账户选择:如果存在 `default` 则使用,否则使用第一个配置的账户 ID(排序后)
- 账户 ID 在内部规范化以便查找
凭据路径与旧版兼容
- 当前认证路径:`~/.openclaw/credentials/whatsapp/<accountId>/creds.json`
- 备份文件:`creds.json.bak`
- 旧版默认认证在 `~/.openclaw/credentials/` 中,对默认账户流程仍可识别/迁移
登出行为
`openclaw channels logout --channel whatsapp [--account <id>]` 清除该账户的 WhatsApp 认证状态。
在旧版认证目录中,`oauth.json` 会被保留,同时 Baileys 认证文件会被移除。
工具、操作和配置写入
- Agent 工具支持 WhatsApp 回应操作(
react)。 - 操作门控:
channels.whatsapp.actions.reactionschannels.whatsapp.actions.polls
- 频道触发的配置写入默认启用(通过
channels.whatsapp.configWrites=false禁用)。
故障排查
未关联(需要 QR 码)
症状:频道状态报告未关联。
修复:
```bash
openclaw channels login --channel whatsapp
openclaw channels status
```
已关联但断开连接 / 重连循环
症状:已关联账户反复断开连接或重连尝试。
修复:
```bash
openclaw doctor
openclaw logs --follow
```
如需要,使用 `channels login` 重新关联。
发送时无活跃监听器
当目标账户没有活跃的 Gateway 监听器时,出站发送会快速失败。
确保 Gateway 正在运行且账户已关联。
群组消息被意外忽略
按以下顺序检查:
- `groupPolicy`
- `groupAllowFrom` / `allowFrom`
- `groups` 白名单条目
- 提及门控(`requireMention` + 提及模式)
- `openclaw.json`(JSON5)中的重复键:后面的条目覆盖前面的,因此每个范围保持单个 `groupPolicy`
Bun 运行时警告
WhatsApp Gateway 运行时应使用 Node。Bun 被标记为不兼容稳定的 WhatsApp/Telegram Gateway 运行。
配置参考指引
主要参考:
WhatsApp 重要字段:
- 访问控制:
dmPolicy、allowFrom、groupPolicy、groupAllowFrom、groups - 投递:
textChunkLimit、chunkMode、mediaMaxMb、sendReadReceipts、ackReaction - 多账户:
accounts.<id>.enabled、accounts.<id>.authDir、账户级覆盖 - 运维:
configWrites、debounceMs、web.enabled、web.heartbeatSeconds、web.reconnect.* - 会话行为:
session.dmScope、historyLimit、dmHistoryLimit、dms.<id>.historyLimit