agents 0.0.0-804e02e → 0.0.0-80a8fbd0
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 +373 -481
- package/agents.tsconfig.json +18 -0
- package/dist/agent-tool-types-DEBXD2Ta.d.ts +6169 -0
- package/dist/agent-tool-types.d.ts +54 -0
- package/dist/agent-tool-types.js +20 -0
- package/dist/agent-tool-types.js.map +1 -0
- package/dist/agent-tools-krZpfAix.d.ts +133 -0
- package/dist/agent-tools-y7zLfw4Q.js +304 -0
- package/dist/agent-tools-y7zLfw4Q.js.map +1 -0
- package/dist/agent-tools.d.ts +70 -0
- package/dist/agent-tools.js +60 -0
- package/dist/agent-tools.js.map +1 -0
- package/dist/ai-chat-agent.d.ts +1 -85
- package/dist/ai-chat-agent.js +4 -358
- package/dist/ai-chat-agent.js.map +1 -1
- package/dist/ai-chat-v5-migration.d.ts +1 -152
- package/dist/ai-chat-v5-migration.js +5 -19
- package/dist/ai-chat-v5-migration.js.map +1 -1
- package/dist/ai-react.d.ts +1 -98
- package/dist/ai-react.js +4 -354
- package/dist/ai-react.js.map +1 -1
- package/dist/ai-types.d.ts +1 -92
- package/dist/ai-types.js +5 -7
- package/dist/ai-types.js.map +1 -1
- package/dist/browser/ai.d.ts +235 -0
- package/dist/browser/ai.js +265 -0
- package/dist/browser/ai.js.map +1 -0
- package/dist/browser/index.d.ts +146 -0
- package/dist/browser/index.js +3 -0
- package/dist/browser/tanstack-ai.d.ts +41 -0
- package/dist/browser/tanstack-ai.js +57 -0
- package/dist/browser/tanstack-ai.js.map +1 -0
- package/dist/chat/index.d.ts +3392 -0
- package/dist/chat/index.js +3408 -0
- package/dist/chat/index.js.map +1 -0
- package/dist/chat/react.d.ts +602 -0
- package/dist/chat/react.js +1517 -0
- package/dist/chat/react.js.map +1 -0
- package/dist/chat-sdk/index.d.ts +135 -0
- package/dist/chat-sdk/index.js +453 -0
- package/dist/chat-sdk/index.js.map +1 -0
- package/dist/classPrivateFieldGet2-DZBYAB34.js +27 -0
- package/dist/classPrivateMethodInitSpec-qMjJ6sHQ.js +7 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +26 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/client-D8tz8bn3.js +2233 -0
- package/dist/client-D8tz8bn3.js.map +1 -0
- package/dist/client-invoker-BNSZxAkv.d.ts +20 -0
- package/dist/client-invoker-oF0lZZtP.js +57 -0
- package/dist/client-invoker-oF0lZZtP.js.map +1 -0
- package/dist/client-tools-aIBO0Fk7.d.ts +53 -0
- package/dist/client.d.ts +248 -44
- package/dist/client.js +272 -11
- package/dist/client.js.map +1 -1
- package/dist/codemode/ai.d.ts +1 -0
- package/dist/codemode/ai.js +6 -0
- package/dist/codemode/ai.js.map +1 -0
- package/dist/compaction-helpers-iiKMr2TQ.js +340 -0
- package/dist/compaction-helpers-iiKMr2TQ.js.map +1 -0
- package/dist/compaction-helpers-wUz6M3us.d.ts +621 -0
- package/dist/connector-CdldGF3h.js +1291 -0
- package/dist/connector-CdldGF3h.js.map +1 -0
- package/dist/connector-v2M1zlZp.d.ts +659 -0
- package/dist/do-oauth-client-provider-VTZj2VtM.d.ts +110 -0
- package/dist/email-CL27preh.d.ts +157 -0
- package/dist/email.d.ts +30 -0
- package/dist/email.js +222 -0
- package/dist/email.js.map +1 -0
- package/dist/experimental/memory/session/index.d.ts +670 -0
- package/dist/experimental/memory/session/index.js +2374 -0
- package/dist/experimental/memory/session/index.js.map +1 -0
- package/dist/experimental/memory/utils/index.d.ts +96 -0
- package/dist/experimental/memory/utils/index.js +79 -0
- package/dist/experimental/memory/utils/index.js.map +1 -0
- package/dist/experimental/webmcp.d.ts +218 -0
- package/dist/experimental/webmcp.js +298 -0
- package/dist/experimental/webmcp.js.map +1 -0
- package/dist/index-BRnybD6X.d.ts +947 -0
- package/dist/index.d.ts +180 -558
- package/dist/index.js +7151 -30
- package/dist/index.js.map +1 -1
- package/dist/internal_context-Dg4Cgjcu.d.ts +37 -0
- package/dist/internal_context.d.ts +6 -0
- package/dist/internal_context.js +11 -0
- package/dist/internal_context.js.map +1 -0
- package/dist/mcp/client.d.ts +38 -11
- package/dist/mcp/client.js +2 -10
- package/dist/mcp/do-oauth-client-provider.d.ts +10 -50
- package/dist/mcp/do-oauth-client-provider.js +290 -6
- package/dist/mcp/do-oauth-client-provider.js.map +1 -1
- package/dist/mcp/index.d.ts +82 -78
- package/dist/mcp/index.js +2045 -1085
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/x402.d.ts +110 -22
- package/dist/mcp/x402.js +254 -3189
- package/dist/mcp/x402.js.map +1 -1
- package/dist/message-builder-BymO4N_D.js +386 -0
- package/dist/message-builder-BymO4N_D.js.map +1 -0
- package/dist/observability/index.d.ts +15 -45
- package/dist/observability/index.js +86 -10
- package/dist/observability/index.js.map +1 -1
- package/dist/react.d.ts +202 -75
- package/dist/react.js +478 -114
- package/dist/react.js.map +1 -1
- package/dist/retries-CAvxtG9d.d.ts +127 -0
- package/dist/retries.d.ts +22 -0
- package/dist/retries.js +229 -0
- package/dist/retries.js.map +1 -0
- package/dist/schedule.d.ts +91 -85
- package/dist/schedule.js +68 -33
- package/dist/schedule.js.map +1 -1
- package/dist/serializable.d.ts +115 -6
- package/dist/serializable.js +1 -1
- package/dist/skills/compile.d.ts +40 -0
- package/dist/skills/compile.js +65 -0
- package/dist/skills/compile.js.map +1 -0
- package/dist/skills/index.d.ts +244 -0
- package/dist/skills/index.js +1323 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/sub-routing.d.ts +14 -0
- package/dist/sub-routing.js +177 -0
- package/dist/sub-routing.js.map +1 -0
- package/dist/tool-output-truncation-CNnnGZQ3.js +98 -0
- package/dist/tool-output-truncation-CNnnGZQ3.js.map +1 -0
- package/dist/types-6Zo2zfoO.d.ts +17 -0
- package/dist/types.d.ts +2 -0
- package/dist/types.js +19 -0
- package/dist/types.js.map +1 -0
- package/dist/utils-CGtGDSgA.d.ts +34 -0
- package/dist/utils.d.ts +6 -0
- package/dist/utils.js +51 -0
- package/dist/utils.js.map +1 -0
- package/dist/vite.d.ts +25 -0
- package/dist/vite.js +310 -0
- package/dist/vite.js.map +1 -0
- package/dist/wire-types-nflOzNuU.js +240 -0
- package/dist/wire-types-nflOzNuU.js.map +1 -0
- package/dist/workflow-types-Baz_PO5v.d.ts +280 -0
- package/dist/workflow-types.d.ts +52 -0
- package/dist/workflow-types.js +16 -0
- package/dist/workflow-types.js.map +1 -0
- package/dist/workflows.d.ts +198 -0
- package/dist/workflows.js +343 -0
- package/dist/workflows.js.map +1 -0
- 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 +1696 -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 +795 -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 +683 -0
- package/docs/mcp-servers.md +548 -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 +362 -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 +238 -56
- package/skills-module.d.ts +22 -0
- package/dist/_esm-LV5FJ3HK.js +0 -3922
- package/dist/_esm-LV5FJ3HK.js.map +0 -1
- package/dist/ccip-CMBYN64O.js +0 -15
- package/dist/ccip-CMBYN64O.js.map +0 -1
- package/dist/chunk-5Y6BEZDY.js +0 -276
- package/dist/chunk-5Y6BEZDY.js.map +0 -1
- package/dist/chunk-BER7KXUJ.js +0 -18
- package/dist/chunk-BER7KXUJ.js.map +0 -1
- package/dist/chunk-JJBFIGUC.js +0 -5202
- package/dist/chunk-JJBFIGUC.js.map +0 -1
- package/dist/chunk-PR4QN5HX.js +0 -43
- package/dist/chunk-PR4QN5HX.js.map +0 -1
- package/dist/chunk-QEPGNUG6.js +0 -650
- package/dist/chunk-QEPGNUG6.js.map +0 -1
- package/dist/chunk-QEVM4BVL.js +0 -116
- package/dist/chunk-QEVM4BVL.js.map +0 -1
- package/dist/chunk-RS5OCNEQ.js +0 -1323
- package/dist/chunk-RS5OCNEQ.js.map +0 -1
- package/dist/chunk-TYAY6AU6.js +0 -159
- package/dist/chunk-TYAY6AU6.js.map +0 -1
- package/dist/chunk-UJVEAURM.js +0 -150
- package/dist/chunk-UJVEAURM.js.map +0 -1
- package/dist/chunk-XFS5ERG3.js +0 -127
- package/dist/chunk-XFS5ERG3.js.map +0 -1
- package/dist/client-BohGLma8.d.ts +0 -5041
- package/dist/mcp/client.js.map +0 -1
- package/dist/secp256k1-M22GZP2U.js +0 -2193
- package/dist/secp256k1-M22GZP2U.js.map +0 -1
- package/dist/serializable.js.map +0 -1
- package/src/index.ts +0 -1987
package/README.md
CHANGED
|
@@ -1,656 +1,548 @@
|
|
|
1
|
-
|
|
1
|
+
# agents
|
|
2
2
|
|
|
3
3
|

