diff --git a/docs/automation/cron-jobs.md b/docs/automation/cron-jobs.md index 6857de41dcba..355861454d28 100644 --- a/docs/automation/cron-jobs.md +++ b/docs/automation/cron-jobs.md @@ -690,7 +690,7 @@ Why this shape is safer: - `allowedAgentIds` prevents this hook endpoint from selecting another agent. If the Gateway serves other hook workflows, include only their intended agent ids too. - `scope: "session"` gives each Gmail message its own sandbox; `workspaceAccess: "none"` keeps the host agent workspace out of that sandbox. - `allow: ["session_status"]` is an absolute per-agent clamp, so global `tools.alsoAllow` additions cannot leak into the reader. The minimal profile and explicit deny list make the intended boundary auditable. -- `deliver: false` keeps completion inside the hook flow. To announce a summary externally after validating the reader, set `deliver: true` and add an explicit `channel` and `to`. Keep agent-to-agent handoff disabled unless you deliberately expose the exact coordination tool and pair it with a narrow [`tools.agentToAgent`](/gateway/config-tools#toolsagenttoagent) policy. +- `deliver: false` keeps completion inside the hook flow. To announce a summary externally after validating the reader, set `deliver: true` and add an explicit `channel` and `to`. Keep agent-to-agent handoff disabled unless you deliberately expose the exact coordination tool and pair it with a narrow [`tools.agentToAgent`](/gateway/config-tools#tools-agenttoagent) policy. Tool policies can only become more restrictive as global, provider, agent, and sandbox rules are combined. The per-agent allowlist cannot restore `session_status` if an earlier policy removed it. Ensure inherited policies retain `session_status`; an empty effective tool set aborts before the model sees the email. @@ -719,7 +719,7 @@ This writes `hooks.gmail` transport settings, enables the Gmail preset, preserve The built-in Gmail preset's per-message session separates conversation context; it does not restrict the target agent's tools or workspace. Without a custom mapping that sets `agentId`, Gmail hooks run as the default agent. -For untrusted inboxes, route the hook to a dedicated reader agent, give that agent read-only or no workspace access, and deny filesystem-write, shell, browser, and other unnecessary tools. If it needs to notify the main agent, expose only the required coordination tool and constrain its targets with `tools.agentToAgent`. See [Prompt injection](/gateway/security#prompt-injection), [Multi-agent sandbox and tools](/tools/multi-agent-sandbox-tools), and [`tools.agentToAgent`](/gateway/config-tools#toolsagenttoagent). +For untrusted inboxes, route the hook to a dedicated reader agent, give that agent read-only or no workspace access, and deny filesystem-write, shell, browser, and other unnecessary tools. If it needs to notify the main agent, expose only the required coordination tool and constrain its targets with `tools.agentToAgent`. See [Prompt injection](/gateway/security#prompt-injection), [Multi-agent sandbox and tools](/tools/multi-agent-sandbox-tools), and [`tools.agentToAgent`](/gateway/config-tools#tools-agenttoagent). ### Verify the reader boundary diff --git a/docs/channels/groups.md b/docs/channels/groups.md index a6b223994f9e..b9eea4daae5f 100644 --- a/docs/channels/groups.md +++ b/docs/channels/groups.md @@ -214,7 +214,7 @@ Related: - Configuration keys and defaults: [Gateway configuration](/gateway/config-agents#agentsdefaultssandbox) - Debugging why a tool is blocked: [Sandbox vs Tool Policy vs Elevated](/gateway/sandbox-vs-tool-policy-vs-elevated) -- Bind mounts details: [Sandboxing](/gateway/sandboxing#custom-bind-mounts) +- Bind mounts details: [Sandboxing](/gateway/sandboxing#multiple-folders-for-one-agent) ## Display labels diff --git a/docs/channels/msteams.md b/docs/channels/msteams.md index d2e1bb6e4a18..16bf65de6d66 100644 --- a/docs/channels/msteams.md +++ b/docs/channels/msteams.md @@ -736,7 +736,7 @@ Key settings (see [/gateway/configuration](/gateway/configuration) for shared ch - `channels.msteams.streaming.chunkMode`: `length` (default) or `newline` to split on blank lines (paragraph boundaries) before length chunking. - `channels.msteams.mediaAllowHosts`: allowlist for inbound attachment hosts (defaults to Microsoft/Teams domains: Graph, SharePoint/OneDrive, Teams CDN, Bot Framework, Azure Media Services). - `channels.msteams.mediaAuthAllowHosts`: allowlist for attaching Authorization headers on media retries (defaults to Graph + Bot Framework hosts). -- `channels.msteams.graphMediaFallback`: opt into Graph message lookups when channel/group HTML omits file markers (default `false`; see [Channel/group file recovery](#channelgroup-file-recovery-graphmediafallback)). +- `channels.msteams.graphMediaFallback`: opt into Graph message lookups when channel/group HTML omits file markers (default `false`; see [Channel/group file recovery](/channels/msteams#channel%2Fgroup-file-recovery-graphmediafallback)). - `channels.msteams.mediaMaxMb`: per-channel media size limit override in MB. Falls back to `agents.defaults.mediaMaxMb` when unset. - `channels.msteams.requireMention`: require @mention in channels/groups (default `true`). - `channels.msteams.replyStyle`: `thread | top-level` (see [Reply style](#reply-style-threads-vs-posts)). diff --git a/docs/channels/qqbot.md b/docs/channels/qqbot.md index a495a5731826..11ec46b1f2c4 100644 --- a/docs/channels/qqbot.md +++ b/docs/channels/qqbot.md @@ -210,16 +210,16 @@ group, then mention it or configure the group to run without a mention. `groups["*"]` sets defaults for every group; a concrete `groups.GROUP_OPENID` entry overrides those defaults for one group. Group settings: -| Field | Default | Description | -| --------------------- | ---------------- | -------------------------------------------------------------------------------------------------- | -| `requireMention` | `true` | Require an `@`-mention before the bot replies. | -| `commandLevel` | `all` | Which built-in slash commands can run in the group (see below). | -| `ignoreOtherMentions` | `false` | Drop messages that mention someone else but not the bot. | -| `historyLimit` | `50` | Recent non-mention messages kept as context for the next mentioned turn. `0` disables history. | -| `tools` | — | Allow/deny tools for the whole group. | -| `toolsBySender` | — | Per-sender tool overrides; see [Groups](/channels/groups#groupchannel-tool-restrictions-optional). | -| `name` | openid prefix | Friendly label used in logs and group context. | -| `prompt` | built-in default | Per-group behavior prompt appended to the agent context. | +| Field | Default | Description | +| --------------------- | ---------------- | ----------------------------------------------------------------------------------------------------- | +| `requireMention` | `true` | Require an `@`-mention before the bot replies. | +| `commandLevel` | `all` | Which built-in slash commands can run in the group (see below). | +| `ignoreOtherMentions` | `false` | Drop messages that mention someone else but not the bot. | +| `historyLimit` | `50` | Recent non-mention messages kept as context for the next mentioned turn. `0` disables history. | +| `tools` | — | Allow/deny tools for the whole group. | +| `toolsBySender` | — | Per-sender tool overrides; see [Groups](/channels/groups#group%2Fchannel-tool-restrictions-optional). | +| `name` | openid prefix | Friendly label used in logs and group context. | +| `prompt` | built-in default | Per-group behavior prompt appended to the agent context. | `commandLevel` accepts: diff --git a/docs/cli/agents.md b/docs/cli/agents.md index 37b9867d667a..f54e4597f130 100644 --- a/docs/cli/agents.md +++ b/docs/cli/agents.md @@ -76,7 +76,7 @@ Options: `--force`, `--json`. Use routing bindings to pin inbound channel traffic to a specific agent. -If you also want different visible skills per agent, configure `agents.defaults.skills` and `agents.entries.*.skills` in `openclaw.json`. See [Skills config](/tools/skills-config) and [Configuration reference](/gateway/config-agents#agentsdefaultsskills). +If you also want different visible skills per agent, configure `agents.defaults.skills` and `agents.entries.*.skills` in `openclaw.json`. See [Skills config](/tools/skills-config) and [Configuration reference](/gateway/config-agents#agents-defaults-skills). List bindings: diff --git a/docs/cli/connect.md b/docs/cli/connect.md index 97d83e137dd5..3154fdc338a7 100644 --- a/docs/cli/connect.md +++ b/docs/cli/connect.md @@ -85,7 +85,7 @@ A join code and a paired device have separate lifecycles: - Burning or expiring a join code prevents another enrollment with that code. - It does not disconnect or remove a node that already redeemed it. - To revoke an enrolled machine, remove its paired device with - [`openclaw devices remove `](/cli/devices#openclaw-devices-remove-deviceid). + [`openclaw devices remove `](/cli/devices#openclaw-devices-remove-%3Cdeviceid%3E). ## Troubleshooting diff --git a/docs/concepts/model-failover.md b/docs/concepts/model-failover.md index 8726f9078842..984ee8bda484 100644 --- a/docs/concepts/model-failover.md +++ b/docs/concepts/model-failover.md @@ -295,7 +295,7 @@ OpenClaw builds the candidate list from the currently requested `provider/model` - explicit aborts that are not timeout/failover-shaped - context overflow errors that should stay inside compaction/retry logic (for example `request_too_large`, `input token count exceeds the maximum number of input tokens`, `input exceeds the maximum number of tokens`, `input too long for the model`, or `ollama error: context length exceeded`) - a final unknown error when there are no candidates left - - Claude Fable 5 safety refusals; direct API-key requests handle those at the provider level via Anthropic's server-side fallback to `claude-opus-4-8` instead (see [Anthropic](/providers/anthropic#safety-refusal-fallback-claude-fable-5)) + - Claude Fable 5 safety refusals; direct API-key requests handle those at the provider level via Anthropic's server-side fallback to `claude-opus-4-8` instead (see [Anthropic](/providers/anthropic#safety-refusal-fallback-claude-opus-5-and-fable-5)) diff --git a/docs/concepts/model-providers.md b/docs/concepts/model-providers.md index db155a215a16..4aeafb6a4a51 100644 --- a/docs/concepts/model-providers.md +++ b/docs/concepts/model-providers.md @@ -164,7 +164,7 @@ Claude CLI reuse (`claude -p`) is a sanctioned OpenClaw integration path. Anthro - `agents.defaults.models["openai/"].params.transport` and `params.serviceTier` are authored embedded-provider request settings. They keep implicit runtime selection on OpenClaw; native Codex owns its app-server transport and service tier. - Valid model-scoped `params.fastMode` / `params.fast_mode` values and valid cutoff keys are portable typed agent-runtime controls. They do not count as authored provider request params and do not select a runtime. Pin `agentRuntime.id: "openclaw"` or `agentRuntime.id: "codex"` when a recipe depends on one runtime. - Hidden OpenClaw attribution headers (`originator`, `version`, `User-Agent`) are only attached on native Codex traffic to `chatgpt.com/backend-api`, not generic OpenAI-compatible proxies -- The shared `/fast` toggle, configured defaults, and valid model-scoped Fast params resolve through one runtime-control policy. See [Thinking levels](/tools/thinking#fast-mode-fast) for precedence. +- The shared `/fast` toggle, configured defaults, and valid model-scoped Fast params resolve through one runtime-control policy. See [Thinking levels](/tools/thinking#fast-mode-%2Ffast) for precedence. - OpenAI API Fast mode is premium-priced and model-specific. GPT-5.6 Sol currently costs 2× Standard token pricing, and long-context multipliers stack. ChatGPT/Codex-credit Fast mode is separate: GPT-5.6 and GPT-5.5 currently consume 2.5× Standard credits, while API-key Codex runs use API token pricing. See [Fast mode](https://openai.com/api-priority-processing/), [API pricing](https://developers.openai.com/api/docs/pricing), and [Codex speed](https://learn.chatgpt.com/docs/agent-configuration/speed). - The native Codex catalog can expose exact `openai/gpt-5.6-sol`, `openai/gpt-5.6-terra`, and `openai/gpt-5.6-luna` refs according to account access. It does not apply the direct API's bare `gpt-5.6` alias client-side. - `openai/gpt-5.5` uses the Codex catalog native `contextWindow = 400000` and default runtime `contextTokens = 272000`; override the runtime cap with `models.providers.openai.models[].contextTokens` diff --git a/docs/concepts/progress-drafts.md b/docs/concepts/progress-drafts.md index f8e1d83e2336..683e1cd24dd1 100644 --- a/docs/concepts/progress-drafts.md +++ b/docs/concepts/progress-drafts.md @@ -278,7 +278,7 @@ enabling `streaming.progress.commentary` hands preambles to the interleaved commentary lane instead. On Discord, when a utility model resolves for the agent — an explicit -[`utilityModel`](/gateway/config-agents#utilitymodel), or the primary +[`utilityModel`](/gateway/config-agents#agents-defaults-model), or the primary provider's declared small-model default (OpenAI → `gpt-5.6-luna`, Anthropic → `claude-haiku-4-5`) — it supplies a short plain-language filler when the model emits no preamble or has been quiet for about 20 seconds diff --git a/docs/concepts/qa-e2e-automation.md b/docs/concepts/qa-e2e-automation.md index 22ef49be2455..1e46475a55d9 100644 --- a/docs/concepts/qa-e2e-automation.md +++ b/docs/concepts/qa-e2e-automation.md @@ -1346,11 +1346,11 @@ candidate refs are replaced with neutral labels such as `candidate-01`; the report maps rankings back to real refs after parsing. Candidate runs default to `high` thinking, with `medium` for GPT-5.6 Luna and -`xhigh` for older OpenAI eval refs that support it. Override a specific -candidate inline with `--model provider/model,thinking=`; inline -options also support `fast`, `no-fast`, and `fast=`. `--thinking -` still sets a global fallback, and the older `--model-thinking -` form is kept for compatibility. OpenAI candidate +`xhigh` for older OpenAI eval refs that support it. Override a specific candidate +inline with `--model provider/model,thinking=`; inline options also support +`fast`, `no-fast`, and `fast=`. `--thinking ` still sets a global +fallback, and the older `--model-thinking ` form is kept for +compatibility. OpenAI candidate refs default to fast mode so priority processing is used where the provider supports it. Pass `--fast` only when you want to force fast mode on for every candidate model. Candidate and judge durations are recorded in the diff --git a/docs/gateway/config-agents.md b/docs/gateway/config-agents.md index 548db189abb3..e374d0406e9e 100644 --- a/docs/gateway/config-agents.md +++ b/docs/gateway/config-agents.md @@ -378,7 +378,7 @@ date context. Falls back to the host timezone. - `model`: accepts either a string (`"provider/model"`) or an object (`{ primary, fallbacks }`). - String form sets only the primary model. - Object form sets primary plus ordered failover models. -- `utilityModel`: optional `provider/model` ref or alias for short internal tasks. It currently powers generated Control UI session titles, Telegram DM topic titles, Discord auto-thread titles, and [progress-draft narration](/concepts/progress-drafts#narrated-status). When unset, OpenClaw derives the primary provider's declared small-model default when one exists (OpenAI → `gpt-5.6-luna`, Anthropic → `claude-haiku-4-5`); title tasks otherwise use the agent's primary model, and narration stays off. If a distinct utility model cannot prepare or complete a generated title, OpenClaw retries that title once with the primary model. For dashboard titles, automatic utility derivation and the regular fallback use the effective session provider and auth profile; an explicit utility model keeps its configured provider/auth. Set `utilityModel: ""` to skip the alternate utility route; dashboard title generation still proceeds directly to the regular session model. `agents.entries.*.utilityModel` overrides the default, and an operation-specific model override wins over both. Utility tasks make separate model calls and send task-specific content to the selected model provider. Dashboard title generation sends at most the first 1,000 characters of the first non-command message; narration sends the inbound request plus compact redacted tool summaries. Choose a provider that matches your cost and data-handling requirements. +- `utilityModel`: optional `provider/model` ref or alias for short internal tasks. It currently powers generated Control UI session titles, Telegram DM topic titles, Discord auto-thread titles, and [progress-draft narration](/concepts/progress-drafts#status-headline). When unset, OpenClaw derives the primary provider's declared small-model default when one exists (OpenAI → `gpt-5.6-luna`, Anthropic → `claude-haiku-4-5`); title tasks otherwise use the agent's primary model, and narration stays off. If a distinct utility model cannot prepare or complete a generated title, OpenClaw retries that title once with the primary model. For dashboard titles, automatic utility derivation and the regular fallback use the effective session provider and auth profile; an explicit utility model keeps its configured provider/auth. Set `utilityModel: ""` to skip the alternate utility route; dashboard title generation still proceeds directly to the regular session model. `agents.entries.*.utilityModel` overrides the default, and an operation-specific model override wins over both. Utility tasks make separate model calls and send task-specific content to the selected model provider. Dashboard title generation sends at most the first 1,000 characters of the first non-command message; narration sends the inbound request plus compact redacted tool summaries. Choose a provider that matches your cost and data-handling requirements. - `imageModel`: accepts either a string (`"provider/model"`) or an object (`{ primary, fallbacks }`). - Used by the `image` tool path as its vision-model config when the active model cannot accept images. Native-vision models receive loaded image bytes directly instead. - Also used as fallback routing when the selected/default model cannot accept image input. diff --git a/docs/gateway/configuration-reference.md b/docs/gateway/configuration-reference.md index 2db7154be596..94bd978a85d9 100644 --- a/docs/gateway/configuration-reference.md +++ b/docs/gateway/configuration-reference.md @@ -1110,7 +1110,7 @@ Validation and safety notes: - The built-in Gmail preset uses `sessionKey: "hook:gmail:{{messages[0].id}}"`. - This per-message key isolates conversation context, not tools or workspace access. Without a custom mapping that sets `agentId`, the preset uses the default agent. -- For untrusted inboxes, route Gmail to a dedicated reader agent and restrict that agent with [per-agent sandbox and tool policy](/tools/multi-agent-sandbox-tools). If the reader must notify the main agent, constrain the handoff with [`tools.agentToAgent`](/gateway/config-tools#toolsagenttoagent). See [Prompt injection](/gateway/security#prompt-injection) for the recommended threat model and model tier. +- For untrusted inboxes, route Gmail to a dedicated reader agent and restrict that agent with [per-agent sandbox and tool policy](/tools/multi-agent-sandbox-tools). If the reader must notify the main agent, constrain the handoff with [`tools.agentToAgent`](/gateway/config-tools#tools-agenttoagent). See [Prompt injection](/gateway/security#prompt-injection) for the recommended threat model and model tier. - The setup wizard configures Gmail transport but does not create the reader agent or required session-key policy. Apply the complete [restricted Gmail reader configuration](/automation/cron-jobs#configure-a-restricted-gmail-reader-recommended) before running setup for untrusted mail. - If you keep that per-message routing, set `hooks.allowRequestSessionKey: true` and constrain `hooks.allowedSessionKeyPrefixes` to match the Gmail namespace, for example `["hook:", "hook:gmail:"]`. - If you need `hooks.allowRequestSessionKey: false`, override the preset with a static `sessionKey` instead of the templated default. diff --git a/docs/gateway/security/index.md b/docs/gateway/security/index.md index 3c27f109cf8d..01a7c0284a56 100644 --- a/docs/gateway/security/index.md +++ b/docs/gateway/security/index.md @@ -245,7 +245,7 @@ What helps in practice: - Limit high-risk tools (`exec`, `browser`, `web_fetch`, `web_search`) to trusted agents or explicit allowlists. - If you allowlist interpreters (`python`, `node`, `ruby`, `perl`, `php`, `lua`, `osascript`), enable `tools.exec.strictInlineEval` so inline eval forms (`-c`, `-e`, and similar) still need explicit approval. In allowlist mode, any heredoc segment (`<<`) always requires reviewer or explicit approval, regardless of quoting - an allowlisted command cannot use a heredoc body to bypass allowlist review. - Reduce blast radius by using a read-only or tool-disabled **reader agent** to summarize untrusted content, then pass the summary to your main agent. -- For Gmail hooks, the built-in per-message session isolates conversation context but does not remove the target agent's tool or workspace permissions. Route untrusted mail to a dedicated reader agent, apply [per-agent sandbox and tool restrictions](/tools/multi-agent-sandbox-tools), and constrain any handoff to the main agent with [`tools.agentToAgent`](/gateway/config-tools#toolsagenttoagent). See [Gmail integration](/gateway/configuration-reference#gmail-integration). +- For Gmail hooks, the built-in per-message session isolates conversation context but does not remove the target agent's tool or workspace permissions. Route untrusted mail to a dedicated reader agent, apply [per-agent sandbox and tool restrictions](/tools/multi-agent-sandbox-tools), and constrain any handoff to the main agent with [`tools.agentToAgent`](/gateway/config-tools#tools-agenttoagent). See [Gmail integration](/gateway/configuration-reference#gmail-integration). - Keep `web_search` / `web_fetch` / `browser` off for tool-enabled agents unless needed. - For OpenResponses URL inputs (`input_file` / `input_image`), set a tight `gateway.http.endpoints.responses.files.urlAllowlist` / `images.urlAllowlist` and keep `maxUrlParts` low (empty allowlists count as unset). Use `files.allowUrl: false` / `images.allowUrl: false` to disable URL fetching entirely. - Keep secrets out of prompts; pass them via env/config on the gateway host instead. @@ -741,7 +741,7 @@ The Control UI needs a secure context (HTTPS or localhost) to generate device id ## Deployment and host trust - Full-disk encryption on the gateway host; prefer a dedicated OS user account for the Gateway if the host is shared. -- Published package dependency lock: source checkouts use `pnpm-lock.yaml`; the published `openclaw` npm package and OpenClaw-owned npm plugin packages include `npm-shrinkwrap.json` so installs use the reviewed transitive dependency graph from the release instead of resolving a fresh graph at install time. This is a supply-chain hardening and release reproducibility boundary, not a sandbox - see [npm shrinkwrap](/gateway/security/shrinkwrap). +- Published package dependency lock: source checkouts use `pnpm-lock.yaml`; the published `openclaw` npm package and OpenClaw-owned npm plugin packages include `npm-shrinkwrap.json` so installs use the reviewed transitive dependency graph from the release instead of resolving a fresh graph at install time. This is a supply-chain hardening and release reproducibility boundary, not a sandbox - see [npm shrinkwrap](/gateway/security/dependency-locking). - Secure file operations: OpenClaw uses `@openclaw/fs-safe` for root-bounded file access, atomic writes, archive extraction, temp workspaces, and secret-file helpers. Optional native acceleration defaults **off**; set `OPENCLAW_FS_SAFE_NATIVE_MODE=auto` to use an installed platform binding or `require` to fail closed when native support is unavailable. Details: [Secure file operations](/gateway/security/secure-file-operations). - Shared Slack workspace risk: if everyone in Slack can message the bot, the core risk is delegated tool authority - any allowed sender can induce tool calls (`exec`, browser, network/file tools) within the agent's policy, prompt/content injection from one sender can affect shared state/devices/outputs, and if the shared agent has sensitive credentials/files, any allowed sender can potentially drive exfiltration via tool usage. Use separate agents/gateways with minimal tools for team workflows; keep personal-data agents private. - Company-shared agent (acceptable pattern): fine when everyone using the agent is in the same trust boundary (for example one company team) and the agent is strictly business-scoped. Run it on a dedicated machine/VM/container, use a dedicated OS user + dedicated browser/profile/accounts, and do not sign that runtime into personal Apple/Google accounts or personal password-manager/browser profiles. Mixing personal and company identities on the same runtime collapses the separation and increases personal-data exposure risk. diff --git a/docs/gateway/stable-https-url.md b/docs/gateway/stable-https-url.md index 13b04f976161..ddca942708b7 100644 --- a/docs/gateway/stable-https-url.md +++ b/docs/gateway/stable-https-url.md @@ -11,7 +11,7 @@ Tailscale Serve gives your Gateway one HTTPS URL without exposing the Gateway po The result is `https://..ts.net`, reachable from permitted devices on your tailnet and not from the public internet. The matching WebSocket URL is `wss://..ts.net`. -If you need a public URL, use [Tailscale Funnel](/gateway/tailscale#public-internet-funnel-shared-password) instead. Funnel is public, and OpenClaw requires password auth for it. +If you need a public URL, use [Tailscale Funnel](/gateway/tailscale#public-internet-funnel-%2B-shared-password) instead. Funnel is public, and OpenClaw requires password auth for it. ## Before you begin diff --git a/docs/help/faq.md b/docs/help/faq.md index 68d0251ed14c..bcf13195f98e 100644 --- a/docs/help/faq.md +++ b/docs/help/faq.md @@ -405,7 +405,7 @@ First-run Q&A - install, onboard, auth routes, subscriptions, initial failures - OpenClaw validates 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 exist yet. - See [Sandboxing](/gateway/sandboxing#custom-bind-mounts) and [Sandbox vs Tool Policy vs Elevated](/gateway/sandbox-vs-tool-policy-vs-elevated#bind-mounts-security-quick-check). + See [Sandboxing](/gateway/sandboxing#multiple-folders-for-one-agent) and [Sandbox vs Tool Policy vs Elevated](/gateway/sandbox-vs-tool-policy-vs-elevated#bind-mounts-security-quick-check). diff --git a/docs/help/testing.md b/docs/help/testing.md index 890bd9978c02..2773d94e6c01 100644 --- a/docs/help/testing.md +++ b/docs/help/testing.md @@ -420,7 +420,7 @@ gh workflow run package-acceptance.yml --ref main \ homeserver. Source-checkout only - packaged installs do not ship `qa-lab`. - Full CLI, profile/scenario catalog, env vars, and artifact layout: - [Matrix smoke lanes](/concepts/qa-e2e-automation#matrix-smoke-lanes). + [Matrix smoke lanes](/concepts/qa-e2e-automation#matrix-live-lane). - `pnpm openclaw qa telegram` - Runs the Telegram live QA lane against a real private group using the driver and SUT bot tokens from env. @@ -495,7 +495,7 @@ table through the Mantis GitHub App when `pr_number` is set. Live transport lanes share one standard contract so new transports do not drift; the per-lane coverage matrix lives in -[QA overview - Live transport coverage](/concepts/qa-e2e-automation#live-transport-coverage). +[QA overview - Live transport coverage](/concepts/qa-e2e-automation#buzz%2C-discord%2C-slack%2C-telegram%2C-and-whatsapp-qa-reference). `qa-channel` is the broad synthetic suite and is not part of that matrix. ### Shared Telegram credentials via Convex (v1) diff --git a/docs/help/troubleshooting.md b/docs/help/troubleshooting.md index 6e611f7240a4..593a2faca7cf 100644 --- a/docs/help/troubleshooting.md +++ b/docs/help/troubleshooting.md @@ -147,7 +147,7 @@ openclaw plugins inspect --runtime --json openclaw plugins enable ``` -Reference: [Operator install policy](/tools/skills-config#operator-install-policy-securityinstallpolicy) +Reference: [Operator install policy](/tools/skills-config#operator-install-policy-security-installpolicy) ## Plugin present but blocked by suspicious ownership diff --git a/docs/install/docker.md b/docs/install/docker.md index 56019b087937..eb452c2464f9 100644 --- a/docs/install/docker.md +++ b/docs/install/docker.md @@ -200,7 +200,7 @@ Optional variables accepted by `scripts/docker/setup.sh` (and, for the gateway c | `OPENCLAW_SANDBOX` | Opt in to sandbox bootstrap (`1`, `true`, `yes`, `on`) | | `OPENCLAW_SKIP_ONBOARDING` | Skip the interactive onboarding step (`1`, `true`, `yes`, `on`) | | `OPENCLAW_DOCKER_SOCKET` | Override the Docker socket path | -| `OPENCLAW_DISABLE_BONJOUR` | Force Bonjour/mDNS advertising on (`0`) or off (`1`); see [Bonjour / mDNS](#bonjour--mdns) | +| `OPENCLAW_DISABLE_BONJOUR` | Force Bonjour/mDNS advertising on (`0`) or off (`1`); see [Bonjour / mDNS](/install/docker#bonjour-%2F-mdns) | | `OPENCLAW_DISABLE_BUNDLED_SOURCE_OVERLAYS` | Disable bundled plugin source bind-mount overlays | | `OTEL_EXPORTER_OTLP_ENDPOINT` | Shared OTLP/HTTP collector endpoint for OpenTelemetry export | | `OTEL_EXPORTER_OTLP_*_ENDPOINT` | Signal-specific OTLP endpoints for traces, metrics, or logs | diff --git a/docs/platforms/mac/bundled-gateway.md b/docs/platforms/mac/bundled-gateway.md index 83cc64e2cc00..829890220878 100644 --- a/docs/platforms/mac/bundled-gateway.md +++ b/docs/platforms/mac/bundled-gateway.md @@ -87,7 +87,7 @@ Logging: - If the host loops with repeated `EADDRINUSE` or fast restarts, check for duplicate `ai.openclaw.gateway` / `ai.openclaw.node` LaunchAgents and the launchd-marker workaround in - [Gateway troubleshooting](/gateway/troubleshooting#macos-launchd-supervisor-loop-with-duplicate-gatewaynode-launchagents). + [Gateway troubleshooting](/gateway/troubleshooting#macos-launchd-supervisor-loop-with-duplicate-gateway%2Fnode-launchagents). ## Version compatibility diff --git a/docs/plugins/codex-computer-use.md b/docs/plugins/codex-computer-use.md index 956605115fa7..d63d8fc38d51 100644 --- a/docs/plugins/codex-computer-use.md +++ b/docs/plugins/codex-computer-use.md @@ -327,7 +327,7 @@ tools when available, and the specific message for the failing setup step. This Codex-owned Computer Use path runs on macOS, where the MCP server may need local OS permissions before it can inspect or control apps. (For cross-platform desktop control on Windows and Linux node hosts, see the -[cua-computer fulfiller](/nodes/computer-use#windows-and-linux-experimental-via-cua-driver).) +[cua-computer fulfiller](/nodes/computer-use#windows-and-linux-experimental%2C-via-cua-driver-sdk).) If OpenClaw says Computer Use is installed but the MCP server is unavailable, verify the Codex-side Computer Use setup first: diff --git a/docs/plugins/copilot.md b/docs/plugins/copilot.md index 6f0dfbe87a7c..130ff230cd5c 100755 --- a/docs/plugins/copilot.md +++ b/docs/plugins/copilot.md @@ -14,7 +14,7 @@ agent loop: native tool execution, native compaction (`infiniteSessions`), and CLI-managed thread state under `copilotHome`. OpenClaw still owns chat channels, session files, model selection, dynamic tools (bridged), approvals, media delivery, the visible transcript mirror, `/btw` side questions (see -[Side questions (`/btw`)](#side-questions-btw)), and `openclaw doctor`. +[Side questions (`/btw`)](/plugins/copilot#side-questions-%2Fbtw)), and `openclaw doctor`. For the broader model/provider/runtime split, start with [Agent runtimes](/concepts/agent-runtimes). diff --git a/docs/plugins/hooks.md b/docs/plugins/hooks.md index c980cd0e07a6..dfb0521f45d2 100644 --- a/docs/plugins/hooks.md +++ b/docs/plugins/hooks.md @@ -1047,7 +1047,7 @@ before the next major release: - **Plaintext channel envelopes** in `inbound_claim` and `message_received` handlers. Read `BodyForAgent` and the structured user-context blocks instead of parsing flat envelope text. See - [Plaintext channel envelopes → BodyForAgent](/plugins/sdk-migration#active-deprecations). + [Plaintext channel envelopes → BodyForAgent](/plugins/sdk-migration#removal-timeline). - **`subagent_spawning`** remains for compatibility with older plugins, but new plugins should not return thread routing from it. Core prepares `thread: true` subagent bindings through channel session-binding adapters @@ -1063,7 +1063,7 @@ before the next major release: For the full list - memory capability registration, provider thinking profile, external auth providers, provider discovery types, task runtime accessors, and the `command-auth` → `command-status` rename - see -[Plugin SDK migration → Active deprecations](/plugins/sdk-migration#active-deprecations). +[Plugin SDK migration → Active deprecations](/plugins/sdk-migration#removal-timeline). ## Related diff --git a/docs/plugins/memory-lancedb.md b/docs/plugins/memory-lancedb.md index e167343f9089..647a0f1b96f8 100644 --- a/docs/plugins/memory-lancedb.md +++ b/docs/plugins/memory-lancedb.md @@ -191,17 +191,17 @@ local server returns context-length errors. ## Recall and capture limits -| Setting | Default | Range | Applies to | -| ----------------- | ------- | ---------------------------- | ---------------------------------------------------------- | -| `recallMaxChars` | `1000` | 100-10000 | Text sent to the embedding API for recall. | -| `captureMaxChars` | `500` | 100-10000 | Message length eligible for auto-capture. | -| `customTriggers` | `[]` | 0-50 items, each <=100 chars | Literal phrases that make auto-capture consider a message. | +| Setting | Default | Range | Applies to | +| ----------------- | ------- | --------------------------- | ---------------------------------------------------------- | +| `recallMaxChars` | `1000` | 100-10000 | Text sent to the embedding API for recall. | +| `captureMaxChars` | `500` | 100-10000 | Message length eligible for auto-capture. | +| `customTriggers` | `[]` | 0-50 items, each ≤100 chars | Literal phrases that make auto-capture consider a message. | `recallMaxChars` bounds the `before_prompt_build` auto-recall query, the -`memory_recall` tool, the `memory_forget` query path, and `openclaw ltm -search`. Auto-recall embeds the latest user message from the turn and falls -back to the full prompt only when no user message is present, keeping channel -metadata and large prompt blocks out of the embedding request. +`memory_recall` tool, the `memory_forget` query path, and `openclaw ltm search`. +Auto-recall embeds the latest user message from the turn and falls back to the +full prompt only when no user message is present, keeping channel metadata and +large prompt blocks out of the embedding request. `captureMaxChars` gates whether a user message from the turn's `agent_end` event is short enough to be considered for auto-capture; it does not affect diff --git a/docs/plugins/sdk-entrypoints.md b/docs/plugins/sdk-entrypoints.md index f1acc53edc92..3aec3d32cd7c 100644 --- a/docs/plugins/sdk-entrypoints.md +++ b/docs/plugins/sdk-entrypoints.md @@ -157,7 +157,7 @@ export default definePluginEntry({ `resolveCreateSession({ agentId })` must return a config-derived model/runtime target before OpenClaw advertises creation or calls `startTerminalSession`. Use - [`api.runtime.agent.resolveSessionCatalogCreateTarget(...)`](/plugins/sdk-runtime#apiruntimeagent) + [`api.runtime.agent.resolveSessionCatalogCreateTarget(...)`](/plugins/sdk-runtime#api-runtime-agent) to apply the host's runtime and model-allowlist policy instead of duplicating it. diff --git a/docs/providers/openai.md b/docs/providers/openai.md index e69470f7340f..5dcc2154ad34 100644 --- a/docs/providers/openai.md +++ b/docs/providers/openai.md @@ -1398,7 +1398,7 @@ not declared Codex-compatible. global default, per-model `params.fastMode`, then off. `/fast default` clears only the session layer. `/status` reports the resolved OpenClaw policy and runtime, not the upstream service tier actually honored or - returned. See [Thinking levels](/tools/thinking#fast-mode-fast) and + returned. See [Thinking levels](/tools/thinking#fast-mode-%2Ffast) and [Codex harness](/plugins/codex-harness#shared-fast-mode-and-codex-fast-mode). diff --git a/docs/reference/memory-config.md b/docs/reference/memory-config.md index 80a55bb83e6c..eb905d59f139 100644 --- a/docs/reference/memory-config.md +++ b/docs/reference/memory-config.md @@ -469,7 +469,7 @@ when you intentionally want both representations. Ordinary model-invoked session transcript search obeys -[`tools.sessions.visibility`](/gateway/config-tools#toolssessions). The default +[`tools.sessions.visibility`](/gateway/config-tools#tools-sessions). The default `tree` visibility exposes the current session, sessions it spawned, and same-agent group sessions watched through ambient group awareness. Other unrelated sessions require `agent` visibility (or `all` only when cross-agent diff --git a/docs/reference/session-management-compaction.md b/docs/reference/session-management-compaction.md index 3e5d1ad2a50f..f9fe3da59a65 100644 --- a/docs/reference/session-management-compaction.md +++ b/docs/reference/session-management-compaction.md @@ -274,7 +274,7 @@ OpenClaw supports "silent" turns for background tasks where the user should not Before auto-compaction happens, OpenClaw can run a silent agentic turn that writes durable state to disk (for example `memory/YYYY-MM-DD.md` in the agent workspace) so compaction cannot erase critical context. It monitors session context usage, and once it crosses a soft threshold below the compaction threshold, it sends a silent "write memory now" directive using the exact silent token `NO_REPLY` / `no_reply` so the user sees nothing. -Config (`agents.defaults.compaction.memoryFlush`), full reference at [/gateway/config-agents](/gateway/config-agents#agentsdefaultscompaction): +Config (`agents.defaults.compaction.memoryFlush`), full reference at [/gateway/config-agents](/gateway/config-agents#agents-defaults-compaction): | Key | Default | Notes | | --------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | diff --git a/docs/releases/2026.6.11.md b/docs/releases/2026.6.11.md index a8781d74c4a2..43c0255a8348 100644 --- a/docs/releases/2026.6.11.md +++ b/docs/releases/2026.6.11.md @@ -84,7 +84,7 @@ Across [Telegram](/channels/telegram), [WhatsApp](/channels/whatsapp), [Matrix]( [Model selection](/providers/models) and setup recover more clearly when catalogs, credentials, streams, timeouts, compaction, or fallbacks go wrong. Affected [OpenAI](/providers/openai), [OpenRouter](/providers/openrouter), and [OpenCode Go](/providers/opencode-go) configurations now report or recover from failures more consistently instead of leaving users with a stale choice or a stalled request. -Follow-up fixes for [fast mode](/tools/thinking#fast-mode-fast) improve its behavior in affected provider and fallback paths; automatic fast mode itself is not new in this release. +Follow-up fixes for [fast mode](/tools/thinking#fast-mode-%2Ffast) improve its behavior in affected provider and fallback paths; automatic fast mode itself is not new in this release. diff --git a/docs/start/onboarding-redesign.md b/docs/start/onboarding-redesign.md index 673a5cb1915e..bedd6fadc809 100644 --- a/docs/start/onboarding-redesign.md +++ b/docs/start/onboarding-redesign.md @@ -37,8 +37,8 @@ Design principles (decided, do not relitigate casually): - **The hatch is a ceremony**: same thread, avatar swap, the agent names itself and picks its own face. The custodian teaches the hierarchy once: "ask me about the system, or just ask your agent — it relays." -- **Trust is tiered by source**: official catalog entries may be pre-selected; - third-party ClawHub skills are never pre-selected regardless of model +- **Trust is tiered by source**: official catalog entries may be preselected; + third-party ClawHub skills are never preselected regardless of model ranking, and their labels say they install the publisher's code. - **Configured installs are sacred**: re-running onboarding is a verification pass. It never re-applies setup and never restarts the Gateway service. @@ -113,7 +113,7 @@ Remote-gateway onboarding keeps its legacy conversational handoff explicit cap is passed). - **Supply-chain guard**: ClawHub listing text is publisher-controlled and reaches the matcher prompt, so a listing can promote itself to - "recommended". Only official catalog entries may be pre-selected; ClawHub + "recommended". Only official catalog entries may be preselected; ClawHub skills always require an explicit tick and are labeled "third-party ClawHub skill; installs its publisher's code". - Node command `device.apps` (TS node-host, Android envelope parity), sharing @@ -324,7 +324,7 @@ restart` from the real environment and verify the plist. Product follow-up: - Magical scan with kill switch, not consent-first (phase 1; persistent output discloses model and ClawHub use before scanning, and the results note repeats it). - Full vertical including the node `device.apps` command (phase 1). -- Third-party ClawHub skills are never pre-selected and are labeled as +- Third-party ClawHub skills are never preselected and are labeled as installing the publisher's code; official entries may be pre-checked (phase 1, shipped security posture). - Two access cards, not three; consent front-loaded into the choice (phase 2). diff --git a/docs/tools/exec-approvals.md b/docs/tools/exec-approvals.md index 4a32fef55435..a4a703c618e5 100644 --- a/docs/tools/exec-approvals.md +++ b/docs/tools/exec-approvals.md @@ -58,7 +58,7 @@ Exec approvals are enforced locally on the execution host: | `openclaw exec-policy set` / `preset` | Synchronize the local requested policy with the local host approvals document in one step. | -Per-session `/exec` overrides are not included. Run `/exec` in the relevant session to inspect its current defaults. See [session overrides](/tools/exec#session-overrides-exec). +Per-session `/exec` overrides are not included. Run `/exec` in the relevant session to inspect its current defaults. See [session overrides](/tools/exec#session-overrides-%2Fexec). Full CLI reference (flags, JSON output, allowlist add/remove): [Approvals CLI](/cli/approvals). @@ -305,18 +305,15 @@ openclaw exec-policy preset yolo Updates both local `tools.exec.host/security/ask` and the local approvals file defaults (including `askFallback: "full"`). It is intentionally local-only. To change gateway-host or node-host approvals remotely, use -`openclaw approvals set --gateway` or `openclaw approvals set --node -`. +`openclaw approvals set --gateway` or +`openclaw approvals set --node `. Other built-in presets: `cautious` (`host=gateway`, `security=allowlist`, `ask=on-miss`, `askFallback=deny`) and `deny-all` (`host=gateway`, `security=deny`, `ask=off`, `askFallback=deny`). Apply the same way: `openclaw exec-policy preset cautious`. -To set individual fields instead of a full preset, use -`openclaw exec-policy set --host --security - --ask --ask-fallback -` with any subset of those flags. +To set individual fields instead of a full preset, use `openclaw exec-policy set --host --security --ask --ask-fallback ` with any subset of those flags. ### Node host diff --git a/docs/tools/loop-detection.md b/docs/tools/loop-detection.md index 15e7eaf00ba3..0967c1355940 100644 --- a/docs/tools/loop-detection.md +++ b/docs/tools/loop-detection.md @@ -152,7 +152,7 @@ spend and lockups while preserving normal tool access. Spawning isolated agents to bound runaway behavior. - + Full `tools.loopDetection` schema and merging semantics. diff --git a/docs/tools/plugin.md b/docs/tools/plugin.md index bb70b83fbc6e..0164b10020bf 100644 --- a/docs/tools/plugin.md +++ b/docs/tools/plugin.md @@ -154,7 +154,7 @@ deprecated `--dangerously-force-unsafe-install` flag is accepted for compatibility but is a no-op: it does not bypass install policy or `before_install` hook blocks. -See [Skills config](/tools/skills-config#operator-install-policy-securityinstallpolicy) +See [Skills config](/tools/skills-config#operator-install-policy-security-installpolicy) for the shared `security.installPolicy` exec schema used by both skills and plugins. diff --git a/docs/tools/screen.md b/docs/tools/screen.md index 362ce6cff68a..06126052ad6f 100644 --- a/docs/tools/screen.md +++ b/docs/tools/screen.md @@ -46,5 +46,5 @@ panels. ## Related - [Control UI](/web/control-ui) -- [Gateway protocol](/gateway/protocol#method-families) +- [Gateway protocol](/gateway/protocol#rpc-method-families) - [Browser tool](/tools/browser) diff --git a/scripts/codespell-ignore.txt b/scripts/codespell-ignore.txt index bbd84a4bff23..a760fcaaa888 100644 --- a/scripts/codespell-ignore.txt +++ b/scripts/codespell-ignore.txt @@ -15,3 +15,4 @@ wit allowIn planText nwe +smoe diff --git a/scripts/docs-link-audit.mts b/scripts/docs-link-audit.mts index a6233df5d346..fb5a839a425e 100644 --- a/scripts/docs-link-audit.mts +++ b/scripts/docs-link-audit.mts @@ -608,6 +608,16 @@ export function prepareAnchorAuditDocsDir(sourceDir = DOCS_DIR) { fs.rmSync(path.join(tempDir, entry.name), { recursive: true, force: true }); } + for (const filePath of walk(tempDir).filter((entry) => /\.mdx?$/iu.test(entry))) { + const raw = fs.readFileSync(filePath, "utf8"); + const normalized = raw.replace(//gu, (comment) => + comment.replace(/[^\r\n]/gu, ""), + ); + if (normalized !== raw) { + fs.writeFileSync(filePath, normalized, "utf8"); + } + } + const docsJsonPath = path.join(tempDir, "docs.json"); const docsConfig = JSON.parse(fs.readFileSync(docsJsonPath, "utf8")); const sanitized = sanitizeDocsConfigForEnglishOnly(docsConfig); diff --git a/src/scripts/docs-link-audit.test.ts b/src/scripts/docs-link-audit.test.ts index 80886d89d0d1..9d7f25292705 100644 --- a/src/scripts/docs-link-audit.test.ts +++ b/src/scripts/docs-link-audit.test.ts @@ -254,13 +254,31 @@ describe("docs-link-audit", () => { )}\n`, "utf8", ); - fs.writeFileSync(path.join(docsRoot, "help", "testing.md"), "# testing\n", "utf8"); + fs.writeFileSync( + path.join(docsRoot, "help", "testing.md"), + [ + "# testing", + "", + "visible text", + "", + "", + ].join("\n"), + "utf8", + ); fs.writeFileSync(path.join(docsRoot, "zh-CN", "help", "testing.md"), "# 测试\n", "utf8"); const anchorDocsDir = prepareAnchorAuditDocsDir(docsRoot); try { expect(fs.existsSync(path.join(anchorDocsDir, "help", "testing.md"))).toBe(true); expect(fs.existsSync(path.join(anchorDocsDir, "zh-CN"))).toBe(false); + const preparedMarkdown = fs.readFileSync( + path.join(anchorDocsDir, "help", "testing.md"), + "utf8", + ); + expect(preparedMarkdown).not.toContain("