Thread di sessione
Elenca, interrompi e archivia i thread di una sessione multiagente, leggi i loro eventi e gestisci le autorizzazioni degli strumenti tra di essi.
In una sessione multiagente, ogni agente lavora nel proprio "session thread" (thread di sessione). Questa pagina spiega come elencare, interrompere e archiviare i thread, gli eventi che inviano e come funzionano le autorizzazioni degli strumenti tra di essi. Anche un'esecuzione di workflow crea thread di sessione.
Thread principale e thread di sessione
Lo stream di eventi a livello di sessione (/v1/sessions/{session_id}/events/stream) è considerato il "primary thread" (thread principale) e contiene una vista condensata di tutta l'attività in tutti i thread. Non vedi l'attività completa dei subagenti, ma vedi l'inizio e la fine del loro lavoro, oltre agli eventi bloccanti come le richieste di autorizzazione degli strumenti.
I thread di sessione sono il luogo in cui puoi approfondire l'attività di un agente specifico.
Lo status della sessione è un'aggregazione di tutta l'attività degli agenti; se almeno un thread è running, anche lo stato complessivo della sessione è running. Anche un'esecuzione di workflow in corso può mantenere la sessione running, anche quando nessuno dei suoi thread sta lavorando. Quando nessun thread sta lavorando e un thread attende il tuo client, la sessione è idle; consulta Sapere quando il lavoro è terminato.
Un budget di sessione è un unico limite condiviso tra tutti i thread di una sessione. Quando il limite viene raggiunto, i thread si mettono in pausa in modo indipendente e il costo di ciascun thread viene calcolato in base al modello servito per quel thread.
Elencare i thread
Elenca tutti i thread associati a una sessione come segue:
for thread in client.beta.sessions.threads.list(session.id):
agent = thread.agent
label = agent.type if agent.type == "advisor" else agent.name
print(f"[{label}] {thread.status}")L'elenco completo include il thread principale. parent_thread_id è null per il thread principale. Ogni altro thread è un thread figlio. workflow_run_id è null tranne che sui thread di un'esecuzione.
Per elencare solo i thread con determinati stati, aggiungi statuses[] alla richiesta e ripetilo per indicare più di uno stato, come in ?statuses[]=running&statuses[]=idle. Omettilo per restituire i thread di ogni stato.
Interrompere un thread di sessione
Invia user.interrupt con session_thread_id per fermare un thread specifico. Omettere session_thread_id interrompe ogni thread non archiviato nella sessione, incluso quello principale. In una sessione con workflow dinamici, un'interruzione non termina alcuna esecuzione, e un'interruzione che indica un thread di un'esecuzione non ferma nulla. Un'interruzione chiude le chiamate agli strumenti in sospeso degli altri thread figli, ma non fare affidamento su di essa per chiudere quelle di un thread di un'esecuzione. Consulta Interrompere una sessione con esecuzioni aperte.
client.beta.sessions.events.send(
session.id,
events=[{"type": "user.interrupt", "session_thread_id": thread.id}],
)Sul thread di un subagente bloccato in requires_action, l'interruzione chiude ogni chiamata allo strumento in sospeso con un risultato di errore dello strumento ("Tool execution was interrupted before completion. Please retry.") e riemette direttamente session.thread_status_idle con stop_reason: end_turn; il modello non viene campionato. Su un thread figlio inattivo con end_turn o budget_reached, l'interruzione non ha alcun effetto. Un'interruzione che indica un thread terminato restituisce un errore 400. Un thread figlio interrotto non invia all'agente del thread principale il report che invia quando un turno termina. Mentre quell'agente attende il thread figlio, non avvia un altro turno finché non gli arriva qualcos'altro, come un user.message o il report di un altro thread.
Archiviare un thread di sessione
Facoltativamente, archivia un thread di sessione quando ha completato il suo lavoro. Archiviare un thread libera il suo posto nel limite di 25 thread figli. Il server archivia autonomamente i thread di un'esecuzione di workflow. Non è necessario archiviarli, e non puoi farlo mentre l'esecuzione è aperta.
archived = client.beta.sessions.threads.archive(thread.id, session_id=session.id)
print(archived.status, archived.archived_at)L'archiviazione riesce solo se il thread è idle. Un thread fermo in requires_action conta come inattivo e può essere archiviato direttamente; solo un thread in esecuzione deve essere prima interrotto:
client.beta.sessions.events.send(
session.id,
events=[{"type": "user.interrupt", "session_thread_id": thread.id}],
)
archived = client.beta.sessions.threads.archive(thread.id, session_id=session.id)
print(archived.status, archived.archived_at)Eventi del thread principale
Questi eventi mostrano l'attività multiagente sul thread principale in /v1/sessions/{session_id}/events/stream. Gli eventi relativi alla direzione dei messaggi sono denominati rispetto al thread sul cui stream compaiono: agent.thread_message_received significa che un messaggio è arrivato su questo thread da un altro thread, e agent.thread_message_sent significa che questo thread ne ha inviato uno. L'attività che l'agente del thread principale delega, ad esempio, arriva sullo stream del thread figlio come evento agent.thread_message_received.
| Tipo | Descrizione |
|---|---|
session.thread_created | È stato creato un thread. Include session_thread_id e agent_name. |
session.thread_status_running | Un thread ha avviato un'attività. |
session.thread_status_idle | L'agente associato al thread è in attesa di input. Include uno stop_reason che indica perché l'agente si è fermato. |
session.thread_status_terminated | Un thread è terminato e non accetta ulteriori input, ad esempio perché è stato archiviato o ha riscontrato un errore irrecuperabile. Anche un thread advisor termina quando la sua consultazione finisce. |
agent.thread_message_received | Sul thread principale, un subagente ha inviato all'agente del thread principale un report o una domanda. Include from_session_thread_id, from_agent_name e content. |
agent.thread_message_sent | Sul thread principale, l'agente del thread principale ha inviato a un subagente un'attività o un messaggio di follow-up. Include to_session_thread_id, to_agent_name e content. |
Le consultazioni dell'advisor emettono questi stessi eventi di thread con il nome riservato anthropic.advisor (come agent_name negli eventi del ciclo di vita del thread e come from_agent_name nella consegna del consiglio); consulta Fornisci un advisor alla sessione per la sequenza.
I thread di un'esecuzione di workflow compaiono sullo stream principale come segue:
- Eventi del ciclo di vita: Ogni thread di un'esecuzione invia
session.thread_created, con ilworkflow_run_iddell'esecuzione, e i propri eventisession.thread_status_running,session.thread_status_idleesession.thread_status_terminated. - Eventi dei messaggi: Il prompt di un thread di un'esecuzione, un evento
agent.thread_message_received, rimane sul proprio stream. - Eventi dell'esecuzione: Anche gli eventi
workflow_run.*arrivano su questo stream; consulta Eventi dell'esecuzione. - Chiamate agli strumenti che attendono te: Le chiamate agli strumenti di un thread di un'esecuzione che richiedono il tuo client vengono ripubblicate su questo stream, come per qualsiasi thread figlio. Consulta Autorizzazioni degli strumenti e strumenti personalizzati.
Eventi dei thread di sessione
Gli eventi critici vengono inoltrati al thread principale. Tuttavia, potresti comunque voler esaminare il ragionamento e le chiamate agli strumenti di un agente specifico. Per farlo, esegui lo streaming o elenca gli eventi dal thread di sessione associato.
Ogni thread di sessione ha il proprio stream di eventi in /v1/sessions/{session_id}/threads/{thread_id}/stream, che accetta lo stesso parametro event_deltas[] dello stream a livello di sessione, così puoi visualizzare in anteprima il testo di un subagente mentre il modello lo genera. Una connessione mostra in anteprima solo il thread che sta leggendo: le anteprime di un thread figlio non compaiono mai sullo stream a livello di sessione, quindi per osservare un subagente in tempo reale, apri lo stream del suo thread. Consulta Visualizzare in anteprima gli eventi dei thread di sessione per l'attivazione, l'accumulo e la riconciliazione delle anteprime.
In un'esecuzione di workflow, il server esegue un workflow: un programma scritto dall'agente del thread principale. Su ciascuno dei thread dell'esecuzione, il primo agent.thread_message_received è il prompt scritto dal workflow. Il suo from_session_thread_id è l'ID del thread principale e l'evento non ha alcun from_agent_name. L'API non garantisce il testo del prompt, quindi non analizzarlo. L'evento session.thread_status_terminated del thread, sullo stream del thread principale, ti indica che il thread ha terminato. Nessun evento registra il risultato che ha restituito al workflow.
Lo stream di un thread non riproduce gli eventi precedenti. Subito dopo session.thread_created, l'elenco degli eventi di un thread di un'esecuzione può essere vuoto, perché il server scrive il primo evento del thread dopo di esso. Quindi apri prima lo stream del thread, poi elenca gli eventi del thread e salta ogni evento in streaming il cui id è stato restituito dall'elenco.
with client.beta.sessions.threads.events.stream(
thread.id,
session_id=session.id,
) as stream:
for event in stream:
match event.type:
case "agent.message":
for block in event.content:
if block.type == "text":
print(block.text, end="")
case "session.thread_status_idle":
breakElenca tutti gli eventi passati del thread di sessione per ottenere una cronologia completa.
for event in client.beta.sessions.threads.events.list(
thread.id,
session_id=session.id,
):
print(f"[{event.type}] {event.processed_at}")Autorizzazioni degli strumenti e strumenti personalizzati
Se un subagente ha bisogno di qualcosa dal tuo client, come l'autorizzazione per eseguire una chiamata a uno strumento o il risultato di uno strumento personalizzato, l'evento viene ripubblicato sul thread principale con session_thread_id che identifica il thread di sessione di origine. Una chiamata a uno strumento richiede la tua autorizzazione con always_ask, oppure con auto quando il server non giunge a una determinazione.
{
"type": "session.thread_status_idle",
"id": "sevt_01ABC...",
"session_thread_id": "sthr_01DEF...",
"agent_name": "code-reviewer",
"stop_reason": {
"type": "requires_action",
"event_ids": ["sevt_01XYZ..."]
}
}Pubblica user.tool_confirmation (con tool_use_id) o user.custom_tool_result (con custom_tool_use_id); il server instrada automaticamente la risposta al thread corretto. La risposta può comparire sul thread principale e sul thread del subagente con valori id diversi. Per far corrispondere le due copie, confronta type e tool_use_id (o custom_tool_use_id), non id.
La sessione passa a idle solo quando nessun thread è running, quindi session.status_idle può arrivare molto tempo dopo la chiamata di un subagente. Non devi attenderlo: invia user.custom_tool_result non appena arriva l'evento agent.custom_tool_use ripubblicato.
Con auto, i tuoi eventi user.message possono portare il server a consentire una chiamata che altrimenti negherebbe. Nulla nel thread di un subagente conta come tua intenzione. Il tuo client non pubblica messaggi lì, e i messaggi che l'agente del thread principale invia al subagente non contano. Quando il server nega una chiamata con auto, nulla viene ripubblicato: l'evento e il risultato di errore dello strumento compaiono solo sullo stream del thread del subagente, e il subagente continua a essere eseguito.
L'esempio seguente va inserito all'interno del ciclo di eventi del gestore di conferma degli strumenti. Per ogni ID in stop_reason.event_ids, invia un user.tool_confirmation che consente la chiamata. Lo stesso schema si applica a user.custom_tool_result.
for event_id in stop.event_ids:
client.beta.sessions.events.send(
session.id,
events=[
{
"type": "user.tool_confirmation",
"tool_use_id": event_id,
"result": "allow",
}
],
)Lo schema precedente risponde alle chiamate elencate da un evento di inattività. Sullo stream principale, l'evento session.thread_status_idle di un subagente può arrivare prima degli eventi agent.tool_use o agent.mcp_tool_use elencati nel suo stop_reason.event_ids. Un user.tool_confirmation per una chiamata il cui evento non è ancora arrivato può restituire 400. Per evitarlo, rispondi a ogni chiamata il cui evaluated_permission è ask quando il suo evento arriva sullo stream principale.
Was this page helpful?