Summary
Vercel sandbox sessions stop immediately after every completed agent turn, while OpenInspect transitions the sandbox back to ready. The UI therefore reports the sandbox as available even though Vercel shows the underlying session as stopped.
This is not caused by the configured sandbox timeout. Vercel snapshots are destructive: creating a snapshot automatically shuts down the sandbox and makes it unreachable.
Reproduction
- Configure
SANDBOX_PROVIDER=vercel with a working base or repository image.
- Start a session and wait for the sandbox runtime to report
ready.
- Complete a turn successfully.
- Observe the sandbox in Vercel and the status shown in OpenInspect.
- Send a follow-up prompt.
Observed behavior
The production sequence reproduced twice:
- The turn completed successfully.
- About 90 ms later, OpenInspect started an
execution_complete snapshot.
- About 130-170 ms after snapshotting began, the sandbox WebSocket disconnected with code
1006 while local status was snapshotting.
- The snapshot completed successfully about 12 seconds later.
- OpenInspect restored and broadcast the previous status,
ready, even though the Vercel session was stopped.
- The follow-up prompt reported
reason=no_sandbox and created a replacement session from the repository prebuild instead of restoring the newly created session snapshot.
No explicit stopSession request occurred at turn completion. The snapshot operation itself stopped the Vercel session.
Root cause
The provider-neutral lifecycle assumes snapshots preserve a running sandbox:
- Every
execution_complete schedules triggerSnapshot("execution_complete") in packages/control-plane/src/session/sandbox-events/execution.handler.ts.
VercelSandboxProvider.takeSnapshot() calls the Vercel session snapshot endpoint in packages/control-plane/src/sandbox/providers/vercel/provider.ts.
- Vercel stops the running session while creating that snapshot.
SandboxLifecycleManager.triggerSnapshot() transitions ready -> snapshotting -> ready in packages/control-plane/src/sandbox/lifecycle/manager.ts.
- Although the Vercel snapshot response includes the resulting
session.status, the adapter discards it and returns only the snapshot ID.
- The frontend correctly renders the persisted
ready state; it never receives stopped until delayed heartbeat reconciliation marks the sandbox stale.
Existing tests encode the incompatible assumption by using a running session in the mocked Vercel snapshot response and expecting successful snapshots to restore ready.
Impact
- The UI exposes stale terminal and preview access as if the sandbox were available.
- Every completed turn unnecessarily terminates the Vercel compute session.
- Follow-up prompts pay replacement startup latency.
- Because snapshot restore selection requires
stopped, stale, or failed, a follow-up can start from the repository prebuild rather than the saved session snapshot, risking loss of uncommitted filesystem changes.
- A queued prompt can race the snapshot that stops the sandbox before queue dispatch.
Proposed remediation
Add a provider capability such as snapshotStopsSandbox or supportsLiveSnapshots and set it appropriately for Vercel. Skip routine execution_complete snapshots for providers whose snapshots stop the running session.
Continue snapshotting through the existing inactivity/termination path, which already persists stopped, clears access, and broadcasts the terminal state before taking the snapshot.
If per-turn snapshots are mandatory, snapshot success must instead transition Vercel from snapshotting to stopped, clear access, detach the bridge, and restore that snapshot on the next prompt. That alternative is accurate but intentionally stops the sandbox after every turn.
Longer term, Vercel's persistent named-sandbox resume lifecycle could be modeled explicitly. The current provider advertises supportsPersistentResume: false.
Acceptance criteria
- Completing a turn does not stop a Vercel sandbox before the configured inactivity boundary.
- OpenInspect never broadcasts
ready for a Vercel session that snapshotting has stopped.
- Inactivity still transitions to
stopped, clears access, snapshots once, and allows the next prompt to restore the saved state.
- A follow-up prompt preserves filesystem changes from the previous turn.
- Provider/lifecycle tests model Vercel's destructive snapshot behavior instead of returning a running session.
Summary
Vercel sandbox sessions stop immediately after every completed agent turn, while OpenInspect transitions the sandbox back to
ready. The UI therefore reports the sandbox as available even though Vercel shows the underlying session as stopped.This is not caused by the configured sandbox timeout. Vercel snapshots are destructive: creating a snapshot automatically shuts down the sandbox and makes it unreachable.
Reproduction
SANDBOX_PROVIDER=vercelwith a working base or repository image.ready.Observed behavior
The production sequence reproduced twice:
execution_completesnapshot.1006while local status wassnapshotting.ready, even though the Vercel session was stopped.reason=no_sandboxand created a replacement session from the repository prebuild instead of restoring the newly created session snapshot.No explicit
stopSessionrequest occurred at turn completion. The snapshot operation itself stopped the Vercel session.Root cause
The provider-neutral lifecycle assumes snapshots preserve a running sandbox:
execution_completeschedulestriggerSnapshot("execution_complete")inpackages/control-plane/src/session/sandbox-events/execution.handler.ts.VercelSandboxProvider.takeSnapshot()calls the Vercel session snapshot endpoint inpackages/control-plane/src/sandbox/providers/vercel/provider.ts.SandboxLifecycleManager.triggerSnapshot()transitionsready -> snapshotting -> readyinpackages/control-plane/src/sandbox/lifecycle/manager.ts.session.status, the adapter discards it and returns only the snapshot ID.readystate; it never receivesstoppeduntil delayed heartbeat reconciliation marks the sandbox stale.Existing tests encode the incompatible assumption by using a
runningsession in the mocked Vercel snapshot response and expecting successful snapshots to restoreready.Impact
stopped,stale, orfailed, a follow-up can start from the repository prebuild rather than the saved session snapshot, risking loss of uncommitted filesystem changes.Proposed remediation
Add a provider capability such as
snapshotStopsSandboxorsupportsLiveSnapshotsand set it appropriately for Vercel. Skip routineexecution_completesnapshots for providers whose snapshots stop the running session.Continue snapshotting through the existing inactivity/termination path, which already persists
stopped, clears access, and broadcasts the terminal state before taking the snapshot.If per-turn snapshots are mandatory, snapshot success must instead transition Vercel from
snapshottingtostopped, clear access, detach the bridge, and restore that snapshot on the next prompt. That alternative is accurate but intentionally stops the sandbox after every turn.Longer term, Vercel's persistent named-sandbox resume lifecycle could be modeled explicitly. The current provider advertises
supportsPersistentResume: false.Acceptance criteria
readyfor a Vercel session that snapshotting has stopped.stopped, clears access, snapshots once, and allows the next prompt to restore the saved state.