This guide covers the changes needed when upgrading from AI SDK v5 to v6 with @cloudflare/ai-chat.
npm install ai@latest @ai-sdk/react@latest @ai-sdk/openai@latestAdd await to all calls:
// v5
const result = streamText({
messages: convertToModelMessages(this.messages),
model: openai("gpt-4o")
});
// v6
const result = streamText({
messages: await convertToModelMessages(this.messages),
model: openai("gpt-4o")
});Replace CoreMessage with ModelMessage and convertToCoreMessages() with convertToModelMessages():
// v5
import { convertToCoreMessages, type CoreMessage } from "ai";
// v6
import { convertToModelMessages, type ModelMessage } from "ai";v6 introduces needsApproval and the onToolCall callback. For most apps, define tools on the server with tool() from "ai" for full Zod type safety:
Before (v5):
// Client defined tools with AITool type
useAgentChat({
agent,
tools: clientTools,
experimental_automaticToolResolution: true,
toolsRequiringConfirmation: ["askConfirmation"]
});After (v6):
// Server: all tools defined here
const tools = {
getWeather: tool({
description: "Get weather",
inputSchema: z.object({ city: z.string() }),
execute: async ({ city }) => fetchWeather(city)
}),
getLocation: tool({
description: "Get user location",
inputSchema: z.object({})
// No execute -- client handles via onToolCall
}),
processPayment: tool({
description: "Process payment",
inputSchema: z.object({ amount: z.number() }),
needsApproval: async ({ amount }) => amount > 100,
execute: async ({ amount }) => charge(amount)
})
};
// Client: handle tools via callbacks
useAgentChat({
agent,
onToolCall: async ({ toolCall, addToolOutput }) => {
if (toolCall.toolName === "getLocation") {
const pos = await getPosition();
addToolOutput({
toolCallId: toolCall.toolCallId,
output: { lat: pos.coords.latitude, lng: pos.coords.longitude }
});
}
}
});Dynamic client tools (SDK/platform pattern):
If you are building an SDK or platform where tools are defined dynamically by the embedding application at runtime, the tools option on useAgentChat and createToolsFromClientSchemas() on the server are still fully supported:
// Server: accept whatever tools the client sends
const tools = {
...createToolsFromClientSchemas(options.clientTools),
...serverTools
};
// Client: register tools dynamically
useAgentChat({
agent,
tools: dynamicTools,
onToolCall: async ({ toolCall, addToolOutput }) => {
const tool = dynamicTools[toolCall.toolName];
if (tool?.execute) {
const output = await tool.execute(toolCall.input);
addToolOutput({ toolCallId: toolCall.toolCallId, output });
}
}
});Remove mode: "json" or similar from generateObject calls.
In v6, these check both static and dynamic tool parts. For the old behavior, use isStaticToolUIPart and getStaticToolName. Most users do not need to change anything.
| Deprecated | Replacement |
|---|---|
toolsRequiringConfirmation |
needsApproval on server tools |
experimental_automaticToolResolution |
onToolCall callback |
addToolResult() |
addToolOutput() or addToolApprovalResponse() |
Not deprecated: AITool, createToolsFromClientSchemas(), extractClientToolSchemas(), and the tools option on useAgentChat are supported for SDK/platform use cases where tools are defined dynamically at runtime.
Packages:
aito^6.0.0@ai-sdk/reactto^3.0.0@ai-sdk/openai(and other providers) to^3.0.0
Code changes:
- Add
awaitto allconvertToModelMessages()calls - Replace
CoreMessagewithModelMessage - Replace
convertToCoreMessages()withconvertToModelMessages() - Remove
modefromgenerateObjectcalls - Move static tool definitions to server using
tool()(recommended for most apps) - Use
onToolCallinuseAgentChatfor client-side tool execution - Replace
toolsRequiringConfirmationwithneedsApproval - Replace
addToolResult()withaddToolOutput()oraddToolApprovalResponse()
- Official AI SDK v6 migration guide
- Human in the Loop --
needsApprovalandaddToolApprovalResponse - Client Tools --
onToolCalland auto-continuation