---
title: "Deploy to Vercel"
description: "Build and deploy the dispatcher to Vercel, set the sandbox backend, smoke-test the live routes with curl and eve remote connect, and find your runs in the dashboard."
canonical_url: "https://vercel.com/academy/building-agents-with-eve/deploy-agent-to-vercel"
md_url: "https://vercel.com/academy/building-agents-with-eve/deploy-agent-to-vercel.md"
docset_id: "vercel-academy"
doc_version: "1.0"
last_updated: "2026-11-03T03:33:29.039Z"
content_type: "lesson"
course: "building-agents-with-eve"
course_title: "Building Agents with eve"
prerequisites:  []
---

<agent-instructions>
Vercel Academy — structured learning, not reference docs.
Lessons are sequenced.
Adapt commands to the human's actual environment (OS, package manager, shell, editor) — detect from project context or ask, don't assume.
The lesson shows one path; if the human's project diverges, adapt concepts to their setup.
Preserve the learning goal over literal steps.
Quizzes are pedagogical — engage, don't spoil.
Quiz answers are included for your reference.
</agent-instructions>

# Deploy to Vercel

# Deploy to Vercel

The agent runs the same way locally and on Vercel. Build it, deploy it, and test the live URL to confirm the dispatcher answers from the hosted environment.

The one production-specific choice is where the sandbox runs, and even that's mostly handled for you. Let's ship it.

## Outcome

The Spoke & Mirror dispatcher runs on Vercel, and you've confirmed it live by hitting its deployed routes.

## Hands-on exercise

**Pick the sandbox backend.** Your agent has a sandbox (it seeds `torque-specs.md` into `/workspace`). Locally that runs on your machine; on Vercel it runs on hosted Vercel Sandbox. One definition covers both, `DefaultSandbox.environment()` picks the right provider per environment:

```ts title="agent/sandbox/sandbox.ts"
import { DefaultSandbox, defineSandbox } from "eve/sandbox";

export const environment = DefaultSandbox.environment();

export default defineSandbox(() => environment.open());
```

The file exports two things. `environment` describes the kind of sandbox to build, and `eve build` prepares it before any session exists. The default export opens a live sandbox for the current session from that environment.

\*\*Note: Pinning a backend explicitly\*\*

`DefaultSandbox` is the portable choice: it picks Vercel Sandbox on Vercel, Docker when a Docker daemon is reachable, and just-bash during `eve dev` when neither is available. To pin Vercel unconditionally instead, import its environment from the nested path:

```ts
import { VercelSandbox } from "eve/sandbox/vercel";
export const environment = VercelSandbox.environment();
```

eve ships an environment per provider; check `node_modules/eve/docs/sandbox/` for the set in your installed version.

**Build and deploy.** `eve deploy` runs the supported production workflow: it links the project when needed, installs dependencies, builds the app, and deploys it to Vercel. From the project root:

```bash
npx eve deploy
```

The deployed app serves the exact same health, session, and stream routes you've been hitting since 1.3, plus the web dashboard from 4.1. If you wired up Slack in 4.2, this is the deploy that gives its webhook a real home.

## Try It

Smoke-test the live agent. Health first, it's public, no auth:

```bash
curl https://<your-app>/eve/v1/health
```

```text
{"ok":true,"status":"ready","workflowId":"workflow//eve//workflowEntry"}
```

Now prove the fail-closed behavior from 5.1. With no customer cookie or Vercel OIDC token, the deployed production process rejects the request:

```bash
curl -i -X POST https://<your-app>/eve/v1/session \
  -H 'content-type: application/json' \
  -d '{"message":"hello"}'
```

```text
HTTP/2 401
{ "ok": false, "code": "unauthorized" }
```

Then drive a real turn as a customer. The same route accepts the server-recognized demo session, returns `202`, and gives you a `sessionId` to stream:

```bash
sid=$(curl -s -X POST https://<your-app>/eve/v1/session \
  -H 'content-type: application/json' -H 'cookie: shop_session=demo-pro' \
  -d '{"message":"what does a full overhaul cost?"}' \
  | sed -E 's/.*"sessionId":"([^"]+)".*/\1/')
curl -sN -H 'cookie: shop_session=demo-pro' \
  "https://<your-app>/eve/v1/session/$sid/stream"
```

Or point the terminal UI at the deployment and talk to it interactively. `eve dev` always starts a local server, so connecting to a deployed agent is its own command. Pass the customer cookie as a header, since the fail-closed channel rejects anyone it doesn't recognize:

```bash
npx eve remote connect --url https://<your-app> \
  --header 'cookie: shop_session=demo-pro'
```

The production dispatcher keeps its tools and approval gate. Ask it to book the overhaul and the turn still pauses for approval.

\*\*Note: Find your runs in the dashboard\*\*

Once deployed, Vercel auto-detects `eve` as the framework and surfaces an **Agent Runs** tab under your project's Observability view. Each conversation is a trace you can open and walk, every tool call, every approval, every turn. (Agent Runs is in beta on every plan and bills at [Always-on Tracing rates](https://vercel.com/docs/tracing/always-on-tracing#usage-and-pricing). If an existing project shows no runs, add a sampling rule under **Settings → Tracing**, as the [Agent Runs docs](https://vercel.com/docs/agent-runs) describe.)

A `401` on every live request means the fail-closed lock rejected the caller. Send a valid `shop_session` cookie, or use the public `/eve/v1/health` route for a quick check. If `eve build` fails on discovery, read the printed diagnostics and `.eve/diagnostics.json`. A common cause is a tool file that doesn't `export default` its `defineTool`.

## Done-When

- [ ] `agent/sandbox/sandbox.ts` exports an `environment` and a `defineSandbox` default (`DefaultSandbox.environment()` is fine).
- [ ] `eve deploy` builds successfully and ships the app.
- [ ] `curl https://<your-app>/eve/v1/health` returns `ok`.
- [ ] An unauthenticated session request returns `401`, while `shop_session=demo-pro` returns `202` with a session ID.
- [ ] A real turn against the deployed URL works (TUI via `eve remote connect --url <url>` with the cookie header, or `curl` with a session).

## Solution

The only code is the sandbox environment; the rest is one command:

```ts title="agent/sandbox/sandbox.ts"
import { DefaultSandbox, defineSandbox } from "eve/sandbox";

export const environment = DefaultSandbox.environment();

export default defineSandbox(() => environment.open());
```

```bash
npx eve deploy
```

The dispatcher now runs in production with the persona and capabilities you built throughout the course. The final lesson covers the eve directories this shop did not need and when you might use them.


---

[Full course index](/academy/llms.txt) · [Sitemap](/academy/sitemap.md)
