Where state lives
All three are render state, rebuilt from the stream on reload. The Agent’s memory is a
separate layer on the server.
An interface’s public state lives under the key
state, and it is the only thing about
that interface the outside world sees. (view and defaultState are legacy spellings the
platform still reads.)
The one question
An interface writes its ownstate. Everything holding it then asks one question:
Do I have a state with that name?A template asks it and draws that state’s shape. An app asks it and draws that state’s layout. A match activates, and no match means the interface renders inline in the conversation. That is the whole reaction contract, and it runs at every scale. A card writing
state: page opens the page state of whatever holds it, and nothing was wired to make
that happen.
Nothing writes another thing’s state. An interface writes its own and nothing else’s,
and the app never writes a component’s: not to promote it, not to retract it, not to close
it. A card’s own ✕ writes its state back, which is why there is no close logic anywhere.
One instance, one place. While an interface’s state matches, it lifts out of the flow
into that place. It is never drawn twice, and there is no trick for hiding a second copy.
Losing the match releases it back inline.
Arrival and lifetime
An interface arrives as data, and where it lands is the host’s decision. Its first declared state stands whenever the host has a state of that name. A card declaringgrid first, arriving into an app with a grid state, starts there. Only when
the host has no such state does the scan run: the host walks its own states in declared
order and takes the first name the interface also declares. With no overlap at all, the
interface wakes in its own first state, inline.
A new turn resets the screen. Every instance returns to its first state, places empty,
and the app derives its base state again. An interface whose first state suits the flow
stays in that turn’s history. One with no inline face retires: visible while placed,
invisible afterwards.
The opt-out is lifetime: conversation in the manifest, for a durable surface such as a
cart or a composed page. The platform keys it by the conversation rather than the turn, so
a repeat arrival merges into the same slice instead of replacing it. It survives the reset
and cancellation, and stays until it is replaced, closes itself, or the app swaps. An app
swap is the hard boundary, and a new shell retires every surface, durable ones included.
Priority
An app is in exactly one state at a time, and its tree declares the order:focus and seven in grid means the app enters
focus. Ties go to the most recent write. No word is special, and focus outranks grid
by list position alone.
The active state is derived, never stored. It is a function of what the app currently
holds, so nothing writes a focus flag anywhere.
A delivery clears the claims below it. Your own navigation does not. When an interface
arrives into a higher-ranked state, interfaces sitting in lower ones release and retract to
inline, so releasing the higher state lands on the base rather than a stale lower one.
Closing a finder returns you to the conversation instead of resurrecting the rail that was
open beforehand. Tapping a rail card into its page enters page without touching the
rail’s claims, so closing that page returns you to the rail you opened it from.
Both are the same walk, with one question added: did a delivery put the winner there, or
did you?
Writing state
Two writes exist, and everything else is a native MCP call.setValue writes the interface’s own slice: its answers, its step, its state.
setAppValue writes the app’s own chrome, such as a disclosure panel or a composer
draft. A component may write it too, because chrome drawn through Ref has no slice of its
own.
Sending a message is tools/call, and answering a waiting wizard is an elicitation. You
never build transport.
A place selects what it holds by state, never by component type and never by id:
state only.
App chrome reads the same fact as surfacedView, the name of the active reaction state, or
empty when everything is inline. A header button reacts by name without needing a slot.
State you cannot write
Three things are managed for you. Project them, and never simulate them.
An app binds the voice service by declaring
service: voice in its manifest.
Modelling a state tree
Three habits keep a tree honest. A state’s layout is its shell. The shell stays on while that state is active, and only its nested substates are choices inside it. You never write a root for a tree, because the compiler builds theSwitch on state from the declaration, and a case never re-guards
the discriminant the tree already selected.
Most “states” are data. Seven wizard questions sharing one arrangement are one state
whose data changes, never seven files. The step value selects what the layout binds, and
only a genuinely different arrangement earns a file. Input is neither a state nor a step,
because a composer or edit form is the app’s one input tool.
The writer of a value owns where it lives. Before nesting anything, ask what writes the
discriminant:
Borrowing another field’s values leaks machinery into your design, so never model a derived
mood as component substates.
The model is not a house invention. One discriminant per axis is the discriminated-union
doctrine, which exists to make impossible states impossible. Nested states with a first
declared entry are statecharts.
A streamed interface is a spawned actor
that owns its state and publishes it, and the app subscribes. Deriving rather than storing
is React’s own Choosing the State Structure.
Next steps
Templates
The arrangements that hold your interfaces and react to their states.
Apps
The shell your templates and components render inside.

