← Agents / agents / runtime
Agents API
This page provides an overview of the Agents SDK. For detailed documentation on each feature, refer to the linked reference pages.
Overview
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 |
Agent class
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.).
Lifecycle
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) |
Core properties
| 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 |
Server-side API reference
| 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() |
| Tracing | wrapAISDK() |
Tracing |
| Diagnostics channels | subscribe(), diagnostics channels |
Diagnostics channels |
| 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 |
SQL API
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.
Client-side API reference
| 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.
Quick example
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 });
}Chat agents
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.
Routing
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.