Saltar al contenido

Eventos de streaming

Formato de los eventos SSE de los tres protocolos con stream: true, los comentarios keepalive que inserta HopBase y cómo se entregan los errores a mitad del stream.

Al enviar "stream": true en el cuerpo de la solicitud, Crear una completion de chat, Crear una respuesta y Crear un mensaje devuelven text/event-stream (SSE). El formato de los eventos sigue la definición oficial de cada protocolo, así que las interfaces de streaming de los SDK oficiales funcionan directamente; HopBase solo inserta comentarios keepalive y no modifica el contenido de los eventos.

POST/v1/chat/completionsPOST/v1/responsesPOST/v1/messages

Comentarios keepalive

Durante el streaming, HopBase escribe aproximadamente cada 10 segundos una línea de comentario SSE entre dos eventos, para que los proxies intermedios no consideren inactiva la conexión y la corten durante razonamientos largos:

: hopbase-keepalive

Las líneas que empiezan con dos puntos son comentarios según la especificación SSE; los SDK oficiales y los analizadores SSE estándar las ignoran. Si analiza el stream línea por línea usted mismo, omita las líneas que empiezan con : en lugar de interpretarlas como JSON. Si el modelo pasa mucho tiempo sin ninguna salida (unos 90–150 segundos, según el modelo), el gateway lo considera atascado y reintenta o devuelve un error; ver Concurrencia, tiempos de espera y facturación.

Chat Completions

Cada evento es una línea data: con un objeto chat.completion.chunk; el texto está en choices[0].delta.content. El stream termina con data: [DONE].

data: {"id":"chatcmpl-EXAMPLE","object":"chat.completion.chunk","model":"gpt-5.6-sol","choices":[{"index":0,"delta":{"role":"assistant","content":"Soy"},"finish_reason":null}]}

data: {"id":"chatcmpl-EXAMPLE","object":"chat.completion.chunk","model":"gpt-5.6-sol","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}

data: {"id":"chatcmpl-EXAMPLE","object":"chat.completion.chunk","model":"gpt-5.6-sol","choices":[],"usage":{"prompt_tokens":14,"completion_tokens":52,"total_tokens":66}}

data: [DONE]
CampoDescripción
choices[].delta.contentTexto de este fragmento
choices[].delta.tool_callsLos argumentos de las llamadas a herramientas llegan por partes; concatene function.arguments según index
choices[].finish_reasonNo vacío en el último fragmento: stop / length / tool_calls
usageSolo se envía si la solicitud incluye stream_options.include_usage: true, en el último evento con choices vacío; omitirlo no afecta la facturación

Responses

Cada evento consta de una línea event: y una línea data:; el type dentro de data coincide con el nombre del evento.

event: response.created
data: {"type":"response.created","response":{"id":"resp_EXAMPLE","status":"in_progress"}}

event: response.output_text.delta
data: {"type":"response.output_text.delta","item_id":"msg_EXAMPLE","output_index":0,"content_index":0,"delta":"Soy"}

event: response.completed
data: {"type":"response.completed","response":{"id":"resp_EXAMPLE","status":"completed","usage":{"input_tokens":14,"output_tokens":58,"total_tokens":72}}}
EventoDescripción
response.createdEmpieza la respuesta
response.output_text.deltaUn fragmento de texto de salida, en delta
response.output_text.doneTermina un bloque de contenido; text es el texto completo
response.completedTermina con éxito; response.usage contiene el uso
response.failedFalla a mitad; el motivo está en response.error.code: rate_limit_exceeded / server_error / invalid_prompt

Anthropic Messages

Orden de los eventos: message_start → por cada bloque de contenido content_block_start / content_block_delta / content_block_stop → message_delta (con stop_reason y el uso de salida) → message_stop.

event: message_start
data: {"type":"message_start","message":{"id":"msg_EXAMPLE","role":"assistant","model":"claude-sonnet-5","content":[],"usage":{"input_tokens":9,"output_tokens":1}}}

event: content_block_delta
data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"¡Hola!"}}

event: message_delta
data: {"type":"message_delta","delta":{"stop_reason":"end_turn"},"usage":{"output_tokens":14}}

event: message_stop
data: {"type":"message_stop"}

Errores en el stream

Una vez que el stream empieza a emitir salida, el código de estado HTTP ya es 200; los errores posteriores llegan como eventos y el código de estado ya no cambia:

Chat Completions   data: {"error": {…}}      (sin línea event:)
Responses          event: response.failed
Anthropic          event: error

Si un stream de Claude se corta a mitad, HopBase envía un evento de error de Anthropic y luego termina:

event: error
data: {"type":"error","error":{"type":"api_error","message":"Response stream interrupted, please retry"}}

El cliente debe manejar los eventos de error dentro del bucle que lee el stream. Los fragmentos ya recibidos no se pueden reanudar: hay que volver a enviar la solicitud completa; la parte generada antes de la interrupción se factura según el uso. La estrategia de reintento está en Códigos de error y reintentos.