# Config basics

> Config format and location, restarts, web search, config.apply recovery, and browser control

- 网址：https://funcoding.ai/agents/openclaw/help/faq/config-basics/
- 来源：OpenClaw 官方文档原文（英文），MIT 许可，同步于 2026-10-11
- 官方原文：https://docs.openclaw.ai/zh-CN/help/faq/config-basics

---
## Config basics

<details>
<summary>What format is the config? Where is it?</summary>

OpenClaw reads an optional **JSON5** config from `$OPENCLAW_CONFIG_PATH` (default: `~/.openclaw/openclaw.json`). If the file is missing, it uses safe-ish defaults, including a default workspace of `~/.openclaw/workspace`.

</details>

<details>
<summary>I set gateway.bind: "lan" (or "tailnet") and now nothing listens / the UI says unauthorized</summary>

Non-loopback binds **require a valid gateway auth path**: shared-secret auth (token or password), or `gateway.auth.mode: "trusted-proxy"` behind a correctly configured identity-aware reverse proxy.

```json5
{
  gateway: {
    bind: "lan",
    auth: {
      mode: "token",
      token: "replace-me",
    },
  },
}
```

- `gateway.remote.token` / `.password` do **not** enable local gateway auth by themselves; local call paths can use `gateway.remote.*` as fallback only when `gateway.auth.*` is unset.
- For password auth, set `gateway.auth.mode: "password"` plus `gateway.auth.password` (or `OPENCLAW_GATEWAY_PASSWORD`).
- If `gateway.auth.token` / `.password` is explicitly configured via SecretRef and unresolved, resolution fails closed (no remote fallback masking).
- Shared-secret Control UI setups authenticate via `connect.params.auth.token` or `connect.params.auth.password` (stored in app/UI settings). Identity-bearing modes such as Tailscale Serve or `trusted-proxy` use request headers instead - avoid putting shared secrets in URLs.
- With `gateway.auth.mode: "trusted-proxy"`, same-host loopback reverse proxies require explicit `gateway.auth.trustedProxy.allowLoopback = true` and a loopback entry in `gateway.trustedProxies`.

</details>

<details>
<summary>Why do I need a token on localhost now?</summary>

OpenClaw enforces gateway auth by default, including loopback. If no explicit auth path is configured, startup resolves to token mode and generates a runtime-only token for that startup, so local WS clients must authenticate. This blocks other local processes from calling the Gateway.

On a fresh loopback start, the Gateway prepares the canonical same-user CLI device credential before `/readyz`, so normal `openclaw` CLI calls can authenticate without persisting the generated token. Other clients still need an explicit shared secret or an approved device pairing.

Configure `gateway.auth.token`, `gateway.auth.password`, `OPENCLAW_GATEWAY_TOKEN`, or `OPENCLAW_GATEWAY_PASSWORD` explicitly when clients need a stable secret across restarts. You can also choose password mode, or `trusted-proxy` for identity-aware reverse proxies. For open loopback, set `gateway.auth.mode: "none"` explicitly. `openclaw doctor --generate-gateway-token` generates a token any time.

</details>

<details>
<summary>Do I have to restart after changing config?</summary>

The Gateway watches the config and supports hot-reload: `gateway.reload.mode: "hybrid"` (default) hot-applies safe changes and restarts for critical ones. `off` disables config reload; the earlier `hot` and `restart` modes are retired. Most `tools.*`, `agents.*` policy, `session.*`, and `messages.*` changes apply immediately with no reload action at all; `gateway.*` binding/port changes require a restart.

</details>

<details>
<summary>How do I enable web search (and web fetch)?</summary>

`web_fetch` works without an API key. `web_search` depends on your selected provider:

| 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 | Local: yes (needs `ollama signin`); hosted: no | Hosted: `OLLAMA_API_KEY` |
| Perplexity | No | `PERPLEXITY_API_KEY` or `OPENROUTER_API_KEY` |
| SearXNG | Yes (self-hosted) | `SEARXNG_BASE_URL` |
| Tavily | No | `TAVILY_API_KEY` |

Grok can also reuse xAI OAuth from model auth (`openclaw onboard --auth-choice xai-oauth`).

**Recommended**: `openclaw configure --section web` and pick a provider.

