跳转到内容

WhatsApp

状态:仅限通过 Baileys 的 WhatsApp Web。网关拥有会话。

  1. 如果可能,使用 单独的电话号码(推荐)。
  2. ~/.openclaw/openclaw.json 中配置 WhatsApp。
  3. 运行 openclaw channels login 以扫描 QR 码(已关联设备)。
  4. 启动网关。

最小配置:

{
channels: {
whatsapp: {
dmPolicy: "allowlist",
allowFrom: ["+15551234567"]
}
}
}
  • 在一个网关进程中支持多个 WhatsApp 账户(多账户)。
  • 确定性路由:回复返回到 WhatsApp,无模型路由。
  • 模型看到足够的上下文以理解引用回复。

默认情况下,WhatsApp 允许写入由 /config set|unset 触发的配置更新(需要 commands.config: true)。

禁用方法:

{
channels: { whatsapp: { configWrites: false } }
}
  • Gateway 拥有 Baileys 套接字和收件箱循环。
  • CLI / macOS app 与网关对话;不直接使用 Baileys。
  • Active listener 是出站发送所必需的;否则发送会快速失败。

WhatsApp 需要一个真实的手机号码进行验证。VoIP 和虚拟号码通常被阻止。有两种支持的方式在 WhatsApp 上运行 OpenClaw:

为 OpenClaw 使用一个 单独的电话号码。最佳用户体验,干净的路由,没有自我聊天的怪癖。理想设置:备用/旧 Android 手机 + eSIM。将其保持在 Wi-Fi 和电源上,并通过 QR 链接它。

WhatsApp Business: 你可以在同一设备上使用 WhatsApp Business 和不同的号码。非常适合将你的个人 WhatsApp 分开 — 安装 WhatsApp Business 并在那里注册 OpenClaw 号码。

示例配置(专用号码,单用户白名单):

{
channels: {
whatsapp: {
dmPolicy: "allowlist",
allowFrom: ["+15551234567"]
}
}
}

配对模式(可选): 如果你想要配对而不是白名单,将 channels.whatsapp.dmPolicy 设置为 pairing。未知发送者会收到一个配对代码;批准方式: openclaw pairing approve whatsapp <code>

快速回退:在 你自己的号码 上运行 OpenClaw。给自己发消息(WhatsApp “Message yourself”)进行测试,这样你就不会向联系人发送垃圾邮件。在设置和实验期间,期望在你的主手机上读取验证码。必须启用自我聊天模式 (self-chat mode)。 当向导询问你的个人 WhatsApp 号码时,输入你将从中发消息的电话(所有者/发送者),而不是助手号码。

示例配置(个人号码,自我聊天):

{
"whatsapp": {
"selfChatMode": true,
"dmPolicy": "allowlist",
"allowFrom": ["+15551234567"]
}
}

如果 messages.responsePrefix 未设置,自我聊天回复默认为 [{identity.name}](否则为 [openclaw])。显式设置它以自定义或禁用前缀(使用 "" 删除它)。

  • 来自你所在国家/地区移动运营商的 本地 eSIM(最可靠)
  • 预付费 SIM — 便宜,只需要接收一条 SMS 进行验证

避免: TextNow, Google Voice, 大多数 “免费 SMS” 服务 — WhatsApp 会积极阻止这些。

