La comunicazione con i Claude Managed Agents è basata su eventi. Invii eventi utente all'agente e ricevi eventi dell'agente e della sessione per monitorarne lo stato.
Tutte le richieste all'API Managed Agents richiedono l'header beta managed-agents-2026-04-01. L'SDK imposta automaticamente l'header beta.
Gli eventi fluiscono in due direzioni.
user.* avviano una sessione e la guidano durante il suo avanzamento; system.message aggiorna il prompt di sistema dell'agente tra un turno e l'altro.Le stringhe dei tipi di evento di sessione, span, agente, utente e sistema seguono una convenzione di denominazione {domain}.{action}. Gli eventi di anteprima delta disponibili solo in streaming (event_start, event_delta) costituiscono l'eccezione. Consulta Tipi di evento nel riferimento per il catalogo completo.
Ogni evento persistito include un timestamp processed_at che indica quando l'evento è stato registrato lato server. Se processed_at è null, significa che l'evento è stato messo in coda dall'harness e viene gestito dopo che gli eventi precedenti hanno terminato l'elaborazione.
Per impostazione predefinita, il testo di risposta dell'agente raggiunge lo stream come eventi agent.message bufferizzati, ciascuno emesso solo dopo che la richiesta al modello che lo ha prodotto è terminata. I delta degli eventi ti consentono di visualizzare quel testo in modo incrementale, come anteprima live, mentre il modello lo sta ancora generando. Un'anteprima non è la risposta: le anteprime sono un ausilio di visualizzazione best-effort, e l'evento agent.message bufferizzato è sempre il record autorevole. Un client che ignora le anteprime riceve comunque uno stream completo e corretto.
Le anteprime sono opt-in per ciascuna connessione di streaming. Aggiungi il parametro di query event_deltas[] a GET /v1/sessions/{session_id}/events/stream, ripetendolo una volta per ogni tipo di evento di cui desideri l'anteprima. I valori accettati sono agent.message e agent.thinking; qualsiasi altro valore restituisce un errore 400. Solo lo stream di eventi a livello di sessione supporta questo parametro. Gli stream di eventi dei thread di sessione lo rifiutano.
Quando inizia un evento in anteprima, lo stream emette un event_start che contiene il tipo e l'id dell'evento in arrivo:
{
"type": "event_start",
"event": {
"type": "agent.message",
"id": "sevt_01abc..."
}
}Per agent.message, lo start è seguito da eventi event_delta che contengono testo incrementale. Ogni delta indica l'evento che estende in event_id e il blocco di contenuto che estende in delta.index:
{
"type": "event_delta",
"event_id": "sevt_01abc...",
"delta": {
"type": "content_delta",
"index": 0,
"content": {
"type": "text",
"text": "Here is the summary"
}
}
}Quando un evento agent.thinking è in anteprima, viene emesso solo l'event_start. Non seguono eventi event_delta, e il contenuto arriva nell'evento agent.thinking bufferizzato come di consueto.
A differenza degli eventi persistiti, event_start ed event_delta non hanno un proprio id o processed_at. L'unico identificatore che contengono è l'id dell'evento di cui forniscono l'anteprima.
I delta degli eventi usano un formato di trasmissione diverso da Streaming dei messaggi, e la differenza è intenzionale. Un agent.message in anteprima riceve un singolo event_start seguito solo da eventi event_delta. Non ci sono eventi di start o stop per ciascun blocco di contenuto e nessun evento di stop per l'evento in anteprima stesso. Il tipo di delta è content_delta, non content_block_delta. Il codice di accumulazione scritto per la Messages API non può essere riutilizzato senza modifiche.
Gli SDK Python, TypeScript e Go includono un helper di accumulazione che indicizza l'anteprima in base all'id dell'evento e gestisce la contabilità dell'index per te. Il pattern manuale funziona in ogni linguaggio: negli altri SDK, applicalo ai tipi di evento generati.
Nel pattern manuale, tratta l'anteprima come un buffer temporaneo e l'evento bufferizzato come il record. Indicizza il buffer per (event_id, index). Riconcilia per ogni richiesta al modello: un turno si apre con un singolo evento session.status_running, poi in un turno che si completa normalmente ogni richiesta al modello produce, nell'ordine, span.model_request_start, event_start, gli eventi event_delta, l'agent.message bufferizzato e infine span.model_request_end (nella scheda Eventi span). Elabora ogni evento man mano che arriva:
event_start, annota l'id annunciato. Gli identificatori corrispondono sempre: event_start.event.id, ogni event_delta.event_id e l'id dell'agent.message bufferizzato sono lo stesso valore.event_delta, aggiungi delta.content.text alla voce in (event_id, delta.index) e visualizza il testo in corso. Il primo delta per un index crea quella voce.agent.message bufferizzato, abbinalo per id, scarta l'anteprima accumulata e visualizza invece il contenuto del messaggio.span.model_request_end, chiudi qualsiasi anteprima che non sia stata riconciliata dal suo evento bufferizzato. Non arriveranno altri delta per essa. Se il turno genera un errore o viene interrotto, l'evento bufferizzato potrebbe non arrivare mai; span.model_request_end arriva comunque.# Snapshot di anteprima, indicizzati per id evento. accumulate_managed_agents_event combina ogni
# event_start / event_delta in uno snapshot agent.message; l'evento
# agent.message bufferizzato lo sostituisce.
previews: dict[str, BetaManagedAgentsAgentMessageEvent] = {}
# Abilita le anteprime agent.message su questa connessione
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":
# L'evento bufferizzato è il record: sostituisce e chiude l'anteprima
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":
# Non arriveranno altri delta. Chiudi ogni anteprima il cui
# evento bufferizzato non è mai arrivato.
for event_id in previews:
print(f"span.model_request_end closing preview for {event_id}")
previews.clear()
case "session.status_idle":
breakLe anteprime sono ottimizzate per la reattività. Sviluppa tenendo conto di questi vincoli:
agent.message bufferizzato arriva comunque completo. Non trattare mai un'anteprima accumulata come definitiva.agent.message che la tua anteprima stava aspettando. Non c'è modo di richiedere nuovamente i delta persi.agent.thinking: Un'anteprima di agent.thinking emette solo l'event_start come segnale che un blocco di pensiero è iniziato; non seguono eventi event_delta.event_start ed event_delta esistono solo sullo stream live. Non compaiono nella cronologia degli eventi della sessione (GET /v1/sessions/{session_id}/events).Quando l'agente invoca uno strumento personalizzato:
agent.custom_tool_use contenente il nome dello strumento e l'input.session.status_idle contenente stop_reason: requires_action. Gli ID degli eventi bloccanti si trovano nell'array stop_reason.event_ids.user.custom_tool_result per ciascuno, passando l'ID dell'evento nel parametro custom_tool_use_id insieme al contenuto del risultato.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:
# Cerca l'evento di uso dello strumento personalizzato ed eseguilo
tool_event = events_by_id[event_id]
result = call_tool(tool_event.name, tool_event.input)
# Invia il risultato indietro
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":
breakQuando una policy di autorizzazione richiede una conferma prima che uno strumento venga eseguito:
agent.tool_use o agent.mcp_tool_use.session.status_idle contenente stop_reason: requires_action. Gli ID degli eventi bloccanti si trovano nell'array stop_reason.event_ids.user.tool_confirmation per ciascuno, passando l'ID dell'evento nel parametro tool_use_id. Imposta result su "allow" o "deny". Usa deny_message per spiegare un rifiuto.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:
# Approva la chiamata allo strumento in sospeso
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "user.tool_confirmation",
"tool_use_id": event_id,
"result": "allow",
},
],
)
case "end_turn":
breakLe sessioni persistono tra le interazioni. La cronologia della conversazione viene preservata a meno che la sessione non venga eliminata esplicitamente. Quando una sessione diventa inattiva, viene creato un checkpoint della sua sandbox, preservando l'intero stato della sandbox, inclusi il filesystem, i pacchetti installati e qualsiasi file creato dall'agente. Questo ti consente di riprendere in modo pulito dopo un periodo di inattività.
Mentre la cronologia della sessione viene persistita fino all'eliminazione, i checkpoint vengono conservati solo per 30 giorni dopo l'ultima attività della sessione. Se il tuo flusso di lavoro richiede che l'intero stato della sandbox (file, strumenti installati e così via) persista oltre i 30 giorni, invia periodicamente eventi user.message per reimpostare il timer di inattività prima che il checkpoint scada.
Per riprendere una sessione, inviale un evento user.message come di consueto:
# In produzione, passa l'ID memorizzato della sessione che vuoi riprendere.
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.
YAMLsystem.message è attualmente supportato solo da Claude Opus 4.8. Se un qualsiasi modello configurato sull'agente non supporta l'iniezione di sistema a metà conversazione, l'evento viene rifiutato con un errore di validazione model_does_not_support_mid_conversation_system.
Invia un evento system.message per aggiornare il prompt di sistema dell'agente tra un turno e l'altro. A differenza del campo system nella definizione dell'agente (che è fissato alla creazione della sessione), system.message ti consente di modificare il prompt di sistema man mano che la sessione procede. Usalo quando l'agente necessita di indicazioni aggiornate a livello di sistema durante la sessione: una persona diversa, vincoli rivisti o contesto recuperato a runtime che dovrebbe influenzare il comportamento del modello da quel momento in poi.
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."
YAMLsystem.message non può essere inviato mentre la sessione è inattiva con stop_reason: requires_action. content accetta da 1 a 1000 elementi di testo.
L'oggetto sessione include un campo usage con statistiche cumulative sui token. Recupera la sessione dopo che diventa inattiva per leggere i totali più recenti e usali per monitorare i costi, applicare budget o controllare il consumo.
{
"id": "sesn_01...",
"status": "idle",
"usage": {
"input_tokens": 5000,
"output_tokens": 3200,
"cache_creation_input_tokens": 2000,
"cache_read_input_tokens": 20000
}
}input_tokens riporta i token di input non memorizzati nella cache e output_tokens riporta i token di output totali su tutte le chiamate al modello nella sessione. I campi cache_creation_input_tokens e cache_read_input_tokens riflettono l'attività della cache dei prompt. Le voci della cache usano un TTL di 5 minuti, quindi turni consecutivi entro quella finestra beneficiano delle letture dalla cache, che riducono il costo per token.
La Console fornisce una vista timeline visuale delle tue sessioni agente. Naviga alla sezione Claude Managed Agents nella Console per vedere:
session.errorWas this page helpful?