Skip to main content

Quick start

This launches your OpenClaw gateway site (web UI for chatting with agents).
import { Sandbox } from 'e2b'

const TOKEN = process.env.OPENCLAW_APP_TOKEN || 'my-gateway-token'
const PORT = 18789

// 1. Create sandbox
const sandbox = await Sandbox.create('openclaw', {
  envs: { OPENAI_API_KEY: process.env.OPENAI_API_KEY },
  timeoutMs: 3600_000,
})

// 2. Set the default model
await sandbox.commands.run('openclaw config set agents.defaults.model.primary openai/gpt-5.2')

// 3. Set insecure control UI flags and start the gateway with token auth
await sandbox.commands.run(
  `bash -lc 'openclaw config set gateway.controlUi.allowInsecureAuth true && ` +
    `openclaw config set gateway.controlUi.dangerouslyDisableDeviceAuth true && ` +
    `openclaw gateway --allow-unconfigured --bind lan --auth token --token ${TOKEN} --port ${PORT}'`,
  { background: true }
)

// 4. Wait for the gateway to start listening
for (let i = 0; i < 45; i++) {
  const probe = await sandbox.commands.run(
    `bash -lc 'ss -ltn | grep -q ":${PORT} " && echo ready || echo waiting'`
  )
  if (probe.stdout.trim() === 'ready') break
  await new Promise((r) => setTimeout(r, 1000))
}

const url = `https://${sandbox.getHost(PORT)}/?token=${TOKEN}`
console.log(`Gateway: ${url}`)
Visit the printed Gateway URL in your browser. If you run in secure mode (set gateway.controlUi.dangerouslyDisableDeviceAuth false), run this after opening the URL to poll pending pairing requests and approve the first one.
// 5. Poll for the browser's pending device request and approve it
for (let i = 0; i < 30; i++) {
  try {
    const res = await sandbox.commands.run(
      `openclaw devices list --json --url ws://127.0.0.1:${PORT} --token ${TOKEN}`
    )
    const data = JSON.parse(res.stdout)
    if (data.pending?.length) {
      const rid = data.pending[0].requestId
      await sandbox.commands.run(
        `openclaw devices approve ${rid} --token ${TOKEN} --url ws://127.0.0.1:${PORT}`
      )
      console.log(`Device approved: ${rid}`)
      break
    }
  } catch {}
  await new Promise((r) => setTimeout(r, 2000))
}
Once approved, the browser connects and the gateway UI loads.

How it works

StepWhat happens
--bind lanGateway listens on 0.0.0.0 so E2B can proxy it
--auth tokenRequires ?token= on the URL for HTTP and WebSocket auth
Browser opens URLGateway serves the UI, browser opens a WebSocket
code=1008 pairing requiredGateway closes the WebSocket until the device is approved (secure mode only)
devices approveApproves the browser’s device fingerprint (secure mode only)
Browser reconnectsWebSocket connects successfully, UI is live

Gateway flags reference

FlagPurpose
--allow-unconfiguredStart without a full config file
--bind lanBind to 0.0.0.0 (required for E2B port proxying)
--auth tokenEnable token-based authentication
--token <value>The auth token (passed as ?token= in the URL)
--port <number>Gateway listen port (default: 18789)

How to restart the gateway

Use this when the gateway is already running and you want a clean restart (for example, after changing model or env settings).
We can’t use the openclaw gateway restart command here. Some SDK environments cannot target a specific Unix user in commands.run. The commands below use the default command user context.
const TOKEN = process.env.OPENCLAW_APP_TOKEN || 'my-gateway-token'
const PORT = 18789

// 1) Kill existing gateway processes if present
await sandbox.commands.run(
  `bash -lc 'for p in "[o]penclaw gateway" "[o]penclaw-gateway"; do for pid in $(pgrep -f "$p" || true); do kill "$pid" >/dev/null 2>&1 || true; done; done'`
)
await new Promise((r) => setTimeout(r, 1000))

// 2) Start gateway again
await sandbox.commands.run(
  `openclaw gateway --allow-unconfigured --bind lan --auth token --token ${TOKEN} --port ${PORT}`,
  { background: true }
)

// 3) Wait for listening socket
for (let i = 0; i < 45; i++) {
  const probe = await sandbox.commands.run(
    `bash -lc 'ss -ltn | grep -q ":${PORT} " && echo ready || echo waiting'`
  )
  if (probe.stdout.trim() === 'ready') break
  await new Promise((r) => setTimeout(r, 1000))
}
Use this to restore secure device authentication after initial testing.
const TOKEN = process.env.OPENCLAW_APP_TOKEN || 'my-gateway-token'
const PORT = 18789

await sandbox.commands.run(
  `bash -lc 'openclaw config set gateway.controlUi.allowInsecureAuth false && ` +
    `openclaw config set gateway.controlUi.dangerouslyDisableDeviceAuth false'`
)

await sandbox.commands.run(
  `bash -lc 'for p in "[o]penclaw gateway" "[o]penclaw-gateway"; do for pid in $(pgrep -f "$p" || true); do kill "$pid" >/dev/null 2>&1 || true; done; done'`
)

await sandbox.commands.run(
  `openclaw gateway --allow-unconfigured --bind lan --auth token --token ${TOKEN} --port ${PORT}`,
  { background: true }
)