提示: 该号码只需要接收一条验证短信。之后,WhatsApp Web 会话通过 creds.json 持久化。

  • 早期的 OpenClaw 版本支持 Twilio 的 WhatsApp Business 集成。
  • WhatsApp Business 号码不太适合个人助手。
  • Meta 强制执行 24 小时回复窗口;如果你在过去 24 小时内没有回复,商业号码无法发起新消息。
  • 高容量或“健谈”的使用会触发积极的阻止,因为商业账户不适合发送数十条个人助理消息。
  • 结果:不可靠的交付和频繁的封锁,因此删除了支持。
  • 登录命令:openclaw channels login(通过已关联设备的 QR)。
  • 多账户登录:openclaw channels login --account <id> (<id> = accountId)。
  • 默认账户(省略 --account 时):default(如果存在),否则为第一个配置的账户 id(排序)。
  • 凭据存储在 ~/.openclaw/credentials/whatsapp/<accountId>/creds.json
  • 备份副本在 creds.json.bak(损坏时恢复)。
  • 旧版兼容性:旧安装直接在 ~/.openclaw/credentials/ 中存储 Baileys 文件。
  • 注销:openclaw channels logout(或 --account <id>)删除 WhatsApp 认证状态(但保留共享的 oauth.json)。
  • 已注销的套接字 => 错误指示重新链接。
  • WhatsApp 事件来自 messages.upsert (Baileys)。
  • 收件箱监听器在关闭时分离,以避免在测试/重启中积累事件处理程序。
  • 状态/广播聊天被忽略。
  • 直接聊天使用 E.164;群组使用群组 JID。
  • 私信策略channels.whatsapp.dmPolicy 控制直接聊天访问(默认:pairing)。
    • 配对:未知发送者获得配对代码(通过 openclaw pairing approve whatsapp <code> 批准;代码 1 小时后过期)。
    • 开放:需要 channels.whatsapp.allowFrom 包含 "*"
    • 你链接的 WhatsApp 号码被隐式信任,因此自我消息跳过 channels.whatsapp.dmPolicychannels.whatsapp.allowFrom 检查。

如果你在 个人 WhatsApp 号码 上运行 OpenClaw,请启用 channels.whatsapp.selfChatMode(见上文示例)。

行为:

  • 出站私信从不触发配对回复(防止向联系人发送垃圾邮件)。
  • 入站未知发送者仍遵循 channels.whatsapp.dmPolicy
  • 自我聊天模式(allowFrom 包含你的号码)避免自动已读回执并忽略提及 JID。
  • 为非自我聊天私信发送已读回执。

默认情况下,网关在接受入站 WhatsApp 消息后将其标记为已读(蓝色勾号)。

全局禁用:

{
channels: { whatsapp: { sendReadReceipts: false } }
}

每个账户禁用:

{
channels: {
whatsapp: {
accounts: {
personal: { sendReadReceipts: false }
}
}
}
}

注意:

  • 自我聊天模式总是跳过已读回执。

WhatsApp 常见问题:发送消息 + 配对

Section titled “WhatsApp 常见问题:发送消息 + 配对”

链接 WhatsApp 时 OpenClaw 会给随机联系人发消息吗? 不会。默认私信策略是 配对,所以未知发送者只会收到配对代码,并且他们的消息 不会被处理。OpenClaw 仅回复它收到的聊天,或你显式触发的发送(智能体/CLI)。

配对在 WhatsApp 上如何工作? 配对是针对未知发送者的私信门控:

  • 来自新发送者的第一条私信返回一个短代码(消息不被处理)。
  • 批准方式:openclaw pairing approve whatsapp <code>(使用 openclaw pairing list whatsapp 列出)。
  • 代码在 1 小时后过期;待处理请求每个频道上限为 3 个。

多人可以在一个 WhatsApp 号码上使用不同的 OpenClaw 实例吗? 可以,通过 bindings 将每个发送者路由到不同的智能体(对等 kind: "dm", 发送者 E.164 如 +15551234567)。回复仍然来自 同一个 WhatsApp 账户,并且直接聊天折叠到每个智能体的主会话,所以 每人使用一个智能体。私信访问控制(dmPolicy/allowFrom)是每个 WhatsApp 账户全局的。参见 多智能体路由

为什么在向导中询问我的电话号码? 向导使用它来设置你的 白名单/所有者,以便允许你自己的私信。它不用于自动发送。如果你在个人 WhatsApp 号码上运行,请使用相同的号码并启用 channels.whatsapp.selfChatMode

消息标准化(模型看到的内容)

Section titled “消息标准化(模型看到的内容)”
  • 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(默认):需要 @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 发送标准消息(当前网关中没有引用回复线程)。
  • 此频道忽略回复标签。

WhatsApp 可以在收到消息后立即自动发送表情符号反应,在机器人生成回复之前。这为用户提供了消息已收到的即时反馈。

配置:

{
"whatsapp": {
"ackReaction": {
"emoji": "👀",
"direct": true,
"group": "mentions"
}
}
}

