What you’ll build: A counter agent with persistent state that syncs to a React frontend in real-time.Time: ~10 minutes
Create a New Project
Use the Cloudflare agents starter template to scaffold a new project:src/server.ts- Your agent codesrc/client.tsx- React frontendwrangler.jsonc- Cloudflare configuration
1
Start the dev server
Your First Agent
Let’s build a simple counter agent from scratch. Replacesrc/server.ts:
src/server.ts
Configure the Agent
Updatewrangler.jsonc to register the agent:
wrangler.jsonc
namein bindings becomes the property onenv(e.g.,env.Counter)class_namemust match your exported class name exactlynew_sqlite_classesenables SQLite storage for state persistence
Connect from React
Replacesrc/client.tsx to connect to your agent:
src/client.tsx
Key Concepts
useAgent
Connects to your agent via WebSocket
onStateUpdate
Fires whenever the agent’s state changes
agent.stub
Calls methods marked with
@callable() on your agentWhat Just Happened?
When you clicked the button:1
Client called agent.stub.increment()
The call is sent over WebSocket to the agent
2
Agent ran increment()
Updated state with
setState()3
State persisted to SQLite
Happens automatically on every
setState() call4
Broadcast sent to all clients
All connected clients receive the state update
5
React updated via onStateUpdate
Your UI re-renders with the new state
Understanding Agent Instances
Agent instance
Agent instance
Each unique name gets its own agent.
Counter:user-123 is separate from Counter:user-456Persistent state
Persistent state
State survives restarts, deploys, and hibernation. It’s stored in SQLite
Real-time sync
Real-time sync
All clients connected to the same agent receive state updates instantly
Hibernation
Hibernation
When no clients are connected, the agent hibernates (no cost). It wakes on the next request
Connect from Vanilla JS
If you’re not using React:Deploy to Cloudflare
When you’re ready to deploy:Troubleshooting
Agent not found / 404 errors
Agent not found / 404 errors
Make sure:
- Agent class is exported from your server file
wrangler.jsonchas the binding and migration- Agent name in client matches the class name (case-insensitive)
State not syncing
State not syncing
Check that:
- You’re calling
this.setState(), not mutatingthis.statedirectly - The
onStateUpdatecallback is wired up in your client - WebSocket connection is established (check browser dev tools)
Method X is not callable errors
Method X is not callable errors
Make sure your methods are decorated with
@callable():Type errors with agent.stub
Type errors with agent.stub
Add the agent type parameter:
Next Steps
Now that you have a working agent, explore these topics:State Management
Deep dive into
setState(), initialState, and onStateChanged()Client SDK
Full
useAgent and AgentClient API referenceScheduling
Run tasks on a delay, schedule, or cron
Agent Class
Lifecycle methods, HTTP handlers, and WebSocket events