This page provides an overview of the Agents SDK. For detailed documentation on each feature, refer to the linked reference pages.
The Agents SDK provides two main APIs:
| API | Description |
|---|---|
Server-side Agent class |
Encapsulates agent logic: connections, state, methods, AI models, error handling |
| Client-side SDK | AgentClient, useAgent, and useAgentChat for connecting from browsers |
An Agent is a class that extends the base Agent class:
import { Agent, routeAgentRequest } from "agents";
export class MyAgent extends Agent<Env, State> {
// Your agent logic
}
export default {
async fetch(request: Request, env: Env) {
return (
(await routeAgentRequest(request, env)) ||
new Response("Not found", { status: 404 })
);
},
} satisfies ExportedHandler<Env>;Each Agent can have millions of instances. Each instance is a separate micro-server that runs independently, allowing horizontal scaling. Instances are addressed by a unique identifier (user ID, email, ticket number, etc.).
flowchart TD
A["onStart<br/>(instance wakes up)"] --> B["onRequest<br/>(HTTP)"]
A --> C["onConnect<br/>(WebSocket)"]
A --> D["onEmail"]
C --> E["onMessage ↔ send()<br/>onError (on failure)"]
E --> F["onClose"]
| Method | When it runs |
|---|---|
onStart(props?) |
When the instance starts, or wakes from hibernation. Receives optional initialization props passed via getAgentByName or routeAgentRequest. |
onRequest(request) |
For each HTTP request to the instance |
onConnect(connection, ctx) |
When a WebSocket connection is established |
onMessage(connection, message) |
For each WebSocket message received |
onError(connection, error) |
When a WebSocket error occurs |
onClose(connection, code, reason, wasClean) |
When a WebSocket connection closes |
onEmail(email) |
When an email is routed to the instance |
onStateChanged(state, source) |
When state changes (from server or client) |
| Property | Type | Description |
|---|---|---|
this.env |
Env |
Environment variables and bindings |
this.ctx |
ExecutionContext |
Execution context for the request |
this.state |
State |
Current persisted state |
this.sql |
Function | Execute SQL queries on embedded SQLite |
| Feature | Methods | Documentation |
|---|---|---|
| State | setState(), onStateChanged(), initialState |
Store and sync state |
| Callable methods | @callable() decorator |
Callable methods |
| Scheduling | schedule(), scheduleEvery(), getScheduleById(), listSchedules() |
Schedule tasks |
| Durable execution | runFiber(), startFiber(), stash(), onFiberRecovered(), keepAlive(), keepAliveWhile() |
Durable execution |
| Queue | queue(), dequeue(), dequeueAll(), getQueue() |
Queue tasks |
| WebSockets | onConnect(), onMessage(), onClose(), broadcast() |
WebSockets |
| HTTP/SSE | onRequest() |
HTTP and SSE |
onEmail(), replyToEmail() |
Email routing | |
| Workflows | runWorkflow(), waitForApproval() |
Run Workflows |
| MCP Client | addMcpServer(), removeMcpServer(), getMcpServers() |
MCP Client API |
| AI Models | Workers AI, OpenAI, Anthropic bindings | Using AI models |
| Protocol messages | shouldSendProtocolMessages(), isConnectionProtocolEnabled() |
Protocol messages |
| Context | getCurrentAgent() |
getCurrentAgent() |
| Observability | subscribe(), diagnostics channels, Tail Workers |
Observability |
| Sub-agents | subAgent(), abortSubAgent(), deleteSubAgent() |
Sub-agents |
| Agents as tools | runAgentTool(), clearAgentToolRuns(), hasAgentToolRun() |
Agents as tools |
| Agent Skills | skills registry, bundled skill sources, script runners |
Agent Skills |
| Sessions | Session.create(), context blocks, compaction, search |
Sessions |
| Think | Think base class, workspace tools, lifecycle hooks, extensions |
Think |
| Chat SDK | createChatSdkState(), ChatSdkStateAgent |
Chat SDK |
Each Agent instance has an embedded SQLite database accessed via this.sql:
// Create tables
this.sql`CREATE TABLE IF NOT EXISTS users (id TEXT PRIMARY KEY, name TEXT)`;
// Insert data
this.sql`INSERT INTO users (id, name) VALUES (${id}, ${name})`;
// Query data
const users = this.sql<User>`SELECT * FROM users WHERE id = ${id}`;For state that needs to sync with clients, use the State API instead.
| Feature | Methods | Documentation |
|---|---|---|
| WebSocket client | AgentClient |
Client SDK |
| HTTP client | agentFetch() |
Client SDK |
| React hook | useAgent() |
Client SDK |
| Chat hook | useAgentChat() |
Client SDK |
| Agent tool events | useAgentToolEvents() |
Agents as tools |
Module-level helper exports include agentTool() from agents/agent-tools, which converts a Think or AIChatAgent subclass into an AI SDK tool definition.
import { useAgent } from "agents/react";
import type { MyAgent } from "./server";
function App() {
const agent = useAgent<MyAgent, State>({
agent: "my-agent",
name: "user-123",
});
// Call methods on the agent
agent.stub.someMethod();
// Update state (syncs to server and all clients)
agent.setState({ count: 1 });
}For AI chat applications, extend AIChatAgent instead of Agent:
import { AIChatAgent } from "@cloudflare/ai-chat";
class ChatAgent extends AIChatAgent {
async onChatMessage(onFinish) {
// this.messages contains the conversation history
// Return a streaming response
}
}Features include:
- Built-in message persistence
- Automatic resumable streaming (reconnect mid-stream)
- Works with
useAgentChatReact hook
Refer to Build a chat agent for a complete tutorial.
Agents are accessed via URL patterns:
https://your-worker.workers.dev/agents/:agent-name/:instance-nameUse routeAgentRequest() in your Worker to route requests:
import { routeAgentRequest } from "agents";
export default {
async fetch(request: Request, env: Env) {
return (
routeAgentRequest(request, env) ||
new Response("Not found", { status: 404 })
);
},
} satisfies ExportedHandler<Env>;Refer to Routing for custom paths, CORS, and instance naming patterns.