Skip to main content
Agents provide built-in state management with automatic persistence and real-time synchronization across all connected clients.

Overview

Agent state is:
  • Persistent - Automatically saved to SQLite, survives restarts and hibernation
  • Synchronized - Changes broadcast to all connected WebSocket clients instantly
  • Bidirectional - Both server and clients can update state
  • Type-safe - Full TypeScript support with generics

Defining Initial State

Use the initialState property to define default values for new agent instances:

Type Safety

The second generic parameter to Agent<Env, State> defines your state type:

When Initial State Applies

Initial state is applied lazily on first access, not on every wake:
1

New agent

initialState is used and persisted
2

Existing agent

Persisted state is loaded from SQLite
3

No initialState defined

this.state is undefined

Reading State

Access the current state via the this.state getter:

Undefined State

If you don’t define initialState, this.state returns undefined:

Updating State

Use setState() to update state. This:
1

Saves to SQLite

State is persisted to storage
2

Broadcasts to all clients

All connected WebSocket clients receive the update
3

Triggers onStateChanged()

After broadcast; best-effort notification

State Must Be Serializable

State is stored as JSON, so it must be serializable:

Responding to State Changes

Override onStateChanged() to react when state changes (notifications/side-effects):

Validating State Updates

If you want to validate or reject state updates, override validateStateChange():
  • Runs before persistence and broadcast
  • Must be synchronous
  • Throwing aborts the update
onStateChanged() is not intended for validation; it is a notification hook and should not block broadcasts.Migration note: onStateChanged replaces the deprecated onStateUpdate (server-side hook). If you’re using onStateUpdate on your agent class, rename it to onStateChanged — the signature and behavior are identical. A console warning will fire once per class until you rename it.

The source Parameter

The source tells you who triggered the update: This is useful for:
  • Avoiding infinite loops (don’t react to your own updates)
  • Validating client input
  • Triggering side effects only on client actions

Common Pattern: Client-Driven Actions

Client-Side State Sync

State synchronizes automatically with connected clients.

React (useAgent)

Vanilla JS (AgentClient)

State from Workflows

When using Workflows, you can update agent state from workflow steps:
These are durable operations - they persist even if the workflow retries.

Patterns and Best Practices

Keep State Small

State is broadcast to all clients on every change. For large data:

Optimistic Updates

For responsive UIs, update client state immediately:

State vs SQL

Avoid Infinite Loops

Be careful not to trigger state updates in response to your own updates:

API Reference

Properties

State
Current state (getter)
State
Default state for new agents

Methods

(state: State) => void
Update state, persist, and broadcast
(state: State, source: Connection | 'server') => void
Called after state is persisted and broadcast

Workflow Step Methods

(state) => Promise<void>
Replace agent state from workflow
(partial) => Promise<void>
Merge partial state from workflow
() => Promise<void>
Reset to initialState from workflow