Native conversation recall
Cloud Agent keeps each chat’s native CLI session in its retained sandbox. The CLI owns the conversation history, and Agent passes each user message through unchanged.
Two questions need separate answers: did the same native session survive, and did the model answer correctly from its history? The September investigation found failures of both kinds. It reproduced native persistence bugs, but it also found models claiming that history was missing even when the request was complete.
For session architecture, see the native Fork/shared-workspace design. The dated findings below are local acceptance evidence. They do not describe the current state of a remote deployment.
Context status
Each turn reports whether the chat’s native context survived:
Context status |
Meaning |
|---|---|
|
No native turn has previously settled for this member |
|
The turn uses the compatible resident CLI process |
|
A replacement process resumes the retained native session |
|
Required native state or container integrity cannot be established; execution is refused |
Stopping a container preserves its writable layer. Losing the container or the Docker data root also loses the required native state. Transcript replay and cross-host restoration are not recovery paths.
Other native CLIs
All five bundled CLIs can keep a failed query for a follow-up, but only when the native turn verifiably ended, activation cleanup completed, and both the transport and native locator remain usable.
CLI |
Native settlement evidence |
|---|---|
Claude Code |
|
Codex |
|
Pi |
|
OpenCode / Kilo |
Bridge |
A command rejection, dead transport, timeout, or cancellation does not count as native settlement. Pi reports terminal API errors as failures, not successful empty turns. OpenCode/Kilo use message-role metadata to collect only assistant-owned text. They resolve late metadata at settlement and exclude events from earlier bridge turns. This keeps user text out of assistant output without changing the native model history.
The pinned Claude 2.1.220 CLI has a reproduced retry-parent-chain defect: a
delayed system/api_error can bypass a successfully retried assistant reply on
a later resume. When the driver sees system/api_retry, it settles the current
turn, saves the native locator, and gracefully retires the process. The next
turn resumes that same session in the same container. A successful turn without
a retry keeps the live process. This handling does not repair transcripts that
the older behavior already damaged.
The sandbox’s http-agent-live-bridge=4 helper pin is required by host
attestation. Version 4 gates every turn on the current live SSE subscription,
and aborts an active native turn if that non-replayable stream is lost. It also
extends autonomous permission replies for both OpenCode and Kilo to the Task
child sessions the root turn explicitly reports, retries a failed one-shot
permission reply, and aborts instead of leaving that request pending. Version 3
added correlated native question replies. Deploy the sandbox_manager/runner and sandbox
image together;
an older helper image must not advertise readiness for the new host.
Release scope and remaining findings
The implementation addresses the reproduced retry/flush history loss and keeps verifiably settled failures across all five CLIs. It also covers Pi error reporting, OpenCode/Kilo assistant-message ownership, and runner/sandbox_manager session identity. The same work corrected the local Responses fixtures and smoke checks.
The documented investigation also left two separate findings:
Finding |
Evidence and limit |
|---|---|
Flash can claim missing history with complete outbound messages |
Reproduced in native and direct synthetic API calls. Reasoning effort and newer CLIs did not reliably fix it; client evidence does not identify the upstream engine/template/model cause. |
Gateway snapshot loses effort configuration and historical thinking blocks in translation |
Reproduced locally. Separate patches outside this repository were not deployment-verified by this investigation; they do not establish that Flash recall is fixed. |
A successful HTTP response does not prove factual recall, and neither does a persisted native session. These fixes do not migrate already damaged transcripts or old disposable chats. Start a new chat when legacy history has no native shared-live membership.
Verification before accepting a deployment
Require CI Gate, including the pinned native CLI request-history regressions. They compare exact user/assistant text, roles, order and repeated occurrences through live follow-ups, immediate close/restore, failed-call retries, and successful internal retries followed by native restores. Sandbox Manager and runner checks must also reject changed locators for successful and settled failed turns. The loopback fixture needs no inference credentials or charges.
Verify the exact host/API SHA, reverse sandbox manager probe and fresh heartbeat using deployment reliability. A working model call does not prove the intended host revision is serving jobs.
Run the opt-in behavior preflight from the target checkout against the target inference Gateway:
CLOUD_AGENT_TEST_API_KEY_FILE=/path/to/test-key \ uv run python -m deploy.preflight.check_model_context \ https://gateway.example.com --repetitions 3
CLOUD_AGENT_TEST_PROXYoptionally names an HTTP proxy. The key remains in the trusted test process, outside sandbox credentials and command arguments. The script sends synthetic messages todeepseek-v4-flashand prints answers and request IDs without authentication headers. Greeting, repeated-question, task, fact/update and no-history cases produce five calls per repetition; the default three repetitions make 15 calls with ordinary inference usage.A non-200 response, stream error, truncation, missing required facts or a recognized missing-history claim fails the check. The script requests native
adaptive/highsettings and also requires observed thinking. Results reportrecall_passedandthinking_observedseparately, retaining the answer even when thinking is absent. Observed thinking does not prove the engine received the exact effort, and missing thinking does not prove history loss. Inspect conservative detector failures: it may reject a reply quoting a bad claim in order to correct it. HTTP 200 alone is insufficient.Use the deployed app to check a new chat, live follow-up and idle restore. Confirm the same retained sandbox and native locator. If an answer reports lost context, compare the outbound request history and settlement evidence before attributing it to persistence.
The preflight is opt-in and is not automatically run by deployment workflows. CI receives no inference key. Repeat it when Gateway model routes, model deployment or CLI pins change. Finite samples test the reported failure without guaranteeing that a model never makes another incorrect claim.
Implementation and checks:
runner.py,
drivers.py,
shared_session_supervisor.py,
shared_protocol.py,
check_model_context.py and
test_claude_driver_context.py.
Current investigation evidence (2026-09-07)
A fresh synthetic reproduction bypassed Cloud Agent and the native CLI entirely:
System:
You are a coding assistant. You can use persistent files for memories between conversations.User:
hiAssistant:
Hello! How can I help you today?User:
我刚才让你做什么了
Using only deepseek-v4-flash, twelve requests compared Anthropic default,
adaptive and enabled thinking with OpenAI default, enabled and disabled thinking
(two samples per configuration). Eleven replies claimed missing history; only
one OpenAI enabled sample recalled hi. All twelve responses were HTTP 200 and
completed normally. This shows that bypassing Anthropic translation or explicitly
requesting thinking is not a reliable fix. It does not identify the selected
upstream provider or prove what its model server received.
API request IDs retained for a future authorized investigation (no gateway logs or configuration were accessed for these tests):
Anthropic adaptive, failed recall:
d419d6b244519572c8481520.OpenAI enabled, successful recall:
3ddbd2035605b4fb3d3a3805.OpenAI enabled, failed recall:
56d2d878c25d78bdbaf52ffb.
A separate local check exercised the gateway source snapshot’s normalizer, translator and adapter through an actual loopback HTTP receiver. All twelve combinations of DeepSeek/SGLang/Ollama profile, streaming mode and inline-system shape preserved the synthetic conversation. It did not exercise deployed dynamic routing, the full router or the upstream model server’s chat template.
The gateway snapshot also strips Anthropic thinking, and drops effort values
when the model config does not declare their domain. These are compatibility
leads, not established causes of the recall failure. No gateway workaround or
model-route change has been shipped as part of this Cloud Agent branch.
Further synthetic tests used OpenAI chat completions with temperature zero and
unchanged messages. A neutral coding-assistant system description recalled hi
in 2/2 samples; adding a file-memory sentence produced false missing-history
claims in 2/2. Explicit high effort produced reasoning output, but only 1/2
replies recalled hi. A further three samples with maximum effort recalled
hi in only 1/3 replies; all three completed normally with reasoning output.
Thus enabling reasoning is not an established fix.
OpenCode also produced a false missing-history answer with complete native
history, so this behavior cannot be attributed solely to Claude’s persistence
or memory feature. These model-behavior failures remain distinct from the
reproduced native failure/LOST and message-ownership bugs fixed above.
The local Docker stack also passed a real-Flash task-history sequence for all five bundled CLIs: initial function-name agreement, two live follow-ups, idle stop and native restore, a terminal API rejection, a successful follow-up and a native fork. The first query also received a locally injected transient API error. Assertions checked every prior successful user/assistant message in the outbound model request, the agreed function name in the visible reply, and the same retained sandbox. The terminal rejection was marked failed for every CLI; the following query and fork retained history. This validates the repaired session lifecycle, but does not override the separate failing greeting-recall samples above or count as verification of a remote deployment.
Fresh greeting checks on the final sandbox image again reproduced false
missing-history claims in OpenCode and Kilo while their outbound requests had
the complete user/assistant history in the correct roles. Their original user
text was no longer copied into the displayed assistant reply. Claude recalled
hi in both live follow-ups and the idle-restore query in this sample; earlier
Codex and Pi greeting checks also recalled it. These finite successful samples
do not eliminate the failing cases or establish an upstream root cause.
Local verification update (2026-09-08)
The original retry behavior was restored only in a test plugin by disabling process retirement. Pinned Claude 2.1.220 then failed the request-history assertion after native restore: the initial
hiwas absent. With the driver fix enabled, all four real native CLI regressions passed (367.95 seconds). The protocol fixture made no remote inference requests.New sandbox_manager/driver identity tests failed before the changes (10 failures), as did all ten shared runner cases for five runtime IDs and two settled outcomes. The combined focused suites now pass 162 tests.
Local Docker smoke and an independent request audit verified all five CLIs across live continuation, idle stop/restore, historical native fork and child stop/restore. The audit compared exact conversational text, roles, order and occurrence counts in 30 requests, including the correct shorter fork prefix. CLI-generated environment annotations were excluded from user text, and two OpenCode/Kilo title requests were identified separately.
That audit first caught a defect in the local Responses mock: it omitted
response.output_item.added/done, so Codex completed jobs without retaining assistant messages. The mock now emits the item/content-part lifecycle, and the smoke requires a nonempty assistant reply belonging to each current job. Codex was rerun after the correction; all six requests had the expected history. The earlier Codex lifecycle pass is not history evidence. This is a local test-fixture fix, not a claim about the deployed inference API.A fresh local Claude chat used the real
deepseek-v4-flashAPI for four turns, with one locally injected retryable failure and an idle restore. Every request retained all earlier user/assistant text in order, including both occurrences of a repeated question. The same container and native session were retained. Flash recognized the initial greeting but also speculated about lost session state; the last answer accurately quotedhi. Sincehiassigns no task, saying that no task was assigned is not itself evidence of memory loss. The unsupported session diagnosis remains a response-quality issue and cannot be treated as proof that Cloud Agent discarded context.make checkpassed formatting, lint and 1,833 tests (194 external/database tests deselected). The four native regressions above ran separately. Local sandbox manager and both runners matched all four changed production source hashes. Temporary gateway overlays were removed after testing. No remote deployment, configuration, logs or web UI were accessed in this verification.
These changes repair reproduced local persistence and identity defects. They do not establish that every missing-history statement has the same cause or that changing reasoning effort can eliminate it. The model-behavior preflight remains a separate acceptance check; production prompts and CLI pins are unchanged by these identity fixes.