Skip to content

Commit 7d8771b

Browse files
Sync comprehensive Agents SDK documentation from PR 812
This sync adds extensive documentation for the Agents SDK covering: **New Concept Guides:** - State Management: setState(), onBeforeStateChange(), onStateUpdate(), validation - Routing: routeAgentRequest(), custom routing with basePath, server-sent identity - Callable Methods: @callable decorator, RPC over WebSocket, streaming responses - Scheduling: Delayed, scheduled, cron, and interval-based task scheduling - HTTP & WebSockets: Lifecycle hooks, connection management, hibernation **New Getting Started:** - Quickstart: Step-by-step counter agent tutorial with React and vanilla JS **New API Reference:** - Client SDK: useAgent, AgentClient, agentFetch, state sync, RPC calls **New MCP Documentation:** - Connecting to MCP Servers: OAuth flows, transport options, tool integration **Key Features Documented:** - Synchronous setState (now returns void instead of Promise) - onBeforeStateChange hook for state validation (sync, gating) - scheduleEvery() for fixed-interval recurring tasks - MCP options-based API for cleaner server connections - Custom routing with basePath and server-sent identity - Client-side RPC timeout support - getCallableMethods() introspection API - Email auto-reply detection utilities All documentation follows Cloudflare docs style guidelines with proper component usage (TypeScriptExample, WranglerConfig, PackageManagers), full relative links, and MDX formatting. Source: cloudflare/agents PR #812
1 parent 554f1c2 commit 7d8771b

File tree

8 files changed

+4868
-0
lines changed

8 files changed

+4868
-0
lines changed

src/content/docs/agents/api-reference/client-sdk.mdx

Lines changed: 596 additions & 0 deletions
Large diffs are not rendered by default.

src/content/docs/agents/concepts/callable-methods.mdx

Lines changed: 709 additions & 0 deletions
Large diffs are not rendered by default.

src/content/docs/agents/concepts/http-websockets.mdx

Lines changed: 696 additions & 0 deletions
Large diffs are not rendered by default.

src/content/docs/agents/concepts/routing.mdx

Lines changed: 692 additions & 0 deletions
Large diffs are not rendered by default.

src/content/docs/agents/concepts/scheduling.mdx

Lines changed: 808 additions & 0 deletions
Large diffs are not rendered by default.

src/content/docs/agents/concepts/state-management.mdx

