Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/vercel/eve/llms.txt

Use this file to discover all available pages before exploring further.

The sandbox is the agent’s isolated bash environment: a filesystem rooted at /workspace where the agent can run shell commands, execute scripts, and read or write files without ever touching your app runtime. Every eve agent has exactly one. The built-in bash, read_file, write_file, glob, and grep tools already target it, and your authored tools can reach it too via ctx.getSandbox(). A working sandbox exists by default — nothing to author. Override it only to add setup, seed workspace files, pick a specific backend, or lock down network egress.

Built-in sandbox tools

The model already has shell and file access through the default harness tools:
ToolDoes
bashRun a shell command in the sandbox
read_file / write_fileRead/write files under /workspace
globFind files by pattern
grepSearch file contents
All of them run with /workspace as the working directory.

Accessing the sandbox from tools

Any authored runtime function — a tool, a step, a model callback — can get a live sandbox handle with ctx.getSandbox(). It is async and only works inside authored runtime execution:
agent/tools/run_analysis.ts
import { defineTool } from "eve/tools";
import { z } from "zod";

export default defineTool({
  description: "Run a Python analysis script and return its output.",
  inputSchema: z.object({ script: z.string() }),
  async execute({ script }, ctx) {
    const sandbox = await ctx.getSandbox();
    await sandbox.writeTextFile({ path: "analysis/run.py", content: script });
    const result = await sandbox.run({ command: "python analysis/run.py" });
    return { stdout: result.stdout };
  },
});
/workspace is one namespace across every backend — /workspace/foo points at the same file whether the backend is local or Vercel. To interpolate a path into a generated command, sandbox.resolvePath("repo/build.py") anchors a relative path to its absolute /workspace/repo/build.py form.

Sandbox handle methods

All methods accept relative paths (resolved from /workspace) or absolute paths (passed through untouched):
MethodDoes
run({ command })Run one command, block until it exits, return { stdout, stderr, ... }
spawn(options)Launch a long-running process (server, watcher) and return a SandboxProcess handle
readTextFile / writeTextFileRead/write a UTF-8 file; readTextFile supports 1-based line ranges
readBinaryFile / writeBinaryFileRead/write raw bytes (images, archives, anything non-text)
readFile / writeFileStream a file in/out as bytes
removePath({ path, force, recursive })Delete one file or directory; force ignores missing paths, recursive removes non-empty dirs
resolvePath(path)Anchor a relative path to its absolute /workspace/... form
setNetworkPolicy(policy)Change egress policy mid-turn (backend-dependent)
Since run blocks until the command exits, use spawn when the process should keep running while the agent does other work:
agent/tools/dev_server.ts
import { defineTool } from "eve/tools";
import { z } from "zod";

export default defineTool({
  description: "Start a dev server and verify it responds.",
  inputSchema: z.object({ port: z.number().default(8000) }),
  async execute({ port }, ctx) {
    const sandbox = await ctx.getSandbox();
    const server = await sandbox.spawn({ command: `python -m http.server ${port}` });
    // ...do other work against the server...
    await server.kill();
    return { started: true };
  },
});
A SandboxProcess exposes stdout/stderr byte streams, wait() (resolves with the exit code), and kill() (idempotent). sandbox.id is a stable per-session identifier that persists across reconnects to the same logical session.

Seeding /workspace

Mount authored files into the sandbox at session start by placing them under agent/sandbox/workspace/. This requires the folder layout (not the top-level agent/sandbox.ts shorthand):
agent/sandbox/
  sandbox.ts                ← optional override
  workspace/
    schema.sql              ← lands at /workspace/schema.sql
    scripts/run.sh          ← lands at /workspace/scripts/run.sh
Every file under workspace/ mirrors into the sandbox with its directory structure intact. eve lists the top-level entries to the model in the prompt automatically.
Skill discovery already seeds files under /workspace/skills/. Authoring agent/sandbox/workspace/skills/... is rejected — put those under agent/skills/ instead.

Overriding the sandbox with defineSandbox

