Agent state

Updated Aug 25, 2026View as Markdown

Agent state is any JSON. The engine stores it and never reads it.

It travels with every decision. The engine sends it on the request as state, and your worker can write a new value on the response. A worker that holds no state of its own gets a memory for each session.

Example

server.mjs
function decide({ trigger, proposed, state }) {
    if (trigger.type === "session.start") {
        return { agent: { model: "claude-haiku-4-5" }, state: { turns: 0 } };
    }

    if (trigger.type === "client.messages") {
        return { ...proposed, state: { turns: (state?.turns ?? 0) + 1 } };
    }

    return proposed;   // no state key keeps the current state
}

Read and write state

The engine sends the current state on every request. To change it, return a new state on the decision.

Response stateEffect
a valueReplaces the state.
{}Clears the state.
omitted or nullKeeps the current state.

Writing the same value again records no new version. A session with no state reads as null, so check for it.

State on a branch

The engine attaches state to the message tree. If you edit an earlier message or branch the conversation, the engine reads the state as it was at that point.

DecisionRequest.state is always correct for the active path. See Conversations.

How state differs from config

Both travel with the decision, and the engine versions them the same way. It reads them differently.

The agent config is a typed document that the engine reads to propose model calls. State is memory that the engine stores and returns unchanged.

Reference

// DecisionRequest
state: unknown          // your state, stored exactly as it is

// DecisionResponse
state?: unknown         // omitted or null keeps it. {} clears it

Next steps