SandboxSDK & APIImages & storage

Images and storage

Use an image for installed tools and dependencies. Use a snapshot for a workspace’s files.

Build an image

Install packages once and reuse the resulting image when creating sandboxes.

TypeScript
import { Image } from "@tangle-network/sandbox";
import { Sandbox } from "@tangle-network/sandbox";

const apiKey = process.env.TANGLE_API_KEY;
if (!apiKey) throw new Error("Set TANGLE_API_KEY");

const client = new Sandbox({
  apiKey,
  baseUrl: "https://sandbox.tangle.tools",
});

const image = await Image.create("python:3.12-slim")
  .addPackages(["pandas"])
  .workdir("/workspace")
  .build({ client, onProgress: (event) => console.log(event.message) });

const box = await client.create({
  environment: image.id,
  maxLifetimeSeconds: 900,
});
await box.waitFor("running");
const result = await box.exec("python -c 'import pandas; print(pandas.__version__)'");
console.log(result.stdout);
await box.delete();

Image.fromDockerfile() accepts a Dockerfile instead of the builder above. The builder also supports system packages, environment variables, build arguments, and a working directory. Image builds require a deployment with image-building support.

Publish a workspace image

box.images.publish() builds an image from a workspace Dockerfile and publishes it to your registry. Pass contextPath, dockerfilePath, repository, and registry auth from your server. Registry credentials stay with the publisher rather than entering the sandbox. The result includes the image digest and declared ports.

Share a starting environment

OperationSDK
List available environmentsclient.environments.list()
Browse public templates and versionsclient.publicTemplates.list(), .get(), .versions()
Publish a public template or versionclient.publicTemplates.publish(), .publishVersion()
Manage a team’s templatesclient.teams.listTemplates(), .createTemplate(), .deleteTemplate()
Start from a saved templateclient.create({ templateId })

Explicit create options override a template’s defaults. Add teamId when creating a sandbox shared with your team.

Store snapshots in your bucket

Set the S3 environment variables used below. This example saves a checkpoint to your bucket and restores that exact snapshot.

TypeScript
import type { StorageConfig } from "@tangle-network/sandbox";
import { Sandbox } from "@tangle-network/sandbox";

const apiKey = process.env.TANGLE_API_KEY;
if (!apiKey) throw new Error("Set TANGLE_API_KEY");

const client = new Sandbox({
  apiKey,
  baseUrl: "https://sandbox.tangle.tools",
});

const bucket = process.env.S3_BUCKET;
const region = process.env.S3_REGION;
const accessKeyId = process.env.AWS_ACCESS_KEY_ID;
const secretAccessKey = process.env.AWS_SECRET_ACCESS_KEY;
if (!bucket || !region || !accessKeyId || !secretAccessKey) {
  throw new Error("Set S3_BUCKET, S3_REGION, AWS_ACCESS_KEY_ID, and AWS_SECRET_ACCESS_KEY");
}
const storage: StorageConfig = {
  type: "s3",
  bucket,
  region,
  credentials: { accessKeyId, secretAccessKey },
  prefix: "sandbox-snapshots/",
};
const box = await client.create({
  maxLifetimeSeconds: 900,
  storage,
});
await box.waitFor("running");
await box.write("/workspace/checkpoint.txt", "saved");
const saved = await box.snapshot({ storage });
await box.write("/workspace/checkpoint.txt", "changed");
const restored = await box.restoreFromStorage(storage, { snapshotId: saved.snapshotId });
if (!restored) throw new Error("Snapshot was not found in storage");
console.log(await box.read("/workspace/checkpoint.txt"));
await box.delete();

StorageConfig supports S3, Cloudflare R2, and Google Cloud Storage with HMAC credentials. R2 requires its account endpoint. Keep storage credentials in your server environment.

Customer-storage snapshots do not support idempotencyKey. Deleting the sandbox does not delete objects in your bucket. For managed snapshots, selected-path restore, and cloning a workspace, see Previews and snapshots.