章節:訊息平台 · 網址:https://hermesbible.com/docs/user-guide/messaging/whatsapp-cloud
WhatsApp Business Cloud API 設定
Hermes 可以透過 Meta 的官方 WhatsApp Business Cloud API 連線到 WhatsApp。這是生產級的路徑:不需要 Node.js bridge 子程序、不需要 QR code、沒有帳號被封的風險。
代價:
- 你需要一個 Meta Business 帳號(不是個人 WhatsApp)。
- 機器人使用一個專屬的商業電話號碼運作,不是你的私人號碼。
- Hermes gateway 需要一個公開的 HTTPS URL,讓 Meta 透過 webhook 傳送訊息給你。
- 在使用者最後一則訊息後超過 24 小時才回覆的訊息,需要使用預先核准的模板(這是 Meta 的「客服時間窗口」規則,不是 Hermes 的限制)。
如果這些限制不適合你的使用場景,Baileys bridge 整合是另一個選擇——個人帳號、不需要公開 URL,但不是官方的,且有被封的風險。
提示——我該用哪一個?
- Cloud API(本指南)——在營運真正的商業機器人,需要穩定性,能接受 Meta 驗證 + 模板申請的流程
- Baileys bridge——個人專案、快速展示、單一使用者設定,願意承擔機器人電話號碼帳號的風險
快速開始
hermes whatsapp-cloud
設定精靈會引導你完成每個憑證的設定,貼上時逐一驗證(抓住最常見的設定陷阱——把電話號碼貼到 Phone Number ID 欄位),並印出需要在精靈之外手動完成的後續步驟(啟動 cloudflared、設定 Meta 的 webhook 後台)。
本頁其餘內容為手動參考說明。
前置需求
- 一個 Meta Business 帳號。在 business.facebook.com 建立。
- 一個啟用 WhatsApp 的 Meta 應用程式。參見下方「建立 Meta 應用程式」。
- 一個將本地連接埠公開到網際網路的方式,並使用 HTTPS。建議使用 Cloudflare Tunnel (
cloudflared)——免費、不需要連接埠轉發、不需要網域。ngrok、使用自己的網域搭配反向代理 + TLS、或直接綁定到公開 IP 的 VPS 也都可以運作。 - 選擇性但建議安裝:在
PATH中加入 ffmpeg,這樣外送語音訊息會以原生 WhatsApp 語音備註氣泡(綠色波形)顯示,而不是 MP3 音訊附件。Hermes 在缺少 ffmpeg 時仍能正常運作。
建立 Meta 應用程式
- 前往 developers.facebook.com/apps → 建立應用程式。
- 選擇使用案例:「透過 WhatsApp 與客戶互動」 → 下一步。
- 選擇或建立一個商業組合。檢視發布要求。確認 → 建立應用程式。
- 建立完成後會到達自訂使用案例 → 在 WhatsApp 上連結 → 快速入門。點擊開始使用 API → 你現在在 API 設定頁面。
- 確認已連結 WhatsApp Business Account (WABA)。如果你在步驟 3 建立了新的組合,系統會自動建立一個。在 API 設定頁面中確認。
你需要從後台取得以下值——設定精靈會按此順序提示你:
| 值 | 後台位置 | 欄位格式 | 備註 |
|---|---|---|---|
| Phone Number ID | App Dashboard → WhatsApp → API Setup → 「From」下拉選單下方 | 數字,15-17 碼 | 不是電話號碼本身。最常見的設定錯誤就是把真實電話號碼貼到這裡。 |
| Access Token | App Dashboard → WhatsApp → API Setup → 「Generate access token」 | 以 EAA 開頭,100+ 字元 | 暫時性 token 有效期限為 24 小時——生產環境請見下方「永久 token」。 |
| App Secret | App Dashboard → Settings → Basic → 點擊 App secret 旁邊的「Show」 | 32 個字元的小寫十六進位字串 | 用於驗證 incoming webhook 簽章。沒有它,inbound 會被以 503 拒絕。 |
| App ID(選擇性) | App Dashboard → Settings → Basic | 數字,15-16 碼 | 訊息功能不一定要有,但可用於分析。 |
| WABA ID(選擇性) | App Dashboard → WhatsApp → API Setup → 頂部附近 | 數字,15+ 碼 | 訊息功能不一定要有,但可用於分析。 |
永久 token(生產環境)
暫時性 access token 在 24 小時後過期,意思是今天產生的 token 明天就無法使用。生產環境部署請使用 System User 永久 token:
- 前往 business.facebook.com/latest/settings → System users(左側邊欄)。
- 新增 → 命名(例如
hermes-bot)→ 角色:Admin。 - 選擇新使用者 → Assign Assets:
- 選擇你的應用程式 → 在 Full control 下切換 Manage app。
- 選擇你的 WhatsApp 帳號 → 在 Full control 下切換 Manage WhatsApp Business Accounts。
- 點擊 Assign assets。
- Generate token 並勾選以下權限:
business_managementwhatsapp_business_messagingwhatsapp_business_management
- 設定 token expiration: Never。
- 複製 token → 更新
~/.hermes/.env中的WHATSAPP_CLOUD_ACCESS_TOKEN→ 重新啟動 gateway。
System User token 除非你手動撤銷,否則不會過期。
將 Hermes 暴露到網際網路
Cloud API 透過 HTTPS POST 將 inbound 訊息傳送到你的 webhook URL——也就是說 Hermes gateway 必須能從 Meta 的伺服器連線到。有三種常見方式:
Cloudflare Tunnel(建議)
免費、不需要連接埠轉發、適用於 Windows / macOS / Linux。與 gateway 並行運作為獨立程序。
安裝:
# Windows
winget install Cloudflare.cloudflared
# macOS
brew install cloudflared
# Linux
# 從 https://github.com/cloudflare/cloudflared/releases 下載執行檔
執行 quick tunnel(不需要 Cloudflare 帳號——會給你一個 https://<random>.trycloudflare.com 的 URL):
cloudflared tunnel --url http://localhost:8090
記下列印出的 URL——這就是你要給 Meta 的地址。
警告——Quick tunnel 會輪換
免費 quick tunnel 的 URL 在每次重新啟動
cloudflared時都會改變。要取得穩定的 URL,請使用cloudflared tunnel login登入並建立 named tunnel。免費 Cloudflare 帳號可以無限制建立 named tunnel——請參閱 Cloudflare 文件 了解 named tunnel 工作流程。
ngrok
ngrok http 8090
免費版每次重啟都會給不同的 URL。付費版提供穩定的子網域。
自己的網域 + 反向代理
如果你已有伺服器和 TLS 憑證(Caddy、nginx 等),將路由指向 localhost:8090。這是生產環境最穩定的選項,但需要已有的基礎設施。
在 Meta 端設定 webhook
你的 tunnel 運作後:
- 記下你的 tunnel 列印出的公開 URL——例如
https://abc123.trycloudflare.com。 - 產生一個 Verify Token——設定精靈會用
secrets.token_urlsafe(32)幫你產生;如果手動設定,請執行:
將它儲存為python -c "import secrets; print(secrets.token_urlsafe(32))"~/.hermes/.env中的WHATSAPP_CLOUD_VERIFY_TOKEN。 - 啟動 Hermes gateway:
hermes gateway。 - 在 Meta App Dashboard → WhatsApp → Configuration(或 Use cases → Customize → Configuration,依 UI 版本而異)→ 點擊 Webhook 區塊的 Edit。
- 填入:
- Callback URL:
https://abc123.trycloudflare.com/whatsapp/webhook - Verify Token:步驟 2 的字串(必須完全吻合)
- Callback URL:
- 點擊 Verify and save。Meta 會向你的 URL 發送 GET 請求,gateway 回傳 challenge 值,Meta 就會將 webhook 標記為已驗證。
- 在 Webhook fields 下方,點擊 Manage → 訂閱 messages 欄位。這會告訴 Meta 將 inbound 訊息實際傳送到你的 webhook。
手動驗證迴圈(從第三個終端):
TUNNEL="https://abc123.trycloudflare.com"
VERIFY="<your verify token>"
# 應該列印出 HTTP 200,body 為 "hello"
curl -i "$TUNNEL/whatsapp/webhook?hub.mode=subscribe&hub.verify_token=$VERIFY&hub.challenge=hello"
# 健康檢查端點——應該顯示 verify_token_configured: true 和 app_secret_configured: true
curl "$TUNNEL/health"
收件者白名單(Meta 端)
在開發模式(應用程式尚未通過 App Review 之前),Meta 會限制你的機器人可以向哪些號碼發送訊息:
- App Dashboard → WhatsApp → API Setup → To 下拉選單。
- 點擊 Manage phone number list。
- 加入你想要發送訊息的電話號碼(你的、你的團隊的、友善的測試者)。Meta 會透過 SMS 或 WhatsApp 發送每個號碼一個 6 碼驗證碼。
開發模式最多 5 個號碼。通過 App Review 後就能解除此限制。
允許清單(Hermes 端)
除了 Meta 的收件者白名單外,Hermes 還有自己的平台級允許清單,用來控制agent 處理哪些 inbound 訊息。在 ~/.hermes/.env 中加入:
# 逗號分隔的電話號碼,含國碼,不含 '+' / 空格 / 斷字
WHATSAPP_CLOUD_ALLOWED_USERS=15551234567,15557654321
# 或允許所有人(僅在與 Meta 收件者白名單同時使用時才安全)
# WHATSAPP_CLOUD_ALLOW_ALL_USERS=true
設定精靈會在步驟 6 中設定此值。若沒有允許清單,所有 inbound 訊息都會被拒絕——這是刻意設計的,確保即使收件者白名單被放寬,機器人也不會被隨機號碼呼叫。
美化你的機器人 WhatsApp 個人資料
WhatsApp 會在聊天頁面的標題和聯絡人清單中顯示你的機器人名稱和頭像。這些無法透過 Cloud API 設定——它們在 Meta 的 Business Manager 中管理。
機器人運作後,前往 business.facebook.com/wa/manage/phone-numbers,點擊你的電話號碼,你會看到:
| 項目 | 位置 | 備註 |
|---|---|---|
| 顯示名稱 | 電話號碼頁面頂部 | 更改需經過 Meta 的名稱審核流程(約 24–48 小時)。 |
| 頭像圖片 | 電話號碼頁面頂部 | 正方形圖片,建議 ≥640×640px。更新後立即生效。 |
| 關於 / 描述 / 網站 / 電子信箱 / 營業時間 / 分類 | 「Edit profile」按鈕 | 使用者點擊機器人名稱時會在資訊面板中顯示。屬於裝飾性設定。 |
| 已驗證徽章(綠色勾勾) | Business Manager → Security Center → Start Verification | 需要 Meta 獨立的商業驗證流程。 |
hermes whatsapp-cloud 設定精靈會在設定結束時印出這些連結。這些都不是機器人運作所必需的——純粹是為了讓機器人對使用者呈現更好的外觀。
設定參考
所有設定都在 ~/.hermes/.env 中。必填值以粗體標示。
| 變數 | 預設值 | 說明 |
|---|---|---|
WHATSAPP_CLOUD_PHONE_NUMBER_ID | — | API 設定中的 15-17 碼 ID。不是電話號碼。 |
WHATSAPP_CLOUD_ACCESS_TOKEN | — | Meta access token(以 EAA 開頭)。暫時性 24 小時或 System User 永久。 |
WHATSAPP_CLOUD_APP_SECRET | — | 32 碼十六進位字串,從 Settings → Basic 取得。沒有它,inbound 會被以 503 拒絕。 |
WHATSAPP_CLOUD_VERIFY_TOKEN | — | GET 握手用的共享密鑰。設定精靈會自動產生。 |
WHATSAPP_CLOUD_ALLOWED_USERS | — | 逗號分隔的 wa_id,允許這些號碼傳訊息給機器人。 |
WHATSAPP_CLOUD_ALLOW_ALL_USERS | false | 設為 true 可繞過允許清單。 |
WHATSAPP_CLOUD_APP_ID | — | 選擇性,用於未來的分析整合。 |
WHATSAPP_CLOUD_WABA_ID | — | 選擇性,用於未來的分析整合。 |
WHATSAPP_CLOUD_WEBHOOK_HOST | 0.0.0.0 | webhook 伺服器綁定的網路介面。 |
WHATSAPP_CLOUD_WEBHOOK_PORT | 8090 | webhook 伺服器綁定的連接埠。必須與你的 tunnel 轉發的連接埠一致。 |
WHATSAPP_CLOUD_WEBHOOK_PATH | /whatsapp/webhook | Meta POST 的 URL 路徑。 |
WHATSAPP_CLOUD_API_VERSION | v20.0 | Meta Graph API 版本。僅在 Meta 文件建議使用較新版本時才覆寫。 |
WHATSAPP_CLOUD_HOME_CHANNEL | — | 用於作為機器人主頻道的 wa_id(用於排程任務等)。 |
你可以同時啟用 Baileys (whatsapp) 和 Cloud (whatsapp_cloud) 適配器,分別指向不同的電話號碼。
功能
Inbound
- 文字訊息——直接傳遞給 agent。
- 圖片——自動下載並附加到 agent 的輸入中。具有原生視覺能力的模型(Claude、GPT-4o、Gemini 等)直接讀取圖片;非視覺模型會收到自動產生的文字描述。
- 語音備註——自動下載為
.ogg,透過你設定的 STT 供應商(本地 faster-whisper、OpenAI/Nous、Groq 等)轉錄,然後以文字形式交給 agent。 - 文件——自動下載。小型可讀文字檔案(
.txt、.md、.json、.py、.csv等)在 100KB 以內會直接嵌入 agent 的輸入中,讓 agent 不需要透過工具呼叫就能讀取。較大的檔案會在本地快取,供 agent 的其他工具存取。 - 按鈕點擊——當使用者點擊機器人先前傳送的按鈕(澄清選擇、指令核准、斜線指令確認)時,點擊會直接路由到對應的處理器。過期的點擊會降級為一般文字輸入。
- 回覆上下文——當使用者回覆先前的機器人訊息時,agent 會看到原始訊息作為上下文。
Outbound
- 文字——markdown 會自動轉換為 WhatsApp 的格式語法(
**粗體**→*粗體*、~~刪除線~~→~刪除線~、標題 → 粗體、[連結](url)→連結 (url))。長訊息會在 4096 字元處分割。 - 圖片——支援 agent 產生的圖片和本地图像檔案,以原生相片附件形式傳送。
- 語音訊息——文字轉語音輸出透過 ffmpeg 轉換為原生 WhatsApp 語音備註氣泡(綠色波形)。未安裝 ffmpeg 時會降級為 MP3 音訊附件。詳見下方「語音訊息」。
- 影片 / 文件——都支援,以原生附件形式傳送。
互動式 UX
當 agent 呼叫這些流程時,Hermes 使用 WhatsApp 的原生互動式訊息——點擊回答按鈕取代「輸入數字回覆」的提示:
clarify工具——多選問題會渲染為快速回覆按鈕(1–3 個選項)或可點擊展開的列表面板(4+ 個選項)。選擇「✏️ Other」可讓使用者輸入自由文字回答,agent 會收到該回答作為解答。- 危險指令核准——當 agent 的終端 / 程式碼執行碰到需要核准的指令時,使用者會看到
✅ Approve/❌ Deny按鈕,而不需要手動輸入/approve或/deny。 - 斜線指令確認——特权指令如
/reload-mcp會顯示✅ Approve Once/🔒 Always/❌ Cancel按鈕。
所有互動式提示在按鈕無法渲染時(例如舊版 WhatsApp 客戶端)都會優雅降級為純文字。
已讀回條與輸入指示器
Hermes 會立即確認收到 inbound 訊息:
- 你的訊息在 gateway 收到後會顯示藍色雙勾勾。
- 機器人在你的 WhatsApp 聊天中會顯示**「輸入中…」**,在 agent 準備回覆期間。
- 輸入指示器會在機器人的第一則回覆訊息送出時自動消失。
這讓你清楚知道機器人已經看到你的訊息,以及它正在處理回覆的狀態。
語音訊息
WhatsApp 會區分「語音備註」(綠色波形氣泡)和一般音訊檔案附件。差異純粹在於編碼格式:語音備註必須是 audio/ogg 並使用 opus 編碼。
Hermes TTS 產生 MP3。有兩種路徑:
- PATH 中有安裝 ffmpeg(建議)——外送 TTS 會被轉換並以正確的語音備註形式到達。安裝方式:
- Windows:
winget install Gyan.FFmpeg - macOS:
brew install ffmpeg - Linux:套件管理器
- Windows:
- 沒有安裝 ffmpeg——外送 TTS 會以 MP3 音訊附件形式到達。播放正常,只是看起來不像是語音備註。gateway 日誌中會發出一次性警告讓你知道。
你可以透過健康檢查端點確認 gateway 是否找到 ffmpeg:
curl http://localhost:8090/health
# 尋找 "ffmpeg_present": true
已知限制
24 小時對話窗口
Meta 僅允許在使用者最後一則 inbound 訊息後的 24 小時窗口內傳送自由格式訊息。超過此窗口後,Meta 的 API 只接受預先核准的訊息模板。
實際意義:
- 回應式聊天(使用者私訊 → 機器人在 24 小時內回覆 → 使用者回覆 → ...)可以永遠運作。這涵蓋了超過 95% 的正常機器人使用場景。
- 在間隔超過 24 小時後透過 WhatsApp 傳送的排程任務會失敗,並帶有 Graph 錯誤碼
131047(「重新互動訊息」)。 - 長時間運行的
delegate_task非同步結果若超過 24 小時,會以同樣方式失敗。 - Webhook 訂閱者若將外部事件路由到 WhatsApp,在使用者最近沒有私訊機器人的情況下會失敗。
Hermes 會在 system prompt 中提醒 agent 這個窗口的限制,讓模型在安排延遲訊息時知道要提及它。
Hermes 尚未實作訊息模板支援(這是逾時窗口外發送的替代方案)。如果你需要此功能,請提交 issue——已納入計畫但等待明確的需求訊號。
群組聊天
Cloud API 的群組支援有限(依 Meta 的功能等級限制)。Hermes 的 whatsapp_cloud 適配器在 v1 中目前僅處理直接訊息。如果你需要群組聊天功能,請使用 Baileys bridge。
外送速率限制
Meta 的預設吞吐量為每個商業電話號碼每秒 80 則訊息,可付費升級。Hermes 目前不在用戶端強制此限制——極高量的發送可能會觸及 Meta 的限制。
疑難排解
設定驗證失敗(「URL couldn't be validated」)在 Meta 後台
幾乎都是以下原因之一:
- Tunnel URL 錯誤或過期——cloudflared quick tunnel 會輪換。取得新的 URL 並同時更新
.env和 Meta 後台。 - Verify token 不吻合——
~/.hermes/.env中的WHATSAPP_CLOUD_VERIFY_TOKEN必須與你在 Meta 後台輸入的完全一致。先用上述的 curl 探測確認 gateway 的 verify 握手在本地運作正常。 - Gateway 未運行——確認
hermes gateway已啟動。 - App Secret 未設定——沒有它,Hermes 會以 503 拒絕 inbound POST。Meta 會將此解讀為「無法驗證」。
graph error 100:Object with ID '...' does not exist
你把電話號碼(10-11 碼)貼到了 WHATSAPP_CLOUD_PHONE_NUMBER_ID,而不是 Phone Number ID(Meta 的 15-17 碼內部 ID)。請重新檢查 API 設定頁面——Phone Number ID 顯示在「From」下拉選單的下方。
設定精靈現在已加入驗證器來抓出此錯誤,但如果你是手動設定,了解這點仍然有幫助。
graph error 190:Authentication Error
你的 access token 無效。子代碼:
subcode 463——token 過期。暫時性 token 有效期 24 小時。重新產生,或改用 System User 永久 token(見上方)。subcode 467——token 已失效(被撤銷或密碼已變更)。- 其他 190——token 在產生時缺少所需的權限。確認三個權限(
business_management、whatsapp_business_messaging、whatsapp_business_management)都已選取。
graph error 131047:Re-engagement message
24 小時對話窗口已過期(見「已知限制」)。你可以:
- 請求使用者先私訊機器人以重新開啟窗口。
- 等待 Hermes 實作模板支援。
Inbound 訊息:media metadata fetch failed (status=401)
與外送相同的 401 根本原因(graph error 190)——access token 無效或已過期。修正 token。
機器人回覆顯示為原始 JSON / 工具呼叫洩漏
常見原因:為 whatsapp_cloud 設定的工具集中缺少 agent 想要呼叫的工具。檢查 hermes tools list 並確認平台使用的是 hermes-whatsapp(預設的 Cloud 適配器工具集,與 Baileys 相同)。
如果模型產生工具呼叫格式的文字而非結構化呼叫,通常表示工具集實際上是空的。請參閱 hermes_cli/platforms.py 了解平台對應的預設工具集。
STT(語音備註轉錄)回傳空白 / "could not transcribe"
預設的 stt.provider: local 需要 pip install faster-whisper。如果你是 Nous 訂閱者,可以改用 Meta 的託管音訊閘道來處理 STT:
hermes config set stt.provider openai
hermes config set stt.use_gateway true
hermes gateway restart
這會使用你的 Nous Portal access token,而不需要單獨的 OpenAI 金鑰。
安全事項
- 將 App Secret 視為密碼——任何取得它的人都能偽造 webhook 負載,而 Hermes 會將其視為真實。
- Verify token 是共享密鑰——洩漏的風險較低(最壞情況是有人可以將 Meta 的 webhook 重新訂閱到他們自己的 URL),但仍應避免提交到版本控制。
- Access token 是你機器人的身份——System User token 等同於長期有效的 API 金鑰。如果部署遭到入侵,請立即輪換。
- Webhook 端點在設定
WHATSAPP_CLOUD_APP_SECRET後僅接受已簽署的請求——即使在開發環境中也請保持設定。沒有它,gateway 會以 HTTP 503 拒絕 inbound 傳送。 /health端點無需驗證——它是安全的,因為只回報設定是否存在(布林值),不回報實際值。但如果你不想暴露它,請在反向代理 / tunnel 層限制存取。
與 Baileys bridge 的比較
Baileys (hermes whatsapp) | Cloud API (hermes whatsapp-cloud) | |
|---|---|---|
| 帳號類型 | 個人 | 商業 |
| 設定方式 | QR code 掃描 | Meta 應用程式 + WABA + token |
| 相依性 | Node.js + npm | 純 Python(httpx + aiohttp) |
| 程序 | 受管理的 Node 子程序 | aiohttp webhook 伺服器 |
| 需要公開 URL? | 否 | 是 |
| 帳號被封風險 | 有(非官方 API) | 無(官方支援) |
| Inbound | 輪詢 Node bridge | Meta 的 Webhook POST |
| Outbound | 本地 bridge → Baileys | HTTPS 連線到 graph.facebook.com |
| 群組 | 完整支援 | 僅直接訊息(v1) |
| 24 小時窗口 | 無限制 | 硬性限制——逾時後需要模板 |
| 語音備註(外送) | 原生 | 有 ffmpeg 時原生,否則降級為 MP3 |
| 已讀回條 | 無 | 有(藍色雙勾勾) |
| 輸入指示器 | 無 | 有(回覆時自動消失) |
| 互動式按鈕 | 僅文字降級 | 原生(澄清、核准、斜線確認) |
| 生產環境使用 | 有風險(Meta 可能封號) | 專為此設計 |
大部分在個人專案中使用 Hermes 的使用者偏好 Baileys。大部分在營運面向客戶的機器人的使用者偏好 Cloud API。
另請參閱
- Meta 官方 WhatsApp Business Cloud API 文件——底層平台的權威參考,包含定價、App Review 和 Meta 端速率限制。
- WhatsApp (Baileys bridge) 設定——個人專案的替代整合方案。
- 訊息平台總覽——所有訊息整合方案一覽。