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.
/v1/chat/completionsPOST/v1/responsesPOST/v1/messagesComentarios 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-keepaliveLas 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]| Campo | Descripción |
|---|---|
choices[].delta.content | Texto de este fragmento |
choices[].delta.tool_calls | Los argumentos de las llamadas a herramientas llegan por partes; concatene function.arguments según index |
choices[].finish_reason | No vacío en el último fragmento: stop / length / tool_calls |
usage | Solo 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}}}| Evento | Descripción |
|---|---|
response.created | Empieza la respuesta |
response.output_text.delta | Un fragmento de texto de salida, en delta |
response.output_text.done | Termina un bloque de contenido; text es el texto completo |
response.completed | Termina con éxito; response.usage contiene el uso |
response.failed | Falla 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: errorSi 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.