---
title: Sandboxes
description: Configure sandbox infrastructure for EVE sessions and code execution
---

Sandbox providers supply execution infrastructure independently of installed tools. ChatJS uses the selected provider for code execution and, when supported, persistent EVE session files. Installing a sandbox provider does not expose a code-execution tool to the model.

## EVE session sandboxes

The main agent declares its sandbox environment in `agent/sandbox.ts`. Account sessions register their sandbox lifecycle, and research subagents inherit the parent sandbox. Persistent providers support session files, process execution, resume, and cleanup.

| Built-in provider | Code-execution tools | Persistent EVE session files |
| --- | --- | --- |
| Vercel Sandbox | Supported | Supported |
| Daytona | Supported | Not supported by the current adapter |

Ordinary chat can run without persistent sandbox support. ChatJS explicitly disables the EVE sandbox environment in that case, and requests requiring its filesystem fail. Ephemeral code execution and persistent session files are separate capabilities.

To install infrastructure without a model-facing tool:

```bash
bunx chat-js@alpha add --sandbox-provider vercel
```

See [Code Execution](../tools/code-execution) for installing and using the tool.

## Select a provider

Select the tool when creating an app:

```bash
npx chat-js@alpha create my-app --yes \
  --code-execution-tool code-execution --sandbox-provider vercel
```

This installs the generic tool under `chatjs/tools/code-execution/` and the selected provider under `chatjs/providers/sandbox/`. An external sandbox registry item URL is also accepted:

```bash
npx chat-js@alpha create my-app --yes \
  --code-execution-tool code-execution --sandbox-provider https://example.com/r/my-sandbox.json
```

The fresh template includes only the selected implementation and dependencies. The CLI prints the selected item's credential requirements. Vercel Sandbox needs `VERCEL_OIDC_TOKEN` or the team/project/token credentials described below.

For an existing app, use `add`. Replace an installed provider explicitly. Modified source requires `--overwrite` after review:

```bash
bunx chat-js@alpha add --sandbox-provider daytona --replace
```

To install infrastructure without exposing a model tool, use `add --sandbox-provider vercel`. To install both together, use `add code-execution --sandbox-provider daytona`. Replacing the provider leaves the tool unchanged. There is no `enabled` flag or central provider switch. Keep generated registrations intact and use `add` or `sync` to regenerate them. Drain existing sandbox resources before replacing the provider or rotating its credentials.

Saved-code execution requires a compatible executor and code documents. The planner resolves these dependencies and reuses an existing sandbox selection. If none exists, select one explicitly:

```bash
bunx chat-js@alpha add saved-code-execution --sandbox-provider daytona
```

### Daytona credentials

To create an app using Daytona:

```bash
bunx chat-js@alpha create my-app --yes \
  --code-execution-tool code-execution --sandbox-provider daytona
```

Configure your Daytona organization and its API key in `.env.local`:

```bash
DAYTONA_API_KEY=your_api_key
DAYTONA_ORGANIZATION_ID=your_organization_id
```

Run the generated environment check before startup. The descriptor declares both variables and the adapter rejects empty credentials before allocation. The returned sandbox organization must match the configured organization. This adapter uses Daytona Cloud at `https://app.daytona.io/api` and needs no Vercel sandbox credentials. It does not certify the rest of your hosting configuration.

## Sandbox images

Select the image for each language with environment variables:

```bash
VERCEL_SANDBOX_IMAGE_PYTHON=vercel/sandbox/python:3.14
VERCEL_SANDBOX_IMAGE_JAVASCRIPT=vercel/sandbox/node:22
```

Vercel execution uses managed images. Python defaults to Python 3.14 on Ubuntu, and JavaScript defaults to Node.js 22 on Ubuntu. You can set either image variable to a Vercel Container Registry reference with the corresponding `python3` and `pip`, or `node`, commands available. Legacy `VERCEL_SANDBOX_RUNTIME*` settings are no longer read.

### Vercel Sandbox outside Vercel hosting

If you select Vercel Sandbox while hosting outside Vercel, you need to authenticate with an access token since `VERCEL_OIDC_TOKEN` is unavailable.

