Guides

Streaming responses

Server-sent events, chunk format, and how to cancel a generation cleanly.

Set stream: true and the response becomes a text/event-stream of chunks in the OpenAI streaming format. Existing SSE parsers work unchanged.

Chunk format

Each event carries a partial delta. The stream ends with a literal [DONE].

stream.txt
data: {"id":"cmpl_9f2a1c","choices":[{"delta":{"role":"assistant"},"index":0}]}
 
data: {"id":"cmpl_9f2a1c","choices":[{"delta":{"content":"Reserved"},"index":0}]}
 
data: {"id":"cmpl_9f2a1c","choices":[{"delta":{"content":" capacity"},"index":0}]}
 
data: {"id":"cmpl_9f2a1c","choices":[{"delta":{},"index":0,"finish_reason":"stop"}]}
 
data: [DONE]

Consuming the stream

stream.tstypescript
const stream = await client.chat.completions.create({
  model: "stac-1",
  messages,
  stream: true,
});
 
for await (const chunk of stream) {
  const delta = chunk.choices[0]?.delta?.content;
  if (delta) process.stdout.write(delta);
}

The -N flag matters for curl: without it the output is buffered and the stream looks like a slow non-streaming response.

Cancelling

Abort the HTTP request. Stac stops generation as soon as the connection closes, freeing that capacity for the next request.

cancel.tstypescript
const controller = new AbortController();
setTimeout(() => controller.abort(), 5000);
 
try {
  const stream = await client.chat.completions.create(
    { model: "stac-1", messages, stream: true },
    { signal: controller.signal }
  );
} catch (error) {
  if (error.name === "AbortError") return;
  throw error;
}

Errors mid-stream

Once the response headers are sent the status is already 200, so a failure after that point can only arrive as a broken connection, not an HTTP error status. Treat a stream that ends without a [DONE] event as a failure and retry the request from scratch — there's no partial-resume.