Sessions sind langlaufende Interaktionen. Während die meisten Echtzeit-Interaktionen über den SSE-Event-Stream ablaufen, benachrichtigen dich Webhooks über wichtige Zustandsänderungen.
Webhook-Events liefern den Event-type und die id zurück, nicht das vollständige Objekt. Wenn du ein Webhook-Event empfängst, musst du das Objekt direkt mit einem GET-Aufruf abrufen. Dadurch wird vermieden, dass bei Wiederholungsversuchen veraltete Daten zugestellt werden, und jede Zustellung bleibt klein.
| Event | Auslöser |
|---|---|
session.status_run_started | Die Agent-Ausführung wurde gestartet. Dies wird bei jedem Übergang des Session-Status zu running ausgelöst. |
session.status_idled | Der Agent wartet auf Eingaben, zum Beispiel auf eine Tool-Berechtigungsfreigabe oder eine neue Benutzernachricht. |
session.budget_reached | Die Session hat ihr Budget erreicht und wurde pausiert. Wird höchstens einmal für jeden von dir festgelegten Budget-Wert ausgelöst; eine Änderung des Budgets aktiviert es erneut. |
session.status_rescheduled | Ein vorübergehender Fehler ist aufgetreten und die Session versucht es automatisch erneut. |
session.status_terminated | Die Session wurde beendet, entweder aufgrund eines nicht behebbaren Fehlers oder weil sie archiviert wurde. |
session.thread_created | Ein neuer Multiagent-Thread wurde geöffnet: Ein zusätzlicher Agent, der vom Koordinator aufgerufen wurde, beginnt mit der Arbeit, oder der Advisor der Session wird konsultiert. |
session.thread_idled | Ein Agent in einer Multiagent-Interaktion wartet auf Eingaben. |
session.thread_terminated | Ein Multiagent-Thread wurde beendet, entweder weil der Thread archiviert wurde oder weil er seine Wiederholungsversuche ausgeschöpft hat. Ein vom Koordinator erzeugter Child-Thread, der seine Arbeit abschließt, wechselt zu idle, nicht zu terminated (ein Advisor-Thread wird beendet, sobald seine Konsultation abgeschlossen ist). Wird nur für Child-Threads ausgelöst; das Ende des primären Threads, einschließlich der Archivierung der gesamten Session, wird nur als session.status_terminated gemeldet. |
session.outcome_evaluation_ended | Die Outcome-Evaluierung für eine einzelne Iteration wurde abgeschlossen. |
session.updated | Session-Eigenschaften wurden geändert (zum Beispiel wurde ihr Name oder ihre Konfiguration aktualisiert). |
session.deleted | Die Session wurde dauerhaft gelöscht. Es gibt kein Objekt mehr zum Abrufen, behandle das Event selbst also als final. |
Gehe zu Manage > Webhooks in der Claude Console.
Ein Webhook-Endpunkt besteht aus:
data.type-Werte, die dieser Endpunkt empfängt. Ein Endpunkt empfängt nur Events, die er abonniert hat.whsec_-Präfix, das bei der Erstellung generiert wird. Es wird nur einmal angezeigt, speichere es also sicher, um Webhook-Zustellungen zu verifizieren.Jede Zustellung enthält die Header webhook-id, webhook-timestamp und webhook-signature. Verwende den unwrap()-Helper des SDK, um die Signatur zu verifizieren und das Event in einem Schritt zu parsen. Er wirft eine Exception, wenn die Signatur ungültig ist oder die Payload älter als 5 Minuten ist.
Setze ANTHROPIC_WEBHOOK_SIGNING_KEY auf das Secret mit whsec_-Präfix, das bei der Endpunkt-Erstellung angezeigt wurde.
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() löst eine Exception aus, wenn die Signatur ungültig oder die Payload veraltet ist
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)
# Behandle andere Event-Typen
return "", 200Parse den Body, verzweige anhand von data.type und rufe die Ressource anhand der ID ab. Gib einen beliebigen 2xx-Status zurück, um zu bestätigen. Jede andere Antwort zählt gegen den Endpunkt: Ein 3xx deaktiviert ihn sofort (Redirects werden nie verfolgt), während andere Fehler erneut versucht werden; siehe Zustellverhalten für die Regeln zu Wiederholungsversuchen und automatischer Deaktivierung.
Jede Event-Payload hat dieselbe Struktur, einschließlich des Event-Typs, des Identifiers und des Zeitstempels, wann das Event aufgetreten ist.
{
"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 "", 204Die event.id auf oberster Ebene ist eindeutig pro Event, nicht pro Zustellung. Wenn du dieselbe event.id zweimal empfängst, handelt es sich um einen Wiederholungsversuch und du kannst ihn verwerfen.
Duplikate: Ein Endpunkt kann dasselbe Event mehr als einmal empfangen, und jeder Versuch liefert dieselbe event.id auf oberster Ebene (derselbe Wert wie der webhook-id-Header). Dedupliziere anhand dieser ID.
Abonnement-Umfang: Ein Event wird nur an Endpunkte zugestellt, die seinen Typ zum Zeitpunkt der Ausgabe abonniert haben. Ein Event, das ausgegeben wird, während kein Endpunkt seinen Typ abonniert hat, wird nie zugestellt, und ein späteres Abonnieren füllt es nicht nachträglich auf – abonniere einen Event-Typ also, bevor du ihn brauchst.
Reihenfolge ist nicht garantiert. Events werden nicht in der Reihenfolge zugestellt, in der sie aufgetreten sind: session.status_idled könnte vor session.outcome_evaluation_ended eintreffen, selbst wenn das Outcome zuerst erzeugt wurde, und ein .deleted-Event kann vor dem .archived-Event für dieselbe Ressource eintreffen. Leite deinen Zustand von der Ressource ab, die du abrufst, nicht von der Reihenfolge, in der Events eintreffen.
Wiederholungsversuche: Für jeden Endpunkt und jedes Event unternimmt Anthropic bis zu drei Zustellversuche (eine Antwort, die die automatische Deaktivierung auslöst, wie später in diesem Abschnitt beschrieben, wird nie erneut versucht) mit gestreutem exponentiellem Backoff zwischen 5 und 120 Sekunden. Jeder Versuch liefert dieselbe event.id. Nachdem der letzte Versuch fehlgeschlagen ist, wird das Event verworfen: Es wird nicht für eine spätere Zustellung in eine Warteschlange gestellt und es gibt kein Signal, dass es verloren gegangen ist. Webhooks sind kein dauerhaftes Log – wenn du jeden Übergang beobachten musst, gleiche ab, indem du die Ressource über die API auflistest oder abrufst.
Zeitstempel: Der webhook-timestamp-Header wird gesetzt, wenn ein Zustellversuch signiert wird, und wird bei jedem Wiederholungsversuch neu generiert, sodass Wiederholungsversuche nicht von der Aktualitätsprüfung des SDK abgelehnt werden. Er ist die Uhr für den Zustellversuch, nicht für das Event: Verwende das created_at der Event-Payload für den Zeitpunkt, zu dem das Event aufgetreten ist.
Automatische Deaktivierung: Ein Endpunkt wird in drei Fällen automatisch auf disabled gesetzt, mit einem maschinenlesbaren disabled_reason:
3xx-Antwort zurück. Redirects werden nie verfolgt; dies deaktiviert den Endpunkt sofort, beim ersten Versuch, mit dem Grund auto-disabled: endpoint URL returned a redirect (3xx). Wenn dein Endpunkt umzieht, aktualisiere die URL in der Console und aktiviere den Endpunkt erneut.auto-disabled: endpoint URL resolved to an invalid address.auto-disabled after sustained delivery failures. Der Auslöser ist, wie lange der Endpunkt ohne Unterbrechung fehlgeschlagen ist, nicht eine Anzahl von Zustellungen. Ein einzelner 2xx setzt das Zeitfenster zurück, sodass ein einzelnes fehlerhaftes Event den Endpunkt nicht deaktivieren kann.Alle drei sind reversibel: Aktiviere den Endpunkt in der Console erneut, nachdem du das Problem behoben hast. Events, die ausgegeben wurden, während der Endpunkt deaktiviert war, werden nicht erneut abgespielt.
Was this page helpful?