Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
f41e732
openclaw gateway instructions
matthewlouisbrockman Feb 25, 2026
329fa1e
also comment
matthewlouisbrockman Feb 25, 2026
d05769d
really really remind to open browser in that step
matthewlouisbrockman Feb 25, 2026
6fbfcf8
start on telegram - can make this easier tho
matthewlouisbrockman Feb 25, 2026
f400c0d
update telegram instructions for enabling it
matthewlouisbrockman Feb 25, 2026
a85ed2b
oauth usage
matthewlouisbrockman Feb 25, 2026
9192375
general env explanation (not sure need this)
matthewlouisbrockman Feb 25, 2026
14a122c
reorder the docs for openclaw
matthewlouisbrockman Feb 25, 2026
6081445
oauth updated
matthewlouisbrockman Feb 25, 2026
c5b0fbf
js implementation of oauth
matthewlouisbrockman Feb 25, 2026
816982c
cleanup a bit
matthewlouisbrockman Feb 25, 2026
ce674ce
rm numbering
matthewlouisbrockman Feb 25, 2026
c480482
env has js/python too, but possibly can yeet this guy and put in the …
matthewlouisbrockman Feb 25, 2026
677820a
bottom links
matthewlouisbrockman Feb 27, 2026
099ff48
standardize on openai
matthewlouisbrockman Feb 27, 2026
36fd2ab
default to 5.2
matthewlouisbrockman Feb 27, 2026
8d1a91c
use 5.2 for telegram instead of 5.3-codex; having issues for some reason
matthewlouisbrockman Feb 27, 2026
6f317ed
simplify openclaw docs to what we know works to get initial version out
matthewlouisbrockman Feb 27, 2026
ce90d0a
slack docs - dm works, may need more guide on @ usage
matthewlouisbrockman Feb 27, 2026
f22e9f1
try/catch around the commands json for js
matthewlouisbrockman Feb 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,15 @@
"docs/agents/amp",
"docs/agents/claude-code",
"docs/agents/codex",
{
"group": "OpenClaw",
"icon": "/images/icons/openclaw.svg",
"pages": [
"docs/agents/openclaw-gateway",
"docs/agents/openclaw-telegram",
"docs/agents/openclaw-slack"
]
},
"docs/agents/opencode"
]
},
Expand Down
331 changes: 331 additions & 0 deletions docs/agents/openclaw-environment.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,331 @@
---
title: "OpenClaw Environment"
description: "Change models, rotate tokens, update channels, and reset OpenClaw state in a running E2B sandbox."
icon: "sliders"
---

Use this guide for post-deploy changes in a running OpenClaw sandbox using SDK calls.

## What you can change without rebuilding

| Setting | Rebuild required? | Notes |
|---|---|---|
| Default model (`agents.defaults.model.primary`) | No | Applies to new runs |
| Gateway token (`--token`) | No | Restart gateway process with new token |
| Telegram bot token | No | Re-run `channels add`, then restart gateway |
| OpenAI / Anthropic API keys | No | Update runtime env used by OpenClaw processes |
| OpenAI Codex OAuth profile | No | Clear auth profile, then relink |

## Connect to your sandbox

<CodeGroup>
```python Python
from e2b import Sandbox

sandbox = Sandbox.connect("<sandbox_id>", timeout=60 * 30)
```
```typescript JavaScript & TypeScript
import { Sandbox } from 'e2b'

const sandbox = await Sandbox.connect('<sandbox_id>', {
timeoutMs: 60 * 30 * 1000,
})
```
</CodeGroup>

## Change default model

<CodeGroup>
```python Python
sandbox.commands.run("openclaw config set agents.defaults.model.primary openai/gpt-5.2")
print(sandbox.commands.run("openclaw models status --json").stdout)
```
```typescript JavaScript & TypeScript
await sandbox.commands.run('openclaw config set agents.defaults.model.primary openai/gpt-5.2')
const models = await sandbox.commands.run('openclaw models status --json')
console.log(models.stdout)
```
</CodeGroup>

## Rotate gateway token (no sandbox restart)

After rotation, old URLs with the previous `?token=` stop working.

