The ReAct run state structure, how tools update it, and what clients can see.
Every run has a persistent state object. The state persists across the run and holds everything the agent needs between steps. Tools receive a snapshot of the current state and can return updates to it alongside their output.
For ReAct, the state holds:
| Field | Type | Description |
|---|---|---|
run_id | string | Unique identifier for this run. |
session_id | string | Identifier for the session this run belongs to. |
model | ModelConfig | null | Model selection, inference, timeout, and retry configuration held in the state. |
capability_override | CapabilityOverride | null | Capability override held in the state. |
messages | array<Message> | The conversation history for this session. |
context_vars | array<ContextVar> | Context variables held in the state. |
tools | array<ToolDefinition> | Tool definitions held in the state. |
context | object | Structured data that persists across steps. This is the primary field for tools to write to and for clients to read from. |
A later run can replace model, capability_override, context_vars, and tools in the session
state. These values remain in the state until another run changes them.
For AG-UI runs, omitting tools or context, or sending [], clears the corresponding stored
list. Omitting model or capability_override from forwardedProps preserves the stored value;
setting either to null clears it.
The context field is a free-form JSON object. Tools write to it via state updates, and clients can
read it from state events. Any data your tools need to communicate back to the frontend should go in
context.
Messages are persisted separately from context. That matters because clients often want to read the
conversation history without starting a new run. The persisted message store is also what makes the
session and message HTTP endpoints useful outside of the active stream.
ReAct user messages can be multimodal. A user message is an ordered list of content blocks. The
common block types are text, image, audio, video, and document. Image, audio, video, and document
blocks carry a source and a media_type. The source is either a URL or base64 payload. The
media_type is the MIME type the model provider should see.
State updates are how the state evolves over the course of a session. Each state has its own corresponding structure for updates. For ReAct, the state update structure is:
| Field | Type | Description |
|---|---|---|
messages | array<Message> | New messages to append to the conversation history. |
context | array<PatchOperation> | Partial updates to the context field in the form of RFC 6902 JSON Patch operations. |
model | ModelConfig | null | Model configuration to replace the stored value, or null to clear it. |
capability_override | CapabilityOverride | null | Capability override to replace the stored value, or null to clear it. |
context_vars | array<ContextVar> | Context variables to replace the stored list. An empty array clears it. |
tools | array<ToolDefinition> | Tool definitions to replace the stored list. An empty array clears it. |
When a tool returns a state_update, it supplies RFC 6902 JSON Patch operations. To change
the ReAct context, append an operation at /context/-. The appended operation's path is
relative to the context object. These context changes persist and are sent to clients as state
delta events.
For example, this update sets context.last_city and context.temperature:
[
{
"op": "add",
"path": "/context/-",
"value": { "op": "add", "path": "/last_city", "value": "London" }
},
{
"op": "add",
"path": "/context/-",
"value": { "op": "add", "path": "/temperature", "value": 18.5 }
}
]Clients only have access to the context field of the run state. When state delta events are
emitted, the client receives patches scoped to context. When a client sends new state in a run
request, it is applied to context.
This design means context is the shared data contract between your tools, your frontend and your
prompt. Structure it as needed for your use case. The
event stream that carries these updates is documented in the
HTTP reference.
© 2026 pogue.dev. All rights reserved.
CC BY 4.0