Skip to main content

Overview

Agents provide built-in state management with automatic persistence to Durable Object storage and real-time synchronization to all connected WebSocket clients.

Setting State

setState()

Update the Agent’s state. Persists to storage and broadcasts to all connected clients.
State
required
The new state to set
Throws: Error if called from a readonly connection context

How setState() Works

  1. Validation - Calls validateStateChange() hook (synchronous)
  2. Persistence - Saves state to Durable Object storage
  3. Broadcast - Sends state update to all connected clients
  4. Notification - Calls onStateChanged() hook (async, non-blocking)

Reading State

state

Access the current state via the state property.

initialState

Define the initial state for new Agent instances.
initialState is only used when the Agent is first created. If state already exists in storage, it takes precedence.

State Lifecycle Hooks

validateStateChange()

Called before state is persisted. Throw an error to reject the update. Must be synchronous.
State
required
The proposed new state
Connection | 'server'
required
Source of the state update
validateStateChange() must be synchronous. Use onStateChanged() for async operations.

onStateChanged()

Called after state has been persisted and broadcast. This is a notification hook—errors are routed to onError() and do not affect persistence.
State | undefined
required
The new state
Connection | 'server'
required
Source of the state update

Client-Side State Management

useAgent Hook

React hook for real-time state synchronization.
See useAgent hook for full documentation.

AgentClient

Vanilla JavaScript client for state synchronization.
See AgentClient for full documentation.

Connection-Level State

Readonly Connections

Mark connections as readonly to prevent state updates.

connection.setState()

Connections can have their own isolated state (separate from Agent state).
Access connection state:

State Persistence

State is automatically persisted to Durable Object SQL storage:
You can access the raw storage if needed:
Direct SQL access to state storage is not recommended. Use setState() and state instead.

State Broadcasting

When state changes, all connected clients receive an update message:
You can suppress protocol messages for specific connections:

Best Practices

Atomic Updates

Always pass the complete state object to setState():

Validate Before Persist

Use validateStateChange() to enforce invariants:

Async Side Effects

Use onStateChanged() for async operations:

State Size

Keep state small (under 128KB recommended). For large data, use SQL or KV: