Skip to main content
Agent state is one persistent value of your State type. setState merges, which is what you want for the common case — update two fields without re-writing the rest.
State lives in the actor’s persistent storage — the same layer the scheduler and the message log write to — as a single entry holding the whole State value. Reads return that value in full, and setState re-persists it inside a storage transaction, so keep it small and fixed-shape: status flags, cursors, the instance’s working memory. It follows the storage layer’s codec rules and per-value size cap (see the storage reference). For data that accumulates or needs querying — rows you’d filter, aggregate, or join — use the agent’s embedded SQL database instead; it lives in the same instance and scales to 1 GB per agent.

initialState()

protected initialState(): State
Default state for a fresh agent instance. Called whenever state is read and nothing has been stored yet. Reading alone does not persist the default — the first write does. Subclasses override this to declare their initial State. Returns State Default Value {}

getState()

protected getState(): Promise<State>
Read the agent’s persistent state. Returns Promise<State> The stored state, or `initialState()` if nothing has been written yet.

setState()

protected setState(patch): Promise<State>
Merge patch into the persistent state and return the merged result. The merge is a recursive JSON merge patch (RFC 7396): top-level keys in patch are merged in, nested objects are deep-merged, and a null value deletes that key. The merge runs in a storage transaction, and `onStateChanged` fires after it commits. Values must be storage-codec-safe (JSON-native values plus Date, Map, Set, ArrayBuffer/TypedArray, BigInt, RegExp); functions, class instances, or circular references throw a CodecError. Parameters Returns Promise<State> The full state after the merge. The merge is recursive, and null deletes:
Untouched keys survive at every level — status and job.id were never rewritten.

replaceState()

protected replaceState(next): Promise<State>
Replace the persistent state wholesale (no merging) and return it. Unlike `setState`, nothing of the previous state survives. `onStateChanged` does fire — with the new state and the state before the replacement. Parameters Returns Promise<State> next, as written.

onStateChanged()

protected onStateChanged(_next, _prev): Promise<void>
Hook: fires after every persistent state change — after each `setState` and `replaceState` resolves. Override to react to changes: mirror state to an external system, log transitions, invalidate caches, or fan state out to connected clients. The default implementation does nothing. Parameters Returns Promise<void> One override fans state out to connected clients — broadcastSnapshot pushes to every socket subscribed to state, and the hook covers setState and replaceState alike:
For patch-level pushes — sending only what changed — broadcast from a setState override instead, where the patch object is in hand; the example on AgentSocketServer shows that variant.