OpenClaw FAQ: Setup, Configuration, and Troubleshooting
Quick answers and deeper troubleshooting for OpenClaw production setups, including local dev, VPS, multi-agent, OAuth/API keys, and model failover. Includes diagnostic commands and health checks.
Read this when
- Answering common setup, install, onboarding, or runtime support questions
- Triaging user-reported issues before deeper debugging
Quick answers and deeper troubleshooting for production-style setups (local dev, VPS, multi-agent, OAuth/API keys, model failover). For runtime diagnostics, refer to Troubleshooting. The complete config reference is in Configuration.
First 60 seconds if something is broken
Quick status
openclaw status
Quick local summary: OS and updates, gateway/service reachability, agents/sessions, provider config plus runtime issues (when the gateway is reachable).
Pasteable report (safe to share)
openclaw status --all
Read-only diagnosis with a log tail (tokens redacted).
Daemon + port state
openclaw gateway status
Displays supervisor runtime versus RPC reachability, the probe target URL, and which config the service likely used.
Deep probes
openclaw status --deep
Live gateway health probe, including channel probes when supported (requires a reachable gateway). See Health.
Tail the latest log
openclaw logs --follow
If RPC is down, fall back to:
tail -f "/tmp/openclaw/openclaw-$(date +%F).log"
# Named profile example:
tail -f "/tmp/openclaw/openclaw-dev-$(date +%F).log"
File logs are separate from service logs; see Logging and Troubleshooting.
Run the doctor (repairs)
openclaw doctor
Repairs/migrates config and state, then runs health checks. See Doctor.
Gateway snapshot (WS-only)
openclaw health --json
openclaw health --verbose # shows the target URL + config path on errors
Asks the running gateway for a full snapshot. See Health.
Quick start and first-run setup
First-run Q&A - install, onboard, auth routes, subscriptions, initial failures - lives on the First-run FAQ.
What is OpenClaw?
What is OpenClaw, in one paragraph?
OpenClaw is a personal AI assistant you run on your own devices. It replies on the messaging surfaces you already use (Discord, Google Chat, iMessage, Mattermost, Signal, Slack, Telegram, WebChat, WhatsApp, and bundled channel plugins such as QQ Bot) and can also do voice plus hosted widgets in chat, on session dashboards, and in the macOS panel. The Gateway is the always-on control plane; the assistant is the product.
Value proposition
OpenClaw is not "just a Claude wrapper." It is a local-first control plane that runs a capable assistant on your own hardware, reachable from the chat apps you already use, with stateful sessions, memory, and tools - without handing your workflows to a hosted SaaS.
- Your devices, your data: run the Gateway wherever you want (Mac, Linux, VPS) and keep the workspace and session history local.
- Real channels, not a web sandbox: Discord/iMessage/Signal/Slack/Telegram/WhatsApp/etc, plus mobile voice and hosted widgets.
- Model-agnostic: use Anthropic, MiniMax, OpenAI, OpenRouter, etc., with per-agent routing and failover.
- Local-only option: run local models so all data can stay on your device.
- Multi-agent routing: separate agents per channel, account, or task, each with its own workspace and defaults.
- Open source and hackable: inspect, extend, and self-host without vendor lock-in.
Docs: Gateway, Channels, Multi-agent, Memory.
I just set it up - what should I do first?
Good first projects: build a website (WordPress, Shopify, or a static site); prototype a mobile app (outline, screens, API plan); organize files and folders; connect Gmail and automate summaries or follow-ups.
It can handle large tasks, but works best split into phases with sub-agents for parallel work.
What are the top five everyday use cases for OpenClaw?
- Personal briefings: summaries of inbox, calendar, and news you care about.
- Research and drafting: quick research, summaries, and first drafts for emails or docs.
- Reminders and follow-ups: cron- or heartbeat-driven nudges and checklists.
- Browser automation: filling forms, collecting data, repeating web tasks.
- Cross-device coordination: send a task from your phone, let the Gateway run it on a server, get the result back in chat.
Can OpenClaw help with lead gen, outreach, ads, and blogs for a SaaS?
Yes, for research, qualification, and drafting: scanning sites, building shortlists, summarizing prospects, writing outreach or ad copy drafts.
For outreach or ad runs, keep a human in the loop. Avoid spam, follow local laws and platform policies, and review anything before it sends. Let OpenClaw draft; you approve.
Docs: Security.
What are the advantages vs Claude Code for web development?
OpenClaw is a personal assistant and coordination layer, not an IDE replacement. Use Claude Code or Codex for the fastest direct coding loop inside a repo. Use OpenClaw for durable memory, cross-device access, and tool orchestration.
- Persistent memory and workspace across sessions.
- Multi-platform access (Telegram, WhatsApp, TUI, WebChat).
- Tool orchestration (browser, files, scheduling, hooks).
- Always-on Gateway (run on a VPS, interact from anywhere).
- Nodes for local browser/screen/camera/exec.
Showcase: https://openclaw.ai/showcase.
Skills and automation
How do I customize skills without keeping the repo dirty?
Use managed overrides instead of editing the repo copy. Put changes in ~/.openclaw/skills/<name>/SKILL.md (or add a folder via skills.load.extraDirs in ~/.openclaw/openclaw.json). Precedence: <workspace>/skills -> <workspace>/.agents/skills -> ~/.agents/skills -> ~/.openclaw/skills -> bundled -> skills.load.extraDirs, so managed overrides win over bundled skills without touching git. To install globally but limit visibility to some agents, keep the shared copy in ~/.openclaw/skills and control visibility with agents.defaults.skills / agents.entries.*.skills. Only upstream-worthy edits should go out as PRs against the repo copy.
Can I load skills from a custom folder?
Yes: add directories via skills.load.extraDirs in ~/.openclaw/openclaw.json (lowest precedence in the order above). clawhub installs into ./skills by default, which OpenClaw treats as <workspace>/skills on the next session. To limit visibility to certain agents, pair with agents.defaults.skills or agents.entries.*.skills.
How can I use different models or settings for different tasks?
Supported patterns:
- Cron jobs: an isolated job can carry its own
modeloverride. - Agents: work can be split across agents, each with its own default model, thinking level, and stream parameters.
- Configured default + current session: a direct owner/admin
/model <model>modifies the session and asks for a best-effort refresh of the configured default. When the agent lacks an explicit primary model, the sharedagents.defaults.modelfallback becomes the target. - Current session only:
/model <model> -s(or--session) touches just this session, leaving configured defaults untouched.
Example - one model, varied per-agent settings:
{
agents: {
ownership: "explicit",
entries: {
coder: {
model: "xiaomi/mimo-v2.5-pro",
thinkingDefault: "high",
params: { temperature: 0.1 },
},
chat: {
model: "xiaomi/mimo-v2.5-pro",
thinkingDefault: "off",
params: { temperature: 0.8 },
},
},
},
}
Keep shared per-model defaults in agents.defaults.models["provider/model"].params, then place agent-specific overrides in flat agents.entries.*.params. Avoid repeating the same model under nested agents.entries.*.models["provider/model"].params; that location is meant for per-agent model catalogs and runtime overrides.
Refer to Cron jobs, Multi-Agent Routing, Configuration, and Slash commands.
The bot freezes while doing heavy work. How do I offload that?
For long-running or parallel work, rely on sub-agents: they operate in their own session, hand back a summary, and leave your main chat responsive. Tell the bot to "spawn a sub-agent for this task," or use /subagents. To check whether the Gateway is occupied, use /status.
Both long tasks and sub-agents burn tokens; if cost is a concern, assign a cheaper model to sub-agents via agents.defaults.subagents.model.
Docs: Sub-agents, Background Tasks.
How do thread-bound subagent sessions work on Discord?
Attach a Discord thread to a subagent or session target so that follow-up messages in that thread stay on the bound session.
- Spawn with
sessions_spawnusingthread: true(optionallymode: "session"for persistent follow-up). - Alternatively, bind manually with
/focus <target>. /agentsshows the current binding state.- Auto-unfocus is managed by
/session idle <duration|off>and/session max-age <duration|off>. - Use
/unfocusto detach the thread.
Config: session.threadBindings.enabled (global switch), session.threadBindings.idleHours (default 24, 0 turns it off), session.threadBindings.maxAgeHours (default 0 = no hard cap), and session.threadBindings.spawnSessions for auto-bind on spawn (default true).
Docs: Sub-agents, Discord, Configuration Reference, Slash commands.
A subagent finished, but the completion update went to the wrong place or never posted. What should I check?
Look at the resolved requester route:
- In completion-mode subagent delivery, a bound thread or conversation route is preferred when one is present.
- If the completion origin carries only a channel, OpenClaw falls back to the requester session's stored route (
lastChannel/lastTo/lastAccountId) so direct delivery can still work. - Without a bound route and without a usable stored route, direct delivery may fail, and the result drops back to queued session delivery instead of posting right away.
- Invalid or stale targets can also push delivery to queue fallback or end in final delivery failure.
- When the child's last visible assistant reply is exactly
NO_REPLY/no_replyorANNOUNCE_SKIP, OpenClaw deliberately skips the announce rather than posting older progress.
Debug: openclaw tasks show <lookup> where <lookup> is a task id, run id, or session key.
Docs: Sub-agents, Background Tasks, Session Tools.
Cron or reminders do not fire. What should I check?
Cron runs within the Gateway process; it will not fire unless the Gateway stays running continuously.
- Verify cron is enabled (
cron.enabled) and thatOPENCLAW_SKIP_CRONis not set. - Make sure the Gateway runs 24/7 (no sleep or restarts).
- Check the job timezone (
--tzagainst the host timezone).
Debug:
openclaw cron run <jobId>
openclaw cron runs --id <jobId> --limit 50
Docs: Cron jobs, Automation.
Cron fired, but nothing was sent to the channel. Why?
Check which delivery mode applies:
--no-deliver/delivery.mode: "none": no runner fallback send is expected.- Missing or invalid announce target (
channel/to): the runner skipped outbound delivery. - Channel auth failures (
unauthorized,Forbidden): the runner tried to deliver but credentials blocked it. - A silent isolated result (
NO_REPLY/no_replyonly) is treated as intentionally non-deliverable, so queued fallback delivery is also suppressed.
For isolated cron jobs, the agent can still send directly with the message tool when a chat route is available. --announce only controls runner fallback delivery for final text the agent did not already send itself.
Debug:
openclaw cron runs --id <jobId> --limit 50
openclaw tasks show <lookup>
Docs: Cron jobs, Background Tasks.
Why did an isolated cron run switch models or retry once?
That is the live model-switch path, not duplicate scheduling. Isolated cron persists a runtime model handoff and retries when the active run throws LiveSessionModelSwitchError, keeping the switched provider/model (and any switched auth-profile override) before retrying.
Model-selection precedence: Gmail hook model override (hooks.gmail.model) first, then per-job model, then any stored cron-session model override, then normal agent/default model selection.
The retry loop is bounded to the initial attempt plus 2 switch retries; cron then aborts instead of looping forever.
Debug:
openclaw cron runs --id <jobId> --limit 50
How do I install skills on Linux?
Use native openclaw skills commands or drop skills into your workspace; the macOS Skills UI is not available on Linux. Browse skills at https://clawhub.ai.
openclaw skills search "calendar"
openclaw skills search --limit 20
openclaw skills install @owner/<skill-slug>
openclaw skills install @owner/<skill-slug> --version <version>
openclaw skills install @owner/<skill-slug> --force
openclaw skills install @owner/<skill-slug> --global
openclaw skills update --all
openclaw skills update --all --global
openclaw skills list --eligible
openclaw skills check
Native openclaw skills install writes into the active workspace skills/ directory by default. Add --global to install into the shared managed skills directory for all local agents. Install the separate clawhub CLI only to publish or sync your own skills. Use agents.defaults.skills or agents.entries.*.skills to narrow which agents see shared skills.
Can OpenClaw run tasks on a schedule or continuously in the background?
Yes, via the Gateway scheduler:
- Cron jobs for scheduled or recurring tasks (persist across restarts).
- Heartbeat for main-session periodic checks.
- Isolated jobs for autonomous agents that post summaries or deliver to chats.
Docs: Cron jobs, Automation, Heartbeat.
Can I run Apple macOS-only skills from Linux?
Not directly. macOS skills are gated by metadata.openclaw.os plus required binaries, and only load when eligible on the Gateway host. On Linux, darwin-only skills (apple-notes, apple-reminders, things-mac) will not load unless you override the gating.
Three supported patterns:
Option A - run the Gateway on a Mac (simplest). Run the Gateway where the macOS binaries exist, then connect from Linux in remote mode or over Tailscale. Skills load normally because the Gateway host is macOS.
Option B - use a macOS node (no SSH). Run the Gateway on Linux, pair a macOS node (menubar app), and set Node Run Commands to "Always Ask" or "Always Allow" on the Mac. OpenClaw treats macOS-only skills as eligible when required binaries exist on the node; the agent runs them via the nodes tool. With "Always Ask," approving "Always Allow" in the prompt adds that command to the allowlist.
Option C - proxy macOS binaries over SSH (advanced). Keep the Gateway on Linux, but make the required CLI binaries resolve to SSH wrappers that run on a Mac, then override the skill to allow Linux so it stays eligible.
- Create an SSH wrapper for the binary (example:
memofor Apple Notes):#!/usr/bin/env bash set -euo pipefail exec ssh -T user@mac-host /opt/homebrew/bin/memo "$@" - Put the wrapper on
PATHon the Linux host (for example~/bin/memo). - Override the skill metadata (workspace or
~/.openclaw/skills) to allow Linux:--- name: apple-notes description: Manage Apple Notes via the memo CLI on macOS. metadata: { "openclaw": { "os": ["darwin", "linux"], "requires": { "bins": ["memo"] } } } --- - Start a new session so the skills snapshot refreshes.
Do you have a Notion or HeyGen integration?
Not built in today. Options:
- Custom skill / plugin: best for reliable API access (both have APIs).
- Browser automation: works without code but is slower and more fragile.
For agency-style per-client context: keep one Notion page per client (context + preferences + active work) and ask the agent to fetch that page at the start of a session.
For a native integration, open a feature request or build a skill against those APIs.
openclaw skills install @owner/<skill-slug>
openclaw skills update --all
Native installs land in the active workspace skills/ directory; use --global for all local agents, or configure agents.defaults.skills / agents.entries.*.skills to limit visibility. Some skills expect Homebrew-installed binaries; on Linux that means Linuxbrew.
See Skills, Skills config, ClawHub.
How do I use my existing signed-in Chrome with OpenClaw?
Use the built-in user browser profile, which attaches through Chrome DevTools MCP:
openclaw browser --browser-profile user tabs
openclaw browser --browser-profile user snapshot
For a custom name, define an explicit MCP profile:
openclaw browser create-profile --name chrome-live --driver existing-session
openclaw browser --browser-profile chrome-live tabs
This profile can target either the local host browser or a browser node that is connected. If the Gateway is hosted elsewhere, either launch a node host on the machine running the browser, or switch to remote CDP.
Here are the current constraints for existing-session / user profiles compared with the managed openclaw profile:
click,type,hover,scrollIntoView,drag, andselectdemand snapshot refs rather than CSS selectors.- Upload hooks need
reforinputRef, processing a single file at a time, with no CSSelement. responsebody, PDF export, download interception, and batch actions continue to rely on the managed browser path.
The complete comparison is available at Browser.
Sandboxing and memory
Is there a dedicated sandboxing doc?
That is correct: Sandboxing. For Docker-specific instructions (the full gateway inside Docker, or sandbox images), refer to Docker.
Docker feels limited - how do I enable full features?
The default image prioritizes security and operates as the node user, so system packages, Homebrew, and bundled browsers are absent. For a more complete environment:
- Keep
/home/nodeusingOPENCLAW_HOME_VOLUMEso caches are retained. - Embed system dependencies into the image with
OPENCLAW_IMAGE_APT_PACKAGES. - Embed Playwright Chromium plus its system dependencies into the image with
OPENCLAW_INSTALL_BROWSER=1.
Documentation: Docker, Browser.
Can I keep DMs personal but make groups public/sandboxed with one agent?
Yes, provided private traffic consists of DMs and public traffic consists of groups. Configure agents.defaults.sandbox.mode: "non-main" so that group/channel sessions (non-main keys) execute in the designated sandbox backend while the primary DM session remains on the host. Choose backend: "docker" for Docker or backend: "podman" for Podman. Limit which tools sandboxed sessions can access through tools.sandbox.tools.
Step-by-step guide: Groups: personal DMs + public groups. Configuration reference: Gateway configuration.
How do I bind a host folder into the sandbox?
Assign agents.defaults.sandbox.docker.binds the value ["host:container:mode"] (for instance "/home/user/src:/src:ro"). Global and per-agent binds combine; per-agent binds are disregarded when scope: "shared". For anything sensitive, use :ro; binds bypass the sandbox filesystem walls.
OpenClaw checks bind sources against both the normalized path and the canonical path resolved through the deepest existing ancestor, so symlink-parent escapes fail closed even when the final path segment does not yet exist.
Consult Sandboxing and Sandbox vs Tool Policy vs Elevated.
How does memory work?
OpenClaw memory consists of Markdown files in the agent workspace: daily notes live in memory/YYYY-MM-DD.md, curated long-term notes in MEMORY.md (main/private sessions only).
OpenClaw also performs a silent pre-compaction memory flush before compaction summarizes the conversation, prompting the model to record durable notes first. This runs only when the workspace is writable (read-only sandboxes skip it); turn it off with agents.defaults.compaction.memoryFlush.enabled: false. See Memory.
Memory keeps forgetting things. How do I make it stick?
Tell the bot to write the fact to memory: long-term notes belong in MEMORY.md, short-term context in memory/YYYY-MM-DD.md. Prompting the model to save memories usually fixes the issue. If forgetting persists, confirm the Gateway uses the same workspace on every run.
Docs: Memory, Agent workspace.
Does memory persist forever? What are the limits?
Memory files reside on disk and remain until removed; storage capacity, not the model, is the only limit. Session context remains bounded by the model context window, so extended conversations may compact or truncate, which is exactly why memory search exists, retrieving only the relevant pieces back into context.
Does semantic memory search require an OpenAI API key?
Only when you use OpenAI embeddings, which is the default provider. Codex OAuth covers chat/completions and does not include embeddings access, so signing in with Codex (OAuth or the Codex CLI login) will not activate semantic memory search. OpenAI embeddings still require a real API key (OPENAI_API_KEY or models.providers.openai.apiKey).
To keep processing on your own hardware, set memory.search.provider: "local" (GGUF/llama.cpp). Additional providers you can use: Bedrock, DeepInfra, Gemini (GEMINI_API_KEY or memory.search.remote.apiKey), GitHub Copilot, LM Studio, Mistral, Ollama, OpenAI-compatible, and Voyage. Configuration instructions are in Memory and Memory search.
Where things live on disk
Is all data used with OpenClaw saved locally?
No: OpenClaw's own state is local, but external services still see what you send them.
- Local by default: sessions, memory files, config, and workspace live on the Gateway host (
~/.openclawplus your workspace directory). - Remote by necessity: messages sent to model providers (Anthropic/OpenAI/etc.) go to their APIs, and chat platforms (Slack/Telegram/WhatsApp/etc.) store message data on their servers.
- You control the footprint: local models keep prompts on your machine, but channel traffic still goes through the channel's servers.
Related: Agent workspace, Memory.
Where does OpenClaw store its data?
Everything lives under $OPENCLAW_STATE_DIR (default: ~/.openclaw):
| Path | Purpose |
|---|---|
$OPENCLAW_STATE_DIR/openclaw.json | Main config (JSON5) |
$OPENCLAW_STATE_DIR/credentials/oauth.json | Legacy OAuth import (copied into auth profiles on first use) |
$OPENCLAW_STATE_DIR/agents/<agentId>/agent/auth-profiles.json | Auth profiles (OAuth, API keys, optional keyRef/tokenRef) |
$OPENCLAW_STATE_DIR/secrets.json | Optional file-backed secret payload for file SecretRef providers |
$OPENCLAW_STATE_DIR/agents/<agentId>/agent/auth.json | Legacy compatibility file (static api_key entries scrubbed) |
$OPENCLAW_STATE_DIR/credentials/ | Provider state (for example whatsapp/<accountId>/creds.json) |
$OPENCLAW_STATE_DIR/agents/ | Per-agent state (agentDir + legacy/archive session artifacts) |
$OPENCLAW_STATE_DIR/agents/<agentId>/agent/openclaw-agent.sqlite | Per-agent SQLite state, including session rows and transcripts |
$OPENCLAW_STATE_DIR/agents/<agentId>/sessions/ | Legacy session migration sources and archive/support artifacts |
Legacy single-agent path ~/.openclaw/agent/* is migrated by openclaw doctor.
Your workspace (AGENTS.md, memory files, skills, etc.) is separate, configured via agents.defaults.workspace (default: ~/.openclaw/workspace).
Where should AGENTS.md / SOUL.md / USER.md / MEMORY.md live?
These live in the agent workspace, not ~/.openclaw.
- Workspace (per agent):
AGENTS.md,SOUL.md,IDENTITY.md,USER.md,MEMORY.md,memory/YYYY-MM-DD.md. Lowercase rootmemory.mdis legacy repair input only;openclaw doctor --fixcan merge it intoMEMORY.mdwhen both exist. - State dir (
~/.openclaw): config, channel/provider state, auth profiles, sessions, logs, shared skills (~/.openclaw/skills).
Default workspace is ~/.openclaw/workspace, configurable:
{
agents: { defaults: { workspace: "~/.openclaw/workspace" } },
}
If the bot "forgets" after a restart, confirm the Gateway uses the same workspace on every launch (remote mode uses the gateway host's workspace, not your local laptop).
Tip: for durable behavior or preference, ask the bot to write it into AGENTS.md or MEMORY.md rather than relying on chat history.
See Agent workspace and Memory.
Can I make SOUL.md bigger?
Yes. SOUL.md is one of the workspace bootstrap files injected into agent context. Default per-file injection limit is 20000 characters; total bootstrap budget across files is 60000 characters.
Change shared defaults:
{
agents: {
defaults: {
bootstrapMaxChars: 50000,
bootstrapTotalMaxChars: 300000,
},
},
}
Or override one agent under agents.entries.*.bootstrapMaxChars / bootstrapTotalMaxChars.
Use /context to check raw vs injected sizes and whether truncation happened. Keep SOUL.md focused on voice, stance, and personality; put operating rules in AGENTS.md and durable facts in memory.
See Context and Agent config.
Recommended backup strategy
Keep your agent workspace inside a private git repository and store a copy somewhere secure, such as a private GitHub repo. Doing so preserves memory along with the AGENTS/SOUL/USER files, allowing you to recover the assistant's "mind" at a later point.
Avoid committing anything located under ~/.openclaw (credentials, sessions, tokens, encrypted secrets payloads). To perform a complete restore, maintain separate backups of both the workspace and the state directory.
Documentation: Agent workspace.
How do I completely uninstall OpenClaw?
Refer to Uninstall for details.
Can agents work outside the workspace?
That is correct. The workspace acts as the default cwd and memory anchor, but it is not a strict sandbox. Relative paths are resolved within the workspace, while absolute paths can reach other host locations unless sandboxing is turned on. For isolation, use agents.defaults.sandbox or configure per-agent sandbox options. To make a repo the default working directory, set that agent's workspace to the repo root. The OpenClaw repo itself is merely source code, so keep the workspace separate unless you deliberately want the agent operating inside it.
{
agents: {
defaults: {
workspace: "~/Projects/my-repo",
},
},
}
Remote mode: where is the session store?
Session state resides on the gateway host. In remote mode, the session store you need is located on the remote machine, not on your local laptop. Check Session management for more.
Config basics
What format is the config? Where is it?
OpenClaw loads an optional JSON5 configuration from $OPENCLAW_CONFIG_PATH (defaulting to ~/.openclaw/openclaw.json). When that file is absent, it falls back to reasonably safe defaults, which include a default workspace of ~/.openclaw/workspace.
I set gateway.bind: "lan" (or "tailnet") and now nothing listens / the UI says unauthorized
Non-loopback binds demand a valid gateway auth path: either shared-secret auth (token or password), or gateway.auth.mode: "trusted-proxy" placed behind a properly configured identity-aware reverse proxy.
{
gateway: {
bind: "lan",
auth: {
mode: "token",
token: "replace-me",
},
},
}
gateway.remote.token/.passwordalone do not activate local gateway auth; local call paths may rely ongateway.remote.*as a fallback only whengateway.auth.*is not set.- For password auth, configure
gateway.auth.mode: "password"together withgateway.auth.password(orOPENCLAW_GATEWAY_PASSWORD). - When
gateway.auth.token/.passwordis explicitly set via SecretRef and cannot be resolved, resolution fails closed (no remote fallback masking). - Shared-secret Control UI setups authenticate using
connect.params.auth.tokenorconnect.params.auth.password(kept in app/UI settings). Identity-bearing modes like Tailscale Serve ortrusted-proxydepend on request headers, so never place shared secrets in URLs. - With
gateway.auth.mode: "trusted-proxy", same-host loopback reverse proxies require explicitgateway.auth.trustedProxy.allowLoopback = trueand a loopback entry ingateway.trustedProxies.
Why do I need a token on localhost now?
Gateway auth is enforced by default, covering loopback as well. When no explicit auth path is configured, startup defaults to token mode and creates a runtime-only token for that startup, meaning local WS clients must authenticate. This prevents other local processes from reaching the Gateway.
On a fresh loopback start, the Gateway prepares the canonical same-user CLI device credential before /readyz, so standard openclaw CLI calls can authenticate without persisting the generated token. Other clients still require an explicit shared secret or an approved device pairing.
Set gateway.auth.token, gateway.auth.password, OPENCLAW_GATEWAY_TOKEN, or OPENCLAW_GATEWAY_PASSWORD explicitly when clients need a stable secret across restarts. Password mode is another option, as is trusted-proxy for identity-aware reverse proxies. For open loopback, set gateway.auth.mode: "none" explicitly. openclaw doctor --generate-gateway-token produces a token on every occasion.
Do I have to restart after changing config?
The Gateway monitors the config and supports hot-reload: gateway.reload.mode: "hybrid" (the default) hot-applies safe changes and restarts for critical ones. off turns off config reload; the older hot and restart modes have been retired. Most tools.*, agents.* policy, session.*, and messages.* changes take effect immediately without any reload action; gateway.* binding/port changes require a restart.
How do I enable web search (and web fetch)?
web_fetch functions without an API key. web_search varies based on the provider you choose:
| Provider | Key-free | Env var(s) |
|---|---|---|
| Brave | No | BRAVE_API_KEY |
| DuckDuckGo | Yes (unofficial HTML-based) | - |
| Exa | No | EXA_API_KEY |
| Firecrawl | No | FIRECRAWL_API_KEY |
| Gemini | No | GEMINI_API_KEY |
| Grok | No (xAI OAuth or key) | XAI_API_KEY |
| Kimi | No | KIMI_API_KEY or MOONSHOT_API_KEY |
| MiniMax Search | No | MINIMAX_CODE_PLAN_KEY, MINIMAX_CODING_API_KEY, or MINIMAX_API_KEY |
| Ollama Web Search | Yes (needs ollama signin) | - |
| Perplexity | No | PERPLEXITY_API_KEY or OPENROUTER_API_KEY |
| SearXNG | Yes (self-hosted) | SEARXNG_BASE_URL |
| Tavily | No | TAVILY_API_KEY |
Grok may also draw on xAI OAuth from model authentication via openclaw onboard --auth-choice xai-oauth.
Recommended: openclaw configure --section web, then choose a provider.
{
plugins: {
entries: {
brave: {
config: {
webSearch: {
apiKey: "BRAVE_API_KEY_HERE",
},
},
},
},
},
tools: {
web: {
search: {
enabled: true,
provider: "brave",
maxResults: 5,
},
fetch: {
enabled: true,
provider: "firecrawl", // optional; omit for auto-detect
},
},
},
}
Provider-specific web-search configuration is located under plugins.entries.<plugin>.config.webSearch.*. Older tools.web.search.* provider paths are still loaded for backward compatibility, though new configs should avoid them. Firecrawl's web-fetch fallback settings sit under plugins.entries.firecrawl.config.webFetch.*.
- Allowlists: include
web_search/web_fetch/x_search, orgroup:webto cover all three. web_fetchcomes activated by default.- When
tools.web.fetch.provideris absent, OpenClaw picks the first ready fetch fallback provider from available credentials on its own; the official Firecrawl plugin supplies that fallback. - Daemons pull env vars from
~/.openclaw/.env(or the service environment).
Docs: Web tools.
config.apply wiped my config. How do I recover and avoid this?
config.apply swaps out the entire config; a partial object wipes out everything else.
Current OpenClaw guards against most accidental clobbers:
- OpenClaw-owned config writes validate the full post-change config before writing.
- Invalid or destructive OpenClaw-owned writes are rejected and saved as
openclaw.json.rejected.*. - A direct edit that breaks startup or hot reload makes the Gateway fail closed or skip the reload; it does not rewrite
openclaw.json. openclaw doctor --fixowns repair, can restore last-known-good, and saves the rejected file asopenclaw.json.clobbered.*.
Recover:
- Check
openclaw logs --followforInvalid config at,Config write rejected:, orconfig reload skipped (invalid config). - Inspect the newest
openclaw.json.clobbered.*oropenclaw.json.rejected.*beside the active config. - Run
openclaw config validateandopenclaw doctor --fix. - Copy only the intended keys back with
openclaw config setorconfig.patch. - No last-known-good or rejected payload: restore from backup, or re-run
openclaw doctorand reconfigure channels/models. - Unexpected loss: file a bug with your last known config or a backup. A local coding agent can often reconstruct a working config from logs or history.
Avoid it: use openclaw config set for small changes, openclaw configure for interactive edits, config.schema.lookup to inspect an unfamiliar path (returns a shallow schema node plus immediate child summaries), and config.patch for partial RPC edits - reserve config.apply for full-config replacement. The agent-facing gateway runtime tool refuses to rewrite tools.exec.ask / tools.exec.security even via legacy tools.bash.* aliases.
Docs: Config, Configure, Gateway troubleshooting, Doctor.
How do I run a central Gateway with specialized workers across devices?
A typical deployment uses one Gateway (a Raspberry Pi works well) plus nodes and agents.
- Gateway (central): manages channels (Signal/WhatsApp), routing, and sessions.
- Nodes (devices): Macs/iOS/Android attach as peripherals and expose local tools like
system.runandcamera; Macs can also show hosted widgets in the native panel. - Agents (workers): dedicated brains/workspaces for specific roles (for instance, ops versus personal data).
- Sub-agents: launch background tasks from a main agent to run in parallel.
- TUI: attaches to the Gateway and lets you switch between agents and sessions.
See the docs: Nodes, Remote access, Multi-Agent Routing, Sub-agents, TUI.
Can the OpenClaw browser run headless?
It does:
{
browser: { headless: true },
agents: {
defaults: {
sandbox: { browser: { headless: true } },
},
},
}
The default is false (headful). Going headless raises the odds of anti-bot detection on certain sites (X/Twitter frequently blocks headless sessions). It relies on the same Chromium engine and handles most automation fine; the only real difference is the absence of a visible browser window (capture screenshots for visuals). Refer to Browser.
How do I use Brave for browser control?
Point browser.executablePath at your Brave binary (or any Chromium-based browser), then restart the Gateway. Details are in Browser.
Remote gateways and nodes
How do commands propagate between Telegram, the gateway, and nodes?
The gateway processes Telegram messages: it runs the agent first, then reaches out to nodes over the Gateway WebSocket only when a node tool is required:
Telegram -> Gateway -> Agent -> node.* -> Node -> Gateway -> Telegram
Nodes never see inbound provider traffic; they receive only node RPC calls.
How can my agent access my computer if the Gateway is hosted remotely?
Set up your computer as a node. The Gateway can live elsewhere yet still invoke node.* tools (screen, camera, system) on your local machine through the Gateway WebSocket.
- Start the Gateway on the always-on host (VPS/home server).
- Put the Gateway host and your computer on the same tailnet.
- Make sure the Gateway WS is reachable (tailnet bind or SSH tunnel).
- Open the macOS app locally and connect in Remote over SSH mode (or direct tailnet) so it registers as a node.
- Approve the node:
openclaw devices list openclaw devices approve <requestId>
There is no need for a separate TCP bridge; nodes connect over the Gateway WebSocket.
Security note: pairing a macOS node grants system.run on that machine. Pair only devices you trust; check Security.
Docs: Nodes, Gateway protocol, macOS remote mode, Security.
Tailscale is connected but I get no replies. What now?
Start with the basics:
openclaw gateway status
openclaw status
openclaw channels status
Next, verify auth and routing: with Tailscale Serve, ensure gateway.auth.allowTailscale is configured correctly; with an SSH tunnel, confirm the tunnel is active and aimed at the right port; and check that your DM/group allowlists include your account.
Docs: Tailscale, Remote access, Channels.
Can two OpenClaw instances talk to each other (local + VPS)?
Yes, but there is no built-in bot-to-bot bridge.
Simplest: use a regular chat channel both bots can reach (Slack/Telegram/WhatsApp). Have Bot A message Bot B, then let Bot B respond normally.
CLI bridge (generic): run a script that calls the other Gateway with openclaw agent --message ... --deliver, aimed at a chat where the other bot listens. If one bot sits on a remote VPS, point your CLI at that remote Gateway via SSH/Tailscale (see Remote access):
openclaw agent --message "Hello from local bot" --deliver --channel telegram --reply-to <chat-id>
Add a guardrail so the two bots do not loop endlessly (mention-only, channel allowlists, or a "do not reply to bot messages" rule).
Docs: Remote access, Agent CLI, Agent send.
Do I need separate VPSes for multiple agents?
No. A single Gateway can host multiple agents, each with its own workspace, model defaults, and routing; this is the standard setup and is far cheaper and simpler than one VPS per agent. Reserve separate VPSes for hard isolation (security boundaries) or for configs so different you do not want to share them.
Is there a benefit to using a node on my personal laptop instead of SSH from a VPS?
Yes: nodes are the primary way to reach your laptop from a remote Gateway and give you more than just shell access. The Gateway runs on macOS/Linux (Windows via WSL2) and is light (a small VPS or Raspberry Pi-class box suffices; 4 GB RAM is plenty), so a typical arrangement is an always-on host plus your laptop as a node.
- No inbound SSH required - nodes connect out to the Gateway WebSocket via device pairing.
- Safer execution controls -
system.runis gated by node allowlists/approvals on that laptop. - More device tools - nodes expose
cameraandscreenin addition tosystem.run; Macs also expose the widget panel. - Local browser automation - keep the Gateway on a VPS but run Chrome locally through a node host, or attach to local Chrome via Chrome MCP.
SSH works for ad-hoc shell access; nodes are better for ongoing agent workflows and device automation.
Docs: Nodes, Nodes CLI, Browser.
Do nodes run a gateway service?
No. Only one gateway should run per host unless you deliberately run isolated profiles (see Multiple gateways). Nodes are peripherals that connect to the gateway (iOS/Android nodes, or macOS "node mode" in the menubar app). For headless node hosts and CLI control, see Node host CLI.
A full restart is required for gateway, discovery, and hosted plugin surface changes.
Is there an API / RPC way to apply config?
Yes:
config.schema.lookup: examine a single configuration subtree, including its shallow schema node, associated UI hint, and direct child summaries, prior to committing changes.config.get: retrieve the present snapshot along with its hash.config.patch: perform a secure partial update, the recommended approach for most RPC edits; triggers hot-reload when feasible, otherwise restarts.config.apply: validate then swap in the entire configuration; hot-reloads if possible, restarts if not.- The agent-side
gatewayruntime tool remains unable to modifytools.exec.askortools.exec.security; oldertools.bash.*aliases are normalized to those same protected paths.
Minimal sane config for a first install
{
agents: { defaults: { workspace: "~/.openclaw/workspace" } },
channels: { whatsapp: { allowFrom: ["+15555550123"] } },
}
Defines your workspace and limits who can activate the bot.
How do I set up Tailscale on a VPS and connect from my Mac?
- Set up and authenticate on the VPS:
curl -fsSL https://tailscale.com/install.sh | sh sudo tailscale up - Set up and authenticate on your Mac via the Tailscale application, joining the same tailnet.
- Turn on MagicDNS in the Tailscale admin panel so the VPS gets a fixed name.
- Connect using the tailnet hostname: SSH to
ssh user@your-vps.tailnet-xxxx.ts.net; Gateway WS atws://your-vps.tailnet-xxxx.ts.net:18789.
To use the Control UI without SSH, run Tailscale Serve on the VPS:
openclaw gateway --tailscale serve
This binds the gateway to loopback while Tailscale provides HTTPS access. Refer to Tailscale.
How do I connect a Mac node to a remote Gateway (Tailscale Serve)?
Serve makes available the Gateway Control UI + WS; nodes connect through that same Gateway WS endpoint.
- Confirm the VPS and Mac share a tailnet.
- Launch the macOS app in Remote mode, where the SSH target can be the tailnet hostname; this tunnels the Gateway port and attaches as a node.
- Authorize the node:
openclaw devices list openclaw devices approve <requestId>
Documentation: Gateway protocol, Discovery, macOS remote mode.
Should I install on a second laptop or just add a node?
When only local tools (screen, camera, exec) are needed on the second laptop, register it as a node, keeping one Gateway and avoiding duplicated config. Local node tools currently support macOS only. Deploy a second Gateway solely for hard isolation or two fully independent bots.
Docs: Nodes, Nodes CLI, Multiple gateways.
Env vars and .env loading
How does OpenClaw load environment variables?
OpenClaw picks up environment variables from the parent process, such as shell, launchd, systemd, or CI, and additionally sources:
.envlocated in the current working directory.- a system-wide fallback
.envfrom~/.openclaw/.env($OPENCLAW_STATE_DIR/.env).
In typical cases, neither .env file supersedes existing environment variables. For an OpenClaw-installed systemd service, the global .env may overwrite only service values that OpenClaw tracks as managed; operator-defined service values still win. Provider credentials and endpoint-routing keys break this rule for workspace .env: entries like GEMINI_API_KEY, XAI_API_KEY, MISTRAL_API_KEY, or any key ending in _ENDPOINT (plus other bundled-provider auth or endpoint env vars) are skipped from workspace .env and belong in the process environment, ~/.openclaw/.env, or config env.vars.
Inline environment variables in config take effect only when absent from the process env:
{
env: {
vars: {
OPENROUTER_API_KEY: "sk-or-...",
GROQ_API_KEY: "gsk-...",
},
},
}
Check /environment for the complete precedence order and sources.
I started the Gateway via the service and my env vars disappeared. What now?
Two remedies:
- Add the absent keys to
~/.openclaw/.envso they load even when the service fails to inherit your shell env. - Turn on shell import, an opt-in convenience:
This executes your login shell and imports only missing expected keys, never overriding existing ones. Equivalent env vars:{ env: { shellEnv: { enabled: true, timeoutMs: 15000, }, }, }OPENCLAW_LOAD_SHELL_ENV=1,OPENCLAW_SHELL_ENV_TIMEOUT_MS=15000.
I set COPILOT_GITHUB_TOKEN, but models status shows "Shell env: off." Why?
openclaw models status indicates whether shell env import is active. Seeing "Shell env: off" does not signal missing env vars; it simply means OpenClaw will not automatically load your login shell.
When the Gateway operates as a service under launchd or systemd, your shell environment is not inherited. Address this by placing the token in ~/.openclaw/.env, activating env.shellEnv.enabled: true, or adding it to config env (effective only if absent), then restart the gateway and verify again:
openclaw models status
Copilot tokens resolve in this sequence: OPENCLAW_GITHUB_TOKEN, followed by COPILOT_GITHUB_TOKEN, then GH_TOKEN, and finally GITHUB_TOKEN.
See /concepts/model-providers and /environment.
Sessions and multiple chats
How do I start a fresh conversation?
Deliver /new or /reset as its own message. Refer to Session management for details.
Do sessions reset automatically if I never send /new?
By default, no. Sessions retain the same sessionId, and compaction keeps the active model context within limits as conversations expand. /new and /reset stay accessible, or you can enable automatic resets through mode: "daily" or mode: "idle". Daily mode rolls over at session.reset.atHour (default 4, 0-23) on the gateway host; idle mode relies on session.reset.idleMinutes measured from the last genuine interaction, not heartbeat/cron/exec system events.
{
session: {
reset: { mode: "daily", atHour: 4 },
resetByType: {
group: { mode: "idle", idleMinutes: 120 },
thread: { mode: "daily", atHour: 6 },
},
resetByChannel: {
discord: { mode: "idle", idleMinutes: 10080 },
},
},
}
resetByType accommodates direct, group, and thread. Doctor converts legacy dm entries into direct; the schema rejects dm. Legacy top-level session.idleMinutes continues to function as a compatibility alias for an idle-mode default when no session.reset/resetByType block is present. The complete lifecycle is covered in Session management.
Is there a way to make a team of OpenClaw instances (one CEO and many agents)?
Yes, through multi-agent routing and sub-agents: a single coordinator agent paired with several worker agents, each having its own workspace and model.
Treat this as an exploratory exercise: it consumes many tokens and is frequently less efficient than a single bot using separate sessions. The standard approach is one bot you converse with, leveraging different sessions for parallel tasks and spawning sub-agents only when necessary.
Documentation: Multi-agent routing, Sub-agents, Agents CLI.
Why did context get truncated mid-task? How do I prevent it?
The model window determines session context limits. Lengthy conversations, substantial tool outputs, or numerous files may lead to compaction or truncation.
- Request a summary of the current state from the bot and save it to a file.
- Run
/compactbefore extended tasks,/newwhen changing topics. - Store essential context in the workspace and have the bot retrieve it.
- Offload long or parallel work to sub-agents so the main chat remains compact.
- Choose a model with a broader context window if this occurs regularly.
How do I completely reset OpenClaw but keep it installed?
openclaw reset
Non-interactive full reset:
openclaw reset --scope full --yes --non-interactive
Then re-run setup:
openclaw onboard --install-daemon
To reset and immediately trigger onboarding, supply openclaw onboard --reset; reset acts as a command flag, not a Setup mode menu option. See Onboarding (CLI). With profiles (--profile / OPENCLAW_PROFILE), reset each state dir (default ~/.openclaw-<profile>). Dev-only reset: openclaw gateway --dev --reset clears dev config, credentials, sessions, and workspace.
I am getting "context too large" errors - how do I reset or compact?
- Compact (retains the conversation, condenses older turns):
/compactor/compact <instructions>to steer the summary. - Reset (new session ID for the same chat key):
/newor/reset.
If this recurs, adjust session pruning (agents.defaults.contextPruning) to cut old tool output, or switch to a model with a larger context window.
Docs: Compaction, Session pruning, Session management.
Why am I seeing "LLM request rejected: messages.content.tool_use.input field required"?
Provider validation failure: the model produced a tool_use block lacking the required input. This typically points to stale or corrupted session history, often after long threads or a tool/schema change.
Remedy: begin a new session with /new (standalone message).
Why am I getting heartbeat messages every 30 minutes?
Heartbeats fire every 30m by default, or 1h when the resolved auth mode is Anthropic OAuth/token auth (including Claude CLI reuse) and heartbeat.every is not set. Adjust or disable:
{
agents: {
defaults: {
heartbeat: {
every: "2h", // or "0m" to disable recurring cadence
},
},
},
}
Heartbeat instructions reside in the monitor's cron scratch. When scratch is effectively empty, the heartbeat run is skipped to conserve API calls; without scratch, the heartbeat still executes and the model chooses its action. 0m does not prevent targeted event-driven wakes, such as a follow-up to a background exec completion; those can still run one agent turn without enabling recurring cadence.
Per-agent overrides rely on agents.entries.*.heartbeat. Reference: Heartbeat.
Do I need to add a "bot account" to a WhatsApp group?
Not at all. OpenClaw operates under your own account, so anything visible to you in the group is visible to it. Group replies stay blocked by default until you grant permission to senders (groupPolicy: "allowlist").
To limit group replies to just yourself:
{
channels: {
whatsapp: {
groupPolicy: "allowlist",
groupAllowFrom: ["+15551234567"],
},
},
}
How do I get the JID of a WhatsApp group?
The quickest route: watch the logs and post a test message in the group.
openclaw logs --follow --json
Watch for chatId (alternatively from) that concludes with @g.us, for example 1234567890-1234567890@g.us.
When configuration or allowlisting is already in place, pull the group list from config:
openclaw directory groups list --channel whatsapp
Docs: WhatsApp, Directory, Logs.
Why does OpenClaw not reply in a group?
Two usual culprits: mention gating is enabled by default, so you have to @mention the bot or satisfy mentionPatterns, or you set up channels.whatsapp.groups without "*" and the group isn't on the allowlist.
Check Groups and Group messages for details.
Do groups/threads share context with DMs?
By default, direct messages fold into the main session. Groups and channels get separate session keys unless a route binding assigns session.groupScope: "main" to combine that room with the main session; Telegram topics and Discord threads each get their own session. See Groups and Group messages.
How many workspaces and agents can I create?
There are no strict caps, dozens or even hundreds work, but keep these in mind:
- Disk growth: each agent's SQLite database holds active sessions and transcripts; legacy and archive artifacts can pile up under
~/.openclaw/agents/<agentId>/sessions/. - Token cost: model usage scales with the number of concurrent agents.
- Ops overhead: auth profiles, workspaces, and channel routing per agent.
Maintain one active workspace per agent (agents.defaults.workspace), clear old sessions with openclaw sessions cleanup when disk space tightens (never hand-edit live SQLite state), and rely on openclaw doctor to catch stray workspaces and profile mismatches.
Can I run multiple bots or chats at the same time (Slack), and how should I set that up?
Absolutely, through Multi-Agent Routing: spin up several isolated agents and direct inbound messages by channel, account, or peer. Slack works as a channel and can be tied to specific agents.
Browser access is capable but not unlimited, anti-bot measures, CAPTCHAs, and MFA can still stop automation. For maximum control, go with local Chrome MCP on the host, or CDP on the machine that actually runs the browser.
Recommended layout: a permanently running Gateway host (VPS or Mac mini), one agent per role via bindings, Slack channel(s) attached to those agents, and a local browser through Chrome MCP or a node when necessary.
Docs: Multi-Agent Routing, Slack, Browser, Nodes.
Models, failover, and auth profiles
Model-related questions, defaults, selection, aliases, switching, failover, and auth profiles, are covered on the Models FAQ.
Gateway: ports, "already running", and remote mode
What port does the Gateway use?
gateway.port governs the single multiplexed port shared by WebSocket and HTTP (Control UI, hooks, and more). Priority order:
--port > OPENCLAW_GATEWAY_PORT > gateway.port > default 18789
Why does openclaw gateway status say "Runtime: running" but "Connectivity probe: failed"?
"Running" reflects the supervisor's perspective (launchd, systemd, or schtasks); the connectivity probe is the CLI actually reaching the gateway WebSocket. Rely on these lines from openclaw gateway status: Probe target: (the URL used by the probe), Listening: (what is genuinely bound on the port), and Last gateway error: (the usual culprit when the process is alive but the port isn't listening).
Why does openclaw gateway status show "Config (cli)" and "Config (service)" different?
You're modifying one config file while the service executes another, often a --profile / OPENCLAW_STATE_DIR mismatch.
To fix it, execute from the same --profile or environment the service should use:
openclaw gateway install --force
What does "another gateway instance is already listening" mean?
OpenClaw enforces a runtime lock by binding the WebSocket listener right at startup (default ws://127.0.0.1:18789). A failed bind with EADDRINUSE triggers GatewayLockError ("another gateway instance is already listening").
Remedy: halt the other instance, release the port, or start with openclaw gateway --port <port>.
How do I run OpenClaw in remote mode (client connects to a Gateway elsewhere)?
Set gateway.mode: "remote" and target a remote WebSocket URL, optionally with shared-secret remote credentials:
{
gateway: {
mode: "remote",
remote: {
url: "ws://gateway.tailnet:18789",
token: "your-token",
password: "your-password",
},
},
}
openclaw gatewaybecomes active only whengateway.modeis set tolocal, unless you supply an override flag.- On macOS, the app monitors the config file and toggles modes in real time whenever those values shift.
gateway.remote.tokenand.passwordserve purely as client-side remote credentials; they don't independently activate local gateway authentication.
The Control UI says "unauthorized" (or keeps reconnecting). What now?
The authentication method used by your gateway path differs from what the UI expects.
Details from the source code:
- The Control UI stores the token in
sessionStorage, tied to the active browser tab and the chosen gateway URL. This keeps same-tab refreshes functional without persisting the token in localStorage over the long term. - When running on
AUTH_TOKEN_MISMATCH, trusted clients get a single bounded retry using a cached device token if the gateway signals retry hints (canRetryWithDeviceToken=true,recommendedNextStep=retry_with_device_token). - That retry with the cached token reuses the approved scopes saved alongside the device token. Callers who explicitly pass
deviceTokenorscopesretain their own requested scope set, rather than adopting the cached scopes. - Outside that retry scenario, connect auth follows this order: explicit shared token or password first, then explicit
deviceToken, followed by the stored device token, and finally the bootstrap token. - The built-in setup-code bootstrap hands out a node device token with
scopes: []plus a limited operator handoff token meant for trusted mobile onboarding. That operator handoff can access setup-time native configuration, but it lacks pairing mutation scopes andoperator.admin.
Remedies:
- Quickest option: run
openclaw dashboard(it prints and copies the dashboard URL, attempts to open it, and displays an SSH hint when no display is available). - If you have no token yet: use
openclaw doctor --generate-gateway-token. - For remote access: establish a tunnel with
ssh -N -L 18789:127.0.0.1:18789 user@hostfirst, then openhttp://127.0.0.1:18789/. - In shared-secret mode: configure
gateway.auth.tokenorOPENCLAW_GATEWAY_TOKEN, alternativelygateway.auth.passwordorOPENCLAW_GATEWAY_PASSWORD, then paste the matching secret into the Control UI settings. - With Tailscale Serve: verify that
gateway.auth.allowTailscaleis turned on and that you're hitting the Serve URL, not a raw loopback or tailnet address that skips Tailscale identity headers. - In trusted-proxy mode: make sure you're arriving through the identity-aware proxy you configured. Loopback proxies on the same host also require
gateway.auth.trustedProxy.allowLoopback = true. - If the mismatch lingers after the single retry, rotate or re-approve the paired device token:
openclaw devices list openclaw devices rotate --device <id> --role operator - When rotation is denied: paired-device sessions can only rotate their own device unless they hold
operator.adminas well, and explicit--scopevalues must stay within the caller's current operator scopes. - Still unresolved: check
openclaw status --alland the Troubleshooting guide. For auth specifics, see Dashboard.
I set gateway.bind tailnet but it listens only on loopback
The tailnet bind selects a Tailscale IP from your network interfaces, specifically within 100.64.0.0/10. If Tailscale isn't running on the machine, or its interface is down, the Gateway falls back to loopback rather than exposing a different network interface.
Fix: start Tailscale on that host and restart the Gateway, or explicitly switch to gateway.bind: "loopback" or "lan".
tailnet is explicit by design; auto leans toward loopback. To keep non-loopback exposure limited to the Tailnet while preserving the required same-host 127.0.0.1 listener, apply gateway.bind: "tailnet".
Can I run multiple Gateways on the same host?
Typically not: a single Gateway can host multiple messaging channels and agents. Deploy additional Gateways only for redundancy (like a rescue bot) or strict isolation, and give each one its own OPENCLAW_CONFIG_PATH, OPENCLAW_STATE_DIR, agents.defaults.workspace, and a distinct gateway.port.
Best practice: use openclaw --profile <name> ... per instance (which auto-generates ~/.openclaw-<name>), a unique gateway.port for each profile config (or --port for manual runs), and a per-profile service with openclaw --profile <name> gateway install.
Profiles also append their names to service names: launchd uses ai.openclaw.<profile>, systemd uses openclaw-gateway-<profile>.service, and Windows uses OpenClaw Gateway (<profile>). The unqualified openclaw-gateway systemd unit exists only for the default profile; the older pre-rename unit name clawdbot-gateway gets migrated automatically.
Full instructions: Multiple gateways.
What does "invalid handshake" / code 1008 mean?
The Gateway acts as a WebSocket server and requires the initial message to be a connect frame. Any other message type causes the connection to close with code 1008 (policy violation).
Typical triggers: opening the HTTP URL in a browser instead of a WS client, hitting the wrong port or path, or having a proxy or tunnel strip auth headers or forward a non-Gateway request.
Fix: connect using the WS URL (ws://<host>:18789, or wss://... for HTTPS), avoid opening the WS port in a regular browser tab, and when auth is enabled, place the token or password inside the connect frame. CLI/TUI example:
openclaw tui --url ws://<host>:18789 --token <token>
Protocol reference: Gateway protocol.
Logging and debugging
Where are logs?
Structured file logs: /tmp/openclaw/openclaw-YYYY-MM-DD.log applies to the default profile, while /tmp/openclaw/openclaw-<profile>-YYYY-MM-DD.log is used for a named profile. A persistent location can be assigned with logging.file; the file log level is controlled by logging.level; console output detail is set through --verbose and logging.consoleLevel.
Quickest way to tail:
openclaw logs --follow
Service or supervisor logs, when the gateway is managed by launchd or systemd:
- macOS launchd stdout:
~/Library/Logs/openclaw/gateway.log(profiles rely ongateway-<profile>.log; stderr is not captured). - Linux:
journalctl --user -u openclaw-gateway[-<profile>].service -n 200 --no-pager. - Windows:
schtasks /Query /TN "OpenClaw Gateway (<profile>)" /V /FO LIST.
Additional guidance is in Troubleshooting.
How do I start/stop/restart the Gateway service?
openclaw gateway status
openclaw gateway restart
For manual gateway execution, openclaw gateway --force can free up the port. Refer to Gateway.
I closed my terminal on Windows - how do I restart OpenClaw?
Three ways to install on Windows:
1) Windows Hub local setup: the native app handles a local app-owned WSL Gateway. Launch OpenClaw Companion from the Start menu or system tray, then navigate to Gateway Setup or the Connections tab.
2) Manual WSL2 Gateway: the Gateway operates inside Linux.
wsl
openclaw gateway status
openclaw gateway restart
When the service was never installed, run it in the foreground with: openclaw gateway run.
3) Native Windows CLI/Gateway: executes directly in Windows.
openclaw gateway status
openclaw gateway restart
For manual execution without a service: openclaw gateway run.
Documentation: Windows, Gateway service runbook.
The Gateway is up but replies never arrive. What should I check?
Rapid health check:
openclaw status
openclaw models status
openclaw channels status
openclaw logs --follow
Typical culprits: model authentication not loaded on the gateway host (verify with models status), channel pairing or allowlist blocking replies (inspect channel configuration and logs), or WebChat/Dashboard open without the proper token. For remote setups, verify the tunnel or Tailscale connection is active and the Gateway WebSocket is reachable.
Documentation: Channels, Troubleshooting, Remote access.
"Disconnected from gateway: no reason" - what now?
This typically signals that the UI lost its WebSocket connection. Investigate: is the Gateway running (openclaw gateway status)? Is it healthy (openclaw status)? Does the UI hold the correct token (openclaw dashboard)? For remote access, is the tunnel or Tailscale link active?
Then follow the logs:
openclaw logs --follow
Documentation: Dashboard, Remote access, Troubleshooting.
Telegram setMyCommands fails. What should I check?
openclaw channels status
openclaw channels logs --channel telegram
Then align the error with the cause:
BOT_COMMANDS_TOO_MUCH: the Telegram menu contains too many entries. OpenClaw already reduces the list to the Telegram limit and retries with fewer commands, yet some menu items might still be omitted. Cut down on plugin, skill, or custom commands, or turn offchannels.telegram.commands.nativeif the menu is unnecessary.TypeError: fetch failed,Network request for 'setMyCommands' failed!, or comparable network errors: on a VPS or behind a proxy, ensure outbound HTTPS is permitted and DNS resolves forapi.telegram.org.
When the Gateway is remote, examine the logs on the Gateway host.
Documentation: Telegram, Channel troubleshooting.
TUI shows no output. What should I check?
openclaw status
openclaw models status
openclaw logs --follow
Inside the TUI, /status displays the current state. To receive replies in a chat channel, verify that delivery is enabled (/deliver on).
Documentation: TUI, Slash commands.
How do I completely stop then start the Gateway?
With the service installed (launchd on macOS, systemd on Linux):
openclaw gateway stop
openclaw gateway start
In the foreground, press Ctrl-C to stop, then run openclaw gateway run.
Documentation: Gateway service runbook.
ELI5: openclaw gateway restart vs openclaw gateway
openclaw gateway restart restarts the background service (launchd/systemd). openclaw gateway launches the gateway in the foreground for this terminal session. If you installed the service, rely on the gateway subcommands; for a one-off run, use the bare foreground command.
Fastest way to get more details when something fails
To get more console output, start the Gateway with --verbose, then check the log file for channel auth, model routing, and RPC errors.
Media and attachments
My skill generated an image/PDF, but nothing was sent
Outbound attachments from the agent must use structured media fields such as media, mediaUrl, path, or filePath. See OpenClaw assistant setup and Agent send.
openclaw message send --target +15555550123 --message "Here you go" --media /path/to/file.png
Also verify: the target channel supports outbound media and is not blocked by allowlists; the file is within the provider's size limits (images resize to a max side of 2048px); tools.fs.workspaceOnly=true limits local-path sends to workspace, temp/media-store, and sandbox-validated files; tools.fs.workspaceOnly=false (default) lets structured local media sends use host-local files the agent can already read, for media plus safe document types (images, audio, video, PDF, Office docs, and validated text documents such as Markdown/MD, TXT, JSON, YAML/YML). This is not a secret scanner - an agent-readable secret.txt or config.json can be attached when the extension and content validation match. Keep sensitive files outside agent-readable paths, or keep tools.fs.workspaceOnly=true for stricter local-path sends.
See Images.
Security and access control
Is it safe to expose OpenClaw to inbound DMs?
Treat inbound DMs as untrusted input. Defaults reduce risk:
- Default behavior on DM-capable channels is pairing: unknown senders receive a pairing code and their message is not processed. Approve with
openclaw pairing approve --channel <channel> [--account <id>] <code>. Pending requests are capped at 3 per channel; checkopenclaw pairing list --channel <channel> [--account <id>]if a code did not arrive. - Opening DMs publicly requires explicit opt-in (
dmPolicy: "open"and allowlist"*").
Run openclaw doctor to surface risky DM policies.
Is prompt injection only a concern for public bots?
No. Prompt injection is about untrusted content, not just who can DM the bot. If your assistant reads external content (web search/fetch, browser pages, emails, docs, attachments, pasted logs), that content can carry instructions that try to hijack the model - even if you are the only sender.
The biggest risk is when tools are enabled: the model can be tricked into exfiltrating context or calling tools on your behalf. Reduce the blast radius:
- use a read-only or tool-disabled "reader" agent to summarize untrusted content
- keep
web_search/web_fetch/browseroff for tool-enabled agents - treat decoded file/document text as untrusted too: OpenResponses
input_fileand media-attachment extraction both wrap extracted text in explicit external-content boundary markers instead of passing raw file text - sandbox and use strict tool allowlists
Details: Security.
Is OpenClaw less safe because it uses TypeScript/Node instead of Rust/WASM?
Language and runtime matter, but are not the main risk for a personal agent. The practical risks are gateway exposure, who can message the bot, prompt injection, tool scope, credential handling, browser access, exec access, and third-party skill/plugin trust.
Rust and WASM can provide stronger isolation for some code classes, but do not solve prompt injection, bad allowlists, public gateway exposure, overbroad tools, or a browser profile already logged in to sensitive accounts. Treat these as the primary controls: keep the Gateway private or authenticated, use pairing and allowlists for DMs/groups, deny or sandbox risky tools for untrusted inputs, install only trusted plugins and skills, and run openclaw security audit --deep after config changes.
Details: Security, Sandboxing.
I saw reports about exposed OpenClaw instances. What should I check?
openclaw security audit --deep
openclaw gateway status
A safer baseline: Gateway bound to loopback, or exposed only through authenticated private access (tailnet, SSH tunnel, token/password auth, or a correctly configured trusted proxy); DMs in pairing or allowlist mode; groups allowlisted and mention-gated unless every member is trusted; high-risk tools (exec, browser, gateway, cron) denied or tightly scoped for agents that read untrusted content; sandboxing enabled where tool execution needs a smaller blast radius.
Public binds without auth, open DMs/groups with tools, and exposed browser control are the findings to fix first. Details: openclaw security audit.
Are ClawHub skills and third-party plugins safe to install?
Treat third-party skills and plugins as code you are choosing to trust. ClawHub skill pages expose scan state before install, but scans are not a complete security boundary. OpenClaw does not run built-in local dangerous-code blocking during plugin/skill install or update; use operator-owned security.installPolicy for local allow/warn/block decisions.
Safer pattern: prefer trusted authors and pinned versions, read the skill/plugin before enabling it, keep plugin/skill allowlists narrow, run untrusted-input workflows in a sandbox with minimal tools, and avoid giving third-party code broad filesystem, exec, browser, or secret access.
Details: Skills, Plugins, Security.
Should my bot have its own email, GitHub account, or phone number?
Yes, for most setups. Isolating the bot with separate accounts and phone numbers reduces the blast radius if something goes wrong, and makes it easier to rotate credentials or revoke access without impacting your personal accounts.
Start small: give access only to the tools and accounts you actually need, and expand later if required.
Can I give it autonomy over my text messages and is that safe?
We do not recommend full autonomy over your personal messages. Safest pattern: keep DMs in pairing mode or a tight allowlist, use a separate number or account if it should message on your behalf, and let it draft while you approve before sending.
To experiment, do it on a dedicated, isolated account. See Security.
Can I use cheaper models for personal assistant tasks?
Yes, if the agent is chat-only and the input is trusted. Smaller tiers are more susceptible to instruction hijacking, so avoid them for tool-enabled agents or when reading untrusted content. If you must use a smaller model, lock down tools and run inside a sandbox. See Security.
I ran /start in Telegram but did not get a pairing code
Pairing codes are generated exclusively when an unrecognized sender reaches out to the bot and dmPolicy: "pairing" is turned on; /start alone won't trigger a code.
To see what's waiting for approval:
openclaw pairing list telegram
Need access right away? Add your sender id to the allowlist or configure dmPolicy: "open" for that account.
WhatsApp: will it message my contacts? How does pairing work?
No. The standard WhatsApp DM policy defaults to pairing. New senders receive only a pairing code, and their message never gets processed. OpenClaw responds solely to incoming chats it receives or to sends you explicitly initiate.
openclaw pairing approve whatsapp <code>
openclaw pairing list whatsapp
The phone number you enter in the wizard assigns your allowlist/owner status so your own DMs are accepted; it has nothing to do with auto-sending. On your personal WhatsApp number, enter that number and activate channels.whatsapp.selfChatMode.
Chat commands, aborting tasks, and "it will not stop"
How do I stop internal system messages from showing in chat?
Internal and tool-related messages typically surface only when verbose, trace, or reasoning is switched on for that session.
To fix it where it appears:
/verbose off
/trace off
/reasoning off
Still too chatty? Look at the session settings in the Control UI, set verbose to inherit, and double-check that no bot profile with verboseDefault: "on" is in your config.
Docs: Thinking and verbose, Security.
How do I stop/cancel a running task?
To abort, send any of these on its own line (no slash prefix): stop, stop action, stop current action, stop run, stop current run, stop agent, stop the agent, stop openclaw, openclaw stop, stop don't do anything, stop do not do anything, stop doing anything, do not do that, please stop, stop please, abort, esc, exit, interrupt, halt. Triggers in other languages (French, German, Spanish, Chinese, Japanese, Hindi, Arabic, Russian) are recognized too.
For background jobs launched via the exec tool, have the agent execute:
process action:kill sessionId:XXX
Most slash commands need to be sent as a standalone message beginning with /, though a few shortcuts (such as /status) function inline for allowlisted senders. See Slash commands.
How do I send a Discord message from Telegram? ("Cross-context messaging denied")
Cross-provider messaging is disabled by default in OpenClaw. When a tool call is tied to Telegram, it won't reach Discord unless you give explicit permission, and the change applies right away, no gateway restart required:
{
tools: {
message: {
crossContext: {
allowAcrossProviders: true,
marker: { enabled: true, prefix: "[from {channel}] " },
},
},
},
}
Why does it feel like the bot "ignores" rapid-fire messages?
By default, prompts that arrive mid-run are routed into the active run. Use /queue to pick how active-run behavior works:
steer(default) - steer the active run at the next model boundary.followup- hold messages and process them sequentially after the current run wraps up.collect- hold compatible messages and respond once after the current run wraps up.interrupt- cancel the current run and begin anew.
For queued modes, you can add options like debounce:0.5s cap:25 drop:summarize. Check out Command queue and Steering queue.
Miscellaneous
What is the default model for Anthropic with an API key?
Model choice and credentials are handled independently. Setting ANTHROPIC_API_KEY (or placing an Anthropic API key in auth profiles) turns on authentication, but the default model is whatever you define in agents.defaults.model.primary (for instance anthropic/claude-sonnet-4-6 or anthropic/claude-opus-4-6). When you see No credentials found for profile "anthropic:default", it means the Gateway couldn't locate Anthropic credentials in the expected auth-profiles.json for the agent that's running.
Need more help? Reach out on Discord or open a ticket via the GitHub issue chooser.
Related
- Getting started FAQ covers setup, onboarding, login, plans, and initial errors
- Model questions FAQ addresses picking models, fallback behavior, and credential profiles
- Issue resolution guides you through symptom-based diagnosis