「Session」(工作階段)是長時間執行的互動。雖然大多數即時互動是透過 SSE 事件串流進行,但 webhook 會在重大狀態變更時通知您。
Webhook 事件會回傳事件的 type 和 id,而非完整物件。當您收到 webhook 事件時,需要透過 GET 呼叫直接擷取該物件。這可避免在重試時傳遞過時的資料,並使每次傳遞保持輕量。
| 事件 | 觸發條件 |
|---|---|
session.status_run_started | 代理程式開始執行。每當工作階段狀態轉換為 running 時都會觸發。 |
session.status_idled | 代理程式正在等待輸入,例如工具權限核准或新的使用者訊息。 |
session.budget_reached | 工作階段已達到其預算並暫停。對於您設定的每個預算值,最多觸發一次;變更預算會重新啟用此事件。 |
session.status_rescheduled | 發生暫時性錯誤,工作階段正在自動重試。 |
session.status_terminated | 工作階段已終止,原因可能是發生無法復原的錯誤,或是工作階段已被封存。 |
session.thread_created | 新的多代理程式執行緒已開啟:由協調器呼叫的額外代理程式正在開始工作,或正在諮詢工作階段的顧問。 |
session.thread_idled | 多代理程式互動中的某個代理程式正在等待輸入。 |
session.thread_terminated | 多代理程式執行緒已終止,原因可能是該執行緒已被封存,或是已用盡重試次數。由協調器產生的子執行緒完成工作後會進入 idle 狀態,而非 terminated(顧問執行緒在諮詢完成後即終止)。僅針對子執行緒觸發;主執行緒的結束(包括封存整個工作階段)僅會以 session.status_terminated 呈現。 |
session.outcome_evaluation_ended | 單次迭代的結果評估已完成。 |
session.updated | 工作階段屬性已變更(例如其名稱或設定已更新)。 |
session.deleted | 工作階段已永久刪除。已無物件可供擷取,因此請將此事件本身視為最終狀態。 |
請前往 Claude Console 中的 Manage > Webhooks。
Webhook 端點包含以下項目:
data.type 值清單。端點只會接收其已訂閱的事件。whsec_ 為前綴的密鑰。此密鑰只會顯示一次,請妥善儲存以驗證 webhook 傳遞。每次傳遞都會帶有 webhook-id、webhook-timestamp 和 webhook-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:
# 若簽章無效或酬載已過期,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 並重新啟用端點。auto-disabled: endpoint URL resolved to an invalid address。auto-disabled after sustained delivery failures。觸發條件是端點連續失敗的時間長度,而非傳遞次數。單一的 2xx 回應即可重設此時間窗口,因此單一不穩定的事件不會導致端點被停用。這三種情況都是可逆的:解決問題後,請在 Console 中重新啟用端點。端點停用期間發出的事件不會被重播。
Was this page helpful?