- MCP Server ToolsUpdated
- Managed MCP with chat()Updated
- Manual MCPUpdated
- MCP Type GenerationUpdated
- MCP Client InputUpdated
- MCP Server Tools: AdvancedNew
- MCP EventsNew
- MCP AppsUpdated
- Serve Tools over HTTPUpdated
- Serve Resources and PromptsUpdated
- Ask for InputUpdated
- Draft Text from a ToolUpdated
- MCP Server TasksUpdated
- MCP Server AuthUpdated
- MCP Server SessionsUpdated
- MCP Server on stdioUpdated
Persistence (Advanced)
- GenerationsUpdated
- Realtime Voice ChatUpdated
- Text-to-SpeechUpdated
- TranscriptionUpdated
- Transcription: AdvancedNew
- Voice CreationUpdated
- Audio RecordingUpdated
- Audio GenerationUpdated
- Image GenerationUpdated
- Image Generation: AdvancedNew
- Video GenerationUpdated
- Video Generation: AdvancedNew
- Live GenerationUpdated
- World GenerationUpdated
- Generation HooksUpdated
- OverviewUpdated
- Quick StartUpdated
- ProvidersUpdated
- HarnessesUpdated
- Harness AuthUpdated
- WorkspaceUpdated
- ToolsUpdated
- PolicyUpdated
- Lifecycle & SnapshotsUpdated
- Portable SnapshotsUpdated
- Keep Files After ReloadUpdated
- Save a Named VersionUpdated
- Branch From a VersionUpdated
- Send a Frozen FileUpdated
- Let the Agent Save and ForkUpdated
- Pick Which Files to KeepUpdated
- What a Snapshot StoresUpdated
- Instance DurabilityUpdated
- Durable RunsUpdated
- EventsUpdated
Sandboxes (Advanced)
- Runtime ContextUpdated
- Bring Your Own KeyUpdated
- Debug LoggingUpdated
- Multimodal ContentUpdated
- Files APIUpdated
- Per-Model Type SafetyUpdated
- Runtime Adapter SwitchingUpdated
- Tree-ShakingUpdated
- Extend AdapterUpdated
- Extend Adapter: AdvancedNew
- Typed Pre-Configured OptionsUpdated
- Test with a Fake ModelUpdated
- Prompt CachingUpdated
- Mid-Conversation ChangesUpdated
- Approval Flow ProcessingUpdated
Providers
A provider is where the sandbox runs: a local process for a fast loop, or an isolated VM in production.
A provider is that place. Every provider has the same contract, so your workspace, policy, and harness stay the same when you change the provider.
Set up a provider#
- Pick a row from the table.
| Provider | Package | Isolation | Needs |
|---|---|---|---|
| Local process | @tanstack/ai-sandbox-local-process | None (your host) | Nothing. For trusted dev work only. |
| Docker | @tanstack/ai-sandbox-docker | Container | Docker running. |
| Docker Sandboxes (sbx) | @tanstack/ai-sandbox-docker | microVM | The sbx CLI, sbx login, and a hypervisor. |
| Daytona | @tanstack/ai-sandbox-daytona | Cloud sandbox | DAYTONA_API_KEY |
| Vercel | @tanstack/ai-sandbox-vercel | microVM | VERCEL_TOKEN, a team, and a project. |
| Sprites | @tanstack/ai-sandbox-sprites | Stateful sandbox | SPRITES_API_KEY |
| Upstash Box | @tanstack/ai-sandbox-upstash-box | Cloud sandbox | UPSTASH_BOX_API_KEY |
| Blaxel | @tanstack/ai-sandbox-blaxel | Cloud sandbox | BL_API_KEY and BL_WORKSPACE, or a Blaxel CLI login. |
| E2B | @tanstack/ai-sandbox-e2b | microVM | E2B_API_KEY |
| boxd | @tanstack/ai-sandbox-boxd | microVM | BOXD_API_KEY and BOXD_ORG. |
| Railway | @tanstack/ai-sandbox-railway | microVM | RAILWAY_API_TOKEN or RAILWAY_TOKEN, and an environment. |
- Install its package. This example installs the Docker provider. Use the package from your row.
npm i @tanstack/ai-sandbox-dockerpnpm add @tanstack/ai-sandbox-dockeryarn add @tanstack/ai-sandbox-dockerbun add @tanstack/ai-sandbox-dockerSet the env vars from the "Needs" column.
Pass the provider to defineSandbox:
import {
createSecrets,
defineSandbox,
defineWorkspace,
githubRepo,
} from '@tanstack/ai-sandbox'
import { dockerSandbox } from '@tanstack/ai-sandbox-docker'
export const repoSandbox = defineSandbox({
id: 'repo-agent',
provider: dockerSandbox({ image: 'node:22' }),
workspace: defineWorkspace({
source: githubRepo({ repo: 'owner/app' }),
setup: ['corepack enable', 'pnpm install'],
secrets: createSecrets({
XAI_API_KEY: process.env.XAI_API_KEY ?? '',
}),
}),
})To change the provider, change only the provider line. Here is the constructor for each one:
import { localProcessSandbox } from '@tanstack/ai-sandbox-local-process'
import { dockerSandbox, sbxSandbox } from '@tanstack/ai-sandbox-docker'
import { daytonaSandbox } from '@tanstack/ai-sandbox-daytona'
import { vercelSandbox } from '@tanstack/ai-sandbox-vercel'
import { spritesSandbox } from '@tanstack/ai-sandbox-sprites'
import { upstashBoxSandbox } from '@tanstack/ai-sandbox-upstash-box'
import { blaxelSandbox } from '@tanstack/ai-sandbox-blaxel'
import { e2bSandbox } from '@tanstack/ai-sandbox-e2b'
import { boxdSandbox } from '@tanstack/ai-sandbox-boxd'
import { railwaySandbox } from '@tanstack/ai-sandbox-railway'
const dev = localProcessSandbox() // runs on your host
const isolated = dockerSandbox({ image: 'node:22' }) // container
const microvm = sbxSandbox() // Docker Sandboxes microVM
const daytona = daytonaSandbox({ apiKey: process.env.DAYTONA_API_KEY })
const vercel = vercelSandbox({ runtime: 'node24' })
const sprites = spritesSandbox({ apiKey: process.env.SPRITES_API_KEY })
const box = upstashBoxSandbox({ apiKey: process.env.UPSTASH_BOX_API_KEY })
const blaxel = blaxelSandbox() // uses the API key or the CLI login
const e2b = e2bSandbox() // reads E2B_API_KEY
const boxd = boxdSandbox({ org: 'acme' }) // reads BOXD_API_KEY
const railway = railwaySandbox() // reads RAILWAY_TOKEN and RAILWAY_ENVIRONMENT_IDdockerSandbox() and sbxSandbox() come from the same package. Every other provider has its own package. For the edge, see Cloudflare.
How it works#
- The provider decides where the agent runs. The harness decides which agent runs.
- The provider does not pick how the agent signs in. Set authMode on the harness. See Harness Auth.
- Isolated and cloud providers have no host CLI login. Pass API keys as workspace secrets there.
- Provider-native snapshots and resume keep or recreate the provider state. They make bootstrap faster. Portable Snapshots store finished files in your own persistence.
Note
Cloud providers (Daytona, Vercel, Sprites, Upstash Box, Blaxel, E2B, boxd, and Railway) run remotely. When you drive them from your laptop, bridged tools cannot reach your localhost. Use the ngrok bridge tunnel from the tools guide, or see Cloudflare for the edge setup.
Capabilities#
Each provider reports what it can do with capabilities(). Code that needs an optional capability checks the flag first:
import { localProcessSandbox } from '@tanstack/ai-sandbox-local-process'
const provider = localProcessSandbox()
if (provider.capabilities().snapshots) {
// This provider can take a snapshot.
} else {
// Skip the snapshot. Local process has no snapshots.
}| Capability | Meaning |
|---|---|
| fs | Read and write the sandbox filesystem. |
| exec | Run commands. |
| env | Inject environment variables. |
| ports | Expose ports (preview URLs). |
| backgroundProcesses | Keep long-running processes alive between calls. |
| writableStdin | A spawned process has a writable stdin from the host. |
| killableProcesses | A spawned process can be stopped with SpawnHandle.kill() and with the signal passed to spawn. |
| snapshots | Take and restore point-in-time snapshots. |
| networkPolicy | Enforce network allow and deny rules. |
| durableFilesystem | The disk stays across resumes. |
| fork | Create a new sandbox from an existing one. |
The framework checks these flags for you. For example, bootstrap takes a snapshot only when snapshots is true, so localProcessSandbox skips that step. If you call an unsupported optional method directly, it throws an UnsupportedCapabilityError.
Branch on the flag, not on the provider name. Then your code keeps working when you change the provider.
killableProcesses across the bundled providers#
The run journal reads this flag to decide how to read a run's output. It also limits what a cancel can do. On a false provider, cancel destroys the sandbox. See what cancel means on a provider that cannot kill.
| Provider | killableProcesses |
|---|---|
| Local process | true |
| Docker | true |
| Docker Sandboxes (sbx) | false |
| Daytona | false |
| Vercel | false |
| Sprites | true (not verified) |
| Upstash Box | true |
| Blaxel | true |
| E2B | true |
| Cloudflare | false |
| boxd | true |
| Railway | true |
A bring-your-own provider must set this flag too. For the reason behind each value, see Providers (Advanced).
Advanced#
Each provider has its own options and limits: idle timers, ports, network rules, non-root users, and snapshot behavior. Read them in Providers (Advanced) before you go to production.