<CodeGroup>
```python Python
NEW_TOKEN = "replace-me"
PORT = 18789

rotate = sandbox.commands.run(
"""bash -lc '
set -euo pipefail
pkill -f "openclaw gateway" >/dev/null 2>&1 || true
nohup openclaw gateway --allow-unconfigured --bind lan --auth token --token "$NEW_TOKEN" --port "$PORT" \
> /home/user/openclaw_gateway.log 2>&1 &
sleep 1
ss -ltn | grep -q ":$PORT " && echo ready || echo waiting
'""",
envs={"NEW_TOKEN": NEW_TOKEN, "PORT": str(PORT)},
)
print(rotate.stdout)
```
```typescript JavaScript & TypeScript
const NEW_TOKEN = 'replace-me'
const PORT = 18789

const rotate = await sandbox.commands.run(
`bash -lc '
set -euo pipefail
pkill -f "openclaw gateway" >/dev/null 2>&1 || true
nohup openclaw gateway --allow-unconfigured --bind lan --auth token --token "$NEW_TOKEN" --port "$PORT" \
> /home/user/openclaw_gateway.log 2>&1 &
sleep 1
ss -ltn | grep -q ":$PORT " && echo ready || echo waiting
'`,
{ envs: { NEW_TOKEN, PORT: String(PORT) } }
)
console.log(rotate.stdout)
```
</CodeGroup>

## Update provider keys after deploy

### One-off command

<CodeGroup>
```python Python
one_off = sandbox.commands.run(
'openclaw agent --local --message "hello"',
envs={"OPENAI_API_KEY": "sk-..."},
)
print(one_off.stdout)
```
```typescript JavaScript & TypeScript
const oneOff = await sandbox.commands.run(
'openclaw agent --local --message "hello"',
{ envs: { OPENAI_API_KEY: 'sk-...' } }
)
console.log(oneOff.stdout)
```
</CodeGroup>

### Persistent runtime env

<CodeGroup>
```python Python
persist = sandbox.commands.run(
"""bash -lc '
set -euo pipefail
cat > /home/user/.openclaw-runtime.env <<EOF
export OPENAI_API_KEY="$OPENAI_API_KEY"
export ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY"
EOF
chmod 600 /home/user/.openclaw-runtime.env
'""",
envs={
"OPENAI_API_KEY": "sk-...",
"ANTHROPIC_API_KEY": "sk-ant-...",
},
)
print(persist.stdout)
```
```typescript JavaScript & TypeScript
const persist = await sandbox.commands.run(
`bash -lc '
set -euo pipefail
cat > /home/user/.openclaw-runtime.env <<EOF
export OPENAI_API_KEY="$OPENAI_API_KEY"
export ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY"
EOF
chmod 600 /home/user/.openclaw-runtime.env
'`,
{
envs: {
OPENAI_API_KEY: 'sk-...',
ANTHROPIC_API_KEY: 'sk-ant-...',
},
}
)
console.log(persist.stdout)
```
</CodeGroup>

## Update Telegram bot token

<CodeGroup>
```python Python
telegram = sandbox.commands.run(
"""bash -lc '
set -euo pipefail
openclaw config set plugins.entries.telegram.enabled true
openclaw channels add --channel telegram --token "$NEW_TELEGRAM_BOT_TOKEN"
'""",
envs={"NEW_TELEGRAM_BOT_TOKEN": "123456:abc"},
)
print(telegram.stdout)
```
```typescript JavaScript & TypeScript
const telegram = await sandbox.commands.run(
`bash -lc '
set -euo pipefail
openclaw config set plugins.entries.telegram.enabled true
openclaw channels add --channel telegram --token "$NEW_TELEGRAM_BOT_TOKEN"
'`,
{ envs: { NEW_TELEGRAM_BOT_TOKEN: '123456:abc' } }
)
console.log(telegram.stdout)
```
</CodeGroup>

## Reset Telegram channel + pairing state

<CodeGroup>
```python Python
sandbox.commands.run("openclaw channels remove --channel telegram --delete")
sandbox.commands.run(
'openclaw channels add --channel telegram --token "$TELEGRAM_BOT_TOKEN"',
envs={"TELEGRAM_BOT_TOKEN": "123456:abc"},
)
print(sandbox.commands.run("openclaw pairing list --json --channel telegram").stdout)
```
```typescript JavaScript & TypeScript
await sandbox.commands.run('openclaw channels remove --channel telegram --delete')
await sandbox.commands.run(
'openclaw channels add --channel telegram --token "$TELEGRAM_BOT_TOKEN"',
{ envs: { TELEGRAM_BOT_TOKEN: '123456:abc' } }
)
const pairing = await sandbox.commands.run('openclaw pairing list --json --channel telegram')
console.log(pairing.stdout)
```
</CodeGroup>

Approve a pending pairing code:

<CodeGroup>
```python Python
PAIRING_CODE = "ABCDEFGH"
sandbox.commands.run(f"openclaw pairing approve --channel telegram {PAIRING_CODE}")
```
```typescript JavaScript & TypeScript
const PAIRING_CODE = 'ABCDEFGH'
await sandbox.commands.run(`openclaw pairing approve --channel telegram ${PAIRING_CODE}`)
```
</CodeGroup>

## Reset OpenAI Codex OAuth profile

<CodeGroup>
```python Python
reset = sandbox.commands.run(
"""python3 - <<'PY'
import json
from pathlib import Path

p = Path('/home/user/.openclaw/agents/main/agent/auth-profiles.json')
raw = json.loads(p.read_text()) if p.exists() else {}
profiles = raw.get('profiles', {}) if isinstance(raw, dict) else {}
raw['profiles'] = {
k: v for k, v in profiles.items()
if not (isinstance(v, dict) and v.get('provider') == 'openai-codex')
}
p.parent.mkdir(parents=True, exist_ok=True)
p.write_text(json.dumps(raw, indent=2) + '\\n')
print('cleared openai-codex oauth profiles')
PY"""
)
print(reset.stdout)
```
```typescript JavaScript & TypeScript
const reset = await sandbox.commands.run(`python3 - <<'PY'
import json
from pathlib import Path

p = Path('/home/user/.openclaw/agents/main/agent/auth-profiles.json')
raw = json.loads(p.read_text()) if p.exists() else {}
profiles = raw.get('profiles', {}) if isinstance(raw, dict) else {}
raw['profiles'] = {
k: v for k, v in profiles.items()
if not (isinstance(v, dict) and v.get('provider') == 'openai-codex')
}
p.parent.mkdir(parents=True, exist_ok=True)
p.write_text(json.dumps(raw, indent=2) + '\\n')
print('cleared openai-codex oauth profiles')
PY`)
console.log(reset.stdout)
```
</CodeGroup>

Then relink OAuth using the OAuth guide.

## Verify current state

<CodeGroup>
```python Python
print(sandbox.commands.run("openclaw channels list --json").stdout)
print(sandbox.commands.run("openclaw channels status --json --probe").stdout)
print(sandbox.commands.run("openclaw pairing list --json --channel telegram").stdout)
print(sandbox.commands.run("openclaw models status --json").stdout)
```
```typescript JavaScript & TypeScript
console.log((await sandbox.commands.run('openclaw channels list --json')).stdout)
console.log((await sandbox.commands.run('openclaw channels status --json --probe')).stdout)
console.log((await sandbox.commands.run('openclaw pairing list --json --channel telegram')).stdout)
console.log((await sandbox.commands.run('openclaw models status --json')).stdout)
```
</CodeGroup>

## Interactive tasks with PTY (optional)

Use PTY when the command expects interactive input (for example OAuth onboarding).

<CodeGroup>
```python Python
from e2b.sandbox.commands.command_handle import PtySize

