diff --git a/docs.json b/docs.json index da53d455..e39fae0c 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..f6a1729d --- /dev/null +++ b/docs/agents/openclaw/openclaw-gateway.mdx @@ -0,0 +1,277 @@ +--- +title: "Deploy OpenClaw" +description: "Start the OpenClaw gateway in an E2B sandbox and connect your browser." +icon: "globe" +--- + +## 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' + +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}`) +``` +```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. Set insecure control UI flags and start the gateway with token auth +sandbox.commands.run( + 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, +) + +# 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}") +``` + + +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. + + +```typescript JavaScript & TypeScript +// 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)) +} +``` +```python Python +import json + +# 5. 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 (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 + +| 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) +``` + + +## Turn insecure flags off (recommended after testing) + +Use this to restore secure device authentication after initial 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 + + + + 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..da2b0059 --- /dev/null +++ b/docs/agents/openclaw/openclaw-telegram.mdx @@ -0,0 +1,196 @@ +--- +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). 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. + +## 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( + `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 } +) + +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"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, +) + +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 + +