Skip to main content
import { Sandbox, Volumes } from '@declaw/sdk';
import type { VolumeInfo, VolumeAttachment } from '@declaw/sdk';
A volume is a tenant-owned blob (gzip-compressed tar archive) that lives in Declaw’s object store. You upload a volume once with Volumes.create(...) and attach it to any number of sandboxes at create time via Sandbox.create({ volumes: [...] }). On boot, Declaw streams the blob from object storage and materializes its regular-file entries under the attachment’s mountPath before the first command runs.

Phase 1 contract

  • Format: only gzip-compressed tar archives (application/gzip). Symlinks, hardlinks, device nodes, and entries containing .. are dropped on the server.
  • Size: upload body is capped at 4 GiB.
  • Semantics: read-at-boot. A volume is materialized into each sandbox’s overlay filesystem when it attaches. Writes inside the sandbox are private to that sandbox and never flow back to the volume.
  • Ownership: a volume is strictly owner-scoped. You can attach only your own volumes.

Volumes.create()

Upload a tar.gz and register it. The body is a Uint8Array or ArrayBuffer; pass a streaming body from disk by reading with fs.readFile, or build it in-memory (see the cookbook for a zero-dep tar writer).
import { readFile } from 'node:fs/promises';
import { Volumes } from '@declaw/sdk';

const bytes = await readFile('dataset.tar.gz');
const vol = await Volumes.create('training-set-v1', bytes);
console.log(vol.volumeId, vol.sizeBytes);
Signature
Volumes.create(
  name: string,
  data: Uint8Array | ArrayBuffer,
  opts?: VolumeCreateOpts,
): Promise<VolumeInfo>
name
string
required
Human-readable name. Not used for addressing — the server returns a stable volumeId.
data
Uint8Array | ArrayBuffer
required
The raw tar.gz bytes to upload.
opts.contentType
string
default:"'application/gzip'"
Content-Type header sent with the upload. Leave as default for Phase 1.
opts.apiKey
string
Override the API key from environment.
opts.domain
string
Override the API domain (e.g. api.declaw.ai).
opts.requestTimeout
number
Per-request timeout in milliseconds. Raise this for multi-GiB uploads.

Volumes.list()

List all volumes owned by the caller, newest first.
for (const v of await Volumes.list()) {
  console.log(v.volumeId, v.name, v.sizeBytes);
}

Volumes.get()

Fetch metadata for a single volume.
const vol = await Volumes.get('vol-abc123');
Throws NotFoundError if the volume does not exist or is owned by a different tenant.

Volumes.delete()

Delete the blob and the metadata row.
await Volumes.delete('vol-abc123');

Attaching to a sandbox

Pass volumes: [...] to Sandbox.create:
import { Sandbox, Volumes } from '@declaw/sdk';
import type { VolumeAttachment } from '@declaw/sdk';

const vol = await Volumes.create('dataset', await readFile('dataset.tar.gz'));

const sbx = await Sandbox.create({
  template: 'python',
  timeout: 600,
  volumes: [{ volumeId: vol.volumeId, mountPath: '/data' }],
});

const result = await sbx.commands.run('ls -la /data');
console.log(result.stdout);
volumes
VolumeAttachment[]
One or more attachments. Each is { volumeId: string, mountPath: string }. mountPath must be an absolute path and must not target a system directory (/, /etc, /usr, /proc, /sys, /dev, /bin, /sbin, /lib, /lib64, /var, /run, /boot).
The same volumeId can appear in many sandbox-create calls in parallel; each sandbox gets its own materialized copy on its overlay.

VolumeInfo shape

interface VolumeInfo {
  volumeId: string;      // "vol-..."
  ownerId: string;
  name: string;          // human-readable, supplied at create
  blobKey: string;       // object-store path, for reference
  sizeBytes: number;
  contentType: string;   // "application/gzip"
  metadata: Record<string, string>;
  createdAt: string;     // ISO-8601
}

Errors

SituationError classHTTP
Volume not found or not owned by callerNotFoundError404
mountPath is a system directory or relativeInvalidArgumentError400
Referenced volumeId doesn’t belong to caller at attach timeAuthenticationError403
Upload body exceeds 4 GiBInvalidArgumentError413

See also