Cloudflare Agents SDK
Your knowledge of the Agents SDK may be outdated. Prefer retrieval over pre-training for any Agents SDK task.
Retrieval Sources
Cloudflare docs: https://developers.cloudflare.com/agents/
| Topic |
Docs URL |
Use for |
| Getting started |
Quick start |
First agent, project setup |
| Adding to existing project |
Add to existing project |
Install into existing Workers app |
| Configuration |
Configuration |
wrangler.jsonc, bindings, assets, deployment |
| Agent class |
Agents API |
Agent lifecycle, patterns, pitfalls |
| State |
Store and sync state |
setState, validateStateChange, persistence |
| Routing |
Routing |
URL patterns, routeAgentRequest |
| Callable methods |
Callable methods |
@callable, RPC, streaming, timeouts |
| Scheduling |
Schedule tasks |
schedule(), scheduleEvery(), cron |
| Workflows |
Run workflows |
AgentWorkflow, durable multi-step tasks |
| HTTP/WebSockets |
WebSockets |
Lifecycle hooks, hibernation |
| Chat agents |
Chat agents |
AIChatAgent, streaming, tools, persistence |
| Client SDK |
Client SDK |
useAgent, AgentClient, state, RPC, HTTP |
| Client tools |
Client tools |
Client-side tools, autoContinueAfterToolResult |
| Server-driven messages |
Autonomous responses |
saveMessages, waitUntilStable, server-initiated turns |
| Resumable streaming |
Chat agents |
Stream recovery on disconnect |
| Email |
Email |
Email routing, secure reply resolver |
| MCP client |
MCP client |
Connecting to MCP servers |
| MCP server |
MCP server |
Building MCP servers with createMcpHandler |
| MCP transports |
MCP transports |
Streamable HTTP, SSE, RPC transport options |
| Securing MCP servers |
Securing MCP |
OAuth, proxy MCP, hardening |
| Human-in-the-loop |
Human-in-the-loop |
Workflow approvals, elicitation, timeout handling |
| Durable execution |
Durable execution |
runFiber(), stash(), surviving DO eviction |
| Queue |
Queue |
Built-in FIFO queue, queue() |
| Retries |
Retries |
this.retry(), backoff/jitter |
| Observability |
Observability |
Diagnostics-channel events |
| Push notifications |
Push notifications |
Web Push + VAPID from agents |
| Webhooks |
Webhooks |
Receiving external webhooks |
| Cross-domain auth |
Cross-domain auth |
WebSocket auth, tokens, CORS |
| Readonly connections |
Readonly |
shouldConnectionBeReadonly |
| Voice |
Voice |
Experimental STT/TTS, withVoice |
| Browse the web |
Browser tools |
Experimental CDP browser automation |
| Think |
Think |
Experimental higher-level chat agent class |
| Migrations |
AI SDK v5, AI SDK v6 |
Upgrading @cloudflare/ai-chat |
Capabilities
The Agents SDK provides:
- Persistent state — SQLite-backed, auto-synced to clients via
setState
- Callable RPC —
@callable() methods invoked over WebSocket
- Scheduling — One-time, recurring (
scheduleEvery), and cron tasks
- Workflows — Durable multi-step background processing via
AgentWorkflow
- Durable execution —
runFiber() / stash() for work that survives DO eviction
- Queue — Built-in FIFO queue with retries via
queue()
- Retries —
this.retry() with exponential backoff and jitter
- MCP integration — Connect to MCP servers or build your own with
createMcpHandler
- Email handling — Receive and reply to emails with secure routing
- Streaming chat —
AIChatAgent with resumable streams, message persistence, tools
- Server-driven messages —
saveMessages, waitUntilStable for proactive agent turns
- React hooks —
useAgent, useAgentChat for client apps
- Observability —
diagnostics_channel events for state, RPC, schedule, lifecycle
- Push notifications — Web Push + VAPID delivery from agents
- Webhooks — Receive and verify external webhooks
- Voice (experimental) — STT/TTS via
@cloudflare/voice
- Browser tools (experimental) — CDP-powered browsing via
agents/browser
- Think (experimental) — Higher-level chat agent via
@cloudflare/think
FIRST: Verify Installation
npm ls agents # Should show agents package
If not installed:
npm install agents
For chat agents:
npm install agents @cloudflare/ai-chat ai @ai-sdk/react
Wrangler Configuration
{
"compatibility_flags": ["nodejs_compat"],
"durable_objects": {
"bindings": [{ "name": "MyAgent", "class_name": "MyAgent" }]
},
"migrations": [{ "tag": "v1", "new_sqlite_classes": ["MyAgent"] }]
}
Gotchas:
- Do NOT enable
experimentalDecorators in tsconfig (breaks @callable)
- Never edit old migrations — always add new tags
- Each agent class needs its own DO binding + migration entry
- Add
"ai": { "binding": "AI" } for Workers AI
Agent Class
import { Agent, routeAgentRequest, callable } from "agents";
type State = { count: number };
export class Counter extends Agent<Env, State> {
initialState = { count: 0 };
validateStateChange(nextState: State, source: Connection | "server") {
if (nextState.count < 0) throw new Error("Count cannot be negative");
}
onStateUpdate(state: State, source: Connection | "server") {
console.log("State updated:", state);
}
@callable()
increment() {
this.setState({ count: this.state.count + 1 });
return this.state.count;
}
}
export default {
fetch: (req, env) => routeAgentRequest(req, env) ?? new Response("Not found", { status: 404 })
};
Routing
Requests route to /agents/{agent-name}/{instance-name}:
| Class |
URL |
Counter |
/agents/counter/user-123 |
ChatRoom |
/agents/chat-room/lobby |
Client: useAgent({ agent: "Counter", name: "user-123" })
Custom routing: use getAgentByName(env.MyAgent, "instance-id") then agent.fetch(request).
Core APIs
| Task |
API |
| Read state |
this.state.count |
| Write state |
this.setState({ count: 1 }) |
| SQL query |
this.sql`SELECT * FROM users WHERE id = ${id}` |
| Schedule (delay) |
await this.schedule(60, "task", payload) |
| Schedule (cron) |
await this.schedule("0 * * * *", "task", payload) |
| Schedule (interval) |
await this.scheduleEvery(30, "poll") |
| RPC method |
@callable() myMethod() { ... } |
| Streaming RPC |
@callable({ streaming: true }) stream(res) { ... } |
| Start workflow |
await this.runWorkflow("ProcessingWorkflow", params) |
| Durable fiber |
await this.runFiber("name", async (ctx) => { ... }) |
| Enqueue work |
this.queue("handler", payload) |
| Retry with backoff |
await this.retry(fn, { maxAttempts: 5 }) |
| Broadcast to clients |
this.broadcast(message) |
| Get connections |
this.getConnections(tag?) |
React Client
Read client-sdk.md for client selection and current connection examples. For chat UI and tools, also read streaming-chat.md.
References
Core
- references/state-scheduling.md — State persistence, scheduling, SQL
- references/callable.md — RPC methods, streaming, timeouts
- references/routing.md — URL patterns, custom routing,
getAgentByName
- references/configuration.md — Wrangler config, bindings, Vite setup
Chat & Streaming
- references/streaming-chat.md — AIChatAgent, resumable streams, tools
- references/client-sdk.md —
useAgent, useAgentChat, AgentClient
- references/server-driven-messages.md — Trigger patterns,
saveMessages
- references/human-in-the-loop.md — Approval flows,
needsApproval
Background Processing
- references/workflows.md — Durable Workflows integration
- references/durable-execution.md —
runFiber, stash, surviving eviction
- references/queue-retries.md — Built-in queue, retry with backoff
Integrations
- references/mcp.md — MCP client and server, transports, securing
- references/email.md — Email routing and handling
- references/webhooks-push.md — Webhooks, push notifications
- references/observability.md — Diagnostics-channel events
Experimental
- references/think.md —
@cloudflare/think higher-level chat agent
- references/voice.md —
@cloudflare/voice STT/TTS
- references/codemode.md — Code Mode for tool orchestration
- references/browse-the-web.md — CDP browser tools
1---2name: agents-sdk3description: Build, debug, or review Cloudflare Agents SDK applications using the agents package.4---56# Cloudflare Agents SDK78Your knowledge of the Agents SDK may be outdated. **Prefer retrieval over pre-training** for any Agents SDK task.910## Retrieval Sources1112Cloudflare docs: https://developers.cloudflare.com/agents/1314| Topic | Docs URL | Use for |15|-------|----------|---------|16| Getting started | [Quick start](https://developers.cloudflare.com/agents/getting-started/quick-start/) | First agent, project setup |17| Adding to existing project | [Add to existing project](https://developers.cloudflare.com/agents/getting-started/add-to-existing-project/) | Install into existing Workers app |18| Configuration | [Configuration](https://developers.cloudflare.com/agents/api-reference/configuration/) | `wrangler.jsonc`, bindings, assets, deployment |19| Agent class | [Agents API](https://developers.cloudflare.com/agents/api-reference/agents-api/) | Agent lifecycle, patterns, pitfalls |20| State | [Store and sync state](https://developers.cloudflare.com/agents/api-reference/store-and-sync-state/) | `setState`, `validateStateChange`, persistence |21| Routing | [Routing](https://developers.cloudflare.com/agents/api-reference/routing/) | URL patterns, `routeAgentRequest` |22| Callable methods | [Callable methods](https://developers.cloudflare.com/agents/api-reference/callable-methods/) | `@callable`, RPC, streaming, timeouts |23| Scheduling | [Schedule tasks](https://developers.cloudflare.com/agents/api-reference/schedule-tasks/) | `schedule()`, `scheduleEvery()`, cron |24| Workflows | [Run workflows](https://developers.cloudflare.com/agents/api-reference/run-workflows/) | `AgentWorkflow`, durable multi-step tasks |25| HTTP/WebSockets | [WebSockets](https://developers.cloudflare.com/agents/api-reference/websockets/) | Lifecycle hooks, hibernation |26| Chat agents | [Chat agents](https://developers.cloudflare.com/agents/communication-channels/chat/chat-agents/) | `AIChatAgent`, streaming, tools, persistence |27| Client SDK | [Client SDK](https://developers.cloudflare.com/agents/communication-channels/chat/client-sdk/) | `useAgent`, `AgentClient`, state, RPC, HTTP |28| Client tools | [Client tools](https://developers.cloudflare.com/agents/harnesses/think/client-tools/) | Client-side tools, `autoContinueAfterToolResult` |29| Server-driven messages | [Autonomous responses](https://developers.cloudflare.com/agents/communication-channels/chat/autonomous-responses/) | `saveMessages`, `waitUntilStable`, server-initiated turns |30| Resumable streaming | [Chat agents](https://developers.cloudflare.com/agents/communication-channels/chat/chat-agents/#resumable-streaming) | Stream recovery on disconnect |31| Email | [Email](https://developers.cloudflare.com/agents/api-reference/email/) | Email routing, secure reply resolver |32| MCP client | [MCP client](https://developers.cloudflare.com/agents/model-context-protocol/apis/client-api/) | Connecting to MCP servers |33| MCP server | [MCP server](https://developers.cloudflare.com/agents/model-context-protocol/apis/handler-api/) | Building MCP servers with `createMcpHandler` |34| MCP transports | [MCP transports](https://developers.cloudflare.com/agents/model-context-protocol/protocol/transport/) | Streamable HTTP, SSE, RPC transport options |35| Securing MCP servers | [Securing MCP](https://developers.cloudflare.com/agents/model-context-protocol/guides/securing-mcp-server/) | OAuth, proxy MCP, hardening |36| Human-in-the-loop | [Human-in-the-loop](https://developers.cloudflare.com/agents/concepts/agentic-patterns/human-in-the-loop/) | Workflow approvals, elicitation, timeout handling |37| Durable execution | [Durable execution](https://developers.cloudflare.com/agents/api-reference/durable-execution/) | `runFiber()`, `stash()`, surviving DO eviction |38| Queue | [Queue](https://developers.cloudflare.com/agents/api-reference/queue-tasks/) | Built-in FIFO queue, `queue()` |39| Retries | [Retries](https://developers.cloudflare.com/agents/api-reference/retries/) | `this.retry()`, backoff/jitter |40| Observability | [Observability](https://developers.cloudflare.com/agents/api-reference/observability/) | Diagnostics-channel events |41| Push notifications | [Push notifications](https://developers.cloudflare.com/agents/communication-channels/webhooks/push-notifications/) | Web Push + VAPID from agents |42| Webhooks | [Webhooks](https://developers.cloudflare.com/agents/communication-channels/webhooks/) | Receiving external webhooks |43| Cross-domain auth | [Cross-domain auth](https://developers.cloudflare.com/agents/runtime/operations/cross-domain-authentication/) | WebSocket auth, tokens, CORS |44| Readonly connections | [Readonly](https://developers.cloudflare.com/agents/api-reference/readonly-connections/) | `shouldConnectionBeReadonly` |45| Voice | [Voice](https://developers.cloudflare.com/agents/api-reference/voice/) | Experimental STT/TTS, `withVoice` |46| Browse the web | [Browser tools](https://developers.cloudflare.com/agents/api-reference/browse-the-web/) | Experimental CDP browser automation |47| Think | [Think](https://developers.cloudflare.com/agents/api-reference/think/) | Experimental higher-level chat agent class |48| Migrations | [AI SDK v5](https://github.com/cloudflare/agents/blob/main/docs/agents/migration-to-ai-sdk-v5.md), [AI SDK v6](https://github.com/cloudflare/agents/blob/main/docs/agents/migration-to-ai-sdk-v6.md) | Upgrading `@cloudflare/ai-chat` |4950## Capabilities5152The Agents SDK provides:5354- **Persistent state** — SQLite-backed, auto-synced to clients via `setState`55- **Callable RPC** — `@callable()` methods invoked over WebSocket56- **Scheduling** — One-time, recurring (`scheduleEvery`), and cron tasks57- **Workflows** — Durable multi-step background processing via `AgentWorkflow`58- **Durable execution** — `runFiber()` / `stash()` for work that survives DO eviction59- **Queue** — Built-in FIFO queue with retries via `queue()`60- **Retries** — `this.retry()` with exponential backoff and jitter61- **MCP integration** — Connect to MCP servers or build your own with `createMcpHandler`62- **Email handling** — Receive and reply to emails with secure routing63- **Streaming chat** — `AIChatAgent` with resumable streams, message persistence, tools64- **Server-driven messages** — `saveMessages`, `waitUntilStable` for proactive agent turns65- **React hooks** — `useAgent`, `useAgentChat` for client apps66- **Observability** — `diagnostics_channel` events for state, RPC, schedule, lifecycle67- **Push notifications** — Web Push + VAPID delivery from agents68- **Webhooks** — Receive and verify external webhooks69- **Voice** (experimental) — STT/TTS via `@cloudflare/voice`70- **Browser tools** (experimental) — CDP-powered browsing via `agents/browser`71- **Think** (experimental) — Higher-level chat agent via `@cloudflare/think`7273## FIRST: Verify Installation7475```bash76npm ls agents # Should show agents package77```7879If not installed:80```bash81npm install agents82```8384For chat agents:85```bash86npm install agents @cloudflare/ai-chat ai @ai-sdk/react87```8889## Wrangler Configuration9091```jsonc92{93 "compatibility_flags": ["nodejs_compat"],94 "durable_objects": {95 "bindings": [{ "name": "MyAgent", "class_name": "MyAgent" }]96 },97 "migrations": [{ "tag": "v1", "new_sqlite_classes": ["MyAgent"] }]98}99```100101**Gotchas:**102- Do NOT enable `experimentalDecorators` in tsconfig (breaks `@callable`)103- Never edit old migrations — always add new tags104- Each agent class needs its own DO binding + migration entry105- Add `"ai": { "binding": "AI" }` for Workers AI106107## Agent Class108109```typescript110import { Agent, routeAgentRequest, callable } from "agents";111112type State = { count: number };113114export class Counter extends Agent<Env, State> {115 initialState = { count: 0 };116117 validateStateChange(nextState: State, source: Connection | "server") {118 if (nextState.count < 0) throw new Error("Count cannot be negative");119 }120121 onStateUpdate(state: State, source: Connection | "server") {122 console.log("State updated:", state);123 }124125 @callable()126 increment() {127 this.setState({ count: this.state.count + 1 });128 return this.state.count;129 }130}131132export default {133 fetch: (req, env) => routeAgentRequest(req, env) ?? new Response("Not found", { status: 404 })134};135```136137## Routing138139Requests route to `/agents/{agent-name}/{instance-name}`:140141| Class | URL |142|-------|-----|143| `Counter` | `/agents/counter/user-123` |144| `ChatRoom` | `/agents/chat-room/lobby` |145146Client: `useAgent({ agent: "Counter", name: "user-123" })`147148Custom routing: use `getAgentByName(env.MyAgent, "instance-id")` then `agent.fetch(request)`.149150## Core APIs151152| Task | API |153|------|-----|154| Read state | `this.state.count` |155| Write state | `this.setState({ count: 1 })` |156| SQL query | `` this.sql`SELECT * FROM users WHERE id = ${id}` `` |157| Schedule (delay) | `await this.schedule(60, "task", payload)` |158| Schedule (cron) | `await this.schedule("0 * * * *", "task", payload)` |159| Schedule (interval) | `await this.scheduleEvery(30, "poll")` |160| RPC method | `@callable() myMethod() { ... }` |161| Streaming RPC | `@callable({ streaming: true }) stream(res) { ... }` |162| Start workflow | `await this.runWorkflow("ProcessingWorkflow", params)` |163| Durable fiber | `await this.runFiber("name", async (ctx) => { ... })` |164| Enqueue work | `this.queue("handler", payload)` |165| Retry with backoff | `await this.retry(fn, { maxAttempts: 5 })` |166| Broadcast to clients | `this.broadcast(message)` |167| Get connections | `this.getConnections(tag?)` |168169## React Client170171Read [client-sdk.md](references/client-sdk.md) for client selection and current connection examples. For chat UI and tools, also read [streaming-chat.md](references/streaming-chat.md).172173## References174175### Core176- **[references/state-scheduling.md](references/state-scheduling.md)** — State persistence, scheduling, SQL177- **[references/callable.md](references/callable.md)** — RPC methods, streaming, timeouts178- **[references/routing.md](references/routing.md)** — URL patterns, custom routing, `getAgentByName`179- **[references/configuration.md](references/configuration.md)** — Wrangler config, bindings, Vite setup180181### Chat & Streaming182- **[references/streaming-chat.md](references/streaming-chat.md)** — AIChatAgent, resumable streams, tools183- **[references/client-sdk.md](references/client-sdk.md)** — `useAgent`, `useAgentChat`, `AgentClient`184- **[references/server-driven-messages.md](references/server-driven-messages.md)** — Trigger patterns, `saveMessages`185- **[references/human-in-the-loop.md](references/human-in-the-loop.md)** — Approval flows, `needsApproval`186187### Background Processing188- **[references/workflows.md](references/workflows.md)** — Durable Workflows integration189- **[references/durable-execution.md](references/durable-execution.md)** — `runFiber`, `stash`, surviving eviction190- **[references/queue-retries.md](references/queue-retries.md)** — Built-in queue, retry with backoff191192### Integrations193- **[references/mcp.md](references/mcp.md)** — MCP client and server, transports, securing194- **[references/email.md](references/email.md)** — Email routing and handling195- **[references/webhooks-push.md](references/webhooks-push.md)** — Webhooks, push notifications196- **[references/observability.md](references/observability.md)** — Diagnostics-channel events197198### Experimental199- **[references/think.md](references/think.md)** — `@cloudflare/think` higher-level chat agent200- **[references/voice.md](references/voice.md)** — `@cloudflare/voice` STT/TTS201- **[references/codemode.md](references/codemode.md)** — Code Mode for tool orchestration202- **[references/browse-the-web.md](references/browse-the-web.md)** — CDP browser tools