---
title: Run agent-desktop in Vercel Sandbox
description: Boot a Linux microVM from a prepared desktop image and run agent-desktop commands against the apps inside it.
url: "https://agent-browser.dev/desktop/sandboxes/vercel-sandbox"
docs_index: /desktop/llms.txt
lastUpdated: 2026-11-11
navTitle: "Vercel Sandbox"
---

> For an index of all documentation, see [/desktop/llms.txt](/desktop/llms.txt).

Vercel Sandbox runs a Linux microVM, and agent-desktop runs inside it against the sandbox's own desktop instead of yours. The [`agent-desktop sandbox` commands](/desktop/sandboxes) do not manage Vercel Sandbox; the Vercel SDK creates and drives it.

## Setup

```bash
npm install @vercel/sandbox                                    # the SDK that creates and drives sandboxes
vercel link                                                    # connect this directory to a Vercel project
vercel env pull                                                # writes VERCEL_OIDC_TOKEN to .env.local
```

The SDK reads that token to create sandboxes. On Vercel, the runtime provides the token, so a deployment skips both `vercel` commands.

## Run agent-desktop

`ad-desktop` is an image you build once with a desktop session (Xvfb, D-Bus, AT-SPI, an app such as GNOME Calculator), the agent-desktop Linux binary, and the `agent-desktop-run` wrapper from the [Docker container guide](/desktop/guides/docker-container).

That wrapper is essential. Vercel Sandbox starts a bare microVM from the image: nothing in the image starts a desktop, and a new or resumed sandbox has no session — no X server, no D-Bus session bus, and no accessibility bus. `agent-desktop` on its own has nothing to talk to; it fails with `PERM_DENIED` and tells you `No D-Bus session bus is reachable`. `agent-desktop-run` starts the session if it is missing, waits for it, and runs the command inside it, so every command that reads or acts on the desktop goes through it. The first command after `create` or a resume pays about a second of startup; later commands reuse the session.

```typescript
import { Sandbox } from "@vercel/sandbox";

// 1. Create a named sandbox from the desktop image (persistent by default)
const sandbox = await Sandbox.create({ name: "ad-demo", image: "ad-desktop" });

// 2. Open the app through the wrapper, which starts the desktop session
await sandbox.runCommand({ cmd: "agent-desktop-run", args: ["launch", "gnome-calculator"] });

// 3. Read the tree inside that same session
const result = await sandbox.runCommand({
  cmd: "agent-desktop-run",
  args: ["snapshot", "--app", "gnome-calculator", "-i", "--compact"],
});

// 4. Check the result - one JSON envelope per command
console.log(result.exitCode); // 0
console.log(JSON.parse(await result.stdout()).data.ref_count); // 27

// 5. Later, resume the same sandbox by name; the wrapper starts a fresh session if the old one is gone
const same = await Sandbox.get({ name: "ad-demo" });
await same.runCommand({ cmd: "agent-desktop-run", args: ["snapshot", "--app", "gnome-calculator", "-i"] });
```

Every command returns one JSON envelope, the same as on your own machine; [JSON output](/desktop/json-output) describes the fields.

---

For a semantic overview of all documentation, see [/sitemap.md](/sitemap.md)

For an index of all available documentation, see [/llms.txt](/llms.txt)