Stream answers
Show an answer as the model writes it, and know how many units it used.
With stream set to true, the answer arrives as the model writes it, as server-sent events. Your app can show words as they come instead of waiting for the whole answer.
Stream with an SDK
Ask for usage too, so the last event says what the call used.
const stream = await client.chat.completions.create({
model: "openai/gpt-oss-120b",
messages: [
{ role: "user", content: "Write a short poem about the ocean." },
],
stream: true,
stream_options: { include_usage: true },
})
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "")
if (chunk.usage) console.log(`\n${chunk.usage.units} AI units`)
}What arrives
- Each event is a line starting
data:with one chunk of the answer, then a blank line. - A chunk's
delta.contentis the next piece of the answer. A reasoning model's thinking arrives first, indelta.reasoning, so you can show it apart or leave it out. - The chunk that ends the answer has
finish_reason:tool_callswhen the model wants a tool. - A line starting with
:is a keep-alive comment, sent every 15 seconds while the model is thinking. Skip it; the SDKs do. - With
include_usage, the last chunk has no choices and holdsusage, withunits. - The stream ends with
data: [DONE].
When a stream fails
Once a stream has started, its status is already 200. If it fails partway, the last event is data: followed by an error in the same shape as any other, all on one line, and the stream ends without [DONE]. Here is that error, spread out to read:
{
"error": {
"message": "A service this request depends on is unavailable, try again shortly.",
"type": "model_unavailable",
"code": "model_unavailable",
"param": null
},
"requestId": "01m3c081dbf3j55x7hsa7wc1yj"
}The SDKs raise it as an error. What the model wrote before it stopped still counts toward your units.
When your app stops reading
If your app closes the connection, the model stops too, and only what it wrote until then counts.
Last updated