Session-Event-Stream
Sende Events, streame Antworten und unterbrich oder lenke deine Session während der Ausführung um.
Die Kommunikation mit Claude Managed Agents ist eventbasiert. Du sendest User-Events an den Agenten und erhältst Agent- und Session-Events zurück, um den Status zu verfolgen.
Event-Typen
Events fließen in zwei Richtungen.
- User-Events und System-Events sind das, was du an den Agenten sendest:
user.*-Events starten eine Session und steuern sie, während sie fortschreitet;system.messagehängt Kontext auf Systemebene an, der für den begleitenden Turn und alle nachfolgenden Turns gilt. - Session-Events, Span-Events und Agent-Events werden an dich gesendet, um Einblick in deinen Session-Zustand und den Fortschritt des Agenten zu geben. Stream-Verbindungen, die sich dafür anmelden, erhalten außerdem Event-Deltas.
Die Typ-Strings von Session-, Span-, Agent-, User- und System-Events folgen einer Namenskonvention {domain}.{action}. Die nur im Stream vorkommenden Delta-Vorschau-Events (event_start, event_delta) sind die Ausnahme. Siehe Event-Typen in der Referenz für den vollständigen Katalog. Webhook-Event-Typen sind davon getrennt, und einige ihrer Namen unterscheiden sich von denen des Streams (zum Beispiel session.status_idled statt session.status_idle).
Jedes persistierte Event enthält einen processed_at-Zeitstempel, der gesetzt wird, wenn die Verarbeitung des Events abgeschlossen ist. Bei Events, die du sendest, ist processed_at null, solange das Event noch hinter früheren Events in der Warteschlange steht. Die Ausnahmen sind user.define_outcome, user.custom_tool_result und user.tool_result, die bei Empfang verarbeitet und mit bereits befülltem processed_at zurückgespiegelt werden.
Events integrieren
Sende ein user.message-Event, um die Arbeit des Agenten zu starten oder fortzusetzen:
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "user.message",
"content": [
{
"type": "text",
"text": "Analyze the performance of the sort function in utils.py",
},
],
},
],
)Sende ein user.interrupt-Event, um den Agenten während der Ausführung zu stoppen, und schicke anschließend ein user.message-Event, um ihn umzulenken:
# Agent analysiert gerade eine Datei...
# Unterbrich mit einer neuen Anweisung:
client.beta.sessions.events.send(
session.id,
events=[
{"type": "user.interrupt"},
{
"type": "user.message",
"content": [
{
"type": "text",
"text": "Instead, focus on fixing the bug in line 42.",
},
],
},
],
)Der Aufruf kehrt zurück, sobald die Events in die Warteschlange gestellt sind, und das processed_at des Interrupts bleibt null, bis der Agent ihn anwendet. Eine laufende Modellantwort stoppt sofort. Das Anwenden des Interrupts kann länger dauern, während Tool-Aufrufe laufen, und die Session bleibt running, bis dies geschieht. Das user.interrupt-Event erscheint dann im Stream, und der unterbrochene Turn endet mit einem session.status_idle-Event. Dessen stop_reason ist end_turn, derselbe Wert wie bei einem Turn, der von selbst endet; es gibt keinen Stop-Reason speziell für Unterbrechungen. Der Agent beginnt seinen nächsten Turn mit der user.message, die du nach dem Interrupt gesendet hast.
Event-Deltas
Standardmäßig erreicht der Antworttext des Agenten den Stream als gepufferte agent.message-Events, die jeweils erst ausgegeben werden, nachdem die Modellanfrage, die sie erzeugt hat, abgeschlossen ist. „Event deltas“ (Event-Deltas) ermöglichen es dir, diesen Text inkrementell als Live-Vorschau zu rendern, während das Modell ihn noch generiert. Eine Vorschau ist nicht die Antwort: Vorschauen sind eine Best-Effort-Anzeigehilfe, und die gepufferte agent.message ist immer der maßgebliche Datensatz. Ein Client, der Vorschauen ignoriert, erhält dennoch einen vollständigen, korrekten Stream.
Für Vorschauen anmelden
Vorschauen sind pro Stream-Verbindung opt-in. Füge den Query-Parameter event_deltas[] zu dem Stream hinzu, den du liest, und wiederhole ihn einmal für jeden Event-Typ, für den du eine Vorschau möchtest. Da [] ein Shell-Glob-Muster ist, setze die URL in Anführungszeichen, wenn du die Anfrage in einer Shell erstellst; die Beispiele kodieren die Klammern prozentual als %5B%5D, was ebenfalls funktioniert. Beide Stream-Endpunkte akzeptieren den Parameter: der Stream auf Session-Ebene unter GET /v1/sessions/{session_id}/events/stream und der eigene Stream jedes Session-Threads unter GET /v1/sessions/{session_id}/threads/{thread_id}/stream. Die akzeptierten Werte sind agent.message und agent.thinking; jeder andere Wert gibt einen 400-Fehler zurück, ebenso wie eine Anfrage mit mehr als 100 Werten. Die Vorschauen eines Subagenten erscheinen im eigenen Thread-Stream dieses Subagenten.
Wenn ein Event mit Vorschau beginnt, gibt der Stream ein event_start aus, das den Typ und die id des kommenden Events trägt:
{
"type": "event_start",
"event": {
"type": "agent.message",
"id": "sevt_01abc..."
}
}Bei agent.message folgen auf den Start event_delta-Events, die inkrementellen Text tragen. Jedes Delta benennt das Event, das es erweitert, in event_id und den Content-Block, den es erweitert, in delta.index:
{
"type": "event_delta",
"event_id": "sevt_01abc...",
"delta": {
"type": "content_delta",
"index": 0,
"content": {
"type": "text",
"text": "Here is the summary"
}
}
}Wenn ein agent.thinking-Event als Vorschau angezeigt wird, wird nur das event_start ausgegeben. Es folgen keine event_delta-Events, und das gepufferte agent.thinking-Event, das die Vorschau abschließt, trägt keinen Thinking-Inhalt; es ist ein Fortschrittssignal, kein Inhaltsträger.
Anders als persistierte Events haben event_start und event_delta keine eigene id oder processed_at. Der einzige Bezeichner, den sie tragen, ist die id des Events, für das sie eine Vorschau liefern.
Akkumulieren und abgleichen
Jedes SDK, das Event-Deltas unterstützt, enthält einen Akkumulator-Helper, der die index-Buchführung für dich übernimmt. Die Helper für Go, Java, Ruby und C# schlüsseln die akkumulierende Vorschau zusätzlich nach der id des Events; bei den Helpern für Python, TypeScript und PHP führst du diese Map selbst und fügst jedes Delta in den Eintrag für seine id ein. Das manuelle Muster funktioniert ebenfalls in jeder Sprache, wenn du eine eigene Buchführung benötigst: Wende es auf die generierten Event-Typen an.
Behandle im manuellen Muster die Vorschau als Scratch-Puffer und das gepufferte Event als den Datensatz. Schlüssele den Puffer nach (event_id, index). Gleiche pro Modellanfrage ab: Ein Turn beginnt mit einem einzelnen session.status_running-Event, dann erzeugt bei einem Turn, der normal abschließt, jede Modellanfrage der Reihe nach span.model_request_start, event_start, die event_delta-Events, die gepufferte agent.message und schließlich span.model_request_end (im Tab Span-Events). Auf der Leitung ist dies der Vorschau-Teil dieser Sequenz, verschachtelt mit den anderen gepufferten Events der Verbindung:
event_start {"event": {"type": "agent.message", "id": "sevt_01abc..."}}
event_delta {"event_id": "sevt_01abc...", "delta": {"type": "content_delta", "index": 0, "content": {"type": "text", "text": "..."}}}
...
agent.message {"id": "sevt_01abc...", "content": [...]}Die event_delta-Zeile wiederholt sich einmal pro Textfragment. Verarbeite jedes Event, sobald es eintrifft:
- Bei
event_startnotiere die angekündigteid. Die Bezeichner stimmen immer überein:event_start.event.id, jedeevent_delta.event_idund dieidder gepuffertenagent.messagesind derselbe Wert. - Bei jedem
event_deltahängedelta.content.textan den Eintrag unter(event_id, delta.index)an und rendere den laufenden Text. Das erste Delta für einenindexerstellt diesen Eintrag. - Wenn die gepufferte
agent.messageeintrifft, ordne sie anhand deridzu, verwirf die akkumulierte Vorschau und rendere stattdessen den Inhalt der Nachricht. - Bei
span.model_request_endschließe jede Vorschau, die nicht durch ihr gepuffertes Event abgeglichen wurde. Für sie kommen keine weiteren Deltas mehr. Wenn der Turn fehlschlägt oder unterbrochen wird, trifft das gepufferte Event möglicherweise nie ein;span.model_request_endhingegen schon.
Garantien, auf die sich das Muster stützt:
- Das Verketten der Deltas einer Vorschau in Ankunftsreihenfolge, geschlüsselt nach
(event_id, index), ergibt ein Präfix voncontent[index].textim gepufferten Event (ein Präfix, nicht notwendigerweise den gesamten Text, da Deltas unter Last verworfen werden können). - Eine Verbindung gibt höchstens ein
event_startproevent_idaus, und das gepufferte Event ist das Letzte, was diese Verbindung für dieseidzustellt.
# Vorschau-Snapshots, indiziert nach Event-ID. accumulate_managed_agents_event faltet jedes
# event_start / event_delta in einen agent.message-Snapshot; das gepufferte
# agent.message ersetzt ihn.
previews: dict[str, BetaManagedAgentsAgentMessageEvent] = {}
# Aktiviere agent.message-Vorschauen auf dieser Verbindung
with client.beta.sessions.events.stream(
session.id, event_deltas=["agent.message"]
) as stream:
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "user.message",
"content": [{"type": "text", "text": "Describe the repo in one sentence."}],
},
],
)
for event in stream:
match event.type:
case "event_start":
snapshot = accumulate_managed_agents_event(None, event)
if snapshot is not None:
previews[event.event.id] = snapshot
print(f"event_start {event.event.type} {event.event.id}")
case "event_delta":
preview = accumulate_managed_agents_event(previews.get(event.event_id), event)
if preview is not None:
previews[event.event_id] = preview
text = "".join(block.text for block in preview.content)
print(f"event_delta preview: {text!r}")
case "agent.message":
# Das gepufferte Event ist der maßgebliche Datensatz: Es ersetzt und schließt die Vorschau
preview = accumulate_managed_agents_event(previews.pop(event.id, None), event)
text = "".join(block.text for block in preview.content)
print(f"agent.message {event.id} {text!r}")
case "span.model_request_end":
# Es kommen keine weiteren Deltas. Schließe jede Vorschau, deren
# gepuffertes Event nie angekommen ist.
for event_id in previews:
print(f"span.model_request_end closing preview for {event_id}")
previews.clear()
case "session.status_idle":
breakVorschau von Session-Thread-Events
In einer Multiagent-Session hat jeder Session-Thread seinen eigenen Event-Stream unter GET /v1/sessions/{session_id}/threads/{thread_id}/stream, und dieser akzeptiert denselben event_deltas[]-Parameter mit denselben Werten. Vorschauen sind absichtlich Thread-bezogen: Eine Verbindung liefert nur Vorschauen für den Thread, den sie liest. Die Vorschauen eines Kind-Threads werden im eigenen Stream dieses Kindes zugestellt und niemals in den Stream auf Session-Ebene übernommen, dessen Vorschauen auf den primären Thread beschränkt bleiben. Um den Text eines Subagenten zu beobachten, während das Modell ihn generiert, öffne den Thread-Stream dieses Subagenten.
Beim Pfad des Thread-Streams passieren leicht Fehler: Er lautet /threads/{thread_id}/stream, nicht /events/stream (das nur auf Session-Ebene existiert), und es gibt keinen Endpunkt /threads/{thread_id}/events/stream.
Die Vorschau-Events selbst ändern sich nicht. event_start und event_delta haben in einem Thread-Stream dieselbe Form wie im Stream auf Session-Ebene, und das Muster Akkumulieren und abgleichen gilt wie beschrieben. Die einzige Anpassung betrifft die Buchführung: Betreibe eine Akkumulator-Instanz pro Stream-Verbindung.
# Liste die Threads der Session auf und wähle einen Child: Child-Threads haben eine
# parent_thread_id ungleich null, die parent_thread_id des primären Threads ist null.
THREAD_ID=$(
curl --fail-with-body -sS \
"https://api.anthropic.com/v1/sessions/$SESSION_ID/threads?beta=true" \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-beta: managed-agents-2026-04-01" |
jq -er 'first(.data[] | select(.parent_thread_id != null)).id'
)
# Der Stream des Child-Threads nimmt denselben event_deltas[]-Parameter wie der
# Session-Stream. Prozent-kodiere die Klammern (%5B%5D) und setze die URL in Anführungszeichen.
exec {stream}< <(
curl --fail-with-body -sS -N \
"https://api.anthropic.com/v1/sessions/$SESSION_ID/threads/$THREAD_ID/stream?beta=true&event_deltas%5B%5D=agent.message" \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-beta: managed-agents-2026-04-01" \
-H "accept: text/event-stream"
)
while IFS= read -r -u "$stream" event_line; do
[[ $event_line == data:* ]] || continue
event_json=${event_line#data: }
case $(jq -r '.type' <<<"$event_json") in
event_delta)
jq -j '.delta.content.text' <<<"$event_json"
;;
agent.message)
# Das gepufferte Event ist der maßgebliche Datensatz; rendere seinen Inhalt.
printf '\n'
jq -j '.content[] | select(.type == "text") | .text' <<<"$event_json"
printf '\n'
;;
session.thread_status_idle)
break
;;
esac
done
exec {stream}<&-Die Leseschleife endet bei session.thread_status_idle, dem Event, das ausgegeben wird, wenn der Turn des Session-Threads abgeschlossen ist und der Thread in den Leerlauf geht.
Einschränkungen
Vorschauen sind auf Reaktionsschnelligkeit ausgelegt. Entwickle unter Berücksichtigung dieser Einschränkungen:
- Best Effort: Unter Last kann der Server Deltas für ein Event verwerfen. Wenn er das tut, erhältst du ein zusammenhängendes Präfix des Textes und danach keine weiteren Deltas für dieses Event. Die gepufferte
agent.messagetrifft dennoch vollständig ein. Behandle eine akkumulierte Vorschau niemals als endgültig. - Keine Wiederholung bei erneuter Verbindung: Deltas werden nur an die Verbindung zugestellt, die sich angemeldet hat, solange sie offen ist. Dies gilt gleichermaßen für den Stream auf Session-Ebene und für jeden Session-Thread-Stream, und eine Verbindung, die geöffnet wird, nachdem eine Modellanfrage begonnen hat, erhält keine Deltas für dieses laufende Event. Wenn der Stream abbricht, folge dem Verfahren zur erneuten Verbindung im Tab Events streamen: Öffne den Stream erneut und liste den Event-Verlauf auf. Der Verlauf enthält alle gepufferten Events, die ausgegeben wurden, während du getrennt warst, einschließlich der
agent.message, auf die deine Vorschau gewartet hat. Es gibt keine Möglichkeit, verpasste Deltas erneut anzufordern. - Ein Thread, nur Text: Vorschauen decken Assistant-Text auf dem Thread ab, den die Verbindung liest. Tool-Nutzung, Tool-Ergebnisse, MCP-Ergebnisse und Aktivität auf jedem anderen Session-Thread werden auf dieser Verbindung niemals als Vorschau angezeigt.
agent.thinkingnur mit Start: Eineagent.thinking-Vorschau gibt nur dasevent_startals Signal aus, dass ein Thinking-Block begonnen hat; es folgen keineevent_delta-Events.- Niemals persistiert:
event_startundevent_deltaexistieren nur im Live-Stream. Sie erscheinen weder im Event-Verlauf der Session (GET /v1/sessions/{session_id}/events) noch im Event-Verlauf irgendeines Session-Threads.
Fehlerbehebung bei Vorschauen
Wenn sich der Stream nicht wie erwartet verhält:
| Du siehst | Was es bedeutet |
|---|---|
Einen Stream mit gepufferten Events, aber ohne event_start oder event_delta | Die Verbindung, die du liest, hat sich nicht angemeldet (event_deltas[] gilt pro Verbindung, nicht pro Session), oder der Turn hat den Thread, den du streamst, nie berührt. Vorschauen sind Thread-bezogen, liste also die Threads der Session auf (GET /v1/sessions/{session_id}/threads), um herauszufinden, welcher gelaufen ist. |
| Einen 404 auf der Stream-URL | Der Pfad oder eine ID ist falsch, oder die Anfrage trägt überhaupt keinen Managed-Agents-Beta-Header. Die Thread-Endpunkte sind Beta-gesperrt, ohne den Header existieren sie also nicht. |
Einen 400, der event_deltas nennt | Nur agent.message und agent.thinking werden akzeptiert. |
Weitere Szenarien
Umgang mit Custom-Tool-Aufrufen
Wenn der Agent ein Custom Tool aufruft:
- Die Session gibt ein
agent.custom_tool_use-Event aus, das den Tool-Namen und die Eingabe enthält. - Die Session pausiert mit einem
session.status_idle-Event, dasstop_reason: requires_actionenthält. Die blockierenden Event-IDs befinden sich im Arraystop_reason.event_ids. - Führe das Tool in deinem System aus und sende für jedes ein
user.custom_tool_result-Event, wobei du die Event-ID im Parametercustom_tool_use_idzusammen mit dem Ergebnisinhalt übergibst. - Sobald alle blockierenden Events aufgelöst sind, wechselt die Session zurück zu
running.
with client.beta.sessions.events.stream(session.id) as stream:
for event in stream:
if event.type == "session.status_idle" and (stop_reason := event.stop_reason):
match stop_reason.type:
case "requires_action":
for event_id in stop_reason.event_ids:
# Suche das Custom-Tool-Use-Event und führe es aus
tool_event = events_by_id[event_id]
result = call_tool(tool_event.name, tool_event.input)
# Sende das Ergebnis zurück
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "user.custom_tool_result",
"custom_tool_use_id": event_id,
"content": [{"type": "text", "text": result}],
},
],
)
case "end_turn":
breakTool-Bestätigung
Wenn eine Berechtigungsrichtlinie eine Bestätigung erfordert, bevor ein Tool ausgeführt wird:
- Die Session gibt ein
agent.tool_use- oderagent.mcp_tool_use-Event aus. - Die Session pausiert mit einem
session.status_idle-Event, dasstop_reason: requires_actionenthält. Die blockierenden Event-IDs befinden sich im Arraystop_reason.event_ids. - Sende für jedes ein
user.tool_confirmation-Event, wobei du die Event-ID im Parametertool_use_idübergibst. Setzeresultauf"allow"oder"deny". Verwendedeny_message, um eine Ablehnung zu erklären. - Sobald alle blockierenden Events aufgelöst sind, wechselt die Session zurück zu
running.
with client.beta.sessions.events.stream(session.id) as stream:
for event in stream:
if event.type == "session.status_idle" and (stop_reason := event.stop_reason):
match stop_reason.type:
case "requires_action":
for event_id in stop_reason.event_ids:
# Genehmige den ausstehenden Tool-Aufruf
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "user.tool_confirmation",
"tool_use_id": event_id,
"result": "allow",
},
],
)
case "end_turn":
breakEine Session im Leerlauf fortsetzen
Sessions bleiben zwischen Interaktionen bestehen. Der Gesprächsverlauf wird beibehalten, sofern die Session nicht explizit gelöscht wird. Wenn eine Session in den Leerlauf geht, wird ein Checkpoint ihrer Sandbox erstellt, der den vollständigen Sandbox-Zustand bewahrt, einschließlich des Dateisystems, installierter Pakete und aller Dateien, die der Agent erstellt hat. So kannst du nach Inaktivität sauber fortsetzen.
Um eine Session fortzusetzen, sende wie gewohnt ein user.message-Event an sie:
# In Produktion übergib die gespeicherte ID der Session, die du fortsetzen willst.
ant beta:sessions:events send --session-id "$SESSION_ID" <<'YAML'
events:
- type: user.message
content:
- type: text
text: Now run the tests against the changes you made earlier.
YAMLEin Session-Budget erreichen
Eine Session, die mit einem Budget erstellt wurde, pausiert, anstatt zu viel auszugeben. Wenn die erfassten Listenkosten der Session die Obergrenze erreichen, pausiert die Plattform jeden Thread vor seiner nächsten Modellanfrage, und die Session geht mit einem stop_reason von budget_reached in den Leerlauf, anstatt zu terminieren. Die Anfrage, die die Gesamtsumme über die Obergrenze gebracht hat, läuft bis zum Abschluss, sodass die vom session.usage-Snapshot gemeldeten list_cost auf oder einen Bruchteil über der Obergrenze liegen können. Im Stream trifft die Pause als drei Events in dieser Reihenfolge ein:
session.thread_status_idlemitstop_reason: budget_reached, für jeden Thread, sobald er pausiert.session.usage, ein Snapshot der kumulierten Nutzung und der erfassten Listenkosten der Session.session.status_idlemitstop_reason: budget_reached. Dassession.usage-Event geht diesem Leerlauf immer unmittelbar voraus.
Ein Thread, dessen letzte Anfrage sowohl die Obergrenze überschreitet als auch seinen Turn abschließt, meldet end_turn in seinem eigenen session.thread_status_idle-Event, während die Session weiterhin budget_reached meldet; orientiere dich am stop_reason auf Session-Ebene, um die Pause zu erkennen.
Solange die Session an ihrer Obergrenze ist, akzeptiert sie nur die Events, die bereits laufende Arbeit abschließen: user.tool_confirmation, user.tool_result, user.custom_tool_result und user.interrupt. Jedes Event, das neue Arbeit starten würde, einschließlich user.message, wird mit einem 400-Fehler abgelehnt, der diese Liste nennt. Wenn eine Session sowohl einen Thread hat, der auf eine Tool-Anfrage wartet, als auch einen Thread, der an der Obergrenze pausiert ist, lautet der stop_reason auf Session-Ebene requires_action, nicht budget_reached: Das Beantworten der Anfrage löst keine Modellanfrage aus, antworte also wie gewohnt darauf.
Kein Event setzt eine an ihrer Obergrenze pausierte Session fort. Aktualisiere stattdessen das Budget der Session: Das Ändern der Obergrenze auf einen beliebigen Wert oberhalb der verbrauchten Listenkosten oder das Entfernen des Budgets durch Aktualisieren der Session mit "budget": null setzt die pausierte Arbeit automatisch fort. Siehe Session-Budgets dazu, wie Listenkosten erfasst werden, sowie zur vollständigen Semantik der Budget-Aktualisierung.
System-Nachrichten senden
Sende ein system.message-Event, um dem Agenten privilegierten Kontext auf Systemebene zu geben, der für den begleitenden Turn und alle nachfolgenden Turns gilt. Anders als das Feld system in der Agent-Definition (das den System-Prompt auf oberster Ebene festlegt) wird der Inhalt von system.message als role: "system"-Turn an den Systemkontext der Session angehängt, anstatt diesen Prompt zu ersetzen. Verwende es, wenn der Agent mitten in der Session aktualisierte Anleitung auf Systemebene benötigt: eine andere Persona, überarbeitete Einschränkungen oder zur Laufzeit abgerufenen Kontext, der das Verhalten des Modells künftig prägen soll.
ant beta:sessions:events send --session-id "$SESSION_ID" <<'YAML'
events:
- type: system.message
content:
- type: text
text: "The user's current timezone is America/New_York."
YAMLWährend die Session mit stop_reason: requires_action im Leerlauf ist, wird eine system.message nur akzeptiert, wenn sie in derselben Anfrage auf ein Tool-Ergebnis-Event folgt; allein oder zusammen mit einer user.message gesendet, wird sie abgelehnt, bis die ausstehenden Tool-Events aufgelöst sind. content akzeptiert 1–1000 Textelemente.
Nutzung nachverfolgen
Das Session-Objekt enthält ein Feld usage mit der kumulierten Nutzung der Session: Token-Zählungen, Server-Tool-Nutzung, aktive Zeit und die nachverfolgten Listenkosten. Rufe die Session ab, nachdem sie in den Leerlauf gegangen ist, um die neuesten Gesamtwerte zu lesen.
{
"id": "sesn_01...",
"status": "idle",
"usage": {
"input_tokens": 5000,
"output_tokens": 3200,
"cache_read_input_tokens": 20000,
"cache_creation": {
"ephemeral_5m_input_tokens": 2000,
"ephemeral_1h_input_tokens": 0
},
"list_cost": {
"amount": "187",
"currency": "USD"
},
"active_seconds": 342.5,
"server_tool_use": {
"web_search_requests": 3,
"web_fetch_requests": 0
}
}
}input_tokens gibt nicht gecachte Eingabe-Token an und output_tokens gibt die gesamten Ausgabe-Token über alle Modellaufrufe in der Session hinweg an. Das Feld cache_read_input_tokens gibt die aus dem Prompt-Cache gelesenen Token an, und das Objekt cache_creation schlüsselt die Cache-Erstellungs-Token nach Cache-Lebensdauer auf (ephemeral_5m_input_tokens und ephemeral_1h_input_tokens). Cache-Einträge verwenden standardmäßig eine TTL von 5 Minuten, sodass direkt aufeinanderfolgende Turns innerhalb dieses Zeitfensters von Cache-Lesevorgängen profitieren, die die Kosten pro Token senken.
list_cost ist der kumulierte Verbrauch der Session, bepreist zu öffentlichen Listenpreisen, als ganze Zahl von Cent in einem String, mit einem Währungscode. active_seconds ist die kumulierte Zeit, in der die Session mindestens einen laufenden Thread hatte; überlappende Aktivität gleichzeitiger Threads wird nur einmal gezählt, anders als bei active_seconds im stats-Objekt der Session, das die eigene aktive Zeit jedes Threads aufsummiert. Dieser deduplizierte Wert ist die Dauer, auf deren Grundlage die Laufzeitkosten der Session bepreist werden. server_tool_use zählt serverseitig ausgeführte Tool-Anfragen für die Preisberechnung: Websuche-Anfragen werden pro Anfrage in die Listenkosten eingepreist, und Web-Fetch-Anfragen verursachen keine Gebühr pro Anfrage und werden nicht gemessen, sodass web_fetch_requests den Wert 0 anzeigt. Das eigene usage jedes Session-Threads enthält ebenfalls list_cost und active_seconds. Die Werte pro Thread werden unabhängig voneinander gerundet und schließen die Laufzeitkosten der Session aus, sodass sie sich nicht exakt zum list_cost der Session aufsummieren; der Session-Wert ist der maßgebliche.
Du musst die Session nicht abfragen, um diese Gesamtwerte zu beobachten. Das Event session.usage trägt denselben kumulierten Snapshot (das usage-Objekt plus das budget der Session, das null ist, wenn die Session keines hat) im Session-Stream und im Event-Verlauf. Es wird bei Übergängen in den Leerlauf ausgegeben und nicht nach einem Timer: Die Session gibt eines unmittelbar aus, bevor sie in den Leerlauf geht, unabhängig vom Stop-Grund, und eines, wenn ein Thread bei einem Session-Budget pausiert. Ein Stream-Leser sieht daher die endgültigen Kosten eines Turns oder der Arbeit, die ein Budget erreicht hat, ohne einen zusätzlichen Abruf.
Um ein Ausgabenlimit durchzusetzen, setze ein Session-Budget, anstatt die Nutzung abzufragen und die Session selbst zu stoppen. Die Plattform bepreist den Verbrauch der Session fortlaufend und pausiert jeden Thread vor seiner nächsten Modellanfrage, sobald die Listenkosten der Session die Obergrenze erreichen; siehe Ein Session-Budget erreichen, um zu sehen, wie das im Stream aussieht.
Observability in der Console
Die Claude Console enthält einen Session-Viewer, mit dem du untersuchen kannst, was ein Agent getan hat, ohne Code zu schreiben. Wähle in der Seitenleiste der Console unter Managed Agents den Eintrag Sessions, um jede Session im Workspace mit ihrem Status, Agenten, Token-Verbrauch, Kosten und Erstellungszeitpunkt zu sehen, und wähle dann eine Session aus, um sie zu öffnen. Der Session-Viewer ist nur für Developers und Admins zugänglich. Er zeigt:
- Timeline-Minimap: Eine zoombare Übersicht über die Aktivität der Session im Zeitverlauf, mit einer Spur pro Thread in Multiagent-Sessions. Wähle eine Spur aus, um diesen Thread anzuzeigen, oder wähle eine Markierung aus, um zu ihrem Event zu springen.
- Transkript: Die Konversation, gruppiert nach Modellanfrage, einschließlich Denken, Tool-Aufrufen mit ihren Eingaben und Ergebnissen sowie Nachrichtentext, während er gestreamt wird. Du kannst die Events filtern und sie als JSON kopieren oder herunterladen.
- Inspector: Ein in der Größe veränderbares Seitenpanel mit Details zur Session, in fünf Tabs:
- Session zeigt die Details und Metadaten der Session, ihre kumulierten Kosten im Zeitverlauf sowie die Ausgaben im Verhältnis zum Budget der Session, wenn eines gesetzt ist.
- Events listet jedes rohe Event im aktuellen Thread in der Reihenfolge auf, in der der Server es gesendet hat; wähle ein Event aus, um sein JSON zu sehen. Eine Nachricht, die gestreamt wurde, während die Seite geöffnet war, hat außerdem eine Deltas-Ansicht ihrer Event-Deltas.
- Tools listet die Tools auf, mit denen die Agenten der Session konfiguriert sind, zusammen mit Aufrufzahlen, Fehlschlägen und medianer Dauer; wähle ein Tool aus, um seine Aufrufe zu sehen und zu einem davon im Transkript zu springen.
- Resources listet eingebundene Dateien, Repositories und Memory Stores an ihren Container-Pfaden auf, einschließlich der Memories in jedem Store und der Änderungen, die diese Session an ihnen vorgenommen hat, sowie Dateien, die der Agent nach
/mnt/session/outputsgeschrieben hat, und die Skills, die den Agenten der Session zugeordnet sind. - Threads listet jeden Thread mit seinem Status, seiner Kontextgröße und seinen Kosten auf. Wähle einen Thread aus, um seine Details anzuzeigen, etwa den Agenten, das Modell, die Kontextnutzung und die Kosten.
Hänge ?event={event_id} an eine Session-URL an, um die Session bei einem bestimmten Event zu öffnen.
Tipps zum Debugging
- Session-Events prüfen: Session-Fehler werden über das Event
session.errorübermittelt - Tool-Ergebnisse überprüfen: Fehlschläge bei der Tool-Ausführung erklären oft unerwartetes Agentenverhalten
- Token-Verbrauch nachverfolgen: Überwache den Token-Verbrauch, um Prompts zu optimieren und Kosten zu senken
- System-Prompts verwenden: Füge dem System-Prompt Logging-Anweisungen hinzu, damit der Agent seine Überlegungen erklärt
- Fehlerbehebung bei Previews: Wenn sich ein Stream, der Event-Deltas aktiviert hat, nicht wie erwartet verhält, siehe Fehlerbehebung bei Previews
Was this page helpful?