Skip to main content

Persistence and volumes

A sandbox's /workspace lives on local disk and disappears with the sandbox. A persistence mode decides what else survives, on a shared volume of your account backed by object storage.

Persistence modes​

ModeWhat survivesPauseBest for
EPHEMERALNothing.Not available (terminate instead).One-shot code execution, untrusted snippets, warm pools.
DIRECTORYEvery file written under the mount path (default /workspace/persist), as soon as it is closed.Instant; nothing to copy.Long-lived work that must survive any timeout: repositories, artifacts, conversation workspaces.
SNAPSHOTThe whole workspace, archived at pause and restored at resume.Packs the workspace (minus snapshotExclude) into one archive.Restoring a full environment (installed packages, build caches) between sessions.
BOTHA live directory plus a whole-workspace snapshot at pause, on the same volume.Packs the workspace.Interactive agents that pause between turns and keep important files in the directory.

The template revision sets the default; each create call can override it with persistenceMode.

Timeouts terminate, they do not pause. When a sandbox hits its idle timeout or maximum lifetime, DIRECTORY data is already safe, but SNAPSHOT/BOTH changes made since the last pause are lost. If losing work on a timeout is not acceptable, keep it under the mount path (DIRECTORY or BOTH), or pause explicitly before you stop using the sandbox.

Where the volume comes from​

  • Created for you. In a volume mode without volumeName, Quave ONE creates a volume named sbvol-<sandboxId> on an object storage point the account can use in the sandbox's region: your own bucket when you connected one there, otherwise the Quave ONE platform point of the region. If neither exists, the create call answers 409.
  • Reused by name. Pass volumeName to attach an existing active shared volume of the account in the same region. This is how a new sandbox continues the work of a previous one.

Terminating or pausing a sandbox never removes its volume. Volumes appear on the Shared Storage page with the sandbox as their origin, and in GET /shared-volumes (MCP: list-shared-volumes) with origin.kind: "sandbox".

One workspace per conversation​

A common pattern is one volume per conversation (or project, or user), reused by every sandbox that works on it:

  1. Create the volume once:

    curl -X POST "$API/shared-volume/create" \
    -H "Authorization: $TOKEN" -H 'Content-Type: application/json' \
    -d '{"accountId": "ACCOUNT_ID", "region": "us-5", "name": "conv-42", "size": "10Gi", "storageClassName": "STORAGE_SERVER_NAME"}'

    Pick storageClassName from GET /storage-servers?accountId=ACCOUNT_ID&region=us-5 (MCP: list-storage-servers), an object storage (volobj) server.

  2. Create every sandbox for that conversation with "persistenceMode": "DIRECTORY" and "volumeName": "conv-42", and keep files under /workspace/persist.

  3. Terminate sandboxes freely; the next one sees the same files.

  4. When the conversation is deleted, remove the volume (POST /shared-volume/remove, MCP: remove-shared-volume). It stays restorable for purgeAfterDays (default 7); POST /shared-volume/restore brings it back.

Only one sandbox should write a given volume at a time. With lockOnWrite (the default on your own bucket), a second writer of the same file gets EBUSY.

File ownership​

Sandbox commands run as uid/gid 1001. Volumes created for a sandbox (sbvol-…) report every file as owned by 1001, so chmod, touch -d, tar -x, git, and package managers behave normally.

A volume you create yourself reports the owner configured on its storage point. When sandboxes will use it, connect your bucket with uid and gid 1001, or update the point before creating the volume (POST /storage-server/object-storage/update, MCP: update-object-storage-server).

Use your own bucket​

To keep sandbox data in your own S3-compatible bucket (AWS S3, Cloudflare R2, OCI Object Storage, MinIO, and others), connect it once per region:

curl -X POST "$API/storage-server/object-storage/create" \
-H "Authorization: $TOKEN" -H 'Content-Type: application/json' \
-d '{
"accountId": "ACCOUNT_ID",
"region": "us-5",
"endpoint": "s3.us-east-1.amazonaws.com",
"bucket": "my-sandbox-data",
"accessKey": "AKIA...",
"secretKey": "...",
"uid": 1001,
"gid": 1001
}'

Credentials are write-only and never returned. Data is encrypted with a master key that is generated for you (or supplied as masterKey); a member with the Secrets Access role can reveal it on the Shared Storage page. From then on, volumes created for sandboxes in that region land in your bucket. MCP: create-object-storage-server. Full field list in the Shared Volumes API.

Snapshots​

In SNAPSHOT and BOTH:

  • Pausing writes one archive of the workspace to the volume, skipping snapshotExclude patterns, up to snapshotMaxMb (default 2048 MB uncompressed). The pause request can override both for that pause only.
  • After a pause, persistence.lastSnapshotAt and persistence.lastSnapshotBytes describe the archive; persistence.lastSnapshotError is set when the last snapshot or restore failed.
  • Resume restores the latest archive before the sandbox serves commands.
  • If the restore at start failed, a later pause is refused unless you pass force: true, so a near-empty workspace never overwrites the last good snapshot.

Costs​

Volumes are billed as shared storage, for what they hold. Paused sandboxes are not billed for compute. See Pricing and Storage.