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 modalUsage
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).
| Option | Env var | Required | Description |
|---|---|---|---|
tokenId | MODAL_TOKEN_ID | required | Modal token id. |
tokenSecret | MODAL_TOKEN_SECRET | required | Modal token secret. |
environment | MODAL_ENVIRONMENT | optional | Modal environment name. |
appName | — | optional | App to attach sandboxes to (created if missing). Defaults to "sbox-sdk". |
image | — | optional | Default 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
| Capability | Level | Notes |
|---|---|---|
list | native | |
streaming | native | ContainerProcess streams |
filesUpload | native | via exec + base64 |
gpu | native | resources.gpu: "A100" |
exposePort | native | declare ports at create |
codeInterpreter | unsupported | |
stop / pause | unsupported | destroy() = terminate |
snapshot / fork | unsupported |
previewModel is tunnel.