To add setup, seed files, or pick a backend, author defineSandbox from eve/sandbox. Two layouts are supported:
  • agent/sandbox.ts — shorthand; use it when you need only a definition with no seeded files.
  • agent/sandbox/sandbox.ts — folder layout; use it when you also seed agent/sandbox/workspace/**. If both exist, the folder layout wins.
agent/sandbox/sandbox.ts
import { defineSandbox } from "eve/sandbox";
import { vercel } from "eve/sandbox/vercel";

export default defineSandbox({
  backend: vercel({ runtime: "node24", resources: { vcpus: 2 } }),
  revalidationKey: () => "repo-bootstrap-v1",
  async bootstrap({ use }) {
    const sandbox = await use();
    await sandbox.run({ command: "apt-get install -y jq" });
  },
  async onSession({ use }) {
    await use({ networkPolicy: "deny-all" });
  },
});

Sandbox lifecycle

1

bootstrap

Template-scoped, runs once when the template is built. Put reusable setup here that every later session inherits: cloning a baseline repo, installing dependencies, or seeding files. Call use() to get a SandboxSession. Set revalidationKey: () => string when external inputs affect what bootstrap produces so eve knows when to rebuild.
2

onSession

Durable-session-scoped, runs once per session. Put per-session setup here: network policy, resources, timeout, per-user credentials. Runs inside the active runtime context, so it can read ctx.session and derive the current principal without baking credentials into the template.
agent/sandbox/sandbox.ts
import { defineSandbox } from "eve/sandbox";
import { vercel } from "eve/sandbox/vercel";

export default defineSandbox({
  backend: vercel(),
  async onSession({ use, ctx }) {
    const sandbox = await use({ networkPolicy: "deny-all" });
    const user = ctx.session.auth.current;
    if (user === null) return;
    await sandbox.writeTextFile({
      path: "SESSION_USER.txt",
      content: `${user.principalId}\n`,
    });
  },
});
If you require a network policy for every session, configure it on the backend factory or in onSession. Do not rely on bootstrap-only configuration.

Backends

eve ships four pinned backend factories plus an availability-aware default:
BackendRuns the sandbox
vercel()On Vercel Sandbox
docker()Locally in a Docker container, driven through the docker CLI
microsandbox()Locally in a lightweight microsandbox VM
justbash()Locally in the pure-JS just-bash interpreter (no daemon or VM, but no real binaries)
defaultBackend()Picks the best available: Vercel Sandbox → Docker → microsandbox → just-bash
With backend omitted, eve uses defaultBackend(). You can configure each inner backend:
agent/sandbox/sandbox.ts
import { defaultBackend, defineSandbox } from "eve/sandbox";

export default defineSandbox({
  backend: defaultBackend({
    vercel: { networkPolicy: "deny-all", resources: { vcpus: 4 } },
    docker: { image: "ghcr.io/vercel/eve:latest" },
    microsandbox: { memoryMiB: 2048 },
  }),
});

Network policy

Egress rules go on the backend factory or in onSession’s use():
networkPolicy: "allow-all"  // default

networkPolicy: "deny-all"   // block all egress, including DNS

networkPolicy: {
  allow: ["ai-gateway.vercel.sh", "*.github.com"],
  subnets: { deny: ["10.0.0.0/8"] },
}
Default egress is allow-all. For non-public, sensitive, regulated, or production workloads, configure deny-all or an explicit allow-list before running untrusted tools or handling sensitive data.
Set the policy on the factory and it applies before authored bootstrap code runs. Set it in onSession’s use() to override per-session. Call sandbox.setNetworkPolicy(...) on the live handle to change the policy mid-turn.

Subagent sandboxes

Each declared subagent gets its own sandbox, independent of its parent. The built-in agent tool (a copy of the same agent) is the exception — its children share the parent’s sandbox because they are copies working on the same files. The default sandbox is not a substitute for configuring network policy, credentials, retention, deletion, or other controls your application requires.

Build docs developers (and LLMs) love