选项:

  • emoji (字符串):用于确认的表情符号(例如 ”👀”, ”✅”, ”📨”)。为空或省略 = 功能禁用。
  • direct (布尔值, 默认: true):在直接/私信聊天中发送反应。
  • group (字符串, 默认: "mentions"):群聊行为:
    • "always":对所有群组消息做出反应(即使没有 @mention)
    • "mentions":仅当机器人被 @mention 时做出反应
    • "never":从不在群组中做出反应

每个账户的覆盖:

{
"whatsapp": {
"accounts": {
"work": {
"ackReaction": {
"emoji": "",
"direct": false,
"group": "always"
}
}
}
}
}

行为说明:

  • 反应在收到消息后 立即 发送,在输入指示或机器人回复之前。
  • requireMention: false(激活:总是)的群组中,group: "mentions" 将对所有消息做出反应(不仅仅是 @mentions)。
  • 即发即弃:反应失败会被记录,但不会阻止机器人回复。
  • 参与者 JID 自动包含在群组反应中。
  • WhatsApp 忽略 messages.ackReaction;请改用 channels.whatsapp.ackReaction
  • 工具:带有 react 动作的 whatsappchatJid, messageId, emoji, 可选 remove)。
  • 可选:participant(群组发送者),fromMe(对自己消息的反应),accountId(多账户)。
  • 反应移除语义:参见 /tools/reactions
  • 工具门控:channels.whatsapp.actions.reactions(默认:启用)。
  • 出站文本分块限制为 channels.whatsapp.textChunkLimit(默认 4000)。
  • 可选换行符分块:设置 channels.whatsapp.chunkMode="newline" 以在长度分块之前按空行(段落边界)拆分。
  • 入站媒体保存限制为 channels.whatsapp.mediaMaxMb(默认 50 MB)。
  • 出站媒体项目限制为 agents.defaults.mediaMaxMb(默认 5 MB)。
  • 使用活动 Web 监听器;如果网关未运行则报错。
  • 文本分块:每条消息最大 4k(可通过 channels.whatsapp.textChunkLimit 配置,可选 channels.whatsapp.chunkMode)。
  • 媒体:
    • 支持图片/视频/音频/文档。
    • 音频作为 PTT 发送;audio/ogg => audio/ogg; codecs=opus
    • 仅在第一个媒体项目上有标题。
    • 媒体获取支持 HTTP(S) 和本地路径。
    • 动画 GIF:WhatsApp 期望具有 gifPlayback: true 的 MP4 以进行内联循环。
      • CLI: openclaw message send --media <mp4> --gif-playback
      • Gateway: send 参数包含 gifPlayback: true

WhatsApp 将音频作为 语音笔记(PTT 气泡)发送。

  • 最佳结果:OGG/Opus。OpenClaw 将 audio/ogg 重写为 audio/ogg; codecs=opus
  • [[audio_as_voice]] 对 WhatsApp 被忽略(音频已经作为语音笔记发送)。
  • 默认出站上限:5 MB(每个媒体项目)。
  • 覆盖:agents.defaults.mediaMaxMb
  • 图片在上限下自动优化为 JPEG(调整大小 + 质量扫描)。
  • 超大媒体 => 错误;媒体回复回退到文本警告。
  • Gateway heartbeat 记录连接健康状况(web.heartbeatSeconds,默认 60s)。
  • Agent heartbeat 可以每个智能体配置(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,Web 监控停止(降级)。
  • 已注销 => 停止并要求重新链接。
  • 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(可配置)。
  • 故障排除指南:网关故障排除

未链接 / 需要 QR 登录

  • 症状:channels status 显示 linked: false 或警告 “Not linked”。
  • 修复:在网关主机上运行 openclaw channels login 并扫描 QR(WhatsApp → 设置 → 已关联设备)。

已链接但断开连接 / 重连循环

  • 症状:channels status 显示 running, disconnected 或警告 “Linked but disconnected”。
  • 修复:openclaw doctor(或重启网关)。如果持续存在,通过 channels login 重新链接并检查 openclaw logs --follow

Bun 运行时

  • 不推荐 使用 Bun。WhatsApp (Baileys) 和 Telegram 在 Bun 上不可靠。 使用 Node 运行网关。(参见入门运行时说明。)