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.
Files changed (122) hide show
  1. package/README.md +11 -8
  2. package/dist/{agent-tool-types-CTw3UJUP.d.ts → agent-tool-types-Cd1TZPfB.d.ts} +587 -137
  3. package/dist/agent-tool-types.d.ts +34 -18
  4. package/dist/agent-tool-types.js +20 -1
  5. package/dist/agent-tool-types.js.map +1 -0
  6. package/dist/agent-tools-BXlsuX0d.js +304 -0
  7. package/dist/agent-tools-BXlsuX0d.js.map +1 -0
  8. package/dist/agent-tools-_E8wxUIK.d.ts +119 -0
  9. package/dist/agent-tools.d.ts +24 -18
  10. package/dist/agent-tools.js.map +1 -1
  11. package/dist/ai-chat-agent.d.ts +1 -1
  12. package/dist/ai-chat-agent.js +1 -2
  13. package/dist/ai-chat-agent.js.map +1 -1
  14. package/dist/ai-chat-v5-migration.d.ts +1 -1
  15. package/dist/ai-chat-v5-migration.js +1 -2
  16. package/dist/ai-chat-v5-migration.js.map +1 -1
  17. package/dist/ai-react.d.ts +1 -1
  18. package/dist/ai-react.js +1 -2
  19. package/dist/ai-react.js.map +1 -1
  20. package/dist/ai-types.d.ts +1 -7
  21. package/dist/ai-types.js +2 -8
  22. package/dist/ai-types.js.map +1 -1
  23. package/dist/browser/ai.js +1 -1
  24. package/dist/browser/index.js +1 -1
  25. package/dist/chat/index.d.ts +1918 -72
  26. package/dist/chat/index.js +1730 -245
  27. package/dist/chat/index.js.map +1 -1
  28. package/dist/chat/react.d.ts +602 -0
  29. package/dist/chat/react.js +1506 -0
  30. package/dist/chat/react.js.map +1 -0
  31. package/dist/chat-sdk/index.d.ts +4 -4
  32. package/dist/{classPrivateFieldGet2-CZ7QjTXN.js → classPrivateFieldGet2-DZBYAB34.js} +5 -5
  33. package/dist/{classPrivateMethodInitSpec-D-0__zd9.js → classPrivateMethodInitSpec-qMjJ6sHQ.js} +2 -2
  34. package/dist/{client-BXJ9n2f7.js → client-BZ-B3NhC.js} +2 -2
  35. package/dist/client-BZ-B3NhC.js.map +1 -0
  36. package/dist/client-tools-aIBO0Fk7.d.ts +53 -0
  37. package/dist/client.d.ts +76 -57
  38. package/dist/client.js +33 -5
  39. package/dist/client.js.map +1 -1
  40. package/dist/{connector-CrKhowfD.js → connector-CdldGF3h.js} +5 -5
  41. package/dist/{connector-CrKhowfD.js.map → connector-CdldGF3h.js.map} +1 -1
  42. package/dist/email.js +1 -1
  43. package/dist/email.js.map +1 -1
  44. package/dist/{index-B7IbEeze.d.ts → index-CcbnKkNh.d.ts} +188 -14
  45. package/dist/index.d.ts +91 -71
  46. package/dist/index.js +562 -24
  47. package/dist/index.js.map +1 -1
  48. package/dist/mcp/client.d.ts +18 -14
  49. package/dist/mcp/client.js +1 -1
  50. package/dist/mcp/index.d.ts +30 -30
  51. package/dist/mcp/index.js +7 -7
  52. package/dist/mcp/index.js.map +1 -1
  53. package/dist/{agent-tools-3zLG7MgA.js → message-builder-BymO4N_D.js} +45 -126
  54. package/dist/message-builder-BymO4N_D.js.map +1 -0
  55. package/dist/observability/index.d.ts +1 -1
  56. package/dist/observability/index.js +4 -2
  57. package/dist/observability/index.js.map +1 -1
  58. package/dist/react.d.ts +123 -110
  59. package/dist/react.js +44 -11
  60. package/dist/react.js.map +1 -1
  61. package/dist/serializable.d.ts +1 -1
  62. package/dist/skills/compile.js +1 -1
  63. package/dist/skills/compile.js.map +1 -1
  64. package/dist/skills/index.js +5 -5
  65. package/dist/skills/index.js.map +1 -1
  66. package/dist/sub-routing.d.ts +6 -6
  67. package/dist/utils.js +1 -1
  68. package/dist/utils.js.map +1 -1
  69. package/dist/vite.js +5 -5
  70. package/dist/vite.js.map +1 -1
  71. package/dist/wire-types-nflOzNuU.js +240 -0
  72. package/dist/wire-types-nflOzNuU.js.map +1 -0
  73. package/dist/{workflow-types-SrZK_o9p.d.ts → workflow-types-Baz_PO5v.d.ts} +42 -22
  74. package/dist/workflow-types.d.ts +25 -21
  75. package/dist/workflow-types.js.map +1 -1
  76. package/dist/workflows.d.ts +22 -21
  77. package/dist/workflows.js +31 -7
  78. package/dist/workflows.js.map +1 -1
  79. package/docs/adding-to-existing-project.md +450 -0
  80. package/docs/agent-class.md +503 -0
  81. package/docs/agent-tools.md +552 -0
  82. package/docs/browse-the-web.md +430 -0
  83. package/docs/callable-methods.md +627 -0
  84. package/docs/chat-agents.md +1687 -0
  85. package/docs/chat-sdk.md +181 -0
  86. package/docs/client-sdk.md +520 -0
  87. package/docs/client-tools-continuation.md +177 -0
  88. package/docs/codemode.md +440 -0
  89. package/docs/configuration.md +775 -0
  90. package/docs/cross-domain-authentication.md +171 -0
  91. package/docs/durable-execution.md +537 -0
  92. package/docs/email.md +663 -0
  93. package/docs/get-current-agent.md +204 -0
  94. package/docs/getting-started.md +305 -0
  95. package/docs/http-websockets.md +668 -0
  96. package/docs/human-in-the-loop.md +661 -0
  97. package/docs/index.md +151 -0
  98. package/docs/long-running-agents.md +730 -0
  99. package/docs/mcp-client.md +620 -0
  100. package/docs/mcp-servers.md +526 -0
  101. package/docs/mcp-transports.md +308 -0
  102. package/docs/migration-to-ai-sdk-v5.md +96 -0
  103. package/docs/migration-to-ai-sdk-v6.md +163 -0
  104. package/docs/observability.md +261 -0
  105. package/docs/push-notifications.md +367 -0
  106. package/docs/queue.md +329 -0
  107. package/docs/readonly-connections.md +278 -0
  108. package/docs/resumable-streaming.md +127 -0
  109. package/docs/retries.md +444 -0
  110. package/docs/routing.md +749 -0
  111. package/docs/scheduling.md +898 -0
  112. package/docs/securing-mcp-servers.md +359 -0
  113. package/docs/server-driven-messages.md +477 -0
  114. package/docs/sessions.md +1024 -0
  115. package/docs/state.md +512 -0
  116. package/docs/sub-agents.md +389 -0
  117. package/docs/webhooks.md +604 -0
  118. package/docs/workflows.md +877 -0
  119. package/package.json +41 -14
  120. package/dist/agent-tools-3zLG7MgA.js.map +0 -1
  121. package/dist/agent-tools-DZhI5F6Q.d.ts +0 -14
  122. package/dist/client-BXJ9n2f7.js.map +0 -1
