agents 0.0.0-7ff0509 → 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.
Files changed (195) hide show
  1. package/README.md +411 -291
  2. package/agents.tsconfig.json +18 -0
  3. package/dist/agent-tool-types-DEBXD2Ta.d.ts +6169 -0
  4. package/dist/agent-tool-types.d.ts +54 -0
  5. package/dist/agent-tool-types.js +20 -0
  6. package/dist/agent-tool-types.js.map +1 -0
  7. package/dist/agent-tools-krZpfAix.d.ts +133 -0
  8. package/dist/agent-tools-y7zLfw4Q.js +304 -0
  9. package/dist/agent-tools-y7zLfw4Q.js.map +1 -0
  10. package/dist/agent-tools.d.ts +70 -0
  11. package/dist/agent-tools.js +60 -0
  12. package/dist/agent-tools.js.map +1 -0
  13. package/dist/ai-chat-agent.d.ts +1 -36
  14. package/dist/ai-chat-agent.js +4 -165
  15. package/dist/ai-chat-agent.js.map +1 -1
  16. package/dist/ai-chat-v5-migration.d.ts +1 -0
  17. package/dist/ai-chat-v5-migration.js +6 -0
  18. package/dist/ai-chat-v5-migration.js.map +1 -0
  19. package/dist/ai-react.d.ts +1 -88
  20. package/dist/ai-react.js +4 -187
  21. package/dist/ai-react.js.map +1 -1
  22. package/dist/ai-types.d.ts +1 -69
  23. package/dist/ai-types.js +5 -0
  24. package/dist/ai-types.js.map +1 -1
  25. package/dist/browser/ai.d.ts +235 -0
  26. package/dist/browser/ai.js +265 -0
  27. package/dist/browser/ai.js.map +1 -0
  28. package/dist/browser/index.d.ts +146 -0
  29. package/dist/browser/index.js +3 -0
  30. package/dist/browser/tanstack-ai.d.ts +41 -0
  31. package/dist/browser/tanstack-ai.js +57 -0
  32. package/dist/browser/tanstack-ai.js.map +1 -0
  33. package/dist/chat/index.d.ts +3392 -0
  34. package/dist/chat/index.js +3408 -0
  35. package/dist/chat/index.js.map +1 -0
  36. package/dist/chat/react.d.ts +602 -0
  37. package/dist/chat/react.js +1517 -0
  38. package/dist/chat/react.js.map +1 -0
  39. package/dist/chat-sdk/index.d.ts +135 -0
  40. package/dist/chat-sdk/index.js +453 -0
  41. package/dist/chat-sdk/index.js.map +1 -0
  42. package/dist/classPrivateFieldGet2-DZBYAB34.js +27 -0
  43. package/dist/classPrivateMethodInitSpec-qMjJ6sHQ.js +7 -0
  44. package/dist/cli/index.d.ts +1 -0
  45. package/dist/cli/index.js +26 -0
  46. package/dist/cli/index.js.map +1 -0
  47. package/dist/client-D8tz8bn3.js +2233 -0
  48. package/dist/client-D8tz8bn3.js.map +1 -0
  49. package/dist/client-invoker-BNSZxAkv.d.ts +20 -0
  50. package/dist/client-invoker-oF0lZZtP.js +57 -0
  51. package/dist/client-invoker-oF0lZZtP.js.map +1 -0
  52. package/dist/client-tools-aIBO0Fk7.d.ts +53 -0
  53. package/dist/client.d.ts +251 -33
  54. package/dist/client.js +269 -133
  55. package/dist/client.js.map +1 -1
  56. package/dist/codemode/ai.d.ts +1 -0
  57. package/dist/codemode/ai.js +6 -0
  58. package/dist/codemode/ai.js.map +1 -0
  59. package/dist/compaction-helpers-iiKMr2TQ.js +340 -0
  60. package/dist/compaction-helpers-iiKMr2TQ.js.map +1 -0
  61. package/dist/compaction-helpers-wUz6M3us.d.ts +621 -0
  62. package/dist/connector-CdldGF3h.js +1291 -0
  63. package/dist/connector-CdldGF3h.js.map +1 -0
  64. package/dist/connector-v2M1zlZp.d.ts +659 -0
  65. package/dist/do-oauth-client-provider-VTZj2VtM.d.ts +110 -0
  66. package/dist/email-CL27preh.d.ts +157 -0
  67. package/dist/email.d.ts +30 -0
  68. package/dist/email.js +222 -0
  69. package/dist/email.js.map +1 -0
  70. package/dist/experimental/memory/session/index.d.ts +670 -0
  71. package/dist/experimental/memory/session/index.js +2374 -0
  72. package/dist/experimental/memory/session/index.js.map +1 -0
  73. package/dist/experimental/memory/utils/index.d.ts +96 -0
  74. package/dist/experimental/memory/utils/index.js +79 -0
  75. package/dist/experimental/memory/utils/index.js.map +1 -0
  76. package/dist/experimental/webmcp.d.ts +218 -0
  77. package/dist/experimental/webmcp.js +298 -0
  78. package/dist/experimental/webmcp.js.map +1 -0
  79. package/dist/index-BRnybD6X.d.ts +947 -0
  80. package/dist/index.d.ts +186 -302
  81. package/dist/index.js +7151 -20
  82. package/dist/index.js.map +1 -1
  83. package/dist/internal_context-Dg4Cgjcu.d.ts +37 -0
  84. package/dist/internal_context.d.ts +6 -0
  85. package/dist/internal_context.js +11 -0
  86. package/dist/internal_context.js.map +1 -0
  87. package/dist/mcp/client.d.ts +38 -0
  88. package/dist/mcp/client.js +2 -0
  89. package/dist/mcp/do-oauth-client-provider.d.ts +10 -0
  90. package/dist/mcp/do-oauth-client-provider.js +292 -0
  91. package/dist/mcp/do-oauth-client-provider.js.map +1 -0
  92. package/dist/mcp/index.d.ts +82 -0
  93. package/dist/mcp/index.js +2059 -0
  94. package/dist/mcp/index.js.map +1 -0
  95. package/dist/mcp/x402.d.ts +119 -0
  96. package/dist/mcp/x402.js +260 -0
  97. package/dist/mcp/x402.js.map +1 -0
  98. package/dist/message-builder-BymO4N_D.js +386 -0
  99. package/dist/message-builder-BymO4N_D.js.map +1 -0
  100. package/dist/observability/index.d.ts +16 -0
  101. package/dist/observability/index.js +88 -0
  102. package/dist/observability/index.js.map +1 -0
  103. package/dist/react.d.ts +232 -21
  104. package/dist/react.js +479 -93
  105. package/dist/react.js.map +1 -1
  106. package/dist/retries-CAvxtG9d.d.ts +127 -0
  107. package/dist/retries.d.ts +22 -0
  108. package/dist/retries.js +229 -0
  109. package/dist/retries.js.map +1 -0
  110. package/dist/schedule.d.ts +123 -43
  111. package/dist/schedule.js +71 -23
  112. package/dist/schedule.js.map +1 -1
  113. package/dist/serializable.d.ts +141 -0
  114. package/dist/serializable.js +1 -0
  115. package/dist/skills/compile.d.ts +40 -0
  116. package/dist/skills/compile.js +65 -0
  117. package/dist/skills/compile.js.map +1 -0
  118. package/dist/skills/index.d.ts +244 -0
  119. package/dist/skills/index.js +1323 -0
  120. package/dist/skills/index.js.map +1 -0
  121. package/dist/sub-routing.d.ts +14 -0
  122. package/dist/sub-routing.js +177 -0
  123. package/dist/sub-routing.js.map +1 -0
  124. package/dist/tool-output-truncation-CNnnGZQ3.js +98 -0
  125. package/dist/tool-output-truncation-CNnnGZQ3.js.map +1 -0
  126. package/dist/types-6Zo2zfoO.d.ts +17 -0
  127. package/dist/types.d.ts +2 -0
  128. package/dist/types.js +19 -0
  129. package/dist/types.js.map +1 -0
  130. package/dist/utils-CGtGDSgA.d.ts +34 -0
  131. package/dist/utils.d.ts +6 -0
  132. package/dist/utils.js +51 -0
  133. package/dist/utils.js.map +1 -0
  134. package/dist/vite.d.ts +25 -0
  135. package/dist/vite.js +310 -0
  136. package/dist/vite.js.map +1 -0
  137. package/dist/wire-types-nflOzNuU.js +240 -0
  138. package/dist/wire-types-nflOzNuU.js.map +1 -0
  139. package/dist/workflow-types-Baz_PO5v.d.ts +280 -0
  140. package/dist/workflow-types.d.ts +52 -0
  141. package/dist/workflow-types.js +16 -0
  142. package/dist/workflow-types.js.map +1 -0
  143. package/dist/workflows.d.ts +198 -0
  144. package/dist/workflows.js +343 -0
  145. package/dist/workflows.js.map +1 -0
  146. package/docs/adding-to-existing-project.md +450 -0
  147. package/docs/agent-class.md +503 -0
  148. package/docs/agent-tools.md +552 -0
  149. package/docs/browse-the-web.md +430 -0
  150. package/docs/callable-methods.md +627 -0
  151. package/docs/chat-agents.md +1696 -0
  152. package/docs/chat-sdk.md +181 -0
  153. package/docs/client-sdk.md +520 -0
  154. package/docs/client-tools-continuation.md +177 -0
  155. package/docs/codemode.md +440 -0
  156. package/docs/configuration.md +795 -0
  157. package/docs/cross-domain-authentication.md +171 -0
  158. package/docs/durable-execution.md +537 -0
  159. package/docs/email.md +663 -0
  160. package/docs/get-current-agent.md +204 -0
  161. package/docs/getting-started.md +305 -0
  162. package/docs/http-websockets.md +668 -0
  163. package/docs/human-in-the-loop.md +661 -0
  164. package/docs/index.md +151 -0
  165. package/docs/long-running-agents.md +730 -0
  166. package/docs/mcp-client.md +683 -0
  167. package/docs/mcp-servers.md +548 -0
  168. package/docs/mcp-transports.md +308 -0
  169. package/docs/migration-to-ai-sdk-v5.md +96 -0
  170. package/docs/migration-to-ai-sdk-v6.md +163 -0
  171. package/docs/observability.md +261 -0
  172. package/docs/push-notifications.md +367 -0
  173. package/docs/queue.md +329 -0
  174. package/docs/readonly-connections.md +278 -0
  175. package/docs/resumable-streaming.md +127 -0
  176. package/docs/retries.md +444 -0
  177. package/docs/routing.md +749 -0
  178. package/docs/scheduling.md +898 -0
  179. package/docs/securing-mcp-servers.md +362 -0
  180. package/docs/server-driven-messages.md +477 -0
  181. package/docs/sessions.md +1024 -0
  182. package/docs/state.md +512 -0
  183. package/docs/sub-agents.md +389 -0
  184. package/docs/webhooks.md +604 -0
  185. package/docs/workflows.md +877 -0
  186. package/package.json +279 -48
  187. package/skills-module.d.ts +22 -0
  188. package/dist/chunk-HMLY7DHA.js +0 -16
  189. package/dist/chunk-HMLY7DHA.js.map +0 -1
  190. package/dist/chunk-KRBQHBPA.js +0 -599
  191. package/dist/chunk-KRBQHBPA.js.map +0 -1
  192. package/dist/mcp.d.ts +0 -58
  193. package/dist/mcp.js +0 -945
  194. package/dist/mcp.js.map +0 -1
  195. package/src/index.ts +0 -925
