Skip to main content

Vercel Sandbox Provider

@smithers-orchestrator/vercel is a first-class Smithers SandboxProvider backed by the Vercel Sandbox SDK. It runs a <Sandbox> child workflow’s request on Vercel Sandbox compute: it ships the request JSON into the sandbox workdir, runs the entry command, and reads the result JSON back. The shared provider-kit owns request shipping, egress, result parsing, secret scrubbing, and cleanup, so this package only supplies the Vercel createSession seam. The provider id is vercel-sandbox (exported as VERCEL_SANDBOX_PROVIDER_ID). The default workdir is /vercel/sandbox.
import {
  createVercelSandboxProvider,
  registerVercelSandboxProvider,
  VERCEL_SANDBOX_PROVIDER_ID,
} from "smithers-orchestrator/vercel";

Credentials

@vercel/sandbox is an optional dependency, imported lazily inside the session. Install it to use the real provider:
npm install @vercel/sandbox
OIDC is preferred; the access-token trio is the fallback. Auth is resolved and validated before the SDK is touched, so a misconfigured provider fails fast with INVALID_INPUT. These values are used only to create the sandbox. They are never written into the request JSON and never forwarded into the remote command env.
  • VERCEL_OIDC_TOKEN (preferred), or
  • VERCEL_TOKEN + VERCEL_TEAM_ID + VERCEL_PROJECT_ID.
Each can also be passed as a factory option (oidcToken, token, teamId, projectId).

Usage

import { createSmithers, Sandbox } from "smithers-orchestrator";
import { createVercelSandboxProvider } from "smithers-orchestrator/vercel";

const provider = createVercelSandboxProvider({
  runtime: "node24",
  vcpus: 2,
  ports: [3000],
  maxDurationMs: 45 * 60_000,
});

export default parent.smithers((ctx) => (
  <parent.Workflow name="vercel-sandbox-run">
    <Sandbox
      id="remote-build"
      provider={provider}
      workflow={childWorkflow}
      input={{ prompt: ctx.input.prompt }}
      output={parent.outputs.result}
    />
  </parent.Workflow>
));
Or register it once and reference it by id:
import { registerVercelSandboxProvider } from "smithers-orchestrator/vercel";

const unregister = registerVercelSandboxProvider({ runtime: "node24" });

// <Sandbox provider="vercel-sandbox" workflow={child} output={outputs.result} />

Request/result contract

The kit writes the request JSON to .smithers/sandbox-request.json in the workdir and hands the entry command two env vars:
  • SMITHERS_SANDBOX_REQUEST_PATH: where to read the request JSON.
  • SMITHERS_SANDBOX_RESULT_PATH: where to write the result JSON.
The entry command either prints the result JSON to stdout or writes it to SMITHERS_SANDBOX_RESULT_PATH. The result is { bundlePath } or a structured { status, output|outputs, patches?, diffBundle?, runId? }. When ports are declared, the reachable sandbox.domain(port) is surfaced through a heartbeat.

Factory options

  • runtime: Vercel Sandbox runtime (default node24).
  • vcpus: vCPU count passed to resources.
  • ports: ports whose domains are surfaced.
  • timeoutMs / maxDurationMs: see duration cap below.
  • persist: stop() (pause) instead of delete() on teardown.
  • command: entry command.
  • workdir: default /vercel/sandbox.
  • cleanup: "destroy" (default) or "keep".
  • env: merged into the command env.
  • client / createOptions: inject the SDK class or extra Sandbox.create options.

Duration and plan cap

The default session timeout is 5 minutes. options.timeoutMs (or request.toolTimeoutMs) maps to the create timeout. Durations above the 5-minute default warn through a heartbeat and call sandbox.extendTimeout(), up to options.maxDurationMs (default 45 minutes). A request above that cap throws INVALID_INPUT rather than provisioning a sandbox that would overrun the plan. Raise maxDurationMs for Pro (up to 5 hours).

Cleanup and cost

Ephemeral sandboxes are deleted permanently on teardown (cleanup: "destroy", the default). Set persist: true to stop() (pause) the sandbox instead so it can be resumed. cleanup: "keep" skips teardown entirely. You pay for Vercel Sandbox wall-clock from create to teardown. createMockVercelSandboxEnvironment(handler, config?) is an in-memory SDK double for tests. Pass it as options.client; it needs zero credentials, so unit tests run in CI without touching Vercel.