1. Copy your **Team ID** from team settings
2. Copy your **Project ID** from project settings
3. Create a token in your [Vercel account settings](https://vercel.com/account/tokens) scoped to your team
4. Set these environment variables:

```bash
VERCEL_TEAM_ID=team_xxx
VERCEL_PROJECT_ID=prj_xxx
VERCEL_TOKEN=your_token_here
```

The sandbox automatically uses these credentials when running outside Vercel infrastructure.

## Provider contract

`chatjs/providers/sandbox/provider.ts` exports the selected provider factory, `adapter.ts` contains its SDK integration, and `options.ts` declares its identity and environment requirements. `lib/sandbox/runtime.ts` exposes `getSandboxProvider()` to consumers. `@chat-js/sandboxes/provider` defines the common command and provider interfaces. `@chat-js/sandboxes/runtime` provides `withSandbox`, which coordinates allocation, cancellation and confirmed cleanup with the consumer's durable ownership store.

In this repository, contracts and lifecycle code live in `packages/sandboxes`, provider implementations in `packages/registry/src/sandboxes/{vercel,daytona}`, and the generic tool in `packages/registry/src/tools/code-execution`.

Third-party sandbox registry items use `kind: "sandbox"` metadata matching `@chat-js/sandboxes/definition` and install `chatjs/providers/sandbox/provider.ts` exporting `createSandboxProvider`. Version 1 requires Python and JavaScript commands, terminating cancellation and durable allocation cleanup. Capability metadata is a declaration, not evidence of live service behavior. Custom code-execution tools can separately implement the [typed executor contract](../tools/authoring#provider-selections).

## Lifecycle and accounting

Daytona execution has a five-minute application deadline and a ten-minute provider wall-clock TTL. Each sandbox is private and ephemeral. Cancellation requests deletion, including when cancellation happens while creation is still completing. Command output is combined into the text response. Python charts return structured data or a PNG. Arbitrary sandbox files are not persisted or downloaded into application storage.

Before allocation, the executor records a durable intent bound to the owner, session, tool call and provider scope. It confirms creation before running source and releases ownership only after provider deletion is confirmed. Cleanup failure retains the intent for a later conversation-deletion retry. Restarted execution refuses to allocate again for the same call until the previous intent is reconciled.

An uncertain create response remains an explicit reconciliation blocker. A single missing-resource response or elapsed TTL is not proof that an in-flight create can never complete. Operators must establish the allocation outcome before clearing its durable intent. This restriction also exists in the Vercel contract.

Daytona API-key authentication does not honor a separate organization override. Cleanup therefore binds to a non-secret key fingerprint as well as the configured organization. Keep the original credentials until all resources are drained. Replacing the provider or key with outstanding intents fails closed and requires restoring the original provider scope or performing verified reconciliation.

The shared executor records a fixed $0.05 usage cost for a completed built-in execution, independently of the provider's invoice. It records zero application cost for infrastructure failure and records the completed-execution cost only after output validation and confirmed cleanup. The optional [Credits plugin](../plugins/credits) applies balance checks and debits. Core retains usage evidence without a billing adapter. Native EVE cancellation and settlement retain their existing receipt behavior. Shared code wrappers can report user-code errors as completed executions. Provider compute costs may still accrue on failures, cancellation and uncertain creation.

## Provider evaluation and validation

Daytona was selected because its [TypeScript SDK](https://www.daytona.io/docs/en/typescript-sdk/daytona/) supports named allocation lookup and deletion confirmation. Its sandbox API also exposes organization identity, command execution, and wall-clock TTL. [E2B metadata](https://e2b.dev/docs/sandbox/metadata) supports finding sandboxes by metadata, but adopting it would require a separate reconciliation design around provider-generated identities. Both are real providers. Neither provider's documentation alone certifies this installation.

The evaluation used the existing Vercel caller contract and provider documentation, not a live vendor benchmark:

| Requirement | Daytona, selected | E2B, evaluated |
| --- | --- | --- |
| JavaScript and Python | SDK supports both, adapter runs the shared Node/Python wrappers | Both supported by its code interpreter |
| Deadline and cancellation | Command timeout plus wall-clock TTL, cancellation deletes the resource | Configurable sandbox timeout and explicit kill, pause behavior must be excluded from erasure |
| Output and files | Command output and sandbox filesystem, shared wrappers return charts | Code output and file read/write APIs, would need ChatJS output conversion |
| Identity before creation | Caller-selected name with returned organization identity | Provider-generated ID plus metadata, requires metadata reconciliation |
| Cleanup after restart | Resolve the durable name, delete and confirm absence | List running/paused resources and kill, additional inventory/absence proof needed |
| Usage accounting | One native ChatJS receipt after confirmed cleanup | Would need the same application receipt wrapper, separate from vendor billing |

E2B references: [languages](https://docs.e2b.dev/code-interpreting/supported-languages), [lifecycle](https://docs.e2b.dev/sandbox), [inventory](https://docs.e2b.dev/sandbox/list), and [file access](https://docs.e2b.dev/filesystem/read-write). Daytona references: [commands](https://www.daytona.io/docs/en/typescript-sdk/process/) and [sandbox lifecycle](https://www.daytona.io/docs/en/typescript-sdk/sandbox/). The choice favors the existing named-allocation contract. It is not a claim that E2B cannot implement it.

The implementation pins `@daytona/sdk` to `0.220.0`. Offline tests cover allocation ordering, identity mismatch, cancellation, cleanup failure, output quoting, and restart cleanup. Live acceptance requires a Daytona account with sandbox create, read, command and delete permissions, both environment variables above, and the application's native EVE/database configuration. Local live verification on October 5, 2026 passed JavaScript output, Python PNG charts, cancellation with deletion, and cleanup from a fresh process. The native executor also recorded a single $0.05 receipt and released durable ownership against isolated PostgreSQL; retry refused duplicate allocation and repeated deletion succeeded. These checks used the real Daytona service, but do not certify a hosted deployment, scheduled retention, or full browser-to-worker execution.
