# Running OpenClaw in Vercel Sandbox

**Author:** Allen Zhou

---

Learn how to run [OpenClaw](https://openclaw.ai/) in a [Vercel Sandbox](https://vercel.com/docs/vercel-sandbox) and connect it to WhatsApp.

A [Vercel Sandbox](https://vercel.com/docs/vercel-sandbox) gives OpenClaw its own isolated Linux MicroVM, completely separate from your local machine. You get a shell to install and configure software, published ports that are accessible over HTTPS, and a configurable timeout so the sandbox stays running as long as you need it. This means your assistant stays reachable without tying up a process on your laptop.

## Prerequisites

- Vercel account with Sandbox access
  
- [Sandbox CLI](https://vercel.com/docs/vercel-sandbox/cli-reference) installed (`npm i -g sandbox`)
  
- An LLM API key (see [Run the onboarding wizard](#run-the-onboarding-wizard))
  

## Install the Sandbox CLI

The [Sandbox CLI](https://vercel.com/docs/vercel-sandbox/cli-reference) lets you create, connect to, and manage sandboxes from your terminal. Install it globally:

`npm i -g sandbox`

Then log in to your Vercel account. This stores a token locally so subsequent commands are authenticated:

`sandbox login`

## Create and connect to a sandbox

OpenClaw's gateway needs at least 2 GB of memory and listens on port 18789. The `--timeout` flag controls how long the sandbox stays running before it shuts down automatically (see [runtime limits](https://vercel.com/docs/vercel-sandbox/pricing#runtime-limits) for maximum values per plan). The `--connect` flag drops you straight into a shell after creation:

`sandbox create \ --timeout 30m \ --publish-port 18789 \ --connect`

The output includes the sandbox ID and a public URL for the published port. Save the sandbox ID so you can reconnect later with `sandbox connect $SANDBOX_ID` if you get disconnected:

`export SANDBOX_ID=sbx_xxxxxxxx`

Everything from here on is run inside this shell.

## Install OpenClaw

Install OpenClaw globally so the `openclaw` command is available everywhere in the sandbox:

`npm install -g openclaw`

Confirm it installed correctly:

`openclaw --version`

## Run the onboarding wizard

OpenClaw has an interactive onboarding wizard that configures the LLM provider, channels, and gateway in one step. Start it inside the sandbox shell:

`openclaw onboard`

Follow the prompts:

1. **Security acknowledgment**: accept to continue
   
2. **Onboarding mode**: select **Quickstart**
   
3. **Model/auth provider**: select your provider. Choose **Vercel AI Gateway** if you want a single endpoint with built-in spend tracking and rate limiting across providers, or pick a provider directly (e.g. **Anthropic**, **OpenAI**) to use your own API key. For [AI Gateway](https://vercel.com/docs/ai-gateway), create an [API Key](https://vercel.com/d?to=%2F%5Bteam%5D%2F%7E%2Fai-gateway%2Fapi-keys&title=AI+Gateway+API+Keys) beforehand.
   
4. **Auth method**: select the API key option for your chosen provider
   
5. **Enter API key**: paste your API key
   
6. **Select model**: choose from available models or keep the default
   
7. **Select channel**: choose **Skip for now** (we'll configure channels later)
   
8. **Configure skills**: select **No**
   
9. **Enable hooks**: select **Skip for now**
   
10. **Gateway service**: select **Skip** (already installed)
    

When onboarding finishes, the output displays a **Dashboard ready** section with a `127.0.0.1` dashboard link.

This link points to localhost inside the sandbox, so it won't work in your browser. Instead, use the public URL from `sandbox create` (the `https://sb-*-18789.vercel.run` address) and append the token fragment from the onboarding output (e.g. `https://sb-xxxxxxxx-18789.vercel.run/#token=your_token_here`).

Once you see **Onboarding complete**, press **Ctrl+C** to exit the wizard and return to the shell prompt.

## Start the gateway

The onboarding wizard configures the gateway but doesn't leave it running after you exit. To start it in the background so it persists after you disconnect from the sandbox:

`nohup openclaw gateway run > /tmp/gateway.log 2>&1 &`

`nohup` keeps the process alive after you disconnect from the shell, and `&` returns you to the prompt immediately. Check the logs to verify it started:

`cat /tmp/gateway.log`

You should see a line like:

`[gateway] listening on ws://127.0.0.1:18789` The dashboard is now reachable at the public URL that was printed when you [created the sandbox](#create-and-connect-to-a-sandbox) (the `--publish-port 18789` mapping).

## Pair your browser

OpenClaw requires device pairing before a browser can control the assistant. This is a security measure: even if someone obtains your dashboard URL and gateway token, they still can't interact with your assistant without an approved device. The first time you open the dashboard, your browser registers as a new device that needs approval.

List pending requests:

`openclaw devices list`

Approve your browser (replace `REQUEST_ID` with the value from the **Request** column):

`openclaw devices approve REQUEST_ID`

Once approved, click **Connect** in the dashboard. A green status indicator means your OpenClaw is ready.

## Configure WhatsApp

WhatsApp uses QR-based device linking, which works through the interactive terminal inside the sandbox.

### Run the channel wizard

`openclaw config --section channels`

Follow the prompts:

1. Select **Local (this machine)** for gateway location
   
2. Choose **Configure/link**
   
3. Select **WhatsApp (QR link)**
   
4. Select **Yes** for "Link WhatsApp now (QR)?"
   

### Scan the QR code

On your phone, open WhatsApp and go to **Settings** > **Linked Devices** > **Link a Device**, then scan the QR code shown in the terminal. After scanning, WhatsApp restarts the connection automatically and you should see "Linked after restart; web session ready."

### Configure DM access

The wizard asks about your phone setup:

- **This is my personal phone number**: sets DM policy to allowlist so only your number can message the assistant
  
- **Separate phone just for OpenClaw**: opens up DM access more freely since the device is dedicated to the assistant
  

If you chose personal phone, enter your WhatsApp number (with country code, e.g. `+15551234567`) when prompted. OpenClaw adds it to the allowlist automatically.

When asked to select another channel, choose **Finished**.

### Restart the gateway

The gateway needs a restart to pick up channel changes:

`openclaw gateway stop nohup openclaw gateway run > /tmp/gateway.log 2>&1 &`

### Verify the connection

1. Open WhatsApp on your phone
   
2. Tap the **new chat** button (pencil/compose icon)
   
3. Your own name appears at the top of the contact list with **"Message yourself"**
   
4. Tap it and send a message
   

OpenClaw will reply in the same chat.

With the default personal phone setup, OpenClaw only responds to messages from your allowlisted number. You can change this later:

`openclaw config set channels.whatsapp.dmPolicy pairing`

Available policies (see [DM access and pairing](https://docs.openclaw.ai/channels/whatsapp#access-control-and-activation) for details):

- **allowlist** (default for personal phone): only responds to numbers in the allowlist
  
- **pairing**: unknown senders get a pairing code you approve before they can message the assistant
  
- **open**: responds to anyone who messages you
  
- **disabled**: ignores all WhatsApp DMs
  

## Lock down egress

Now that OpenClaw is installed, configured, and connected to WhatsApp, you can restrict outbound network access to only the domains the agent actually needs. This is the key security benefit of running in a sandbox: even if the agent tries to reach an unexpected service (your email, a random API, anything not on the list), the request is blocked at the network level.

Use `sandbox config network-policy` from your local terminal (not inside the sandbox) to set an allowlist:

`sandbox config network-policy $SANDBOX_ID \ --network-policy restricted \ --allowed-domain ai-gateway.vercel.sh \ --allowed-domain web.whatsapp.com \ --allowed-domain mmg.whatsapp.net`

This blocks all outbound traffic except to the specified domains. Adjust the list based on your LLM provider:

- **Vercel AI Gateway**: `ai-gateway.vercel.sh`
  
- **Anthropic**: `api.anthropic.com`
  
- **OpenAI**: `api.openai.com`
  
- **WhatsApp**: `web.whatsapp.com`, `mmg.whatsapp.net` (always include these)
  

You can verify the policy is working by trying to reach a blocked domain from inside the sandbox:

`curl https://example.com`

This should fail. Then confirm your allowed domains still work:

`curl -I https://api.anthropic.com`

If you need to install something later (e.g. update OpenClaw), temporarily remove the restriction, install, then re-apply. Or better, use [snapshots](#using-snapshots-for-faster-starts) to capture the installed state and start new sandboxes with the allowlist from the beginning.

## Using snapshots for faster starts

Installing OpenClaw takes about a minute. You can skip that step on future sandboxes by creating a snapshot after the install. A snapshot captures the full filesystem state, so anything you've installed or configured is preserved.

Create a snapshot (this stops the sandbox):

`sandbox snapshot $SANDBOX_ID --stop`

Next time, create a sandbox from the snapshot with the network policy already applied:

`sandbox create \ --snapshot snap_xxxxxxxx \ --timeout 1h \ --publish-port 18789 \ --network-policy restricted \ --allowed-domain ai-gateway.vercel.sh \ --allowed-domain web.whatsapp.com \ --allowed-domain mmg.whatsapp.net`

The new sandbox boots with OpenClaw already installed and egress locked down from the start. You only need to [run the onboarding wizard](#run-the-onboarding-wizard) and [start the gateway](#start-the-gateway).

## Security

- **Egress control**: restrict outbound traffic to only the domains the agent needs. Everything else is blocked at the network level, so the agent can't reach your email, internal APIs, or anything outside the allowlist.
  
- **Sandbox isolation**: each sandbox is its own MicroVM with no access to your host machine
  
- **Timeouts**: sandboxes shut down automatically when the timeout expires, so nothing runs forever by accident
  
- **Port control**: only ports you explicitly publish are reachable from the internet
  
- **Token auth**: the gateway token prevents unauthorized dashboard access
  
- **Device pairing**: even with the token, only approved devices can control the assistant
  
- **AI Gateway**: optionally adds spend caps and rate limits on top of provider access

---

[View full KB sitemap](/kb/sitemap.md)
