Claude Platform Docs
Managed Agents將工作委派給您的代理

訂閱 webhook

在重大事件發生時收到通知,無需輪詢。

Session(工作階段)是長時間執行的互動。雖然大多數即時互動是透過 SSE 事件串流進行,但 webhook 會在重大狀態變更時通知您。

Webhook 事件會回傳事件的 typeid,而非完整物件。當您收到 webhook 事件時,需要透過 GET 呼叫直接擷取該物件。這可避免在重試時傳遞過時的資料,並讓每次傳遞保持精簡。

支援的事件類型

其中部分事件的命名與 session 事件串流上對應的事件不同。例如,串流中的 session.status_idlesession.status_running 分別對應 session.status_idledsession.status_run_started webhook 事件。

事件觸發條件
session.status_run_started代理程式開始執行。每次 session 狀態轉換為 running 時都會觸發。
session.status_idled代理程式正在等待輸入,例如工具權限核准或新的使用者訊息。
session.budget_reachedSession 已達到其預算並暫停。對於您設定的每個預算值最多觸發一次;變更預算會再次啟用此事件。
session.status_rescheduled發生暫時性錯誤,session 正在自動重試。
session.status_terminatedSession 已終止,原因可能是發生無法復原的錯誤,或是已被封存。
session.thread_created新的多代理程式執行緒已開啟:由協調者呼叫的額外代理程式正在開始工作,或正在諮詢 session 的顧問
session.thread_idled多代理程式互動中的某個代理程式正在等待輸入。
session.thread_terminated多代理程式執行緒已終止,原因可能是執行緒已被封存,或是已耗盡重試次數。由協調者產生的子執行緒完成工作後會進入 idle,而非 terminated(顧問執行緒在諮詢完成後即終止)。僅針對子執行緒觸發;主執行緒的結束(包括封存整個 session)僅會以 session.status_terminated 呈現。
session.outcome_evaluation_ended單次迭代的結果評估已完成。
session.updatedSession 屬性已變更(例如其名稱或設定已更新)。
session.deletedSession 已永久刪除。已無物件可供擷取,因此請將事件本身視為最終結果。

註冊端點

請前往 Claude Console 中的 Manage > Webhooks

Webhook 端點包含:

  • **URL:**必須是連接埠 443 上的 HTTPS,且主機名稱可公開解析。
  • **事件類型:**此端點接收的 data.type 值清單。端點只會接收其已訂閱的事件。
  • **簽署密鑰:**建立時產生的 32 位元組、以 whsec_ 為前綴的密鑰。它只會顯示一次,因此請妥善保存以驗證 webhook 傳遞。

驗證簽章

每次傳遞都會攜帶 webhook-idwebhook-timestampwebhook-signature 標頭。請使用 SDK 的 unwrap() 輔助函式,一步完成簽章驗證與事件解析。若簽章無效或承載資料已超過 5 分鐘,它會拋出例外。

請將 ANTHROPIC_WEBHOOK_SIGNING_KEY 設定為建立端點時顯示的、以 whsec_ 為前綴的密鑰。

from flask import Flask, request
import anthropic

client = anthropic.Anthropic()  # reads ANTHROPIC_WEBHOOK_SIGNING_KEY from env
app = Flask(__name__)


@app.route("/webhook", methods=["POST"])
def webhook():
    try:
        # 若簽章無效或 payload 已過期,unwrap() 會拋出例外
        event = client.beta.webhooks.unwrap(
            request.get_data(as_text=True),
            headers=dict(request.headers),
        )
    except Exception:
        return "invalid signature", 400

    if event.data.type == "session.status_idled":
        print("session idled:", event.data.id)
    # 處理其他事件類型

    return "", 200

處理事件

解析主體、依 data.type 進行分支,並依 ID 擷取資源。回傳任何 2xx 即表示確認收到。任何其他回應都會對端點造成不利影響:3xx 會立即停用端點(永遠不會跟隨重新導向),而其他失敗則會重試;重試與自動停用規則請參閱傳遞行為

每個事件承載資料都具有相同的結構,包括事件類型、識別碼,以及事件發生時的時間戳記。

{
  "type": "event",
  "id": "whe_9d5c1f7e...",
  "created_at": "2026-03-18T14:05:22Z",
  "data": {
    "type": "session.status_idled",
    "id": "sesn_01XYZ...",
    "organization_id": "8a3d2f1e-...",
    "workspace_id": "c7b0e4d9-..."
  }
}
if event.data.type == "session.status_idled":
    session = client.beta.sessions.retrieve(event.data.id)
    notify_user(session)
return "", 204

頂層的 event.id 是每個事件唯一,而非每次傳遞唯一。若您收到相同的 event.id 兩次,表示這是重試,您可以將其捨棄。

傳遞行為

  • **重複:**端點可能會多次收到同一事件,且每次嘗試都會傳遞相同的頂層 event.id(與 webhook-id 標頭的值相同)。請依此進行去重。

  • **訂閱範圍:**事件只會傳遞給在其發出當下已訂閱該類型的端點。若事件發出時沒有任何端點訂閱其類型,則該事件永遠不會被傳遞,且之後再訂閱也不會回補,因此請在需要之前先訂閱事件類型。

  • **不保證順序。**事件不會依其發生順序傳遞:即使結果先產生,session.status_idled 也可能比 session.outcome_evaluation_ended 先到達;同一資源的 .deleted 事件也可能比 .archived 事件先到達。請依據您擷取的資源來驅動狀態,而非依據事件到達的順序。

  • **重試:**對於每個端點與事件,Anthropic 最多會進行三次傳遞嘗試(觸發自動停用的回應永遠不會重試,詳見本節稍後說明),並在 5 到 120 秒之間採用帶抖動的指數退避。每次嘗試都會傳遞相同的 event.id。最後一次嘗試失敗後,事件即被捨棄:不會排入佇列以供稍後傳遞,也不會有任何訊號表示它已遺失。Webhook 並非持久性日誌,因此若您需要觀察每一次轉換,請透過 API 列出或擷取資源來進行核對。

  • 時間戳記:webhook-timestamp 標頭是在傳遞嘗試簽署時加上的,且每次重試都會重新產生,因此重試不會被 SDK 的時效檢查拒絕。它是傳遞嘗試的時鐘,而非事件的時鐘:請使用事件承載資料中的 created_at 來判斷事件發生的時間。

  • **自動停用:**在以下三種情況下,端點會自動設為 disabled,並附帶機器可讀的 disabled_reason

    • 端點回傳 3xx 回應。永遠不會跟隨重新導向;這會在第一次嘗試時立即停用端點,原因為 auto-disabled: endpoint URL returned a redirect (3xx)。若您的端點已搬移,請在 Console 中更新 URL 並重新啟用端點。
    • 當 Anthropic 連線時,端點的 URL 解析為非公開 IP 位址。這會立即停用端點,原因為 auto-disabled: endpoint URL resolved to an invalid address
    • 對端點的傳遞持續失敗一段時間,原因為 auto-disabled after sustained delivery failures。觸發條件是端點不間斷失敗的持續時間,而非傳遞次數。單一次 2xx 即會重設此時間窗,因此單一不穩定的事件無法停用端點。

    這三種情況皆可復原:解決問題後,請在 Console 中重新啟用端點。端點停用期間發出的事件不會重新播放。

Was this page helpful?