Previsualizar respuestas con deltas de eventos
Renderiza el texto de respuesta del agente como una vista previa en vivo mientras el modelo todavía lo está generando.
De forma predeterminada, el texto de respuesta del agente llega al flujo de eventos de la sesión como eventos agent.message almacenados en búfer. Cada uno se emite solo después de que finaliza la solicitud al modelo que lo produjo. Los "event deltas" (deltas de eventos) te permiten renderizar ese texto de forma incremental, como una vista previa en vivo, mientras el modelo todavía lo está generando.
Las vistas previas son una ayuda de visualización de mejor esfuerzo, y el agent.message almacenado en búfer es siempre el registro autoritativo. Un cliente que ignora las vistas previas sigue recibiendo un flujo completo y correcto.
Activar las vistas previas
Las vistas previas se activan por conexión de flujo. Agrega el parámetro de consulta event_deltas[] al flujo que estás leyendo y repítelo una vez por cada tipo de evento que quieras previsualizar. Los valores aceptados son agent.message y agent.thinking. Cualquier otro valor devuelve un error 400, al igual que una solicitud con más de 100 valores.
Ambos endpoints de flujo aceptan el parámetro:
- Flujo a nivel de sesión:
GET /v1/sessions/{session_id}/events/stream - Flujo de hilo de sesión:
GET /v1/sessions/{session_id}/threads/{thread_id}/stream
Las vistas previas de un subagente aparecen en el propio flujo de hilo de ese subagente.
[] es un patrón glob del shell, así que pon la URL entre comillas siempre que construyas la solicitud en un shell. Los ejemplos codifican los corchetes como %5B%5D, lo cual también funciona.
Eventos de vista previa
Cuando comienza un evento con vista previa, el flujo emite un event_start que lleva el tipo y el id del evento que está por llegar:
{
"type": "event_start",
"event": {
"type": "agent.message",
"id": "sevt_01abc..."
}
}Para agent.message, al inicio le siguen eventos event_delta que llevan texto incremental. Cada delta indica el evento que extiende en event_id y el bloque de contenido que extiende en delta.index:
{
"type": "event_delta",
"event_id": "sevt_01abc...",
"delta": {
"type": "content_delta",
"index": 0,
"content": {
"type": "text",
"text": "Here is the summary"
}
}
}Para agent.thinking, solo se emite el event_start, como señal de que ha comenzado un bloque de pensamiento. No le siguen eventos event_delta. El evento agent.thinking almacenado en búfer que concluye la vista previa es una señal de progreso y no lleva contenido de pensamiento.
A diferencia de los eventos persistidos, event_start y event_delta no tienen id ni processed_at propios. El único identificador que llevan es el id del evento que previsualizan. Sus cadenas de tipo también son la excepción a la convención de nomenclatura {domain}.{action} de los eventos persistidos.
Acumular y conciliar
Cada SDK que admite deltas de eventos incluye un helper acumulador que gestiona por ti el seguimiento de index. El patrón manual de esta sección funciona en todos los lenguajes cuando necesitas un seguimiento personalizado. Aplícalo a los tipos de eventos generados.
En el patrón manual, guarda el texto de vista previa en un mapa temporal con clave (event_id, index) y trata el evento almacenado en búfer como el registro. Concilia ambos por cada solicitud al modelo.
Un turno se abre con un único evento session.status_running. En un turno que se completa normalmente, cada solicitud al modelo produce entonces estos eventos, en orden:
span.model_request_startevent_start- Los eventos
event_delta - El
agent.messagealmacenado en búfer span.model_request_end(en la pestaña Eventos de span)
En la transmisión, esta es la parte previsualizada de esa secuencia, intercalada con los demás eventos almacenados en búfer de la conexión:
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": [...]}La línea event_delta se repite una vez por fragmento de texto. Procesa cada evento a medida que llega:
- En
event_start, anota elidanunciado. Los identificadores siempre coinciden:event_start.event.id, cadaevent_delta.event_idy eliddelagent.messagealmacenado en búfer son el mismo valor. - En cada
event_delta, agregadelta.content.texta la entrada en(event_id, delta.index)y renderiza el texto acumulado. El primer delta para unindexcrea esa entrada. - Cuando llegue el
agent.messagealmacenado en búfer, emparéjalo porid, descarta la vista previa acumulada y renderiza en su lugar el contenido del mensaje. - En
span.model_request_end, cierra cualquier vista previa que no haya sido conciliada por su evento almacenado en búfer. No llegarán más deltas para ella. Si el turno produce un error o se interrumpe, es posible que el evento almacenado en búfer nunca llegue, perospan.model_request_endsí llega.
El patrón se basa en dos garantías:
- Concatenar los deltas de una vista previa en orden de llegada, con clave
(event_id, index), da un prefijo decontent[index].texten el evento almacenado en búfer. No es necesariamente el texto completo, porque los deltas podrían descartarse bajo carga. - Una conexión emite como máximo un
event_startporevent_id, y el evento almacenado en búfer es lo último que esa conexión entrega para eseid.
Helpers acumuladores del SDK
El helper de cada SDK gestiona el seguimiento de index. Los helpers de Go, Java, Ruby y C# también usan el id del evento como clave de la vista previa acumulada. Con los helpers de Python, TypeScript y PHP, mantén ese mapa tú mismo e incorpora cada delta a la entrada de su id.
Los siguientes ejemplos activan las vistas previas de agent.message y las concilian con el evento almacenado en búfer:
# Instantáneas de vista previa, indexadas por id de evento. accumulate_managed_agents_event pliega cada
# event_start / event_delta en una instantánea agent.message; el agent.message
# almacenado en búfer la reemplaza.
previews: dict[str, BetaManagedAgentsAgentMessageEvent] = {}
# Habilita las vistas previas de agent.message en esta conexión
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":
# El evento almacenado en búfer es el registro: reemplaza y cierra la vista previa
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":
# Ya no llegarán más deltas. Cierra cualquier vista previa cuyo
# evento almacenado en búfer nunca llegó.
for event_id in previews:
print(f"span.model_request_end closing preview for {event_id}")
previews.clear()
case "session.status_idle":
breakPrevisualizar eventos de hilos de sesión
En una sesión multiagente, cada hilo de sesión tiene su propio flujo de eventos. Acepta el mismo parámetro event_deltas[] con los mismos valores.
Una conexión previsualiza solo el hilo que está leyendo. El flujo a nivel de sesión previsualiza el hilo principal, y las vistas previas de un hilo hijo nunca se publican en él. Para ver el texto de un subagente a medida que el modelo lo genera, abre el flujo de hilo de ese subagente.
La ruta de un flujo de hilo termina en /threads/{thread_id}/stream. /events/stream existe solo a nivel de sesión, por lo que no hay un endpoint /threads/{thread_id}/events/stream.
event_start y event_delta tienen la misma forma en un flujo de hilo que en el flujo a nivel de sesión, y el patrón de acumular y conciliar se aplica tal como está escrito. Ejecuta una instancia de acumulador por cada conexión de flujo.
# Lista los hilos de la sesión y elige un hijo: los hilos hijos tienen un parent_thread_id
# no nulo, y el parent_thread_id del hilo principal es null.
child_thread = next(
thread
for thread in client.beta.sessions.threads.list(session.id)
if thread.parent_thread_id is not None
)
# El stream del hilo hijo acepta el mismo parámetro event_deltas que el
# stream de la sesión.
with client.beta.sessions.threads.events.stream(
child_thread.id,
session_id=session.id,
event_deltas=["agent.message"],
) as stream:
for event in stream:
match event.type:
case "event_delta":
print(event.delta.content.text, end="")
case "agent.message":
# El evento almacenado en búfer es el registro autoritativo; renderiza su contenido
print()
for block in event.content:
if block.type == "text":
print(block.text, end="")
print()
case "session.thread_status_idle":
breakEl bucle de lectura termina en session.thread_status_idle, el evento emitido cuando el turno del hilo de sesión finaliza y el hilo queda inactivo.
Limitaciones
- Mejor esfuerzo: Bajo carga, el servidor podría descartar deltas de un evento. Cuando lo hace, recibes un prefijo contiguo del texto y luego ningún delta más para ese evento. El
agent.messagealmacenado en búfer sigue llegando completo. Nunca trates una vista previa acumulada como definitiva. - Sin repetición al reconectar: Los deltas se entregan solo a la conexión que los activó, mientras está abierta. Esto se aplica por igual al flujo a nivel de sesión y a cada flujo de hilo de sesión. Una conexión abierta después de que comenzó una solicitud al modelo no recibe deltas para ese evento en curso. No hay forma de volver a solicitar los deltas perdidos.
- Un hilo, solo texto: Las vistas previas cubren el texto del asistente en el hilo que la conexión está leyendo. El uso de herramientas, los resultados de herramientas y los resultados de MCP nunca se previsualizan.
- Nunca se persisten:
event_startyevent_deltaexisten solo en el flujo en vivo. No aparecen en el historial de eventos de la sesión (GET /v1/sessions/{session_id}/events) ni en el historial de eventos de ningún hilo de sesión.
Solucionar problemas de las vistas previas
| Lo que ves | Qué significa |
|---|---|
Un flujo con eventos almacenados en búfer pero sin event_start ni event_delta | La conexión que estás leyendo no activó las vistas previas, o el turno nunca tocó el hilo que estás recibiendo por streaming. event_deltas[] se aplica por conexión, no por sesión. Para saber qué hilo se ejecutó, lista los hilos de la sesión (GET /v1/sessions/{session_id}/threads). |
| Un flujo que se cae durante una vista previa | Los deltas no se repiten. Sigue el procedimiento de reconexión: vuelve a abrir el flujo y lista el historial de eventos. El historial incluye cualquier evento almacenado en búfer emitido mientras estabas desconectado, incluido el agent.message que tu vista previa estaba esperando. |
| Un 404 en la URL del flujo | La ruta o un ID es incorrecto, o la solicitud no lleva ningún encabezado beta de managed-agents. Los endpoints de hilos están restringidos a la beta, así que sin el encabezado no existen. |
Un 400 que menciona event_deltas | Solo se aceptan agent.message y agent.thinking. |
Próximos pasos
Envía eventos, recibe respuestas por streaming e interrumpe o redirige tu sesión a mitad de la ejecución.
Coordina varios agentes dentro de una sola sesión.
Was this page helpful?