Learn how to create several streamText steps with different settings
You may want to have different steps in your stream where each step has different settings,
e.g. models, tools, or system prompts.
With createUIMessageStream and sendFinish / sendStart options when merging
into the UIMessageStream, you can control when the finish and start events are sent to the client,
allowing you to have different steps in a single assistant UI message.
import { convertToModelMessages, createUIMessageStream, createUIMessageStreamResponse, streamText, toUIMessageStream, tool,} from 'ai';import { z } from 'zod';export async function POST(req: Request) { const { messages } = await req.json(); const stream = createUIMessageStream({ execute: async ({ writer }) => { const modelMessages = await convertToModelMessages(messages); // step 1 example: forced tool call const result1 = streamText({ model: 'openai/gpt-6-luna', instructions: 'Extract the user goal from the conversation.', messages: modelMessages, toolChoice: 'required', // force the model to call a tool tools: { extractGoal: tool({ inputSchema: z.object({ goal: z.string() }), execute: async ({ goal }) => goal, // no-op extract tool }), }, }); // forward the initial result to the client without the finish event: writer.merge( toUIMessageStream({ stream: result1.stream, sendFinish: false }), ); // note: you can use any programming construct here, e.g. if-else, loops, etc. // workflow programming is normal programming with this approach. // example: continue stream with forced tool call from previous step const result2 = streamText({ // different system prompt, different model, no tools: model: 'openai/gpt-6-astra', instructions: 'You are a helpful assistant with a different system prompt. Repeat the extract user goal in your answer.', // continue the workflow stream with the messages from the previous step: messages: [...modelMessages, ...(await result1.response).messages], }); // forward the 2nd result to the client (incl. the finish event): writer.merge( toUIMessageStream({ stream: result2.stream, sendStart: false }), ); }, }); return createUIMessageStreamResponse({ stream });}