@@ -0,0 +1,204 @@
1
+ # `getCurrentAgent()`
2
+
3
+ ## Automatic context for custom methods
4
+
5
+ The framework detects and wraps custom Agent methods during initialization so `getCurrentAgent()` can resolve the active agent inside them and the functions they call.
6
+
7
+ ## How It Works
8
+
9
+ ```typescript
10
+ import { AIChatAgent } from "@cloudflare/ai-chat";
11
+ import { getCurrentAgent } from "agents";
12
+
13
+ export class MyAgent extends AIChatAgent {
14
+ async customMethod() {
15
+ const { agent } = getCurrentAgent<MyAgent>();
16
+ // ✅ agent is automatically available!
17
+ console.log(agent.name);
18
+ }
19
+
20
+ async anotherMethod() {
21
+ // ✅ This works too - no setup needed!
22
+ const { agent } = getCurrentAgent<MyAgent>();
23
+ return agent.state;
24
+ }
25
+ }
26
+ ```
27
+
28
+ **Zero configuration required!** The framework automatically:
29
+
30
+ 1. Scans your agent class for custom methods
31
+ 2. Wraps them with agent context during initialization
32
+ 3. Ensures `getCurrentAgent()` works in all external functions called from your methods
33
+
34
+ ## Real-World Example
35
+
36
+ ```typescript
37
+ import { AIChatAgent } from "@cloudflare/ai-chat";
38
+ import { getCurrentAgent } from "agents";
39
+ import { generateText } from "ai";
40
+ import { openai } from "@ai-sdk/openai";
41
+
42
+ // External utility function that needs agent context
43
+ async function processWithAI(prompt: string) {
44
+ const { agent } = getCurrentAgent<MyAgent>();
45
+ // ✅ External functions can access the current agent!
46
+
47
+ return await generateText({
48
+ model: openai("gpt-4"),
49
+ prompt: `Agent ${agent?.name}: ${prompt}`
50
+ });
51
+ }
52
+
53
+ export class MyAgent extends AIChatAgent {
54
+ async customMethod(message: string) {
55
+ // Use this.* to access agent properties directly
56
+ console.log("Agent name:", this.name);
57
+ console.log("Agent state:", this.state);
58
+
59
+ // External functions automatically work!
60
+ const result = await processWithAI(message);
61
+ return result.text;
62
+ }
63
+ }
64
+ ```
65
+
66
+ ### Built-in vs Custom Methods
67
+
68
+ - **Built-in methods** (onRequest, onEmail, onStateChanged): Already have context
69
+ - **Custom methods** (your methods): Automatically wrapped during initialization
70
+ - **External functions**: Access context through `getCurrentAgent()`
71
+
72
+ ### The Context Flow
73
+
74
+ ```typescript
75
+ // When you call a custom method:
76
+ agent.customMethod()
77
+ → automatically wrapped with agentContext.run()
78
+ → your method executes with full context
79
+ → external functions can use getCurrentAgent()
80
+ ```
81
+
82
+ ## Common Use Cases
83
+
84
+ ### Working with AI SDK Tools
85
+
86
+ ```typescript
87
+ import { AIChatAgent } from "@cloudflare/ai-chat";
88
+ import { generateText } from "ai";
89
+ import { openai } from "@ai-sdk/openai";
90
+
91
+ export class MyAgent extends AIChatAgent {
92
+ async generateResponse(prompt: string) {
93
+ // AI SDK tools automatically work
94
+ const response = await generateText({
95
+ model: openai("gpt-4"),
96
+ prompt,
97
+ tools: {
98
+ // Tools that use getCurrentAgent() work perfectly
99
+ }
100
+ });
101
+
102
+ return response.text;
103
+ }
104
+ }
105
+ ```
106
+
107
+ ### Calling External Libraries
108
+
109
+ ```typescript
110
+ import { AIChatAgent } from "@cloudflare/ai-chat";
111
+ import { getCurrentAgent } from "agents";
112
+
113
+ async function saveToDatabase(data: any) {
114
+ const { agent } = getCurrentAgent<MyAgent>();
115
+ // Can access agent info for logging, context, etc.
116
+ console.log(`Saving data for agent: ${agent?.name}`);
117
+ }
118
+
119
+ export class MyAgent extends AIChatAgent {
120
+ async processData(data: any) {
121
+ // External functions automatically have context
122
+ await saveToDatabase(data);
123
+ }
124
+ }
125
+ ```
126
+
127
+ ## When context is lost
128
+
129
+ The agent context only propagates along the call tree of the original
130
+ invocation. Code reached outside that call tree starts with an empty context,
131
+ so `getCurrentAgent()` returns an object whose fields are `undefined`. Common
132
+ cases include:
133
+
134
+ - a host callback invoked through RPC from a Worker Loader child isolate, such
135
+ as sandboxed Codemode execution;
136
+ - a service binding or Durable Object RPC entrypoint;
137
+ - a queue consumer or another entrypoint that retains an agent reference.
138
+
139
+ Route the callback through a public method on the agent. Custom methods are
140
+ wrapped automatically, so calling `agent.someMethod()` re-enters that agent's
141
+ context:
142
+
143
+ ```typescript
144
+ import { RpcTarget } from "cloudflare:workers";
145
+
146
+ class HostCallbackBridge extends RpcTarget {
147
+ constructor(private agent: MyMcpAgent) {
148
+ super();
149
+ }
150
+
151
+ // Invoked through RPC from a Worker Loader child isolate. There is no context
152
+ // ancestry. Calling a public agent method restores it automatically.
153
+ async invoke() {
154
+ return this.agent.handleSandboxCallback();
155
+ }
156
+ }
157
+
158
+ export class MyMcpAgent extends McpAgent {
159
+ async handleSandboxCallback() {
160
+ const { agent } = getCurrentAgent<MyMcpAgent>();
161
+ // `agent` is available again.
162
+ }
163
+ }
164
+ ```
165
+
166
+ Context restored this way has `connection`, `request`, and `email` unset. It
167
+ is not tied to live client I/O.
168
+
169
+ Server-initiated MCP requests (`elicitInput`, `createMessage`, and `listRoots`)
170
+ on `McpAgent` do not require this indirection because the MCP transport retains
171
+ its owning agent.
172
+
173
+ ## API reference
174
+
175
+ The agents package exports one main function for context management:
176
+
177
+ ### `getCurrentAgent<T>()`
178
+
179
+ Gets the current agent from any context where it's available.
180
+
181
+ **Returns:**
182
+
183
+ ```typescript
184
+ {
185
+ agent: T | undefined,
186
+ connection: Connection | undefined,
187
+ request: Request | undefined
188
+ }
189
+ ```
190
+
191
+ **Usage:**
192
+
193
+ ```typescript
194
+ import { AIChatAgent } from "@cloudflare/ai-chat";
195
+ import { getCurrentAgent } from "agents";
196
+
197
+ export class MyAgent extends AIChatAgent {
198
+ async customMethod() {
199
+ const { agent, connection, request } = getCurrentAgent<MyAgent>();
200
+ // agent is properly typed as MyAgent
201
+ // connection and request available if called from a request handler
202
+ }
203
+ }
204
+ ```
@@ -0,0 +1,305 @@
1
+ # Getting Started
2
+
3
+ Build AI agents that persist, think, and act. Agents run on Cloudflare's global network, maintain state across requests, and connect to clients in real-time via WebSockets.
4
+
5
+ **What you'll build:** A counter agent with persistent state that syncs to a React frontend in real-time.
6
+
7
+ **Time:** ~10 minutes
8
+
9
+ ---
10
+
11
+ ## Create a New Project
12
+
13
+ ```bash
14
+ npm create cloudflare@latest -- --template cloudflare/agents-starter
15
+ cd my-agent
16
+ npm install
17
+ ```
18
+
19
+ This creates a project with:
20
+
21
+ - `src/server.ts` - Your agent code
22
+ - `src/client.tsx` - React frontend
23
+ - `wrangler.jsonc` - Cloudflare configuration
24
+ - `tsconfig.json` - Extends `agents/tsconfig` for correct decorator and module settings
25
+ - `vite.config.ts` - Includes the `agents/vite` plugin for decorator support
26
+
27
+ The starter template includes two SDK integrations that are required for `@callable()` decorators. If you are setting up a project manually, add both:
28
+
29
+ **tsconfig.json** — extends `agents/tsconfig`, which sets `target: "ES2021"` and other recommended options:
30
+
31
+ ```json
32
+ {
33
+ "extends": "agents/tsconfig"
34
+ }
35
+ ```
36
+
37
+ **vite.config.ts** — includes the `agents()` plugin, which handles TC39 decorator transforms (required because Vite 8's Oxc transpiler does not support them yet):
38
+
39
+ ```typescript
40
+ import { cloudflare } from "@cloudflare/vite-plugin";
41
+ import react from "@vitejs/plugin-react";
42
+ import agents from "agents/vite";
43
+ import { defineConfig } from "vite";
44
+
45
+ export default defineConfig({
46
+ plugins: [agents(), react(), cloudflare()]
47
+ });
48
+ ```
49
+
50
+ Start the dev server:
51
+
52
+ ```bash
53
+ npm run dev
54
+ ```
55
+
56
+ Open [http://localhost:5173](http://localhost:5173) to see your agent in action.
57
+
58
+ ---
59
+
60
+ ## Your First Agent
61
+
62
+ Let's build a simple counter agent from scratch. Replace `src/server.ts`:
63
+
64
+ ```typescript
65
+ import { Agent, routeAgentRequest, callable } from "agents";
66
+
67
+ // Define the state shape
68
+ type CounterState = {
69
+ count: number;
70
+ };
71
+
72
+ // Create the agent
73
+ export class Counter extends Agent<Env, CounterState> {
74
+ // Initial state for new instances
75
+ initialState: CounterState = { count: 0 };
76
+
77
+ // Methods marked with @callable can be called from the client
78
+ @callable()
79
+ increment() {
80
+ this.setState({ count: this.state.count + 1 });
81
+ return this.state.count;
82
+ }
83
+
84
+ @callable()
85
+ decrement() {
86
+ this.setState({ count: this.state.count - 1 });
87
+ return this.state.count;
88
+ }
89
+
90
+ @callable()
91
+ reset() {
92
+ this.setState({ count: 0 });
93
+ }
94
+ }
95
+
96
+ // Route requests to agents
97
+ export default {
98
+ async fetch(request: Request, env: Env, ctx: ExecutionContext) {
99
+ return (
100
+ (await routeAgentRequest(request, env)) ??
101
+ new Response("Not found", { status: 404 })
102
+ );
103
+ }
104
+ };
105
+ ```
106
+
107
+ Update `wrangler.jsonc` to register the agent:
108
+
109
+ ```jsonc
110
+ {
111
+ "name": "my-agent",
112
+ "main": "src/server.ts",
113
+ "compatibility_date": "2025-01-01",
114
+ "compatibility_flags": ["nodejs_compat"],
115
+ "durable_objects": {
116
+ "bindings": [
117
+ {
118
+ "name": "Counter",
119
+ "class_name": "Counter"
120
+ }
121
+ ]
122
+ },
123
+ "migrations": [
124
+ {
125
+ "tag": "v1",
126
+ "new_sqlite_classes": ["Counter"]
127
+ }
128
+ ]
129
+ }
130
+ ```
131
+
132
+ ---
133
+
134
+ ## Connect from React
135
+
136
+ Replace `src/client.tsx`:
137
+
138
+ ```tsx
139
+ import { useAgent } from "agents/react";
140
+
141
+ // Match your agent's state type
142
+ type CounterState = {
143
+ count: number;
144
+ };
145
+
146
+ export default function App() {
147
+ // Connect to the Counter agent
148
+ const agent = useAgent<CounterState>({
149
+ agent: "Counter"
150
+ });
151
+
152
+ return (
153
+ <div style={{ padding: "2rem", fontFamily: "system-ui" }}>
154
+ <h1>Counter Agent</h1>
155
+ <p style={{ fontSize: "3rem" }}>{agent.state?.count ?? 0}</p>
156
+ <div style={{ display: "flex", gap: "1rem" }}>
157
+ <button onClick={() => agent.stub.decrement()}>-</button>
158
+ <button onClick={() => agent.stub.reset()}>Reset</button>
159
+ <button onClick={() => agent.stub.increment()}>+</button>
160
+ </div>
161
+ </div>
162
+ );
163
+ }
164
+ ```
165
+
166
+ Key points:
167
+
168
+ - **`useAgent`** connects to your agent via WebSocket
169
+ - **`agent.state`** is reactive — the component re-renders when state changes
170
+ - **`agent.stub.methodName()`** calls methods marked with `@callable()` on your agent
171
+
172
+ ---
173
+
174
+ ## What Just Happened?
175
+
176
+ When you clicked the button:
177
+
178
+ 1. **Client** called `agent.stub.increment()` over WebSocket
179
+ 2. **Agent** ran `increment()`, updated state with `setState()`
180
+ 3. **State** persisted to SQLite automatically
181
+ 4. **Broadcast** sent to all connected clients
182
+ 5. **React** re-rendered with updated `agent.state`
183
+
184
+ ```
185
+ ┌─────────────┐ ┌─────────────┐
186
+ │ Browser │◄───────►│ Agent │
187
+ │ (React) │ WS │ (Counter) │
188
+ └─────────────┘ └──────┬──────┘
189
+
190
+ ┌──────▼──────┐
191
+ │ SQLite │
192
+ │ (State) │
193
+ └─────────────┘
194
+ ```
195
+
196
+ ### Key Concepts
197
+
198
+ | Concept | What it means |
199
+ | -------------------- | ------------------------------------------------------------------------------------------- |
200
+ | **Agent instance** | Each unique name gets its own agent. `Counter:user-123` is separate from `Counter:user-456` |
201
+ | **Persistent state** | State survives restarts, deploys, and hibernation. It's stored in SQLite |
202
+ | **Real-time sync** | All clients connected to the same agent receive state updates instantly |
203
+ | **Hibernation** | When no clients are connected, the agent hibernates (no cost). It wakes on the next request |
204
+
205
+ ---
206
+
207
+ ## Connect from Vanilla JS
208
+
209
+ If you're not using React:
210
+
211
+ ```typescript
212
+ import { AgentClient } from "agents/client";
213
+
214
+ const agent = new AgentClient({
215
+ agent: "Counter",
216
+ name: "my-counter", // optional, defaults to "default"
217
+ host: window.location.host
218
+ });
219
+
220
+ await agent.ready;
221
+
222
+ // Call methods
223
+ await agent.call("increment");
224
+ console.log("Current count:", agent.state?.count);
225
+
226
+ await agent.call("reset");
227
+ ```
228
+
229
+ ---
230
+
231
+ ## Deploy to Cloudflare
232
+
233
+ ```bash
234
+ npm run deploy
235
+ ```
236
+
237
+ Your agent is now live on Cloudflare's global network, running close to your users.
238
+
239
+ ---
240
+
241
+ ## Next Steps
242
+
243
+ Now that you have a working agent, explore these topics:
244
+
245
+ - **[State Management](./state.md)** - Deep dive into `setState()`, `initialState`, and `onStateChanged()`
246
+ - **[Client SDK](./client-sdk.md)** - Full `useAgent` and `AgentClient` API reference
247
+ - **[Scheduling](./scheduling.md)** - Run tasks on a delay, schedule, or cron
248
+ - **[Agent Class](./agent-class.md)** - Lifecycle methods, HTTP handlers, and WebSocket events
249
+
250
+ ### Common Patterns
251
+
252
+ | I want to... | Read... |
253
+ | ------------------------ | ---------------------------------------- |
254
+ | Add AI/LLM capabilities | [Chat Agents](./chat-agents.md) |
255
+ | Expose tools via MCP | [Creating MCP Servers](./mcp-servers.md) |
256
+ | Run background tasks | [Scheduling](./scheduling.md) |
257
+ | Handle emails | [Email Service](./email.md) |
258
+ | Use Cloudflare Workflows | [Workflows](./workflows.md) |
259
+
260
+ ---
261
+
262
+ ## Troubleshooting
263
+
264
+ ### "Agent not found" / 404 errors
265
+
266
+ Make sure:
267
+
268
+ 1. Agent class is exported from your server file
269
+ 2. `wrangler.jsonc` has the binding and migration
270
+ 3. Agent name in client matches the class name (case-insensitive)
271
+
272
+ ### State not syncing
273
+
274
+ Check that:
275
+
276
+ 1. You're calling `this.setState()`, not mutating `this.state` directly
277
+ 2. Your agent has `initialState` defined (state is only sent on connect if the agent has state)
278
+ 3. WebSocket connection is established (check browser dev tools)
279
+
280
+ ### "Method X is not callable" errors
281
+
282
+ Make sure your methods are decorated with `@callable()`:
283
+
284
+ ```typescript
285
+ import { callable } from "agents";
286
+
287
+ @callable()
288
+ increment() {
289
+ // ...
290
+ }
291
+ ```
292
+
293
+ ### Type errors with `agent.stub`
294
+
295
+ Add the agent type parameter:
296
+
297
+ ```typescript
298
+ const agent = useAgent<Counter, CounterState>({
299
+ agent: "Counter",
300
+ onStateUpdate: (state) => setCount(state.count)
301
+ });
302
+
303
+ // Now agent.stub is fully typed
304
+ agent.stub.increment(); // ✓ TypeScript knows this method exists
305
+ ```