Modal

Modal sandboxes with streaming exec and first-class GPU. Backed by the modal JS SDK; an App + Image are created lazily.

Installation

modal is an optional peer dependency of sbox-sdk, loaded lazily on first use.

pnpm add sbox-sdk modal

Usage

import { createSandboxClient } from "sbox-sdk";
import { modal } from "sbox-sdk/modal";

const client = createSandboxClient({
  provider: modal({
    tokenId: process.env.MODAL_TOKEN_ID,
    tokenSecret: process.env.MODAL_TOKEN_SECRET,
    appName: "my-agent", // App is created if missing
  }),
});

const sandbox = await client.create({
  template: "python:3.13", // container image
  resources: { vcpus: 2, memoryMB: 2048, gpu: "A100" }, // GPU is first-class
});

for await (const ev of sandbox.commands.run("nvidia-smi")) {
  if (ev.type === "stdout") process.stdout.write(ev.data);
}

Credentials fall back to Modal's standard environment (MODAL_TOKEN_ID / MODAL_TOKEN_SECRET) when the options are omitted. template is a container image passed to images.fromRegistry.

Modal's JS SDK has no high-level file API, so files.read/files.write are implemented via exec + base64 — the image needs coreutils base64 (present on python:*, debian, ubuntu). Ports must be declared in spec.ports at create time before ports.expose() can resolve a tunnel.

Authentication

A token id + secret (or Modal's standard environment).

Authentication variables for the modal adapter.
OptionEnv varRequiredDescription
tokenIdMODAL_TOKEN_IDrequiredModal token id.
tokenSecretMODAL_TOKEN_SECRETrequiredModal token secret.
environmentMODAL_ENVIRONMENToptionalModal environment name.
appNameoptionalApp to attach sandboxes to (created if missing). Defaults to "sbox-sdk".
imageoptionalDefault container image when a spec omits `template`.

Credentials fall back to the standard Modal environment (MODAL_TOKEN_ID / MODAL_TOKEN_SECRET) when the options are omitted.

Options

Prop

Type

Capabilities

CapabilityLevelNotes
listnative
streamingnativeContainerProcess streams
filesUploadnativevia exec + base64
gpunativeresources.gpu: "A100"
exposePortnativedeclare ports at create
codeInterpreterunsupported
stop / pauseunsupporteddestroy() = terminate
snapshot / forkunsupported

previewModel is tunnel.

On this page