Repeated assistant messages in useChat
Issue
When using useChat
with streamText
on the server, the assistant's messages appear duplicated in the UI - showing both the previous message and the new message, or showing the same message multiple times. This can occur when using tool calls or complex message flows.
// Server-side code that may experience assistant message duplication on the clientexport async function POST(req: Request) { const { messages } = await req.json();
const result = streamText({ model: openai('gpt-4o-mini'), messages: convertToModelMessages(messages), tools: { weather: { description: 'Get the weather for a location', parameters: z.object({ location: z.string(), }), execute: async ({ location }) => { return { temperature: 72, condition: 'sunny' }; }, }, }, });
return result.toUIMessageStreamResponse();}
Background
The duplication occurs because toUIMessageStreamResponse
generates new message IDs for each new message.
Solution
Pass the original messages array to toUIMessageStreamResponse
using the originalMessages
option. By passing originalMessages
, the method can reuse existing message IDs instead of generating new ones, ensuring the client properly updates existing messages rather than creating duplicates.
export async function POST(req: Request) { const { messages } = await req.json();
const result = streamText({ model: openai('gpt-4o-mini'), messages: convertToModelMessages(messages), tools: { weather: { description: 'Get the weather for a location', parameters: z.object({ location: z.string(), }), execute: async ({ location }) => { return { temperature: 72, condition: 'sunny' }; }, }, }, });
return result.toUIMessageStreamResponse({ originalMessages: messages, // Pass the original messages here generateMessageId: generateId, onFinish: ({ messages }) => { saveChat({ id, messages }); }, });}