|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**Build software that thinks and does.**
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Persistent AI agents on Cloudflare's global network. They remember context, reason through problems, schedule their own work, and take action—all without you managing servers.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
```sh
|
|
10
|
+
npm create cloudflare@latest -- --template cloudflare/agents-starter
|
|
11
|
+
```
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
Or add to an existing project:
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
- **Growth**: Learns and adapts through its interactions
|
|
15
|
+
```sh
|
|
16
|
+
npm install agents
|
|
17
|
+
```
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Why Agents, Why Now
|
|
22
|
+
|
|
23
|
+
LLMs can reason, plan, and use tools—but they need infrastructure that matches their capabilities. Traditional serverless is stateless and ephemeral. Agents are persistent and purposeful.
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
From request handlers → to autonomous entities
|
|
27
|
+
From stateless functions → to persistent intelligence
|
|
28
|
+
|
|
29
|
+
Traditional serverless: Request → Response → Gone
|
|
30
|
+
Agents: Thinking, remembering, acting — continuously
|
|
31
|
+
```
|
|
19
32
|
|
|
20
|
-
|
|
33
|
+
**Pay only when active.** Agents hibernate between requests. You can have millions of agents—one per user, per session, per game room—each costs nothing when idle.
|
|
21
34
|
|
|
22
|
-
|
|
23
|
-
2. **Long-lived Presence**: Agents can run for extended periods, resting when idle
|
|
24
|
-
3. **Natural Communication**: Interact through HTTP, WebSockets, or direct calls
|
|
25
|
-
4. **Global Distribution**: Leverage Cloudflare's network for worldwide presence
|
|
26
|
-
5. **Resource Harmony**: Efficient hibernation and awakening as needed
|
|
35
|
+
Built on Cloudflare Durable Objects, agents run globally, close to your users, with persistent state that survives restarts.
|
|
27
36
|
|
|
28
37
|
---
|
|
29
38
|
|
|
30
|
-
|
|
39
|
+
## Quick Example
|
|
31
40
|
|
|
32
|
-
|
|
41
|
+
A counter agent with real-time state sync and callable methods:
|
|
33
42
|
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
|
|
43
|
+
```typescript
|
|
44
|
+
// server.ts
|
|
45
|
+
import { Agent, callable } from "agents";
|
|
37
46
|
|
|
38
|
-
|
|
39
|
-
|
|
47
|
+
type State = { count: number };
|
|
48
|
+
|
|
49
|
+
export class CounterAgent extends Agent<Env, State> {
|
|
50
|
+
initialState: State = { count: 0 };
|
|
51
|
+
|
|
52
|
+
@callable()
|
|
53
|
+
increment() {
|
|
54
|
+
this.setState({ count: this.state.count + 1 });
|
|
55
|
+
return this.state.count;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@callable()
|
|
59
|
+
decrement() {
|
|
60
|
+
this.setState({ count: this.state.count - 1 });
|
|
61
|
+
return this.state.count;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
40
64
|
```
|
|
41
65
|
|
|
42
|
-
|
|
66
|
+
```tsx
|
|
67
|
+
// client.tsx
|
|
68
|
+
import { useAgent } from "agents/react";
|
|
69
|
+
import { useState } from "react";
|
|
43
70
|
|
|
44
|
-
|
|
71
|
+
function Counter() {
|
|
72
|
+
const [count, setCount] = useState(0);
|
|
45
73
|
|
|
46
|
-
|
|
47
|
-
|
|
74
|
+
const agent = useAgent<State>({
|
|
75
|
+
agent: "counter-agent",
|
|
76
|
+
name: "my-counter",
|
|
77
|
+
onStateUpdate: (state) => setCount(state.count)
|
|
78
|
+
});
|
|
48
79
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
80
|
+
return (
|
|
81
|
+
<div>
|
|
82
|
+
<span>{count}</span>
|
|
83
|
+
<button onClick={() => agent.stub.increment()}>+</button>
|
|
84
|
+
<button onClick={() => agent.stub.decrement()}>-</button>
|
|
85
|
+
</div>
|
|
86
|
+
);
|
|
54
87
|
}
|
|
55
88
|
```
|
|
56
89
|
|
|
57
|
-
|
|
90
|
+
State changes sync to all connected clients automatically. Call methods like they're local functions.
|
|
58
91
|
|
|
59
|
-
|
|
92
|
+
---
|
|
60
93
|
|
|
61
|
-
|
|
62
|
-
import { Agent } from "agents";
|
|
63
|
-
import { OpenAI } from "openai";
|
|
94
|
+
## What You Can Build
|
|
64
95
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
96
|
+
| Use Case | Why Agents |
|
|
97
|
+
| ---------------------- | ----------------------------------------------------- |
|
|
98
|
+
| Multiplayer game rooms | Per-room state, real-time sync, hibernates when empty |
|
|
99
|
+
| Customer support bots | Remembers conversation history, escalates to humans |
|
|
100
|
+
| Collaborative editors | Presence, cursors, document state |
|
|
101
|
+
| Approval workflows | Long-running, pauses for human input, durable |
|
|
102
|
+
| Personal AI assistants | Per-user memory, tool access via MCP |
|
|
103
|
+
| Notification systems | Scheduled delivery, user preferences, retry logic |
|
|
71
104
|
|
|
72
|
-
|
|
73
|
-
const response = await ai.chat.completions.create({
|
|
74
|
-
model: "gpt-4",
|
|
75
|
-
messages: [{ role: "user", content: await request.text() }]
|
|
76
|
-
});
|
|
105
|
+
---
|
|
77
106
|
|
|
78
|
-
|
|
107
|
+
## Features
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
Core State sync · Routing · HTTP & WebSockets · @callable RPC · Sub-agents (facets)
|
|
111
|
+
Clients React hook · Vanilla JS · Real-time state sync
|
|
112
|
+
Channels WebSocket · HTTP · Email · (coming: SMS, Voice, Messengers)
|
|
113
|
+
Background Queue · Scheduling · Managed fibers · Workflows · Human-in-the-loop
|
|
114
|
+
AI Chat agents · Agent tools · Tool calling · MCP servers & clients
|
|
115
|
+
Platform Observability · Cross-domain auth · Resumable streams
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### State Management
|
|
119
|
+
|
|
120
|
+
State persists across requests and syncs to all connected clients:
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
export class MyAgent extends Agent<Env, { items: string[] }> {
|
|
124
|
+
initialState = { items: [] };
|
|
125
|
+
|
|
126
|
+
@callable()
|
|
127
|
+
addItem(item: string) {
|
|
128
|
+
this.setState({ items: [...this.state.items, item] });
|
|
79
129
|
}
|
|
80
130
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
await this.act();
|
|
84
|
-
await this.reflect();
|
|
131
|
+
onStateChanged(state: State, source: Connection | "server") {
|
|
132
|
+
// Called after state is persisted and broadcast
|
|
85
133
|
}
|
|
86
134
|
}
|
|
87
135
|
```
|
|
88
136
|
|
|
89
|
-
###
|
|
137
|
+
### Callable Methods
|
|
90
138
|
|
|
91
|
-
|
|
139
|
+
Expose methods to clients with the `@callable()` decorator:
|
|
92
140
|
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
"class_name": "AIAgent"
|
|
100
|
-
}
|
|
101
|
-
]
|
|
102
|
-
},
|
|
103
|
-
"migrations": [
|
|
104
|
-
{
|
|
105
|
-
"tag": "v1",
|
|
106
|
-
// Mandatory for the Agent to store state
|
|
107
|
-
"new_sqlite_classes": ["AIAgent"]
|
|
108
|
-
}
|
|
109
|
-
]
|
|
141
|
+
```typescript
|
|
142
|
+
@callable()
|
|
143
|
+
async processOrder(orderId: string, items: Item[]) {
|
|
144
|
+
// Full type safety - clients call this like a local function
|
|
145
|
+
const result = await this.validateAndProcess(orderId, items);
|
|
146
|
+
return result;
|
|
110
147
|
}
|
|
111
148
|
```
|
|
112
149
|
|
|
113
|
-
|
|
150
|
+
```typescript
|
|
151
|
+
// Client
|
|
152
|
+
const result = await agent.stub.processOrder("order-123", items);
|
|
153
|
+
```
|
|
114
154
|
|
|
115
|
-
|
|
155
|
+
### Scheduling
|
|
116
156
|
|
|
117
|
-
|
|
118
|
-
// Create a new instance
|
|
119
|
-
const id = env.AIAgent.newUniqueId();
|
|
120
|
-
const agent = env.AIAgent.get(id);
|
|
157
|
+
Run tasks later, on intervals, or with cron expressions:
|
|
121
158
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
context: "incoming_data",
|
|
126
|
-
parameters: initialConfig
|
|
127
|
-
});
|
|
159
|
+
```typescript
|
|
160
|
+
// In 60 seconds
|
|
161
|
+
this.schedule(60, "sendReminder", { userId: "123" });
|
|
128
162
|
|
|
129
|
-
//
|
|
130
|
-
|
|
131
|
-
```
|
|
163
|
+
// Every hour
|
|
164
|
+
this.scheduleEvery(3600, "syncData");
|
|
132
165
|
|
|
133
|
-
|
|
166
|
+
// Daily at 9am UTC
|
|
167
|
+
this.schedule("0 9 * * *", "dailyReport");
|
|
134
168
|
|
|
135
|
-
|
|
169
|
+
// At a specific date
|
|
170
|
+
this.schedule(new Date("2025-12-31"), "yearEndTask");
|
|
171
|
+
```
|
|
136
172
|
|
|
137
|
-
|
|
173
|
+
### Background Tasks
|
|
138
174
|
|
|
139
|
-
|
|
140
|
-
export class APIAgent extends Agent {
|
|
141
|
-
async onRequest(request) {
|
|
142
|
-
const data = await request.json();
|
|
175
|
+
Queue immediate background work:
|
|
143
176
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
}
|
|
177
|
+
```typescript
|
|
178
|
+
await this.queue("processUpload", { fileId: "abc" });
|
|
179
|
+
// Returns immediately, task runs in background
|
|
150
180
|
```
|
|
151
181
|
|
|
152
|
-
|
|
182
|
+
### Sub-agents
|
|
153
183
|
|
|
154
|
-
|
|
184
|
+
Spawn child Durable Objects (facets) from a parent agent. Each child has
|
|
185
|
+
its own SQLite storage and runs in parallel, but is addressed under the
|
|
186
|
+
parent's URL:
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
export class Inbox extends Agent {
|
|
190
|
+
@callable()
|
|
191
|
+
async createChat() {
|
|
192
|
+
const id = crypto.randomUUID();
|
|
193
|
+
await this.subAgent(Chat, id);
|
|
194
|
+
return id;
|
|
195
|
+
}
|
|
155
196
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
197
|
+
override async onBeforeSubAgent(_req, { className, name }) {
|
|
198
|
+
if (!this.hasSubAgent(className, name)) {
|
|
199
|
+
return new Response("Not found", { status: 404 });
|
|
200
|
+
}
|
|
160
201
|
}
|
|
202
|
+
}
|
|
161
203
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
await this.
|
|
204
|
+
export class Chat extends Agent {
|
|
205
|
+
async writePreview(text: string) {
|
|
206
|
+
const inbox = await this.parentAgent(Inbox);
|
|
207
|
+
await inbox.savePreview(this.name, text);
|
|
165
208
|
}
|
|
166
209
|
}
|
|
167
210
|
```
|
|
168
211
|
|
|
169
|
-
|
|
212
|
+
Client-side, connect to a child with `useAgent({ sub: [...] })`:
|
|
170
213
|
|
|
171
|
-
|
|
214
|
+
```tsx
|
|
215
|
+
const inbox = useAgent({ agent: "Inbox", name: userId });
|
|
216
|
+
const chat = useAgent({
|
|
217
|
+
agent: "Inbox",
|
|
218
|
+
name: userId,
|
|
219
|
+
sub: [{ agent: "Chat", name: chatId }]
|
|
220
|
+
});
|
|
221
|
+
```
|
|
172
222
|
|
|
173
|
-
|
|
174
|
-
import { AgentClient } from "agents/client";
|
|
223
|
+
The routed URL becomes `/agents/inbox/{userId}/sub/chat/{chatId}`.
|
|
175
224
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
225
|
+
Child WebSocket clients can use the same URL shape. The parent remains the
|
|
226
|
+
public address, while child agents still receive `onConnect`, `onMessage`,
|
|
227
|
+
`onClose`, `broadcast()`, and `getConnections()` calls scoped to their own
|
|
228
|
+
clients. Parent broadcasts do not leak to child-targeted sockets, and child
|
|
229
|
+
connection tags, readonly state, and protocol-message settings are preserved
|
|
230
|
+
when a connection is resumed from hibernation.
|
|
180
231
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
});
|
|
232
|
+
Nested sub-agent URLs are supported using repeated `/sub/{agent}/{name}`
|
|
233
|
+
segments, subject to the platform's current facet nesting limits.
|
|
184
234
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
235
|
+
### Agent Tools
|
|
236
|
+
|
|
237
|
+
Run chat-capable sub-agents as tools from a parent chat agent. Think agents and
|
|
238
|
+
`AIChatAgent` subclasses are supported. The child keeps its own messages, tools,
|
|
239
|
+
SQLite storage, and resumable stream, while the parent broadcasts
|
|
240
|
+
`agent-tool-event` frames so the UI can render the child timeline inline.
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
import { Think } from "@cloudflare/think";
|
|
244
|
+
import { agentTool } from "agents/agent-tools";
|
|
245
|
+
import { z } from "zod";
|
|
246
|
+
|
|
247
|
+
export class Researcher extends Think<Env> {
|
|
248
|
+
getSystemPrompt() {
|
|
249
|
+
return "Research the requested topic and end with a concise summary.";
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export class Assistant extends Think<Env> {
|
|
254
|
+
getTools() {
|
|
255
|
+
return {
|
|
256
|
+
research: agentTool(Researcher, {
|
|
257
|
+
description: "Research one topic in depth.",
|
|
258
|
+
inputSchema: z.object({ query: z.string().min(3) })
|
|
259
|
+
})
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
}
|
|
191
263
|
```
|
|
192
264
|
|
|
193
|
-
|
|
265
|
+
For deterministic fan-out, call `this.runAgentTool(Researcher, { input })`
|
|
266
|
+
directly. Parent recovery reconciles stale child rows after restarts and marks
|
|
267
|
+
unrecoverable runs `interrupted` instead of hanging. In React, use
|
|
268
|
+
`useAgentToolEvents({ agent })` to render retained and replayed child timelines.
|
|
269
|
+
AIChatAgent children run headlessly, so browser client tools require a separate
|
|
270
|
+
bridge; server-side tools work normally. See the full
|
|
271
|
+
[Agent Tools guide](../../docs/agents/agent-tools.md).
|
|
194
272
|
|
|
195
|
-
|
|
273
|
+
### WebSocket Connections
|
|
196
274
|
|
|
197
|
-
|
|
198
|
-
import { useAgent } from "agents/react";
|
|
275
|
+
Handle real-time communication:
|
|
199
276
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
onMessage: (message) => {
|
|
205
|
-
console.log("Understanding received:", message.data);
|
|
206
|
-
},
|
|
207
|
-
onOpen: () => console.log("Connection established"),
|
|
208
|
-
onClose: () => console.log("Connection closed")
|
|
209
|
-
});
|
|
277
|
+
```typescript
|
|
278
|
+
async onConnect(connection: Connection) {
|
|
279
|
+
console.log(`Client ${connection.id} connected`);
|
|
280
|
+
}
|
|
210
281
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
content: "What insights have you gathered?"
|
|
216
|
-
})
|
|
217
|
-
);
|
|
218
|
-
};
|
|
282
|
+
async onMessage(connection: Connection, message: unknown) {
|
|
283
|
+
// Handle incoming messages
|
|
284
|
+
connection.send(JSON.stringify({ received: true }));
|
|
285
|
+
}
|
|
219
286
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
<button onClick={inquire}>Seek Understanding</button>
|
|
223
|
-
</div>
|
|
224
|
-
);
|
|
287
|
+
async onClose(connection: Connection) {
|
|
288
|
+
console.log(`Client ${connection.id} disconnected`);
|
|
225
289
|
}
|
|
226
290
|
```
|
|
227
291
|
|
|
228
|
-
###
|
|
229
|
-
|
|
230
|
-
Maintain and evolve your agent's understanding:
|
|
292
|
+
### Email
|
|
231
293
|
|
|
232
|
-
|
|
233
|
-
export class ThinkingAgent extends Agent {
|
|
234
|
-
async evolve(newInsight) {
|
|
235
|
-
this.setState({
|
|
236
|
-
...this.state,
|
|
237
|
-
insights: [...(this.state.insights || []), newInsight],
|
|
238
|
-
understanding: this.state.understanding + 1
|
|
239
|
-
});
|
|
240
|
-
}
|
|
294
|
+
Agents can receive and respond to emails:
|
|
241
295
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
}
|
|
296
|
+
```typescript
|
|
297
|
+
async onEmail(email: EmailMessage) {
|
|
298
|
+
const from = email.from;
|
|
299
|
+
const subject = email.headers.get("subject");
|
|
300
|
+
// Process incoming email
|
|
248
301
|
}
|
|
249
302
|
```
|
|
250
303
|
|
|
251
|
-
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
## Client SDK
|
|
307
|
+
|
|
308
|
+
### React
|
|
252
309
|
|
|
253
310
|
```tsx
|
|
254
|
-
import { useState } from "react";
|
|
255
311
|
import { useAgent } from "agents/react";
|
|
312
|
+
import { useState } from "react";
|
|
256
313
|
|
|
257
|
-
function
|
|
258
|
-
const [state, setState] = useState
|
|
314
|
+
function App() {
|
|
315
|
+
const [state, setState] = useState<MyState | null>(null);
|
|
259
316
|
|
|
260
|
-
const agent = useAgent({
|
|
261
|
-
agent: "
|
|
317
|
+
const agent = useAgent<MyState>({
|
|
318
|
+
agent: "my-agent",
|
|
319
|
+
name: "instance-name",
|
|
262
320
|
onStateUpdate: (newState) => setState(newState)
|
|
263
321
|
});
|
|
264
322
|
|
|
265
|
-
const increment = () => {
|
|
266
|
-
agent.setState({ counter: state.counter + 1 });
|
|
267
|
-
};
|
|
268
|
-
|
|
269
323
|
return (
|
|
270
324
|
<div>
|
|
271
|
-
<
|
|
272
|
-
<button onClick={
|
|
325
|
+
<pre>{JSON.stringify(state, null, 2)}</pre>
|
|
326
|
+
<button onClick={() => agent.stub.doSomething()}>Call Agent</button>
|
|
273
327
|
</div>
|
|
274
328
|
);
|
|
275
329
|
}
|
|
276
330
|
```
|
|
277
331
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
### ⏳ Temporal Patterns
|
|
332
|
+
### Vanilla JavaScript
|
|
281
333
|
|
|
282
|
-
|
|
334
|
+
```typescript
|
|
335
|
+
import { AgentClient } from "agents/client";
|
|
283
336
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
337
|
+
const client = new AgentClient({
|
|
338
|
+
agent: "my-agent",
|
|
339
|
+
name: "instance-name",
|
|
340
|
+
onStateUpdate: (state) => console.log("State:", state)
|
|
341
|
+
});
|
|
289
342
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
depth: "comprehensive"
|
|
293
|
-
});
|
|
343
|
+
// Call methods
|
|
344
|
+
const result = await client.call("processData", [payload]);
|
|
294
345
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
346
|
+
// Or use the stub
|
|
347
|
+
const result = await client.stub.processData(payload);
|
|
348
|
+
```
|
|
298
349
|
|
|
299
|
-
|
|
300
|
-
await this.analyze(data.focus);
|
|
301
|
-
}
|
|
350
|
+
---
|
|
302
351
|
|
|
303
|
-
|
|
304
|
-
await this.synthesize(data.depth);
|
|
305
|
-
}
|
|
352
|
+
## Workflows Integration
|
|
306
353
|
|
|
307
|
-
|
|
308
|
-
await this.analyze();
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
```
|
|
354
|
+
For durable, multi-step tasks that survive failures and can pause for human approval, integrate with [Cloudflare Workflows](https://developers.cloudflare.com/workflows/):
|
|
312
355
|
|
|
313
|
-
|
|
356
|
+
```typescript
|
|
357
|
+
import { AgentWorkflow } from "agents";
|
|
314
358
|
|
|
315
|
-
|
|
359
|
+
export class OrderWorkflow extends AgentWorkflow<OrderAgent, OrderParams> {
|
|
360
|
+
async run(event, step) {
|
|
361
|
+
// Step 1: Validate (retries automatically on failure)
|
|
362
|
+
const validated = await step.do("validate", async () => {
|
|
363
|
+
return validateOrder(event.payload);
|
|
364
|
+
});
|
|
316
365
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
import { streamText, generateText, createDataStreamResponse } from "ai";
|
|
366
|
+
// Step 2: Wait for human approval
|
|
367
|
+
await this.reportProgress({ step: "approval", status: "pending" });
|
|
368
|
+
const approval = await this.waitForApproval(step, { timeout: "7 days" });
|
|
321
369
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
return createDataStreamResponse({
|
|
326
|
-
execute: async (dataStream) => {
|
|
327
|
-
const stream = streamText({
|
|
328
|
-
model: openai("gpt-4o"),
|
|
329
|
-
messages: this.messages,
|
|
330
|
-
// Optional: onFinish is invoked by the AI SDK when generation completes.
|
|
331
|
-
// Persistence is handled automatically by AIChatAgent after streaming completes.
|
|
332
|
-
onFinish
|
|
333
|
-
});
|
|
334
|
-
|
|
335
|
-
stream.mergeIntoDataStream(dataStream);
|
|
336
|
-
}
|
|
370
|
+
// Step 3: Process the approved order
|
|
371
|
+
await step.do("process", async () => {
|
|
372
|
+
return processOrder(validated, approval);
|
|
337
373
|
});
|
|
338
|
-
|
|
339
|
-
// Option 2: Non-streaming responses (simpler, but no real-time updates)
|
|
340
|
-
// const result = await generateText({
|
|
341
|
-
// model: openai("gpt-4o"),
|
|
342
|
-
// messages: this.messages,
|
|
343
|
-
// });
|
|
344
|
-
//
|
|
345
|
-
// // For non-streaming with metadata, use toUIMessage:
|
|
346
|
-
// const message = result.toUIMessage({
|
|
347
|
-
// metadata: {
|
|
348
|
-
// model: 'gpt-4o',
|
|
349
|
-
// totalTokens: result.usage?.totalTokens,
|
|
350
|
-
// }
|
|
351
|
-
// });
|
|
352
|
-
//
|
|
353
|
-
// return new Response(JSON.stringify(message), {
|
|
354
|
-
// headers: { 'Content-Type': 'application/json' }
|
|
355
|
-
// });
|
|
356
374
|
}
|
|
357
375
|
}
|
|
358
376
|
```
|
|
359
377
|
|
|
360
|
-
|
|
378
|
+
Workflows provide:
|
|
361
379
|
|
|
362
|
-
|
|
380
|
+
- **Durable execution** — steps retry automatically, state persists across failures
|
|
381
|
+
- **Human-in-the-loop** — pause for approval with `waitForApproval()`
|
|
382
|
+
- **Long-running tasks** — run for days or weeks
|
|
383
|
+
- **Progress tracking** — report status back to the agent
|
|
384
|
+
|
|
385
|
+
See [Workflows](../../docs/agents/workflows.md) and [Human in the Loop](../../docs/agents/human-in-the-loop.md).
|
|
386
|
+
|
|
387
|
+
---
|
|
363
388
|
|
|
364
|
-
|
|
389
|
+
## AI Chat Integration
|
|
365
390
|
|
|
366
|
-
|
|
391
|
+
For AI-powered chat experiences with persistent conversations, streaming responses, and tool support, see [`@cloudflare/ai-chat`](../ai-chat/README.md).
|
|
367
392
|
|
|
368
393
|
```typescript
|
|
369
|
-
import { AIChatAgent } from "
|
|
370
|
-
import { streamText } from "ai";
|
|
371
|
-
import { openai } from "@ai-sdk/openai";
|
|
394
|
+
import { AIChatAgent } from "@cloudflare/ai-chat";
|
|
372
395
|
|
|
373
|
-
export class
|
|
396
|
+
export class ChatAgent extends AIChatAgent<Env> {
|
|
374
397
|
async onChatMessage(onFinish) {
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
const result = streamText({
|
|
398
|
+
return streamText({
|
|
378
399
|
model: openai("gpt-4o"),
|
|
379
400
|
messages: this.messages,
|
|
401
|
+
tools: this.tools,
|
|
380
402
|
onFinish
|
|
381
403
|
});
|
|
382
|
-
|
|
383
|
-
return result.toUIMessageStreamResponse({
|
|
384
|
-
messageMetadata: ({ part }) => {
|
|
385
|
-
if (part.type === "start") {
|
|
386
|
-
return {
|
|
387
|
-
model: "gpt-4o",
|
|
388
|
-
createdAt: Date.now(),
|
|
389
|
-
messageCount: this.messages.length
|
|
390
|
-
};
|
|
391
|
-
}
|
|
392
|
-
if (part.type === "finish") {
|
|
393
|
-
return {
|
|
394
|
-
responseTime: Date.now() - startTime,
|
|
395
|
-
totalTokens: part.totalUsage?.totalTokens
|
|
396
|
-
};
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
});
|
|
400
404
|
}
|
|
401
405
|
}
|
|
402
406
|
```
|
|
403
407
|
|
|
404
|
-
##### Accessing Metadata on the Client
|
|
405
|
-
|
|
406
|
-
Access metadata through the `message.metadata` property:
|
|
407
|
-
|
|
408
|
-
```typescript
|
|
409
|
-
'use client';
|
|
410
|
-
|
|
411
|
-
import { useChat } from '@ai-sdk/react';
|
|
412
|
-
import { DefaultChatTransport } from 'ai';
|
|
413
|
-
import type { MyUIMessage } from '@/types';
|
|
414
|
-
|
|
415
|
-
export default function Chat() {
|
|
416
|
-
const { messages } = useChat<MyUIMessage>({
|
|
417
|
-
transport: new DefaultChatTransport({
|
|
418
|
-
api: '/api/chat',
|
|
419
|
-
}),
|
|
420
|
-
});
|
|
421
|
-
|
|
422
|
-
return (
|
|
423
|
-
<div>
|
|
424
|
-
{messages.map(message => (
|
|
425
|
-
<div key={message.id}>
|
|
426
|
-
<div>
|
|
427
|
-
{message.role === 'user' ? 'User: ' : 'AI: '}
|
|
428
|
-
{message.metadata?.createdAt && (
|
|
429
|
-
<span className="text-sm text-gray-500">
|
|
430
|
-
{new Date(message.metadata.createdAt).toLocaleTimeString()}
|
|
431
|
-
</span>
|
|
432
|
-
)}
|
|
433
|
-
</div>
|
|
434
|
-
{/* Render message content */}
|
|
435
|
-
{message.parts.map((part, index) =>
|
|
436
|
-
part.type === 'text' ? <div key={index}>{part.text}</div> : null,
|
|
437
|
-
)}
|
|
438
|
-
{/* Display additional metadata */}
|
|
439
|
-
{message.metadata?.totalTokens && (
|
|
440
|
-
<div className="text-xs text-gray-400">
|
|
441
|
-
{message.metadata.totalTokens} tokens
|
|
442
|
-
</div>
|
|
443
|
-
)}
|
|
444
|
-
</div>
|
|
445
|
-
))}
|
|
446
|
-
</div>
|
|
447
|
-
);
|
|
448
|
-
}
|
|
449
|
-
```
|
|
450
|
-
|
|
451
|
-
For more details, see the [AI SDK Message Metadata documentation](https://ai-sdk.dev/docs/ai-sdk-ui/message-metadata).
|
|
452
|
-
|
|
453
|
-
#### Creating the Interface
|
|
454
|
-
|
|
455
|
-
Connect with your agent through a React interface:
|
|
456
|
-
|
|
457
408
|
```tsx
|
|
458
|
-
|
|
459
|
-
import { useAgentChat } from "
|
|
409
|
+
// Client
|
|
410
|
+
import { useAgentChat } from "@cloudflare/ai-chat/react";
|
|
460
411
|
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
agent: "dialogue-agent"
|
|
465
|
-
});
|
|
466
|
-
|
|
467
|
-
// Set up the chat interaction
|
|
468
|
-
const { messages, input, handleInputChange, handleSubmit, clearHistory } =
|
|
469
|
-
useAgentChat({
|
|
470
|
-
agent,
|
|
471
|
-
maxSteps: 5
|
|
472
|
-
});
|
|
473
|
-
|
|
474
|
-
return (
|
|
475
|
-
<div className="chat-interface">
|
|
476
|
-
{/* Message History */}
|
|
477
|
-
<div className="message-flow">
|
|
478
|
-
{messages.map((message) => (
|
|
479
|
-
<div key={message.id} className="message">
|
|
480
|
-
<div className="role">{message.role}</div>
|
|
481
|
-
<div className="content">
|
|
482
|
-
{message.parts.map((part, i) => {
|
|
483
|
-
if (part.type === "text")
|
|
484
|
-
return <span key={i}>{part.text}</span>;
|
|
485
|
-
// Render other part types (e.g., files, tool calls) as desired
|
|
486
|
-
return null;
|
|
487
|
-
})}
|
|
488
|
-
</div>
|
|
489
|
-
</div>
|
|
490
|
-
))}
|
|
491
|
-
</div>
|
|
492
|
-
|
|
493
|
-
{/* Input Area */}
|
|
494
|
-
<form onSubmit={handleSubmit} className="input-area">
|
|
495
|
-
<input
|
|
496
|
-
value={input}
|
|
497
|
-
onChange={handleInputChange}
|
|
498
|
-
placeholder="Type your message..."
|
|
499
|
-
className="message-input"
|
|
500
|
-
/>
|
|
501
|
-
</form>
|
|
502
|
-
|
|
503
|
-
<button onClick={clearHistory} className="clear-button">
|
|
504
|
-
Clear Chat
|
|
505
|
-
</button>
|
|
506
|
-
</div>
|
|
507
|
-
);
|
|
508
|
-
}
|
|
412
|
+
const { messages, input, handleSubmit } = useAgentChat({
|
|
413
|
+
agent: useAgent({ agent: "chat-agent" })
|
|
414
|
+
});
|
|
509
415
|
```
|
|
510
416
|
|
|
511
|
-
|
|
417
|
+
Features:
|
|
512
418
|
|
|
513
|
-
-
|
|
514
|
-
-
|
|
515
|
-
-
|
|
516
|
-
-
|
|
419
|
+
- Automatic message persistence
|
|
420
|
+
- Resumable streaming (survives disconnections)
|
|
421
|
+
- Server and client-side tool execution
|
|
422
|
+
- Human-in-the-loop approval for sensitive tools
|
|
517
423
|
|
|
518
|
-
|
|
424
|
+
---
|
|
519
425
|
|
|
520
|
-
|
|
426
|
+
## MCP (Model Context Protocol)
|
|
521
427
|
|
|
522
|
-
|
|
428
|
+
Agents integrate with MCP to act as servers (providing tools to AI assistants) or clients (using tools from other services).
|
|
429
|
+
|
|
430
|
+
### Creating an MCP Server
|
|
523
431
|
|
|
524
432
|
```typescript
|
|
525
433
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
526
434
|
import { McpAgent } from "agents/mcp";
|
|
527
|
-
import { z } from "zod";
|
|
528
|
-
|
|
529
|
-
type Env = {
|
|
530
|
-
MyMCP: DurableObjectNamespace<MyMCP>;
|
|
531
|
-
};
|
|
532
|
-
|
|
533
|
-
type State = { counter: number };
|
|
534
435
|
|
|
535
436
|
export class MyMCP extends McpAgent<Env, State, {}> {
|
|
536
|
-
server = new McpServer({
|
|
537
|
-
name: "Demo",
|
|
538
|
-
version: "1.0.0"
|
|
539
|
-
});
|
|
540
|
-
|
|
541
|
-
initialState: State = {
|
|
542
|
-
counter: 1
|
|
543
|
-
};
|
|
437
|
+
server = new McpServer({ name: "my-tools", version: "1.0.0" });
|
|
544
438
|
|
|
545
439
|
async init() {
|
|
546
|
-
this.server.
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
this.server.tool(
|
|
553
|
-
"add",
|
|
554
|
-
"Add to the counter, stored in the MCP",
|
|
555
|
-
{ a: z.number() },
|
|
556
|
-
async ({ a }) => {
|
|
557
|
-
this.setState({ ...this.state, counter: this.state.counter + a });
|
|
558
|
-
|
|
559
|
-
return {
|
|
560
|
-
content: [
|
|
561
|
-
{
|
|
562
|
-
text: String(`Added ${a}, total is now ${this.state.counter}`),
|
|
563
|
-
type: "text"
|
|
564
|
-
}
|
|
565
|
-
]
|
|
566
|
-
};
|
|
440
|
+
this.server.registerTool(
|
|
441
|
+
"lookup",
|
|
442
|
+
{ description: "Look up data", inputSchema: { query: z.string() } },
|
|
443
|
+
async ({ query }) => {
|
|
444
|
+
const result = await this.search(query);
|
|
445
|
+
return { content: [{ type: "text", text: result }] };
|
|
567
446
|
}
|
|
568
447
|
);
|
|
569
448
|
}
|
|
570
|
-
|
|
571
|
-
onStateUpdate(state: State) {
|
|
572
|
-
console.log({ stateUpdate: state });
|
|
573
|
-
}
|
|
574
449
|
}
|
|
575
450
|
|
|
576
|
-
|
|
577
|
-
export default MyMCP.serve("/mcp", {
|
|
578
|
-
binding: "MyMCP"
|
|
579
|
-
});
|
|
580
|
-
|
|
581
|
-
// Or SSE transport for legacy compatibility
|
|
582
|
-
// export default MyMCP.serveSSE("/mcp", { binding: "MyMCP" });
|
|
451
|
+
export default MyMCP.serve("/mcp", { binding: "MyMCP" });
|
|
583
452
|
```
|
|
584
453
|
|
|
585
|
-
|
|
454
|
+
### Using MCP Tools
|
|
586
455
|
|
|
587
456
|
```typescript
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
457
|
+
// Connect to external MCP servers
|
|
458
|
+
await this.addMcpServer(
|
|
459
|
+
"weather-service",
|
|
460
|
+
"https://weather-mcp.example.com/mcp",
|
|
461
|
+
{
|
|
462
|
+
transport: { type: "streamable-http" }
|
|
463
|
+
}
|
|
464
|
+
);
|
|
591
465
|
|
|
592
|
-
//
|
|
593
|
-
await
|
|
594
|
-
|
|
466
|
+
// Use with AI SDK
|
|
467
|
+
const result = await generateText({
|
|
468
|
+
model: openai("gpt-4o"),
|
|
469
|
+
tools: this.mcp.getTools(),
|
|
470
|
+
prompt: "What's the weather in Tokyo?"
|
|
595
471
|
});
|
|
472
|
+
```
|
|
596
473
|
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
474
|
+
---
|
|
475
|
+
|
|
476
|
+
## Configuration
|
|
477
|
+
|
|
478
|
+
Add your agent to `wrangler.jsonc`:
|
|
479
|
+
|
|
480
|
+
```jsonc
|
|
481
|
+
{
|
|
482
|
+
"durable_objects": {
|
|
483
|
+
"bindings": [{ "name": "MyAgent", "class_name": "MyAgent" }]
|
|
484
|
+
},
|
|
485
|
+
"migrations": [{ "tag": "v1", "new_sqlite_classes": ["MyAgent"] }]
|
|
486
|
+
}
|
|
603
487
|
```
|
|
604
488
|
|
|
605
|
-
|
|
489
|
+
Route requests to your agent:
|
|
606
490
|
|
|
607
491
|
```typescript
|
|
608
|
-
import {
|
|
492
|
+
import { routeAgentRequest } from "agents";
|
|
609
493
|
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
494
|
+
export default {
|
|
495
|
+
async fetch(request: Request, env: Env) {
|
|
496
|
+
return (
|
|
497
|
+
(await routeAgentRequest(request, env)) ??
|
|
498
|
+
new Response("Not found", { status: 404 })
|
|
499
|
+
);
|
|
500
|
+
}
|
|
501
|
+
};
|
|
616
502
|
```
|
|
617
503
|
|
|
618
|
-
|
|
504
|
+
---
|
|
505
|
+
|
|
506
|
+
## Coming Soon
|
|
619
507
|
|
|
620
|
-
- **
|
|
621
|
-
- **
|
|
622
|
-
- **
|
|
508
|
+
- **Browse the Web** — Headless browser for web scraping and automation
|
|
509
|
+
- **Cloudflare Sandboxes** — Isolated environments for code execution
|
|
510
|
+
- **SMS, Voice, Messengers** — Multi-channel communication
|
|
623
511
|
|
|
624
|
-
|
|
512
|
+
---
|
|
625
513
|
|
|
626
|
-
|
|
514
|
+
## Learn More
|
|
627
515
|
|
|
628
|
-
|
|
516
|
+
The published package includes the complete documentation tree at
|
|
517
|
+
`docs/index.md`.
|
|
629
518
|
|
|
630
|
-
-
|
|
631
|
-
|
|
632
|
-
|
|
519
|
+
[Getting Started](../../docs/agents/getting-started.md) ·
|
|
520
|
+
[State Management](../../docs/agents/state.md) ·
|
|
521
|
+
[Scheduling](../../docs/agents/scheduling.md) ·
|
|
522
|
+
[Callable Methods](../../docs/agents/callable-methods.md) ·
|
|
523
|
+
[MCP Integration](../../docs/agents/mcp-client.md) ·
|
|
524
|
+
[Full Documentation](../../docs/agents/index.md)
|
|
633
525
|
|
|
634
|
-
|
|
526
|
+
---
|
|
635
527
|
|
|
636
|
-
|
|
637
|
-
- **Clear Sight**: Deep visibility into agent processes
|
|
638
|
-
- **Private Realms**: Complete self-hosting guide
|
|
528
|
+
## Contributing
|
|
639
529
|
|
|
640
|
-
|
|
530
|
+
Contributions are welcome, especially when:
|
|
641
531
|
|
|
642
|
-
|
|
532
|
+
- You've opened an issue as an RFC to discuss your proposal
|
|
533
|
+
- The contribution isn't "AI slop" — LLMs are tools, but vibe-coded PRs won't meet the quality bar
|
|
534
|
+
- You're open to feedback to ensure changes fit the SDK's goals
|
|
643
535
|
|
|
644
|
-
|
|
536
|
+
Small fixes, type bugs, and documentation improvements can be raised directly as PRs.
|
|
645
537
|
|
|
646
|
-
|
|
538
|
+
---
|
|
647
539
|
|
|
648
|
-
|
|
649
|
-
- Not "AI slop": LLMs are powerful tools, but contributions entirely authored by vibe coding are unlikely to meet the quality bar, and will be rejected.
|
|
650
|
-
- You're willing to accept feedback and make sure the changes fit the goals of the `agents` SDK. Not everything will, and that's OK.
|
|
540
|
+
## License
|
|
651
541
|
|
|
652
|
-
|
|
542
|
+
MIT licensed. See the [LICENSE](../../LICENSE) file for details.
|
|
653
543
|
|
|
654
|
-
|
|
544
|
+
---
|
|
655
545
|
|
|
656
|
-
|
|
546
|
+
<p align="center">
|
|
547
|
+
<i>Build something that thinks. Ship something that does.</i>
|
|
548
|
+
</p>
|