SESSIONS · STATE VERSUS EVENTS
Session state: separate a snapshot from history
Keep a cart, a unit preference and a sign-in token across ten turns and a restart, and see which belong in state, which in history, and which nowhere.
Your experiment
Jenya adds a cookbook, two bookmarks and a reading lamp over ten turns, removes the bookmarks at T8 and asks for the cart at T10. They also state a unit preference and sign in. The opening agent keeps no cart at all: it re-reads the last six turns, so the answer is “reading lamp”. Then check a new session for Jenya and a session for Tanishka.
Play replays the computed run over sixty inspection seconds; Next event steps, Restart rewinds, and Inspection time scrubs. Any input change recomputes the run and rewinds it without autoplay.
Event trace
Computed data
Final metrics
Simplified session model, not ADK source: a write through a tool or callback context becomes a state delta on an event; an assignment on a session fetched outside them is not carried by any event, so the next load returns the old value. Prefix lifetimes follow the ADK documentation. In-memory services lose everything on restart. No model is called.
History, snapshot and scope
A session keeps two things: an append-only history of events, and state, a small snapshot of current values folded from the state changes those events carry. Where the cart lives chooses between re-deriving the cart from the transcript, writing it to state through the tool context so each change rides on an event, and assigning it on a session object fetched outside any tool or callback. Turns of history sent to the model sets how much transcript the model sees. Session service and Process restart before T10 decide what survives. The two key selectors, Unit preference key and Sign-in token key, pick a prefix: none for this session, user: for every session of this user, app: for every user, temp: for this invocation only.
The opening run: the cart is reconstructed, badly
With no cart in state and six turns of history, the T10 window starts at T5. It sees the reading lamp being added and the bookmarks being removed, but not the cookbook added at T1, so the answer is “reading lamp”. The preference was stored without a prefix, so Jenya’s new session at T11 has to ask about units again, and the unprefixed sign-in token is written to the database row. Three problems, and 12 history events are sent with every model call.
Moving the snapshot into state
Raise Turns of history sent to the model to 10 and the answer is right, but every call now carries 20 events and the next long conversation will break it again; at 4 turns only the removal is visible and the cart comes back empty. Set Where the cart lives to State, written through the tool context and the answer is cookbook, reading lamp at any window, because the cart no longer depends on the transcript. Assigned on a fetched session gives an empty cart: no event carried those writes, so each load returned the old value.
Failure boundary: scope and durability
Set Unit preference key to user:preferred_units and the new session already knows metric; choose app:preferred_units and Tanishka gets it too, a preference leaked across users. temp:gateway_token is never persisted. With the cart in state, user: and temp:, all checks pass. Now set Session service to In-memory: the restart wipes the session, so the cart is empty and the preference is gone again. Untick Process restart before T10 (it only matters for the in-memory service) and the cart returns.
Reading the run and its limits
Play replays each turn, the T10 answer, the two new sessions and the stored-session audit over sixty inspection seconds; the table compares expected and observed values. Next event, Restart, Speed and Inspection time control the replay. This is a simplified model of the documented behaviour, not ADK source: real services differ in how they merge user: and app: values and in what a restart keeps, so confirm the guarantees of the service you deploy.