Cloudflare Agents SDK
Not to be confused with the OpenAI Agents SDK (Python-based agent orchestration). This skill covers Cloudflare's Agents SDK for building stateful agents on Workers.
Prefer retrieval over pre-training — the Agents SDK evolves rapidly. Current version: v0.14.0 (June 2, 2026).
Documentation
Fetch current docs from https://github.com/cloudflare/agents/tree/main/docs before implementing.
| Topic |
Doc |
Use for |
| Getting started |
docs/getting-started.md |
First agent, project setup |
| State |
docs/state.md |
setState, validateStateChange, persistence |
| Routing |
docs/routing.md |
URL patterns, routeAgentRequest, basePath |
| Callable methods |
docs/callable-methods.md |
@callable, RPC, streaming, timeouts |
| Scheduling |
docs/scheduling.md |
schedule(), scheduleEvery(), cron |
| Workflows |
docs/workflows.md |
AgentWorkflow, durable multi-step tasks |
| HTTP/WebSockets |
docs/http-websockets.md |
Lifecycle hooks, hibernation |
| Email |
docs/email.md |
Email routing, secure reply resolver |
| MCP client |
docs/mcp-client.md |
Connecting to MCP servers |
| MCP server |
docs/mcp-servers.md |
Building MCP servers with McpAgent |
| Client SDK |
docs/client-sdk.md |
useAgent, useAgentChat, React hooks |
| Human-in-the-loop |
docs/human-in-the-loop.md |
Approval flows, pausing workflows |
| Resumable streaming |
docs/resumable-streaming.md |
Stream recovery on disconnect |
Cloudflare docs: https://developers.cloudflare.com/agents/
Capabilities
The Agents SDK provides:
- Persistent state - SQLite-backed, auto-synced to clients
- Callable RPC -
@callable() methods invoked over WebSocket
- Scheduling - One-time, recurring (
scheduleEvery), cron, and declarative scheduled tasks (v0.14+)
- Workflows - Durable multi-step background processing via
AgentWorkflow, with reasoning steps (v0.14+)
- MCP integration - Connect to MCP servers or build your own with
McpAgent
- Email handling - Receive and reply to emails with secure routing
- Streaming chat -
AIChatAgent with resumable streams and hardened recovery (v0.14+)
- Agent Skills - Modular, composable skill definitions (v0.14+)
- Chat Messengers - Direct Telegram integration (v0.14+)
- React hooks -
useAgent, useAgentChat for client apps
FIRST: Verify Installation
npm ls agents # Should show agents package
If not installed:
npm install agents
Wrangler Configuration
{
"durable_objects": {
"bindings": [{ "name": "MyAgent", "class_name": "MyAgent" }]
},
"migrations": [{ "tag": "v1", "new_sqlite_classes": ["MyAgent"] }]
}
Agent Class
import { Agent, routeAgentRequest, callable } from "agents";
type State = { count: number };
export class Counter extends Agent<Env, State> {
initialState = { count: 0 };
// Validation hook - runs before state persists (sync, throwing rejects the update)
validateStateChange(nextState: State, source: Connection | "server") {
if (nextState.count < 0) throw new Error("Count cannot be negative");
}
// Notification hook - runs after state persists (async, non-blocking)
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" })
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) |
React Client
import { useAgent } from "agents/react";
function App() {
const [state, setLocalState] = useState({ count: 0 });
const agent = useAgent({
agent: "Counter",
name: "my-instance",
onStateUpdate: (newState) => setLocalState(newState),
onIdentity: (name, agentType) => console.log(`Connected to ${name}`)
});
return (
<button => agent.setState({ count: state.count + 1 })}>
Count: {state.count}
</button>
);
}
References
- references/workflows.md - Durable Workflows integration
- references/callable.md - RPC methods, streaming, timeouts
- references/state-scheduling.md - State persistence, scheduling
- references/streaming-chat.md - AIChatAgent, resumable streams
- references/mcp.md - MCP server integration
- references/email.md - Email routing and handling
- references/codemode.md - Code Mode (experimental)
1---2name: agents-sdk3description: Build AI agents on Cloudflare Workers using the Agents SDK. Load when creating stateful agents, durable workflows, real-time WebSocket apps, scheduled tasks, MCP servers, or chat applications. Covers Agent class, state management, callable RPC, Workflows integration, and React hooks.4---56# Cloudflare Agents SDK78> **Not to be confused with** the [OpenAI Agents SDK](https://github.com/openai/openai-agents-python) (Python-based agent orchestration). This skill covers **Cloudflare's** Agents SDK for building stateful agents on Workers.910Prefer retrieval over pre-training — the Agents SDK evolves rapidly. **Current version: v0.14.0** (June 2, 2026).1112## Documentation1314Fetch current docs from `https://github.com/cloudflare/agents/tree/main/docs` before implementing.1516| Topic | Doc | Use for |17|-------|-----|---------|18| Getting started | `docs/getting-started.md` | First agent, project setup |19| State | `docs/state.md` | `setState`, `validateStateChange`, persistence |20| Routing | `docs/routing.md` | URL patterns, `routeAgentRequest`, `basePath` |21| Callable methods | `docs/callable-methods.md` | `@callable`, RPC, streaming, timeouts |22| Scheduling | `docs/scheduling.md` | `schedule()`, `scheduleEvery()`, cron |23| Workflows | `docs/workflows.md` | `AgentWorkflow`, durable multi-step tasks |24| HTTP/WebSockets | `docs/http-websockets.md` | Lifecycle hooks, hibernation |25| Email | `docs/email.md` | Email routing, secure reply resolver |26| MCP client | `docs/mcp-client.md` | Connecting to MCP servers |27| MCP server | `docs/mcp-servers.md` | Building MCP servers with `McpAgent` |28| Client SDK | `docs/client-sdk.md` | `useAgent`, `useAgentChat`, React hooks |29| Human-in-the-loop | `docs/human-in-the-loop.md` | Approval flows, pausing workflows |30| Resumable streaming | `docs/resumable-streaming.md` | Stream recovery on disconnect |3132Cloudflare docs: https://developers.cloudflare.com/agents/3334## Capabilities3536The Agents SDK provides:3738- **Persistent state** - SQLite-backed, auto-synced to clients39- **Callable RPC** - `@callable()` methods invoked over WebSocket40- **Scheduling** - One-time, recurring (`scheduleEvery`), cron, and **declarative scheduled tasks** (v0.14+)41- **Workflows** - Durable multi-step background processing via `AgentWorkflow`, with **reasoning steps** (v0.14+)42- **MCP integration** - Connect to MCP servers or build your own with `McpAgent`43- **Email handling** - Receive and reply to emails with secure routing44- **Streaming chat** - `AIChatAgent` with resumable streams and **hardened recovery** (v0.14+)45- **Agent Skills** - Modular, composable skill definitions (v0.14+)46- **Chat Messengers** - Direct Telegram integration (v0.14+)47- **React hooks** - `useAgent`, `useAgentChat` for client apps4849## FIRST: Verify Installation5051```bash52npm ls agents # Should show agents package53```5455If not installed:56```bash57npm install agents58```5960## Wrangler Configuration6162```jsonc63{64 "durable_objects": {65 "bindings": [{ "name": "MyAgent", "class_name": "MyAgent" }]66 },67 "migrations": [{ "tag": "v1", "new_sqlite_classes": ["MyAgent"] }]68}69```7071## Agent Class7273```typescript74import { Agent, routeAgentRequest, callable } from "agents";7576type State = { count: number };7778export class Counter extends Agent<Env, State> {79 initialState = { count: 0 };8081 // Validation hook - runs before state persists (sync, throwing rejects the update)82 validateStateChange(nextState: State, source: Connection | "server") {83 if (nextState.count < 0) throw new Error("Count cannot be negative");84 }8586 // Notification hook - runs after state persists (async, non-blocking)87 onStateUpdate(state: State, source: Connection | "server") {88 console.log("State updated:", state);89 }9091 @callable()92 increment() {93 this.setState({ count: this.state.count + 1 });94 return this.state.count;95 }96}9798export default {99 fetch: (req, env) => routeAgentRequest(req, env) ?? new Response("Not found", { status: 404 })100};101```102103## Routing104105Requests route to `/agents/{agent-name}/{instance-name}`:106107| Class | URL |108|-------|-----|109| `Counter` | `/agents/counter/user-123` |110| `ChatRoom` | `/agents/chat-room/lobby` |111112Client: `useAgent({ agent: "Counter", name: "user-123" })`113114## Core APIs115116| Task | API |117|------|-----|118| Read state | `this.state.count` |119| Write state | `this.setState({ count: 1 })` |120| SQL query | `` this.sql`SELECT * FROM users WHERE id = ${id}` `` |121| Schedule (delay) | `await this.schedule(60, "task", payload)` |122| Schedule (cron) | `await this.schedule("0 * * * *", "task", payload)` |123| Schedule (interval) | `await this.scheduleEvery(30, "poll")` |124| RPC method | `@callable() myMethod() { ... }` |125| Streaming RPC | `@callable({ streaming: true }) stream(res) { ... }` |126| Start workflow | `await this.runWorkflow("ProcessingWorkflow", params)` |127128## React Client129130```tsx131import { useAgent } from "agents/react";132133function App() {134 const [state, setLocalState] = useState({ count: 0 });135136 const agent = useAgent({137 agent: "Counter",138 name: "my-instance",139 onStateUpdate: (newState) => setLocalState(newState),140 onIdentity: (name, agentType) => console.log(`Connected to ${name}`)141 });142143 return (144 <button onClick={() => agent.setState({ count: state.count + 1 })}>145 Count: {state.count}146 </button>147 );148}149```150151## References152153- **[references/workflows.md](references/workflows.md)** - Durable Workflows integration154- **[references/callable.md](references/callable.md)** - RPC methods, streaming, timeouts155- **[references/state-scheduling.md](references/state-scheduling.md)** - State persistence, scheduling156- **[references/streaming-chat.md](references/streaming-chat.md)** - AIChatAgent, resumable streams157- **[references/mcp.md](references/mcp.md)** - MCP server integration158- **[references/email.md](references/email.md)** - Email routing and handling159- **[references/codemode.md](references/codemode.md)** - Code Mode (experimental)