terminal = sandbox.pty.create(PtySize(cols=140, rows=40), timeout=0)
sandbox.pty.send_stdin(terminal.pid, b"openclaw onboard --accept-risk --flow quickstart --mode local --auth-choice openai-codex\\r")
```
```typescript JavaScript & TypeScript
const terminal = await sandbox.pty.create({ cols: 140, rows: 40, timeoutMs: 10 * 60_000, onData: (d) => process.stdout.write(new TextDecoder().decode(d)) })
await sandbox.pty.sendInput(terminal.pid, new TextEncoder().encode('openclaw onboard --accept-risk --flow quickstart --mode local --auth-choice openai-codex\\r'))
```
</CodeGroup>

## Cleanup

<CodeGroup>
```python Python
sandbox.kill()
```
```typescript JavaScript & TypeScript
await sandbox.kill()
```
</CodeGroup>

## Troubleshooting

- `Unknown channel: telegram`
- Telegram channel is not configured yet.
- Run `openclaw channels add --channel telegram --token "$TELEGRAM_BOT_TOKEN"`, then retry.
- `No API key found for provider ...`
- Model/provider mismatch.
- `openai/...` needs `OPENAI_API_KEY`; `anthropic/...` needs `ANTHROPIC_API_KEY`.
- Pairing list is empty
- Send a fresh message to the bot first.

## Related

<CardGroup cols={4}>
<Card title="OpenClaw" icon="terminal" href="/docs/agents/openclaw">
Run OpenClaw headless in a sandbox
</Card>
<Card title="OpenClaw Gateway" icon="globe" href="/docs/agents/openclaw-gateway">
Run OpenClaw's web/channel runtime
</Card>
<Card title="OpenClaw Telegram" icon="message-circle" href="/docs/agents/openclaw-telegram">
Connect and pair Telegram users
</Card>
<Card title="OpenClaw OAuth" icon="key" href="/docs/agents/openclaw-oauth">
Link OpenAI Codex OAuth in a sandbox
</Card>
</CardGroup>
Loading