agents 0.16.2 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -8
- package/dist/{agent-tool-types-CTw3UJUP.d.ts → agent-tool-types-Cd1TZPfB.d.ts} +587 -137
- package/dist/agent-tool-types.d.ts +34 -18
- package/dist/agent-tool-types.js +20 -1
- package/dist/agent-tool-types.js.map +1 -0
- package/dist/agent-tools-BXlsuX0d.js +304 -0
- package/dist/agent-tools-BXlsuX0d.js.map +1 -0
- package/dist/agent-tools-_E8wxUIK.d.ts +119 -0
- package/dist/agent-tools.d.ts +24 -18
- package/dist/agent-tools.js.map +1 -1
- package/dist/ai-chat-agent.d.ts +1 -1
- package/dist/ai-chat-agent.js +1 -2
- package/dist/ai-chat-agent.js.map +1 -1
- package/dist/ai-chat-v5-migration.d.ts +1 -1
- package/dist/ai-chat-v5-migration.js +1 -2
- package/dist/ai-chat-v5-migration.js.map +1 -1
- package/dist/ai-react.d.ts +1 -1
- package/dist/ai-react.js +1 -2
- package/dist/ai-react.js.map +1 -1
- package/dist/ai-types.d.ts +1 -7
- package/dist/ai-types.js +2 -8
- package/dist/ai-types.js.map +1 -1
- package/dist/browser/ai.js +1 -1
- package/dist/browser/index.js +1 -1
- package/dist/chat/index.d.ts +1918 -72
- package/dist/chat/index.js +1730 -245
- package/dist/chat/index.js.map +1 -1
- package/dist/chat/react.d.ts +602 -0
- package/dist/chat/react.js +1506 -0
- package/dist/chat/react.js.map +1 -0
- package/dist/chat-sdk/index.d.ts +4 -4
- package/dist/{classPrivateFieldGet2-CZ7QjTXN.js → classPrivateFieldGet2-DZBYAB34.js} +5 -5
- package/dist/{classPrivateMethodInitSpec-D-0__zd9.js → classPrivateMethodInitSpec-qMjJ6sHQ.js} +2 -2
- package/dist/{client-BXJ9n2f7.js → client-BZ-B3NhC.js} +2 -2
- package/dist/client-BZ-B3NhC.js.map +1 -0
- package/dist/client-tools-aIBO0Fk7.d.ts +53 -0
- package/dist/client.d.ts +76 -57
- package/dist/client.js +33 -5
- package/dist/client.js.map +1 -1
- package/dist/{connector-CrKhowfD.js → connector-CdldGF3h.js} +5 -5
- package/dist/{connector-CrKhowfD.js.map → connector-CdldGF3h.js.map} +1 -1
- package/dist/email.js +1 -1
- package/dist/email.js.map +1 -1
- package/dist/{index-B7IbEeze.d.ts → index-CcbnKkNh.d.ts} +188 -14
- package/dist/index.d.ts +91 -71
- package/dist/index.js +562 -24
- package/dist/index.js.map +1 -1
- package/dist/mcp/client.d.ts +18 -14
- package/dist/mcp/client.js +1 -1
- package/dist/mcp/index.d.ts +30 -30
- package/dist/mcp/index.js +7 -7
- package/dist/mcp/index.js.map +1 -1
- package/dist/{agent-tools-3zLG7MgA.js → message-builder-BymO4N_D.js} +45 -126
- package/dist/message-builder-BymO4N_D.js.map +1 -0
- package/dist/observability/index.d.ts +1 -1
- package/dist/observability/index.js +4 -2
- package/dist/observability/index.js.map +1 -1
- package/dist/react.d.ts +123 -110
- package/dist/react.js +44 -11
- package/dist/react.js.map +1 -1
- package/dist/serializable.d.ts +1 -1
- package/dist/skills/compile.js +1 -1
- package/dist/skills/compile.js.map +1 -1
- package/dist/skills/index.js +5 -5
- package/dist/skills/index.js.map +1 -1
- package/dist/sub-routing.d.ts +6 -6
- package/dist/utils.js +1 -1
- package/dist/utils.js.map +1 -1
- package/dist/vite.js +5 -5
- package/dist/vite.js.map +1 -1
- package/dist/wire-types-nflOzNuU.js +240 -0
- package/dist/wire-types-nflOzNuU.js.map +1 -0
- package/dist/{workflow-types-SrZK_o9p.d.ts → workflow-types-Baz_PO5v.d.ts} +42 -22
- package/dist/workflow-types.d.ts +25 -21
- package/dist/workflow-types.js.map +1 -1
- package/dist/workflows.d.ts +22 -21
- package/dist/workflows.js +31 -7
- package/dist/workflows.js.map +1 -1
- package/docs/adding-to-existing-project.md +450 -0
- package/docs/agent-class.md +503 -0
- package/docs/agent-tools.md +552 -0
- package/docs/browse-the-web.md +430 -0
- package/docs/callable-methods.md +627 -0
- package/docs/chat-agents.md +1687 -0
- package/docs/chat-sdk.md +181 -0
- package/docs/client-sdk.md +520 -0
- package/docs/client-tools-continuation.md +177 -0
- package/docs/codemode.md +440 -0
- package/docs/configuration.md +775 -0
- package/docs/cross-domain-authentication.md +171 -0
- package/docs/durable-execution.md +537 -0
- package/docs/email.md +663 -0
- package/docs/get-current-agent.md +204 -0
- package/docs/getting-started.md +305 -0
- package/docs/http-websockets.md +668 -0
- package/docs/human-in-the-loop.md +661 -0
- package/docs/index.md +151 -0
- package/docs/long-running-agents.md +730 -0
- package/docs/mcp-client.md +620 -0
- package/docs/mcp-servers.md +526 -0
- package/docs/mcp-transports.md +308 -0
- package/docs/migration-to-ai-sdk-v5.md +96 -0
- package/docs/migration-to-ai-sdk-v6.md +163 -0
- package/docs/observability.md +261 -0
- package/docs/push-notifications.md +367 -0
- package/docs/queue.md +329 -0
- package/docs/readonly-connections.md +278 -0
- package/docs/resumable-streaming.md +127 -0
- package/docs/retries.md +444 -0
- package/docs/routing.md +749 -0
- package/docs/scheduling.md +898 -0
- package/docs/securing-mcp-servers.md +359 -0
- package/docs/server-driven-messages.md +477 -0
- package/docs/sessions.md +1024 -0
- package/docs/state.md +512 -0
- package/docs/sub-agents.md +389 -0
- package/docs/webhooks.md +604 -0
- package/docs/workflows.md +877 -0
- package/package.json +41 -14
- package/dist/agent-tools-3zLG7MgA.js.map +0 -1
- package/dist/agent-tools-DZhI5F6Q.d.ts +0 -14
- package/dist/client-BXJ9n2f7.js.map +0 -1
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
# MCP Transports
|
|
2
|
+
|
|
3
|
+
This guide explains the different transport options for connecting to MCP servers with the Agents SDK.
|
|
4
|
+
|
|
5
|
+
For a primer on MCP servers and how they are implemented in the Agents SDK with `McpAgent`, see [Creating MCP Servers](./mcp-servers.md).
|
|
6
|
+
|
|
7
|
+
## Streamable HTTP Transport (Recommended)
|
|
8
|
+
|
|
9
|
+
The **Streamable HTTP** transport is the recommended way to connect to MCP servers.
|
|
10
|
+
|
|
11
|
+
### How it works
|
|
12
|
+
|
|
13
|
+
When a client connects to your MCP server:
|
|
14
|
+
|
|
15
|
+
1. The client makes an HTTP request to your Worker with a JSON-RPC message in the body
|
|
16
|
+
2. Your Worker upgrades the connection to a WebSocket
|
|
17
|
+
3. The WebSocket connects to your `McpAgent` Durable Object which manages connection state
|
|
18
|
+
4. JSON-RPC messages flow bidirectionally over the WebSocket
|
|
19
|
+
5. Your Worker streams responses back to the client using Server-Sent Events (SSE)
|
|
20
|
+
|
|
21
|
+
This is all handled automatically by the `McpAgent.serve()` method:
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import { McpAgent } from "agents/mcp";
|
|
25
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
26
|
+
|
|
27
|
+
export class MyMCP extends McpAgent {
|
|
28
|
+
server = new McpServer({ name: "Demo", version: "1.0.0" });
|
|
29
|
+
|
|
30
|
+
async init() {
|
|
31
|
+
// Define your tools, resources, prompts
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Serve with Streamable HTTP transport
|
|
36
|
+
export default MyMCP.serve("/mcp");
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The `serve()` method returns a Worker with a `fetch` handler that:
|
|
40
|
+
|
|
41
|
+
- Handles CORS preflight requests
|
|
42
|
+
- Manages WebSocket upgrades
|
|
43
|
+
- Routes messages to your Durable Object
|
|
44
|
+
|
|
45
|
+
### Connection from clients
|
|
46
|
+
|
|
47
|
+
Clients connect using the `streamable-http` transport:
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
await agent.addMcpServer("my-server", "https://your-worker.workers.dev/mcp");
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Auto Transport
|
|
54
|
+
|
|
55
|
+
The **auto** transport serves both Streamable HTTP and legacy SSE on the same endpoint. Capable clients use Streamable HTTP automatically, while older SSE-only clients continue to work.
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
export default MyMCP.serve("/mcp", { transport: "auto" });
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The handler distinguishes between the two protocols based on the request shape — no configuration or content negotiation is required from clients. This is useful when migrating from SSE to Streamable HTTP without breaking existing clients.
|
|
62
|
+
|
|
63
|
+
## SSE Transport (Deprecated)
|
|
64
|
+
|
|
65
|
+
We also support the legacy **SSE (Server-Sent Events)** transport, but it is deprecated in favor of Streamable HTTP.
|
|
66
|
+
|
|
67
|
+
If you need SSE transport for compatibility:
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
// Server
|
|
71
|
+
export default MyMCP.serveSSE("/sse");
|
|
72
|
+
|
|
73
|
+
// Client
|
|
74
|
+
await agent.addMcpServer("my-server", url);
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## RPC Transport (Experimental)
|
|
78
|
+
|
|
79
|
+
The **RPC transport** is a custom transport designed for internal applications where your MCP server and agent are both running on Cloudflare. They can even run in the same Worker! It sends JSON-RPC messages directly over Cloudflare's RPC bindings without going over the public internet.
|
|
80
|
+
|
|
81
|
+
### Why use RPC transport?
|
|
82
|
+
|
|
83
|
+
- **Faster**: No network overhead - direct function calls
|
|
84
|
+
- **Simpler**: No HTTP endpoints, no connection management
|
|
85
|
+
- **Internal only**: Perfect for agents calling MCP servers within the same Worker
|
|
86
|
+
|
|
87
|
+
**Note**: RPC transport does not support authentication. Use HTTP/SSE for external connections that require OAuth.
|
|
88
|
+
|
|
89
|
+
### Connecting an Agent to an McpAgent via RPC
|
|
90
|
+
|
|
91
|
+
The RPC transport uses Durable Object bindings to connect your `Agent` (MCP client) directly to your `McpAgent` (MCP server).
|
|
92
|
+
|
|
93
|
+
#### Step 1: Define your MCP server
|
|
94
|
+
|
|
95
|
+
Create your `McpAgent` with the tools you want to expose:
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
import { McpAgent } from "agents/mcp";
|
|
99
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
100
|
+
import { z } from "zod";
|
|
101
|
+
|
|
102
|
+
type State = { counter: number };
|
|
103
|
+
|
|
104
|
+
export class MyMCP extends McpAgent<Env, State> {
|
|
105
|
+
server = new McpServer({ name: "MyMCP", version: "1.0.0" });
|
|
106
|
+
initialState: State = { counter: 0 };
|
|
107
|
+
|
|
108
|
+
async init() {
|
|
109
|
+
this.server.tool(
|
|
110
|
+
"add",
|
|
111
|
+
"Add to the counter",
|
|
112
|
+
{ amount: z.number() },
|
|
113
|
+
async ({ amount }) => {
|
|
114
|
+
this.setState({ counter: this.state.counter + amount });
|
|
115
|
+
return {
|
|
116
|
+
content: [
|
|
117
|
+
{
|
|
118
|
+
type: "text",
|
|
119
|
+
text: `Added ${amount}, total is now ${this.state.counter}`
|
|
120
|
+
}
|
|
121
|
+
]
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
#### Step 2: Connect your Agent to the MCP server
|
|
130
|
+
|
|
131
|
+
In your `Agent`, call `addMcpServer()` with the Durable Object binding in `onStart()`:
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
import { AIChatAgent } from "agents/ai-chat-agent";
|
|
135
|
+
|
|
136
|
+
export class Chat extends AIChatAgent<Env> {
|
|
137
|
+
async onStart(): Promise<void> {
|
|
138
|
+
// Pass the DO namespace binding directly
|
|
139
|
+
await this.addMcpServer("my-mcp", this.env.MyMCP);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async onChatMessage(onFinish) {
|
|
143
|
+
const allTools = this.mcp.getAITools();
|
|
144
|
+
|
|
145
|
+
const result = streamText({
|
|
146
|
+
model,
|
|
147
|
+
tools: allTools
|
|
148
|
+
// ...
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
return createUIMessageStreamResponse({ stream: result });
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
RPC connections are automatically restored after Durable Object hibernation, just like HTTP connections. The binding name and props are persisted to storage so the connection can be re-established without any extra code.
|
|
157
|
+
|
|
158
|
+
**Deduplication:** For RPC transport, if `addMcpServer` is called with a name that already has an active connection, the existing connection is returned instead of creating a duplicate. For HTTP transport, deduplication matches on both server name and URL (see [MCP Client API](./mcp-client.md) for details). This makes it safe to call `addMcpServer` in `onStart()` without worrying about creating multiple connections on restart.
|
|
159
|
+
|
|
160
|
+
#### Step 3: Configure Durable Object bindings
|
|
161
|
+
|
|
162
|
+
In your `wrangler.jsonc`, define bindings for both Durable Objects:
|
|
163
|
+
|
|
164
|
+
```jsonc
|
|
165
|
+
{
|
|
166
|
+
"durable_objects": {
|
|
167
|
+
"bindings": [
|
|
168
|
+
{ "name": "Chat", "class_name": "Chat" },
|
|
169
|
+
{ "name": "MyMCP", "class_name": "MyMCP" }
|
|
170
|
+
]
|
|
171
|
+
},
|
|
172
|
+
"migrations": [
|
|
173
|
+
{
|
|
174
|
+
"new_sqlite_classes": ["MyMCP", "Chat"],
|
|
175
|
+
"tag": "v1"
|
|
176
|
+
}
|
|
177
|
+
]
|
|
178
|
+
}
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
#### Step 4: Set up your Worker fetch handler
|
|
182
|
+
|
|
183
|
+
Route requests to your Chat agent:
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
import { routeAgentRequest } from "agents";
|
|
187
|
+
|
|
188
|
+
export default {
|
|
189
|
+
async fetch(request: Request, env: Env, ctx: ExecutionContext) {
|
|
190
|
+
const url = new URL(request.url);
|
|
191
|
+
|
|
192
|
+
// Optionally expose the MCP server via HTTP as well
|
|
193
|
+
if (url.pathname.startsWith("/mcp")) {
|
|
194
|
+
return MyMCP.serve("/mcp").fetch(request, env, ctx);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const response = await routeAgentRequest(request, env);
|
|
198
|
+
if (response) return response;
|
|
199
|
+
|
|
200
|
+
return new Response("Not found", { status: 404 });
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Passing props from client to server
|
|
206
|
+
|
|
207
|
+
Since RPC transport does not have an OAuth flow, you can pass user context (like userId, role, etc.) directly as props:
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
await this.addMcpServer("my-mcp", this.env.MyMCP, {
|
|
211
|
+
props: { userId: "user-123", role: "admin" }
|
|
212
|
+
});
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Your `McpAgent` can then access these props:
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
export class MyMCP extends McpAgent<
|
|
219
|
+
Env,
|
|
220
|
+
State,
|
|
221
|
+
{ userId?: string; role?: string }
|
|
222
|
+
> {
|
|
223
|
+
async init() {
|
|
224
|
+
this.server.tool("whoami", "Get current user info", {}, async () => {
|
|
225
|
+
const userId = this.props?.userId || "anonymous";
|
|
226
|
+
const role = this.props?.role || "guest";
|
|
227
|
+
|
|
228
|
+
return {
|
|
229
|
+
content: [{ type: "text", text: `User ID: ${userId}, Role: ${role}` }]
|
|
230
|
+
};
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
The props are:
|
|
237
|
+
|
|
238
|
+
- **Type-safe**: TypeScript extracts the Props type from your McpAgent generic
|
|
239
|
+
- **Persistent**: Stored in Durable Object storage via `updateProps()`
|
|
240
|
+
- **Available immediately**: Set before any tool calls are made
|
|
241
|
+
|
|
242
|
+
This is useful for:
|
|
243
|
+
|
|
244
|
+
- User authentication context
|
|
245
|
+
- Tenant/organization IDs
|
|
246
|
+
- Feature flags or permissions
|
|
247
|
+
- Any per-connection configuration
|
|
248
|
+
|
|
249
|
+
### How RPC transport works under the hood
|
|
250
|
+
|
|
251
|
+
When you call `addMcpServer()` with a Durable Object binding, the SDK:
|
|
252
|
+
|
|
253
|
+
1. Creates an `RPCClientTransport` that wraps the DO stub
|
|
254
|
+
2. Calls `handleMcpMessage()` on the `McpAgent` for each JSON-RPC message
|
|
255
|
+
3. The `McpAgent` routes messages through its `RPCServerTransport` to the MCP server
|
|
256
|
+
4. Responses flow back synchronously through the RPC call
|
|
257
|
+
|
|
258
|
+
This happens entirely within your Worker's execution context using Cloudflare's RPC mechanism - no HTTP, no WebSockets, no public internet.
|
|
259
|
+
|
|
260
|
+
The RPC transport fully supports:
|
|
261
|
+
|
|
262
|
+
- JSON-RPC 2.0 validation (via the MCP SDK's schema)
|
|
263
|
+
- Batch requests
|
|
264
|
+
- Notifications (messages without `id` field)
|
|
265
|
+
- Automatic reconnection after Durable Object hibernation (when called from `onStart()`)
|
|
266
|
+
|
|
267
|
+
### Configuring RPC Transport Server Timeout
|
|
268
|
+
|
|
269
|
+
The RPC transport has a configurable timeout for waiting for tool responses. By default, the server will wait **60 seconds** for a tool handler to respond. You can customize this by overriding `getRpcTransportOptions()` in your `McpAgent`:
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
export class MyMCP extends McpAgent<Env, State> {
|
|
273
|
+
server = new McpServer({ name: "MyMCP", version: "1.0.0" });
|
|
274
|
+
|
|
275
|
+
protected getRpcTransportOptions() {
|
|
276
|
+
return { timeout: 120000 }; // 2 minutes
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
async init() {
|
|
280
|
+
this.server.tool(
|
|
281
|
+
"long-running-task",
|
|
282
|
+
"A tool that takes a while",
|
|
283
|
+
{ input: z.string() },
|
|
284
|
+
async ({ input }) => {
|
|
285
|
+
await longRunningOperation(input);
|
|
286
|
+
return {
|
|
287
|
+
content: [{ type: "text", text: "Task completed" }]
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
## Choosing a transport
|
|
296
|
+
|
|
297
|
+
| Transport | Use when | Pros | Cons |
|
|
298
|
+
| ------------------- | ---------------------------------------- | ---------------------------------------- | ------------------------------- |
|
|
299
|
+
| **Streamable HTTP** | External MCP servers, production apps | Standard protocol, secure, supports auth | Slight network overhead |
|
|
300
|
+
| **Auto** | Migrating from SSE, mixed client support | Serves both protocols on one endpoint | Reserves `{path}/message` route |
|
|
301
|
+
| **RPC** | Internal agents | Fastest, simplest setup | No auth, Service Bindings only |
|
|
302
|
+
| **SSE** | Legacy compatibility | Backwards compatible | Deprecated, use Streamable HTTP |
|
|
303
|
+
|
|
304
|
+
## Examples
|
|
305
|
+
|
|
306
|
+
- **Streamable HTTP**: See [`examples/mcp`](https://github.com/cloudflare/agents/tree/main/examples/mcp)
|
|
307
|
+
- **RPC Transport**: See [`examples/mcp-rpc-transport`](https://github.com/cloudflare/agents/tree/main/examples/mcp-rpc-transport)
|
|
308
|
+
- **MCP Client**: See [`examples/mcp-client`](https://github.com/cloudflare/agents/tree/main/examples/mcp-client)
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Migrating from AI SDK v4 to v5
|
|
2
|
+
|
|
3
|
+
This guide covers the changes needed when upgrading from AI SDK v4 to v5 with `@cloudflare/ai-chat`.
|
|
4
|
+
|
|
5
|
+
> If you are on AI SDK v5 and upgrading to v6, see the [v6 migration guide](./migration-to-ai-sdk-v6.md) instead.
|
|
6
|
+
|
|
7
|
+
## Message format: `content` to `parts`
|
|
8
|
+
|
|
9
|
+
The biggest change. Messages now use a `parts` array instead of a `content` string:
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
// v4
|
|
13
|
+
const message = { id: "1", role: "user", content: "Hello" };
|
|
14
|
+
|
|
15
|
+
// v5
|
|
16
|
+
const message = {
|
|
17
|
+
id: "1",
|
|
18
|
+
role: "user",
|
|
19
|
+
parts: [{ type: "text", text: "Hello" }]
|
|
20
|
+
};
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**You do not need to migrate stored messages manually.** `AIChatAgent` automatically transforms legacy messages on load via `autoTransformMessages()`. This handles v4 `content` strings, tool invocations, reasoning parts, file data, and malformed formats.
|
|
24
|
+
|
|
25
|
+
## Import changes
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
// v4
|
|
29
|
+
import type { Message } from "ai";
|
|
30
|
+
import { useChat } from "ai/react";
|
|
31
|
+
|
|
32
|
+
// v5
|
|
33
|
+
import type { UIMessage } from "ai";
|
|
34
|
+
import { useChat } from "@ai-sdk/react";
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Tool definitions: `parameters` to `inputSchema`
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
// v4
|
|
41
|
+
const tools = {
|
|
42
|
+
weather: {
|
|
43
|
+
description: "Get weather",
|
|
44
|
+
parameters: z.object({ city: z.string() }),
|
|
45
|
+
execute: async ({ city }) => fetchWeather(city)
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// v5
|
|
50
|
+
const tools = {
|
|
51
|
+
weather: {
|
|
52
|
+
description: "Get weather",
|
|
53
|
+
inputSchema: z.object({ city: z.string() }),
|
|
54
|
+
execute: async ({ city }) => fetchWeather(city)
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Streaming events
|
|
60
|
+
|
|
61
|
+
v5 adds `text-start` and `text-end` events around text deltas, and renames `textDelta` to `delta`:
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
// v4
|
|
65
|
+
chunk.type === "text-delta" && chunk.textDelta;
|
|
66
|
+
|
|
67
|
+
// v5
|
|
68
|
+
chunk.type === "text-delta" && chunk.delta;
|
|
69
|
+
// Plus new: "text-start" and "text-end" events
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Migration checklist
|
|
73
|
+
|
|
74
|
+
1. Update dependencies: `npm update agents ai`
|
|
75
|
+
2. Replace `import type { Message }` with `import type { UIMessage }`
|
|
76
|
+
3. Replace `"ai/react"` imports with `"@ai-sdk/react"`
|
|
77
|
+
4. Rename `parameters` to `inputSchema` in tool definitions
|
|
78
|
+
5. Run `npm run typecheck` and fix any remaining type errors
|
|
79
|
+
6. Test your application -- legacy stored messages are migrated automatically
|
|
80
|
+
|
|
81
|
+
## Migration utilities (deprecated)
|
|
82
|
+
|
|
83
|
+
These are available but rarely needed since migration is automatic:
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
import {
|
|
87
|
+
autoTransformMessages, // Used internally by AIChatAgent
|
|
88
|
+
migrateMessagesToUIFormat, // Deprecated -- use autoTransformMessages
|
|
89
|
+
analyzeCorruption // Deprecated -- debugging only
|
|
90
|
+
} from "@cloudflare/ai-chat/ai-chat-v5-migration";
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Further reading
|
|
94
|
+
|
|
95
|
+
- [Official AI SDK v5 migration guide](https://ai-sdk.dev/docs/migration-guides/migration-guide-5-0)
|
|
96
|
+
- [v6 migration guide](./migration-to-ai-sdk-v6.md) (if upgrading further)
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
# Migrating from AI SDK v5 to v6
|
|
2
|
+
|
|
3
|
+
This guide covers the changes needed when upgrading from AI SDK v5 to v6 with `@cloudflare/ai-chat`.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install ai@latest @ai-sdk/react@latest @ai-sdk/openai@latest
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Breaking changes
|
|
12
|
+
|
|
13
|
+
### 1. `convertToModelMessages()` is now async
|
|
14
|
+
|
|
15
|
+
Add `await` to all calls:
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
// v5
|
|
19
|
+
const result = streamText({
|
|
20
|
+
messages: convertToModelMessages(this.messages),
|
|
21
|
+
model: openai("gpt-4o")
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// v6
|
|
25
|
+
const result = streamText({
|
|
26
|
+
messages: await convertToModelMessages(this.messages),
|
|
27
|
+
model: openai("gpt-4o")
|
|
28
|
+
});
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### 2. `CoreMessage` removed
|
|
32
|
+
|
|
33
|
+
Replace `CoreMessage` with `ModelMessage` and `convertToCoreMessages()` with `convertToModelMessages()`:
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
// v5
|
|
37
|
+
import { convertToCoreMessages, type CoreMessage } from "ai";
|
|
38
|
+
|
|
39
|
+
// v6
|
|
40
|
+
import { convertToModelMessages, type ModelMessage } from "ai";
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### 3. Tool pattern: server-side tools (recommended)
|
|
44
|
+
|
|
45
|
+
v6 introduces `needsApproval` and the `onToolCall` callback. For most apps, define tools on the server with `tool()` from `"ai"` for full Zod type safety:
|
|
46
|
+
|
|
47
|
+
**Before (v5):**
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
// Client defined tools with AITool type
|
|
51
|
+
useAgentChat({
|
|
52
|
+
agent,
|
|
53
|
+
tools: clientTools,
|
|
54
|
+
experimental_automaticToolResolution: true,
|
|
55
|
+
toolsRequiringConfirmation: ["askConfirmation"]
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**After (v6):**
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
// Server: all tools defined here
|
|
63
|
+
const tools = {
|
|
64
|
+
getWeather: tool({
|
|
65
|
+
description: "Get weather",
|
|
66
|
+
inputSchema: z.object({ city: z.string() }),
|
|
67
|
+
execute: async ({ city }) => fetchWeather(city)
|
|
68
|
+
}),
|
|
69
|
+
getLocation: tool({
|
|
70
|
+
description: "Get user location",
|
|
71
|
+
inputSchema: z.object({})
|
|
72
|
+
// No execute -- client handles via onToolCall
|
|
73
|
+
}),
|
|
74
|
+
processPayment: tool({
|
|
75
|
+
description: "Process payment",
|
|
76
|
+
inputSchema: z.object({ amount: z.number() }),
|
|
77
|
+
needsApproval: async ({ amount }) => amount > 100,
|
|
78
|
+
execute: async ({ amount }) => charge(amount)
|
|
79
|
+
})
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
// Client: handle tools via callbacks
|
|
83
|
+
useAgentChat({
|
|
84
|
+
agent,
|
|
85
|
+
onToolCall: async ({ toolCall, addToolOutput }) => {
|
|
86
|
+
if (toolCall.toolName === "getLocation") {
|
|
87
|
+
const pos = await getPosition();
|
|
88
|
+
addToolOutput({
|
|
89
|
+
toolCallId: toolCall.toolCallId,
|
|
90
|
+
output: { lat: pos.coords.latitude, lng: pos.coords.longitude }
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**Dynamic client tools (SDK/platform pattern):**
|
|
98
|
+
|
|
99
|
+
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:
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
// Server: accept whatever tools the client sends
|
|
103
|
+
const tools = {
|
|
104
|
+
...createToolsFromClientSchemas(options.clientTools),
|
|
105
|
+
...serverTools
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
// Client: register tools dynamically
|
|
109
|
+
useAgentChat({
|
|
110
|
+
agent,
|
|
111
|
+
tools: dynamicTools,
|
|
112
|
+
onToolCall: async ({ toolCall, addToolOutput }) => {
|
|
113
|
+
const tool = dynamicTools[toolCall.toolName];
|
|
114
|
+
if (tool?.execute) {
|
|
115
|
+
const output = await tool.execute(toolCall.input);
|
|
116
|
+
addToolOutput({ toolCallId: toolCall.toolCallId, output });
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### 4. `generateObject` mode option removed
|
|
123
|
+
|
|
124
|
+
Remove `mode: "json"` or similar from `generateObject` calls.
|
|
125
|
+
|
|
126
|
+
### 5. `isToolUIPart` and `getToolName` now include dynamic tools
|
|
127
|
+
|
|
128
|
+
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.
|
|
129
|
+
|
|
130
|
+
## Deprecated APIs
|
|
131
|
+
|
|
132
|
+
| Deprecated | Replacement |
|
|
133
|
+
| -------------------------------------- | --------------------------------------------------------- |
|
|
134
|
+
| `toolsRequiringConfirmation` | [`needsApproval`](./human-in-the-loop.md) on server tools |
|
|
135
|
+
| `experimental_automaticToolResolution` | [`onToolCall`](./client-tools-continuation.md) callback |
|
|
136
|
+
| `addToolResult()` | `addToolOutput()` or `addToolApprovalResponse()` |
|
|
137
|
+
|
|
138
|
+
**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.
|
|
139
|
+
|
|
140
|
+
## Migration checklist
|
|
141
|
+
|
|
142
|
+
**Packages:**
|
|
143
|
+
|
|
144
|
+
- `ai` to `^6.0.0`
|
|
145
|
+
- `@ai-sdk/react` to `^3.0.0`
|
|
146
|
+
- `@ai-sdk/openai` (and other providers) to `^3.0.0`
|
|
147
|
+
|
|
148
|
+
**Code changes:**
|
|
149
|
+
|
|
150
|
+
- Add `await` to all `convertToModelMessages()` calls
|
|
151
|
+
- Replace `CoreMessage` with `ModelMessage`
|
|
152
|
+
- Replace `convertToCoreMessages()` with `convertToModelMessages()`
|
|
153
|
+
- Remove `mode` from `generateObject` calls
|
|
154
|
+
- Move static tool definitions to server using `tool()` (recommended for most apps)
|
|
155
|
+
- Use `onToolCall` in `useAgentChat` for client-side tool execution
|
|
156
|
+
- Replace `toolsRequiringConfirmation` with `needsApproval`
|
|
157
|
+
- Replace `addToolResult()` with `addToolOutput()` or `addToolApprovalResponse()`
|
|
158
|
+
|
|
159
|
+
## Further reading
|
|
160
|
+
|
|
161
|
+
- [Official AI SDK v6 migration guide](https://ai-sdk.dev/docs/migration-guides/migration-guide-6-0)
|
|
162
|
+
- [Human in the Loop](./human-in-the-loop.md) -- `needsApproval` and `addToolApprovalResponse`
|
|
163
|
+
- [Client Tools](./client-tools-continuation.md) -- `onToolCall` and auto-continuation
|