> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/cloudflare/agents/llms.txt
> Use this file to discover all available pages before exploring further.

# Counter Example

> Build a simple counter agent with persistent state, callable methods, and real-time sync to a React frontend

A counter agent with persistent state, callable methods, and real-time sync to a React frontend. This is the simplest example showing the core patterns of Cloudflare Agents.

## What it demonstrates

* **Persistent State** - Counter value survives restarts and hibernation
* **Callable Methods** - Type-safe RPC via the `@callable()` decorator
* **Real-time Sync** - State changes automatically sync to all connected clients
* **React Integration** - `useAgent` hook for frontend integration

## Server Implementation

```typescript server.ts theme={null}
import { Agent, routeAgentRequest, callable } from "agents";

export type CounterState = { count: number };

export class CounterAgent extends Agent<Env, CounterState> {
  initialState = { count: 0 };

  @callable()
  increment() {
    this.setState({ count: this.state.count + 1 });
    return this.state.count;
  }

  @callable()
  decrement() {
    this.setState({ count: this.state.count - 1 });
    return this.state.count;
  }
}

export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext) {
    return (
      (await routeAgentRequest(request, env)) ??
      new Response("Not found", { status: 404 })
    );
  }
};
```

## React Client

```tsx client.tsx theme={null}
import { useAgent } from "agents/react";
import { useState } from "react";
import type { CounterAgent, CounterState } from "./server";

function Counter() {
  const [count, setCount] = useState(0);

  const agent = useAgent<CounterAgent, CounterState>({
    agent: "CounterAgent",
    onStateUpdate: (state) => setCount(state.count)
  });

  return (
    <div>
      <span>{count}</span>
      <button onClick={() => agent.stub.increment()}>+</button>
      <button onClick={() => agent.stub.decrement()}>-</button>
    </div>
  );
}
```

## How it works

<Steps>
  <Step title="Define Agent State">
    The `CounterState` type defines the shape of the agent's persistent state. This state is stored in Durable Objects and syncs to all connected clients.
  </Step>

  <Step title="Mark Methods as Callable">
    The `@callable()` decorator exposes methods as RPC endpoints. Clients can call them like local functions via `agent.stub.methodName()`.
  </Step>

  <Step title="Update State">
    `this.setState()` updates the agent's state and automatically broadcasts the change to all connected WebSocket clients.
  </Step>

  <Step title="Connect from React">
    The `useAgent` hook establishes a WebSocket connection, receives state updates via `onStateUpdate`, and provides a type-safe `stub` for calling methods.
  </Step>
</Steps>

## Key Concepts

### State Persistence

Agent state is stored in Durable Objects and survives:

* Worker restarts
* Hibernation (when no clients are connected)
* Redeployments

### Real-time Broadcasting

When `setState()` is called:

1. State is persisted to Durable Objects storage
2. Update is broadcast to all connected WebSocket clients
3. Each client's `onStateUpdate` callback fires with the new state

### Type Safety

The `useAgent` hook is fully typed:

```typescript theme={null}
const agent = useAgent<CounterAgent, CounterState>({
  agent: "CounterAgent",
  onStateUpdate: (state) => {
    // `state` is typed as CounterState
    setCount(state.count);
  }
});

// `stub` has the same methods as CounterAgent
await agent.stub.increment();
```

## Running the Example

<CodeGroup>
  ```bash npm theme={null}
  npm create cloudflare@latest -- --template cloudflare/agents-starter
  cd my-agent
  npm run dev
  ```

  ```bash Clone from repo theme={null}
  git clone https://github.com/cloudflare/agents
  cd agents
  npm install
  npm run build
  cd examples/playground  # Has counter and many other examples
  npm start
  ```
</CodeGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="AI Chat Example" icon="comments" href="/examples/ai-chat">
    Add AI chat with streaming and tool execution
  </Card>

  <Card title="Workflows Example" icon="diagram-project" href="/examples/workflows">
    Build multi-step workflows with human approval
  </Card>

  <Card title="MCP Server" icon="server" href="/examples/mcp-server">
    Expose your agent as an MCP server
  </Card>

  <Card title="API Reference" icon="code" href="/api/agent">
    Full Agent class documentation
  </Card>
</CardGroup>