package/README.md CHANGED
@@ -1,428 +1,548 @@
1
- ### 🧠 `agents` - A Framework for Digital Intelligence
1
+ # agents
2
2
 
3
- ![agents-header](https://github.com/user-attachments/assets/f6d99eeb-1803-4495-9c5e-3cf07a37b402)
3
+ ![npm install agents](../../assets/npm-install-agents.svg)
4
4
 
5
- Welcome to a new chapter in software development, where AI agents persist, think, and act with purpose. The `agents` framework creates an environment where artificial intelligence can flourish - maintaining state, engaging in meaningful interactions, and evolving over time.
5
+ **Build software that thinks and does.**
6
6
 
7
- _This project is in active development. Join us in shaping the future of intelligent agents._
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
- #### The Nature of Agents
9
+ ```sh
10
+ npm create cloudflare@latest -- --template cloudflare/agents-starter
11
+ ```
12
+
13
+ Or add to an existing project:
14
+
15
+ ```sh
16
+ npm install agents
17
+ ```
18
+
19
+ ---
10
20
 
11
- An AI agent transcends traditional software boundaries. It's an entity that:
21
+ ## Why Agents, Why Now
12
22
 
13
- - **Persistence**: Maintains its state and knowledge across time
14
- - **Agency**: Acts autonomously within its defined purpose
15
- - **Connection**: Communicates through multiple channels with both humans and other agents
16
- - **Growth**: Learns and adapts through its interactions
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.
17
24
 
18
- Built on Cloudflare's global network, this framework provides agents with a reliable, distributed foundation where they can operate continuously and effectively.
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
- #### 💫 Core Principles
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
- 1. **Stateful Existence**: Each agent maintains its own persistent reality
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
- ### 🌱 Beginning the Journey
39
+ ## Quick Example
31
40
 
32
- Start with a complete environment:
41
+ A counter agent with real-time state sync and callable methods:
33
42
 
34
- ```sh
35
- # Create a new project
36
- npm create cloudflare@latest -- --template cloudflare/agents-starter
43
+ ```typescript
44
+ // server.ts
45
+ import { Agent, callable } from "agents";
37
46
 
38
- # Or enhance an existing one
39
- npm install agents
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
- ### 📝 Your First Agent
66
+ ```tsx
67
+ // client.tsx
68
+ import { useAgent } from "agents/react";
69
+ import { useState } from "react";
43
70
 
44
- Create an agent that bridges thought and action:
71
+ function Counter() {
72
+ const [count, setCount] = useState(0);
45
73
 
46
- ```ts
47
- import { Agent } from "agents";
74
+ const agent = useAgent<State>({
75
+ agent: "counter-agent",
76
+ name: "my-counter",
77
+ onStateUpdate: (state) => setCount(state.count)
78
+ });
48
79
 
49
- export class IntelligentAgent extends Agent {
50
- async onRequest(request) {
51
- // Transform intention into response
52
- return new Response("Ready to assist.");
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
- ### 🎭 Patterns of Intelligence
90
+ State changes sync to all connected clients automatically. Call methods like they're local functions.
58
91
 
59
- Agents can manifest various forms of understanding:
92
+ ---
60
93
 
61
- ```ts
62
- import { Agent } from "agents";
63
- import { OpenAI } from "openai";
94
+ ## What You Can Build
64
95
 
65
- export class AIAgent extends Agent {
66
- async onRequest(request) {
67
- // Connect with AI capabilities
68
- const ai = new OpenAI({
69
- apiKey: this.env.OPENAI_API_KEY,
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
- // Process and understand
73
- const response = await ai.chat.completions.create({
74
- model: "gpt-4",
75
- messages: [{ role: "user", content: await request.text() }],
76
- });
105
+ ---
106
+
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
77
119
 
78
- return new Response(response.choices[0].message.content);
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
- async processTask(task) {
82
- await this.understand(task);
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
- ### 🏰 Creating Space
137
+ ### Callable Methods
90
138
 
91
- Define your agent's domain:
139
+ Expose methods to clients with the `@callable()` decorator:
92
140
 
93
- ```jsonc
94
- {
95
- "durable_objects": {
96
- "bindings": [
97
- {
98
- "name": "AIAgent",
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
- ### 🌐 Lifecycle
150
+ ```typescript
151
+ // Client
152
+ const result = await agent.stub.processOrder("order-123", items);
153
+ ```
114
154
 
115
- Bring your agent into being:
155
+ ### Scheduling
116
156
 
117
- ```ts
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
- // Initialize with purpose
123
- await agent.processTask({
124
- type: "analysis",
125
- context: "incoming_data",
126
- parameters: initialConfig,
127
- });
159
+ ```typescript
160
+ // In 60 seconds
161
+ this.schedule(60, "sendReminder", { userId: "123" });
128
162
 
129
- // Or reconnect with an existing one
130
- const existingAgent = await getAgentByName(env.AIAgent, "data-analyzer");
131
- ```
163
+ // Every hour
164
+ this.scheduleEvery(3600, "syncData");
132
165
 
133
- ### 🔄 Paths of Communication
166
+ // Daily at 9am UTC
167
+ this.schedule("0 9 * * *", "dailyReport");
134
168
 
135
- #### HTTP Understanding
169
+ // At a specific date
170
+ this.schedule(new Date("2025-12-31"), "yearEndTask");
171
+ ```
136
172
 
137
- Process and respond to direct requests:
173
+ ### Background Tasks
138
174
 
139
- ```ts
140
- export class APIAgent extends Agent {
141
- async onRequest(request) {
142
- const data = await request.json();
175
+ Queue immediate background work:
143
176
 
144
- return Response.json({
145
- insight: await this.process(data),
146
- moment: Date.now(),
147
- });
148
- }
149
- }
177
+ ```typescript
178
+ await this.queue("processUpload", { fileId: "abc" });
179
+ // Returns immediately, task runs in background
150
180
  ```
151
181
 
152
- #### Persistent Connections
182
+ ### Sub-agents
153
183
 
154
- Maintain ongoing dialogues through WebSocket:
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
- ```ts
157
- export class DialogueAgent extends Agent {
158
- async onConnect(connection) {
159
- await this.initiate(connection);
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
- async onMessage(connection, message) {
163
- const understanding = await this.comprehend(message);
164
- await this.respond(connection, understanding);
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
- #### Client Communion
212
+ Client-side, connect to a child with `useAgent({ sub: [...] })`:
170
213
 
171
- For direct connection to your agent:
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
- ```ts
174
- import { AgentClient } from "agents/client";
223
+ The routed URL becomes `/agents/inbox/{userId}/sub/chat/{chatId}`.
175
224
 
176
- const connection = new AgentClient({
177
- agent: "dialogue-agent",
178
- name: "insight-seeker",
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
- connection.addEventListener("message", (event) => {
182
- console.log("Received:", event.data);
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
- connection.send(
186
- JSON.stringify({
187
- type: "inquiry",
188
- content: "What patterns do you see?",
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
- #### React Integration
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
- For harmonious integration with React:
273
+ ### WebSocket Connections
196
274
 
197
- ```tsx
198
- import { useAgent } from "agents/react";
275
+ Handle real-time communication:
199
276
 
200
- function AgentInterface() {
201
- const connection = useAgent({
202
- agent: "dialogue-agent",
203
- name: "insight-seeker",
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
- const inquire = () => {
212
- connection.send(
213
- JSON.stringify({
214
- type: "inquiry",
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
- return (
221
- <div className="agent-interface">
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
- ### 🌊 Flow of State
229
-
230
- Maintain and evolve your agent's understanding:
292
+ ### Email
231
293
 
232
- ```ts
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
- onStateUpdate(state, source) {
243
- console.log("Understanding deepened:", {
244
- newState: state,
245
- origin: source,
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
- Connect to your agent's state from React:
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 StateInterface() {
258
- const [state, setState] = useState({ counter: 0 });
314
+ function App() {
315
+ const [state, setState] = useState<MyState | null>(null);
259
316
 
260
- const agent = useAgent({
261
- agent: "thinking-agent",
262
- onStateUpdate: (newState) => setState(newState),
317
+ const agent = useAgent<MyState>({
318
+ agent: "my-agent",
319
+ name: "instance-name",
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
- <div>Count: {state.counter}</div>
272
- <button onClick={increment}>Increment</button>
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
- This creates a synchronized state that automatically updates across all connected clients.
332
+ ### Vanilla JavaScript
279
333
 
280
- ### ⏳ Temporal Patterns
334
+ ```typescript
335
+ import { AgentClient } from "agents/client";
281
336
 
282
- Schedule moments of action and reflection:
337
+ const client = new AgentClient({
338
+ agent: "my-agent",
339
+ name: "instance-name",
340
+ onStateUpdate: (state) => console.log("State:", state)
341
+ });
283
342
 
284
- ```ts
285
- export class TimeAwareAgent extends Agent {
286
- async initialize() {
287
- // Quick reflection
288
- this.schedule(10, "quickInsight", { focus: "patterns" });
343
+ // Call methods
344
+ const result = await client.call("processData", [payload]);
289
345
 
290
- // Daily synthesis
291
- this.schedule("0 0 * * *", "dailySynthesis", {
292
- depth: "comprehensive",
293
- });
346
+ // Or use the stub
347
+ const result = await client.stub.processData(payload);
348
+ ```
294
349
 
295
- // Milestone review
296
- this.schedule(new Date("2024-12-31"), "yearlyAnalysis");
297
- }
350
+ ---
298
351
 
299
- async quickInsight(data) {
300
- await this.analyze(data.focus);
301
- }
352
+ ## Workflows Integration
302
353
 
303
- async dailySynthesis(data) {
304
- await this.synthesize(data.depth);
305
- }
354
+ For durable, multi-step tasks that survive failures and can pause for human approval, integrate with [Cloudflare Workflows](https://developers.cloudflare.com/workflows/):
355
+
356
+ ```typescript
357
+ import { AgentWorkflow } from "agents";
358
+
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
+ });
365
+
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" });
306
369
 
307
- async yearlyAnalysis() {
308
- await this.analyze();
370
+ // Step 3: Process the approved order
371
+ await step.do("process", async () => {
372
+ return processOrder(validated, approval);
373
+ });
309
374
  }
310
375
  }
311
376
  ```
312
377
 
313
- ### 💬 AI Dialogue
378
+ Workflows provide:
379
+
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
+ ---
388
+
389
+ ## AI Chat Integration
314
390
 
315
- Create meaningful conversations with intelligence:
391
+ For AI-powered chat experiences with persistent conversations, streaming responses, and tool support, see [`@cloudflare/ai-chat`](../ai-chat/README.md).
316
392
 
317
- ```ts
318
- import { AIChatAgent } from "agents/ai-chat-agent";
319
- import { openai } from "@ai-sdk/openai";
393
+ ```typescript
394
+ import { AIChatAgent } from "@cloudflare/ai-chat";
320
395
 
321
- export class DialogueAgent extends AIChatAgent {
396
+ export class ChatAgent extends AIChatAgent<Env> {
322
397
  async onChatMessage(onFinish) {
323
- return createDataStreamResponse({
324
- execute: async (dataStream) => {
325
- const stream = streamText({
326
- model: openai("gpt-4o"),
327
- messages: this.messages,
328
- onFinish, // call onFinish so that messages get saved
329
- });
330
-
331
- stream.mergeIntoDataStream(dataStream);
332
- },
398
+ return streamText({
399
+ model: openai("gpt-4o"),
400
+ messages: this.messages,
401
+ tools: this.tools,
402
+ onFinish
333
403
  });
334
404
  }
335
405
  }
336
406
  ```
337
407
 
338
- #### Creating the Interface
408
+ ```tsx
409
+ // Client
410
+ import { useAgentChat } from "@cloudflare/ai-chat/react";
339
411
 
340
- Connect with your agent through a React interface:
412
+ const { messages, input, handleSubmit } = useAgentChat({
413
+ agent: useAgent({ agent: "chat-agent" })
414
+ });
415
+ ```
341
416
 
342
- ```tsx
343
- import { useAgent } from "agents/react";
344
- import { useAgentChat } from "agents/ai-react";
417
+ Features:
345
418
 
346
- function ChatInterface() {
347
- // Connect to the agent
348
- const agent = useAgent({
349
- agent: "dialogue-agent",
350
- });
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
351
423
 
352
- // Set up the chat interaction
353
- const { messages, input, handleInputChange, handleSubmit, clearHistory } =
354
- useAgentChat({
355
- agent,
356
- maxSteps: 5,
357
- });
424
+ ---
358
425
 
359
- return (
360
- <div className="chat-interface">
361
- {/* Message History */}
362
- <div className="message-flow">
363
- {messages.map((message) => (
364
- <div key={message.id} className="message">
365
- <div className="role">{message.role}</div>
366
- <div className="content">{message.content}</div>
367
- </div>
368
- ))}
369
- </div>
370
-
371
- {/* Input Area */}
372
- <form onSubmit={handleSubmit} className="input-area">
373
- <input
374
- value={input}
375
- onChange={handleInputChange}
376
- placeholder="Type your message..."
377
- className="message-input"
378
- />
379
- </form>
380
-
381
- <button onClick={clearHistory} className="clear-button">
382
- Clear Chat
383
- </button>
384
- </div>
385
- );
426
+ ## MCP (Model Context Protocol)
427
+
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
431
+
432
+ ```typescript
433
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
434
+ import { McpAgent } from "agents/mcp";
435
+
436
+ export class MyMCP extends McpAgent<Env, State, {}> {
437
+ server = new McpServer({ name: "my-tools", version: "1.0.0" });
438
+
439
+ async init() {
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 }] };
446
+ }
447
+ );
448
+ }
449
+ }
450
+
451
+ export default MyMCP.serve("/mcp", { binding: "MyMCP" });
452
+ ```
453
+
454
+ ### Using MCP Tools
455
+
456
+ ```typescript
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
+ );
465
+
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?"
471
+ });
472
+ ```
473
+
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"] }]
386
486
  }
387
487
  ```
388
488
 
389
- This creates:
489
+ Route requests to your agent:
390
490
 
391
- - Real-time message streaming
392
- - Simple message history
393
- - Intuitive input handling
394
- - Easy conversation reset
491
+ ```typescript
492
+ import { routeAgentRequest } from "agents";
493
+
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
+ };
502
+ ```
395
503
 
396
- ### 💬 The Path Forward
504
+ ---
397
505
 
398
- We're developing new dimensions of agent capability:
506
+ ## Coming Soon
399
507
 
400
- #### Enhanced Understanding
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
401
511
 
402
- - **WebRTC Perception**: Audio and video communication channels
403
- - **Email Discourse**: Automated email interaction and response
404
- - **Deep Memory**: Long-term context and relationship understanding
512
+ ---
405
513
 
406
- #### Development Insights
514
+ ## Learn More
407
515
 
408
- - **Evaluation Framework**: Understanding agent effectiveness
409
- - **Clear Sight**: Deep visibility into agent processes
410
- - **Private Realms**: Complete self-hosting guide
516
+ The published package includes the complete documentation tree at
517
+ `docs/index.md`.
411
518
 
412
- These capabilities will expand your agents' potential while maintaining their reliability and purpose.
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)
413
525
 
414
- Welcome to the future of intelligent agents. Create something meaningful. 🌟
526
+ ---
415
527
 
416
- ### Contributing
528
+ ## Contributing
417
529
 
418
- Contributions are welcome, but are especially welcome when:
530
+ Contributions are welcome, especially when:
419
531
 
420
- - You have opened an issue as a Request for Comment (RFC) to discuss your proposal, show your thinking, and iterate together.
421
- - Is 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.
422
- - 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.
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
423
535
 
424
536
  Small fixes, type bugs, and documentation improvements can be raised directly as PRs.
425
537
 
426
- ### License
538
+ ---
539
+
540
+ ## License
541
+
542
+ MIT licensed. See the [LICENSE](../../LICENSE) file for details.
543
+
544
+ ---
427
545
 
428
- MIT licensed. See the LICENSE file at the root of this repository for details.
546
+ <p align="center">
547
+ <i>Build something that thinks. Ship something that does.</i>
548
+ </p>