A language model is stateless. Each API call starts from nothing: the model reads the tokens it is sent, writes a reply, and keeps nothing. A chat that seems to remember is an application that stores the conversation and resends it, so the model's memory is whatever the application decides to put in the context window on the next call. This film makes that choice visible.
The scenario is one real conversation with `google/gemini-3.8-flash` at temperature 0, recorded on 11 September 2026. In turn 1 the user says the API returns every JSON field in snake_case, never camelCase, and the model promises to follow it. Turn 3 adds that money is stored as integer pence. Four unrelated questions follow, about pagination, cursor headers, caching and request ids. Then the user asks for the TypeScript type of an order response, which only comes out right if the model still knows the rules. Each chapter sends that same request with a different window and shows one of five recorded replies, with the tally across all five.
On the left of the bench is the transcript shelf: the application's stored conversation history, every turn with its real token count from the o200k_base tokenizer. Next to it is the memory store, a few saved facts from this session and earlier ones, and below it the slot for the current request. The upright column is the context window, 300 tokens to the red limit, and every card in it is as tall as its token count. The model box sees only the column. Each call copies cards into the column from the three compartments; whatever is left behind does not exist for the model.
Sent whole, the conversation is 417 tokens and every run uses snake_case. Asked after turn 3, at 192 tokens, the rule is in the window and every run uses it, and four of five name the field total_pence. After turn 7, an application with a 300-token budget does what many chat applications do by default and keeps the newest turns that fit. Turns 1 to 3 drop out without any error or warning, and all five runs switch to camelCase, exactly like a call sent with no history at all. The model did not forget. It was never told.
Persistent memory is the usual fix, and the film shows why it is not a guarantee. A memory store is still just text the application selects and resends. Here the application embeds the request, retrieves the two most similar saved facts and puts them in the system prompt. The snake_case fact comes back, and so does snake_case in every run. The pence fact scores 0.06 against a request that never mentions money units, ranks last behind facts about deploy days and the on-call rota, and is not sent, so no run says pence. Pinning the conventions that must always hold, so they ride in every call whatever the similarity, restores both rules to the window: snake_case holds in five of five runs, and the total is named in pence in two. Having the rule in the window makes it available, not obeyed, so check the output too. Pinned text is not free either: it takes the same slice of the budget on every call, which here left room for only turns 5 to 7 of the history.
The practical rules follow. Decide what must persist, and pin it into every call rather than hoping retrieval ranks it. Retrieve the rest deliberately, and log what was retrieved and what was left out. Track the token budget per call, because truncation is silent from the model's side. Summarising older turns (compaction) is another option not recorded here: it keeps more history in fewer tokens, but a summary can drop a rule just as quietly as truncation does.
The honest caveat is scale. Real context windows run to hundreds of thousands of tokens, so a 300-token budget is shrunk to make the window fill in seven turns; in production the same truncation happens after far longer conversations, or much sooner when an application caps history to save cost and latency. There are five runs per condition, one model and one conversation, and the pence check reads only field names, so a reply that keeps pence in a comment would count as a miss.
The maths
- The window budget
Every call is rebuilt from pieces: the system prompt, any saved facts, the stored turns the application chooses (the set S) and the new request. Each card in the column is as tall as its token count, and the red bar is B. The film shrinks B to 300 so a seven-turn conversation of 417 tokens can overflow it.
- Truncation keeps the newest turns that fit
The common default walks back from the newest turn and stops at the first one that does not fit. With the system prompt and request fixed at 60 tokens, turns 4 to 7 fit in 285 and turns 1 to 3 drop out, including the one that set snake_case. Nothing in the reply says so.
- Retrieval chooses by similarity, not importance
Each saved fact f is scored against the request with openai/text-embedding-3-small. The snake_case fact scored 0.19 and was sent; the integer-pence fact scored 0.06, last of five, below facts about deploy days and the on-call rota, so it never reached the window.
- The model conditions only on the window
The reply is a function of the window w and the fixed weights, nothing else. A stored turn that is not in w has exactly the influence of a turn that was never said, which is why the truncated run and the no-history run give the same camelCase reply.
Related terms
- StatelessStateless means the model API keeps no memory between requests. Each call starts blank, so every request must carry all the context the model needs. This is foundational to how agents are built.
- StatefulStateful describes anything that keeps state across requests: conversation history, memory, a session. In an agent that job belongs to the harness or app, never to the stateless model API.
- Context windowThe context window is the maximum amount of text, measured in tokens, that a model can consider for a single request. It is a hard ceiling, and it is the main resource you manage when working with an agent.
- SessionA session is one continuous conversation with an agent that accumulates history in the context window. Resetting or ending it clears that history and starts the agent from a blank slate.
- Memory systemA memory system is an external store the harness uses to persist facts across sessions and reload them into context. It is how a stateless model ends up behaving as if it remembers you and your project.
- CompactionCompaction is condensing older conversation history into a summary to reclaim context-window space while keeping the important gist. It is lossy by design.