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:
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.
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.
Pass "allow-all" when the agent genuinely needs the open internet, and nothing at all to inherit the secure default.
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:
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.
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.
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.
- AgentKit for Vercel Eve for the full package reference.
- Network policies for what Box's allow lists can express.
- Snapshots for building and restoring the boxes behind templates.