# WhatsApp

> WhatsApp 渠道支持、访问控制、消息投递行为和运维

- 网址：https://funcoding.ai/agents/openclaw/channels/whatsapp/
- 来源：OpenClaw 官方文档原文（中文），MIT 许可，同步于 2026-10-11
- 官方原文：https://docs.openclaw.ai/zh-CN/channels/whatsapp

---
状态：已通过 WhatsApp Web（Baileys）达到生产就绪状态。Gateway 网关拥有已关联的会话；不存在单独的 Twilio WhatsApp 渠道。

## 安装

`openclaw onboard` 和 `openclaw channels add --channel whatsapp` 会在你首次选择该插件时提示安装；如果插件缺失，`openclaw channels login --channel whatsapp` 会提供相同的安装流程。开发检出版本使用本地插件路径；稳定版/测试版安装会先从 ClawHub 安装 `@openclaw/whatsapp`，失败时回退到 npm。WhatsApp 运行时在 OpenClaw 核心 npm 包之外发布，因此其运行时依赖项随外部插件一起提供。手动安装：

```bash
openclaw plugins install clawhub:@openclaw/whatsapp
```

仅将纯 npm 包（`@openclaw/whatsapp`）用于注册表回退；只有在需要可复现安装时才固定到确切版本。

- [配对](https://funcoding.ai/agents/openclaw/channels/pairing/)：对于未知发送者，默认私信策略为配对。
- [渠道故障排除](https://funcoding.ai/agents/openclaw/channels/troubleshooting/)：跨渠道诊断和修复操作手册。
- [Gateway 配置](https://funcoding.ai/agents/openclaw/gateway/configuration/)：完整的渠道配置模式和示例。

## 快速设置

**配置访问策略**

```json5
{
  channels: {
    whatsapp: {
      dmPolicy: "pairing",
      allowFrom: ["+15551234567"],
      groupPolicy: "allowlist",
      groupAllowFrom: ["+15551234567"],
    },
  },
}
```

**关联 WhatsApp（二维码）**

```bash
openclaw channels login --channel whatsapp
```

    登录仅支持二维码。在远程或无头主机上，开始登录前应确保有可靠的方式将实时二维码传送到手机；终端渲染的二维码、屏幕截图或聊天附件可能在传输过程中失效。

    对于特定账户：

```bash
openclaw channels login --channel whatsapp --account work
```

    要在登录前关联现有/自定义身份验证目录：

```bash
openclaw channels add --channel whatsapp --account work --auth-dir /path/to/wa-auth
openclaw channels login --channel whatsapp --account work
```

**启动 Gateway 网关**

```bash
openclaw gateway
```

**批准第一个私信访问请求（配对模式）**

    打开 **Settings → Channels → DM access requests**，找到 WhatsApp 账户，
    然后批准发送者。如果更喜欢使用 CLI：

```bash
openclaw pairing list whatsapp
openclaw pairing approve whatsapp <CODE>
```

    私信访问请求会在 1 小时后过期；每个账户最多可有 3 个待处理请求。
    此批准与用于关联账户本身的 WhatsApp 登录二维码相互独立。

<div class="callout callout-note">

建议使用单独的 WhatsApp 号码（设置和元数据针对这种方式进行了优化），但也完全支持个人号码/与自己聊天的设置。

</div>

## 部署模式

<details>
<summary>专用号码（推荐）</summary>

- OpenClaw 使用单独的 WhatsApp 身份
- 更清晰的私信允许列表和路由边界
- 降低与自己聊天时产生混淆的可能性

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

</details>

<details>
<summary>个人号码回退方案</summary>

新手引导支持个人号码模式，并写入适合与自己聊天的基线配置：`dmPolicy: "allowlist"`、包含你自己号码的 `allowFrom`、`selfChatMode: true`。运行时的与自己聊天保护机制以已关联的自身号码和 `allowFrom` 为依据。

</details>

## 运行时模型

- Gateway 网关拥有 WhatsApp 套接字和重连循环。
- 看门狗独立跟踪两种信号：原始 WhatsApp Web 传输活动和应用消息活动。会话即使处于静默状态，只要仍保持连接，就不会仅因近期没有收到消息而重启；只有在传输帧持续一个固定的内部时间窗口未到达（用户不可配置），或应用消息的静默时间超过正常消息超时的 4 倍时，才会强制重连。对于最近处于活跃状态的会话，刚刚完成重连后的第一个时间窗口使用较短的正常消息超时，而不是 4 倍时间窗口。对于 Baileys 在该重连早期送达的离线消息，OpenClaw 可以自动回复，范围受入站消息 ID 去重生命周期限制；初始启动仍保留较短的陈旧历史记录防护。
- 出站发送要求目标账户具有活跃的 WhatsApp 监听器；否则发送会立即失败。
- 在群组发送中，当 `@+<digits>` 和 `@<digits>` 令牌（位于文本和媒体说明中）与当前参与者元数据匹配时，会附加原生提及元数据，包括由 LID 支持的群组。
- 状态和广播聊天（`@status`、`@broadcast`）会被忽略。
- 直接聊天使用私信会话规则（`session.dmScope`；默认的 `main` 会将私信合并到智能体主会话中）。群组会话按 JID 隔离（`agent:<agentId>:whatsapp:group:<jid>`）。
- WhatsApp Channels/Newsletters 可以通过其原生 `@newsletter` JID 明确指定为出站目标，并使用渠道会话元数据（`agent:<agentId>:whatsapp:channel:<jid>`），而不是私信语义。
- WhatsApp Web 传输遵循 Gateway 网关主机上的标准代理环境变量（`HTTPS_PROXY`、`HTTP_PROXY`、`NO_PROXY` 及其小写变体）。优先使用主机级代理配置，而不是每渠道设置。

## 使用 MeowCaller 呼叫当前请求者（实验性）

该插件可以在源自 WhatsApp 的智能体轮次中公开 `whatsapp_call`。它使用 [MeowCaller](https://github.com/purpshell/meowcaller) 向当前已获授权的请求者发起 WhatsApp 语音通话，并在对方接听后播放 OpenClaw TTS 消息。该工具没有目标号码参数，因此提示词无法将通话重定向到其他号码。默认禁用。

<div class="callout callout-warning">

MeowCaller 是实验性功能，没有带标签的发布版本，并且使用单独配对的 whatsmeow 已关联设备会话——它无法复用插件的 Baileys 凭据。配对会向同一个 WhatsApp 账户添加另一台已关联设备；请使用 OpenClaw 所用的身份进行扫描。个人号码/与自己聊天模式无法呼叫自身；请使用专用 OpenClaw 号码呼叫你的个人号码。

</div>

**启用实验性通话**

    将 `actions.calls: true` 添加到 WhatsApp 渠道配置中，然后重启 Gateway 网关：

```json
{
  "channels": {
    "whatsapp": {
      "actions": {
        "calls": true
      }
    }
  }
}
```

    如果缺少该项或其值为 `false`，OpenClaw 不会公开 `whatsapp_call` 工具。

**安装经过审查的 MeowCaller CLI**

    适配器要求 Gateway 网关主机的 `PATH` 中存在 `meowcaller` 可执行文件。在 [MeowCaller PR #7](https://github.com/purpshell/meowcaller/pull/7) 合并之前，请构建经过审查的分支：

```bash
git clone --branch feat/send-only-notify https://github.com/steipete/meowcaller.git
cd meowcaller
git checkout 752050471fc2bf7a8cdfbf7dbd3cd4e865d85d3f
mkdir -p "$HOME/.local/bin"
go build -o "$HOME/.local/bin/meowcaller" ./cmd/meowcaller
```

    确保 `$HOME/.local/bin` 位于 Gateway 网关服务的 `PATH` 中。此修订版提供明确的 `pair` 和仅发送的 `notify` 命令；`notify` 不会打开麦克风、扬声器、视频设备或诊断捕获。请勿改用上游示例 CLI 的 `play` 命令。

**配对 MeowCaller 已关联设备**

    要求 WhatsApp 智能体检查通话设置（`whatsapp_call` 状态操作会报告账户专属状态目录和配对命令）。对于默认账户：

```bash
state_dir="$HOME/.openclaw/credentials/whatsapp-calls/default"
mkdir -p "$state_dir"
chmod 700 "$state_dir"
meowcaller pair --store "$state_dir/wa-voip.db"
```

    以交互方式运行此命令，通过 **WhatsApp > Linked devices** 扫描二维码，并等待 `MeowCaller linked device ready`。请将 `wa-voip.db` 保密——它是 MeowCaller 会话。非默认账户会通过状态操作获得各自的存储路径；在 Windows 上，请运行其 PowerShell 命令。

**配置 TTS 并从 WhatsApp 发起通话**

配置支持电话通话的 [TTS 提供商](https://funcoding.ai/agents/openclaw/tools/tts/)，重启 Gateway 网关，然后发送类似 `Call me and say the build finished.` 的请求。该工具从可信的入站上下文解析发送者，合成临时私有 WAV 文件，在有界的通话时间窗口内运行 MeowCaller，并在之后删除音频文件。OpenClaw 会明确传入账户的存储位置，在接听、播放和挂断后等待零退出状态，并将超时或非零退出视为工具调用失败。

限制：仅支持一对一出站音频通话、不支持任意目标号码、不与聊天连接共享身份验证、不支持在个人号码/与自己聊天模式下呼叫自身、合成音频最长为 60 秒、除 MeowCaller 完成接听/播放/挂断外不提供手机端可听性回执，并且 OpenClaw 会在有界的 115-175 秒时间窗口后停止伴随进程（涵盖 MeowCaller 的连接、接听、播放和关闭阶段）。

## 审批提示

WhatsApp 可以将 Exec 和插件审批提示呈现为 `👍`/`👎` 表情回应，由顶层审批转发配置控制：

```json5
{
  approvals: {
    exec: {
      enabled: true,
      mode: "session",
    },
    plugin: {
      enabled: true,
      mode: "targets",
      targets: [{ channel: "whatsapp", to: "+15551234567" }],
    },
  },
}
```

`approvals.exec` 和 `approvals.plugin` 相互独立；仅将 WhatsApp 启用为渠道只会关联传输层，不会发送任何内容，除非相应的审批类别已启用并路由到该渠道。会话模式仅对源自 WhatsApp 的审批发送原生表情符号审批。目标模式对明确目标使用共享转发管线，不会创建单独的审批者私信扇出。

WhatsApp 审批表情回应要求在 `allowFrom`（或 `"*"`）中明确指定审批者。`defaultTo` 设置普通的默认消息目标，而不是审批者列表。手动执行的 `/approve` 命令仍会先经过正常的 WhatsApp 发送者授权路径，然后才解析审批。

## 问题表情回应

对于包含一个非敏感单选问题和一至四个选项的 `ask_user` 提示，WhatsApp 会在选项标签旁显示从 `1️⃣` 到 `4️⃣`。使用匹配的数字对已送达的提示作出表情回应即可回答。OpenClaw 通过 Gateway 网关将数字映射到规范选项；过期或重复的点击会被忽略。多问题、多选和自由文本提示仍只能通过文本回复。正常的 WhatsApp 私信/群组准入规则会对作出表情回应的发送者进行授权。

## 插件钩子和隐私

入站 WhatsApp 消息可能包含个人内容、电话号码、群组标识符、发送者姓名和会话关联字段。除非你选择启用，否则 WhatsApp 不会向插件广播入站 `message_received` 钩子载荷：

```json5
{
  channels: {
    whatsapp: {
      pluginHooks: {
        messageReceived: true,
      },
    },
  },
}
```

请在 `channels.whatsapp.accounts.<id>.pluginHooks.messageReceived` 下将选择启用的范围限定为一个账户。仅对你信任其可访问入站 WhatsApp 内容和标识符的插件启用此功能。

## 访问控制和激活

**私信策略**

`channels.whatsapp.dmPolicy`：

| 值 | 行为 |
| --- | --- |
| `pairing`（默认） | 未知发送者请求配对；所有者批准 |
| `allowlist` | 仅允许 `allowFrom` 中的发送者 |
| `open` | 要求 `allowFrom` 包含 `"*"` |
| `disabled` | 阻止所有私信 |

`allowFrom` 接受 E.164 格式的号码（内部会进行规范化）。它仅是私信发送者访问控制列表，不会限制向群组 JID 或 `@newsletter` 渠道 JID 的显式出站发送。

多账号覆盖：`channels.whatsapp.accounts.<id>.dmPolicy`（以及 `.allowFrom`）优先于该账号的渠道级默认值。

运行时说明：

- 配对会持久化到渠道允许存储中，并与配置的 `allowFrom` 合并
- 定时自动化和 Heartbeat 收件人回退使用显式投递目标或配置的 `allowFrom`；私信配对批准不会隐式成为定时任务/Heartbeat 收件人
- 如果未配置允许列表，默认允许已关联的本机号码
- OpenClaw 绝不会自动配对出站 `fromMe` 私信（即你从已关联设备发送给自己的消息）

**群组策略和允许列表**

群组访问分为两层：

1. **群组成员资格允许列表**（`channels.whatsapp.groups`）：如果省略 `groups`，则所有群组均符合条件；如果存在，它将充当群组允许列表（`"*"` 允许所有群组）。
2. **群组发送者策略**（`channels.whatsapp.groupPolicy` + `groupAllowFrom`）：`open` 会绕过发送者允许列表，`allowlist` 要求匹配 `groupAllowFrom`（或 `*`），`disabled` 会阻止所有群组入站消息。

如果未设置 `groupAllowFrom`，当 `allowFrom` 包含条目时，发送者检查会回退到该配置。发送者允许列表的评估先于提及/回复激活。

如果完全不存在 `channels.whatsapp` 块，运行时会回退到 `groupPolicy: "allowlist"`（并记录警告日志），即使 `channels.defaults.groupPolicy` 设置为其他值也是如此。

<div class="callout callout-note">

群组成员资格解析提供单账号安全保障：如果只配置了一个 WhatsApp 账号，且其 `accounts.<id>.groups` 是显式空对象（`{}`），则会将其视为“未设置”，并回退到根级 `channels.whatsapp.groups` 映射，而不是静默阻止所有群组。配置 2 个或更多账号时，显式空账号映射会保持为空且不会回退——这使一个账号可以有意禁用所有群组，而不影响其他账号。

</div>

**提及和 /activation**

默认情况下，群组回复需要提及。提及检测包括：

- 在 WhatsApp 中显式提及 Bot 身份
- 配置的提及正则表达式模式（`agents.entries.*.groupChat.mentionPatterns`，回退到 `messages.groupChat.mentionPatterns`）
- 已获授权的群组消息中的入站语音留言转录文本
- 隐式的回复 Bot 检测（回复发送者与 Bot 身份匹配）

安全性：引用/回复仅满足提及门控要求，**不会**授予发送者权限。使用 `groupPolicy: "allowlist"` 时，不在允许列表中的发送者即使回复允许列表中用户的消息，也仍会被阻止。

会话级激活命令：`/activation mention` 或 `/activation always`。此命令更新会话状态（而非全局配置），且仅限所有者使用。

## 已配置的 ACP 绑定

WhatsApp 通过顶层 `bindings[]` 支持持久化 ACP 绑定：

```json5
{
  bindings: [
    {
      type: "acp",
      agentId: "codex",
      match: {
        channel: "whatsapp",
        accountId: "work",
        peer: { kind: "direct", id: "+15555550123" },
      },
    },
    {
      type: "acp",
      agentId: "codex",
      match: {
        channel: "whatsapp",
        accountId: "work",
        peer: { kind: "group", id: "120363424282127706@g.us" },
      },
    },
  ],
}
```

私聊匹配 E.164 号码；群组匹配 WhatsApp 群组 JID。在 OpenClaw 确保绑定的 ACP 会话存在之前，会先执行群组允许列表、发送者策略以及提及/激活门控。匹配的绑定拥有该路由——广播群组不会将该轮次分发到普通 WhatsApp 会话。

## 个人号码和与自己聊天的行为

当已关联的本人号码也存在于 `allowFrom` 中时，会启用与自己聊天的保护措施：跳过与自己聊天轮次的已读回执；忽略会提醒自己的提及 JID 自动触发行为；并且当渠道/账户的 `responsePrefix` 未设置时，默认将回复发送到 `[{identity.name}]`（或 `[openclaw]`）。

## 消息规范化和上下文

<details>
<summary>入站信封和回复上下文</summary>

传入消息会封装在共享入站信封中。引用回复会以以下形式追加上下文：

```text
[Replying to <sender> id:<stanzaId>]
<quoted body or media placeholder>
[/Replying]
```

可用时会填充回复元数据（`ReplyToId`、`ReplyToBody`、`ReplyToSender`、发送者 JID/E.164）。如果被引用的目标是可下载媒体，OpenClaw 会通过常规入站媒体存储保存它，并公开 `MediaPath`/`MediaType`，以便智能体直接检查，而不是只能看到 `<media:image>`。

</details>

<details>
<summary>媒体占位符以及位置/联系人提取</summary>

仅包含媒体的消息会规范化为占位符：`<media:image>`、`<media:video>`、`<media:audio>`、`<media:document>`、`<media:sticker>`。

当正文仅为 `<media:audio>` 时，已获授权的群组语音消息会在提及门控之前转写，因此在语音消息中说出对机器人的提及即可触发回复。如果转写文本仍未提及机器人，它会保留在待处理的群组历史记录中，而不是保留原始占位符。

位置正文会呈现为简洁的坐标文本。位置标签/评论以及联系人/vCard 详细信息会呈现为围栏式不受信任元数据，而不是内联提示文本。

</details>

<details>
<summary>待处理群组历史记录注入</summary>

未处理的群组消息会被缓冲，并在机器人最终被触发时作为上下文注入。

- 默认限制：`50`
- 配置：`channels.whatsapp.historyLimit`，回退值为 `messages.groupChat.historyLimit`
- `0` 可禁用

注入标记：`[Chat messages since your last reply - for context]` 和 `[Current message - respond to this]`。

</details>

<details>
<summary>已读回执</summary>

对已接受的入站消息默认启用。全局禁用：

```json5
{ channels: { whatsapp: { sendReadReceipts: false } } }
```

每账户覆盖：`channels.whatsapp.accounts.<id>.sendReadReceipts`。即使已全局启用，自聊轮次也会跳过已读回执。

</details>

## 发送、分块和媒体

<details>
<summary>文本分块</summary>

- 默认分块限制：`channels.whatsapp.textChunkLimit = 4000`
- `channels.whatsapp.streaming.chunkMode = "length" | "newline"`；`newline` 优先按段落边界（空行）分块，然后回退到长度安全的分块方式

</details>

<details>
<summary>出站媒体行为</summary>

- 支持图像、视频、音频（PTT 语音消息）和文档载荷
- 音频以 Baileys `audio` 载荷发送，并带有 `ptt: true`，呈现为按键通话语音消息；回复载荷会保留 `audioAsVoice`，因此无论提供商的源格式如何，TTS 语音消息输出都会继续走此路径
- 原生 Ogg/Opus 音频以 `audio/ogg; codecs=opus` 发送；其他任何格式（包括 Microsoft Edge TTS 的 MP3/WebM 输出）都会通过 `ffmpeg` 转码为 48 kHz 单声道 Ogg/Opus，然后再通过 PTT 发送
- `/tts latest` 会将智能体的最新回复作为一条语音消息发送，并抑制同一回复的重复发送；`/tts chat on|off|default` 控制当前聊天的自动 TTS
- 在发送视频时启用 `gifPlayback: true`，可实现 GIF 动画播放
- `forceDocument`/`asDocument` 会通过 Baileys 文档载荷路由出站图像、GIF 和视频，以避免 WhatsApp 的媒体压缩，并保留解析后的文件名和 MIME 类型
- 在包含多个媒体项的回复中，说明文字应用于第一个媒体项，但 PTT 语音消息除外：音频会先发送且不附带说明文字，然后说明文字会作为单独的文本消息发送（WhatsApp 客户端无法始终一致地呈现语音消息说明文字）
- 媒体源可以是 HTTP(S)、`file://` 或本地路径

</details>

<details>
<summary>媒体大小限制和回退行为</summary>

- 入站保存上限和出站发送上限：`channels.whatsapp.mediaMaxMb`（默认为 `50`）
- 每账户覆盖：`channels.whatsapp.accounts.<id>.mediaMaxMb`
- 除非 `forceDocument`/`asDocument` 请求以文档形式发送，否则图像会自动优化（调整大小/遍历质量）以符合限制
- 媒体发送失败时，针对第一个媒体项的回退行为会发送文本警告，而不会静默丢弃回复

</details>

## 回复引用

`channels.whatsapp.replyToMode` 控制原生回复引用（出站回复会明显引用入站消息）：

| 值             | 行为                                                       |
| ----------------- | -------------------------------------------------------------- |
| `"off"`（默认） | 从不引用；作为普通消息发送                           |
| `"first"`         | 仅引用第一个出站回复分块                      |
| `"all"`           | 引用每个出站回复分块                               |
| `"batched"`       | 引用已排队的批量回复；即时回复不引用 |

每账户覆盖：`channels.whatsapp.accounts.<id>.replyToMode`。

```json5
{ channels: { whatsapp: { replyToMode: "first" } } }
```

## 表情回应级别

`channels.whatsapp.reactionLevel` 控制智能体使用表情符号回应的范围：

| 级别                 | 确认回应 | 智能体主动发起的回应  |
| --------------------- | ------------- | -------------------------- |
| `"off"`               | 否            | 否                         |
| `"ack"`               | 是           | 否                         |
| `"minimal"`（默认） | 是           | 是，采用保守指引 |
| `"extensive"`         | 是           | 是，采用鼓励性指引   |

每账户覆盖：`channels.whatsapp.accounts.<id>.reactionLevel`。

```json5
{ channels: { whatsapp: { reactionLevel: "ack" } } }
```

## 确认回应

`channels.whatsapp.ackReaction` 会在收到入站消息后立即发送回应，该行为受 `reactionLevel` 限制（当 `"off"` 时会被抑制）：

```json5
{
  channels: {
    whatsapp: {
      ackReaction: {
        emoji: "👀",
        direct: true,
        group: "mentions", // always | mentions | never
      },
    },
  },
}
```

注意：入站消息被接受后立即发送（回复前）；如果存在 `ackReaction` 但没有 `emoji`，WhatsApp 会使用路由到的智能体的身份表情符号，并在不可用时回退到“👀”（省略 `ackReaction` 或设置 `emoji: ""` 可禁用确认回应）；失败会被记录，但不会阻止回复发送；群组模式 `mentions` 仅在由提及触发的轮次中做出回应，而群组激活 `always` 会绕过该检查；WhatsApp 仅使用 `channels.whatsapp.ackReaction`（旧版 `messages.ackReaction` 在此处不适用）。

## 生命周期状态回应

设置 `messages.statusReactions.enabled: true` 后，WhatsApp 会在轮次期间替换确认回应，而不是一直保留静态的已接收表情符号，并依次显示已排队、思考中、工具活动、压缩、完成和错误等状态：

```json5
{
  messages: {
    statusReactions: {
      enabled: true,
    },
  },
}
```

注意：`channels.whatsapp.ackReaction` 仍控制私信和群组的适用条件；已排队状态使用与普通确认回应相同的有效表情符号；对于每条消息，WhatsApp 只有一个 Bot 回应槽位，因此生命周期更新会就地替换当前回应，并在最终的完成/错误状态后恢复确认回应。

## 多账户和凭据

<details>
<summary>账户选择和默认值</summary>

账户 ID 来自 `channels.whatsapp.accounts`。如果存在 `default`，则将其选为默认账户；否则选择按字母顺序排序后的第一个已配置账户 ID。账户 ID 会在内部进行规范化以供查找。

</details>

<details>
<summary>凭据路径和旧版兼容性</summary>

- 当前身份验证路径：`~/.openclaw/credentials/whatsapp/<accountId>/creds.json`（备份：`creds.json.bak`）
- 仍会识别/迁移 `~/.openclaw/credentials/` 中的旧版默认身份验证，以用于默认账户流程

</details>

<details>
<summary>登出行为</summary>

`openclaw channels logout --channel whatsapp [--account <id>]` 会清除该账户的 WhatsApp 身份验证状态。当 Gateway 网关可访问时，登出会先停止该账户的实时监听器，因此关联会话会在下次重启前停止接收消息。`openclaw channels remove --channel whatsapp` 也会在禁用或删除账户配置前停止实时监听器。

在旧版身份验证目录中，删除 Baileys 身份验证文件时会保留 `oauth.json`。

</details>

## 工具、操作和配置写入

- Agent 工具支持包括 WhatsApp 表情回应操作（`react`）。
- 操作开关：`channels.whatsapp.actions.reactions`、`channels.whatsapp.actions.polls`（现有操作默认为 `true`）、`channels.whatsapp.actions.calls`（默认值为 `false`，参见上文的 MeowCaller）。
- 默认启用由渠道发起的配置写入；可通过 `channels.whatsapp.configWrites: false` 禁用。

## 故障排查

<details>
<summary>未关联（需要二维码）</summary>

    症状：渠道状态报告未关联。

```bash
openclaw channels login --channel whatsapp
openclaw channels status
```

</details>

<details>
<summary>已关联但断开连接/重新连接循环</summary>

症状：已关联的账户反复断开连接或尝试重新连接。

不活跃的账户可以在超过正常消息超时时间后仍保持连接；仅当 WhatsApp Web 传输活动停止、套接字关闭，或应用级活动保持静默的时间超过较长的安全窗口时，看门狗才会重启（参见上文的运行时模型）。

修复：

```bash
openclaw channels status --probe
openclaw doctor
openclaw logs --follow
openclaw gateway status
```

如果修复主机连接和计时问题后循环仍然存在，请备份账户身份验证目录并重新关联：

```bash
cp -a ~/.openclaw/credentials/whatsapp/<accountId> \
  ~/.openclaw/credentials/whatsapp/<accountId>.bak
openclaw channels logout --channel whatsapp --account <accountId>
openclaw channels login --channel whatsapp --account <accountId>
```

如果 `~/.openclaw/logs/whatsapp-health.log` 显示 `Gateway inactive`，但 `openclaw gateway status` 和 `openclaw channels status --probe` 均显示健康，请运行 `openclaw doctor`。在 Linux 上，Doctor 会对调用已停用 `~/.openclaw/bin/ensure-whatsapp.sh` 脚本的旧版 crontab 条目发出警告；请使用 `crontab -e` 删除这些条目——cron 可能缺少 systemd 用户总线环境，从而导致该旧脚本错误报告 Gateway 健康状况。

</details>

<details>
<summary>通过代理登录时二维码超时</summary>

症状：`openclaw channels login --channel whatsapp` 在显示可用二维码之前失败，并出现 `status=408 Request Time-out` 或 TLS 套接字断开连接。

WhatsApp Web 登录使用 Gateway 网关主机的标准代理环境（`HTTPS_PROXY`、`HTTP_PROXY`、对应的小写变体以及 `NO_PROXY`）。请确认 Gateway 网关进程继承了代理环境，并且 `NO_PROXY` 不匹配 `mmg.whatsapp.net`。

</details>

<details>
<summary>发送时没有活动监听器</summary>

如果目标账户没有活动的 Gateway 网关监听器，出站发送会快速失败。请确认 Gateway 网关正在运行且账户已关联。

</details>

<details>
<summary>回复出现在记录中，但未出现在 WhatsApp 中</summary>

记录行会保存智能体生成的内容；WhatsApp 投递情况会单独检查。只有在至少一次用户可见的文本或媒体发送中，Baileys 返回出站消息 ID 后，OpenClaw 才会将自动回复视为已发送。

确认表情回应是独立于回复前完成的回执——表情回应成功并不能证明后续文本/媒体回复已被接受。请检查 Gateway 网关日志中是否存在 `auto-reply delivery failed` 或 `auto-reply was not accepted by WhatsApp provider`。

</details>

<details>
<summary>群组消息意外被忽略</summary>

请按以下顺序检查：`groupPolicy`、`groupAllowFrom`/`allowFrom`、`groups` 允许列表条目、提及门控（`requireMention` + 提及模式），以及 `openclaw.json` 中的重复键（JSON5 中靠后的条目会覆盖靠前的条目——每个作用域仅保留一个 `groupPolicy`）。

如果存在 `channels.whatsapp.groups`，WhatsApp 仍可观察来自其他群组的消息，但 OpenClaw 会在会话路由之前丢弃这些消息。将群组 JID 添加到 `channels.whatsapp.groups`，或添加 `groups["*"]` 以允许所有群组，同时继续由 `groupPolicy`/`groupAllowFrom` 控制发送者授权。

</details>

<details>
<summary>Bun 运行时警告</summary>

OpenClaw Gateway 网关需要 Node。Bun 不提供规范状态存储所使用的 `node:sqlite` API，Doctor 会将旧版 Bun 服务迁移到 Node。

</details>

## 系统提示词

WhatsApp 通过 `groups` 和 `direct` 映射，为群组和私聊支持 Telegram 风格的系统提示词。

群组消息的解析方式：首先确定有效的 `groups` 映射——只要账户定义了自己的 `groups` 键，它就会完全替换根级 `groups` 映射（不会深度合并）。随后，提示词查找仅在这个最终映射上进行：

1. **群组专属提示词**（`groups["<groupId>"].systemPrompt`）：当群组条目存在，**并且**其 `systemPrompt` 键已定义时使用。空字符串（`""`）会阻止使用通配符且不应用任何提示词。
2. **群组通配符提示词**（`groups["*"].systemPrompt`）：当特定群组条目不存在，或存在但没有 `systemPrompt` 键时使用。

私信的解析方式与此完全相同，但使用的是 `direct` 映射和 `direct["*"]`。

<div class="callout callout-note">

`dms` 仍是轻量级的每私信历史记录覆盖存储桶（`dms.<id>.historyLimit`）。提示词覆盖位于 `direct` 下。

</div>

<div class="callout callout-note">

在提示词解析中，这种“账户替换根级配置”的行为是普通的浅层覆盖：任何账户级 `groups`/`direct` 键（包括显式空对象）都会替换根级映射。它与上文所述的群组成员资格允许列表检查不同；后者针对意外为空的 `groups: {}` 提供单账户安全保护。

</div>

**与 Telegram 的区别：**在多账户设置中，Telegram 会为每个账户禁止使用根级 `groups`（即使账户没有自己的 `groups`），以防止 Bot 接收其不属于的群组消息。WhatsApp 不应用该保护——无论账户数量多少，没有自身覆盖的任何账户都会继承根级 `groups`/`direct`。在多账户 WhatsApp 设置中，如果需要按账户配置提示词，请在每个账户下显式定义完整映射。

重要行为：

- `channels.whatsapp.groups` 既是按群组配置的映射，也是聊天级群组允许列表。在根级或账户级作用域中，`groups["*"]` 表示该作用域“允许所有群组”。
- 仅当你本来就希望该作用域允许所有群组时，才添加通配符 `systemPrompt`。如果只想让固定的一组群组 ID 符合条件，请在每个显式加入允许列表的条目中重复提示词，而不要使用 `groups["*"]`。
- 群组准入和发送者授权是两项独立检查。`groups["*"]` 会扩大可进入群组处理流程的群组范围；它不会授权这些群组中的所有发送者——发送者授权仍由 `groupPolicy`/`groupAllowFrom` 控制。
- `channels.whatsapp.direct` 对私信没有相应的副作用：`direct["*"]` 仅在私信已通过 `dmPolicy` 加 `allowFrom` 或配对存储规则获准后，提供默认配置。

示例：

```json5
{
  channels: {
    whatsapp: {
      groups: {
        // 仅当根级作用域应允许所有群组时使用。
        // 应用于所有未定义自身 groups 映射的账户。
        "*": { systemPrompt: "所有群组的默认提示词。" },
      },
      direct: {
        // 应用于所有未定义自身 direct 映射的账户。
        "*": { systemPrompt: "所有私聊的默认提示词。" },
      },
      accounts: {
        work: {
          groups: {
            // 此账户定义了自己的 groups，因此根级 groups 会被完全
            // 替换。若要保留通配符，也需要在此显式定义 "*"。
            "120363406415684625@g.us": {
              requireMention: false,
              systemPrompt: "专注于项目管理。",
            },
            // 仅当此账户应允许所有群组时使用。
            "*": { systemPrompt: "工作群组的默认提示词。" },
          },
          direct: {
            // 此账户定义了自己的 direct 映射，因此根级 direct 条目会被
            // 完全替换。若要保留通配符，也需要在此显式定义 "*"。
            "+15551234567": { systemPrompt: "特定工作私聊的提示词。" },
            "*": { systemPrompt: "工作私聊的默认提示词。" },
          },
        },
      },
    },
  },
}
```

## 配置参考入口

主要参考：[Configuration reference - WhatsApp](https://funcoding.ai/agents/openclaw/gateway/config-channels/#whatsapp)

| 范畴             | 字段                                                                                                         |
| ---------------- | -------------------------------------------------------------------------------------------------------------- |
| 访问             | `dmPolicy`、`allowFrom`、`groupPolicy`、`groupAllowFrom`、`groups`                                             |
| 投递             | `textChunkLimit`、`streaming.chunkMode`、`mediaMaxMb`、`sendReadReceipts`、`ackReaction`、`reactionLevel`      |
| 多账户           | `accounts.<id>.enabled`、`accounts.<id>.authDir` 及其他按账户覆盖                              |
| 操作             | `configWrites`、`enabled`                                                                                      |
| 入站批处理       | `messages.inbound.debounceMs`、`messages.inbound.byChannel.whatsapp`                                           |
| 会话行为         | `session.dmScope`、`historyLimit`、`dmHistoryLimit`、`dms.<id>.historyLimit`                                   |
| 提示词           | `groups.<id>.systemPrompt`、`groups["*"].systemPrompt`、`direct.<id>.systemPrompt`、`direct["*"].systemPrompt` |

## 相关内容

- [配对](https://funcoding.ai/agents/openclaw/channels/pairing/)
- [群组](https://funcoding.ai/agents/openclaw/channels/groups/)
- [安全](https://funcoding.ai/agents/openclaw/gateway/security/)
- [渠道路由](https://funcoding.ai/agents/openclaw/channels/channel-routing/)
- [多 Agent 路由](https://funcoding.ai/agents/openclaw/concepts/multi-agent/)
- [故障排查](https://funcoding.ai/agents/openclaw/channels/troubleshooting/)
