You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The core of the `agents` library is the exported `Agent` class. Following the pattern from [Durable Objects](/durable-objects/api/), the main API for developers is to extend the `Agent` class so those classes inherit all the built-in features. While this effectively is a supercharged primitive that allows developers to only write the logic they need in their agents, it obscures the inner workings.
11
11
@@ -25,14 +25,10 @@ This won't cover Durable Objects in detail, but it's good to know what primitive
25
25
26
26
### constructor
27
27
28
-
<TypeScriptExample>
29
-
30
28
```ts
31
29
constructor(ctx: DurableObjectState, env: Env) {}
32
30
```
33
31
34
-
</TypeScriptExample>
35
-
36
32
The Workers runtime always calls the constructor to handle things internally. This means 2 things:
37
33
38
34
1. While the constructor is called every time the DO is initialized, the signature is fixed. Developers **can't add or update parameters from the constructor**.
@@ -42,8 +38,6 @@ The Workers runtime always calls the constructor to handle things internally. Th
42
38
43
39
By writing a Durable Object class which inherits from the built-in type `DurableObject`, public methods are exposed as RPC methods, which developers can call using a [DurableObjectStub from a Worker](/durable-objects/best-practices/create-durable-object-stubs-and-send-requests/#invoking-methods-on-a-durable-object).
44
40
45
-
<TypeScriptExample>
46
-
47
41
```ts
48
42
// This instance could've been active, hibernated,
49
43
// not initialized or maybe had never even been created!
Durable Objects can take a `Request` from a Worker and send a `Response` back. This can **only** be done through the [`fetch`](/durable-objects/best-practices/create-durable-object-stubs-and-send-requests/#invoking-the-fetch-handler) method (which the developer must implement).
@@ -66,8 +58,6 @@ Durable Objects include first-class support for [WebSockets](/durable-objects/be
66
58
67
59
The base class provides `webSocketMessage(ws, message)`, `webSocketClose(ws, code, reason, wasClean)` and `webSocketError(ws , error)` ([API](/workers/runtime-apis/websockets)).
68
60
69
-
<TypeScriptExample>
70
-
71
61
```ts
72
62
exportclassMyDurableObjectextendsDurableObject {
73
63
async fetch(request) {
@@ -91,8 +81,6 @@ export class MyDurableObject extends DurableObject {
91
81
}
92
82
```
93
83
94
-
</TypeScriptExample>
95
-
96
84
### alarm()
97
85
98
86
HTTP and RPC requests are not the only entrypoints for a DO. Alarms allow developers to schedule tasks to run at a later time. Whenever the runtime knows an alarm is due, it will call the `alarm()` method, which is left to the developer to implement.
@@ -107,8 +95,6 @@ The base `DurableObject` class sets the [DurableObjectState](/durable-objects/ap
107
95
108
96
[DurableObjectStorage](/durable-objects/api/sqlite-storage-api/) is the main interface with the DO's persistence mechanisms, which include both a KV and SQLITE **synchronous** APIs.
109
97
110
-
<TypeScriptExample>
111
-
112
98
```ts
113
99
const sql =this.ctx.storage.sql;
114
100
const kv =this.ctx.storage.kv;
@@ -120,8 +106,6 @@ const rows = sql.exec("SELECT * FROM contacts WHERE country = ?", "US");
120
106
const token =kv.get("someToken");
121
107
```
122
108
123
-
</TypeScriptExample>
124
-
125
109
### this.ctx.env
126
110
127
111
Lastly, it's worth mentioning that the DO also has the Worker `Env` in `this.env`. Read more about [bindings](/workers/runtime-apis/bindings).
@@ -138,8 +122,6 @@ An important note is that `Server` **does NOT make use any of the DO storage** s
138
122
139
123
Compare this to the DO addressing [example above](#rpc).
You can have a look at [the implementation](https://github.com/cloudflare/partykit/blob/main/packages/partyserver/src/index.ts#L122) if you're interested.
172
148
173
149
### onStart
174
150
175
151
The extra plumbing that `Server` includes on addressing allows it to expose an `onStart` callback that is **executed every time the DO starts up** (the DO was evicted, hibernated or never created at all) and **before any `fetch` or RPC**.
176
152
177
-
<TypeScriptExample>
178
-
179
153
```ts
180
154
classMyServerextendsServer {
181
155
onStart() {
@@ -187,14 +161,10 @@ class MyServer extends Server {
187
161
}
188
162
```
189
163
190
-
</TypeScriptExample>
191
-
192
164
### onRequest and onConnect
193
165
194
166
`Server` already implements `fetch` for the underlying Durable Object and exposes 2 different callbacks that developers can make use of, `onRequest` and `onConnect` for HTTP requests and incoming WS connections, respectively (**WebSocket connections are accepted by default**).
195
167
196
-
<TypeScriptExample>
197
-
198
168
```ts
199
169
classMyServerextendsServer {
200
170
async onRequest(request:Request) {
@@ -213,8 +183,6 @@ class MyServer extends Server {
213
183
}
214
184
```
215
185
216
-
</TypeScriptExample>
217
-
218
186
### WebSockets
219
187
220
188
Just as `onConnect` is the callback for every new connection, `Server` also provides wrappers on top of the default callbacks from the `DurableObject` class: `onMessage`, `onClose` and `onError`.
@@ -237,8 +205,6 @@ One of the core features of `Agent` is **automatic state persistence**. Develope
237
205
238
206
There's also `this.onStateUpdate` that you can override to react to state changes.
239
207
240
-
<TypeScriptExample>
241
-
242
208
```ts
243
209
classMyAgentextendsAgent<Env, { count:number }> {
244
210
initialState = { count: 0 };
@@ -253,16 +219,12 @@ class MyAgent extends Agent<Env, { count: number }> {
253
219
}
254
220
```
255
221
256
-
</TypeScriptExample>
257
-
258
222
State is stored in the `cf_agents_state` SQL table. State messages are sent with `type: "cf_agent_state"` (both from the client and the server). Since the `agents` provides [JS and React clients](/agents/api-reference/store-and-sync-state/#synchronizing-state), real-time state updates are available out of the box.
259
223
260
224
### this.sql
261
225
262
226
The Agent provides a convenient `sql` template tag for executing queries against the Durable Object's SQL storage. It constructs parameterized queries and executes them. This uses the **synchronous** SQL API from `this.ctx.storage.sql`.
263
227
264
-
<TypeScriptExample>
265
-
266
228
```ts
267
229
classMyAgentextendsAgent {
268
230
onStart() {
@@ -285,14 +247,10 @@ class MyAgent extends Agent {
285
247
}
286
248
```
287
249
288
-
</TypeScriptExample>
289
-
290
250
### RPC and Callable Methods
291
251
292
252
`agents` take Durable Objects RPC one step forward by implementing RPC through WebSockets, so clients can also call methods on the Agent directly. To make a method callable, developers can use the `@callable` decorator. Methods can return a serializable value or a stream (when using `@callable({ stream: true })`).
293
253
294
-
<TypeScriptExample>
295
-
296
254
```ts
297
255
classMyAgentextendsAgent {
298
256
@callable({ description: "Add two numbers" })
@@ -302,8 +260,6 @@ class MyAgent extends Agent {
302
260
}
303
261
```
304
262
305
-
</TypeScriptExample>
306
-
307
263
Clients can invoke this method by sending a WebSocket message:
308
264
309
265
```json
@@ -317,22 +273,16 @@ Clients can invoke this method by sending a WebSocket message:
317
273
318
274
For example, with the provided `React` client it's as easy as:
319
275
320
-
<TypeScriptExample>
321
-
322
276
```ts
323
277
const { stub } =useAgent({ name: "my-agent" });
324
278
const result =awaitstub.add(2, 3);
325
279
console.log(result); // 5
326
280
```
327
281
328
-
</TypeScriptExample>
329
-
330
282
### this.queue and friends
331
283
332
284
Agents include a built-in task queue for deferred execution. This is useful for offloading work or retrying operations. The available methods are `this.queue`, `this.dequeue`, `this.dequeueAll`, `this.dequeueAllByCallback`, `this.getQueue`, and `this.getQueues`.
333
285
334
-
<TypeScriptExample>
335
-
336
286
```ts
337
287
classMyAgentextendsAgent {
338
288
async onConnect() {
@@ -346,16 +296,12 @@ class MyAgent extends Agent {
346
296
}
347
297
```
348
298
349
-
</TypeScriptExample>
350
-
351
299
Tasks are stored in the `cf_agents_queues` SQL table and are automatically flushed in sequence. If a task succeeds, it's automatically dequeued.
352
300
353
301
### this.schedule and friends
354
302
355
303
Agents support scheduled execution of methods by wrapping the Durable Object's `alarm()`. The available methods are `this.schedule`, `this.getSchedule`, `this.getSchedules`, `this.cancelSchedule`. Schedules can be one-time, delayed, or recurring (using cron expressions).
356
304
357
-
<TypeScriptExample>
358
-
359
305
```ts
360
306
classMyAgentextendsAgent {
361
307
async onStart() {
@@ -385,16 +331,12 @@ class MyAgent extends Agent {
385
331
}
386
332
```
387
333
388
-
</TypeScriptExample>
389
-
390
334
Schedules are stored in the `cf_agents_schedules` SQL table. Cron schedules automatically reschedule themselves after execution, while one-time schedules are deleted.
391
335
392
336
### this.mcp and friends
393
337
394
338
`Agent` includes a multi-server MCP client. This enables your Agent to interact with external services that expose MCP interfaces. The MCP client is documented in detail at [MCP Client API](/agents/model-context-protocol/mcp-client-api/).
395
339
396
-
<TypeScriptExample>
397
-
398
340
```ts
399
341
classMyAgentextendsAgent {
400
342
async onConnect() {
@@ -409,14 +351,10 @@ class MyAgent extends Agent {
409
351
}
410
352
```
411
353
412
-
</TypeScriptExample>
413
-
414
354
### Email Handling
415
355
416
356
Agents can receive and reply to emails using Cloudflare's [Email Routing](/email-routing/email-workers/).
417
357
418
-
<TypeScriptExample>
419
-
420
358
```ts
421
359
classMyAgentextendsAgent {
422
360
async onEmail(email:AgentEmail) {
@@ -437,12 +375,8 @@ class MyAgent extends Agent {
437
375
}
438
376
```
439
377
440
-
</TypeScriptExample>
441
-
442
378
To route emails to your Agent, use `routeAgentEmail` in your Worker's email handler:
443
379
444
-
<TypeScriptExample>
445
-
446
380
```ts
447
381
exportdefault {
448
382
async email(message, env, ctx) {
@@ -453,14 +387,10 @@ export default {
453
387
};
454
388
```
455
389
456
-
</TypeScriptExample>
457
-
458
390
### Context Management
459
391
460
392
`agents` wraps all your methods with an `AsyncLocalStorage` to maintain context throughout the request lifecycle. This allows you to access the current agent, connection, request, or email (depending of what event is being handled) from anywhere in your code:
461
393
462
-
<TypeScriptExample>
463
-
464
394
```ts
465
395
import { getCurrentAgent } from"agents";
466
396
@@ -477,14 +407,10 @@ function someUtilityFunction() {
477
407
}
478
408
```
479
409
480
-
</TypeScriptExample>
481
-
482
410
### this.onError
483
411
484
412
`Agent` extends `Server`'s `onError` so it can be used to handle errors that are not necessarily WebSocket errors. It is called with a `Connection` or `unknown` error.
@@ -502,14 +428,10 @@ class MyAgent extends Agent {
502
428
}
503
429
```
504
430
505
-
</TypeScriptExample>
506
-
507
431
### this.destroy
508
432
509
433
`destroy()` drops all tables, deletes alarms, clears storage, and aborts the context. The `this.abort` method that is called by `this.destroy` comes from `DurableObject` and ensures that the Agent is fully evicted. In order to do so, it throws an uncatchable error that will show up in your logs (read more at [abort()](/durable-objects/api/state/#abort)).
510
434
511
-
<TypeScriptExample>
512
-
513
435
```ts
514
436
classMyAgentextendsAgent {
515
437
async onStart() {
@@ -524,14 +446,10 @@ class MyAgent extends Agent {
524
446
}
525
447
```
526
448
527
-
</TypeScriptExample>
528
-
529
449
### Routing
530
450
531
451
The `Agent` class re-exports PartyKit's [addressing helpers](#addressing) as `getAgentByName` and `routeAgentRequest`.
0 commit comments