Session Persistence: Why Your AI Forgets You Between Tabs
Inference is stateless by design. Every "conversation" is the full transcript replayed, and the tab boundary is just where the client stops replaying it.
There is no conversation. There is a function call. Every time you press enter in a chat UI, the client serializes the entire message history it has been accumulating in memory and posts it to a stateless HTTP endpoint. The model reads that array, produces the next message, and forgets everything. The server holds no session. What you experience as a thread is the client replaying the transcript to a process with amnesia, over and over, at increasing cost.
The request looks like this, and it looks like this on turn 1 and on turn 40:
POST /v1/messages
{
"model": "...",
"messages": [
{ "role": "user", "content": "I'm building on Postgres, not Mongo." },
{ "role": "assistant", "content": "Got it, Postgres." },
{ "role": "user", "content": "..." },
/* ...38 more... */
{ "role": "user", "content": "which driver should I use?" }
]
}Once you internalize that, the tab question answers itself. The tab is where the message array lives. Close it and the array is garbage collected. Open a new one and you get a new array, length zero. The model did not forget you, because the model never knew you. The client stopped replaying.
The KV cache is not memory, and it expires
The usual objection at this point is prompt caching, and it is worth being precise about what caching does. During generation, the attention layers compute key and value tensors for every token in the prompt. Those tensors are deterministic given the prefix, so a provider can store them and skip recomputation on the next request if the prefix matches exactly. That is a real optimization: it cuts time-to-first-token substantially and providers bill cached input tokens at a steep discount.
What it is not is state you can rely on. Three properties disqualify it as a continuity mechanism:
- It is prefix-exact. One changed byte anywhere before the cache breakpoint and the entry is a miss. Insert a memory into the middle of your prompt and you have invalidated everything after it.
- It is short-lived. Anthropic's prompt caching documentation specifies a five-minute TTL refreshed on each cache hit, with a longer one-hour option available. Either way, it is a window measured in minutes, not the weeks over which a real project runs.
- It is opaque and provider-scoped. You cannot read it, enumerate it, migrate it, or hand it to a different vendor. A cache entry on one provider is worth exactly nothing to another.
Caching makes the replay cheaper. It does not remove the need to replay, and it certainly does not survive to tomorrow. It is a CDN for tensors.
The design consequence
Continuity is a storage problem that happens to live next to a model. That is a boring conclusion, and it is the correct one, and it has a sharp implication: whoever owns the transcript store owns the continuity. If the store is the browser tab, continuity ends at the tab. If it is the vendor's account database, continuity ends at the vendor boundary, which is why your ChatGPT history is invisible to Claude and always will be.
Cross-tab, cross-device, cross-model continuity therefore requires an external store that all clients can read and write, plus a retrieval step that rehydrates the relevant subset into whatever prompt is being assembled. The pieces are not exotic:
# at the start of any turn, on any client, on any model
ctx = store.recall(query=user_msg, k=8)
ctx += store.get_recent(limit=5)
messages = [system(ctx)] + local_turns + [user(user_msg)]
# after the turn, extract what is worth keeping
store.remember(distill(user_msg, assistant_msg))Note what is being written. Not the transcript. A transcript is the wrong storage unit, because it grows linearly with usage while its information content does not. Twelve turns of debugging that conclude "the connection pool was set to 1" should be stored as that one fact plus a pointer, not as twelve turns. This distillation step is what makes the store queryable at all: a store of raw transcripts is a store where every retrieval returns mostly filler.
Why "just use a bigger context window" does not fix it
A million-token window sounds like it eliminates the problem, and it does not, for four separate reasons.
You still have to fill it. The window is a buffer, not a database. Something has to put the previous six months into the request, which means something has to have stored the previous six months and chosen what to include. That something is the memory system you were trying to avoid building.
Attention cost is quadratic in sequence length. Even with the optimized kernels everyone now uses, the arithmetic in the attention step scales with n squared while the memory traffic is linearized. Doubling the context you actually send does not double the cost of the attention computation, it roughly quadruples it. You do not want to pay that per turn for context that was relevant four months ago.
Retrieval quality degrades in the middle. Long-context models reliably do better with material at the very start and the very end of the window than with material buried at 60% depth. A fact you technically included is not a fact the model reliably used.
It does not cross the vendor boundary. This is the one that matters most and gets discussed least. A window of any size is per-request. It has no opinion about where the bytes came from, and it does nothing to make the session you had on your phone with one provider available to a different provider on your laptop. That is an interoperability problem, and no context length solves an interoperability problem.
Where the seam belongs
If the store has to be external and every model has to be able to reach it, the interface needs to be one that clients already speak. That is the argument for putting the memory layer behind MCP rather than behind a proprietary SDK: the client already knows how to discover and call tools, so continuity becomes a capability the host adds rather than an integration each vendor has to agree to build.
Unimatrix is that store. The five tools a client needs (remember, recall, get_recent, continue_from, list_contexts) are documented in the MCP reference, and the honest framing is that we are not making the model remember anything. We are making sure the replay does not start from zero when you switch tabs.
Your AI remembers everything. Everywhere.
Unimatrix gives you a shared, durable memory layer across Claude Desktop, Cursor, ChatGPT, and Gemini. Setup in 2 minutes. Free and paid plans available.
Keep reading
Self-consistency samples k reasoning paths and takes the majority answer. It works because errors scatter and correct answers converge, and it costs k times as much.
License terms, context length, and tool-calling reliability matter more than leaderboard rank. A filter for deciding which open weights deserve a GPU-hour.
An MCP client is a non-browser, long-lived consumer. That breaks the assumptions behind short-lived OAuth tokens, and the fix is scoped keys with rotation.