Claude Platform Docs
Managed AgentsOrchestrazione avanzata

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.

TipoDescrizione
session.thread_createdÈ stato creato un thread. Include session_thread_id e agent_name.
session.thread_status_runningUn thread ha avviato un'attività.
session.thread_status_idleL'agente associato al thread è in attesa di input. Include uno stop_reason che indica perché l'agente si è fermato.
session.thread_status_terminatedUn 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_receivedSul 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_sentSul 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 il workflow_run_id dell'esecuzione, e i propri eventi session.thread_status_running, session.thread_status_idle e session.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":
                break

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?