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

# State

> getState, setState, replaceState — merge-patch durable state on a single key, plus the initialState and onStateChanged hooks.

Agent state is one durable value of your `State` type. `setState` **merges**, which is
what you want for the common case — update two fields without re-writing the rest.

```ts theme={null}
interface ConvState extends Record<string, unknown> {
  status: "idle" | "processing";
  lastReply: string;
  at: number;
}

export class Conversation extends Agent<Env, ConvState> {
  protected override initialState(): ConvState {
    return { status: "idle", lastReply: "", at: 0 };
  }

  async process(): Promise<void> {
    await this.setState({ status: "processing" });          // merge: other keys untouched
    // ...
    await this.setState({ status: "idle", at: Date.now() });
  }
}
```

## Methods

| Method               | Returns          | Semantics                                                                      |
| -------------------- | ---------------- | ------------------------------------------------------------------------------ |
| `getState()`         | `Promise<State>` | The stored state, or `initialState()` if nothing has been written yet          |
| `setState(patch)`    | `Promise<State>` | Recursive-merges `patch` (RFC 7396) in a transaction; returns the merged state |
| `replaceState(next)` | `Promise<State>` | Writes `next` wholesale; returns it                                            |

* The merge is **recursive** (RFC 7396) — top-level keys are merged in, nested objects are
  deep-merged, and `null` deletes a key.
* Values must be codec-safe, like all actor storage — see
  [Errors](/docs/edge-compute/stateful-actors/api-reference/errors) for `CodecError`.

## Hooks

### `initialState(): State`

The default for a fresh actor. Called whenever state is read and nothing has been
stored yet; the default implementation returns `{}`. Reading alone doesn't persist it —
the first write does.

### `onStateChanged(next, prev)`

Fires after every `setState()` resolves, with the merged state and the state before the
patch. Override it to react to changes — mirror to an external system, log transitions,
invalidate caches.

`replaceState()` **does** fire this hook — the `next` argument is the new state and `prev`
is the state before replacement.
