sidebar_position: 6 title: “WhatsApp Business (Cloud API)” description: “Set up Hermes Agent as a WhatsApp bot via Meta’s official Business Cloud API”
WhatsApp Business Cloud API 设置指南
Hermes 可通过 Meta 的官方WhatsApp Business Cloud API 与 WhatsApp 进行连接。这是生产级解决方案:无需 Node.js 中间进程,无需二维码,也不会存在账号被封的风险。
但相应地,您需要满足以下条件:
- 您必须拥有 Meta 商业账户(而非个人 WhatsApp 账号);
- 机器人将运行在专用的企业电话号码上,而非您的个人号码;
- Hermes 网关需要一个公开的 HTTPS 地址,以便 Meta 通过 webhook 发送消息;
- 若在用户最后发送消息 24 小时后才回复,则必须使用预先审批好的模板(这是 Meta 的“客户服务时间窗口”规定,并非 Hermes 的限制)。
- 如果这些要求不符合您的使用场景,Baileys 中间件集成方案 是另一种选择——可使用个人账号,无需公开地址,但属于非官方方案,且更容易导致账号被封。
-
::提示 我该选哪种方案?
- Cloud API(本指南所述方式)——用于运行真正的企业级机器人,追求稳定性,愿意接受 Meta 的验证流程及模板审批手续;
- Baileys 中间件——适用于个人项目、快速演示或单用户场景,但需承担机器人所在电话号码被封的风险。 :::
快速入门
hermes whatsapp-cloud
向导会逐步引导您填写每一项凭证,在您输入时实时验证每一项(从而避免最常见的设置错误——将电话号码误填入“电话号码ID”字段),并针对那些需要在向导之外完成的操作(如启动 Cloudflare Tunnel、配置 Meta 的 webhook 控制面板)提供精确的后续操作指南。
本页面的其余部分则为手动参考资料。
先决条件
- 一个 Meta 商家账户。请在 business.facebook.com 上创建。
- 一个已启用 WhatsApp 功能的 Meta 应用。详情请参见下文的“创建 Meta 应用”部分。
- 一种能够通过 HTTPS 将本地端口暴露到公共互联网的方法。推荐使用 Cloudflare Tunnel(
cloudflared)——免费、无需端口转发、也不需要域名。ngrok、带有反向代理和 TLS 的自建域名,或是将网关直接绑定到公网 IP 的 VPS 也同样适用。 - 非必需但推荐:确保系统中包含位于
PATH路径下的 ffmpeg,这样发送的语音消息就会以 WhatsApp 原生的语音气泡形式(绿色波形)呈现,而非 MP3 音频附件。若未安装 ffmpeg,Hermes 仍可正常运行,只是功能会有所受限。
创建 Meta 应用
- 访问 developers.facebook.com/apps,然后选择创建应用。
- 选择使用场景:“通过 WhatsApp 与客户建立联系”,接着点击下一步。
- 选择一个现有的业务组合或创建一个新的。仔细阅读发布要求,确认后点击创建应用。
- 创建完成后,您将进入自定义使用场景 → 通过 WhatsApp 建立联系 → 快速入门页面。点击开始使用 API,即可进入API 设置页面。
- 确保已关联一个 WhatsApp 商业账户(WABA)。如果您在步骤 3 中创建了新的业务组合,系统会自动生成一个账户,请在 API 设置页面中进行验证。
向导会按顺序要求您提供控制面板中的以下信息:
| 值 | 控制面板位置 | 字段类型 | 备注 |
|---|---|---|---|
| 电话号码 ID | 应用控制面板 → WhatsApp → API 设置 → “发件人”下拉菜单下方 | 数字,15–17位 | 并非电话号码本身。最常见的错误就是将实际的电话号码粘贴至此处。 |
| 访问令牌 | 应用控制面板 → WhatsApp → API 设置 → “生成访问令牌” | 以 EAA 开头,长度超过100个字符 | 临时令牌有效期为24小时——如需用于正式环境,请参阅下方的“永久令牌”。 |
| 应用密钥 | 应用控制面板 → 设置 → 基本设置 → 点击“显示”按钮 | 32位小写十六进制字符串 | 用于验证传入的webhook签名。若缺少此密钥,消息将因503错误而被拒绝接收。 |
| 应用 ID(可选) | 应用控制面板 → 设置 → 基本设置 | 数字,15–16位 | 发送消息时并非必需,但有助于数据分析。 |
| WABA ID(可选) | 应用控制面板 → WhatsApp → API 设置 → 顶部附近 | 数字,15位以上 | 发送消息时并非必需,但有助于数据分析。 |
永久令牌(正式环境)
临时访问令牌的有效期为24小时,这意味着今天生成的令牌次日就会失效。对于正式环境部署,应使用系统用户永久令牌:
- 访问 business.facebook.com/latest/settings,在左侧导航栏中选择 System users。
- 点击 Add,输入名称(例如
hermes-bot),然后设置角色为 Admin。 - 选中新创建的用户,接着点击 Assign Assets:
- 选择您的应用,在“Full control”选项下开启 Manage app。
- 选择您的 WhatsApp 账户,在“Full control”选项下开启 Manage WhatsApp Business Accounts。
- 点击 Assign assets。
- 使用以下权限生成令牌:
business_managementwhatsapp_business_messagingwhatsapp_business_management
- 将令牌的过期时间设置为 Never。
- 复制生成的令牌,将其内容更新到
~/.hermes/.env文件中的WHATSAPP_CLOUD_ACCESS_TOKEN字段,最后重启网关。
除非您主动撤销,否则系统用户令牌不会过期。
将 Hermes 接入互联网
Cloud API 会通过 HTTPS POST 方式将接收到的消息发送到您的 webhook 地址——这意味着 Hermes 网关必须能够被 Meta 的服务器访问。通常有以下三种实现方式:
Cloudflare Tunnel(推荐)
免费且无需端口转发,支持 Windows、macOS 和 Linux 系统。该方案作为独立进程与网关一同运行。
安装步骤:
# Windows
winget install Cloudflare.cloudflared
# macOS
brew install cloudflared
# Linux
# Download the binary from https://github.com/cloudflare/cloudflared/releases
快速创建隧道(无需 Cloudflare 账户——即可生成一个 https://<随机字符串>.trycloudflare.com 的网址):
cloudflared tunnel --url http://localhost:8090
- 请记下显示的URL——这就是您需要提供给Meta的地址。
-
::warning 快速隧道会定期更换 每次重新启动
cloudflared后,免费的快速隧道URL都会发生变化。如需使用稳定的URL,请通过cloudflared tunnel login登录并创建一个命名隧道。免费Cloudflare账户可创建无限数量的命名隧道——有关命名隧道的操作流程,请参阅Cloudflare官方文档。 -
::
ngrok
ngrok http 8090
免费套餐在每次重启后都会显示不同的网址,而付费套餐则能为您提供稳定的子域名。
自有域名 + 反向代理
如果您已拥有配备 TLS 证书的服务器(如 Caddy、nginx 等),只需将路由指向 localhost:8090 即可。这是最适用于生产环境的稳定方案,但需要您预先准备好相关基础设施。
在 Meta 端配置 webhook
当您的隧道开始运行后:
- 记下隧道生成的公开网址——例如
https://abc123.trycloudflare.com。 - 生成一个验证令牌——向导会自动使用
secrets.token_urlsafe(32)为您生成;如果您选择手动配置,则需执行相应命令:python -c "import secrets; print(secrets.token_urlsafe(32))"
在 ~/.hermes/.env 文件中,将该值保存为 WHATSAPP_CLOUD_VERIFY_TOKEN。
3. 启动 Hermes 网关:执行命令 hermes gateway。
4. 进入 Meta 应用控制面板 → WhatsApp → Configuration(具体路径可能因界面版本不同而显示为 Use cases → Customize → Configuration)→ 点击 Webhook 部分下的 Edit 按钮。
5. 填写以下内容:
- Callback URL:
https://abc123.trycloudflare.com/whatsapp/webhook - Verify Token:步骤 2 中获得的字符串(必须完全一致)
- 点击 Verify and save。Meta 会通过 GET 请求访问您的 URL,网关会回传验证挑战信息,随后 Meta 会将该 Webhook 标记为已验证。
- 在 Webhook fields 下方,点击 Manage → 订阅 messages 字段。这样即可告知 Meta 将接收到的消息实际发送到您的 Webhook。
如需手动测试此流程(可在第三个终端中操作):
TUNNEL="https://abc123.trycloudflare.com"
VERIFY="<your verify token>"
# Should print HTTP 200 with body "hello"
curl -i "$TUNNEL/whatsapp/webhook?hub.mode=subscribe&hub.verify_token=$VERIFY&hub.challenge=hello"
# Health endpoint — should show verify_token_configured: true and app_secret_configured: true
curl "$TUNNEL/health"
收件人白名单(Meta端)
在开发模式下(即您的应用尚未通过应用审核之前),Meta会限制机器人可以发送消息的号码范围:
- 进入“应用控制面板”→“WhatsApp”→“API设置”→收件人下拉菜单。
- 点击管理手机号码列表。
- 添加您希望向其发送消息的手机号码(包括您自己的、团队成员的以及合作测试人员的号码)。Meta会通过短信或WhatsApp向每个号码发送一个6位数的验证码。
在开发模式下最多支持5个号码。一旦应用进入审核流程,此限制将被取消。
允许列表(Hermes端)
除了Meta设定的收件人白名单外,Hermes还拥有针对不同平台的独立允许列表,用于控制机器人需要处理哪些来电消息。请在~/.hermes/.env文件中添加相应配置:
# Comma-separated phone numbers, country code, no '+' / spaces / dashes
WHATSAPP_CLOUD_ALLOWED_USERS=15551234567,15557654321
# Or allow everyone (only safe in combination with Meta's recipient whitelist)
# WHATSAPP_CLOUD_ALLOW_ALL_USERS=true
向导会在第6步中设置此项。若没有允许列表,所有传入的消息都将被拒绝——这是有意为之,这样即便接收者白名单的管控力度有所放宽,也无法让随机号码调用该机器人。
完善机器人的 WhatsApp 个人资料
WhatsApp 会在聊天界面标题和联系人列表中显示机器人的名称和头像。这些内容无法通过 Cloud API 设置,而需在 Meta 的 Business Manager 中进行配置。
一旦机器人开始运行,请访问 business.facebook.com/wa/manage/phone-numbers,点击对应的电话号码,即可看到以下选项:
| 项目 | 所在位置 | 备注 |
|---|---|---|
| 显示名称 | 电话号码页面顶部 | 更改内容需经过 Meta 的名称审核流程(约24–48小时)。 |
| 头像 | 电话号码页面顶部 | 建议使用正方形图片,尺寸至少为640×640像素。更改后会立即生效。 |
| 简介/描述/网站/邮箱/服务时间/类别 | “编辑个人资料”按钮 | 用户点击机器人名称时,这些信息会显示在信息窗格中,仅用于美化展示。 |
| 已验证徽章(绿色对勾) | Business Manager → 安全中心 → 开始验证 | 需要经过 Meta 独立的商家验证流程。 |
hermes whatsapp-cloud 向导会在设置流程的最后提供这些链接。虽然这些内容并非机器人运行的必需项,但它们能提升机器人在用户眼中的呈现效果。
配置参考
所有设置均保存在 ~/.hermes/.env 文件中。必填值以粗体标出。
| 参数名 | 默认值 | 说明 |
|---|---|---|
WHATSAPP_CLOUD_PHONE_NUMBER_ID | — | 来自 API 设置的 15–17 位数字标识符,并非电话号码。 |
WHATSAPP_CLOUD_ACCESS_TOKEN | — | Meta 访问令牌(以 EAA 开头),有效期为 24 小时,或为系统用户永久有效。 |
WHATSAPP_CLOUD_APP_SECRET | — | 来自“设置”→“基本信息”选项的 32 位十六进制字符串,缺少该值会导致接收消息时返回 503 错误。 |
WHATSAPP_CLOUD_VERIFY_TOKEN | — | 用于 GET 请求鉴权的共享密钥,由向导自动生成。 |
WHATSAPP_CLOUD_ALLOWED_USERS | — | 以逗号分隔的 wa_ids 列表,指定允许向该机器人发送消息的用户。 |
WHATSAPP_CLOUD_ALLOW_ALL_USERS | false | 设置为 true 可绕过用户白名单限制。 |
WHATSAPP_CLOUD_APP_ID | — | 可选参数,用于未来集成分析功能。 |
WHATSAPP_CLOUD_WABA_ID | — | 可选参数,用于未来集成分析功能。 |
WHATSAPP_CLOUD_WEBHOOK_HOST | 未设置(双栈模式:支持 IPv4 和 IPv6 的所有接口) | Webhook 服务器绑定的接口地址。 |
WHATSAPP_CLOUD_WEBHOOK_PORT | 8090 | Webhook 服务器绑定的端口号,必须与隧道转发的端口一致。 |
WHATSAPP_CLOUD_WEBHOOK_PATH | /whatsapp/webhook | Meta 发送消息的 URL 路径。 |
WHATSAPP_CLOUD_API_VERSION | v20.0 | Meta Graph API 版本,仅当 Meta 的文档推荐使用更高版本时才需修改。 |
WHATSAPP_CLOUD_HOME_CHANNEL | — | 用作机器人主通道的 wa_id(用于定时任务等场景)。 |
您可以将 Baileys(whatsapp)和 Cloud(whatsapp_cloud)两种适配器同时启用,针对不同的电话号码分别使用。 |
功能特性
接收消息
- 文本消息——直接传递给智能体。
- 图片——自动下载并附加到智能体的输入内容中。具备原生视觉功能的模型(如 Claude、GPT-4o、Gemini 等)可直接读取图片;不具备视觉功能的模型则会收到自动生成的文本描述。
- 语音备忘录——自动下载为
.ogg格式,通过您配置的文本转语音服务(如本地的 faster-whisper、OpenAI/Nous、Groq 等)进行转录,之后以文本形式传递给智能体。 - 文档——自动下载。大小不超过 100KB、可读性良好的文本文件(如
.txt、.md、.json、.py、.csv等)会直接嵌入到智能体的输入内容中,使其无需调用其他工具即可读取。较大文件则会缓存在本地,供智能体的其他工具使用。 - 按钮点击——当用户点击机器人先前发送的按钮(如确认选项、批准指令、确认斜杠命令)时,该点击操作会直接路由到对应的处理函数。过期的点击操作则会被视为普通文本输入处理。
- 回复上下文——当用户对机器人之前的消息进行回复时,智能体可以将原始消息作为上下文信息获取。
发送消息
- 文本 — Markdown 格式会自动转换为 WhatsApp 特有的语法格式(
**粗体**→*粗体*,~~删除线~~→~删除线~,标题则变为粗体,[链接](url)→链接 (url))。过长的消息会按每 4096 个字符拆分传输。 - 图片 — 支持由智能体生成的图片以及本地图片文件,均会以原生照片附件的形式发送。
- 语音消息 — 文本转语音功能会通过 ffmpeg 转换为 WhatsApp 原生的语音消息格式(绿色波形图标)。若未安装 ffmpeg,则会退化为 MP3 音频附件。详情请参见下文的“语音消息”部分。
- 视频/文档 — 两者均受支持,将以原生附件的形式发送。
交互式用户体验
当智能体触发上述任意流程时,Hermes 会使用 WhatsApp 原生的交互式消息功能——通过点击按钮来回应,而非要求用户输入“回复编号”:
clarify工具 — 多项选择题会以快速回复按钮的形式呈现(1–3 个选项),或通过点击打开列表页(4 个及以上选项)。选择“✏️ 其他”后,用户可输入自由文本作为答案,智能体将此内容视为最终解答。- 危险命令审批 — 当智能体的终端/代码执行遇到受限命令时,用户会看到
✅ 批准/❌ 拒绝按钮,而无需手动输入/approve或/deny。 - 斜杠命令确认 — 对于如
/reload-mcp这类具有特殊权限的命令,系统会显示✅ 仅批准一次/🔒 始终允许/❌ 取消等按钮。
如果在某些情况下无法显示这些按钮(例如在旧版 WhatsApp 客户端上),所有交互式提示都会自动降级为纯文本形式。
已读回执与输入状态指示
Hermes 会立即确认收到的消息:
- 一旦网关接收到您的消息,它就会显示蓝色双对勾。
- 当智能体正在准备回复时,WhatsApp 聊天窗口中的机器人名称会显示为“正在输入…”。
- 一旦智能体发出首条回复消息,该输入状态指示便会自动消失。
这样一来,就能清楚地分辨出机器人何时已看到您的消息,以及何时仍在处理回复。
语音消息
WhatsApp 会将“语音便签”(绿色波形气泡)与普通音频文件附件区分开来。两者的区别仅在于编码格式:语音便签必须为采用 opus 编码的 audio/ogg 格式。
而 Hermes 的文本转语音功能则生成 MP3 格式的音频。有两种处理方式:
- 系统路径中已安装 ffmpeg(推荐)——输出的语音内容会被转换为标准的语音便签格式。安装方法如下:
- Windows:
winget install Gyan.FFmpeg - macOS:
brew install ffmpeg - Linux:通过对应包管理器安装
- Windows:
- 未安装 ffmpeg——输出的语音内容将以 MP3 音频附件的形式发送。虽然可以正常播放,但外观上并非语音便签格式。网关日志中会记录一次警告信息,以便您知晓。
您可以通过健康检查接口来查看网关是否找到了 ffmpeg:
curl http://localhost:8090/health
# look for "ffmpeg_present": true
已知限制
24小时对话窗口限制
Meta仅允许在用户最后一次发送消息后的24小时窗口内发送自由格式消息。超出该时间窗口后,Meta的API仅能接收经过预先审批的消息模板。
实际应用中的含义:
- 反向聊天模式(用户发送私信 → 机器人在24小时内回复 → 用户再次回复……)可永久使用,这涵盖了95%以上的常规机器人使用场景。
- 若通过定时任务在24小时间隔后向WhatsApp发送消息,将会因Graph错误代码
131047(“重新互动消息”)而失败。 - 耗时超过24小时的长时间运行的
delegate_task异步操作也会出现同样的失败情况。 - 那些将外部事件路由到WhatsApp的Webhook订阅者,在用户近期未向机器人发送私信时也会失效。
Hermes会在其系统提示中向代理发出关于此时间窗口的限制警告,因此模型在安排延迟发送的消息时会自动提及这一点。
目前Hermes尚未实现消息模板支持功能(即用于处理窗口外发送消息的替代方案)。如果您需要该功能,请提交问题——该功能已有规划,但仍在等待明确的用户需求信号。
群组聊天
Cloud API对群组聊天的支持较为有限(具体能力由Meta控制)。在v1版本中,Hermes的whatsapp_cloud适配器仅支持直接消息。如果您需要处理群组聊天,请使用Baileys桥接方案。
发送消息速率限制
Meta的默认吞吐量为每个企业电话号码每秒80条消息,也可选择升级更高额度。Hermes目前并未在客户端侧强制执行此限制——但超高频率的发送操作仍可能触及Meta的限制。
故障排除
在Meta控制台中出现设置验证失败(“无法验证URL”)的情况
通常由以下原因之一导致:
- 隧道URL错误或已过期——cloudflared的快速隧道会定期更换。请获取新的URL,并同步更新
.env文件及Meta控制台中的配置。 - 验证令牌不匹配——
~/.hermes/.env文件中WHATSAPP_CLOUD_VERIFY_TOKEN字段的值必须与在Meta控制台输入的值完全一致。建议先运行上述curl测试,确认本地网关的验证流程能够正常工作。 - 网关未运行——请检查
hermes gateway服务是否处于启动状态。 - 未设置应用密钥——若缺少该密钥,Hermes会以503错误拒绝接收POST请求,而Meta则会将其解读为“无法验证”。
graph error 100:编号为‘…’的对象不存在
您可能将电话号码(10-11位)直接填入了WHATSAPP_CLOUD_PHONE_NUMBER_ID字段,而非Meta系统使用的电话号码ID(15-17位内部编号)。请重新查看API设置页面——电话号码ID显示在“发件人”下拉菜单的下方。
虽然现在向导已通过验证工具检测此类错误,但如果您是手动配置的话,了解这一点仍很有帮助。
graph error 190:认证错误
您的访问令牌无效。相关子代码包括:
subcode 463— 令牌已过期。临时令牌的有效期为24小时。请重新生成令牌,或切换为系统用户的永久令牌(参见上文)。subcode 467— 令牌失效(已被撤销或密码已更改)。- 其他值190 — 生成的令牌不具备所需的权限。请确保已选中全部三项权限:
business_management、whatsapp_business_messaging和whatsapp_business_management。
graph error 131047:重新建立对话提示
24小时的对话窗口已到期(参见“已知限制”)。您可以:
- 要求用户先通过私信与机器人沟通,以重新开启对话窗口;
- 等待Hermes支持模板功能。
接收到的消息:media metadata fetch failed (status=401)
其根本原因与发送消息时出现的401错误相同(graph error 190)——访问令牌无效或已过期。请修复该令牌。
机器人的回复显示为原始JSON格式/工具调用信息泄露
常见原因在于为whatsapp_cloud配置的工具集缺少机器人所需调用的工具。请查看hermes tools list,并确认平台使用的是hermes-whatsapp(即默认的云适配器工具集,与Baileys相同)。
如果模型输出的内容呈现为类似工具调用的文本,而非结构化的调用指令,通常意味着工具集实际上为空。有关平台与默认工具集的对应关系,请参阅hermes_cli/platforms.py文件。
STT(语音笔记转录)功能返回空值/“无法转录”
默认的 stt.provider: local 设置需要先执行 pip install faster-whisper。如果您是 Nous 的订阅用户,可以通过托管网关来实现文本转语音功能——在 hermes tools 中选择 Nous Subscription 选项,或直接进行相应设置即可。
hermes config set stt.provider nous
hermes gateway restart
该方案使用您的 Nous Portal 访问令牌,无需单独的 OpenAI 密钥。(旧版文档建议设置 stt.use_gateway true——该标志已过时;如今路由逻辑仅由提供商选择来决定。)
安全注意事项
- 将应用密钥视同密码对待——任何获取到该密钥的人都可以伪造 webhook 请求体,而 Hermes 会将其视为合法数据予以接收。
- 验证令牌属于共享密钥——虽然其泄露带来的风险相对较低(最坏情况下只是有人将自己的 Meta webhook 重新指向其他网址),但仍应避免将其泄露。
- 访问令牌代表您机器人的身份——系统用户令牌相当于长期有效的 API 密钥。若部署环境遭到入侵,应立即更换令牌。
- 当设置了
WHATSAPP_CLOUD_APP_SECRET时,webhook 端点仅接受已签名请求——即使在开发环境中也应保持该设置。若未设置,网关会以 HTTP 503 错误拒绝接收请求。 /health端点无需身份验证——由于它仅返回配置是否存在的相关布尔值,而非具体配置内容,因此公开该端点是安全的。但如果您不愿公开它,也可在反向代理或隧道层进行访问限制。
与 Baileys bridge 的对比
Baileys(hermes whatsapp) | 云 API(hermes whatsapp-cloud) | |
|---|---|---|
| 账户类型 | 个人账户 | 商业账户 |
| 设置方式 | 扫描二维码 | Meta 应用 + WABA + 令牌 |
| 依赖环境 | Node.js + npm | 纯 Python(httpx + aiohttp) |
| 处理流程 | 由 Node 子进程管理 | aiohttp Webhook 服务器 |
| 是否需要公开 URL? | 不需要 | 需要 |
| 账户被封风险 | 有(非官方 API) | 无(官方支持) |
| 接收消息方式 | 通过 Node 桥接轮询 | 来自 Meta 的 Webhook POST 请求 |
| 发送消息方式 | 本地桥接 → Baileys | 通过 HTTPS 连接到 graph.facebook.com |
| 群组功能 | 完全支持 | 仅支持私信(v1版本) |
| 24小时使用限制 | 无限制 | 有严格限制——之后必须使用模板 |
| 发送语音消息 | 原生支持 | 原生支持,否则会通过 ffmpeg 转换为 MP3格式 |
| 已读回执 | 不支持 | 支持(显示蓝色双对勾) |
| 输入中状态指示 | 不支持 | 支持(收到回复后会自动消失) |
| 交互式按钮 | 仅支持文本选项 | 原生支持(包括“确认”、“批准”、“slash-confirm”等功能) |
| 生产环境使用 | 存在风险(可能被 Meta 封禁) | 专为生产环境设计 |
大多数将 Hermes 用于个人项目的用户更倾向于选择 Baileys,而那些开发面向客户的机器人的用户则更常选择云 API。
参见
- Meta 官方 WhatsApp Business Cloud API 文档——涵盖底层平台规则、定价标准、应用审核流程以及 Meta 端的速率限制等权威参考信息。
- WhatsApp(Baileys bridge)集成指南——适用于个人项目的替代集成方案。
- 消息平台概览——一键查看所有消息集成功能。