LetsBeBiz-Redesign/openclaw/docs/zh-CN/channels/whatsapp.md

412 lines
17 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
read_when:
- 处理 WhatsApp/网页渠道行为或收件箱路由时
summary: WhatsApp网页渠道集成登录、收件箱、回复、媒体和运维
title: WhatsApp
x-i18n:
generated_at: "2026-02-03T07:46:24Z"
model: claude-opus-4-5
provider: pi
source_hash: 44fd88f8e269284999e5a5a52b230edae6e6f978528dd298d6a5603d03c0c38d
source_path: channels/whatsapp.md
workflow: 15
---
# WhatsApp网页渠道
状态:仅支持通过 Baileys 的 WhatsApp Web。Gateway 网关拥有会话。
## 快速设置(新手)
1. 如果可能,使用**单独的手机号码**(推荐)。
2.`~/.openclaw/openclaw.json` 中配置 WhatsApp。
3. 运行 `openclaw channels login` 扫描二维码(关联设备)。
4. 启动 Gateway 网关。
最小配置:
```json5
{
channels: {
whatsapp: {
dmPolicy: "allowlist",
allowFrom: ["+15551234567"],
},
},
}
```
## 目标
- 在一个 Gateway 网关进程中支持多个 WhatsApp 账户(多账户)。
- 确定性路由:回复返回到 WhatsApp无模型路由。
- 模型能看到足够的上下文来理解引用回复。
## 配置写入
默认情况下WhatsApp 允许写入由 `/config set|unset` 触发的配置更新(需要 `commands.config: true`)。
禁用方式:
```json5
{
channels: { whatsapp: { configWrites: false } },
}
```
## 架构(谁拥有什么)
- **Gateway 网关**拥有 Baileys socket 和收件箱循环。
- **CLI / macOS 应用**与 Gateway 网关通信;不直接使用 Baileys。
- 发送出站消息需要**活跃的监听器**;否则发送会快速失败。
## 获取手机号码(两种模式)
WhatsApp 需要真实手机号码进行验证。VoIP 和虚拟号码通常会被封锁。在 WhatsApp 上运行 OpenClaw 有两种支持的方式:
### 专用号码(推荐)
为 OpenClaw 使用**单独的手机号码**。最佳用户体验,清晰的路由,无自聊天怪异问题。理想设置:**备用/旧 Android 手机 + eSIM**。保持 Wi-Fi 和电源连接,通过二维码关联。
**WhatsApp Business** 你可以在同一设备上使用不同号码的 WhatsApp Business。非常适合将个人 WhatsApp 分开——安装 WhatsApp Business 并在那里注册 OpenClaw 号码。
**示例配置(专用号码,单用户允许列表):**
```json5
{
channels: {
whatsapp: {
dmPolicy: "allowlist",
allowFrom: ["+15551234567"],
},
},
}
```
**配对模式(可选):**
如果你想使用配对而不是允许列表,请将 `channels.whatsapp.dmPolicy` 设置为 `pairing`。未知发送者会收到配对码;使用以下命令批准:
`openclaw pairing approve whatsapp <code>`
### 个人号码(备选方案)
快速备选方案:在**你自己的号码**上运行 OpenClaw。给自己发消息WhatsApp"给自己发消息")进行测试,这样就不会打扰联系人。在设置和实验期间需要在主手机上阅读验证码。**必须启用自聊天模式。**
当向导询问你的个人 WhatsApp 号码时,输入你将用于发送消息的手机(所有者/发送者),而不是助手号码。
**示例配置(个人号码,自聊天):**
```json
{
"whatsapp": {
"selfChatMode": true,
"dmPolicy": "allowlist",
"allowFrom": ["+15551234567"]
}
}
```
当设置了 `identity.name` 时,自聊天回复默认为 `[{identity.name}]`(否则为 `[openclaw]`
前提是 `messages.responsePrefix` 未设置。明确设置它可以自定义或禁用
前缀(使用 `""` 来移除)。
### 号码获取提示
- **本地 eSIM** 来自你所在国家的移动运营商(最可靠)
- 奥地利:[hot.at](https://www.hot.at)
- 英国:[giffgaff](https://www.giffgaff.com) — 免费 SIM 卡,无合约
- **预付费 SIM 卡** — 便宜,只需接收一条验证短信
**避免:** TextNow、Google Voice、大多数"免费短信"服务——WhatsApp 会积极封锁这些。
**提示:** 该号码只需要接收一条验证短信。之后WhatsApp Web 会话通过 `creds.json` 持久化。
## 为什么不用 Twilio
- 早期 OpenClaw 版本支持 Twilio 的 WhatsApp Business 集成。
- WhatsApp Business 号码不适合个人助手。
- Meta 强制执行 24 小时回复窗口;如果你在过去 24 小时内没有回复,商业号码无法发起新消息。
- 高频或"频繁"使用会触发激进的封锁,因为商业账户不适合发送大量个人助手消息。
- 结果:投递不可靠且频繁被封锁,因此该支持已被移除。
## 登录 + 凭证
- 登录命令:`openclaw channels login`(通过关联设备扫描二维码)。
- 多账户登录:`openclaw channels login --account <id>``<id>` = `accountId`)。
- 默认账户(省略 `--account` 时):如果存在则为 `default`,否则为第一个配置的账户 id排序后
- 凭证存储在 `~/.openclaw/credentials/whatsapp/<accountId>/creds.json`
- 备份副本在 `creds.json.bak`(损坏时恢复)。
- 旧版兼容性:较旧的安装将 Baileys 文件直接存储在 `~/.openclaw/credentials/` 中。
- 登出:`openclaw channels logout`(或 `--account <id>`)删除 WhatsApp 认证状态(但保留共享的 `oauth.json`)。
- 已登出的 socket => 错误提示重新关联。
## 入站流程(私信 + 群组)
- WhatsApp 事件来自 `messages.upsert`Baileys
- 收件箱监听器在关闭时分离,以避免在测试/重启时累积事件处理器。
- 状态/广播聊天被忽略。
- 直接聊天使用 E.164;群组使用群组 JID。
- **私信策略**`channels.whatsapp.dmPolicy` 控制直接聊天访问(默认:`pairing`)。
- 配对:未知发送者会收到配对码(通过 `openclaw pairing approve whatsapp <code>` 批准;码在 1 小时后过期)。
- 开放:需要 `channels.whatsapp.allowFrom` 包含 `"*"`
- 你关联的 WhatsApp 号码是隐式信任的,因此自身消息会跳过 `channels.whatsapp.dmPolicy``channels.whatsapp.allowFrom` 检查。
### 个人号码模式(备选方案)
如果你在**个人 WhatsApp 号码**上运行 OpenClaw请启用 `channels.whatsapp.selfChatMode`(见上面的示例)。
行为:
- 出站私信永远不会触发配对回复(防止打扰联系人)。
- 入站未知发送者仍遵循 `channels.whatsapp.dmPolicy`
- 自聊天模式allowFrom 包含你的号码)避免自动已读回执并忽略提及 JID。
- 非自聊天私信会发送已读回执。
## 已读回执
默认情况下Gateway 网关在接受入站 WhatsApp 消息后将其标记为已读(蓝色勾号)。
全局禁用:
```json5
{
channels: { whatsapp: { sendReadReceipts: false } },
}
```
按账户禁用:
```json5
{
channels: {
whatsapp: {
accounts: {
personal: { sendReadReceipts: false },
},
},
},
}
```
注意事项:
- 自聊天模式始终跳过已读回执。
## WhatsApp 常见问题:发送消息 + 配对
**当我关联 WhatsApp 时OpenClaw 会给随机联系人发消息吗?**
不会。默认私信策略是**配对**,因此未知发送者只会收到配对码,他们的消息**不会被处理**。OpenClaw 只会回复它收到的聊天,或你明确触发的发送(智能体/CLI
**WhatsApp 上的配对是如何工作的?**
配对是未知发送者的私信门控:
- 来自新发送者的第一条私信返回一个短码(消息不会被处理)。
- 使用以下命令批准:`openclaw pairing approve whatsapp <code>`(使用 `openclaw pairing list whatsapp` 列出)。
- 码在 1 小时后过期;每个渠道的待处理请求上限为 3 个。
**多个人可以在一个 WhatsApp 号码上使用不同的 OpenClaw 实例吗?**
可以,通过 `bindings` 将每个发送者路由到不同的智能体peer `kind: "dm"`,发送者 E.164 如 `+15551234567`)。回复仍然来自**同一个 WhatsApp 账户**,直接聊天会折叠到每个智能体的主会话,因此**每人使用一个智能体**。私信访问控制(`dmPolicy`/`allowFrom`)是每个 WhatsApp 账户全局的。参见[多智能体路由](/concepts/multi-agent)。
**为什么向导会询问我的手机号码?**
向导使用它来设置你的**允许列表/所有者**,以便允许你自己的私信。它不会用于自动发送。如果你在个人 WhatsApp 号码上运行,请使用相同的号码并启用 `channels.whatsapp.selfChatMode`
## 消息规范化(模型看到的内容)
- `Body` 是带有信封的当前消息正文。
- 引用回复上下文**始终附加**
```
[Replying to +1555 id:ABC123]
<quoted text or <media:...>>
[/Replying]
```
- 回复元数据也会设置:
- `ReplyToId` = stanzaId
- `ReplyToBody` = 引用正文或媒体占位符
- `ReplyToSender` = 已知时为 E.164
- 纯媒体入站消息使用占位符:
- `<media:image|video|audio|document|sticker>`
## 群组
- 群组映射到 `agent:<agentId>:whatsapp:group:<jid>` 会话。
- 群组策略:`channels.whatsapp.groupPolicy = open|disabled|allowlist`(默认 `allowlist`)。
- 激活模式:
- `mention`(默认):需要 @提及或正则匹配
- `always`:始终触发。
- `/activation mention|always` 仅限所有者,必须作为独立消息发送。
- 所有者 = `channels.whatsapp.allowFrom`(如果未设置则为自身 E.164)。
- **历史注入**(仅待处理):
- 最近*未处理*的消息(默认 50 条)插入在:
`[Chat messages since your last reply - for context]`(已在会话中的消息不会重新注入)
- 当前消息在:
`[Current message - respond to this]`
- 附加发送者后缀:`[from: Name (+E164)]`
- 群组元数据缓存 5 分钟(主题 + 参与者)。
## 回复投递(线程)
- WhatsApp Web 发送标准消息(当前 Gateway 网关无引用回复线程)。
- 此渠道忽略回复标签。
## 确认表情(收到时自动回应)
WhatsApp 可以在收到传入消息时立即自动发送表情回应,在机器人生成回复之前。这为用户提供即时反馈,表明他们的消息已收到。
**配置:**
```json
{
"whatsapp": {
"ackReaction": {
"emoji": "👀",
"direct": true,
"group": "mentions"
}
}
}
```
**选项:**
- `emoji`(字符串):用于确认的表情(例如"👀"、"✅"、"📨")。为空或省略 = 功能禁用。
- `direct`(布尔值,默认:`true`):在直接/私信聊天中发送表情回应。
- `group`(字符串,默认:`"mentions"`):群聊行为:
- `"always"`:对所有群消息做出回应(即使没有 @提及
- `"mentions"`:仅在机器人被 @提及时做出回应
- `"never"`:从不在群组中做出回应
**按账户覆盖:**
```json
{
"whatsapp": {
"accounts": {
"work": {
"ackReaction": {
"emoji": "✅",
"direct": false,
"group": "always"
}
}
}
}
}
```
**行为说明:**
- 表情回应在消息收到时**立即**发送,在输入指示器或机器人回复之前。
-`requireMention: false`激活always的群组中`group: "mentions"` 会对所有消息做出回应(不仅仅是 @提及)。
- 即发即忘:表情回应失败会被记录但不会阻止机器人回复。
- 群组表情回应会自动包含参与者 JID。
- WhatsApp 忽略 `messages.ackReaction`;请改用 `channels.whatsapp.ackReaction`
## 智能体工具(表情回应)
- 工具:`whatsapp`,带有 `react` 动作(`chatJid`、`messageId`、`emoji`,可选 `remove`)。
- 可选:`participant`(群组发送者)、`fromMe`(对自己的消息做出回应)、`accountId`(多账户)。
- 表情移除语义:参见 [/tools/reactions](/tools/reactions)。
- 工具门控:`channels.whatsapp.actions.reactions`(默认:启用)。
## 限制
- 出站文本按 `channels.whatsapp.textChunkLimit` 分块(默认 4000
- 可选换行分块:设置 `channels.whatsapp.chunkMode="newline"` 在长度分块之前按空行(段落边界)分割。
- 入站媒体保存受 `channels.whatsapp.mediaMaxMb` 限制(默认 50 MB
- 出站媒体项受 `agents.defaults.mediaMaxMb` 限制(默认 5 MB
## 出站发送(文本 + 媒体)
- 使用活跃的网页监听器;如果 Gateway 网关未运行则报错。
- 文本分块:每条消息最大 4k可通过 `channels.whatsapp.textChunkLimit` 配置,可选 `channels.whatsapp.chunkMode`)。
- 媒体:
- 支持图片/视频/音频/文档。
- 音频作为 PTT 发送;`audio/ogg` => `audio/ogg; codecs=opus`
- 仅在第一个媒体项上添加标题。
- 媒体获取支持 HTTP(S) 和本地路径。
- 动画 GIFWhatsApp 期望带有 `gifPlayback: true` 的 MP4 以实现内联循环。
- CLI`openclaw message send --media <mp4> --gif-playback`
- Gateway 网关:`send` 参数包含 `gifPlayback: true`
## 语音消息PTT 音频)
WhatsApp 将音频作为**语音消息**PTT 气泡)发送。
- 最佳效果OGG/Opus。OpenClaw 将 `audio/ogg` 重写为 `audio/ogg; codecs=opus`
- WhatsApp 忽略 `[[audio_as_voice]]`(音频已作为语音消息发送)。
## 媒体限制 + 优化
- 默认出站上限5 MB每个媒体项
- 覆盖:`agents.defaults.mediaMaxMb`。
- 图片自动优化为上限以下的 JPEG调整大小 + 质量扫描)。
- 超大媒体 => 错误;媒体回复降级为文本警告。
## 心跳
- **Gateway 网关心跳**记录连接健康状态(`web.heartbeatSeconds`,默认 60 秒)。
- **智能体心跳**可以按智能体配置(`agents.list[].heartbeat`)或通过
`agents.defaults.heartbeat` 全局配置(当没有设置按智能体条目时的降级)。
- 使用配置的心跳提示词(默认:`Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK.`+ `HEARTBEAT_OK` 跳过行为。
- 投递默认为最后使用的渠道(或配置的目标)。
## 重连行为
- 退避策略:`web.reconnect`
- `initialMs`、`maxMs`、`factor`、`jitter`、`maxAttempts`。
- 如果达到 maxAttempts网页监控停止降级
- 已登出 => 停止并要求重新关联。
## 配置快速映射
- `channels.whatsapp.dmPolicy`私信策略pairing/allowlist/open/disabled
- `channels.whatsapp.selfChatMode`(同手机设置;机器人使用你的个人 WhatsApp 号码)。
- `channels.whatsapp.allowFrom`私信允许列表。WhatsApp 使用 E.164 手机号码(无用户名)。
- `channels.whatsapp.mediaMaxMb`(入站媒体保存上限)。
- `channels.whatsapp.ackReaction`(消息收到时的自动回应:`{emoji, direct, group}`)。
- `channels.whatsapp.accounts.<accountId>.*`(按账户设置 + 可选 `authDir`)。
- `channels.whatsapp.accounts.<accountId>.mediaMaxMb`(按账户入站媒体上限)。
- `channels.whatsapp.accounts.<accountId>.ackReaction`(按账户确认回应覆盖)。
- `channels.whatsapp.groupAllowFrom`(群组发送者允许列表)。
- `channels.whatsapp.groupPolicy`(群组策略)。
- `channels.whatsapp.historyLimit` / `channels.whatsapp.accounts.<accountId>.historyLimit`(群组历史上下文;`0` 禁用)。
- `channels.whatsapp.dmHistoryLimit`(私信历史限制,按用户轮次)。按用户覆盖:`channels.whatsapp.dms["<phone>"].historyLimit`。
- `channels.whatsapp.groups`(群组允许列表 + 提及门控默认值;使用 `"*"` 允许全部)
- `channels.whatsapp.actions.reactions`(门控 WhatsApp 工具表情回应)。
- `agents.list[].groupChat.mentionPatterns`(或 `messages.groupChat.mentionPatterns`
- `messages.groupChat.historyLimit`
- `channels.whatsapp.messagePrefix`(入站前缀;按账户:`channels.whatsapp.accounts.<accountId>.messagePrefix`;已弃用:`messages.messagePrefix`
- `messages.responsePrefix`(出站前缀)
- `agents.defaults.mediaMaxMb`
- `agents.defaults.heartbeat.every`
- `agents.defaults.heartbeat.model`(可选覆盖)
- `agents.defaults.heartbeat.target`
- `agents.defaults.heartbeat.to`
- `agents.defaults.heartbeat.session`
- `agents.list[].heartbeat.*`(按智能体覆盖)
- `session.*`scope、idle、store、mainKey
- `web.enabled`(为 false 时禁用渠道启动)
- `web.heartbeatSeconds`
- `web.reconnect.*`
## 日志 + 故障排除
- 子系统:`whatsapp/inbound`、`whatsapp/outbound`、`web-heartbeat`、`web-reconnect`。
- 日志文件:`/tmp/openclaw/openclaw-YYYY-MM-DD.log`(可配置)。
- 故障排除指南:[Gateway 网关故障排除](/gateway/troubleshooting)。
## 故障排除(快速)
**未关联 / 需要二维码登录**
- 症状:`channels status` 显示 `linked: false` 或警告"Not linked"。
- 修复:在 Gateway 网关主机上运行 `openclaw channels login` 并扫描二维码WhatsApp → 设置 → 关联设备)。
**已关联但断开连接 / 重连循环**
- 症状:`channels status` 显示 `running, disconnected` 或警告"Linked but disconnected"。
- 修复:`openclaw doctor`(或重启 Gateway 网关)。如果问题持续,通过 `channels login` 重新关联并检查 `openclaw logs --follow`
**Bun 运行时**
- **不推荐** Bun。WhatsAppBaileys和 Telegram 在 Bun 上不可靠。
请使用 **Node** 运行 Gateway 网关。(参见入门指南运行时说明。)