Skip to main content
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:
This creates a project with:
  • src/server.ts - Your agent code
  • src/client.tsx - React frontend
  • wrangler.jsonc - Cloudflare configuration
1

Start the dev server

Open http://localhost:5173 to see your agent in action.

Your First Agent

Let’s build a simple counter agent from scratch. Replace src/server.ts:
src/server.ts
Methods must be decorated with @callable() to be invoked from clients.

Configure the Agent

Update wrangler.jsonc to register the agent:
wrangler.jsonc
  • name in bindings becomes the property on env (e.g., env.Counter)
  • class_name must match your exported class name exactly
  • new_sqlite_classes enables SQLite storage for state persistence

Connect from React

Replace src/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 agent

What 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() call
4

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

Each unique name gets its own agent. Counter:user-123 is separate from Counter:user-456
State survives restarts, deploys, and hibernation. It’s stored in SQLite
All clients connected to the same agent receive state updates instantly
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:
Your agent is now live on Cloudflare’s global network, running close to your users.

Troubleshooting

Make sure:
  1. Agent class is exported from your server file
  2. wrangler.jsonc has the binding and migration
  3. Agent name in client matches the class name (case-insensitive)
Check that:
  1. You’re calling this.setState(), not mutating this.state directly
  2. The onStateUpdate callback is wired up in your client
  3. WebSocket connection is established (check browser dev tools)
Make sure your methods are decorated with @callable():
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 reference

Scheduling

Run tasks on a delay, schedule, or cron

Agent Class

Lifecycle methods, HTTP handlers, and WebSocket events

Common Use Cases