Skip to main content

Vercel Eve Sandboxes

4 min read

Eve is Vercel's agent framework. It gives an agent a code-execution sandbox through a single agent/sandbox.ts file, and the backend behind that file is swappable.

@upstash/agentkit-eve ships an Upstash Box backend for it. It is a drop-in replacement for Eve's vercel() backend: change one import and your agent runs its code inside a Box, with deny-all egress by default, snapshot-backed templates, and one box per conversation.


1. Start from an Eve project#

Scaffold one if you do not have it yet. This installs eve and an AI SDK provider for you.

Use eve 0.43.0 or later.


2. Install the packages#

@upstash/box is an optional peer dependency of the AgentKit package. You only need it because you are importing the sandbox backend.

Get a Box API key from the Upstash Console:

.env

Redis backs the template registry described in step 5. It is only touched when your sandbox has a template, so a sandbox with no seed files and no bootstrap runs on the Box key alone.


3. Swap the backend#

Point defineSandbox at the upstash backend. Everything else in the sandbox file stays as it is.

agent/sandbox.ts

upstash(config) takes the @upstash/box BoxConfig. Whatever you would pass to Box.create({ ... }) you pass here: runtime, size, apiKey (defaults to UPSTASH_BOX_API_KEY), keepAlive, initCommand, env, git, skills, mcpServers, timeout, and so on. There are no renamed knobs to keep in sync.

Two things differ from a raw Box.create. networkPolicy is not accepted at all, because egress is governed per session (see the next step). And a few AgentKit-only fields sit alongside the Box config and are stripped before the rest is handed to Box.create: redis and templatePrefix for the template registry, baseSnapshot (step 5), and enableTelemetry.

That is the whole setup. Run your agent and ask it to execute something:


4. Open egress per session#

The sandbox runs model-generated code, so egress is deny-all by default. Open it where you need it, in the use(...) call, never as a backend-level setting.

agent/sandbox.ts

Pass "allow-all" when the agent genuinely needs the open internet, and nothing at all to inherit the secure default.

Warning

env passed to upstash({ env }) is readable by code running in the box. Do not put secrets there that the model should not see.

Brokering credentials#

Box network policies are plain domain and CIDR allow lists. Eve's per-domain firewall rules (transform header injection, forwardURL) have no Box equivalent, so passing them to use({ networkPolicy }) throws instead of quietly sending the request unauthenticated.

Use Box's attachHeaders instead. A proxy on the box injects the header at the firewall, so the secret never enters the box:

agent/sandbox.ts

5. Bake setup into a template#

A bootstrap hook runs once, and Eve caches the result as a template so later sessions start from it. On Box that template is a snapshot.

agent/sandbox.ts

A box runs as the non-root boxuser, so system-wide installs need sudo -n. Without it apt-get exits 100 on the dpkg lock and the bootstrap fails. Workspace-local installs such as npm install need no sudo.

Eve builds the template at build or startup time, while session creation runs per request in a different process. The snapshot id is therefore stored in a durable Redis registry (redis, defaulting to Redis.fromEnv(), under the agentkit:sandbox:template prefix). An in-memory map would orphan the prewarmed box.

Bump revalidationKey when the bootstrap should run again.

Heavy, slow-changing setup#

For things too heavy for a per-repo bootstrap (browser binaries, ffmpeg, a full toolchain), build a Box snapshot yourself out of band and point baseSnapshot at it. Every fresh session restores from it instead of creating a bare box.

Pass a snapshot id or a resolver, since Box addresses snapshots by id rather than by name. Returning undefined, or an id that no longer exists, falls back to a fresh box. When a prewarmed template snapshot also applies, the template wins and baseSnapshot is the fallback for sessions that have no template.


6. Lifecycle#

Eve re-opens a session several times per turn. The backend reattaches to the same box instead of creating a new one, so you get one box per conversation rather than one per tool call.

Boxes use Box's pause-based idle lifecycle by default (keepAlive: false): auto-paused when idle, resumed on reattach, and reaped by Box. Pass keepAlive: true only when you want an always-running box that you manage and delete yourself.

Note

Eve roots its tools at /workspace, while a Box session lives at /workspace/home. The backend rewrites paths and command text between the two automatically, so tools like glob and grep search the right directory.


Next steps#

The same package carries the rest of AgentKit for Eve: long-term memory, searchable chat history, RAG over Redis Search, a rate-limit gate for your channel's auth walk, and Redis-memoized tools.