{"slug": "the-session-you-cannot-take-with-you", "title": "The Session You Cannot Take With You", "summary": "Inference APIs are increasingly returning provider-bound state that makes AI sessions non-portable, according to a critical analysis by Earendil. Features like encrypted content and server-side storage prevent users from fully owning their session transcripts, as the operational state belongs to the inference provider rather than the user. The analysis argues that a truly portable session should allow exporting a transcript that another model can continue from, without requiring the old provider to dereference IDs or decrypt blobs.", "body_md": "The original promise of an inference API was wonderfully simple: send some input, receive some output. If you kept both, you had the conversation. You could inspect it, archive it, replay it, or give it to a different model.\n\nThat abstraction was never completely true. [Prompt caches\nlive](https://earendil.com/posts/prompt-caching/) on somebody else's GPUs, tokenization differs\nbetween models, and sampling is not reproducible (and quite intentionally so).\nBut the *semantic record* of a session in the form of a transcript could still\nbelong to the user. A transcript should contain the instructions, messages,\ntool calls and tool results. Another sufficiently capable model might not\ncontinue identically, but it could understand what happened and take over.\n\nInference APIs are frustratingly moving away from that property, at least somewhat. They increasingly return a mixture of text and provider-bound state that is very intentionally non-portable.\n\nEach feature comes with a basic justification that's trivial for a provider to come up with, along with good arguments for why this is good for the user. Together all of these things change the ownership reality of an AI session: the transcript on your machine is no longer your session but a partial view of a session whose operational state belongs to an inference provider and not you.\n\nWe are not fans of this direction, and we want to talk a bit about what it means to you, as a user, and what it means to us, as people developing tools in this space.\n\nBy a portable session we do not mean that switching from one model to another must produce the same next token. That's a given because models have different capabilities, trained personalities, context windows, and ways of working with tools. And well, it's all quite nondeterministic anyway. Portability means something more modest:\n\n``` js\nconst transcript = session.export();\nrevokeCredentials(oldProvider);\nsession = newProvider.continueFrom(transcript);\n```\n\nThe archive should contain enough intelligible information for another model to continue the work. It should not require the old provider to dereference an ID, decrypt a blob, remember a search result, or reconstruct a summary.\n\nThis gives us five useful tests:\n\nA response ID is not a transcript, a ciphertext the user cannot decrypt is not user-controlled state, a list of citations is not the evidence that was placed in the model's context by a search result.\n\nThe naming and marketing around these features can be misleading.\n`encrypted_content`\n\nsounds like a privacy feature under the user's control.\nUsually it is a capsule that the client cannot read and only the provider can\nopen. The provider chooses the keys, decrypts the content for its own models,\nand defines where the data can be replayed.\n\nA better term is **provider-sealed state**.\n\nProvider sealing can have a real privacy benefit. OpenAI, for example, can\nreturn encrypted reasoning to a client using `store: false`\n\n, then decrypt it in\nmemory on the next request without persisting the intermediate state. That is\nbetter than requiring server-side conversation storage, particularly for Zero\nData Retention customers. But, remember, there is not really anything that\nneeds encryption to begin with!\n\nMost importantly, this encryption does not hide the data from the inference provider; it hides it from you.\n\nOpenAI's Responses API stores responses by default. Its documentation says\nresponse objects are retained for at least 30 days by default; items attached to\na Conversation are not subject to that 30-day TTL. `store: false`\n\nis available\nand should be used, as it makes it work more like completions: the data is not\nstored on OpenAI's servers.\n\nThe new Gemini Interactions API has made a similar choice. It defaults to\n`store: true`\n\n; on the paid tier interactions are retained for 55 days, and on\nthe free tier for one day.\n\nAnd obviously, the idea of storing state on the server is quite attractive:\n\n``` js\nconst first = responses.create({\n  model: \"frontier-model\",\n  input: \"Investigate this production failure\",\n  store: true,\n});\n\nconst second = responses.create({\n  model: \"frontier-model\",\n  previousResponseId: first.id,\n  input: \"Now implement the fix\",\n  store: true,\n});\n```\n\nThe application sends less data, the provider can preserve hidden reasoning and\ntool state, and cache routing becomes easier. But if the local application only\nrecords the user messages and final text, `first.id`\n\nis now a foreign key into a\ndatabase it does not control.\n\nAll major labs claim to have legitimate reasons not to expose raw chain of thought. As a result, on non-open-weights models we typically do not see these tokens.\n\nRaw reasoning is not visible via the API. With stored responses, prior\nreasoning can be recovered through `previous_response_id`\n\n. With `store: false`\n\n,\nthe API returns `encrypted_content`\n\n, which the client must preserve and replay.\nPersisted reasoning remains opaque even when `reasoning.context: \"all_turns\"`\n\nlets a later sample use it.\n\nAnthropic returns the encrypted full thinking in a `signature`\n\nfield. The\nreadable thinking text, when enabled, is a summary produced by another model,\nnot the raw chain of thought. Thinking blocks must be passed back unchanged\nduring tool-use turns. Anthropic's documentation also says thinking blocks are\ntied to the model that produced them and should be stripped when switching\nmodels. So these reasoning traces do not attempt to be portable within\nAnthropic.\n\nThe same story repeats with all closed-weights models.\n\nThese encryption mechanisms permit continuity *inside* an ecosystem but they do\nnot create a portable transcript that can be taken to another provider's model.\nA session archive can contain the blob, but another model cannot use its\nmeaning:\n\n```\n{\"type\": \"reasoning\", \"encrypted_content\": \"gAAAAAB...\"}\n{\"type\": \"thinking\", \"thinking\": \"\", \"signature\": \"EqQBCg...\"}\n{\"type\": \"thought\", \"summary\": [], \"signature\": \"EpoGCp...\"}\n```\n\nServer-side web search is one of the clearest examples of a transcript having holes in it hidden from the user. A client-side search tool behaves like any other tool:\n\n``` js\nconst result = search(query);\nrecord({\n  query,\n  retrievedAt: now(),\n  results: result.map((item) => ({\n    url: item.url,\n    title: item.title,\n    passages: item.passages,\n  })),\n});\nmodel.send({ toolResult: result });\n```\n\nThe user can inspect the ranking and passages, refetch the pages, cache a copy, or provide the same evidence to another model.\n\nWith hosted search, the provider performs a private tool loop. OpenAI, Google and Anthropic expose search actions, citations, and optionally a list of source URLs, but not the complete text context used to produce an answer. A URL is not a stable replay: its contents can change, disappear, become personalized, or have been reduced to a provider-specific snippet before the model saw it.\n\nThe final answer may be perfectly good. The problem appears on the next turn:\n\nCompare the third source with the first one, re-check the disputed number, and continue this research using another model.\n\nThe new model receives an answer and a few URLs. It does not receive the result ranking, extracted passages, filtered-out material, or exact evidence the first model used. The old provider is still part of the session even if the next request goes elsewhere.\n\nHosted search should have a full-fidelity export mode containing queries, result metadata, retrieved passages, timestamps, content hashes, and filtering steps. Concise citations can remain the user interface; they should not be the only record.\n\nLong agent sessions eventually need compaction. A visible, client-controlled summary is lossy, but it is at least inspectable and transferable. The user can review it, edit it, or ask a different model to produce another one.\n\nOpenAI's server-side compaction instead emits an encrypted compaction item. The\ndocumentation describes it as \"opaque and not intended to be\nhuman-interpretable.\" The standalone `/responses/compact`\n\nendpoint returns a\n\"canonical next context window\" that clients are instructed to pass on as-is.\n\nConceptually, the transition looks like this:\n\n``` js\n// Before: expensive but portable\nlet history = [\n  userMessage,\n  assistantMessage,\n  toolCall,\n  fullToolResult,\n  // ... 200,000 more tokens of intelligible history\n];\n\n// After: cheap to continue only with the original provider\nhistory = [\n  {\n    type: \"compaction\",\n    encryptedContent: \"enc_provider_only_state...\",\n  },\n  ...recentItems,\n];\n```\n\nOpenAI can continue from the compressed meaning, but a different provider sees an unreadable string plus a recent suffix (well, would see it, we never pass this sort of information to another provider).\n\nThis is not technically necessary. Anthropic's server-side compaction returns\na `compaction`\n\nblock with a readable `content`\n\nfield. It lets the client provide\ncustom summarization instructions, and the resulting summary can be inspected\nand passed to another model. Client-side compaction is also possible with any\nprovider.\n\nOpenAI's sealed artifact may preserve more model-specific state than a plain summary and may perform better on the original model. That is a reasonable optional optimization. It should be accompanied by a readable handoff summary, not replace one. But again, a lot of this has the added benefit of further locking you into one ecosystem.\n\nMulti-agent systems compound the problem because there is no longer one transcript. There is a tree of sessions and a stream of messages between them. Usually they are prompts as if a human wrote them, just now authored by a machine for another machine.\n\nOpenAI's hosted Responses Multi-agent beta returns three new item types:\n`multi_agent_call`\n\n, `multi_agent_call_output`\n\n, and `agent_message`\n\n. The example\nfor `spawn_agent`\n\ncontains an encrypted `message`\n\nargument, and inter-agent\nmessages contain only `encrypted_content`\n\n. Automatic server-side compaction is\nimplicitly enabled for every agent when Multi-agent is enabled, even if the\nclient did not request it. Reasoning summaries are not supported. The API also\ninjects root and subagent instructions that the developer cannot edit or remove.\n\nThis is a bundle of non-transferable state: sealed delegation, sealed agent messages, separate automatically compacted contexts, hidden reasoning, and provider-hosted orchestration.\n\nA related change landed in the open-source Codex client in June 2026. The\ncommit, titled [\"Encrypt multi-agent v2 message\npayloads\"](https://github.com/openai/codex/commit/5f4d06ef186b896d316620556e561d59206c3ebf),\nexplains the flow directly:\n\n```\n// Parent model's tool call, as persisted by Codex\n{\n  \"name\": \"spawn_agent\",\n  \"arguments\": {\n    \"task_name\": \"worker\",\n    \"message\": \"<ciphertext>\"\n  }\n}\n\n// Child model's input\n{\n  \"type\": \"agent_message\",\n  \"author\": \"/root\",\n  \"recipient\": \"/root/worker\",\n  \"content\": [{\n    \"type\": \"encrypted_content\",\n    \"encrypted_content\": \"<ciphertext>\"\n  }]\n}\n```\n\nThe Responses API encrypts the tool argument emitted by the parent, Codex\nforwards it, and the API decrypts it internally for the child. Codex's own\n`InterAgentCommunication.content`\n\nis empty. The exact task is absent from its\nreadable rollout and history.\n\nPresumably this is not merely an abstract model-switching concern. One could\nimagine if the child changes the wrong file, leaks a secret, duplicates another\nagent's work, or follows a bad assumption, the user cannot answer the simple\nquestion of *what was that agent asked to do?*\n\nAn [open Codex issue](https://github.com/openai/codex/issues/28058) asks for the\nencrypted delivery to retain a separate readable audit copy. That is the\nminimum acceptable design. Better still, plaintext inter-agent messages should\nremain the norm.\n\nProbably not. Most people do not switch their operating system or phone provider every week either. But even if you do not utilize that freedom, it matters because it changes the relationship you have with the provider and the provider has with you.\n\nAs a user you also may need to move a session because a model is retired, a service is down, a price changes, a policy blocks the next request (hello fable), a confidential phase must run locally, or an auditor needs to reconstruct what happened. Agents are also making sessions much longer. A coding or research session can accumulate days of decisions and evidence and a personal assistant may accumulate session transcripts going back years (presumably as we don't have them for that long yet).\n\nThe option to leave also creates discipline. If a provider knows that a user can continue elsewhere, it has to compete on model quality, price, reliability, and trust. If the user's accumulated context can only be interpreted by one provider, it sets very unfortunate incentives.\n\nWe would like inference providers and agent builders to adopt a small set of rules.\n\n`store: false`\n\nshould be easy, documented, and\npreferably the default. Features that require retention should say so at the\npoint of use.There is a related form of lock-in at the model layer.\n\nSome of the largest closed-weight US labs are increasingly hostile to outside\ndistillation. Anthropic's [February 2026\npost](https://www.anthropic.com/news/detecting-and-preventing-distillation-attacks)\nabout alleged campaigns by DeepSeek, Moonshot, and MiniMax calls them\n\"distillation attacks\". Its commercial terms say customers own their outputs,\nbut prohibit using the service to train a competing AI model. At the same time,\nAnthropic's own post acknowledges that \"distillation is a widely used and\nlegitimate training method\" when frontier labs use it on their own models.\n\nAnthropic uses robots to gather data from the public web for model development\nand they famously cut up books to scan them. OpenAI similarly says it trains on\nfreely accessible public internet content and has argued that training on\npublicly available internet materials is fair use. Both companies describe\ndistillation as a normal way to produce smaller models when it happens inside\ntheir own walls. OpenAI has also offered an explicit [first-party API\ndistillation workflow](https://openai.com/index/api-model-distillation/) for\nusing outputs from a stronger OpenAI model to fine-tune a smaller OpenAI model.\n\nThe moral asymmetry is still hard to miss. The labs ask society to accept that machines may learn from the enormous body of work humans placed on the internet—often without advance, individual permission—while insisting that other machines must not learn from outputs the labs generate. The broadest version of that principle conveniently allows learning to flow into closed models but not back out of them.\n\nWe think the default attitude toward distillation should move from hostility to support. Distillation can turn expensive frontier capability into smaller, cheaper, faster models that can run locally, offline, on constrained hardware, or under the user's control. It can increase competition, preserve capability when an API disappears, and reduce the compute and energy required for common tasks.\n\nA user should be able to close an account, keep a session, and hand it to another model. The new model may disagree, ask questions, or perform worse. It should not be staring at ciphertext where the old model saw the user's history, evidence, plans, and delegated work.\n\nWe do not object to providers building better stateful APIs. We object to better performance being coupled to less user control. Stateful storage should be optional, hosted tools should be observable, compaction should be readable, agent communication should be auditable and ideally opaque reasoning is not opaque or at least should have a portable handoff. Distillation should be a path by which capability becomes more available, not a taboo used to justify ever higher walls.", "url": "https://wpnews.pro/news/the-session-you-cannot-take-with-you", "canonical_source": "https://earendil.com/posts/session-portability/", "published_at": "2026-07-29 22:00:00+00:00", "updated_at": "2026-07-30 14:32:58.469358+00:00", "lang": "en", "topics": ["ai-infrastructure", "ai-policy", "ai-ethics"], "entities": ["OpenAI", "Gemini", "Earendil"], "alternates": {"html": "https://wpnews.pro/news/the-session-you-cannot-take-with-you", "markdown": "https://wpnews.pro/news/the-session-you-cannot-take-with-you.md", "text": "https://wpnews.pro/news/the-session-you-cannot-take-with-you.txt", "jsonld": "https://wpnews.pro/news/the-session-you-cannot-take-with-you.jsonld"}}