Lines changed: 488 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 282 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
1+
---
2+
title: Quickstart
3+
pcx_content_type: get-started
4+
sidebar:
5+
order: 0
6+
---
7+
8+
import { PackageManagers, TypeScriptExample, WranglerConfig } from "~/components";
9+
10+
Build AI agents that persist, think, and act. Agents run on Cloudflare's global network, maintain state across requests, and connect to clients in real-time via WebSockets.
11+
12+
**What you will build:** A counter agent with persistent state that syncs to a React frontend in real-time.
13+
14+
**Time:** Approximately 10 minutes
15+
16+
## Create a New Project
17+
18+
<PackageManagers type="create" pkg="cloudflare@latest" args={"-- --template cloudflare/agents-starter"} />
19+
20+
```sh
21+
cd my-agent
22+
```
23+
24+
<PackageManagers type="install" />
25+
26+
This creates a project with:
27+
28+
- `src/server.ts` - Your agent code
29+
- `src/client.tsx` - React frontend
30+
- `wrangler.jsonc` - Cloudflare configuration
31+
32+
Start the dev server:
33+
34+
<PackageManagers type="run" args={"dev"} />
35+
36+
Open [http://localhost:5173](http://localhost:5173) to see your agent in action.
37+
38+
## Your First Agent
39+
40+
Build a simple counter agent from scratch. Replace `src/server.ts`:
41+
42+
<TypeScriptExample>
43+
44+
```ts
45+
import { Agent, routeAgentRequest, callable } from "agents";
46+
47+
// Define the state shape
48+
type CounterState = {
49+
count: number;
50+
};
51+
52+
// Create the agent
53+
export class Counter extends Agent<Env, CounterState> {
54+
// Initial state for new instances
55+
initialState: CounterState = { count: 0 };
56+
57+
// Methods marked with @callable can be called from the client
58+
@callable()
59+
increment() {
60+
this.setState({ count: this.state.count + 1 });
61+
return this.state.count;
62+
}
63+
64+
@callable()
65+
decrement() {
66+
this.setState({ count: this.state.count - 1 });
67+
return this.state.count;
68+
}
69+
70+
@callable()
71+
reset() {
72+
this.setState({ count: 0 });
73+
}
74+
}
75+
76+
// Route requests to agents
77+
export default {
78+
async fetch(request: Request, env: Env, ctx: ExecutionContext) {
79+
return (
80+
(await routeAgentRequest(request, env)) ??
81+
new Response("Not found", { status: 404 })
82+
);
83+
}
84+
};
85+
```
86+
87+
</TypeScriptExample>
88+
89+
Update `wrangler.jsonc` to register the agent:
90+
91+
<WranglerConfig>
92+
93+
```jsonc
94+
{
95+
"name": "my-agent",
96+
"main": "src/server.ts",
97+
"compatibility_date": "2025-01-01",
98+
"compatibility_flags": ["nodejs_compat"],
99+
"durable_objects": {
100+
"bindings": [
101+
{
102+
"name": "Counter",
103+
"class_name": "Counter"
104+
}
105+
]
106+
},
107+
"migrations": [
108+
{
109+
"tag": "v1",
110+
"new_sqlite_classes": ["Counter"]
111+
}
112+
]
113+
}
114+
```
115+
116+
</WranglerConfig>
117+
118+
## Connect from React
119+
120+
Replace `src/client.tsx`:
121+
122+
<TypeScriptExample>
123+
124+
```tsx
125+
import { useState } from "react";
126+
import { useAgent } from "agents/react";
127+
128+
// Match your agent's state type
129+
type CounterState = {
130+
count: number;
131+
};
132+
133+
export default function App() {
134+
const [count, setCount] = useState(0);
135+
136+
// Connect to the Counter agent
137+
const agent = useAgent<CounterState>({
138+
agent: "Counter",
139+
onStateUpdate: (state) => setCount(state.count)
140+
});
141+
142+
return (
143+
<div style={{ padding: "2rem", fontFamily: "system-ui" }}>
144+
<h1>Counter Agent</h1>
145+
<p style={{ fontSize: "3rem" }}>{count}</p>
146+
<div style={{ display: "flex", gap: "1rem" }}>
147+
<button onClick={() => agent.stub.decrement()}>-</button>
148+
<button onClick={() => agent.stub.reset()}>Reset</button>
149+
<button onClick={() => agent.stub.increment()}>+</button>
150+
</div>
151+
</div>
152+
);
153+
}
154+
```
155+
156+
</TypeScriptExample>
157+
158+
Key points:
159+
160+
- **`useAgent`** connects to your agent via WebSocket
161+
- **`onStateUpdate`** fires whenever the agent's state changes
162+
- **`agent.stub.methodName()`** calls methods marked with `@callable()` on your agent
163+
164+
## What Just Happened
165+
166+
When you clicked the button:
167+
168+
1. **Client** called `agent.stub.increment()` over WebSocket
169+
2. **Agent** ran `increment()`, updated state with `setState()`
170+
3. **State** persisted to SQLite automatically
171+
4. **Broadcast** sent to all connected clients
172+
5. **React** updated via `onStateUpdate`
173+
174+
### Key Concepts
175+
176+
| Concept | What it means |
177+
| -------------------- | ------------------------------------------------------------------------------------------- |
178+
| **Agent instance** | Each unique name gets its own agent. `Counter:user-123` is separate from `Counter:user-456` |
179+
| **Persistent state** | State survives restarts, deploys, and hibernation. It is stored in SQLite |
180+
| **Real-time sync** | All clients connected to the same agent receive state updates instantly |
181+
| **Hibernation** | When no clients are connected, the agent hibernates (no cost). It wakes on the next request |
182+
183+
## Connect from Vanilla JS
184+
185+
If you are not using React:
186+
187+
<TypeScriptExample>
188+
189+
```ts
190+
import { AgentClient } from "agents/client";
191+
192+
const agent = new AgentClient({
193+
agent: "Counter",
194+
name: "my-counter", // optional, defaults to "default"
195+
onStateUpdate: (state) => {
196+
console.log("New count:", state.count);
197+
}
198+
});
199+
200+
// Call methods
201+
await agent.call("increment");
202+
await agent.call("reset");
203+
```
204+
205+
</TypeScriptExample>
206+
207+
## Deploy to Cloudflare
208+
209+
<PackageManagers type="run" args={"deploy"} />
210+
211+
Your agent is now live on Cloudflare's global network, running close to your users.
212+
213+
## Next Steps
214+
215+
Now that you have a working agent, explore these topics:
216+
217+
- [State Management](/agents/concepts/state-management/) - Deep dive into `setState()`, `initialState`, and `onStateUpdate()`
218+
- [Client SDK](/agents/api-reference/client-sdk/) - Full `useAgent` and `AgentClient` API reference
219+
- [Scheduling](/agents/concepts/scheduling/) - Run tasks on a delay, schedule, or cron
220+
- [HTTP and WebSockets](/agents/concepts/http-websockets/) - Lifecycle methods, HTTP handlers, and WebSocket events
221+
222+
### Common Patterns
223+
224+
| I want to... | Read... |
225+
| ------------------------ | ---------------------------------------- |
226+
| Add AI or LLM capabilities | [Using AI Models](/agents/api-reference/using-ai-models/) |
227+
| Expose tools via MCP | [Creating MCP Servers](/agents/model-context-protocol/mcp-servers-for-cloudflare/) |
228+
| Run background tasks | [Scheduling](/agents/concepts/scheduling/) |
229+
| Use Cloudflare Workflows | [Run Workflows](/agents/api-reference/run-workflows/) |
230+
231+
## Troubleshooting
232+
233+
### Agent not found or 404 errors
234+
235+
Make sure:
236+
237+
1. Agent class is exported from your server file
238+
2. `wrangler.jsonc` has the binding and migration
239+
3. Agent name in client matches the class name (case-insensitive)
240+
241+
### State not syncing
242+
243+
Check that:
244+
245+
1. You are calling `this.setState()`, not mutating `this.state` directly
246+
2. The `onStateUpdate` callback is wired up in your client
247+
3. WebSocket connection is established (check browser dev tools)
248+
249+
### Method X is not callable errors
250+
251+
Make sure your methods are decorated with `@callable()`:
252+
253+
<TypeScriptExample>
254+
255+
```ts
256+
import { callable } from "agents";
257+
258+
@callable()
259+
increment() {
260+
// ...
261+
}
262+
```
263+
264+
</TypeScriptExample>
265+
266+
### Type errors with agent.stub
267+
268+
Add the agent type parameter:
269+
270+
<TypeScriptExample>
271+
272+
```ts
273+
const agent = useAgent<Counter, CounterState>({
274+
agent: "Counter",
275+
onStateUpdate: (state) => setCount(state.count)
276+
});
277+
278+
// Now agent.stub is fully typed
279+
agent.stub.increment(); // ✓ TypeScript knows this method exists
280+
```
281+
282+
</TypeScriptExample>

0 commit comments

Comments
 (0)