BuildStructured outputsStream structured output

Stream structured output

⚠️
Preview — this feature is being built; the design below is the spec.

Structured output streams like any other reply: the JSON text arrives in fragments. Users see progress, and your code can act on fields as soon as they are complete.

What arrives

With stream: true and a json_schema response format, each chunk’s delta.content holds the next piece of JSON text. The concatenation is always valid JSON matching the schema once the stream ends with finish_reason: "stop". Individual chunks are not valid JSON on their own.

Parsing as you go

Use a tolerant parser that completes an unfinished JSON prefix:

import { parse as parsePartial } from 'partial-json'
 
let text = ''
for await (const chunk of stream) {
  text += chunk.choices[0]?.delta?.content ?? ''
  const partial = parsePartial(text) // e.g. { "title": "Refund pol", "steps": [] }
  render(partial)
}

The SDK helpers do this for you: client.chat.completions.stream({..., response_format}) emits content.delta events with a parsed snapshot of the object so far.

Design for streaming

  • Put the fields people should see first at the top of the schema; fields are written in schema order.
  • For long lists, show items as each one closes rather than re-rendering the whole list on every chunk.
  • Do not act on a field (send an email, book a slot) until the stream has finished and the final object validated. A cut-off stream can leave a field half-written.

When the stream breaks

If the stream ends with an error event or finish_reason: "length", the JSON is incomplete. Discard it and retry with a higher max_tokens, or narrow the schema. See Refusals and cut-offs.

Was this page helpful?