Hilos de sesión
Lista, interrumpe y archiva los hilos de una sesión multiagente, lee sus eventos y gestiona los permisos de herramientas entre ellos.
En una sesión multiagente, cada agente trabaja en su propio "session thread" (hilo de sesión). Esta página explica cómo listar, interrumpir y archivar hilos, los eventos que envían y cómo funcionan los permisos de herramientas entre ellos. Una "workflow run" (ejecución de flujo de trabajo) también crea hilos de sesión.
Hilo principal e hilos de sesión
El "session-level event stream" (flujo de eventos a nivel de sesión) (/v1/sessions/{session_id}/events/stream) se considera el "primary thread" (hilo principal), y contiene una vista condensada de toda la actividad en todos los hilos. No ves la actividad completa de los subagentes, pero sí ves el inicio y el final de su trabajo, así como los eventos bloqueantes, como las solicitudes de permiso de herramientas.
Los hilos de sesión te permiten examinar en detalle la actividad de un agente específico.
El status de la sesión es una agregación de toda la actividad de los agentes; si al menos un hilo está running, el estado general de la sesión también es running. Una ejecución de flujo de trabajo que está en curso también puede mantener la sesión en running, incluso mientras ninguno de sus hilos está trabajando. Cuando ningún hilo está trabajando y un hilo espera a tu cliente, la sesión está idle; consulta Saber cuándo termina el trabajo.
Un presupuesto de sesión es un único límite compartido entre todos los hilos de una sesión. Cuando se alcanza el límite, los hilos se pausan de forma independiente, y el costo de cada hilo se calcula según el modelo que atiende a ese hilo.
Listar hilos
Lista todos los hilos asociados a una sesión de la siguiente manera:
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}")La lista completa incluye el hilo principal. parent_thread_id es null para el hilo principal. Todos los demás hilos son hilos hijos. workflow_run_id es null excepto en los hilos de una ejecución.
Para listar solo los hilos que tienen ciertos estados, agrega statuses[] a la solicitud y repítelo para indicar más de un estado, como en ?statuses[]=running&statuses[]=idle. Omítelo para devolver hilos de todos los estados.
Interrumpir un hilo de sesión
Envía user.interrupt con session_thread_id para detener un hilo específico. Omitir session_thread_id interrumpe todos los hilos no archivados de la sesión, incluido el principal. En una sesión con flujos de trabajo dinámicos, una interrupción no finaliza ninguna ejecución, y una que nombra un hilo de una ejecución no detiene nada. Una interrupción cierra las llamadas a herramientas pendientes de otros hilos hijos, pero no confíes en ella para cerrar las de un hilo de ejecución. Consulta Interrumpir una sesión con ejecuciones abiertas.
client.beta.sessions.events.send(
session.id,
events=[{"type": "user.interrupt", "session_thread_id": thread.id}],
)Si el hilo de un subagente está bloqueado en requires_action, la interrupción cierra cada llamada a herramienta pendiente con un resultado de herramienta de error ("Tool execution was interrupted before completion. Please retry.") y vuelve a emitir session.thread_status_idle con stop_reason: end_turn directamente; no se muestrea el modelo. Si el hilo hijo está inactivo con end_turn o budget_reached, la interrupción no tiene efecto. Una interrupción que nombra un hilo terminado devuelve un error 400. Un hijo interrumpido no envía al agente del hilo principal el informe que envía cuando termina un turno. Mientras ese agente espera al hijo, no inicia otro turno hasta que le llegue algo más, como un user.message o el informe de otro hilo.
Archivar un hilo de sesión
Opcionalmente, archiva un hilo de sesión cuando haya completado su trabajo. Archivar un hilo libera su lugar dentro del límite de 25 hilos hijos. El servidor archiva por sí mismo los hilos de una ejecución de flujo de trabajo. No necesitas archivarlos, y no puedes hacerlo mientras la ejecución esté abierta.
archived = client.beta.sessions.threads.archive(thread.id, session_id=session.id)
print(archived.status, archived.archived_at)Archivar solo tiene éxito si el hilo está idle. Un hilo detenido en requires_action cuenta como inactivo y se puede archivar directamente; solo un hilo en ejecución debe interrumpirse primero:
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)Eventos del hilo principal
Estos eventos muestran la actividad multiagente en el hilo principal en /v1/sessions/{session_id}/events/stream. Los eventos de mensajes se nombran según el hilo en cuyo flujo aparecen: agent.thread_message_received significa que llegó un mensaje a este hilo desde otro hilo, y agent.thread_message_sent significa que este hilo envió uno. La tarea que delega el agente del hilo principal, por ejemplo, llega al flujo propio del hijo como un evento agent.thread_message_received.
| Tipo | Descripción |
|---|---|
session.thread_created | Se creó un hilo. Incluye session_thread_id y agent_name. |
session.thread_status_running | Un hilo inició actividad. |
session.thread_status_idle | El agente asociado al hilo está esperando una entrada. Incluye un stop_reason que indica por qué se detuvo el agente. |
session.thread_status_terminated | Un hilo terminó y no acepta más entradas, por ejemplo porque se archivó o encontró un error irrecuperable. Un hilo de asesor también termina cuando finaliza su consulta. |
agent.thread_message_received | En el hilo principal, un subagente envió al agente del hilo principal un informe o una pregunta. Incluye from_session_thread_id, from_agent_name y content. |
agent.thread_message_sent | En el hilo principal, el agente del hilo principal envió a un subagente una tarea o un mensaje de seguimiento. Incluye to_session_thread_id, to_agent_name y content. |
Las consultas al asesor emiten estos mismos eventos de hilo bajo el nombre reservado anthropic.advisor (como agent_name en los eventos del ciclo de vida del hilo y como from_agent_name en la entrega del consejo); consulta Darle un asesor a la sesión para ver la secuencia.
Los hilos de una ejecución de flujo de trabajo se muestran en el flujo principal de la siguiente manera:
- Eventos del ciclo de vida: Cada hilo de ejecución envía
session.thread_created, con elworkflow_run_idde la ejecución, y sus eventossession.thread_status_running,session.thread_status_idleysession.thread_status_terminated. - Eventos de mensajes: El prompt de un hilo de ejecución, un evento
agent.thread_message_received, permanece en su propio flujo. - Eventos de ejecución: Los eventos
workflow_run.*también llegan a este flujo; consulta Eventos de ejecución. - Llamadas a herramientas que esperan tu respuesta: Las llamadas a herramientas de un hilo de ejecución que necesitan a tu cliente se publican también en este flujo, como ocurre con cualquier hilo hijo. Consulta Permisos de herramientas y herramientas personalizadas.
Eventos del hilo de sesión
Los eventos críticos se reenvían al hilo principal. Sin embargo, es posible que aún quieras investigar el razonamiento y las llamadas a herramientas de un agente específico. Para hacerlo, haz streaming o lista los eventos del hilo de sesión asociado.
Cada hilo de sesión tiene su propio flujo de eventos en /v1/sessions/{session_id}/threads/{thread_id}/stream, y acepta el mismo parámetro event_deltas[] que el flujo a nivel de sesión, por lo que puedes previsualizar el texto de un subagente a medida que el modelo lo genera. Una conexión solo previsualiza el hilo que está leyendo: las previsualizaciones de un hilo hijo nunca aparecen en el flujo a nivel de sesión, así que para observar a un subagente en vivo, abre el flujo de su propio hilo. Consulta Previsualizar eventos de hilos de sesión para saber cómo activar, acumular y conciliar las previsualizaciones.
En una ejecución de flujo de trabajo, el servidor ejecuta un flujo de trabajo: un programa que escribe el agente del hilo principal. En cada uno de los hilos de la ejecución, el primer agent.thread_message_received es el prompt que escribió el flujo de trabajo. Su from_session_thread_id es el ID del hilo principal, y no tiene from_agent_name. La API no garantiza el texto del prompt, así que no lo analices. El evento session.thread_status_terminated del hilo, en el flujo del hilo principal, te indica que el hilo terminó. Ningún evento registra el resultado que devolvió al flujo de trabajo.
El flujo de un hilo no reproduce eventos anteriores. Justo después de session.thread_created, la lista de eventos del hilo de una ejecución puede estar vacía, porque el servidor escribe el primer evento del hilo después de ese. Así que abre primero el flujo del hilo, luego lista los eventos del hilo y omite cada evento recibido por streaming cuyo id haya devuelto la lista.
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":
breakLista todos los eventos pasados del hilo de sesión para obtener un historial completo.
for event in client.beta.sessions.threads.events.list(
thread.id,
session_id=session.id,
):
print(f"[{event.type}] {event.processed_at}")Permisos de herramientas y herramientas personalizadas
Si un subagente necesita algo de tu cliente, como permiso para ejecutar una llamada a herramienta o el resultado de una herramienta personalizada, el evento se publica también en el hilo principal con un session_thread_id que identifica el hilo de sesión de origen. Una llamada a herramienta necesita tu permiso bajo always_ask, o bajo auto cuando el servidor no llega a ninguna determinación.
{
"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..."]
}
}Publica user.tool_confirmation (con tool_use_id) o user.custom_tool_result (con custom_tool_use_id); el servidor enruta la respuesta al hilo correcto automáticamente. La respuesta puede aparecer en el hilo principal y en el hilo del subagente con valores de id diferentes. Para emparejar las dos copias, compara type y tool_use_id (o custom_tool_use_id), no id.
La sesión pasa a idle solo cuando ningún hilo está running, por lo que session.status_idle puede llegar mucho después de la llamada de un subagente. No tienes que esperarlo: envía el user.custom_tool_result en cuanto llegue el evento agent.custom_tool_use publicado en el hilo principal.
Bajo auto, tus eventos user.message pueden llevar al servidor a permitir una llamada que de otro modo denegaría. Nada en el hilo de un subagente cuenta como tu intención. Tu cliente no publica mensajes allí, y los mensajes que el agente del hilo principal envía al subagente no cuentan. Cuando el servidor deniega una llamada bajo auto, no se publica nada en el hilo principal: el evento y el resultado de herramienta de error aparecen solo en el propio flujo del hilo del subagente, y el subagente sigue ejecutándose.
El siguiente ejemplo va dentro del bucle de eventos del controlador de confirmación de herramientas. Para cada ID en stop_reason.event_ids, envía un user.tool_confirmation que permite la llamada. El mismo patrón se aplica 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",
}
],
)El patrón anterior responde a las llamadas que enumera un evento de inactividad. En el flujo principal, el evento session.thread_status_idle de un subagente puede llegar antes que los eventos agent.tool_use o agent.mcp_tool_use que enumera su stop_reason.event_ids. Un user.tool_confirmation para una llamada cuyo evento aún no ha llegado puede devolver 400. Para evitarlo, responde a cada llamada cuyo evaluated_permission sea ask cuando su propio evento llegue al flujo principal.
Was this page helpful?