From bd89da2e942ac014deae12731b24ddb62c7691d6 Mon Sep 17 00:00:00 2001 From: Matt Brockman Date: Fri, 27 Feb 2026 00:32:22 -0800 Subject: [PATCH 1/8] initial openclaw instructions --- docs.json | 8 + docs/agents/openclaw/openclaw-gateway.mdx | 234 +++++++++++++++++++++ docs/agents/openclaw/openclaw-telegram.mdx | 192 +++++++++++++++++ 3 files changed, 434 insertions(+) create mode 100644 docs/agents/openclaw/openclaw-gateway.mdx create mode 100644 docs/agents/openclaw/openclaw-telegram.mdx diff --git a/docs.json b/docs.json index 1a813472..8a3d60c5 100644 --- a/docs.json +++ b/docs.json @@ -56,6 +56,14 @@ "docs/agents/amp", "docs/agents/claude-code", "docs/agents/codex", + { + "group": "OpenClaw", + "icon": "/images/icons/openclaw.svg", + "pages": [ + "docs/agents/openclaw/openclaw-gateway", + "docs/agents/openclaw/openclaw-telegram" + ] + }, "docs/agents/opencode" ] }, diff --git a/docs/agents/openclaw/openclaw-gateway.mdx b/docs/agents/openclaw/openclaw-gateway.mdx new file mode 100644 index 00000000..a61cecc2 --- /dev/null +++ b/docs/agents/openclaw/openclaw-gateway.mdx @@ -0,0 +1,234 @@ +--- +title: "Deploy OpenClaw" +description: "Start the OpenClaw gateway in an E2B sandbox, connect your browser, and auto-approve device pairing." +icon: "globe" +--- + +The OpenClaw [gateway](https://docs.openclaw.ai/gateway) serves a web UI for chatting with agents. When exposed over a network it requires **token auth** and **device pairing** — your browser must be approved as a trusted device before it can connect. + +This guide starts the gateway inside an E2B sandbox, prints the URL, and programmatically approves your browser. + +## Quick start + + +```typescript JavaScript & TypeScript +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. Start the gateway with token auth +sandbox.commands.run( + `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}`) +// Open the URL in your browser before running the next step. +``` +```python Python +import os, time +from e2b import Sandbox + +TOKEN = os.environ.get("OPENCLAW_APP_TOKEN", "my-gateway-token") +PORT = 18789 + +# 1. Create sandbox +sandbox = Sandbox.create("openclaw", envs={ + "OPENAI_API_KEY": os.environ["OPENAI_API_KEY"], +}, timeout=3600) + +# 2. Set the default model +sandbox.commands.run("openclaw config set agents.defaults.model.primary openai/gpt-5.2") + +# 3. Start the gateway with token auth +sandbox.commands.run( + f"openclaw gateway --allow-unconfigured --bind lan --auth token --token {TOKEN} --port {PORT}", + background=True, +) + +# 4. Wait for the gateway to start listening +for _ in range(45): + probe = sandbox.commands.run( + f'bash -lc \'ss -ltn | grep -q ":{PORT} " && echo ready || echo waiting\'' + ) + if probe.stdout.strip() == "ready": + break + time.sleep(1) + +url = f"https://{sandbox.get_host(PORT)}/?token={TOKEN}" +print(f"Gateway: {url}") +# Open the URL in your browser before running the next step. +``` + + + +Open the URL in your browser. It will show **"Pairing required"** — that's expected. Run the next step to approve your device. + + +## Approve device pairing + +The gateway requires each browser to be approved as a paired device. Run this after opening the URL — it polls for pending requests and approves the first one. + + +```typescript JavaScript & TypeScript +// Make sure you've opened the gateway URL in your browser before running this. + +// 4. Poll for the browser's pending device request and approve it +for (let i = 0; i < 30; i++) { + 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 + } + await new Promise((r) => setTimeout(r, 2000)) +} +``` +```python Python +import json + +# Make sure you've opened the gateway URL in your browser before running this. + +# 4. Poll for the browser's pending device request and approve it +for _ in range(30): + try: + res = sandbox.commands.run( + f"openclaw devices list --json --url ws://127.0.0.1:{PORT} --token {TOKEN}" + ) + data = json.loads(res.stdout) + if data.get("pending"): + rid = data["pending"][0]["requestId"] + sandbox.commands.run( + f"openclaw devices approve {rid} --token {TOKEN} --url ws://127.0.0.1:{PORT}" + ) + print(f"Device approved: {rid}") + break + except Exception: + pass + time.sleep(2) +``` + + +Once approved, the browser connects and the gateway UI loads. + +## How it works + +| Step | What happens | +|------|-------------| +| `--bind lan` | Gateway listens on `0.0.0.0` so E2B can proxy it | +| `--auth token` | Requires `?token=` on the URL for HTTP and WebSocket auth | +| Browser opens URL | Gateway serves the UI, browser opens a WebSocket | +| `code=1008 pairing required` | Gateway closes the WebSocket until the device is approved | +| `devices approve` | Approves the browser's device fingerprint | +| Browser reconnects | WebSocket connects successfully, UI is live | + +## Gateway flags reference + +| Flag | Purpose | +|------|---------| +| `--allow-unconfigured` | Start without a full config file | +| `--bind lan` | Bind to `0.0.0.0` (required for E2B port proxying) | +| `--auth token` | Enable token-based authentication | +| `--token ` | The auth token (passed as `?token=` in the URL) | +| `--port ` | 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. + + + +```typescript JavaScript & TypeScript +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)) +} +``` +```python Python +import os, time + +TOKEN = os.environ.get("OPENCLAW_APP_TOKEN", "my-gateway-token") +PORT = 18789 + +# 1) Kill existing gateway processes if present +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'""" +) +time.sleep(1) + +# 2) Start gateway again +sandbox.commands.run( + f"openclaw gateway --allow-unconfigured --bind lan --auth token --token {TOKEN} --port {PORT}", + background=True, +) + +# 3) Wait for listening socket +for _ in range(45): + probe = sandbox.commands.run( + f'bash -lc \'ss -ltn | grep -q ":{PORT} " && echo ready || echo waiting\'' + ) + if probe.stdout.strip() == "ready": + break + time.sleep(1) +``` + + +## Related + + + + Connect OpenClaw to Telegram and approve pairing + + diff --git a/docs/agents/openclaw/openclaw-telegram.mdx b/docs/agents/openclaw/openclaw-telegram.mdx new file mode 100644 index 00000000..319f760d --- /dev/null +++ b/docs/agents/openclaw/openclaw-telegram.mdx @@ -0,0 +1,192 @@ +--- +title: "OpenClaw Telegram" +description: "Connect OpenClaw to Telegram in an E2B sandbox, approve pairing, and chat through your bot." +icon: "paper-plane" +--- + +OpenClaw supports Telegram as a chat channel. In E2B you can run OpenClaw in a sandbox, attach your bot token, and approve user pairing from the terminal. + +This guide covers the working flow we used: + +1. Start OpenClaw in a sandbox. +2. Enable the Telegram plugin. +3. Add Telegram channel credentials. +4. Start the channel runtime in background. +5. Approve Telegram pairing. + +## Prerequisites + +- A Telegram bot token from [@BotFather](https://t.me/BotFather). +- An OpenAI API key for the OpenClaw model. +- E2B API key configured locally. + +## Quick start + + +```typescript JavaScript & TypeScript +import { Sandbox } from 'e2b' + +const GATEWAY_PORT = 18789 +const GATEWAY_TOKEN = process.env.OPENCLAW_APP_TOKEN || 'my-openclaw-token' + +const sandbox = await Sandbox.create('openclaw', { + envs: { + OPENAI_API_KEY: process.env.OPENAI_API_KEY, + TELEGRAM_BOT_TOKEN: process.env.TELEGRAM_BOT_TOKEN, + }, + timeoutMs: 3600_000, +}) + +await sandbox.commands.run('openclaw config set agents.defaults.model.primary openai/gpt-5.2') + +// Enable the Telegram plugin (required before adding the channel) +await sandbox.commands.run('openclaw config set plugins.entries.telegram.enabled true') +await sandbox.commands.run('openclaw channels add --channel telegram --token "$TELEGRAM_BOT_TOKEN"') + +await sandbox.commands.run( + `openclaw gateway --allow-unconfigured --bind lan --auth token --token ${GATEWAY_TOKEN} --port ${GATEWAY_PORT}`, + { background: true } +) + +for (let i = 0; i < 45; i++) { + const probe = await sandbox.commands.run( + `bash -lc 'ss -ltn | grep -q ":${GATEWAY_PORT} " && echo ready || echo waiting'` + ) + if (probe.stdout.trim() === 'ready') break + await new Promise((r) => setTimeout(r, 1000)) +} +``` +```python Python +import os +import time +from e2b import Sandbox + +GATEWAY_PORT = 18789 +GATEWAY_TOKEN = os.environ.get("OPENCLAW_APP_TOKEN", "my-openclaw-token") + +sandbox = Sandbox.create("openclaw", envs={ + "OPENAI_API_KEY": os.environ["OPENAI_API_KEY"], + "TELEGRAM_BOT_TOKEN": os.environ["TELEGRAM_BOT_TOKEN"], +}, timeout=3600) + +sandbox.commands.run("openclaw config set agents.defaults.model.primary openai/gpt-5.2") + +# Enable the Telegram plugin (required before adding the channel) +sandbox.commands.run("openclaw config set plugins.entries.telegram.enabled true") +sandbox.commands.run('openclaw channels add --channel telegram --token "$TELEGRAM_BOT_TOKEN"') + +sandbox.commands.run( + f"openclaw gateway --allow-unconfigured --bind lan --auth token --token {GATEWAY_TOKEN} --port {GATEWAY_PORT}", + background=True, +) + +for _ in range(45): + probe = sandbox.commands.run( + f"bash -lc 'ss -ltn | grep -q \":{GATEWAY_PORT} \" && echo ready || echo waiting'" + ) + if probe.stdout.strip() == "ready": + break + time.sleep(1) +``` + + + +For Telegram setup, you do **not** need to open the gateway URL in a browser. The gateway process is used here as a long-running channel runtime. + + +## Pair your Telegram user + +1. Open your bot in Telegram and send a message (for example: `hi`). +2. Telegram will return a pairing prompt similar to: + +```text +OpenClaw: access not configured. + +Your Telegram user id: ... +Pairing code: XXXXXXXX + +Ask the bot owner to approve with: +openclaw pairing approve telegram XXXXXXXX +``` + +3. Approve that pairing code via `sandbox.commands.run(...)`: + + +```typescript JavaScript & TypeScript +const PAIRING_CODE = 'XXXXXXXX' // from Telegram + +await sandbox.commands.run( + `openclaw pairing approve --channel telegram ${PAIRING_CODE}` +) +``` +```python Python +PAIRING_CODE = "XXXXXXXX" # from Telegram + +sandbox.commands.run( + f"openclaw pairing approve --channel telegram {PAIRING_CODE}" +) +``` + + +`openclaw pairing approve telegram ` also works if you prefer that form. + +## Verify channel status + + +```typescript JavaScript & TypeScript +const channels = await sandbox.commands.run('openclaw channels list --json') +const status = await sandbox.commands.run('openclaw channels status --json --probe') +const pairing = await sandbox.commands.run('openclaw pairing list --json --channel telegram') + +console.log(JSON.parse(channels.stdout)) +console.log(JSON.parse(status.stdout)) +console.log(JSON.parse(pairing.stdout)) +``` +```python Python +import json + +channels = sandbox.commands.run("openclaw channels list --json") +status = sandbox.commands.run("openclaw channels status --json --probe") +pairing = sandbox.commands.run("openclaw pairing list --json --channel telegram") + +print(json.loads(channels.stdout)) +print(json.loads(status.stdout)) +print(json.loads(pairing.stdout)) +``` + + +If you need logs from channel handlers: + + +```typescript JavaScript & TypeScript +const logs = await sandbox.commands.run( + 'openclaw channels logs --channel telegram --lines 200' +) +console.log(logs.stdout) +``` +```python Python +logs = sandbox.commands.run( + "openclaw channels logs --channel telegram --lines 200" +) +print(logs.stdout) +``` + + +## Troubleshooting + +- `Unknown channel: telegram` + - The Telegram plugin is not enabled. Run `openclaw config set plugins.entries.telegram.enabled true` before adding the channel. +- `OpenClaw: access not configured` + - Pairing has not been approved yet. Run `openclaw pairing approve ...`. +- `No API key found for provider ...` + - This guide uses `openai/gpt-5.2`. Set `OPENAI_API_KEY` in sandbox envs. +- No pending pairing requests from `pairing list` + - Send a fresh message to the bot first, then retry `pairing list --channel telegram`. + +## Related + + + + Run OpenClaw's web gateway with token auth + + From d7e3617955f702bdf53b1b0d5e639ce12fcc8f82 Mon Sep 17 00:00:00 2001 From: Matt Brockman Date: Fri, 27 Feb 2026 11:32:59 -0800 Subject: [PATCH 2/8] try/catch aroudn the js command polling --- docs/agents/openclaw/openclaw-gateway.mdx | 24 ++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/docs/agents/openclaw/openclaw-gateway.mdx b/docs/agents/openclaw/openclaw-gateway.mdx index a61cecc2..99f2f625 100644 --- a/docs/agents/openclaw/openclaw-gateway.mdx +++ b/docs/agents/openclaw/openclaw-gateway.mdx @@ -95,18 +95,20 @@ The gateway requires each browser to be approved as a paired device. Run this af // 4. Poll for the browser's pending device request and approve it for (let i = 0; i < 30; i++) { - 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}` + try { + const res = await sandbox.commands.run( + `openclaw devices list --json --url ws://127.0.0.1:${PORT} --token ${TOKEN}` ) - console.log(`Device approved: ${rid}`) - break - } + 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)) } ``` From 44fb38d106bccd75c341aea798a7664c6e3bce66 Mon Sep 17 00:00:00 2001 From: Matt Brockman Date: Fri, 27 Feb 2026 11:58:56 -0800 Subject: [PATCH 3/8] add note about the bot token --- docs/agents/openclaw/openclaw-telegram.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/agents/openclaw/openclaw-telegram.mdx b/docs/agents/openclaw/openclaw-telegram.mdx index 319f760d..5f093a81 100644 --- a/docs/agents/openclaw/openclaw-telegram.mdx +++ b/docs/agents/openclaw/openclaw-telegram.mdx @@ -16,7 +16,7 @@ This guide covers the working flow we used: ## Prerequisites -- A Telegram bot token from [@BotFather](https://t.me/BotFather). +- A Telegram bot token from [@BotFather](https://t.me/BotFather). There's instructions to follow there, it runs /newbot for you and walks you through naming and creating your bot. - An OpenAI API key for the OpenClaw model. - E2B API key configured locally. From b00dd71dda3692c30e3b7da3f451a9204de8499d Mon Sep 17 00:00:00 2001 From: Matt Brockman Date: Fri, 27 Feb 2026 12:12:06 -0800 Subject: [PATCH 4/8] missing await on openclaw js --- docs/agents/openclaw/openclaw-gateway.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/agents/openclaw/openclaw-gateway.mdx b/docs/agents/openclaw/openclaw-gateway.mdx index 99f2f625..617e4c74 100644 --- a/docs/agents/openclaw/openclaw-gateway.mdx +++ b/docs/agents/openclaw/openclaw-gateway.mdx @@ -27,7 +27,7 @@ const sandbox = await Sandbox.create('openclaw', { await sandbox.commands.run('openclaw config set agents.defaults.model.primary openai/gpt-5.2') // 3. Start the gateway with token auth -sandbox.commands.run( +await sandbox.commands.run( `openclaw gateway --allow-unconfigured --bind lan --auth token --token ${TOKEN} --port ${PORT}`, { background: true } ) From 6940f5823423d3e8649b62ceed211a2dc15177f7 Mon Sep 17 00:00:00 2001 From: Matt Brockman Date: Mon, 2 Mar 2026 11:38:54 -0800 Subject: [PATCH 5/8] dangerouslyDisableDeviceAuth insturctions --- docs/agents/openclaw/openclaw-gateway.mdx | 82 ++++++++++++++++++---- docs/agents/openclaw/openclaw-telegram.mdx | 8 ++- 2 files changed, 76 insertions(+), 14 deletions(-) diff --git a/docs/agents/openclaw/openclaw-gateway.mdx b/docs/agents/openclaw/openclaw-gateway.mdx index 617e4c74..628e35b8 100644 --- a/docs/agents/openclaw/openclaw-gateway.mdx +++ b/docs/agents/openclaw/openclaw-gateway.mdx @@ -1,12 +1,17 @@ --- title: "Deploy OpenClaw" -description: "Start the OpenClaw gateway in an E2B sandbox, connect your browser, and auto-approve device pairing." +description: "Start the OpenClaw gateway in an E2B sandbox and connect your browser (with optional insecure Control UI settings)." icon: "globe" --- -The OpenClaw [gateway](https://docs.openclaw.ai/gateway) serves a web UI for chatting with agents. When exposed over a network it requires **token auth** and **device pairing** — your browser must be approved as a trusted device before it can connect. +The OpenClaw [gateway](https://docs.openclaw.ai/gateway) serves a web UI for chatting with agents. When exposed over a network it typically uses **token auth** and may require **device pairing**. -This guide starts the gateway inside an E2B sandbox, prints the URL, and programmatically approves your browser. +This guide starts the gateway inside an E2B sandbox and sets: + +- `gateway.controlUi.allowInsecureAuth=true` +- `gateway.controlUi.dangerouslyDisableDeviceAuth=true` + +for local/testing convenience. ## Quick start @@ -26,9 +31,11 @@ const sandbox = await Sandbox.create('openclaw', { // 2. Set the default model await sandbox.commands.run('openclaw config set agents.defaults.model.primary openai/gpt-5.2') -// 3. Start the gateway with token auth +// 3. Set insecure control UI flags and start the gateway with token auth await sandbox.commands.run( - `openclaw gateway --allow-unconfigured --bind lan --auth token --token ${TOKEN} --port ${PORT}`, + `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 } ) @@ -60,9 +67,11 @@ sandbox = Sandbox.create("openclaw", envs={ # 2. Set the default model sandbox.commands.run("openclaw config set agents.defaults.model.primary openai/gpt-5.2") -# 3. Start the gateway with token auth +# 3. Set insecure control UI flags and start the gateway with token auth sandbox.commands.run( - f"openclaw gateway --allow-unconfigured --bind lan --auth token --token {TOKEN} --port {PORT}", + f"bash -lc 'openclaw config set gateway.controlUi.allowInsecureAuth true && " + f"openclaw config set gateway.controlUi.dangerouslyDisableDeviceAuth true && " + f"openclaw gateway --allow-unconfigured --bind lan --auth token --token {TOKEN} --port {PORT}'", background=True, ) @@ -82,12 +91,12 @@ print(f"Gateway: {url}") -Open the URL in your browser. It will show **"Pairing required"** — that's expected. Run the next step to approve your device. +Open the URL in your browser. With the insecure Control UI settings above, device pairing is disabled. -## Approve device pairing +## Optional: approve device pairing (secure mode) -The gateway requires each browser to be approved as a paired device. Run this after opening the URL — it polls for pending requests and approves the first one. +If you remove `gateway.controlUi.dangerouslyDisableDeviceAuth`, the gateway will require each browser to be approved as a paired device. Run this after opening the URL — it polls for pending requests and approves the first one. ```typescript JavaScript & TypeScript @@ -146,8 +155,8 @@ Once approved, the browser connects and the gateway UI loads. | `--bind lan` | Gateway listens on `0.0.0.0` so E2B can proxy it | | `--auth token` | Requires `?token=` on the URL for HTTP and WebSocket auth | | Browser opens URL | Gateway serves the UI, browser opens a WebSocket | -| `code=1008 pairing required` | Gateway closes the WebSocket until the device is approved | -| `devices approve` | Approves the browser's device fingerprint | +| `code=1008 pairing required` | Gateway closes the WebSocket until the device is approved (secure mode only) | +| `devices approve` | Approves the browser's device fingerprint (secure mode only) | | Browser reconnects | WebSocket connects successfully, UI is live | ## Gateway flags reference @@ -227,6 +236,55 @@ for _ in range(45): ``` +## Turn insecure flags off (recommended after testing) + +Use this to restore secure device authentication after local testing. + + +```typescript JavaScript & TypeScript +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 } +) +``` +```python Python +import os + +TOKEN = os.environ.get("OPENCLAW_APP_TOKEN", "my-gateway-token") +PORT = 18789 + +sandbox.commands.run( + "bash -lc 'openclaw config set gateway.controlUi.allowInsecureAuth false && " + "openclaw config set gateway.controlUi.dangerouslyDisableDeviceAuth false'" +) + +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'""" +) + +sandbox.commands.run( + f"openclaw gateway --allow-unconfigured --bind lan --auth token --token {TOKEN} --port {PORT}", + background=True, +) +``` + + ## Related diff --git a/docs/agents/openclaw/openclaw-telegram.mdx b/docs/agents/openclaw/openclaw-telegram.mdx index 5f093a81..da2b0059 100644 --- a/docs/agents/openclaw/openclaw-telegram.mdx +++ b/docs/agents/openclaw/openclaw-telegram.mdx @@ -44,7 +44,9 @@ await sandbox.commands.run('openclaw config set plugins.entries.telegram.enabled await sandbox.commands.run('openclaw channels add --channel telegram --token "$TELEGRAM_BOT_TOKEN"') await sandbox.commands.run( - `openclaw gateway --allow-unconfigured --bind lan --auth token --token ${GATEWAY_TOKEN} --port ${GATEWAY_PORT}`, + `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 ${GATEWAY_TOKEN} --port ${GATEWAY_PORT}'`, { background: true } ) @@ -76,7 +78,9 @@ sandbox.commands.run("openclaw config set plugins.entries.telegram.enabled true" sandbox.commands.run('openclaw channels add --channel telegram --token "$TELEGRAM_BOT_TOKEN"') sandbox.commands.run( - f"openclaw gateway --allow-unconfigured --bind lan --auth token --token {GATEWAY_TOKEN} --port {GATEWAY_PORT}", + f"bash -lc 'openclaw config set gateway.controlUi.allowInsecureAuth true && " + f"openclaw config set gateway.controlUi.dangerouslyDisableDeviceAuth true && " + f"openclaw gateway --allow-unconfigured --bind lan --auth token --token {GATEWAY_TOKEN} --port {GATEWAY_PORT}'", background=True, ) From 1e03a72c4298559ce1c1f2018d3f6813b54ef97f Mon Sep 17 00:00:00 2001 From: Matt Brockman Date: Mon, 2 Mar 2026 11:57:32 -0800 Subject: [PATCH 6/8] change from local testing to demo --- docs/agents/openclaw/openclaw-gateway.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/agents/openclaw/openclaw-gateway.mdx b/docs/agents/openclaw/openclaw-gateway.mdx index 628e35b8..3fbd330c 100644 --- a/docs/agents/openclaw/openclaw-gateway.mdx +++ b/docs/agents/openclaw/openclaw-gateway.mdx @@ -11,7 +11,7 @@ This guide starts the gateway inside an E2B sandbox and sets: - `gateway.controlUi.allowInsecureAuth=true` - `gateway.controlUi.dangerouslyDisableDeviceAuth=true` -for local/testing convenience. +for demonstration purposes. ## Quick start @@ -238,7 +238,7 @@ for _ in range(45): ## Turn insecure flags off (recommended after testing) -Use this to restore secure device authentication after local testing. +Use this to restore secure device authentication after initial testing. ```typescript JavaScript & TypeScript From 5b206e827971e956349de7f363ae56f453db0e38 Mon Sep 17 00:00:00 2001 From: Matt Brockman Date: Mon, 2 Mar 2026 12:09:30 -0800 Subject: [PATCH 7/8] clean up wording on dangerouslyDisableDeviceAuth --- docs/agents/openclaw/openclaw-gateway.mdx | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/docs/agents/openclaw/openclaw-gateway.mdx b/docs/agents/openclaw/openclaw-gateway.mdx index 3fbd330c..8f7fc23d 100644 --- a/docs/agents/openclaw/openclaw-gateway.mdx +++ b/docs/agents/openclaw/openclaw-gateway.mdx @@ -1,17 +1,10 @@ --- title: "Deploy OpenClaw" -description: "Start the OpenClaw gateway in an E2B sandbox and connect your browser (with optional insecure Control UI settings)." +description: "Start the OpenClaw gateway in an E2B sandbox and connect your browser." icon: "globe" --- -The OpenClaw [gateway](https://docs.openclaw.ai/gateway) serves a web UI for chatting with agents. When exposed over a network it typically uses **token auth** and may require **device pairing**. - -This guide starts the gateway inside an E2B sandbox and sets: - -- `gateway.controlUi.allowInsecureAuth=true` -- `gateway.controlUi.dangerouslyDisableDeviceAuth=true` - -for demonstration purposes. +The OpenClaw [gateway](https://docs.openclaw.ai/gateway) serves a web UI for chatting with agents. ## Quick start @@ -91,7 +84,8 @@ print(f"Gateway: {url}") -Open the URL in your browser. With the insecure Control UI settings above, device pairing is disabled. +If you're running with `dangerouslyDisableDeviceAuth` it should work now! +If device pairing is required, open the URL in your browser. With the insecure Control UI settings above, device pairing is disabled. ## Optional: approve device pairing (secure mode) From e3f9e4c32b3028831c52d9c9fc2698fe82ace075 Mon Sep 17 00:00:00 2001 From: Matt Brockman Date: Mon, 2 Mar 2026 15:47:39 -0800 Subject: [PATCH 8/8] move insecure flags instructions to bottom --- docs/agents/openclaw/openclaw-gateway.mdx | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/docs/agents/openclaw/openclaw-gateway.mdx b/docs/agents/openclaw/openclaw-gateway.mdx index 8f7fc23d..f6a1729d 100644 --- a/docs/agents/openclaw/openclaw-gateway.mdx +++ b/docs/agents/openclaw/openclaw-gateway.mdx @@ -4,10 +4,10 @@ description: "Start the OpenClaw gateway in an E2B sandbox and connect your brow icon: "globe" --- -The OpenClaw [gateway](https://docs.openclaw.ai/gateway) serves a web UI for chatting with agents. - ## Quick start +This launches your OpenClaw [gateway](https://docs.openclaw.ai/gateway) site (web UI for chatting with agents). + ```typescript JavaScript & TypeScript import { Sandbox } from 'e2b' @@ -43,7 +43,6 @@ for (let i = 0; i < 45; i++) { const url = `https://${sandbox.getHost(PORT)}/?token=${TOKEN}` console.log(`Gateway: ${url}`) -// Open the URL in your browser before running the next step. ``` ```python Python import os, time @@ -79,24 +78,16 @@ for _ in range(45): url = f"https://{sandbox.get_host(PORT)}/?token={TOKEN}" print(f"Gateway: {url}") -# Open the URL in your browser before running the next step. ``` - -If you're running with `dangerouslyDisableDeviceAuth` it should work now! -If device pairing is required, open the URL in your browser. With the insecure Control UI settings above, device pairing is disabled. - +Visit the printed `Gateway` URL in your browser. -## Optional: approve device pairing (secure mode) - -If you remove `gateway.controlUi.dangerouslyDisableDeviceAuth`, the gateway will require each browser to be approved as a paired device. Run this after opening the URL — it polls for pending requests and approves the first one. +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. ```typescript JavaScript & TypeScript -// Make sure you've opened the gateway URL in your browser before running this. - -// 4. Poll for the browser's pending device request and approve it +// 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( @@ -118,9 +109,7 @@ for (let i = 0; i < 30; i++) { ```python Python import json -# Make sure you've opened the gateway URL in your browser before running this. - -# 4. Poll for the browser's pending device request and approve it +# 5. Poll for the browser's pending device request and approve it for _ in range(30): try: res = sandbox.commands.run(