type StructuredOutputStream<T> = AsyncIterable<
| Exclude<StreamChunk, CustomEvent>
| StructuredOutputStartEvent
| StructuredOutputCompleteEvent<T>
| ApprovalRequestedEvent
| ToolInputAvailableEvent>;type StructuredOutputStream<T> = AsyncIterable<
| Exclude<StreamChunk, CustomEvent>
| StructuredOutputStartEvent
| StructuredOutputCompleteEvent<T>
| ApprovalRequestedEvent
| ToolInputAvailableEvent>;Defined in: packages/ai/src/types.ts:1318
Public type for streams returned by chat({ outputSchema, stream: true }).
Yields all standard StreamChunk lifecycle events plus the three tagged CUSTOM events the orchestrator can emit through this path:
Each variant has a literal name, so a single discriminated narrow gives you a typed value with no helper or cast:
for await (const chunk of stream) {
if (chunk.type === 'CUSTOM' && chunk.name === 'structured-output.complete') {
chunk.value.object // typed as T
} else if (chunk.type === 'CUSTOM' && chunk.name === 'approval-requested') {
chunk.value.toolCallId // typed as string
}
}for await (const chunk of stream) {
if (chunk.type === 'CUSTOM' && chunk.name === 'structured-output.complete') {
chunk.value.object // typed as T
} else if (chunk.type === 'CUSTOM' && chunk.name === 'approval-requested') {
chunk.value.toolCallId // typed as string
}
}Caveat: tools can emit arbitrary user-defined custom events via the emitCustomEvent(name, value) context API. Those flow through this stream at runtime but are intentionally absent from this type — including a bare CustomEvent (whose value: any would poison the union) would collapse chunk.value back to any after the narrow. If you rely on emitCustomEvent plus outputSchema + stream: true, branch on CUSTOM outside the literal-name narrows or cast explicitly.
T = unknown