```json5
{
  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 config lives under `plugins.entries.<plugin>.config.webSearch.*`. Legacy `tools.web.search.*` provider paths still load for compatibility but should not be used in new configs. Firecrawl web-fetch fallback config lives under `plugins.entries.firecrawl.config.webFetch.*`.

- Allowlists: add `web_search`/`web_fetch`/`x_search`, or `group:web` for all three.
- `web_fetch` is enabled by default.
- If `tools.web.fetch.provider` is omitted, OpenClaw auto-detects the first ready fetch fallback provider from available credentials; the official Firecrawl plugin provides that fallback.
- Daemons read env vars from `~/.openclaw/.env` (or the service environment).

Docs: [Web tools](https://funcoding.ai/agents/openclaw/tools/web/).

</details>

<details>
<summary>config.apply wiped my config. How do I recover and avoid this?</summary>

`config.apply` replaces the **entire config**; a partial object removes everything else.

Current OpenClaw protects 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.*`.
- Startup can migrate deterministic legacy keys in eligible single-file configs when the whole result validates, keeping the previous config in the `.bak` ring. Other invalid edits make startup fail closed; hot reload skips invalid edits without rewriting `openclaw.json`.
- `openclaw doctor --fix` owns repairs beyond that startup migration, can restore last-known-good, and saves the rejected file as `openclaw.json.clobbered.*`.

Recover:

- Check `openclaw logs --follow` for `Invalid config at`, `Config write rejected:`, or `config reload skipped (invalid config)`.
- Inspect the newest `openclaw.json.clobbered.*` or `openclaw.json.rejected.*` beside the active config.
- Run `openclaw config validate` and `openclaw doctor --fix`.
- Copy only the intended keys back with `openclaw config set` or `config.patch`.
- No last-known-good or rejected payload: restore from backup, or re-run `openclaw doctor` and 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](https://funcoding.ai/agents/openclaw/cli/config/), [Configure](https://funcoding.ai/agents/openclaw/cli/configure/), [Gateway troubleshooting](https://funcoding.ai/agents/openclaw/gateway/troubleshooting/#gateway-rejected-invalid-config), [Doctor](https://funcoding.ai/agents/openclaw/gateway/doctor/).

</details>

<details>
<summary>How do I run a central Gateway with specialized workers across devices?</summary>

Common pattern: **one Gateway** (for example a Raspberry Pi) plus **nodes** and **agents**.

- **Gateway (central)**: owns channels (Signal/WhatsApp), routing, sessions.
- **Nodes (devices)**: Macs/iOS/Android connect as peripherals and expose local tools such as `system.run` and `camera`; Macs can also present hosted widgets in the native panel.
- **Agents (workers)**: separate brains/workspaces for special roles (for example ops vs personal data).
- **Sub-agents**: spawn background work from a main agent for parallelism.
- **TUI**: connect to the Gateway and switch agents/sessions.

Docs: [Nodes](https://funcoding.ai/agents/openclaw/nodes/), [Remote access](https://funcoding.ai/agents/openclaw/gateway/remote/), [Multi-Agent Routing](https://funcoding.ai/agents/openclaw/concepts/multi-agent/), [Sub-agents](https://funcoding.ai/agents/openclaw/tools/subagents/), [TUI](https://funcoding.ai/agents/openclaw/web/tui/).

</details>

<details>
<summary>Can the OpenClaw browser run headless?</summary>

Yes:

```json5
{
  browser: { headless: true },
  agents: {
    defaults: {
      sandbox: { browser: { headless: true } },
    },
  },
}
```

Default is `false` (headful). Headless is more likely to trigger anti-bot checks on some sites (X/Twitter often blocks headless sessions). It uses the same Chromium engine and works for most automation; the main difference is no visible browser window (use screenshots for visuals). See [Browser](https://funcoding.ai/agents/openclaw/tools/browser/).

</details>

<details>
<summary>How do I use Brave for browser control?</summary>

Set `browser.executablePath` to your Brave binary (or any Chromium-based browser) and restart the Gateway. See [Browser](https://funcoding.ai/agents/openclaw/tools/browser/configuration/#use-brave-or-another-chromium-based-browser).

</details>
