登入開始免費試用
Meta Tech Provider

在 WhatsApp 號碼上運行 OpenAI Agents SDK 代理程式

將號碼的 Webhook 目的地設為您 Python 應用程式中的一條路由。每收到一則訊息,就以 Runner.run 執行代理程式,並使用以發送者號碼作為鍵的工作階段,然後憑該號碼的存取權杖和電話號碼 ID,透過 Cloud API 把 result.final_output 發送回去。WhatsApp Business 應用程式在同一號碼上照常使用。

SQLiteSession

SDK 內建的工作階段(以檔案或記憶體儲存),會按工作階段 ID 記住先前的對話回合。

params["auth"]

MCPServerStreamableHttp 在此接受 httpx.Auth 或 Authorization 標頭,用於伺服器驗證。

v25.0

Meta 現行發送訊息範例所使用的 Graph API 版本。

WhatsApp 訊息如何變成一次代理程式運行?

透過您自己應用程式中、由 Meta 呼叫的一條路由。將號碼的 Webhook 目的地設為該路由,並在路徑中加入一段較長的隨機密鑰。路由以純文字回傳 hub.challenge 來回應 Meta 的驗證 GET,接受每個 POST,立即回應 200 並把工作加入佇列,因為 Meta 會重試回應過慢的請求,否則代理程式會被執行兩次。

之後由背景工作程式從負載中讀取發送者和文字,並呼叫 Runner.run。傳入一個以發送者號碼作為 ID 的工作階段:SDK 會按該 ID 儲存對話,所以同一位客戶的下一則訊息會接續上一次的內容,兩位客戶也不會共用記錄。起步時使用 SQLiteSession 已足夠;如有多個背景工作程式,SDK 亦提供 Redis 和 SQLAlchemy 工作階段。

這裡的驗證靠的是網址中的密鑰。Meta 使用 Tech Provider 的應用程式密鑰為傳送內容簽署,因此客戶無法驗證簽署標頭。

Worker: run the agent for one message and send the answer
import os, httpx
from agents import Agent, Runner, SQLiteSession

agent = Agent(name="Front desk", instructions="Answer briefly and politely.")
URL = f"https://graph.facebook.com/v25.0/{os.environ['PHONE_NUMBER_ID']}/messages"

async def handle(sender: str, text: str) -> None:
    session = SQLiteSession(sender, "whatsapp.db")
    result = await Runner.run(agent, text, session=session)
    async with httpx.AsyncClient() as http:
        await http.post(
            URL,
            headers={"Authorization": f"Bearer {os.environ['WA_TOKEN']}"},
            json={"messaging_product": "whatsapp", "to": sender,
                  "type": "text", "text": {"body": result.final_output}},
        )

為甚麼應由您的程式碼而非代理程式發送回覆?

因為絕不可違反的那條規則是時間規則,由程式碼執行比由提示詞執行更可靠。客戶發訊息時,Meta 會開啟 24 小時的客戶服務時段。在時段內可以發送自由格式訊息;時段外只能發送已核准的訊息範本,否則自由格式訊息會返回錯誤 131047。

回覆剛剛收到的訊息的背景工作程式必然處於時段內,所以把 result.final_output 當作文字發送,在設計上是安全的。之後才發生的工作,例如翌日早上的跟進或提醒,應走另一條只發送訊息範本、絕不發送自由格式訊息的路徑。

代理程式仍然可以使用工具。您可以提供函式工具讓它查詢資料,例如訂單或預約,而 WhatsApp 的發送則留在背景工作程式內。這樣也能令存取權杖遠離模型可用任意參數呼叫的任何工具。

代理程式可以使用 EasyCoexistence MCP 伺服器嗎?

可以,透過 MCPServerStreamableHttp,但設定比加一個標頭複雜。SDK 接受 Authorization 標頭,或 params["auth"] 中的 httpx.Auth。EasyCoexistence MCP 伺服器會在瀏覽器登入後自行發出 OAuth 權杖,並採用動態客戶端註冊和 PKCE,所以不存在靜態金鑰。MCP Python SDK 附帶 OAuthClientProvider,這是一個執行該流程的 HTTP 驗證處理器,支援 PKCE 和權杖更新,把它放進 params["auth"] 即可。

當您希望代理程式自行決定時就值得這樣做:檢查號碼的健康狀況、讀取訊息範本狀態,或按工具說明中的規則在 send_message 和 send_template 之間選擇。如果只是負責回覆的前台,上面的背景工作程式寫法更短,出錯的機會也更少。

無論哪種做法,Webhook 都要保留。MCP 是請求與回應模式,客戶的訊息只能經由 Meta 呼叫的路由到達代理程式。

常見錯誤

  • 在向 Meta 回傳 200 之前就執行代理程式。回應過慢會被重試,客戶便會收到兩個回覆。
  • 所有客戶共用同一個工作階段。請以發送者號碼作為鍵,否則記錄會混在一起。
  • 讓延遲的跟進發送自由格式訊息。超過 24 小時後會以 131047 失敗,請改為發送訊息範本。
使用 EasyCoexistence 完成這項設定

在 easycoexistence.com 連接號碼,將 Webhook 目的地設為您的路由,並從控制台讀取存取權杖和電話號碼 ID。每個號碼每月 US$ 9 起,隨號碼增加降至 US$ 1,首 3 天免費。

常見問題

這需要使用 OpenAI Responses API 的託管 MCP 工具嗎?

不需要。背景工作程式以 Runner.run 在本機執行代理程式,WhatsApp 一方只是您的程式碼發出的普通 HTTPS 呼叫。

我應該使用哪個 Graph API 版本?

Meta 現行範例使用 v25.0。請在程式碼中的單一位置固定版本,升級時只需改一行。

可以由真人在手機上接手嗎?

可以。Coexistence 讓 WhatsApp Business 應用程式保持可用,而在手機上的回覆會以 echo 事件送到您的路由,背景工作程式可據此暫停代理程式。

EasyCoexistence 會儲存對話嗎?

不會。Meta 直接將訊息傳送到您的路由。工作階段儲存的任何內容,都保存在您自己的資料庫中。

繼續閱讀

準備開始嗎?

幾分鐘內設定 WhatsApp Coexistence,而非幾個月。應用程式在手機上仍可繼續運作。

開始免費試用

驗證日期

在 WhatsApp 使用 OpenAI Agents SDK,Cloud API