Record Final Object after Streaming Object
When you're streaming structured data, you may want to record the final object for logging or other purposes.
onFinish and output
Use onFinish for metadata like token usage and await result.output for the final structured object.
import { streamText, Output } from 'ai';import { z } from 'zod';
const result = streamText({ model: 'openai/gpt-4.1', output: Output.object({ schema: z.object({ recipe: z.object({ name: z.string(), ingredients: z.array(z.string()), steps: z.array(z.string()), }), }), }), prompt: 'Generate a lasagna recipe.', onFinish({ usage }) { console.log('Token usage:', usage); },});
for await (const _ of result.partialOutputStream) {}
try { const output = await result.output; console.log('Final object:', JSON.stringify(output, null, 2));} catch (error) { console.error('Failed to parse output:', error);}output Promise
The streamText result contains an output promise that resolves to the final object.
The object is fully typed. When the type validation according to the schema fails, the promise will be rejected with a TypeValidationError.
import { streamText, Output } from 'ai';import { z } from 'zod';
const result = streamText({ model: 'openai/gpt-4.1', output: Output.object({ schema: z.object({ recipe: z.object({ name: z.string(), ingredients: z.array(z.string()), steps: z.array(z.string()), }), }), }), prompt: 'Generate a lasagna recipe.',});
for await (const partialObject of result.partialOutputStream) {}
try { const { recipe } = await result.output; console.log('Recipe:', JSON.stringify(recipe, null, 2));} catch (error) { console.error(error);}