From 4e74d640e1a9a541e469ca28b574eaeadd7868fa Mon Sep 17 00:00:00 2001 From: "openclaw-docs-i18n[bot]" Date: Thu, 23 Apr 2026 07:10:57 +0000 Subject: [PATCH] chore(i18n): refresh zh-CN translations --- docs/zh-CN/automation/cron-jobs.md | 177 ++-- docs/zh-CN/channels/discord.md | 402 +++---- docs/zh-CN/channels/irc.md | 87 +- docs/zh-CN/channels/matrix.md | 595 +++++------ docs/zh-CN/channels/mattermost.md | 280 ++--- docs/zh-CN/channels/slack.md | 390 +++---- docs/zh-CN/channels/synology-chat.md | 91 +- docs/zh-CN/channels/telegram.md | 494 ++++----- docs/zh-CN/channels/whatsapp.md | 266 ++--- docs/zh-CN/cli/doctor.md | 43 +- docs/zh-CN/cli/gateway.md | 233 ++-- docs/zh-CN/cli/mcp.md | 226 ++-- docs/zh-CN/cli/memory.md | 107 +- docs/zh-CN/cli/models.md | 114 +- docs/zh-CN/cli/plugins.md | 205 +++- docs/zh-CN/cli/tui.md | 41 +- docs/zh-CN/concepts/session-tool.md | 143 ++- docs/zh-CN/gateway/cli-backends.md | 211 ++-- docs/zh-CN/gateway/configuration.md | 363 ++++--- docs/zh-CN/gateway/openshell.md | 163 ++- docs/zh-CN/gateway/pairing.md | 127 ++- docs/zh-CN/gateway/security/index.md | 1228 +++++++++++----------- docs/zh-CN/gateway/trusted-proxy-auth.md | 230 ++-- docs/zh-CN/plugins/architecture.md | 1167 ++++++++++---------- docs/zh-CN/plugins/bundles.md | 211 ++-- docs/zh-CN/plugins/codex-harness.md | 240 +++-- docs/zh-CN/reference/RELEASING.md | 214 ++-- docs/zh-CN/tools/acp-agents.md | 555 +++++----- docs/zh-CN/tools/slash-commands.md | 257 ++--- docs/zh-CN/tools/trajectory.md | 190 ++++ docs/zh-CN/web/control-ui.md | 312 +++--- 31 files changed, 4961 insertions(+), 4401 deletions(-) create mode 100644 docs/zh-CN/tools/trajectory.md diff --git a/docs/zh-CN/automation/cron-jobs.md b/docs/zh-CN/automation/cron-jobs.md index 24d97505b..6fd623460 100644 --- a/docs/zh-CN/automation/cron-jobs.md +++ b/docs/zh-CN/automation/cron-jobs.md @@ -2,21 +2,21 @@ read_when: - 调度后台任务或唤醒操作 - 将外部触发器(webhook、Gmail)接入 OpenClaw - - 为定时任务决定使用心跳还是 cron -summary: 用于 Gateway 网关调度器的定时任务、webhook 和 Gmail PubSub 触发器 -title: 定时任务 + - 为计划任务决定使用 heartbeat 还是 cron +summary: 用于 Gateway 网关调度器的计划任务、webhook 和 Gmail PubSub 触发器 +title: 计划任务 x-i18n: - generated_at: "2026-04-21T06:32:47Z" + generated_at: "2026-04-23T07:03:26Z" model: gpt-5.4 provider: openai - source_hash: ac08f67af43bc85a1713558899a220c935479620f1ef74aa76336259daac2828 + source_hash: c9565b73efc151c991ee6a1029c887c35d8673736913ddc5cdcfae09a4652f86 source_path: automation/cron-jobs.md workflow: 15 --- -# 定时任务(Cron) +# 计划任务(Cron) -Cron 是 Gateway 网关内置的调度器。它会持久化任务,在正确时间唤醒智能体,并且可以将输出回传到聊天渠道或 webhook 端点。 +Cron 是 Gateway 网关内置的调度器。它会持久化任务,在正确的时间唤醒智能体,并可将输出回传到聊天渠道或 webhook 端点。 ## 快速开始 @@ -30,7 +30,7 @@ openclaw cron add \ --wake now \ --delete-after-run -# 检查你的任务 +# 查看你的任务 openclaw cron list openclaw cron show @@ -38,60 +38,61 @@ openclaw cron show openclaw cron runs --id ``` -## cron 的工作方式 +## Cron 的工作方式 -- Cron **运行在 Gateway 网关** 进程内部(而不是在模型内部)。 -- 任务定义持久化保存在 `~/.openclaw/cron/jobs.json`,因此重启不会丢失计划。 -- 运行时执行状态保存在同目录下的 `~/.openclaw/cron/jobs-state.json`。如果你用 git 跟踪 cron 定义,请跟踪 `jobs.json`,并将 `jobs-state.json` 加入 gitignore。 -- 在拆分之后,旧版本的 OpenClaw 仍然可以读取 `jobs.json`,但可能会将任务视为全新任务,因为运行时字段现在保存在 `jobs-state.json` 中。 +- Cron 在 **Gateway 网关** 进程**内部**运行(不在模型内部)。 +- 任务定义持久化保存在 `~/.openclaw/cron/jobs.json`,因此重启不会丢失调度计划。 +- 运行时执行状态保存在旁边的 `~/.openclaw/cron/jobs-state.json` 中。如果你用 git 跟踪 cron 定义,请跟踪 `jobs.json`,并将 `jobs-state.json` 加入 `.gitignore`。 +- 拆分之后,旧版 OpenClaw 可以读取 `jobs.json`,但可能会将任务视为全新任务,因为运行时字段现在位于 `jobs-state.json` 中。 - 所有 cron 执行都会创建[后台任务](/zh-CN/automation/tasks)记录。 -- 一次性任务(`--at`)默认会在成功后自动删除。 -- 独立 cron 运行会尽力在运行完成后关闭其 `cron:` 会话所跟踪的浏览器标签页/进程,这样分离的浏览器自动化就不会留下孤儿进程。 -- 独立 cron 运行还会防止陈旧的确认回复。如果第一个结果只是一个中间状态更新(例如 `on it`、`pulling everything together` 以及类似提示),并且没有后代子智能体运行仍然负责最终答案,OpenClaw 会在投递前再次提示一次以获取实际结果。 +- 一次性任务(`--at`)默认在成功后自动删除。 +- 独立 cron 运行会在运行完成时尽力关闭其 `cron:` 会话所跟踪的浏览器标签页/进程,这样分离的浏览器自动化就不会留下孤儿进程。 +- 独立 cron 运行还会防止过时的确认回复。如果第一个结果只是中间状态更新(如 `on it`、`pulling everything together` 以及类似提示),并且没有任何后代子智能体运行仍负责最终答案,OpenClaw 会在投递前再次提示一次,以获取实际结果。 -cron 的任务协调由运行时负责:当 cron 运行时仍将该任务标记为运行中时,即使仍存在旧的子会话行,一个活动中的 cron 任务也会保持存活。 -一旦运行时不再拥有该任务,且 5 分钟宽限窗口过期,维护流程就可以将任务标记为 `lost`。 +Cron 的任务协调由运行时负责:只要 cron 运行时仍将该任务跟踪为正在运行,对应的活动 cron 任务就会保持存活,即使仍存在旧的子会话行记录也是如此。一旦运行时不再拥有该任务,且 5 分钟宽限期到期,维护流程就可以将该任务标记为 `lost`。 ## 调度类型 -| 类型 | CLI 标志 | 描述 | -| ------- | --------- | --------------------------------------------------- | -| `at` | `--at` | 一次性时间戳(ISO 8601 或类似 `20m` 的相对时间) | -| `every` | `--every` | 固定间隔 | -| `cron` | `--cron` | 5 字段或 6 字段 cron 表达式,可选配 `--tz` | +| 类型 | CLI 标志 | 描述 | +| ------- | -------- | --------------------------------------------------- | +| `at` | `--at` | 一次性时间戳(ISO 8601 或类似 `20m` 的相对时间) | +| `every` | `--every`| 固定间隔 | +| `cron` | `--cron` | 5 字段或 6 字段的 cron 表达式,可选搭配 `--tz` 使用 | -不带时区的时间戳会被视为 UTC。添加 `--tz America/New_York` 可按本地钟表时间调度。 +不带时区的时间戳会被视为 UTC。添加 `--tz America/New_York` 可按本地墙上时钟时间进行调度。 -每小时整点的周期性表达式会自动错峰,最多延迟 5 分钟,以减少负载尖峰。使用 `--exact` 可强制精确触发,或使用 `--stagger 30s` 指定一个明确的错峰窗口。 +循环的整点表达式会自动错开最多 5 分钟,以减少负载尖峰。使用 `--exact` 可强制精确时间,或使用 `--stagger 30s` 指定明确的错开窗口。 -### day-of-month 和 day-of-week 使用 OR 逻辑 +### 月中的某天与星期几使用 OR 逻辑 -Cron 表达式由 [croner](https://github.com/Hexagon/croner) 解析。当 day-of-month 和 day-of-week 字段都不是通配符时,croner 会在**任一**字段匹配时触发,而不是两者都必须匹配。这是标准的 Vixie cron 行为。 +Cron 表达式由 [croner](https://github.com/Hexagon/croner) 解析。当“月中的某天”和“星期几”字段都不是通配符时,croner 会在**任一**字段匹配时触发,而不是两个都匹配时才触发。这是标准的 Vixie cron 行为。 ``` -# 预期:"每月 15 日上午 9 点,且仅当这天是周一" -# 实际: "每月每个 15 日上午 9 点,以及每个周一上午 9 点" +# 预期:"每月 15 日上午 9 点,且仅当这一天是周一" +# 实际:"每个 15 日上午 9 点,以及每个周一上午 9 点" 0 9 15 * 1 ``` -这会每月触发约 5–6 次,而不是每月 0–1 次。OpenClaw 在这里使用 Croner 默认的 OR 行为。若要同时满足这两个条件,请使用 Croner 的 `+` day-of-week 修饰符(`0 9 15 * +1`),或者只按一个字段调度,并在你的任务提示或命令中对另一个条件进行判断。 +这样每月会触发约 5–6 次,而不是 0–1 次。OpenClaw 在这里使用 Croner 默认的 OR 行为。若要同时要求两个条件都满足,请使用 Croner 的 `+` 星期几修饰符(`0 9 15 * +1`),或仅按一个字段调度,再在任务的提示词或命令中对另一个条件进行判断。 ## 执行方式 -| 方式 | `--session` 值 | 运行位置 | 最适合 | -| -------------- | ------------------ | ------------------------ | ----------------------------- | -| 主会话 | `main` | 下一个心跳轮次 | 提醒、系统事件 | -| 独立 | `isolated` | 专用 `cron:` | 报告、后台杂务 | -| 当前会话 | `current` | 在创建时绑定 | 依赖上下文的周期性工作 | -| 自定义会话 | `session:custom-id`| 持久命名会话 | 基于历史持续推进的工作流 | +| 方式 | `--session` 值 | 运行位置 | 最适合 | +| --------------- | ------------------- | ------------------------ | ----------------------------- | +| 主会话 | `main` | 下一次 heartbeat 轮次 | 提醒、系统事件 | +| 独立 | `isolated` | 专用 `cron:` | 报告、后台杂务 | +| 当前会话 | `current` | 绑定到创建时的会话 | 依赖上下文的循环工作 | +| 自定义会话 | `session:custom-id` | 持久化命名会话 | 基于历史逐步推进的工作流 | -**主会话**任务会排入一个系统事件,并可选择唤醒心跳(`--wake now` 或 `--wake next-heartbeat`)。**独立**任务会在一个全新会话中运行专用的智能体轮次。**自定义会话**(`session:xxx`)会在多次运行之间保留上下文,因此适用于像每日站会这类依赖前次摘要持续推进的工作流。 +**主会话**任务会入队一个系统事件,并可选择唤醒 heartbeat(`--wake now` 或 `--wake next-heartbeat`)。**独立**任务会在一个全新会话中运行专用的智能体轮次。**自定义会话**(`session:xxx`)会在多次运行之间保留上下文,从而支持诸如基于前一天摘要继续推进的每日站会等工作流。 -对于独立任务,运行时拆除现在包含针对该 cron 会话的尽力浏览器清理。清理失败会被忽略,因此实际的 cron 结果仍然优先。 +对于独立任务,运行时拆除现在包含了该 cron 会话的尽力式浏览器清理。清理失败会被忽略,以确保实际的 cron 结果仍然优先。 -当独立 cron 运行编排子智能体时,投递也会优先使用最终后代输出,而不是陈旧的父级中间文本。如果后代仍在运行,OpenClaw 会抑制该父级的部分更新,而不是将其发布出去。 +独立 cron 运行还会通过共享的运行时清理路径,释放为该任务创建的所有内置 MCP 运行时实例。这与主会话和自定义会话的 MCP 客户端拆除方式一致,因此独立 cron 任务不会在多次运行之间泄漏 stdio 子进程或长期存活的 MCP 连接。 + +当独立 cron 运行编排子智能体时,投递逻辑也会优先使用最终的后代输出,而不是过时的父级中间文本。如果后代仍在运行,OpenClaw 会抑制该父级的部分更新,而不是直接播报它。 ### 独立任务的负载选项 @@ -100,36 +101,36 @@ Cron 表达式由 [croner](https://github.com/Hexagon/croner) 解析。当 day-o - `--light-context`:跳过工作区引导文件注入 - `--tools exec,read`:限制任务可使用的工具 -`--model` 会为该任务使用所选的允许模型。如果请求的模型不被允许,cron 会记录一条警告,并回退到该任务的智能体/默认模型选择。已配置的回退链仍然适用,但仅有模型覆盖且没有显式按任务设置回退列表时,不会再把智能体主模型作为隐藏的额外重试目标追加进去。 +`--model` 会为该任务使用所选的允许模型。如果请求的模型不被允许,cron 会记录一条警告,并回退到该任务的智能体/默认模型选择。已配置的回退链仍然适用,但如果只是普通的模型覆盖,且没有显式的逐任务回退列表,就不再把智能体主模型作为隐藏的额外重试目标附加进去。 独立任务的模型选择优先级如下: 1. Gmail hook 模型覆盖(当运行来自 Gmail 且该覆盖被允许时) -2. 按任务负载中的 `model` +2. 每个任务负载中的 `model` 3. 已存储的 cron 会话模型覆盖 4. 智能体/默认模型选择 -快速模式也会遵循解析后的实际选择。如果所选模型配置具有 `params.fastMode`,独立 cron 默认会使用它。已存储的会话 `fastMode` 覆盖在任意方向上都仍然优先于配置。 +快速模式也会遵循解析后的 live 选择。如果所选模型配置包含 `params.fastMode`,独立 cron 默认就会使用该设置。已存储的会话 `fastMode` 覆盖在两个方向上都仍然优先生效。 -如果独立运行遇到实时模型切换交接,cron 会使用切换后的提供商/模型进行重试,并在重试前持久化该实时选择。当切换同时携带新的 auth profile 时,cron 也会持久化该 auth profile 覆盖。重试次数是有上限的:初始尝试加上 2 次切换重试之后,cron 会中止,而不是无限循环。 +如果独立运行遇到 live 模型切换交接,cron 会使用切换后的 provider/模型重试,并在重试前持久化该 live 选择。如果切换同时携带新的凭证配置文件,cron 也会持久化该凭证配置文件覆盖。重试次数是有限的:在初始尝试加上 2 次切换重试之后,cron 会中止,而不是无限循环。 ## 投递与输出 -| 模式 | 行为说明 | -| ---------- | --------------------------------------------------------------- | -| `announce` | 如果智能体没有发送,则回退并将最终文本投递到目标 | -| `webhook` | 将完成事件负载以 POST 方式发送到某个 URL | -| `none` | 运行器不做回退投递 | +| 模式 | 行为说明 | +| ---------- | ------------------------------------------------------------- | +| `announce` | 如果智能体未发送,则回退投递最终文本到目标 | +| `webhook` | 将完成事件负载以 POST 方式发送到某个 URL | +| `none` | 运行器不执行回退投递 | -使用 `--announce --channel telegram --to "-1001234567890"` 可投递到渠道。对于 Telegram forum topics,请使用 `-1001234567890:topic:123`。Slack/Discord/Mattermost 目标应使用显式前缀(`channel:`、`user:`)。 +使用 `--announce --channel telegram --to "-1001234567890"` 可投递到渠道。对于 Telegram 论坛话题,请使用 `-1001234567890:topic:123`。Slack/Discord/Mattermost 目标应使用显式前缀(`channel:`、`user:`)。 -对于独立任务,聊天投递是共享的。如果有可用聊天路由,即使任务使用了 `--no-deliver`,智能体也可以使用 `message` 工具。如果智能体发送到了已配置/当前目标,OpenClaw 会跳过回退 announce。否则,`announce`、`webhook` 和 `none` 只控制运行器如何在智能体轮次结束后处理最终回复。 +对于独立任务,聊天投递是共享的。如果聊天路由可用,智能体即使在任务使用 `--no-deliver` 时也可以使用 `message` 工具。如果智能体发送到了已配置/当前目标,OpenClaw 就会跳过回退 announce。否则,`announce`、`webhook` 和 `none` 只控制运行器在智能体轮次结束后如何处理最终回复。 失败通知遵循单独的目标路径: -- `cron.failureDestination` 设置失败通知的全局默认目标。 +- `cron.failureDestination` 设置失败通知的全局默认值。 - `job.delivery.failureDestination` 可按任务覆盖该设置。 -- 如果两者都未设置,且任务本身已通过 `announce` 投递,失败通知现在会回退到该主 announce 目标。 +- 如果两者都未设置,而该任务本身已通过 `announce` 投递,则失败通知现在会回退到该主 announce 目标。 - `delivery.failureDestination` 仅在 `sessionTarget="isolated"` 的任务上受支持,除非主投递模式是 `webhook`。 ## CLI 示例 @@ -145,7 +146,7 @@ openclaw cron add \ --wake now ``` -带投递的周期性独立任务: +带投递的循环独立任务: ```bash openclaw cron add \ @@ -175,7 +176,7 @@ openclaw cron add \ ## Webhooks -Gateway 网关可以暴露 HTTP webhook 端点以接收外部触发器。在配置中启用: +Gateway 网关可以暴露 HTTP webhook 端点,用于外部触发器。在配置中启用: ```json5 { @@ -187,18 +188,18 @@ Gateway 网关可以暴露 HTTP webhook 端点以接收外部触发器。在配 } ``` -### 认证 +### 身份验证 -每个请求都必须通过请求头包含 hook token: +每个请求都必须通过请求头携带 hook token: - `Authorization: Bearer `(推荐) - `x-openclaw-token: ` -不接受查询字符串 token。 +查询字符串中的 token 会被拒绝。 ### POST /hooks/wake -为主会话排入一个系统事件: +为主会话入队一个系统事件: ```bash curl -X POST http://127.0.0.1:18789/hooks/wake \ @@ -225,23 +226,23 @@ curl -X POST http://127.0.0.1:18789/hooks/agent \ ### 映射 hook(POST /hooks/\) -自定义 hook 名称通过配置中的 `hooks.mappings` 解析。映射可以通过模板或代码转换,将任意负载转换为 `wake` 或 `agent` 动作。 +自定义 hook 名称会通过配置中的 `hooks.mappings` 解析。映射可以通过模板或代码转换,将任意负载转换为 `wake` 或 `agent` 动作。 ### 安全性 -- 将 hook 端点放在 loopback、tailnet 或可信反向代理之后。 -- 使用专用 hook token;不要复用 gateway 认证 token。 -- 将 `hooks.path` 设为专用子路径;`/` 会被拒绝。 +- 将 hook 端点放在 loopback、tailnet 或受信任的反向代理之后。 +- 使用专用的 hook token;不要复用 gateway 身份验证 token。 +- 将 `hooks.path` 放在专用子路径下;`/` 会被拒绝。 - 设置 `hooks.allowedAgentIds` 以限制显式 `agentId` 路由。 -- 保持 `hooks.allowRequestSessionKey=false`,除非你确实需要由调用方选择会话。 -- 如果你启用了 `hooks.allowRequestSessionKey`,也请同时设置 `hooks.allowedSessionKeyPrefixes` 来约束允许的会话键形态。 +- 除非你确实需要由调用方选择会话,否则请保持 `hooks.allowRequestSessionKey=false`。 +- 如果你启用了 `hooks.allowRequestSessionKey`,也要同时设置 `hooks.allowedSessionKeyPrefixes`,以约束允许的会话键形态。 - 默认情况下,hook 负载会被安全边界包装。 ## Gmail PubSub 集成 通过 Google PubSub 将 Gmail 收件箱触发器接入 OpenClaw。 -**前置条件**:`gcloud` CLI、`gog`(gogcli)、已启用 OpenClaw hooks,以及用于公共 HTTPS 端点的 Tailscale。 +**前提条件**:`gcloud` CLI、`gog`(gogcli)、已启用 OpenClaw hooks,以及用于公共 HTTPS 端点的 Tailscale。 ### 向导设置(推荐) @@ -249,15 +250,15 @@ curl -X POST http://127.0.0.1:18789/hooks/agent \ openclaw webhooks gmail setup --account openclaw@gmail.com ``` -这会写入 `hooks.gmail` 配置、启用 Gmail 预设,并使用 Tailscale Funnel 作为推送端点。 +这会写入 `hooks.gmail` 配置,启用 Gmail 预设,并使用 Tailscale Funnel 作为推送端点。 ### Gateway 网关自动启动 -当 `hooks.enabled=true` 且设置了 `hooks.gmail.account` 时,Gateway 网关会在启动时运行 `gog gmail watch serve` 并自动续订 watch。设置 `OPENCLAW_SKIP_GMAIL_WATCHER=1` 可选择退出。 +当 `hooks.enabled=true` 且设置了 `hooks.gmail.account` 时,Gateway 网关会在启动时启动 `gog gmail watch serve`,并自动续订 watch。设置 `OPENCLAW_SKIP_GMAIL_WATCHER=1` 可选择退出此行为。 ### 手动一次性设置 -1. 选择 `gog` 所使用 OAuth 客户端所属的 GCP 项目: +1. 选择由 `gog` 使用的 OAuth 客户端所属的 GCP 项目: ```bash gcloud auth login @@ -265,7 +266,7 @@ gcloud config set project gcloud services enable gmail.googleapis.com pubsub.googleapis.com ``` -2. 创建 topic 并授予 Gmail 推送权限: +2. 创建主题并授予 Gmail 推送权限: ```bash gcloud pubsub topics create gog-gmail-watch @@ -328,9 +329,9 @@ openclaw cron edit --clear-agent 模型覆盖说明: - `openclaw cron add|edit --model ...` 会更改任务所选的模型。 -- 如果该模型被允许,那个确切的提供商/模型就会传递到独立智能体运行中。 +- 如果该模型被允许,独立智能体运行将使用这个精确的 provider/模型。 - 如果不被允许,cron 会发出警告,并回退到任务的智能体/默认模型选择。 -- 已配置的回退链仍然适用,但普通的 `--model` 覆盖若没有显式的按任务回退列表,将不再静默回落到智能体主模型作为额外重试目标。 +- 已配置的回退链仍然适用,但普通的 `--model` 覆盖如果没有显式的逐任务回退列表,就不再静默回落到智能体主模型作为额外的重试目标。 ## 配置 @@ -352,19 +353,19 @@ openclaw cron edit --clear-agent } ``` -运行时状态 sidecar 由 `cron.store` 推导得出:像 `~/clawd/cron/jobs.json` 这样的 `.json` 存储会使用 `~/clawd/cron/jobs-state.json`,而没有 `.json` 后缀的存储路径则会追加 `-state.json`。 +运行时状态 sidecar 由 `cron.store` 推导而来:像 `~/clawd/cron/jobs.json` 这样的 `.json` 存储会使用 `~/clawd/cron/jobs-state.json`,而没有 `.json` 后缀的存储路径则会追加 `-state.json`。 禁用 cron:`cron.enabled: false` 或 `OPENCLAW_SKIP_CRON=1`。 **一次性任务重试**:瞬时错误(速率限制、过载、网络、服务器错误)最多重试 3 次,并使用指数退避。永久性错误会立即禁用。 -**周期性任务重试**:重试之间使用指数退避(30 秒到 60 分钟)。在下一次成功运行后,退避会重置。 +**循环任务重试**:重试之间使用指数退避(30 秒到 60 分钟)。下一次成功运行后会重置退避状态。 **维护**:`cron.sessionRetention`(默认 `24h`)会清理独立运行的会话条目。`cron.runLog.maxBytes` / `cron.runLog.keepLines` 会自动清理运行日志文件。 ## 故障排除 -### 命令阶梯 +### 命令排查顺序 ```bash openclaw status @@ -380,27 +381,27 @@ openclaw doctor ### Cron 未触发 - 检查 `cron.enabled` 和 `OPENCLAW_SKIP_CRON` 环境变量。 -- 确认 Gateway 网关在持续运行。 -- 对于 `cron` 调度,确认时区(`--tz`)与主机时区是否一致。 -- 运行输出中的 `reason: not-due` 表示手动运行通过 `openclaw cron run --due` 检查时,该任务尚未到期。 +- 确认 Gateway 网关正在持续运行。 +- 对于 `cron` 调度,请核对时区(`--tz`)与主机时区是否一致。 +- 运行输出中的 `reason: not-due` 表示你通过 `openclaw cron run --due` 检查了手动运行,但该任务尚未到期。 ### Cron 已触发但没有投递 -- 投递模式 `none` 表示不应期待运行器执行回退发送。若有可用聊天路由,智能体仍然可以通过 `message` 工具直接发送。 -- 缺少/无效的投递目标(`channel`/`to`)表示出站发送已被跳过。 -- 渠道认证错误(`unauthorized`、`Forbidden`)表示投递被凭证阻止。 -- 如果独立运行只返回静默 token(`NO_REPLY` / `no_reply`),OpenClaw 会抑制直接出站投递,也会抑制回退的排队摘要路径,因此不会向聊天回发任何内容。 -- 如果应该由智能体自己向用户发送消息,请检查该任务是否有可用路由(带先前聊天记录的 `channel: "last"`,或显式的渠道/目标)。 +- 投递模式为 `none` 表示不应期待运行器执行回退发送。如果聊天路由可用,智能体仍可通过 `message` 工具直接发送。 +- 投递目标缺失/无效(`channel`/`to`)表示已跳过出站发送。 +- 渠道身份验证错误(`unauthorized`、`Forbidden`)表示投递被凭证阻止。 +- 如果独立运行只返回静默 token(`NO_REPLY` / `no_reply`),OpenClaw 会抑制直接的出站投递,也会抑制回退的排队摘要路径,因此不会有任何内容发回聊天。 +- 如果智能体应自行向用户发送消息,请检查该任务是否具有可用路由(带有先前聊天记录的 `channel: "last"`,或显式的渠道/目标)。 ### 时区注意事项 -- 不带 `--tz` 的 cron 使用 gateway 主机时区。 +- 不带 `--tz` 的 cron 会使用 Gateway 网关主机时区。 - 不带时区的 `at` 调度会被视为 UTC。 -- 心跳 `activeHours` 使用已配置的时区解析。 +- Heartbeat 的 `activeHours` 使用已配置的时区解析。 ## 相关内容 -- [自动化与任务](/zh-CN/automation) —— 各类自动化机制总览 -- [后台任务](/zh-CN/automation/tasks) —— cron 执行的任务台账 -- [Heartbeat](/zh-CN/gateway/heartbeat) —— 周期性的主会话轮次 -- [时区](/zh-CN/concepts/timezone) —— 时区配置 +- [自动化与任务](/zh-CN/automation) — 一览所有自动化机制 +- [后台任务](/zh-CN/automation/tasks) — cron 执行的任务账本 +- [Heartbeat](/zh-CN/gateway/heartbeat) — 周期性的主会话轮次 +- [时区](/zh-CN/concepts/timezone) — 时区配置 diff --git a/docs/zh-CN/channels/discord.md b/docs/zh-CN/channels/discord.md index d84b76249..0468ebe81 100644 --- a/docs/zh-CN/channels/discord.md +++ b/docs/zh-CN/channels/discord.md @@ -4,17 +4,17 @@ read_when: summary: Discord 机器人支持状态、功能和配置 title: Discord x-i18n: - generated_at: "2026-04-22T19:54:31Z" + generated_at: "2026-04-23T07:03:23Z" model: gpt-5.4 provider: openai - source_hash: 1a500da6a2aa080f1c38efd3510bef000abc61059fdc0ff3cb14a62ad292cf9a + source_hash: 0bee2c419651701f7ab57e46a4c0c473c83596eb9bd2156bac3c6117513236ab source_path: channels/discord.md workflow: 15 --- # Discord(Bot API) -状态:已就绪,可通过官方 Discord gateway 支持私信和服务器频道。 +状态:已就绪,可通过官方 Discord Gateway 网关用于私信和服务器频道。 @@ -30,45 +30,45 @@ x-i18n: ## 快速开始 -你需要创建一个包含机器人的新应用,将机器人添加到你的服务器,并将其与 OpenClaw 配对。我们建议把你的机器人添加到你自己的私有服务器。如果你还没有,可以先[创建一个](https://support.discord.com/hc/en-us/articles/204849977-How-do-I-create-a-server)(选择 **Create My Own > For me and my friends**)。 +你需要创建一个带机器人的新应用,将机器人添加到你的服务器,并将其与 OpenClaw 配对。我们建议把你的机器人添加到你自己的私有服务器。如果你还没有服务器,请先[创建一个](https://support.discord.com/hc/en-us/articles/204849977-How-do-I-create-a-server)(选择 **Create My Own > For me and my friends**)。 - 前往 [Discord Developer Portal](https://discord.com/developers/applications),点击 **New Application**。将其命名为类似 “OpenClaw” 的名称。 + 前往 [Discord Developer Portal](https://discord.com/developers/applications),然后点击 **New Application**。给它起一个类似 “OpenClaw” 的名字。 点击侧边栏中的 **Bot**。将 **Username** 设置为你对 OpenClaw 智能体的称呼。 - 仍然在 **Bot** 页面,向下滚动到 **Privileged Gateway Intents** 并启用: + 仍在 **Bot** 页面时,向下滚动到 **Privileged Gateway Intents**,并启用: - **Message Content Intent**(必需) - - **Server Members Intent**(推荐;角色允许列表和名称到 ID 匹配所必需) - - **Presence Intent**(可选;仅在需要在线状态更新时才需要) + - **Server Members Intent**(推荐;角色 allowlist 和名称到 ID 匹配时必需) + - **Presence Intent**(可选;仅在需要在线状态更新时使用) - 向上滚动回 **Bot** 页面顶部并点击 **Reset Token**。 + 向上滚动回 **Bot** 页面顶部,点击 **Reset Token**。 - 尽管名字如此,这会生成你的第一个令牌——并不会“重置”任何东西。 + 尽管名字叫这样,但这里会生成你的第一个令牌 —— 并没有任何内容被“重置”。 - 复制该令牌并将其保存在某处。这就是你的 **Bot Token**,你很快就会用到它。 + 复制该令牌并保存到某处。这就是你的 **Bot Token**,你很快就会用到它。 - 点击侧边栏中的 **OAuth2**。你将生成一个具有正确权限的邀请 URL,以便将机器人添加到你的服务器。 + 点击侧边栏中的 **OAuth2**。你将生成一个带有正确权限的邀请 URL,用于把机器人添加到你的服务器。 - 向下滚动到 **OAuth2 URL Generator** 并启用: + 向下滚动到 **OAuth2 URL Generator**,并启用: - `bot` - `applications.commands` - 下方会出现一个 **Bot Permissions** 部分。至少启用以下权限: + 下方会出现 **Bot Permissions** 区域。至少启用: **General Permissions** - View Channels @@ -79,31 +79,31 @@ x-i18n: - Attach Files - Add Reactions(可选) - 这是普通文本频道的基础权限集合。如果你计划在 Discord 线程中发帖,包括会创建或继续线程的论坛或媒体频道工作流,还需启用 **Send Messages in Threads**。 - 复制底部生成的 URL,将其粘贴到浏览器中,选择你的服务器,然后点击 **Continue** 进行连接。现在你应该能在 Discord 服务器中看到你的机器人。 + 这是普通文本频道的基础权限集。如果你计划在 Discord 帖子串中发帖,包括会创建或继续帖子串的 forum 或 media 渠道工作流,还需要启用 **Send Messages in Threads**。 + 复制底部生成的 URL,粘贴到浏览器中,选择你的服务器,然后点击 **Continue** 进行连接。现在你应该能在 Discord 服务器中看到你的机器人。 - 回到 Discord 应用,你需要启用开发者模式,这样你才能复制内部 ID。 + 回到 Discord 应用中,你需要启用开发者模式,这样才能复制内部 ID。 1. 点击 **User Settings**(头像旁边的齿轮图标)→ **Advanced** → 打开 **Developer Mode** - 2. 在侧边栏中右键点击你的**服务器图标** → **Copy Server ID** - 3. 右键点击你自己的**头像** → **Copy User ID** + 2. 在侧边栏中右键点击你的 **server icon** → **Copy Server ID** + 3. 右键点击你自己的 **avatar** → **Copy User ID** - 将你的 **Server ID** 和 **User ID** 与 Bot Token 一起保存——下一步你会把这三项都发送给 OpenClaw。 + 将你的 **Server ID** 和 **User ID** 与 Bot Token 一起保存 —— 下一步你会把这三项都提供给 OpenClaw。 - 为了让配对正常工作,Discord 需要允许你的机器人向你发送私信。右键点击你的**服务器图标** → **Privacy Settings** → 打开 **Direct Messages**。 + 要让配对正常工作,Discord 需要允许你的机器人向你发送私信。右键点击你的 **server icon** → **Privacy Settings** → 打开 **Direct Messages**。 - 这会允许服务器成员(包括机器人)向你发送私信。如果你想通过 Discord 私信使用 OpenClaw,请保持启用。如果你只打算使用服务器频道,则可在配对完成后禁用私信。 + 这样服务器成员(包括机器人)就可以向你发送私信。如果你想在 OpenClaw 中使用 Discord 私信,请保持该选项启用。如果你只打算使用服务器频道,那么在完成配对后可以关闭私信。 - 你的 Discord 机器人令牌是机密信息(类似密码)。在向你的智能体发送消息之前,请先在运行 OpenClaw 的机器上设置它。 + 你的 Discord 机器人令牌是机密信息(类似密码)。在给你的智能体发消息之前,请先在运行 OpenClaw 的机器上设置它。 ```bash export DISCORD_BOT_TOKEN="YOUR_BOT_TOKEN" @@ -113,7 +113,7 @@ openclaw config set channels.discord.enabled true --strict-json openclaw gateway ``` - 如果 OpenClaw 已作为后台服务运行,请通过 OpenClaw Mac 应用重新启动,或停止并重新启动 `openclaw gateway run` 进程。 + 如果 OpenClaw 已经作为后台服务运行,请通过 OpenClaw Mac 应用重启它,或者停止并重新启动 `openclaw gateway run` 进程。 @@ -121,9 +121,9 @@ openclaw gateway - 在任何现有渠道(例如 Telegram)中与你的 OpenClaw 智能体聊天,并告诉它。如果 Discord 是你的第一个渠道,请改用 CLI / 配置标签页。 + 在任何现有渠道(例如 Telegram)上与你的 OpenClaw 智能体聊天,并告诉它。如果 Discord 是你的第一个渠道,请改用 CLI / config 标签页。 - > “我已经在配置中设置了 Discord 机器人令牌。请使用 User ID `` 和 Server ID `` 完成 Discord 设置。” + > “我已经在配置中设置好了 Discord 机器人令牌。请使用 User ID `` 和 Server ID `` 完成 Discord 设置。” 如果你更喜欢基于文件的配置,请设置: @@ -149,7 +149,7 @@ openclaw gateway DISCORD_BOT_TOKEN=... ``` - 支持明文 `token` 值。`channels.discord.token` 也支持跨 env/file/exec 提供商的 SecretRef 值。参见 [Secrets Management](/zh-CN/gateway/secrets)。 + 支持纯文本 `token` 值。`channels.discord.token` 也支持跨 env/file/exec 提供商的 SecretRef 值。请参阅 [Secrets Management](/zh-CN/gateway/secrets)。 @@ -161,7 +161,7 @@ DISCORD_BOT_TOKEN=... - 在你现有的渠道中把配对码发给你的智能体: + 在你现有的渠道中,把配对码发送给你的智能体: > “批准这个 Discord 配对码:``” @@ -175,29 +175,29 @@ openclaw pairing approve discord - 配对码将在 1 小时后过期。 + 配对码会在 1 小时后过期。 - 现在你应该可以通过私信在 Discord 中与你的智能体聊天了。 + 现在你应该已经可以通过私信在 Discord 中与你的智能体聊天了。 -令牌解析具有账户感知能力。配置中的令牌值优先于环境变量回退。`DISCORD_BOT_TOKEN` 仅用于默认账户。 -对于高级出站调用(消息工具/渠道操作),会对该次调用使用显式的每次调用 `token`。这适用于发送以及读取/探测类操作(例如 read/search/fetch/thread/pins/permissions)。账户策略/重试设置仍来自活动运行时快照中所选账户。 +令牌解析是账户感知的。配置中的令牌值优先于环境变量回退。`DISCORD_BOT_TOKEN` 仅用于默认账户。 +对于高级出站调用(消息工具/渠道操作),会为该次调用使用显式的逐调用 `token`。这适用于发送以及读取/探测类操作(例如 read/search/fetch/thread/pins/permissions)。账户策略和重试设置仍然来自活动运行时快照中所选的账户。 ## 推荐:设置服务器工作区 -当私信可用后,你可以将 Discord 服务器设置为完整工作区,其中每个频道都会获得各自独立的智能体会话和上下文。对于只有你和机器人参与的私有服务器,我们推荐这样做。 +私信可用后,你可以把 Discord 服务器设置为一个完整工作区,其中每个频道都会获得自己的智能体会话和独立上下文。对于只有你和机器人使用的私有服务器,我们推荐这样做。 - - 这会让你的智能体能够在服务器上的任何频道中回复,而不仅仅是私信。 + + 这样你的智能体就可以在服务器中的任意频道内响应,而不仅仅是私信。 - > “将我的 Discord Server ID `` 添加到服务器允许列表” + > “把我的 Discord Server ID `` 添加到服务器 allowlist” @@ -223,14 +223,14 @@ openclaw pairing approve discord - 默认情况下,你的智能体只有在被 @ 提及时才会在服务器频道中回复。对于私有服务器,你大概率会希望它对每条消息都进行回复。 + 默认情况下,你的智能体只有在服务器频道中被 @ 提及时才会回复。对于私有服务器,你可能更希望它对每条消息都进行回复。 - > “允许我的智能体在这个服务器中无需被 @ 提及也能回复” + > “允许我的智能体在这个服务器中回复,而不需要被 @ 提及” - 在你的服务器配置中设置 `requireMention: false`: + 在你的服务器配置中将 `requireMention: false` 设置为: ```json5 { @@ -259,68 +259,68 @@ openclaw pairing approve discord > “当我在 Discord 频道中提问时,如果你需要来自 MEMORY.md 的长期上下文,请使用 memory_search 或 memory_get。” - 如果你需要在每个频道中共享上下文,请将稳定的说明放入 `AGENTS.md` 或 `USER.md`(它们会注入到每个会话中)。将长期笔记保存在 `MEMORY.md` 中,并按需通过记忆工具访问。 + 如果你需要在每个频道中共享上下文,请把稳定的指令放在 `AGENTS.md` 或 `USER.md` 中(它们会注入到每个会话)。把长期笔记保存在 `MEMORY.md` 中,并在需要时通过 memory 工具访问它们。 -现在,在你的 Discord 服务器中创建一些频道并开始聊天。你的智能体可以看到频道名称,并且每个频道都会获得各自隔离的会话——因此你可以设置 `#coding`、`#home`、`#research`,或任何适合你工作流的频道。 +现在,在你的 Discord 服务器中创建一些频道并开始聊天吧。你的智能体可以看到频道名称,并且每个频道都会获得自己隔离的会话 —— 因此你可以设置 `#coding`、`#home`、`#research`,或者任何适合你工作流的频道。 ## 运行时模型 -- Gateway 网关拥有 Discord 连接。 -- 回复路由是确定性的:来自 Discord 的入站回复会返回到 Discord。 +- Gateway 网关负责 Discord 连接。 +- 回复路由是确定性的:来自 Discord 的入站消息会回复到 Discord。 - 默认情况下(`session.dmScope=main`),私聊共享智能体主会话(`agent:main:main`)。 - 服务器频道使用隔离的会话键(`agent::discord:channel:`)。 -- 群组私信默认会被忽略(`channels.discord.dm.groupEnabled=false`)。 -- 原生斜杠命令在隔离的命令会话中运行(`agent::discord:slash:`),同时仍携带 `CommandTargetSessionKey` 指向被路由的对话会话。 +- 默认忽略群组私信(`channels.discord.dm.groupEnabled=false`)。 +- 原生斜杠命令在隔离的命令会话中运行(`agent::discord:slash:`),同时仍会将 `CommandTargetSessionKey` 传递到路由后的对话会话。 -## 论坛频道 +## forum 渠道 -Discord 论坛和媒体频道只接受线程帖子。OpenClaw 支持两种创建方式: +Discord forum 和 media 渠道只接受帖子串。OpenClaw 支持两种创建方式: -- 向论坛父级频道(`channel:`)发送消息以自动创建线程。线程标题使用你消息中的第一行非空内容。 -- 使用 `openclaw message thread create` 直接创建线程。对于论坛频道,不要传递 `--message-id`。 +- 向 forum 父频道(`channel:`)发送消息以自动创建帖子串。帖子串标题使用你消息中的第一行非空内容。 +- 使用 `openclaw message thread create` 直接创建帖子串。对于 forum 渠道,不要传递 `--message-id`。 -示例:向论坛父级频道发送消息以创建线程 +示例:发送到 forum 父频道以创建帖子串 ```bash openclaw message send --channel discord --target channel: \ --message "Topic title\nBody of the post" ``` -示例:显式创建论坛线程 +示例:显式创建 forum 帖子串 ```bash openclaw message thread create --channel discord --target channel: \ --thread-name "Topic title" --message "Body of the post" ``` -论坛父级频道不接受 Discord 组件。如果你需要组件,请发送到线程本身(`channel:`)。 +forum 父频道不接受 Discord components。如果你需要 components,请发送到帖子串本身(`channel:`)。 -## 交互式组件 +## 交互式 components -OpenClaw 支持在智能体消息中使用 Discord components v2 容器。请使用带有 `components` 负载的消息工具。交互结果会作为普通入站消息路由回智能体,并遵循现有的 Discord `replyToMode` 设置。 +OpenClaw 为智能体消息支持 Discord components v2 容器。请使用带有 `components` 负载的消息工具。交互结果会像普通入站消息一样路由回智能体,并遵循现有的 Discord `replyToMode` 设置。 -支持的区块: +支持的块: - `text`、`section`、`separator`、`actions`、`media-gallery`、`file` -- 操作行最多允许 5 个按钮,或单个选择菜单 +- 操作行最多允许 5 个按钮或单个选择菜单 - 选择类型:`string`、`user`、`role`、`mentionable`、`channel` -默认情况下,组件为单次使用。设置 `components.reusable=true` 可允许按钮、选择器和表单在过期前被多次使用。 +默认情况下,components 为一次性使用。设置 `components.reusable=true` 可允许按钮、选择器和表单在过期前被多次使用。 -若要限制谁可以点击按钮,请在该按钮上设置 `allowedUsers`(Discord 用户 ID、标签或 `*`)。配置后,不匹配的用户会收到一条临时拒绝消息。 +如果要限制谁可以点击按钮,请在该按钮上设置 `allowedUsers`(Discord 用户 ID、标签,或 `*`)。配置后,不匹配的用户会收到一条仅自己可见的拒绝消息。 -`/model` 和 `/models` 斜杠命令会打开一个交互式模型选择器,其中包含提供商和模型下拉菜单,以及一个提交步骤。除非设置 `commands.modelsWrite=false`,否则 `/models add` 也支持通过聊天添加新的提供商/模型条目,而且新添加的模型无需重启 Gateway 网关即可显示。选择器回复是临时的,且只有调用该命令的用户可以使用。 +`/model` 和 `/models` 斜杠命令会打开一个交互式模型选择器,其中包含提供商和模型下拉菜单,以及一个 Submit 步骤。除非设置了 `commands.modelsWrite=false`,否则 `/models add` 也支持通过聊天添加新的提供商/模型条目,新增模型无需重启 Gateway 网关即可显示。选择器回复为仅自己可见,并且只有调用它的用户可以使用。 文件附件: -- `file` 区块必须指向一个附件引用(`attachment://`) +- `file` 块必须指向一个附件引用(`attachment://`) - 通过 `media`/`path`/`filePath` 提供附件(单文件);多个文件请使用 `media-gallery` -- 当上传名称需要与附件引用一致时,使用 `filename` 覆盖上传名称 +- 当上传名称需要与附件引用匹配时,请使用 `filename` 覆盖上传名称 模态表单: @@ -393,20 +393,20 @@ OpenClaw 支持在智能体消息中使用 Discord components v2 容器。请使 - `open`(要求 `channels.discord.allowFrom` 包含 `"*"`;旧版:`channels.discord.dm.allowFrom`) - `disabled` - 如果私信策略不是 open,未知用户会被拦截(或在 `pairing` 模式下被提示进行配对)。 + 如果私信策略不是 open,未知用户会被阻止(或在 `pairing` 模式下被提示进行配对)。 多账户优先级: - - `channels.discord.accounts.default.allowFrom` 仅应用于 `default` 账户。 - - 当具名账户自身未设置 `allowFrom` 时,它们会继承 `channels.discord.allowFrom`。 + - `channels.discord.accounts.default.allowFrom` 仅适用于 `default` 账户。 + - 当具名账户自己的 `allowFrom` 未设置时,会继承 `channels.discord.allowFrom`。 - 具名账户不会继承 `channels.discord.accounts.default.allowFrom`。 用于投递的私信目标格式: - `user:` - - `<@id>` mention + - `<@id>` 提及 - 裸数字 ID 含义不明确,会被拒绝,除非显式提供用户/频道目标类型。 + 裸数字 ID 存在歧义,除非提供了明确的用户/频道目标类型,否则会被拒绝。 @@ -417,16 +417,16 @@ OpenClaw 支持在智能体消息中使用 Discord components v2 容器。请使 - `allowlist` - `disabled` - 当存在 `channels.discord` 时,安全的基线设置是 `allowlist`。 + 当存在 `channels.discord` 时,安全的基线是 `allowlist`。 `allowlist` 行为: - 服务器必须匹配 `channels.discord.guilds`(优先使用 `id`,也接受 slug) - - 可选的发送者允许列表:`users`(推荐稳定 ID)和 `roles`(仅角色 ID);如果其中任一项已配置,则发送者在匹配 `users` 或 `roles` 时即被允许 - - 直接名称/标签匹配默认禁用;仅在紧急兼容模式下启用 `channels.discord.dangerouslyAllowNameMatching: true` - - `users` 支持名称/标签,但 ID 更安全;当使用名称/标签条目时,`openclaw security audit` 会发出警告 + - 可选的发送者 allowlist:`users`(推荐使用稳定 ID)和 `roles`(仅角色 ID);如果配置了任一项,则当发送者匹配 `users` 或 `roles` 时即被允许 + - 默认禁用直接名称/标签匹配;只有在紧急兼容模式下才启用 `channels.discord.dangerouslyAllowNameMatching: true` + - `users` 支持名称/标签,但 ID 更安全;使用名称/标签条目时,`openclaw security audit` 会发出警告 - 如果某个服务器配置了 `channels`,则未列出的频道会被拒绝 - - 如果某个服务器没有 `channels` 块,则该允许列表服务器中的所有频道都被允许 + - 如果某个服务器没有 `channels` 块,则该 allowlist 服务器中的所有频道都被允许 示例: @@ -452,33 +452,33 @@ OpenClaw 支持在智能体消息中使用 Discord components v2 容器。请使 } ``` - 如果你仅设置了 `DISCORD_BOT_TOKEN`,但没有创建 `channels.discord` 块,则运行时回退为 `groupPolicy="allowlist"`(日志中会有警告),即使 `channels.defaults.groupPolicy` 是 `open` 也是如此。 + 如果你只设置了 `DISCORD_BOT_TOKEN`,但没有创建 `channels.discord` 块,则运行时回退为 `groupPolicy="allowlist"`(日志中会有警告),即使 `channels.defaults.groupPolicy` 是 `open` 也是如此。 - 服务器消息默认受提及门控限制。 + 默认情况下,服务器消息受提及门控。 提及检测包括: - 显式提及机器人 - 已配置的提及模式(`agents.list[].groupChat.mentionPatterns`,回退为 `messages.groupChat.mentionPatterns`) - - 在支持场景中的隐式回复机器人行为 + - 在受支持场景中的隐式回复机器人行为 `requireMention` 按服务器/频道配置(`channels.discord.guilds...`)。 - `ignoreOtherMentions` 可选地丢弃那些提及了其他用户/角色但未提及机器人的消息(不包括 @everyone/@here)。 + `ignoreOtherMentions` 可选择丢弃那些提及了其他用户/角色但没有提及机器人的消息(不包括 @everyone/@here)。 群组私信: - 默认:忽略(`dm.groupEnabled=false`) - - 可选允许列表:通过 `dm.groupChannels`(频道 ID 或 slug) + - 可选:通过 `dm.groupChannels` allowlist 允许(频道 ID 或 slug) ### 基于角色的智能体路由 -使用 `bindings[].match.roles` 可根据角色 ID 将 Discord 服务器成员路由到不同智能体。基于角色的绑定仅接受角色 ID,并且会在 peer 或 parent-peer 绑定之后、guild-only 绑定之前进行评估。如果某个绑定还设置了其他匹配字段(例如 `peer` + `guildId` + `roles`),则所有已配置字段都必须匹配。 +使用 `bindings[].match.roles` 按角色 ID 将 Discord 服务器成员路由到不同的智能体。基于角色的绑定仅接受角色 ID,并且会在 peer 或 parent-peer 绑定之后、guild-only 绑定之前进行评估。如果某个绑定还设置了其他匹配字段(例如 `peer` + `guildId` + `roles`),则所有已配置字段都必须匹配。 ```json5 { @@ -519,7 +519,7 @@ OpenClaw 支持在智能体消息中使用 Discord components v2 容器。请使 - Message Content Intent - Server Members Intent(推荐) - Presence intent 是可选的,只有在你想接收在线状态更新时才需要。设置机器人在线状态(`setPresence`)不需要为成员启用在线状态更新。 + Presence intent 是可选的,只有在你希望接收在线状态更新时才需要。设置机器人在线状态(`setPresence`)并不要求为成员启用在线状态更新。 @@ -539,8 +539,8 @@ OpenClaw 支持在智能体消息中使用 Discord components v2 容器。请使 - Attach Files - Add Reactions(可选) - 这是普通文本频道的基础权限集合。如果你计划在 Discord 线程中发帖,包括会创建或继续线程的论坛或媒体频道工作流,还需启用 **Send Messages in Threads**。 - 除非明确需要,否则避免授予 `Administrator`。 + 这是普通文本频道的基础权限集。如果你计划在 Discord 帖子串中发帖,包括会创建或继续帖子串的 forum 或 media 渠道工作流,还需要启用 **Send Messages in Threads**。 + 除非明确需要,否则避免使用 `Administrator`。 @@ -551,20 +551,20 @@ OpenClaw 支持在智能体消息中使用 Discord components v2 容器。请使 - channel ID - user ID - 在 OpenClaw 配置中优先使用数字 ID,以获得可靠的审计和探测结果。 + 在 OpenClaw 配置中优先使用数字 ID,以获得更可靠的审计和探测结果。 -## 原生命令和命令认证 +## 原生命令和命令鉴权 -- `commands.native` 默认为 `"auto"`,并且对 Discord 启用。 +- `commands.native` 默认为 `"auto"`,并且已为 Discord 启用。 - 按渠道覆盖:`channels.discord.commands.native`。 -- `commands.native=false` 会显式清除先前已注册的 Discord 原生命令。 -- 原生命令认证使用与普通消息处理相同的 Discord 允许列表/策略。 -- 对于未获授权的用户,命令在 Discord UI 中仍可能可见;执行时仍会强制执行 OpenClaw 认证,并返回“未获授权”。 +- `commands.native=false` 会显式清除之前已注册的 Discord 原生命令。 +- 原生命令鉴权使用与普通消息处理相同的 Discord allowlist/策略。 +- 对于未获授权的用户,这些命令在 Discord UI 中可能仍然可见;但执行时仍会强制执行 OpenClaw 鉴权,并返回 “not authorized”。 -参见[斜杠命令](/zh-CN/tools/slash-commands)了解命令目录和行为。 +命令目录和行为请参阅[斜杠命令](/zh-CN/tools/slash-commands)。 默认斜杠命令设置: @@ -586,25 +586,25 @@ OpenClaw 支持在智能体消息中使用 Discord components v2 容器。请使 - `all` - `batched` - 注意:`off` 会禁用隐式回复线程行为。显式的 `[[reply_to_*]]` 标签仍然会被处理。 - `first` 总是会将隐式原生回复引用附加到该轮对外发送的第一条 Discord 消息上。 - `batched` 仅在入站轮次是由多条消息去抖合并后的批次时,才附加 Discord 的隐式原生回复引用。当你只希望在含糊不清的突发聊天场景中主要使用原生回复,而不是每个单消息轮次都使用时,这会很有用。 + 注意:`off` 会禁用隐式回复线程。显式的 `[[reply_to_*]]` 标签仍会被遵循。 + `first` 始终会把隐式原生回复引用附加到该轮的第一条 Discord 出站消息上。 + `batched` 仅当入站轮次是由多条消息组成的去抖动批次时,才会附加 Discord 的隐式原生回复引用。当你主要想在含糊不清的突发聊天中使用原生回复,而不是对每一个单消息轮次都使用时,这会很有用。 - 消息 ID 会在上下文/历史中暴露出来,以便智能体定位特定消息。 + 消息 ID 会在上下文/历史记录中呈现,因此智能体可以定位特定消息。 - OpenClaw 可以通过发送临时消息并在文本到达时持续编辑它,来流式显示草稿回复。 + OpenClaw 可以通过发送一条临时消息并在文本到达时编辑它,来流式显示草稿回复。 - `channels.discord.streaming` 控制预览流式传输(`off` | `partial` | `block` | `progress`,默认:`off`)。 - - 默认保持为 `off`,因为 Discord 预览编辑很容易触发速率限制,尤其是在多个机器人或 Gateway 网关共享同一账户或服务器流量时。 + - 默认保持 `off`,因为 Discord 预览编辑很容易触发速率限制,尤其是在多个机器人或 Gateway 网关共享同一账户或服务器流量时。 - 为了跨渠道一致性,接受 `progress`,并在 Discord 上映射为 `partial`。 - `channels.discord.streamMode` 是旧版别名,会被自动迁移。 - `partial` 会在 token 到达时编辑单条预览消息。 - `block` 会输出草稿大小的分块(使用 `draftChunk` 调整大小和断点)。 - 媒体、错误和显式回复的最终消息会取消待处理的预览编辑,而不会在正常投递前刷新临时草稿。 - - `streaming.preview.toolProgress` 控制工具/进度更新是否复用同一条草稿预览消息(默认:`true`)。设为 `false` 可保留独立的工具/进度消息。 + - `streaming.preview.toolProgress` 控制工具/进度更新是否复用同一条草稿预览消息(默认:`true`)。设置为 `false` 可保留单独的工具/进度消息。 示例: @@ -618,7 +618,7 @@ OpenClaw 支持在智能体消息中使用 Discord components v2 容器。请使 } ``` - `block` 模式的分块默认值(会限制在 `channels.discord.textChunkLimit` 范围内): + `block` 模式的默认分块设置(会被限制在 `channels.discord.textChunkLimit` 范围内): ```json5 { @@ -635,17 +635,17 @@ OpenClaw 支持在智能体消息中使用 Discord components v2 容器。请使 } ``` - 预览流式传输仅支持文本;媒体回复会回退到正常投递。 + 预览流式传输仅支持文本;媒体回复会回退为普通投递。 - 注意:预览流式传输与分块流式传输是分开的。当明确为 Discord 启用分块流式传输时,OpenClaw 会跳过预览流,以避免双重流式传输。 + 注意:预览流式传输与分块流式传输是分开的。当为 Discord 显式启用分块流式传输时,OpenClaw 会跳过预览流,以避免重复流式传输。 - + 服务器历史上下文: - `channels.discord.historyLimit` 默认值为 `20` - - 回退值:`messages.groupChat.historyLimit` + - 回退:`messages.groupChat.historyLimit` - `0` 表示禁用 私信历史控制: @@ -653,28 +653,32 @@ OpenClaw 支持在智能体消息中使用 Discord components v2 容器。请使 - `channels.discord.dmHistoryLimit` - `channels.discord.dms[""].historyLimit` - 线程行为: + 帖子串行为: - - Discord 线程会被路由为频道会话 - - 父线程元数据可用于父会话关联 - - 线程配置会继承父频道配置,除非存在线程专用条目 + - Discord 帖子串作为频道会话进行路由 + - 父帖子串元数据可用于父会话关联 + - 除非存在特定于帖子串的条目,否则帖子串配置会继承父频道配置 + - 新创建的自动帖子串是否继承父转录内容,由 `channels.discord.thread.inheritParent` 选择启用(默认 `false`)。当为 `false` 时,新创建的 Discord 帖子串会话会与父频道转录内容隔离;当为 `true` 时,父频道历史会为新帖子串会话提供初始上下文 + - 按账户覆盖位于 `channels.discord.accounts..thread.inheritParent` + - 消息工具的 reaction 除了频道目标外,也可以解析 `user:` 私信目标 + - `channels.discord.guilds..channels..requireMention: false` 会在回复阶段激活回退期间被保留,因此即使运行回复阶段回退,已配置为始终开启的频道仍会保持始终开启 频道主题会作为**不受信任**的上下文注入(而不是作为系统提示词)。 - 回复和引用消息的上下文目前会按接收时的原样保留。 - Discord 允许列表主要用于控制谁可以触发智能体,而不是完整的补充上下文脱敏边界。 + 回复和引用消息上下文目前会按接收时的样子保留。 + Discord allowlist 主要用于限制谁可以触发智能体,而不是完整的补充上下文脱敏边界。 - - Discord 可以将一个线程绑定到某个会话目标,这样该线程中的后续消息会持续路由到同一会话(包括子智能体会话)。 + + Discord 可以将一个帖子串绑定到某个会话目标,这样该帖子串中的后续消息会持续路由到同一个会话(包括子智能体会话)。 命令: - - `/focus ` 将当前/新线程绑定到子智能体/会话目标 - - `/unfocus` 移除当前线程绑定 + - `/focus ` 将当前/新帖子串绑定到一个子智能体/会话目标 + - `/unfocus` 移除当前帖子串绑定 - `/agents` 显示活动运行和绑定状态 - - `/session idle ` 检查/更新已聚焦绑定的不活动自动取消聚焦设置 - - `/session max-age ` 检查/更新已聚焦绑定的硬性最大存活时长 + - `/session idle ` 查看/更新聚焦绑定的空闲自动取消聚焦时间 + - `/session max-age ` 查看/更新聚焦绑定的硬性最大存活时间 配置: @@ -700,20 +704,20 @@ OpenClaw 支持在智能体消息中使用 Discord components v2 容器。请使 } ``` - 注意: + 说明: - `session.threadBindings.*` 设置全局默认值。 - - `channels.discord.threadBindings.*` 覆盖 Discord 行为。 - - `spawnSubagentSessions` 必须为 true,才能为 `sessions_spawn({ thread: true })` 自动创建/绑定线程。 - - `spawnAcpSessions` 必须为 true,才能为 ACP(`/acp spawn ... --thread ...` 或 `sessions_spawn({ runtime: "acp", thread: true })`)自动创建/绑定线程。 - - 如果某个账户禁用了线程绑定,则 `/focus` 和相关线程绑定操作不可用。 + - `channels.discord.threadBindings.*` 会覆盖 Discord 行为。 + - `spawnSubagentSessions` 必须为 true,才能为 `sessions_spawn({ thread: true })` 自动创建/绑定帖子串。 + - `spawnAcpSessions` 必须为 true,才能为 ACP 自动创建/绑定帖子串(`/acp spawn ... --thread ...` 或 `sessions_spawn({ runtime: "acp", thread: true })`)。 + - 如果某个账户禁用了帖子串绑定,则 `/focus` 及相关帖子串绑定操作不可用。 - 参见 [Sub-agents](/zh-CN/tools/subagents)、[ACP Agents](/zh-CN/tools/acp-agents) 和 [Configuration Reference](/zh-CN/gateway/configuration-reference)。 + 请参阅[子智能体](/zh-CN/tools/subagents)、[ACP Agents](/zh-CN/tools/acp-agents) 和[配置参考](/zh-CN/gateway/configuration-reference)。 - 对于稳定的“始终在线” ACP 工作区,可配置指向 Discord 对话的顶层类型化 ACP 绑定。 + 对于稳定的“始终在线” ACP 工作区,可配置顶层的类型化 ACP 绑定,并将其目标指向 Discord 对话。 配置路径: @@ -769,31 +773,31 @@ OpenClaw 支持在智能体消息中使用 Discord components v2 容器。请使 说明: - - `/acp spawn codex --bind here` 会就地绑定当前 Discord 频道或线程,并让后续消息持续路由到同一个 ACP 会话。 - - 这仍可能意味着“启动一个全新的 Codex ACP 会话”,但它本身不会创建新的 Discord 线程。现有频道仍然是聊天界面。 - - Codex 仍可能在自己独立的 `cwd` 或磁盘上的 backend 工作区中运行。该工作区属于运行时状态,而不是 Discord 线程。 - - 线程消息可以继承父频道的 ACP 绑定。 - - 在已绑定的频道或线程中,`/new` 和 `/reset` 会原地重置同一个 ACP 会话。 - - 临时线程绑定仍然可用,并且在生效期间可以覆盖目标解析。 - - 只有当 OpenClaw 需要通过 `--thread auto|here` 创建/绑定子线程时,才需要 `spawnAcpSessions`。对于当前频道中的 `/acp spawn ... --bind here`,则不需要。 + - `/acp spawn codex --bind here` 会就地绑定当前 Discord 频道或帖子串,并使未来的消息持续路由到同一个 ACP 会话。 + - 这仍然可能意味着“启动一个全新的 Codex ACP 会话”,但它本身不会创建新的 Discord 帖子串。现有频道会继续作为聊天界面。 + - Codex 仍然可能在它自己的 `cwd` 或磁盘上的后端工作区中运行。该工作区是运行时状态,而不是 Discord 帖子串。 + - 帖子串消息可以继承父频道的 ACP 绑定。 + - 在已绑定的频道或帖子串中,`/new` 和 `/reset` 会就地重置同一个 ACP 会话。 + - 临时帖子串绑定仍然可用,并且在生效期间可以覆盖目标解析。 + - 只有当 OpenClaw 需要通过 `--thread auto|here` 创建/绑定子帖子串时,才需要 `spawnAcpSessions`。对于当前频道中的 `/acp spawn ... --bind here`,则不需要。 - 参见 [ACP Agents](/zh-CN/tools/acp-agents) 了解绑定行为细节。 + 有关绑定行为的详细信息,请参阅 [ACP Agents](/zh-CN/tools/acp-agents)。 - - 按服务器配置的反应通知模式: + + 按服务器配置的 reaction 通知模式: - `off` - `own`(默认) - `all` - `allowlist`(使用 `guilds..users`) - 反应事件会被转换为系统事件,并附加到被路由的 Discord 会话中。 + Reaction 事件会被转换为系统事件,并附加到路由后的 Discord 会话。 - + `ackReaction` 会在 OpenClaw 处理入站消息时发送一个确认 emoji。 解析顺序: @@ -806,7 +810,7 @@ OpenClaw 支持在智能体消息中使用 Discord components v2 容器。请使 说明: - Discord 接受 unicode emoji 或自定义 emoji 名称。 - - 使用 `""` 可为某个渠道或账户禁用该反应。 + - 使用 `""` 可为某个渠道或账户禁用该 reaction。 @@ -815,7 +819,7 @@ OpenClaw 支持在智能体消息中使用 Discord components v2 容器。请使 这会影响 `/config set|unset` 流程(当命令功能启用时)。 - 禁用方式: + 禁用: ```json5 { @@ -830,7 +834,7 @@ OpenClaw 支持在智能体消息中使用 Discord components v2 容器。请使 - 使用 `channels.discord.proxy` 通过 HTTP(S) 代理路由 Discord gateway WebSocket 流量和启动时的 REST 查询(应用 ID + 允许列表解析)。 + 使用 `channels.discord.proxy`,通过 HTTP(S) 代理路由 Discord gateway WebSocket 流量和启动时的 REST 查询(application ID + allowlist 解析)。 ```json5 { @@ -861,7 +865,7 @@ OpenClaw 支持在智能体消息中使用 Discord components v2 容器。请使 - 启用 PluralKit 解析,将代理消息映射到系统成员身份: + 启用 PluralKit 解析,将代理消息映射到 system member 身份: ```json5 { @@ -878,8 +882,8 @@ OpenClaw 支持在智能体消息中使用 Discord components v2 容器。请使 说明: - - 允许列表可使用 `pk:` - - 只有在 `channels.discord.dangerouslyAllowNameMatching: true` 时,才会按名称/slug 匹配成员显示名 + - allowlist 可以使用 `pk:` + - 只有当 `channels.discord.dangerouslyAllowNameMatching: true` 时,才会按名称/slug 匹配成员显示名 - 查询使用原始消息 ID,并受时间窗口限制 - 如果查询失败,代理消息会被视为机器人消息并丢弃,除非设置了 `allowBots=true` @@ -953,7 +957,7 @@ OpenClaw 支持在智能体消息中使用 Discord components v2 容器。请使 } ``` - 自动在线状态会将运行时可用性映射到 Discord 状态:healthy => online,degraded 或 unknown => idle,exhausted 或 unavailable => dnd。可选文本覆盖项: + 自动在线状态会将运行时可用性映射为 Discord 状态:healthy => online,degraded 或 unknown => idle,exhausted 或 unavailable => dnd。可选的文本覆盖项: - `autoPresence.healthyText` - `autoPresence.degradedText` @@ -962,7 +966,7 @@ OpenClaw 支持在智能体消息中使用 Discord components v2 容器。请使 - Discord 支持在私信中使用基于按钮的审批处理,也可选择在发起渠道中发布审批提示。 + Discord 支持在私信中使用基于按钮的审批处理,并且还可以选择在发起审批的原始频道中发布审批提示。 配置路径: @@ -971,27 +975,27 @@ OpenClaw 支持在智能体消息中使用 Discord components v2 容器。请使 - `channels.discord.execApprovals.target`(`dm` | `channel` | `both`,默认:`dm`) - `agentFilter`、`sessionFilter`、`cleanupAfterResolve` - 当 `enabled` 未设置或为 `"auto"`,且至少能从 `execApprovals.approvers` 或 `commands.ownerAllowFrom` 解析出一个 approver 时,Discord 会自动启用原生 exec 审批。Discord 不会从渠道 `allowFrom`、旧版 `dm.allowFrom` 或私信 `defaultTo` 推断 exec approver。若要显式禁用 Discord 作为原生审批客户端,请设置 `enabled: false`。 + 当 `enabled` 未设置或为 `"auto"`,并且至少可以解析出一个 approver(来自 `execApprovals.approvers` 或 `commands.ownerAllowFrom`)时,Discord 会自动启用原生 exec 审批。Discord 不会从渠道 `allowFrom`、旧版 `dm.allowFrom` 或私信 `defaultTo` 推断 exec approver。将 `enabled: false` 设为显式禁用 Discord 作为原生审批客户端。 - 当 `target` 为 `channel` 或 `both` 时,审批提示会显示在频道中。只有已解析出的 approver 才能使用这些按钮;其他用户会收到一条临时拒绝消息。审批提示包含命令文本,因此仅应在受信任的频道中启用渠道投递。如果无法从会话键中推导出频道 ID,OpenClaw 会回退为通过私信投递。 + 当 `target` 为 `channel` 或 `both` 时,审批提示会显示在频道中。只有已解析的 approver 可以使用这些按钮;其他用户会收到仅自己可见的拒绝提示。审批提示包含命令文本,因此仅应在受信任的频道中启用频道投递。如果无法从会话键推导出频道 ID,OpenClaw 会回退为私信投递。 - Discord 也会渲染其他聊天渠道使用的共享审批按钮。原生 Discord 适配器主要增加了 approver 私信路由和渠道扇出能力。 - 当这些按钮存在时,它们就是主要的审批 UX;只有在工具结果表明聊天审批不可用,或手动审批是唯一途径时,OpenClaw 才应包含手动 `/approve` 命令。 + Discord 也会渲染其他聊天渠道使用的共享审批按钮。原生 Discord 适配器主要增加了 approver 私信路由和频道扇出。 + 当这些按钮存在时,它们就是主要的审批 UX;只有当工具结果表明聊天审批不可用,或手动审批是唯一途径时,OpenClaw 才应包含手动 `/approve` 命令。 - 该处理器的 Gateway 网关认证使用与其他 Gateway 网关客户端相同的共享凭证解析约定: + 此处理器的 Gateway 网关鉴权使用与其他 Gateway 网关客户端相同的共享凭证解析契约: - - env-first 本地认证(`OPENCLAW_GATEWAY_TOKEN` / `OPENCLAW_GATEWAY_PASSWORD`,然后是 `gateway.auth.*`) - - 在本地模式下,仅当 `gateway.auth.*` 未设置时,`gateway.remote.*` 才可用作回退;若本地 SecretRef 已配置但无法解析,则会失败关闭 - - 在适用时,通过 `gateway.remote.*` 支持远程模式 - - URL 覆盖是安全可覆盖的:CLI 覆盖不会复用隐式凭证,而环境变量覆盖仅使用环境变量凭证 + - 环境变量优先的本地鉴权(`OPENCLAW_GATEWAY_TOKEN` / `OPENCLAW_GATEWAY_PASSWORD`,然后是 `gateway.auth.*`) + - 在本地模式下,仅当 `gateway.auth.*` 未设置时,才可将 `gateway.remote.*` 作为回退;已配置但无法解析的本地 SecretRef 会失败关闭 + - 在适用情况下,通过 `gateway.remote.*` 支持远程模式 + - URL 覆盖是安全的覆盖:CLI 覆盖不会复用隐式凭证,而环境变量覆盖仅使用环境变量凭证 审批解析行为: - 以 `plugin:` 为前缀的 ID 通过 `plugin.approval.resolve` 解析。 - 其他 ID 通过 `exec.approval.resolve` 解析。 - - Discord 不会在这里额外执行一次从 exec 到 plugin 的回退跳转;ID 前缀决定它调用哪个 gateway 方法。 + - Discord 不会在这里再执行额外的 exec 到 plugin 回退跳转;ID 前缀决定它调用哪个 Gateway 网关方法。 - Exec 审批默认会在 30 分钟后过期。如果审批因未知审批 ID 而失败,请检查 approver 解析、功能启用状态,以及已投递的审批 ID 类型是否与待处理请求匹配。 + 默认情况下,Exec 审批会在 30 分钟后过期。如果审批因未知审批 ID 而失败,请检查 approver 解析、功能是否已启用,以及已投递的审批 ID 类型是否与待处理请求匹配。 相关文档:[Exec approvals](/zh-CN/tools/exec-approvals) @@ -1000,34 +1004,34 @@ OpenClaw 支持在智能体消息中使用 Discord components v2 容器。请使 ## 工具和操作门控 -Discord 消息操作包括消息发送、频道管理、审核、在线状态和元数据操作。 +Discord 消息操作包括消息传递、频道管理、审核、在线状态和元数据操作。 核心示例: -- 消息:`sendMessage`、`readMessages`、`editMessage`、`deleteMessage`、`threadReply` -- 反应:`react`、`reactions`、`emojiList` +- 消息传递:`sendMessage`、`readMessages`、`editMessage`、`deleteMessage`、`threadReply` +- reactions:`react`、`reactions`、`emojiList` - 审核:`timeout`、`kick`、`ban` - 在线状态:`setPresence` -`event-create` 操作接受一个可选的 `image` 参数(URL 或本地文件路径),用于设置计划事件封面图。 +`event-create` 操作接受一个可选的 `image` 参数(URL 或本地文件路径),用于设置计划事件封面图片。 操作门控位于 `channels.discord.actions.*` 下。 默认门控行为: -| 操作组 | 默认值 | -| ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------ | -| reactions, messages, threads, pins, Polls, search, memberInfo, roleInfo, channelInfo, channels, voiceStatus, events, stickers, emojiUploads, stickerUploads, permissions | enabled | -| roles | disabled | -| moderation | disabled | -| presence | disabled | +| 操作组 | 默认值 | +| --- | --- | +| reactions、messages、threads、pins、polls、search、memberInfo、roleInfo、channelInfo、channels、voiceStatus、events、stickers、emojiUploads、stickerUploads、permissions | enabled | +| roles | disabled | +| moderation | disabled | +| presence | disabled | ## Components v2 UI -OpenClaw 对 exec 审批和跨上下文标记使用 Discord components v2。Discord 消息操作也可以接受 `components` 来构建自定义 UI(高级用法;需要通过 discord 工具构造组件负载),而旧版 `embeds` 仍可用,但不推荐使用。 +OpenClaw 使用 Discord components v2 作为 exec 审批和跨上下文标记的 UI。Discord 消息操作也可以接受 `components` 用于自定义 UI(高级用法;需要通过 discord 工具构造组件负载),而旧版 `embeds` 仍然可用,但不推荐。 - `channels.discord.ui.components.accentColor` 设置 Discord 组件容器使用的强调色(hex)。 -- 可按账户通过 `channels.discord.accounts..ui.components.accentColor` 设置。 +- 可通过 `channels.discord.accounts..ui.components.accentColor` 按账户设置。 - 当存在 components v2 时,`embeds` 会被忽略。 示例: @@ -1048,15 +1052,15 @@ OpenClaw 对 exec 审批和跨上下文标记使用 Discord components v2。Disc ## 语音频道 -OpenClaw 可以加入 Discord 语音频道,以进行实时、连续的对话。这与语音消息附件是分开的。 +OpenClaw 可以加入 Discord 语音频道,以实现实时、连续的对话。这与语音消息附件是分开的。 要求: - 启用原生命令(`commands.native` 或 `channels.discord.commands.native`)。 - 配置 `channels.discord.voice`。 -- 机器人需要在目标语音频道中具有 Connect 和 Speak 权限。 +- 机器人需要在目标语音频道中拥有 Connect 和 Speak 权限。 -使用仅限 Discord 的原生命令 `/vc join|leave|status` 来控制会话。该命令使用账户默认智能体,并遵循与其他 Discord 命令相同的允许列表和服务器策略规则。 +使用仅限 Discord 的原生命令 `/vc join|leave|status` 来控制会话。该命令使用账户默认智能体,并遵循与其他 Discord 命令相同的 allowlist 和 group policy 规则。 自动加入示例: @@ -1087,20 +1091,20 @@ OpenClaw 可以加入 Discord 语音频道,以进行实时、连续的对话 说明: - `voice.tts` 仅对语音播放覆盖 `messages.tts`。 -- 语音转录轮次会根据 Discord `allowFrom`(或 `dm.allowFrom`)推导所有者状态;非所有者发言者无法访问仅限所有者的工具(例如 `gateway` 和 `cron`)。 -- 语音默认启用;设置 `channels.discord.voice.enabled=false` 可将其禁用。 +- 语音转录轮次会根据 Discord `allowFrom`(或 `dm.allowFrom`)派生 owner 状态;非 owner 的说话者无法访问仅限 owner 的工具(例如 `gateway` 和 `cron`)。 +- 语音默认启用;设置 `channels.discord.voice.enabled=false` 可禁用它。 - `voice.daveEncryption` 和 `voice.decryptionFailureTolerance` 会透传给 `@discordjs/voice` 的加入选项。 - 如果未设置,`@discordjs/voice` 的默认值为 `daveEncryption=true` 和 `decryptionFailureTolerance=24`。 -- OpenClaw 还会监控接收解密失败,并在短时间内重复失败后,通过离开并重新加入语音频道来自动恢复。 -- 如果接收日志中反复出现 `DecryptionFailed(UnencryptedWhenPassthroughDisabled)`,这可能是上游 `@discordjs/voice` 接收 bug,见 [discord.js #11419](https://github.com/discordjs/discord.js/issues/11419)。 +- OpenClaw 还会监控接收解密失败,并在短时间内重复失败后,通过离开/重新加入语音频道自动恢复。 +- 如果接收日志反复显示 `DecryptionFailed(UnencryptedWhenPassthroughDisabled)`,这可能是上游 `@discordjs/voice` 的接收 bug,记录在 [discord.js #11419](https://github.com/discordjs/discord.js/issues/11419) 中。 ## 语音消息 -Discord 语音消息会显示波形预览,并要求使用 OGG/Opus 音频以及元数据。OpenClaw 会自动生成波形,但它需要在 Gateway 网关主机上可用的 `ffmpeg` 和 `ffprobe` 来检查并转换音频文件。 +Discord 语音消息会显示波形预览,并且需要 OGG/Opus 音频和元数据。OpenClaw 会自动生成波形,但它需要在 Gateway 网关主机上可用的 `ffmpeg` 和 `ffprobe` 来检查和转换音频文件。 要求和限制: -- 提供**本地文件路径**(不接受 URL)。 +- 提供**本地文件路径**(URL 会被拒绝)。 - 省略文本内容(Discord 不允许在同一负载中同时发送文本和语音消息)。 - 接受任意音频格式;OpenClaw 会在需要时将其转换为 OGG/Opus。 @@ -1113,7 +1117,7 @@ message(action="send", channel="discord", target="channel:123", path="/path/to/a ## 故障排除 - + - 启用 Message Content Intent - 当你依赖用户/成员解析时,启用 Server Members Intent @@ -1121,14 +1125,14 @@ message(action="send", channel="discord", target="channel:123", path="/path/to/a - + - - 检查 `groupPolicy` - - 检查 `channels.discord.guilds` 下的服务器允许列表 - - 如果存在服务器 `channels` 映射,则仅允许列出的频道 - - 检查 `requireMention` 行为和提及模式 + - 验证 `groupPolicy` + - 验证 `channels.discord.guilds` 下的服务器 allowlist + - 如果存在服务器 `channels` 映射,则只允许列出的频道 + - 验证 `requireMention` 行为和提及模式 - 有用的检查命令: + 有用的检查: ```bash openclaw doctor @@ -1138,12 +1142,12 @@ openclaw logs --follow - + 常见原因: - - `groupPolicy="allowlist"`,但没有匹配的服务器/频道允许列表 - - `requireMention` 配置在错误位置(必须位于 `channels.discord.guilds` 或频道条目下) - - 发送者被服务器/频道 `users` 允许列表拦截 + - `groupPolicy="allowlist"`,但没有匹配的服务器/频道 allowlist + - `requireMention` 配置在错误的位置(必须位于 `channels.discord.guilds` 或频道条目下) + - 发送者被服务器/频道 `users` allowlist 阻止 @@ -1155,12 +1159,12 @@ openclaw logs --follow - `Slow listener detected ...` - `discord inbound worker timed out after ...` - 监听器预算调节项: + 监听器预算旋钮: - 单账户:`channels.discord.eventQueue.listenerTimeout` - 多账户:`channels.discord.accounts..eventQueue.listenerTimeout` - Worker 运行超时调节项: + Worker 运行超时旋钮: - 单账户:`channels.discord.inboundWorker.runTimeoutMs` - 多账户:`channels.discord.accounts..inboundWorker.runTimeoutMs` @@ -1187,14 +1191,14 @@ openclaw logs --follow } ``` - 对于缓慢的监听器初始化,请使用 `eventQueue.listenerTimeout`;仅当你希望为排队中的智能体轮次提供单独的安全阀时,才使用 `inboundWorker.runTimeoutMs`。 + 对于缓慢的监听器初始化,请使用 `eventQueue.listenerTimeout`;只有在你希望为排队的智能体轮次设置单独的安全阀时,才使用 `inboundWorker.runTimeoutMs`。 - `channels status --probe` 的权限检查仅适用于数字频道 ID。 + `channels status --probe` 权限检查仅适用于数字频道 ID。 - 如果你使用 slug 键,运行时匹配仍然可能正常工作,但探测无法完整验证权限。 + 如果你使用 slug 键,运行时匹配仍然可以工作,但探测无法完整验证权限。 @@ -1207,22 +1211,22 @@ openclaw logs --follow - 默认情况下,会忽略由机器人发送的消息。 + 默认情况下,由机器人发送的消息会被忽略。 - 如果你设置了 `channels.discord.allowBots=true`,请使用严格的提及和允许列表规则以避免循环行为。 - 更推荐使用 `channels.discord.allowBots="mentions"`,仅接受提及机器人的机器人消息。 + 如果你设置了 `channels.discord.allowBots=true`,请使用严格的提及和 allowlist 规则,以避免循环行为。 + 建议使用 `channels.discord.allowBots="mentions"`,仅接受提及该机器人的机器人消息。 - - 保持 OpenClaw 为最新版本(`openclaw update`),以确保包含 Discord 语音接收恢复逻辑 - - 确认 `channels.discord.voice.daveEncryption=true`(默认值) - - 从 `channels.discord.voice.decryptionFailureTolerance=24`(上游默认值)开始,仅在必要时再调整 - - 观察日志中是否有: + - 保持 OpenClaw 为最新版本(`openclaw update`),以确保存在 Discord 语音接收恢复逻辑 + - 确认 `channels.discord.voice.daveEncryption=true`(默认) + - 从 `channels.discord.voice.decryptionFailureTolerance=24`(上游默认值)开始,仅在必要时调整 + - 关注日志中的以下内容: - `discord voice: DAVE decrypt failures detected` - `discord voice: repeated decrypt failures; attempting rejoin` - - 如果自动重新加入后故障仍持续,请收集日志并与 [discord.js #11419](https://github.com/discordjs/discord.js/issues/11419) 进行对比 + - 如果自动重新加入后故障仍然持续,请收集日志并与 [discord.js #11419](https://github.com/discordjs/discord.js/issues/11419) 进行对比 @@ -1231,11 +1235,11 @@ openclaw logs --follow 主要参考: -- [Configuration reference - Discord](/zh-CN/gateway/configuration-reference#discord) +- [配置参考 - Discord](/zh-CN/gateway/configuration-reference#discord) -高信号的 Discord 字段: +高信号 Discord 字段: -- 启动/认证:`enabled`、`token`、`accounts.*`、`allowBots` +- 启动/鉴权:`enabled`、`token`、`accounts.*`、`allowBots` - 策略:`groupPolicy`、`dm.*`、`guilds.*`、`guilds.*.channels.*` - 命令:`commands.native`、`commands.useAccessGroups`、`configWrites`、`slashCommand.*` - 事件队列:`eventQueue.listenerTimeout`(监听器预算)、`eventQueue.maxQueueSize`、`eventQueue.maxConcurrency` @@ -1244,7 +1248,7 @@ openclaw logs --follow - 投递:`textChunkLimit`、`chunkMode`、`maxLinesPerMessage` - 流式传输:`streaming`(旧版别名:`streamMode`)、`streaming.preview.toolProgress`、`draftChunk`、`blockStreaming`、`blockStreamingCoalesce` - 媒体/重试:`mediaMaxMb`、`retry` - - `mediaMaxMb` 限制发往 Discord 的上传大小(默认值:`100MB`) + - `mediaMaxMb` 限制 Discord 出站上传大小(默认:`100MB`) - 操作:`actions.*` - 在线状态:`activity`、`status`、`activityType`、`activityUrl` - UI:`ui.components.accentColor` @@ -1252,7 +1256,7 @@ openclaw logs --follow ## 安全和运维 -- 将机器人令牌视为机密信息(在受监管环境中优先使用 `DISCORD_BOT_TOKEN`)。 +- 将机器人令牌视为机密(在受监管环境中优先使用 `DISCORD_BOT_TOKEN`)。 - 授予最小权限的 Discord 权限。 - 如果命令部署/状态已过期,请重启 Gateway 网关,并使用 `openclaw channels status --probe` 重新检查。 diff --git a/docs/zh-CN/channels/irc.md b/docs/zh-CN/channels/irc.md index 037a7c8e3..4d0552671 100644 --- a/docs/zh-CN/channels/irc.md +++ b/docs/zh-CN/channels/irc.md @@ -1,27 +1,27 @@ --- read_when: - 你想将 OpenClaw 连接到 IRC 频道或私信 - - 你正在配置 IRC allowlist、群组策略或提及门控 + - 你正在配置 IRC 允许列表、群组策略或提及门控 summary: IRC 插件设置、访问控制和故障排除 title: IRC x-i18n: - generated_at: "2026-04-23T06:40:06Z" + generated_at: "2026-04-23T07:03:26Z" model: gpt-5.4 provider: openai - source_hash: 89c788a2be95b43420a5324ed30cada32626b72b2feb77df62aeb928fc0a386c + source_hash: 28d0929e1e3f882eca1ba46eeb5e3fa537baaebfedbe2cf4079946cd9b432c87 source_path: channels/irc.md workflow: 15 --- # IRC -当你希望 OpenClaw 出现在传统频道(`#room`)和私信中时,请使用 IRC。 -IRC 作为内置插件提供,但需在主配置中的 `channels.irc` 下进行配置。 +当你希望 OpenClaw 进入传统频道(`#room`)和私信时,请使用 IRC。 +IRC 作为内置插件提供,但需要在主配置中的 `channels.irc` 下进行配置。 ## 快速开始 1. 在 `~/.openclaw/openclaw.json` 中启用 IRC 配置。 -2. 至少设置: +2. 至少设置以下内容: ```json5 { @@ -38,7 +38,7 @@ IRC 作为内置插件提供,但需在主配置中的 `channels.irc` 下进行 } ``` -优先使用私有 IRC 服务器进行机器人协作。如果你有意使用公共 IRC 网络,常见选择包括 Libera.Chat、OFTC 和 Snoonet。避免将可预测的公共频道用于机器人或 swarm 的回传流量。 +优先使用私有 IRC 服务器来协调机器人。如果你有意使用公共 IRC 网络,常见选择包括 Libera.Chat、OFTC 和 Snoonet。避免将可预测的公共频道用于机器人或 swarm 的回传通道流量。 3. 启动/重启 Gateway 网关: @@ -48,38 +48,38 @@ openclaw gateway run ## 安全默认值 -- `channels.irc.dmPolicy` 默认为 `"pairing"`。 -- `channels.irc.groupPolicy` 默认为 `"allowlist"`。 -- 当 `groupPolicy="allowlist"` 时,设置 `channels.irc.groups` 以定义允许的频道。 -- 使用 TLS(`channels.irc.tls=true`),除非你明确接受明文传输。 +- `channels.irc.dmPolicy` 默认值为 `"pairing"`。 +- `channels.irc.groupPolicy` 默认值为 `"allowlist"`。 +- 使用 `groupPolicy="allowlist"` 时,设置 `channels.irc.groups` 来定义允许的频道。 +- 除非你有意接受明文传输,否则请使用 TLS(`channels.irc.tls=true`)。 ## 访问控制 -IRC 频道有两个彼此独立的“门”: +IRC 频道有两个彼此独立的“门控”: 1. **频道访问**(`groupPolicy` + `groups`):机器人是否完全接受来自某个频道的消息。 2. **发送者访问**(`groupAllowFrom` / 每频道 `groups["#channel"].allowFrom`):在该频道内,谁被允许触发机器人。 配置键: -- 私信 allowlist(私信发送者访问):`channels.irc.allowFrom` -- 群组发送者 allowlist(频道发送者访问):`channels.irc.groupAllowFrom` +- 私信允许列表(私信发送者访问):`channels.irc.allowFrom` +- 群组发送者允许列表(频道发送者访问):`channels.irc.groupAllowFrom` - 每频道控制(频道 + 发送者 + 提及规则):`channels.irc.groups["#channel"]` - `channels.irc.groupPolicy="open"` 允许未配置的频道(**默认仍然受提及门控限制**) -allowlist 条目应使用稳定的发送者身份(`nick!user@host`)。 -仅昵称匹配是可变的,并且只有在 `channels.irc.dangerouslyAllowNameMatching: true` 时才会启用。 +允许列表条目应使用稳定的发送者身份(`nick!user@host`)。 +裸昵称匹配是可变的,只有在 `channels.irc.dangerouslyAllowNameMatching: true` 时才会启用。 ### 常见陷阱:`allowFrom` 用于私信,不用于频道 -如果你看到如下日志: +如果你看到这样的日志: - `irc: drop group sender alice!ident@host (policy=allowlist)` -……这意味着发送者没有被允许发送**群组/频道**消息。可通过以下方式修复: +……这表示该发送者未被允许发送**群组/频道**消息。可通过以下任一方式修复: - 设置 `channels.irc.groupAllowFrom`(对所有频道全局生效),或 -- 设置每频道发送者 allowlist:`channels.irc.groups["#channel"].allowFrom` +- 设置每频道发送者允许列表:`channels.irc.groups["#channel"].allowFrom` 示例(允许 `#tuirc-dev` 中的任何人与机器人对话): @@ -98,11 +98,11 @@ allowlist 条目应使用稳定的发送者身份(`nick!user@host`)。 ## 回复触发(提及) -即使频道已被允许(通过 `groupPolicy` + `groups`),且发送者也已被允许,OpenClaw 在群组上下文中默认仍会启用**提及门控**。 +即使某个频道已被允许(通过 `groupPolicy` + `groups`),且发送者也已被允许,OpenClaw 在群组上下文中默认仍采用**提及门控**。 -这意味着,除非消息中包含与机器人匹配的提及模式,否则你可能会看到如 `drop channel … (missing-mention)` 这样的日志。 +这意味着,除非消息中包含与机器人匹配的提及模式,否则你可能会看到类似 `drop channel … (missing-mention)` 的日志。 -如果你希望机器人在 IRC 频道中**无需提及也能回复**,请为该频道禁用提及门控: +如果你想让机器人在 IRC 频道中**无需提及也能回复**,请为该频道禁用提及门控: ```json5 { @@ -120,7 +120,7 @@ allowlist 条目应使用稳定的发送者身份(`nick!user@host`)。 } ``` -或者,如果要允许**所有** IRC 频道(不使用每频道 allowlist),同时仍然无需提及即可回复: +或者,如果要允许**所有** IRC 频道(不使用每频道允许列表),并且仍然无需提及即可回复: ```json5 { @@ -137,10 +137,10 @@ allowlist 条目应使用稳定的发送者身份(`nick!user@host`)。 ## 安全说明(建议用于公共频道) -如果你在公共频道中允许 `allowFrom: ["*"]`,任何人都可以向机器人发出提示。 +如果你在公共频道中设置 `allowFrom: ["*"]`,那么任何人都可以向机器人发起提示。 为降低风险,请限制该频道可用的工具。 -### 频道中所有人使用相同的工具 +### 频道中所有人使用相同工具 ```json5 { @@ -159,9 +159,9 @@ allowlist 条目应使用稳定的发送者身份(`nick!user@host`)。 } ``` -### 按发送者使用不同的工具(所有者拥有更高权限) +### 按发送者使用不同工具(所有者权限更高) -使用 `toolsBySender`,对 `"*"` 应用更严格的策略,而对你的昵称应用更宽松的策略: +使用 `toolsBySender` 对 `"*"` 应用更严格的策略,并对你的昵称应用更宽松的策略: ```json5 { @@ -187,16 +187,16 @@ allowlist 条目应使用稳定的发送者身份(`nick!user@host`)。 说明: -- `toolsBySender` 键应对 IRC 发送者身份值使用 `id:`: - `id:eigen` 或 `id:eigen!~eigen@174.127.248.171`,后者匹配更强。 -- 旧版不带前缀的键仍然可接受,但只会按 `id:` 进行匹配。 -- 首个匹配到的发送者策略会生效;`"*"` 是通配回退项。 +- `toolsBySender` 的键应对 IRC 发送者身份值使用 `id:`: + `id:eigen`,或使用更强匹配的 `id:eigen!~eigen@174.127.248.171`。 +- 旧版未加前缀的键仍然受支持,但只会按 `id:` 进行匹配。 +- 第一个匹配到的发送者策略优先生效;`"*"` 是通配回退项。 -有关群组访问与提及门控(以及它们如何交互)的更多内容,请参阅:[/channels/groups](/zh-CN/channels/groups)。 +有关群组访问与提及门控(以及它们如何交互)的更多内容,请参见:[/channels/groups](/zh-CN/channels/groups)。 ## NickServ -要在连接后通过 NickServ 进行身份识别: +连接后通过 NickServ 进行身份识别: ```json5 { @@ -240,20 +240,27 @@ allowlist 条目应使用稳定的发送者身份(`nick!user@host`)。 - `IRC_USERNAME` - `IRC_REALNAME` - `IRC_PASSWORD` -- `IRC_CHANNELS`(逗号分隔) +- `IRC_CHANNELS`(以逗号分隔) - `IRC_NICKSERV_PASSWORD` - `IRC_NICKSERV_REGISTER_EMAIL` + +`IRC_HOST` 位于端点屏蔽列表中,不能通过工作区 `.env` 文件设置。 +它必须来自 shell 环境或 Gateway 网关进程环境, +以防止不受信任的工作区将 IRC 流量重定向到其他服务器。 +完整列表请参见 [工作区 `.env` 文件](/zh-CN/gateway/security)。 + + ## 故障排除 -- 如果机器人已连接,但在频道中始终不回复,请检查 `channels.irc.groups`,**以及** 是否因提及门控而丢弃消息(`missing-mention`)。如果你希望它无需 ping 就能回复,请为该频道设置 `requireMention:false`。 -- 如果登录失败,请检查昵称是否可用以及服务器密码是否正确。 -- 如果在自定义网络上 TLS 失败,请检查主机/端口和证书设置。 +- 如果机器人已连接但从不在频道中回复,请检查 `channels.irc.groups`,**以及**消息是否因提及门控而被丢弃(`missing-mention`)。如果你希望它无需 ping 就能回复,请为该频道设置 `requireMention:false`。 +- 如果登录失败,请检查昵称是否可用,以及服务器密码是否正确。 +- 如果在自定义网络上 TLS 失败,请检查 host/port 和证书设置。 ## 相关内容 -- [渠道概览](/zh-CN/channels) — 所有受支持的渠道 -- [Pairing](/zh-CN/channels/pairing) — 私信认证和配对流程 -- [Groups](/zh-CN/channels/groups) — 群聊行为与提及门控 +- [渠道概览](/zh-CN/channels) — 所有支持的渠道 +- [配对](/zh-CN/channels/pairing) — 私信身份验证和配对流程 +- [群组](/zh-CN/channels/groups) — 群聊行为和提及门控 - [渠道路由](/zh-CN/channels/channel-routing) — 消息的会话路由 - [安全](/zh-CN/gateway/security) — 访问模型与加固措施 diff --git a/docs/zh-CN/channels/matrix.md b/docs/zh-CN/channels/matrix.md index 136fcad02..c72bcaabc 100644 --- a/docs/zh-CN/channels/matrix.md +++ b/docs/zh-CN/channels/matrix.md @@ -5,10 +5,10 @@ read_when: summary: Matrix 支持状态、设置和配置示例 title: Matrix x-i18n: - generated_at: "2026-04-21T20:11:29Z" + generated_at: "2026-04-23T07:03:28Z" model: gpt-5.4 provider: openai - source_hash: 5e78d85096ea84361951935a0daf34966c575d822f8581277eb384276c7c706a + source_hash: 678d0e678cbb52a9817d5a1f4977a738820f6d0228f1810614c9c195c0de7218 source_path: channels/matrix.md workflow: 15 --- @@ -16,13 +16,13 @@ x-i18n: # Matrix Matrix 是 OpenClaw 的一个内置渠道插件。 -它使用官方的 `matrix-js-sdk`,并支持私信、房间、线程、媒体、回应、投票、位置和 E2EE。 +它使用官方 `matrix-js-sdk`,并支持私信、房间、线程、媒体、回应、投票、位置和 E2EE。 ## 内置插件 -Matrix 作为内置插件随当前的 OpenClaw 版本发布,因此常规的打包构建不需要单独安装。 +Matrix 作为当前 OpenClaw 版本中的内置插件提供,因此普通的打包构建不需要单独安装。 -如果你使用的是较旧的构建版本,或排除了 Matrix 的自定义安装,请手动安装: +如果你使用的是较旧的构建版本,或是排除了 Matrix 的自定义安装,请手动安装: 从 npm 安装: @@ -36,20 +36,20 @@ openclaw plugins install @openclaw/matrix openclaw plugins install ./path/to/local/matrix-plugin ``` -有关插件行为和安装规则,请参见 [Plugins](/zh-CN/tools/plugin)。 +有关插件行为和安装规则,请参阅 [插件](/zh-CN/tools/plugin)。 ## 设置 1. 确保 Matrix 插件可用。 - 当前打包的 OpenClaw 版本已内置该插件。 - - 较旧或自定义安装可以使用上面的命令手动添加。 -2. 在你的 homeserver 上创建一个 Matrix 账户。 + - 较旧/自定义安装可使用上述命令手动添加。 +2. 在你的 homeserver 上创建一个 Matrix 账号。 3. 使用以下任一方式配置 `channels.matrix`: - `homeserver` + `accessToken`,或 - `homeserver` + `userId` + `password`。 4. 重启 Gateway 网关。 5. 与机器人发起私信,或邀请它加入房间。 - - 只有当 `channels.matrix.autoJoin` 允许时,新发出的 Matrix 邀请才会生效。 + - 只有在 `channels.matrix.autoJoin` 允许的情况下,新发出的 Matrix 邀请才会生效。 交互式设置路径: @@ -61,32 +61,32 @@ openclaw configure --section channels Matrix 向导会询问以下内容: - homeserver URL -- 认证方式:access token 或密码 -- 用户 ID(仅密码认证) -- 可选设备名称 +- 认证方式:访问令牌或密码 +- 用户 ID(仅限密码认证) +- 可选的设备名称 - 是否启用 E2EE - 是否配置房间访问和邀请自动加入 向导的关键行为: -- 如果 Matrix 认证环境变量已存在,且该账户尚未在配置中保存认证信息,则向导会提供一个环境变量快捷选项,以便将认证信息保留在环境变量中。 -- 账户名称会规范化为账户 ID。例如,`Ops Bot` 会变成 `ops-bot`。 -- 私信允许列表条目可直接接受 `@user:server`;显示名称只有在实时目录查找找到一个精确匹配时才有效。 -- 房间允许列表条目可直接接受房间 ID 和别名。优先使用 `!room:server` 或 `#alias:server`;未解析的名称会在运行时被允许列表解析忽略。 -- 在邀请自动加入的允许列表模式下,只使用稳定的邀请目标:`!roomId:server`、`#alias:server` 或 `*`。普通房间名称会被拒绝。 +- 如果 Matrix 认证环境变量已存在,并且该账号的认证信息尚未保存在配置中,向导会提供一个环境变量快捷选项,以便将认证信息保留在环境变量中。 +- 账号名称会规范化为账号 ID。例如,`Ops Bot` 会变成 `ops-bot`。 +- 私信 allowlist 条目可直接接受 `@user:server`;显示名称只有在实时目录查找能找到唯一精确匹配时才可用。 +- 房间 allowlist 条目可直接接受房间 ID 和别名。优先使用 `!room:server` 或 `#alias:server`;无法解析的名称会在运行时被 allowlist 解析忽略。 +- 在邀请自动加入的 allowlist 模式下,只能使用稳定的邀请目标:`!roomId:server`、`#alias:server` 或 `*`。普通房间名称会被拒绝。 - 如需在保存前解析房间名称,请使用 `openclaw channels resolve --channel matrix "Project Room"`。 -`channels.matrix.autoJoin` 默认值为 `off`。 +`channels.matrix.autoJoin` 默认为 `off`。 -如果你不设置它,机器人将不会加入被邀请的房间或新的私信式邀请,因此除非你先手动加入,否则它不会出现在新群组或被邀请的私信中。 +如果你不设置它,机器人将不会加入受邀房间或新发起的私信式邀请,因此除非你先手动加入,否则它不会出现在新的群组或受邀私信中。 -将 `autoJoin: "allowlist"` 与 `autoJoinAllowlist` 一起设置,可限制它接受哪些邀请;如果你希望它加入所有邀请,可设置 `autoJoin: "always"`。 +如果你想限制它接受哪些邀请,请设置 `autoJoin: "allowlist"` 并同时配置 `autoJoinAllowlist`;如果你希望它加入所有邀请,请设置 `autoJoin: "always"`。 -在 `allowlist` 模式下,`autoJoinAllowlist` 只接受 `!roomId:server`、`#alias:server` 或 `*`。 +在 `allowlist` 模式下,`autoJoinAllowlist` 仅接受 `!roomId:server`、`#alias:server` 或 `*`。 -允许列表示例: +Allowlist 示例: ```json5 { @@ -116,7 +116,7 @@ Matrix 向导会询问以下内容: } ``` -基于 token 的最小设置: +基于令牌的最小化设置: ```json5 { @@ -131,7 +131,7 @@ Matrix 向导会询问以下内容: } ``` -基于密码的设置(登录后会缓存 token): +基于密码的设置(登录后会缓存令牌): ```json5 { @@ -148,10 +148,10 @@ Matrix 向导会询问以下内容: ``` Matrix 会将缓存的凭证存储在 `~/.openclaw/credentials/matrix/` 中。 -默认账户使用 `credentials.json`;命名账户使用 `credentials-.json`。 -当该位置存在缓存凭证时,即使当前认证未直接在配置中设置,OpenClaw 仍会在设置、Doctor 和渠道状态发现中将 Matrix 视为已配置。 +默认账号使用 `credentials.json`;命名账号使用 `credentials-.json`。 +如果那里存在缓存凭证,OpenClaw 在设置、Doctor 和渠道状态发现中会将 Matrix 视为已配置,即使当前认证信息没有直接在配置中设置也是如此。 -对应的环境变量(当未设置配置键时使用): +对应的环境变量(当配置键未设置时使用): - `MATRIX_HOMESERVER` - `MATRIX_ACCESS_TOKEN` @@ -160,7 +160,7 @@ Matrix 会将缓存的凭证存储在 `~/.openclaw/credentials/matrix/` 中。 - `MATRIX_DEVICE_ID` - `MATRIX_DEVICE_NAME` -对于非默认账户,请使用带账户作用域的环境变量: +对于非默认账号,请使用账号范围的环境变量: - `MATRIX__HOMESERVER` - `MATRIX__ACCESS_TOKEN` @@ -169,24 +169,30 @@ Matrix 会将缓存的凭证存储在 `~/.openclaw/credentials/matrix/` 中。 - `MATRIX__DEVICE_ID` - `MATRIX__DEVICE_NAME` -以账户 `ops` 为例: +账号 `ops` 的示例: - `MATRIX_OPS_HOMESERVER` - `MATRIX_OPS_ACCESS_TOKEN` -对于规范化后的账户 ID `ops-bot`,请使用: +对于规范化后的账号 ID `ops-bot`,请使用: - `MATRIX_OPS_X2D_BOT_HOMESERVER` - `MATRIX_OPS_X2D_BOT_ACCESS_TOKEN` -Matrix 会对账户 ID 中的标点进行转义,以确保带作用域的环境变量不会发生冲突。 -例如,`-` 会变为 `_X2D_`,因此 `ops-prod` 会映射为 `MATRIX_OPS_X2D_PROD_*`。 +Matrix 会对账号 ID 中的标点符号进行转义,以避免带作用域的环境变量发生冲突。 +例如,`-` 会变成 `_X2D_`,因此 `ops-prod` 会映射为 `MATRIX_OPS_X2D_PROD_*`。 -只有在这些认证环境变量已存在,且所选账户尚未在配置中保存 Matrix 认证信息时,交互式向导才会提供环境变量快捷选项。 +只有当这些认证环境变量已存在,且所选账号尚未在配置中保存 Matrix 认证信息时,交互式向导才会提供环境变量快捷选项。 + + +`MATRIX_HOMESERVER` 位于端点屏蔽列表中,不能通过工作区 `.env` 文件设置。 +它必须来自 shell 环境变量或 Gateway 网关进程环境变量,这样不受信任的工作区就无法将 Matrix 流量重定向到其他 homeserver。完整列表请参阅 +[工作区 `.env` 文件](/zh-CN/gateway/security)。 + ## 配置示例 -这是一个实用的基础配置,启用了私信配对、房间允许列表和 E2EE: +这是一个实用的基础配置,启用了私信配对、房间 allowlist 和 E2EE: ```json5 { @@ -221,13 +227,13 @@ Matrix 会对账户 ID 中的标点进行转义,以确保带作用域的环境 } ``` -`autoJoin` 适用于所有 Matrix 邀请,包括私信式邀请。OpenClaw 无法在邀请发生时可靠地将受邀房间分类为私信或群组,因此所有邀请都会先经过 `autoJoin`。`dm.policy` 会在机器人加入后、房间被分类为私信之后再生效。 +`autoJoin` 适用于所有 Matrix 邀请,包括私信式邀请。OpenClaw 无法在邀请发生时可靠地区分受邀房间是私信还是群组,因此所有邀请都会先经过 `autoJoin`。`dm.policy` 会在机器人加入之后、并且该房间被识别为私信后才生效。 ## 流式预览 -Matrix 回复流式传输是可选启用的。 +Matrix 回复流式传输为选择启用。 -当你希望 OpenClaw 发送一条实时预览回复、在模型生成文本时原地编辑该预览,并在回复完成后将其定稿时,请将 `channels.matrix.streaming` 设置为 `"partial"`: +当你希望 OpenClaw 发送一条实时预览回复、在模型生成文本时原地编辑这条预览,并在回复完成后将其定稿时,请将 `channels.matrix.streaming` 设置为 `"partial"`: ```json5 { @@ -239,37 +245,37 @@ Matrix 回复流式传输是可选启用的。 } ``` -- `streaming: "off"` 是默认值。OpenClaw 会等待最终回复并一次性发送。 -- `streaming: "partial"` 会为当前助手块创建一条可编辑的预览消息,并使用普通 Matrix 文本消息。这会保留 Matrix 传统的“预览优先”通知行为,因此标准客户端可能会针对首次流式预览文本发送通知,而不是在完整块完成时通知。 -- `streaming: "quiet"` 会为当前助手块创建一条可编辑的静默预览通知。只有当你也为已完成的预览编辑配置了接收方 push 规则时,才应使用此模式。 -- `blockStreaming: true` 会启用单独的 Matrix 进度消息。启用预览流式传输后,Matrix 会保留当前块的实时草稿,并将已完成的块保留为单独消息。 -- 当启用预览流式传输且 `blockStreaming` 为 off 时,Matrix 会原地编辑实时草稿,并在块或轮次结束时将同一事件定稿。 -- 如果预览内容不再适合放入单个 Matrix 事件中,OpenClaw 会停止预览流式传输,并回退到普通的最终发送方式。 -- 媒体回复仍会正常发送附件。如果过期预览已无法安全复用,OpenClaw 会在发送最终媒体回复前将其撤回。 -- 预览编辑会带来额外的 Matrix API 调用。如果你希望采用最保守的限流行为,请保持关闭流式传输。 +- `streaming: "off"` 是默认值。OpenClaw 会等待最终回复,然后一次性发送。 +- `streaming: "partial"` 会为当前智能体输出块创建一条可编辑的预览消息,并使用普通 Matrix 文本消息进行更新。这样会保留 Matrix 传统的“预览优先”通知行为,因此标准客户端可能会在第一段流式预览文本出现时通知,而不是在最终内容完成时通知。 +- `streaming: "quiet"` 会为当前智能体输出块创建一条可编辑的静默预览通知。只有在你同时为最终定稿的预览编辑配置了接收者推送规则时,才应使用此模式。 +- `blockStreaming: true` 会启用单独的 Matrix 进度消息。在启用预览流式传输时,Matrix 会为当前块保留实时草稿,并将已完成的块保留为单独消息。 +- 当预览流式传输开启且 `blockStreaming` 关闭时,Matrix 会原地编辑实时草稿,并在块或整轮完成时定稿同一个事件。 +- 如果预览内容已无法容纳在单个 Matrix 事件中,OpenClaw 会停止预览流式传输并回退为普通的最终发送。 +- 媒体回复仍会正常发送附件。如果过期预览已无法安全复用,OpenClaw 会在发送最终媒体回复前将其清除。 +- 预览编辑会带来额外的 Matrix API 调用。如果你希望采用最保守的速率限制行为,请保持关闭流式传输。 `blockStreaming` 本身不会启用草稿预览。 -使用 `streaming: "partial"` 或 `streaming: "quiet"` 来启用预览编辑;如果你还希望已完成的助手块作为独立进度消息保留可见,再额外添加 `blockStreaming: true`。 +如需预览编辑,请使用 `streaming: "partial"` 或 `streaming: "quiet"`;如果你还希望已完成的智能体输出块以单独的进度消息保留可见,再额外添加 `blockStreaming: true`。 -如果你需要标准 Matrix 通知,而不想配置自定义 push 规则,请使用 `streaming: "partial"` 获得“预览优先”行为,或保持 `streaming` 为 off 以仅在最终完成时发送。使用 `streaming: "off"` 时: +如果你需要标准 Matrix 通知而不配置自定义推送规则,请使用 `streaming: "partial"` 获得“预览优先”行为,或保持 `streaming` 为关闭以仅发送最终结果。当 `streaming: "off"` 时: -- `blockStreaming: true` 会将每个已完成块作为普通的可通知 Matrix 消息发送。 -- `blockStreaming: false` 只会将最终完成的回复作为普通的可通知 Matrix 消息发送。 +- `blockStreaming: true` 会将每个已完成的块作为普通的可通知 Matrix 消息发送。 +- `blockStreaming: false` 只会将最终完整回复作为普通的可通知 Matrix 消息发送。 -### 自托管环境中用于静默已定稿预览的 push 规则 +### 自托管的静默定稿预览推送规则 -如果你运行的是自己的 Matrix 基础设施,并希望静默预览只在某个块或最终回复完成时触发通知,请设置 `streaming: "quiet"`,并为每个用户添加一条用于已定稿预览编辑的 push 规则。 +如果你运行自己的 Matrix 基础设施,并且希望静默预览只在某个块或最终回复完成时才触发通知,请设置 `streaming: "quiet"`,并为定稿后的预览编辑添加按用户配置的推送规则。 -这通常是接收方用户级别的设置,而不是 homeserver 全局配置变更: +这通常是接收用户侧的设置,而不是 homeserver 全局配置变更: -开始前的快速说明: +开始前的快速映射: - recipient user = 应收到通知的人 -- bot user = 发送回复的 OpenClaw Matrix 账户 -- 下方 API 调用请使用 recipient user 的 access token -- 在 push 规则中,将 `sender` 匹配为 bot user 的完整 MXID +- bot user = 发送回复的 OpenClaw Matrix 账号 +- 对下面的 API 调用使用 recipient user 的访问令牌 +- 在推送规则中,将 `sender` 与 bot user 的完整 MXID 匹配 -1. 配置 OpenClaw 使用静默预览: +1. 将 OpenClaw 配置为使用静默预览: ```json5 { @@ -281,12 +287,12 @@ Matrix 回复流式传输是可选启用的。 } ``` -2. 确保接收方账户已经能够接收普通 Matrix push 通知。静默预览规则只有在该用户已有可用的 pusher 或设备时才会生效。 +2. 确保接收账号已经能收到普通的 Matrix 推送通知。静默预览规则只有在该用户已有正常工作的 pusher/设备时才会生效。 -3. 获取接收方用户的 access token。 - - 使用接收消息用户的 token,而不是机器人的 token。 - - 复用现有客户端会话 token 通常是最简单的方式。 - - 如果你需要签发一个新的 token,可以通过标准 Matrix Client-Server API 登录: +3. 获取 recipient user 的访问令牌。 + - 使用接收用户的令牌,而不是机器人的令牌。 + - 复用现有客户端会话令牌通常最简单。 + - 如果你需要创建新的令牌,可以通过标准 Matrix Client-Server API 登录: ```bash curl -sS -X POST \ @@ -302,7 +308,7 @@ curl -sS -X POST \ }' ``` -4. 验证接收方账户已存在 pusher: +4. 验证接收账号已经存在 pusher: ```bash curl -sS \ @@ -310,9 +316,9 @@ curl -sS \ "https://matrix.example.org/_matrix/client/v3/pushers" ``` -如果这里返回没有活动 pusher 或设备,请先修复普通 Matrix 通知,再添加下方的 OpenClaw 规则。 +如果这里没有返回任何活动的 pusher/设备,请先修复普通的 Matrix 通知,再添加下面的 OpenClaw 规则。 -OpenClaw 会使用以下标记来标识已定稿的纯文本预览编辑: +OpenClaw 会用以下标记来标识已定稿的纯文本预览编辑: ```json { @@ -320,7 +326,7 @@ OpenClaw 会使用以下标记来标识已定稿的纯文本预览编辑: } ``` -5. 为每个应接收此类通知的接收方账户创建一条 override push 规则: +5. 为每个应收到这些通知的接收账号创建一条 override 推送规则: ```bash curl -sS -X PUT \ @@ -350,23 +356,23 @@ curl -sS -X PUT \ }' ``` -运行命令前,请替换以下值: +在运行该命令前,请替换以下值: - `https://matrix.example.org`:你的 homeserver 基础 URL -- `$USER_ACCESS_TOKEN`:接收方用户的 access token -- `openclaw-finalized-preview-botname`:对此接收方用户和此机器人的唯一规则 ID -- `@bot:example.org`:你的 OpenClaw Matrix 机器人 MXID,而不是接收方用户的 MXID +- `$USER_ACCESS_TOKEN`:接收用户的访问令牌 +- `openclaw-finalized-preview-botname`:对此接收用户而言、此机器人专用且唯一的规则 ID +- `@bot:example.org`:你的 OpenClaw Matrix 机器人 MXID,而不是接收用户的 MXID -对于多机器人部署,重要说明: +对多机器人设置很重要: -- Push 规则以 `ruleId` 为键。对同一个规则 ID 重复执行 `PUT` 会更新该条规则。 -- 如果同一个接收用户需要对多个 OpenClaw Matrix 机器人账户触发通知,请为每个机器人分别创建一条规则,并为每个 `sender` 匹配使用唯一的规则 ID。 +- 推送规则以 `ruleId` 为键。对同一个规则 ID 重复执行 `PUT` 会更新该条规则。 +- 如果同一个接收用户需要对多个 OpenClaw Matrix 机器人账号触发通知,请为每个机器人各创建一条规则,并为每个 `sender` 匹配使用唯一的规则 ID。 - 一个简单的命名模式是 `openclaw-finalized-preview-`,例如 `openclaw-finalized-preview-ops` 或 `openclaw-finalized-preview-support`。 -该规则会针对事件发送者进行匹配: +该规则会根据事件发送者进行评估: -- 使用接收用户的 token 进行认证 -- 将 `sender` 与 OpenClaw 机器人的 MXID 进行匹配 +- 使用接收用户的令牌进行认证 +- 将 `sender` 与 OpenClaw 机器人 MXID 匹配 6. 验证规则是否存在: @@ -376,9 +382,9 @@ curl -sS \ "https://matrix.example.org/_matrix/client/v3/pushrules/global/override/openclaw-finalized-preview-botname" ``` -7. 测试一次流式回复。在 quiet 模式下,房间中应显示一条静默草稿预览,并且当块或轮次结束时,最终的原地编辑应触发一次通知。 +7. 测试一条流式回复。在静默模式下,房间中应显示一条静默草稿预览,并且最终的原地编辑应在该块或整轮完成时触发一次通知。 -如果你之后需要移除该规则,请使用接收用户的 token 删除同一个规则 ID: +如果你之后需要移除该规则,请使用接收用户的令牌删除同一个规则 ID: ```bash curl -sS -X DELETE \ @@ -386,35 +392,35 @@ curl -sS -X DELETE \ "https://matrix.example.org/_matrix/client/v3/pushrules/global/override/openclaw-finalized-preview-botname" ``` -说明: +注意: -- 创建规则时请使用接收用户的 access token,而不是机器人的。 +- 使用接收用户的访问令牌创建规则,而不是机器人的令牌。 - 新建的用户自定义 `override` 规则会插入到默认抑制规则之前,因此不需要额外的排序参数。 -- 这只影响 OpenClaw 能够安全原地定稿的纯文本预览编辑。媒体回退和过期预览回退仍会使用普通 Matrix 发送方式。 -- 如果 `GET /_matrix/client/v3/pushers` 显示没有 pusher,说明该用户在此账户或设备上还没有可用的 Matrix push 投递。 +- 这只影响 OpenClaw 能够安全原地定稿的纯文本预览编辑。媒体回退和过期预览回退仍会使用普通 Matrix 投递。 +- 如果 `GET /_matrix/client/v3/pushers` 显示没有 pusher,说明该用户在此账号/设备上尚未配置可用的 Matrix 推送投递。 #### Synapse -对于 Synapse,通常只需完成上述设置即可: +对于 Synapse,以上设置通常本身就足够了: -- 不需要为 OpenClaw 已定稿预览通知专门修改 `homeserver.yaml`。 -- 如果你的 Synapse 部署已经能够发送普通 Matrix push 通知,那么上面的用户 token + `pushrules` 调用就是主要设置步骤。 -- 如果你的 Synapse 运行在反向代理或 workers 后面,请确保 `/_matrix/client/.../pushrules/` 能正确到达 Synapse。 -- 如果你使用 Synapse workers,请确保 pushers 状态健康。Push 投递由主进程或 `synapse.app.pusher` / 已配置的 pusher workers 处理。 +- finalized OpenClaw 预览通知不需要特殊的 `homeserver.yaml` 变更。 +- 如果你的 Synapse 部署已经能发送普通 Matrix 推送通知,那么上面的用户令牌 + `pushrules` 调用就是主要设置步骤。 +- 如果你在反向代理或 workers 后运行 Synapse,请确保 `/_matrix/client/.../pushrules/` 能正确到达 Synapse。 +- 如果你运行的是 Synapse workers,请确保 pusher 状态健康。推送投递由主进程或 `synapse.app.pusher` / 已配置的 pusher workers 处理。 #### Tuwunel -对于 Tuwunel,使用与上方相同的设置流程和 push-rule API 调用: +对于 Tuwunel,请使用上文所示的相同设置流程和推送规则 API 调用: -- 对于已定稿预览标记本身,不需要任何 Tuwunel 特定配置。 -- 如果该用户的普通 Matrix 通知已经正常工作,那么上面的用户 token + `pushrules` 调用就是主要设置步骤。 -- 如果用户在另一台设备活跃时通知似乎消失了,请检查是否启用了 `suppress_push_when_active`。Tuwunel 在 2025 年 9 月 12 日发布的 Tuwunel 1.4.2 中加入了该选项,它可能会在一台设备活跃时故意抑制发往其他设备的 push。 +- finalized preview 标记本身不需要任何 Tuwunel 专用配置。 +- 如果该用户的普通 Matrix 通知已经正常工作,那么上面的用户令牌 + `pushrules` 调用就是主要设置步骤。 +- 如果通知似乎会在用户正在另一台设备上活跃时消失,请检查是否启用了 `suppress_push_when_active`。Tuwunel 在 2025 年 9 月 12 日发布的 Tuwunel 1.4.2 中加入了该选项,它可能会在某一台设备处于活跃状态时,有意抑制向其他设备发送推送。 ## 机器人到机器人的房间 -默认情况下,来自其他已配置 OpenClaw Matrix 账户的 Matrix 消息会被忽略。 +默认情况下,来自其他已配置 OpenClaw Matrix 账号的 Matrix 消息会被忽略。 -如果你有意启用智能体之间的 Matrix 通信,请使用 `allowBots`: +当你确实需要智能体之间的 Matrix 通信时,请使用 `allowBots`: ```json5 { @@ -431,17 +437,17 @@ curl -sS -X DELETE \ } ``` -- `allowBots: true` 会在允许的房间和私信中接受来自其他已配置 Matrix 机器人账户的消息。 -- `allowBots: "mentions"` 仅在这些消息在房间中明确提及此机器人时接受。私信仍然允许。 -- `groups..allowBots` 会覆盖账户级设置,仅对某一个房间生效。 +- `allowBots: true` 会在允许的房间和私信中接受来自其他已配置 Matrix 机器人账号的消息。 +- `allowBots: "mentions"` 仅在这些消息在房间中明确提及此机器人时才接受。私信仍然允许。 +- `groups..allowBots` 会覆盖该房间的账号级设置。 - OpenClaw 仍会忽略来自同一个 Matrix 用户 ID 的消息,以避免自回复循环。 -- Matrix 在这里不提供原生的机器人标记;OpenClaw 将“机器人发送”定义为“由此 OpenClaw Gateway 网关上另一个已配置的 Matrix 账户发送”。 +- Matrix 在这里不会暴露原生的机器人标记;OpenClaw 将“由机器人撰写”视为“由此 OpenClaw Gateway 网关上另一个已配置的 Matrix 账号发送”。 -在共享房间中启用机器人到机器人通信时,请使用严格的房间允许列表和提及要求。 +在共享房间中启用机器人到机器人流量时,请使用严格的房间 allowlist 和提及要求。 -## 加密和验证 +## 加密与验证 -在加密的(E2EE)房间中,出站图片事件使用 `thumbnail_file`,因此图片预览会与完整附件一起被加密。未加密房间仍使用普通的 `thumbnail_url`。无需额外配置——该插件会自动检测 E2EE 状态。 +在加密(E2EE)房间中,出站图片事件会使用 `thumbnail_file`,因此图片预览会与完整附件一起加密。未加密房间仍使用普通的 `thumbnail_url`。无需配置——插件会自动检测 E2EE 状态。 启用加密: @@ -477,19 +483,19 @@ openclaw matrix verify status --verbose openclaw matrix verify status --include-recovery-key --json ``` -初始化 cross-signing 和验证状态: +引导 cross-signing 和验证状态: ```bash openclaw matrix verify bootstrap ``` -详细的初始化诊断: +详细的引导诊断: ```bash openclaw matrix verify bootstrap --verbose ``` -在初始化之前强制重置为全新的 cross-signing 身份: +在引导前强制重置 cross-signing 身份: ```bash openclaw matrix verify bootstrap --force-reset-cross-signing @@ -531,18 +537,18 @@ openclaw matrix verify backup restore openclaw matrix verify backup restore --verbose ``` -删除当前服务器备份并创建一个全新的备份基线。如果已存储的备份密钥无法被干净地加载,此重置也可以重新创建 secret storage,以便未来冷启动时能够加载新的备份密钥: +删除当前服务器备份并创建一个全新的备份基线。如果已存储的备份密钥无法被干净地加载,此重置也可以重建 secret storage,以便未来冷启动时能够加载新的备份密钥: ```bash openclaw matrix verify backup reset --yes ``` 所有 `verify` 命令默认都保持简洁(包括安静的内部 SDK 日志),只有在使用 `--verbose` 时才显示详细诊断信息。 -编写脚本时,请使用 `--json` 获取完整的机器可读输出。 +在编写脚本时,请使用 `--json` 获取完整的机器可读输出。 -在多账户设置中,Matrix CLI 命令会使用隐式的 Matrix 默认账户,除非你传入 `--account `。 -如果你配置了多个命名账户,请先设置 `channels.matrix.defaultAccount`,否则这些隐式 CLI 操作会停止并要求你显式选择账户。 -当你希望验证或设备操作明确针对某个命名账户时,请使用 `--account`: +在多账号设置中,除非你传入 `--account `,否则 Matrix CLI 命令会使用隐式的 Matrix 默认账号。 +如果你配置了多个命名账号,请先设置 `channels.matrix.defaultAccount`,否则这些隐式 CLI 操作会停止并要求你明确选择一个账号。 +当你希望验证或设备操作明确针对某个命名账号时,请使用 `--account`: ```bash openclaw matrix verify status --account assistant @@ -550,40 +556,40 @@ openclaw matrix verify backup restore --account assistant openclaw matrix devices list --account assistant ``` -当某个命名账户的加密被禁用或不可用时,Matrix 警告和验证错误会指向该账户的配置键,例如 `channels.matrix.accounts.assistant.encryption`。 +当某个命名账号的加密被禁用或不可用时,Matrix 警告和验证错误会指向该账号的配置键,例如 `channels.matrix.accounts.assistant.encryption`。 -### “已验证”的含义 +### “已验证” 的含义 只有当这个 Matrix 设备已被你自己的 cross-signing 身份验证时,OpenClaw 才会将其视为已验证。 在实践中,`openclaw matrix verify status --verbose` 会暴露三个信任信号: -- `Locally trusted`:该设备仅被当前客户端本地信任 +- `Locally trusted`:该设备仅被当前客户端信任 - `Cross-signing verified`:SDK 报告该设备已通过 cross-signing 验证 - `Signed by owner`:该设备已由你自己的 self-signing 密钥签名 只有在存在 cross-signing 验证或 owner-signing 时,`Verified by owner` 才会变为 `yes`。 -仅有本地信任并不足以让 OpenClaw 将该设备视为完全已验证。 +仅有本地信任还不足以让 OpenClaw 将设备视为完全已验证。 ### bootstrap 会做什么 -`openclaw matrix verify bootstrap` 是加密 Matrix 账户的修复和设置命令。 -它会按顺序执行以下所有操作: +`openclaw matrix verify bootstrap` 是针对加密 Matrix 账号的修复和设置命令。 +它会按顺序完成以下所有操作: -- 初始化 secret storage,并尽可能复用现有恢复密钥 -- 初始化 cross-signing,并上传缺失的公开 cross-signing 密钥 +- 引导 secret storage,并尽可能复用现有恢复密钥 +- 引导 cross-signing 并上传缺失的公开 cross-signing 密钥 - 尝试标记并 cross-sign 当前设备 -- 如果服务器端尚不存在房间密钥备份,则创建一个新的备份 +- 如果服务器端房间密钥备份尚不存在,则创建一个新的备份 -如果 homeserver 在上传 cross-signing 密钥时要求交互式认证,OpenClaw 会先尝试无认证上传,然后尝试 `m.login.dummy`,最后在配置了 `channels.matrix.password` 时尝试 `m.login.password`。 +如果 homeserver 在上传 cross-signing 密钥时需要交互式认证,OpenClaw 会先尝试不带认证上传,然后尝试使用 `m.login.dummy`,如果配置了 `channels.matrix.password`,再尝试使用 `m.login.password`。 -只有在你明确希望丢弃当前 cross-signing 身份并创建新身份时,才使用 `--force-reset-cross-signing`。 +只有当你明确希望丢弃当前 cross-signing 身份并创建新身份时,才使用 `--force-reset-cross-signing`。 -如果你明确希望丢弃当前房间密钥备份,并为未来消息建立一个新的备份基线,请使用 `openclaw matrix verify backup reset --yes`。 -只有在你接受无法恢复的旧加密历史将继续不可用,并且 OpenClaw 可能会在当前备份密钥无法安全加载时重新创建 secret storage 的情况下,才这样做。 +如果你明确希望丢弃当前房间密钥备份,并为未来消息建立新的备份基线,请使用 `openclaw matrix verify backup reset --yes`。 +仅当你接受无法恢复的旧加密历史将继续不可用,并且接受在当前备份密钥无法安全加载时 OpenClaw 可能会重建 secret storage,才应这样做。 ### 全新的备份基线 -如果你希望未来的加密消息继续可用,并接受失去无法恢复的旧历史,请按顺序运行以下命令: +如果你希望未来的加密消息继续正常工作,并接受丢失无法恢复的旧历史,请按顺序运行以下命令: ```bash openclaw matrix verify backup reset --yes @@ -591,53 +597,53 @@ openclaw matrix verify backup status --verbose openclaw matrix verify status ``` -如果你希望明确指定某个命名 Matrix 账户,请为每个命令添加 `--account `。 +如果你希望明确指定某个命名 Matrix 账号,请为每条命令添加 `--account `。 ### 启动行为 -当 `encryption: true` 时,Matrix 会将 `startupVerification` 默认设为 `"if-unverified"`。 -启动时,如果该设备仍未验证,Matrix 会在另一个 Matrix 客户端中请求自我验证;如果已有一个请求处于待处理状态,则跳过重复请求;并在重启后重试前应用本地冷却时间。 -默认情况下,失败的请求尝试会比成功创建请求后更早重试。 -如果你想禁用自动启动请求,请设置 `startupVerification: "off"`;如果你希望缩短或延长重试窗口,请调整 `startupVerificationCooldownHours`。 +当 `encryption: true` 时,Matrix 默认会将 `startupVerification` 设为 `"if-unverified"`。 +启动时,如果该设备仍未验证,Matrix 会在另一个 Matrix 客户端中请求自验证,在已有待处理请求时跳过重复请求,并在重启后重试前应用本地冷却时间。 +默认情况下,失败的请求尝试会比成功创建请求后的重试更早再次进行。 +如果你想禁用自动启动请求,请设置 `startupVerification: "off"`;如果你想缩短或延长重试窗口,请调整 `startupVerificationCooldownHours`。 -启动时也会自动执行一次保守的加密 bootstrap 检查。 -该检查会优先尝试复用当前的 secret storage 和 cross-signing 身份,并避免重置 cross-signing,除非你运行了显式的 bootstrap 修复流程。 +启动时还会自动执行一次保守的加密 bootstrap 检查。 +该检查会优先尝试复用当前的 secret storage 和 cross-signing 身份,并避免重置 cross-signing,除非你显式运行 bootstrap 修复流程。 -如果启动时仍发现 bootstrap 状态损坏,即使未配置 `channels.matrix.password`,OpenClaw 也可以尝试受保护的修复路径。 -如果 homeserver 要求密码型 UIA 才能完成该修复,OpenClaw 会记录一条警告,并保持启动为非致命错误,而不是中止机器人。 -如果当前设备已经由 owner 签名,OpenClaw 会保留该身份,而不会自动重置它。 +如果启动时仍然发现损坏的 bootstrap 状态,即使未配置 `channels.matrix.password`,OpenClaw 也可以尝试执行受保护的修复路径。 +如果 homeserver 为该修复要求基于密码的 UIA,OpenClaw 会记录一条警告,并保持启动为非致命状态,而不是中止机器人。 +如果当前设备已经由 owner 签名,OpenClaw 会保留该身份,而不是自动重置它。 -完整的升级流程、限制、恢复命令和常见迁移消息,请参见 [Matrix migration](/zh-CN/install/migrating-matrix)。 +完整的升级流程、限制、恢复命令和常见迁移消息,请参阅 [Matrix 迁移](/zh-CN/install/migrating-matrix)。 ### 验证通知 -Matrix 会将验证生命周期通知直接作为 `m.notice` 消息发布到严格的私信验证房间中。 -包括: +Matrix 会将验证生命周期通知直接作为 `m.notice` 消息发布到严格私信验证房间中。 +这包括: - 验证请求通知 -- 验证就绪通知(包含明确的“通过表情符号验证”指引) +- 验证就绪通知(带有明确的“通过表情符号验证”指引) - 验证开始和完成通知 -- SAS 详情(如果可用,包括表情符号和十进制数字) +- SAS 详情(表情符号和十进制),如可用 -来自其他 Matrix 客户端的传入验证请求会被 OpenClaw 跟踪并自动接受。 -对于自我验证流程,当表情符号验证可用时,OpenClaw 也会自动启动 SAS 流程并确认自己这一侧。 -对于来自其他 Matrix 用户或设备的验证请求,OpenClaw 会自动接受请求,然后等待 SAS 流程正常继续。 -你仍然需要在你的 Matrix 客户端中比对表情符号或十进制 SAS,并在那里确认“它们匹配”,才能完成验证。 +来自另一个 Matrix 客户端的传入验证请求会被 OpenClaw 跟踪并自动接受。 +对于自验证流程,当表情符号验证可用时,OpenClaw 也会自动启动 SAS 流程并确认自己这一侧。 +对于来自另一个 Matrix 用户/设备的验证请求,OpenClaw 会自动接受该请求,然后等待 SAS 流程正常继续。 +你仍然需要在你的 Matrix 客户端中比对表情符号或十进制 SAS,并在其中确认“它们匹配”,以完成验证。 -OpenClaw 不会盲目自动接受由自己发起的重复流程。当已有自我验证请求处于待处理状态时,启动过程会跳过创建新请求。 +OpenClaw 不会盲目自动接受由自己发起的重复流程。如果已存在待处理的自验证请求,启动时会跳过创建新请求。 -验证协议或系统通知不会转发到智能体聊天管道,因此不会产生 `NO_REPLY`。 +验证协议/系统通知不会被转发到智能体聊天管道,因此不会产生 `NO_REPLY`。 -### 设备清理 +### 设备卫生 -旧的由 OpenClaw 管理的 Matrix 设备可能会在账户中不断累积,使加密房间的信任状态更难判断。 -使用以下命令列出它们: +账号中可能会累积旧的由 OpenClaw 管理的 Matrix 设备,从而使加密房间的信任状态更难判断。 +可使用以下命令列出它们: ```bash openclaw matrix devices list ``` -使用以下命令移除过期的 OpenClaw 管理设备: +使用以下命令移除过期的由 OpenClaw 管理的设备: ```bash openclaw matrix devices prune-stale @@ -645,67 +651,67 @@ openclaw matrix devices prune-stale ### 加密存储 -Matrix E2EE 在 Node 中使用官方 `matrix-js-sdk` 的 Rust 加密路径,并以 `fake-indexeddb` 作为 IndexedDB shim。加密状态会持久化到一个快照文件(`crypto-idb-snapshot.json`)并在启动时恢复。该快照文件属于敏感运行时状态,使用严格的文件权限存储。 +Matrix E2EE 在 Node 中使用官方 `matrix-js-sdk` 的 Rust 加密路径,并以 `fake-indexeddb` 作为 IndexedDB shim。加密状态会持久化到快照文件(`crypto-idb-snapshot.json`)中,并在启动时恢复。该快照文件属于敏感的运行时状态,使用严格的文件权限进行存储。 -加密运行时状态位于按账户、按用户 token 哈希划分的根目录下: +加密运行时状态位于按账号、按用户 token 哈希划分的根目录下: `~/.openclaw/matrix/accounts//__//`。 该目录包含同步存储(`bot-storage.json`)、加密存储(`crypto/`)、 恢复密钥文件(`recovery-key.json`)、IndexedDB 快照(`crypto-idb-snapshot.json`)、 线程绑定(`thread-bindings.json`)以及启动验证状态(`startup-verification.json`)。 -当 token 发生变化但账户身份保持不变时,OpenClaw 会为该账户 / homeserver / 用户元组复用最合适的现有根目录,以便先前的同步状态、加密状态、线程绑定和启动验证状态仍然可见。 +当 token 发生变化但账号身份保持不变时,OpenClaw 会为该 account/homeserver/user 元组复用最佳的现有根目录,以便先前的同步状态、加密状态、线程绑定和启动验证状态仍然可见。 -## 配置文件管理 +## 资料管理 -使用以下命令为所选账户更新 Matrix 自身配置文件: +使用以下命令更新所选账号的 Matrix 自身资料: ```bash openclaw matrix profile set --name "OpenClaw Assistant" openclaw matrix profile set --avatar-url https://cdn.example.org/avatar.png ``` -如果你想显式指定某个命名 Matrix 账户,请添加 `--account `。 +当你希望明确指定某个命名 Matrix 账号时,请添加 `--account `。 -Matrix 可直接接受 `mxc://` 头像 URL。当你传入 `http://` 或 `https://` 头像 URL 时,OpenClaw 会先将其上传到 Matrix,然后将解析后的 `mxc://` URL 回写到 `channels.matrix.avatarUrl`(或所选账户的覆盖配置)中。 +Matrix 可直接接受 `mxc://` 头像 URL。当你传入 `http://` 或 `https://` 头像 URL 时,OpenClaw 会先将其上传到 Matrix,然后将解析得到的 `mxc://` URL 回写到 `channels.matrix.avatarUrl`(或所选账号的覆盖配置)中。 ## 线程 -Matrix 同时支持自动回复和消息工具发送使用原生 Matrix 线程。 +Matrix 同时支持自动回复和 message-tool 发送使用原生 Matrix 线程。 -- `dm.sessionScope: "per-user"`(默认)会将 Matrix 私信路由保持为发送者作用域,因此多个私信房间在解析为同一对端时可以共享一个会话。 -- `dm.sessionScope: "per-room"` 会将每个 Matrix 私信房间隔离到各自的会话键中,同时仍使用普通私信认证和允许列表检查。 -- 显式的 Matrix 会话绑定仍然优先于 `dm.sessionScope`,因此已绑定的房间和线程会保留它们选择的目标会话。 -- `threadReplies: "off"` 会让回复保持在顶层,并将传入的线程消息保留在父会话上。 -- `threadReplies: "inbound"` 仅当传入消息本身已经在该线程中时,才在线程内回复。 -- `threadReplies: "always"` 会将房间回复保持在线程中,该线程以触发消息为根,并从第一条触发消息开始通过匹配的线程作用域会话路由该会话。 -- `dm.threadReplies` 仅对私信覆盖顶层设置。例如,你可以让房间线程保持隔离,同时让私信保持扁平。 +- `dm.sessionScope: "per-user"`(默认)会让 Matrix 私信路由保持按发送者作用域,因此多个私信房间在解析为同一对端时可以共享一个会话。 +- `dm.sessionScope: "per-room"` 会将每个 Matrix 私信房间隔离为各自独立的会话键,同时仍使用普通的私信认证和 allowlist 检查。 +- 显式的 Matrix 会话绑定仍然优先生效,因此已绑定的房间和线程会保持其选定的目标会话。 +- `threadReplies: "off"` 会让回复保持在顶层,并让传入的线程消息继续使用父会话。 +- `threadReplies: "inbound"` 仅当传入消息本身已经位于某个线程中时,才在线程内回复。 +- `threadReplies: "always"` 会让房间回复保持在线程中,线程根为触发消息,并从第一条触发消息开始,通过匹配的线程作用域会话路由该会话。 +- `dm.threadReplies` 仅覆盖私信的顶层设置。例如,你可以让房间线程保持隔离,同时让私信保持扁平。 - 传入的线程消息会将线程根消息作为额外的智能体上下文一并包含。 -- 当目标是同一房间,或同一私信用户目标时,消息工具发送会自动继承当前 Matrix 线程,除非显式提供了 `threadId`。 -- 只有当当前会话元数据能够证明是在同一个 Matrix 账户下与同一个私信对端通信时,才会复用同会话的私信用户目标;否则 OpenClaw 会回退到普通的用户作用域路由。 -- 当 OpenClaw 发现某个 Matrix 私信房间与同一个共享 Matrix 私信会话中的另一个私信房间冲突时,如果启用了线程绑定并设置了 `dm.sessionScope` 提示,它会在该房间中发布一次性 `m.notice`,提示可使用 `/focus` 作为跳出方案。 +- 当目标是同一个房间,或同一个私信用户目标时,message-tool 发送会自动继承当前 Matrix 线程,除非显式提供了 `threadId`。 +- 同一会话的私信用户目标复用,只有在当前会话元数据能够证明它是在同一个 Matrix 账号上的同一私信对端时才会生效;否则 OpenClaw 会回退到普通的按用户作用域路由。 +- 当 OpenClaw 发现某个 Matrix 私信房间与另一个私信房间在同一个共享 Matrix 私信会话上发生冲突时,如果启用了线程绑定并设置了 `dm.sessionScope` 提示,它会在该房间中发布一次性的 `m.notice`,其中包含 `/focus` 逃生口。 - Matrix 支持运行时线程绑定。`/focus`、`/unfocus`、`/agents`、`/session idle`、`/session max-age` 以及线程绑定的 `/acp spawn` 都可在 Matrix 房间和私信中使用。 -- 当 `threadBindings.spawnSubagentSessions=true` 时,在顶层 Matrix 房间 / 私信中执行 `/focus` 会创建一个新的 Matrix 线程,并将其绑定到目标会话。 -- 在现有 Matrix 线程中执行 `/focus` 或 `/acp spawn --thread here` 时,则会改为绑定当前线程本身。 +- 当 `threadBindings.spawnSubagentSessions=true` 时,在 Matrix 房间/私信顶层执行 `/focus` 会创建一个新的 Matrix 线程,并将其绑定到目标会话。 +- 在现有 Matrix 线程内运行 `/focus` 或 `/acp spawn --thread here`,则会改为绑定当前线程本身。 ## ACP 会话绑定 -Matrix 房间、私信和现有 Matrix 线程都可以在不改变聊天界面的情况下转换为持久化 ACP 工作区。 +Matrix 房间、私信以及现有 Matrix 线程都可以变成持久化的 ACP 工作区,而无需更改聊天界面。 快速操作流程: -- 在你希望继续使用的 Matrix 私信、房间或现有线程中运行 `/acp spawn codex --bind here`。 -- 在顶层 Matrix 私信或房间中,当前私信 / 房间会继续作为聊天界面,后续消息会路由到新创建的 ACP 会话。 -- 在现有 Matrix 线程中,`--bind here` 会直接原位绑定当前线程。 -- `/new` 和 `/reset` 会原位重置同一个已绑定 ACP 会话。 -- `/acp close` 会关闭 ACP 会话并移除绑定。 +- 在你想继续使用的 Matrix 私信、房间或现有线程中运行 `/acp spawn codex --bind here`。 +- 在 Matrix 私信或房间的顶层,当前私信/房间会继续作为聊天界面,后续消息会被路由到新建的 ACP 会话。 +- 在现有 Matrix 线程内部,`--bind here` 会将当前线程原地绑定。 +- `/new` 和 `/reset` 会原地重置同一个已绑定的 ACP 会话。 +- `/acp close` 会关闭 ACP 会话并移除该绑定。 -说明: +注意: - `--bind here` 不会创建子 Matrix 线程。 -- `threadBindings.spawnAcpSessions` 只在 `/acp spawn --thread auto|here` 时需要,因为此时 OpenClaw 需要创建或绑定一个子 Matrix 线程。 +- 只有在使用 `/acp spawn --thread auto|here` 时,才需要 `threadBindings.spawnAcpSessions`,因为此时 OpenClaw 需要创建或绑定一个子 Matrix 线程。 ### 线程绑定配置 -Matrix 会继承 `session.threadBindings` 中的全局默认值,同时也支持按渠道覆盖: +Matrix 会继承来自 `session.threadBindings` 的全局默认值,同时也支持按渠道覆盖: - `threadBindings.enabled` - `threadBindings.idleHours` @@ -713,64 +719,64 @@ Matrix 会继承 `session.threadBindings` 中的全局默认值,同时也支 - `threadBindings.spawnSubagentSessions` - `threadBindings.spawnAcpSessions` -Matrix 的线程绑定 spawn 标志为可选启用: +Matrix 的线程绑定 spawn 标志为显式启用: -- 设置 `threadBindings.spawnSubagentSessions: true`,以允许顶层 `/focus` 创建并绑定新的 Matrix 线程。 -- 设置 `threadBindings.spawnAcpSessions: true`,以允许 `/acp spawn --thread auto|here` 将 ACP 会话绑定到 Matrix 线程。 +- 设置 `threadBindings.spawnSubagentSessions: true` 以允许顶层 `/focus` 创建并绑定新的 Matrix 线程。 +- 设置 `threadBindings.spawnAcpSessions: true` 以允许 `/acp spawn --thread auto|here` 将 ACP 会话绑定到 Matrix 线程。 -## 回应 +## Reactions -Matrix 支持出站回应操作、入站回应通知和入站 ack 回应。 +Matrix 支持出站 reaction 操作、入站 reaction 通知,以及入站确认 reaction。 -- 出站回应工具由 `channels["matrix"].actions.reactions` 控制。 -- `react` 会向特定 Matrix 事件添加一个回应。 -- `reactions` 会列出特定 Matrix 事件的当前回应汇总。 -- `emoji=""` 会移除机器人账户在该事件上的所有自身回应。 -- `remove: true` 只会移除机器人账户上的指定 emoji 回应。 +- 出站 reaction 工具受 `channels["matrix"].actions.reactions` 控制。 +- `react` 会向特定的 Matrix 事件添加一个 reaction。 +- `reactions` 会列出特定 Matrix 事件当前的 reaction 摘要。 +- `emoji=""` 会移除机器人账号在该事件上的自身 reaction。 +- `remove: true` 只会移除该机器人账号上的指定 emoji reaction。 -ack 回应使用标准 OpenClaw 解析顺序: +确认 reaction 使用标准 OpenClaw 解析顺序: - `channels["matrix"].accounts..ackReaction` - `channels["matrix"].ackReaction` - `messages.ackReaction` -- 智能体身份 emoji 回退值 +- 智能体身份 emoji 回退 -ack 回应作用域按以下顺序解析: +确认 reaction 作用域按以下顺序解析: - `channels["matrix"].accounts..ackReactionScope` - `channels["matrix"].ackReactionScope` - `messages.ackReactionScope` -回应通知模式按以下顺序解析: +Reaction 通知模式按以下顺序解析: - `channels["matrix"].accounts..reactionNotifications` - `channels["matrix"].reactionNotifications` -- 默认:`own` +- 默认值:`own` 行为: -- `reactionNotifications: "own"` 会在新增的 `m.reaction` 事件目标是机器人发送的 Matrix 消息时转发这些事件。 -- `reactionNotifications: "off"` 会禁用回应系统事件。 -- 回应移除不会被合成为系统事件,因为 Matrix 将它们表现为 redaction,而不是独立的 `m.reaction` 移除事件。 +- `reactionNotifications: "own"` 会在新增的 `m.reaction` 事件指向机器人撰写的 Matrix 消息时将其转发。 +- `reactionNotifications: "off"` 会禁用 reaction 系统事件。 +- reaction 移除不会被合成为系统事件,因为 Matrix 将其作为 redaction 暴露,而不是作为独立的 `m.reaction` 移除事件暴露。 ## 历史上下文 - `channels.matrix.historyLimit` 控制当 Matrix 房间消息触发智能体时,作为 `InboundHistory` 包含多少条最近的房间消息。它会回退到 `messages.groupChat.historyLimit`;如果两者都未设置,则有效默认值为 `0`。设置为 `0` 可禁用。 - Matrix 房间历史仅限房间。私信仍使用普通会话历史。 -- Matrix 房间历史是仅待处理的:OpenClaw 会缓冲那些尚未触发回复的房间消息,然后在提及或其他触发条件到来时对该窗口进行快照。 -- 当前触发消息不会包含在 `InboundHistory` 中;它会保留在该轮次的主入站消息体中。 -- 同一个 Matrix 事件的重试会复用原始历史快照,而不是漂移到更新的房间消息。 +- Matrix 房间历史是仅待处理的:OpenClaw 会缓冲那些尚未触发回复的房间消息,然后在提及或其他触发到来时,对该窗口拍摄快照。 +- 当前触发消息不会包含在 `InboundHistory` 中;该轮中它会保留在主入站正文里。 +- 对同一个 Matrix 事件的重试会复用原始历史快照,而不是漂移到更新的房间消息。 ## 上下文可见性 -Matrix 支持共享的 `contextVisibility` 控制,用于补充房间上下文,例如获取到的回复文本、线程根消息和待处理历史。 +Matrix 支持共享的 `contextVisibility` 控制,用于补充房间上下文,例如获取到的回复文本、线程根和待处理历史。 -- `contextVisibility: "all"` 为默认值。补充上下文会按接收到的内容保留。 -- `contextVisibility: "allowlist"` 会根据当前房间 / 用户允许列表检查,过滤补充上下文中的发送者。 -- `contextVisibility: "allowlist_quote"` 的行为与 `allowlist` 类似,但仍会保留一条显式引用回复。 +- `contextVisibility: "all"` 是默认值。补充上下文会按接收时原样保留。 +- `contextVisibility: "allowlist"` 会将补充上下文过滤为通过当前房间/用户 allowlist 检查的发送者。 +- `contextVisibility: "allowlist_quote"` 的行为类似 `allowlist`,但仍会保留一条显式引用回复。 此设置影响的是补充上下文的可见性,而不是入站消息本身是否可以触发回复。 -触发授权仍由 `groupPolicy`、`groups`、`groupAllowFrom` 和私信策略设置决定。 +触发授权仍然来自 `groupPolicy`、`groups`、`groupAllowFrom` 和私信策略设置。 ## 私信和房间策略 @@ -795,7 +801,7 @@ Matrix 支持共享的 `contextVisibility` 控制,用于补充房间上下文 } ``` -有关提及门控和允许列表行为,请参见 [Groups](/zh-CN/channels/groups)。 +有关提及门控和 allowlist 行为,请参阅 [群组](/zh-CN/channels/groups)。 Matrix 私信的配对示例: @@ -804,80 +810,81 @@ openclaw pairing list matrix openclaw pairing approve matrix ``` -如果某个尚未批准的 Matrix 用户在获批前持续给你发消息,OpenClaw 会复用同一个待处理配对码,并可能在短暂冷却后再次发送提醒回复,而不是签发一个新代码。 +如果某个尚未批准的 Matrix 用户在获得批准前持续向你发送消息,OpenClaw 会复用同一个待处理配对码,并且在短暂冷却后可能再次发送提醒回复,而不是创建新的配对码。 -有关共享的私信配对流程和存储布局,请参见 [Pairing](/zh-CN/channels/pairing)。 +有关共享的私信配对流程和存储布局,请参阅 [配对](/zh-CN/channels/pairing)。 ## 直接房间修复 -如果私信状态不同步,OpenClaw 可能会残留过期的 `m.direct` 映射,使其指向旧的一对一房间而不是当前活跃私信。使用以下命令检查某个对端的当前映射: +如果私信状态不同步,OpenClaw 可能会保留陈旧的 `m.direct` 映射,将其指向旧的单聊房间,而不是当前活跃的私信。使用以下命令检查某个对端当前的映射: ```bash openclaw matrix direct inspect --user-id @alice:example.org ``` -使用以下命令修复: +使用以下命令修复它: ```bash openclaw matrix direct repair --user-id @alice:example.org ``` -修复流程会: +修复流程: - 优先选择已经在 `m.direct` 中映射的严格 1:1 私信 -- 如果没有,则回退到与该用户当前已加入的任意严格 1:1 私信 -- 如果仍不存在健康的私信,则创建一个新的直连房间并重写 `m.direct` +- 如果没有,则回退到当前已加入的、与该用户的任意严格 1:1 私信 +- 如果不存在健康的私信,则创建一个新的 direct room 并重写 `m.direct` -修复流程不会自动删除旧房间。它只会选择健康的私信并更新映射,使新的 Matrix 发送、验证通知和其他私信流程重新指向正确的房间。 +修复流程不会自动删除旧房间。它只会选择健康的私信并更新映射,以便新的 Matrix 发送、验证通知和其他私信流程再次指向正确的房间。 ## Exec 审批 -Matrix 可以作为某个 Matrix 账户的原生审批客户端。原生私信 / 渠道路由控制项仍位于 exec 审批配置下: +Matrix 可以作为某个 Matrix 账号的原生审批客户端。原生 +私信/渠道路由控制项仍位于 exec 审批配置下: - `channels.matrix.execApprovals.enabled` -- `channels.matrix.execApprovals.approvers`(可选;会回退到 `channels.matrix.dm.allowFrom`) +- `channels.matrix.execApprovals.approvers`(可选;回退到 `channels.matrix.dm.allowFrom`) - `channels.matrix.execApprovals.target`(`dm` | `channel` | `both`,默认:`dm`) - `channels.matrix.execApprovals.agentFilter` - `channels.matrix.execApprovals.sessionFilter` -审批人必须是 Matrix 用户 ID,例如 `@owner:example.org`。当 `enabled` 未设置或为 `"auto"`,且至少能解析出一位审批人时,Matrix 会自动启用原生审批。Exec 审批会优先使用 `execApprovals.approvers`,并可回退到 `channels.matrix.dm.allowFrom`。插件审批则通过 `channels.matrix.dm.allowFrom` 进行授权。将 `enabled: false` 设为显式禁用 Matrix 作为原生审批客户端。否则,审批请求会回退到其他已配置的审批路径或审批回退策略。 +审批人必须是 Matrix 用户 ID,例如 `@owner:example.org`。当 `enabled` 未设置或为 `"auto"`,且至少有一个审批人可以解析时,Matrix 会自动启用原生审批。Exec 审批优先使用 `execApprovals.approvers`,并可回退到 `channels.matrix.dm.allowFrom`。插件审批通过 `channels.matrix.dm.allowFrom` 授权。设置 `enabled: false` 可显式禁用 Matrix 作为原生审批客户端。否则,审批请求会回退到其他已配置的审批路径或审批回退策略。 -Matrix 原生路由支持两种审批类型: +Matrix 原生路由同时支持两种审批类型: -- `channels.matrix.execApprovals.*` 控制 Matrix 审批提示的原生私信 / 渠道扇出模式。 +- `channels.matrix.execApprovals.*` 控制 Matrix 审批提示的原生私信/渠道扇出模式。 - Exec 审批使用来自 `execApprovals.approvers` 或 `channels.matrix.dm.allowFrom` 的 exec 审批人集合。 -- 插件审批使用来自 `channels.matrix.dm.allowFrom` 的 Matrix 私信允许列表。 -- Matrix 回应快捷方式和消息更新同时适用于 exec 审批和插件审批。 +- 插件审批使用来自 `channels.matrix.dm.allowFrom` 的 Matrix 私信 allowlist。 +- Matrix reaction 快捷方式和消息更新同时适用于 exec 审批和插件审批。 投递规则: - `target: "dm"` 会将审批提示发送到审批人的私信 -- `target: "channel"` 会将提示发回原始 Matrix 房间或私信 -- `target: "both"` 会同时发送到审批人的私信以及原始 Matrix 房间或私信 +- `target: "channel"` 会将提示发送回发起的 Matrix 房间或私信 +- `target: "both"` 会将提示发送到审批人的私信以及发起的 Matrix 房间或私信 -Matrix 审批提示会在主审批消息上添加回应快捷方式: +Matrix 审批提示会在主审批消息上预置 reaction 快捷方式: - `✅` = 允许一次 - `❌` = 拒绝 -- `♾️` = 始终允许,前提是有效 exec 策略允许该决定 +- `♾️` = 始终允许,前提是有效的 exec 策略允许该决定 -审批人可以对该消息添加回应,也可以使用回退斜杠命令:`/approve allow-once`、`/approve allow-always` 或 `/approve deny`。 +审批人可以对该消息添加 reaction,也可以使用回退斜杠命令:`/approve allow-once`、`/approve allow-always` 或 `/approve deny`。 -只有已解析出的审批人才能执行批准或拒绝。对于 exec 审批,渠道投递会包含命令文本,因此仅应在可信房间中启用 `channel` 或 `both`。 +只有已解析的审批人可以批准或拒绝。对于 exec 审批,渠道投递会包含命令文本,因此仅应在受信任房间中启用 `channel` 或 `both`。 -按账户覆盖: +按账号覆盖: - `channels.matrix.accounts..execApprovals` -相关文档:[Exec approvals](/zh-CN/tools/exec-approvals) +相关文档:[Exec 审批](/zh-CN/tools/exec-approvals) -## 斜杠命令 +## Slash commands -Matrix 斜杠命令(例如 `/new`、`/reset`、`/model`)可直接在私信中使用。在房间中,OpenClaw 也会识别以机器人自身 Matrix 提及为前缀的斜杠命令,因此 `@bot:server /new` 会触发命令路径,而不需要自定义提及正则。这使机器人能够响应 Element 及类似客户端发出的房间式 `@mention /command` 消息:用户先通过补全输入机器人,再输入命令即可。 +Matrix slash commands(例如 `/new`、`/reset`、`/model`)可直接在私信中使用。在房间中,OpenClaw 也能识别以前缀为机器人自身 Matrix 提及的 slash commands,因此 `@bot:server /new` 会触发命令路径,而无需自定义提及正则。这让机器人在 Element 和类似客户端中对房间样式的 `@mention /command` 消息保持响应,这类消息通常出现在用户先用 Tab 补全机器人,再输入命令时。 -授权规则仍然适用:命令发送者必须像普通消息一样满足私信或房间允许列表 / owner 策略。 +授权规则仍然适用:命令发送者必须像普通消息一样满足私信或房间的 allowlist/owner 策略。 -## 多账户 +## 多账号 ```json5 { @@ -907,23 +914,23 @@ Matrix 斜杠命令(例如 `/new`、`/reset`、`/model`)可直接在私信 } ``` -顶层 `channels.matrix` 值会作为命名账户的默认值,除非某个账户进行了覆盖。 -你可以通过 `groups..account` 将继承的房间条目限定到某一个 Matrix 账户。 -未设置 `account` 的条目会在所有 Matrix 账户之间共享,而设置了 `account: "default"` 的条目在默认账户直接配置于顶层 `channels.matrix.*` 时也仍然有效。 -部分共享认证默认值本身不会创建一个单独的隐式默认账户。只有当该默认账户拥有新的认证信息(`homeserver` 加 `accessToken`,或 `homeserver` 加 `userId` 和 `password`)时,OpenClaw 才会合成顶层 `default` 账户;命名账户仍可在稍后通过缓存凭证满足认证时,仅凭 `homeserver` 加 `userId` 保持可发现。 -如果 Matrix 已经恰好有一个命名账户,或者 `defaultAccount` 指向一个现有命名账户键,则从单账户到多账户的修复 / 设置提升会保留该账户,而不是新建一个 `accounts.default` 条目。只有 Matrix 的认证 / bootstrap 键会移入被提升的账户;共享的投递策略键会保留在顶层。 -当你希望 OpenClaw 在隐式路由、探测和 CLI 操作中优先使用某个命名 Matrix 账户时,请设置 `defaultAccount`。 -如果配置了多个 Matrix 账户,且其中一个账户 ID 是 `default`,即使 `defaultAccount` 未设置,OpenClaw 也会隐式使用该账户。 -如果你配置了多个命名账户,请设置 `defaultAccount`,或在依赖隐式账户选择的 CLI 命令中传入 `--account `。 -当你希望为某一条命令覆盖该隐式选择时,请向 `openclaw matrix verify ...` 和 `openclaw matrix devices ...` 传入 `--account `。 +顶层 `channels.matrix` 值会作为命名账号的默认值,除非某个账号进行了覆盖。 +你可以使用 `groups..account` 将继承的房间条目限定到某一个 Matrix 账号。 +未设置 `account` 的条目会在所有 Matrix 账号之间共享,而设置了 `account: "default"` 的条目在默认账号直接配置于顶层 `channels.matrix.*` 时也仍然有效。 +部分共享认证默认值本身不会创建一个单独的隐式默认账号。只有当该默认账号具备最新认证信息(`homeserver` 加 `accessToken`,或 `homeserver` 加 `userId` 和 `password`)时,OpenClaw 才会合成顶层 `default` 账号;命名账号仍然可以只通过 `homeserver` 加 `userId` 保持可发现性,并在稍后缓存凭证满足认证时生效。 +如果 Matrix 已经恰好存在一个命名账号,或者 `defaultAccount` 指向一个现有的命名账号键,那么从单账号到多账号的修复/设置升级会保留该账号,而不是新建一个 `accounts.default` 条目。只有 Matrix 认证/bootstrap 键会移动到该升级后的账号中;共享的投递策略键仍会保留在顶层。 +当你希望 OpenClaw 在隐式路由、探测和 CLI 操作中优先使用某个命名 Matrix 账号时,请设置 `defaultAccount`。 +如果配置了多个 Matrix 账号,并且其中一个账号 ID 为 `default`,那么即使未设置 `defaultAccount`,OpenClaw 也会隐式使用该账号。 +如果你配置了多个命名账号,请设置 `defaultAccount`,或为依赖隐式账号选择的 CLI 命令传入 `--account `。 +当你希望为单个命令覆盖该隐式选择时,请将 `--account ` 传给 `openclaw matrix verify ...` 和 `openclaw matrix devices ...`。 -共享多账户模式请参见 [Configuration reference](/zh-CN/gateway/configuration-reference#multi-account-all-channels)。 +有关共享的多账号模式,请参阅 [配置参考](/zh-CN/gateway/configuration-reference#multi-account-all-channels)。 -## 私有 / LAN homeserver +## 私有/LAN homeserver -默认情况下,出于 SSRF 防护,OpenClaw 会阻止连接私有 / 内部 Matrix homeserver,除非你为某个账户显式选择加入。 +默认情况下,出于 SSRF 防护,OpenClaw 会屏蔽私有/内部 Matrix homeserver,除非你为每个账号显式选择启用。 -如果你的 homeserver 运行在 localhost、LAN/Tailscale IP 或内部主机名上,请为该 Matrix 账户启用 +如果你的 homeserver 运行在 localhost、LAN/Tailscale IP 或内部主机名上,请为该 Matrix 账号启用 `network.dangerouslyAllowPrivateNetwork`: ```json5 @@ -950,8 +957,8 @@ openclaw matrix account add \ --access-token syt_ops_xxx ``` -此选择加入仅允许受信任的私有 / 内部目标。公共明文 homeserver,例如 -`http://matrix.example.org:8008`,仍会被阻止。尽可能优先使用 `https://`。 +此显式启用仅允许受信任的私有/内部目标。公共明文 homeserver,例如 +`http://matrix.example.org:8008`,仍会被屏蔽。请尽可能优先使用 `https://`。 ## 代理 Matrix 流量 @@ -969,86 +976,86 @@ openclaw matrix account add \ } ``` -命名账户可以通过 `channels.matrix.accounts..proxy` 覆盖顶层默认值。 -OpenClaw 会对运行时 Matrix 流量和账户状态探测使用相同的代理设置。 +命名账号可以通过 `channels.matrix.accounts..proxy` 覆盖顶层默认值。 +OpenClaw 会对运行时 Matrix 流量和账号状态探测使用同一个代理设置。 ## 目标解析 -在 OpenClaw 任何要求你提供房间或用户目标的地方,Matrix 都接受以下目标格式: +无论 OpenClaw 在何处要求你提供房间或用户目标,Matrix 都接受以下目标形式: - 用户:`@user:server`、`user:@user:server` 或 `matrix:user:@user:server` - 房间:`!room:server`、`room:!room:server` 或 `matrix:room:!room:server` - 别名:`#alias:server`、`channel:#alias:server` 或 `matrix:channel:#alias:server` -实时目录查找使用已登录的 Matrix 账户: +实时目录查找使用已登录的 Matrix 账号: - 用户查找会查询该 homeserver 上的 Matrix 用户目录。 -- 房间查找会直接接受显式房间 ID 和别名,然后回退到搜索该账户已加入房间的名称。 -- 已加入房间名称查找属于尽力而为。如果某个房间名称无法解析为 ID 或别名,它会在运行时允许列表解析中被忽略。 +- 房间查找会直接接受显式房间 ID 和别名,然后回退为搜索该账号已加入房间的名称。 +- 已加入房间名称查找属于尽力而为。如果某个房间名称无法解析为 ID 或别名,它会在运行时 allowlist 解析中被忽略。 ## 配置参考 - `enabled`:启用或禁用该渠道。 -- `name`:账户的可选标签。 -- `defaultAccount`:当配置多个 Matrix 账户时的首选账户 ID。 +- `name`:账号的可选标签。 +- `defaultAccount`:配置多个 Matrix 账号时的首选账号 ID。 - `homeserver`:homeserver URL,例如 `https://matrix.example.org`。 -- `network.dangerouslyAllowPrivateNetwork`:允许该 Matrix 账户连接到私有 / 内部 homeserver。当 homeserver 解析到 `localhost`、LAN/Tailscale IP 或内部主机(如 `matrix-synapse`)时启用此项。 -- `proxy`:Matrix 流量的可选 HTTP(S) 代理 URL。命名账户可用其自己的 `proxy` 覆盖顶层默认值。 -- `userId`:完整 Matrix 用户 ID,例如 `@bot:example.org`。 -- `accessToken`:基于 token 的认证所用 access token。`channels.matrix.accessToken` 和 `channels.matrix.accounts..accessToken` 支持明文值和 SecretRef 值,适用于 env/file/exec 提供商。参见 [Secrets Management](/zh-CN/gateway/secrets)。 -- `password`:基于密码登录所用密码。支持明文值和 SecretRef 值。 +- `network.dangerouslyAllowPrivateNetwork`:允许该 Matrix 账号连接到私有/内部 homeserver。当 homeserver 解析为 `localhost`、LAN/Tailscale IP 或内部主机(如 `matrix-synapse`)时,请启用此项。 +- `proxy`:Matrix 流量可选的 HTTP(S) 代理 URL。命名账号可使用各自的 `proxy` 覆盖顶层默认值。 +- `userId`:完整的 Matrix 用户 ID,例如 `@bot:example.org`。 +- `accessToken`:基于令牌认证所使用的访问令牌。`channels.matrix.accessToken` 和 `channels.matrix.accounts..accessToken` 在 env/file/exec 提供商中都支持明文值和 SecretRef 值。请参阅 [Secrets Management](/zh-CN/gateway/secrets)。 +- `password`:基于密码登录所使用的密码。支持明文值和 SecretRef 值。 - `deviceId`:显式 Matrix 设备 ID。 -- `deviceName`:用于密码登录的设备显示名称。 -- `avatarUrl`:用于配置文件同步和 `profile set` 更新的已存储自身头像 URL。 -- `initialSyncLimit`:启动同步期间抓取的最大事件数。 +- `deviceName`:密码登录时的设备显示名称。 +- `avatarUrl`:用于资料同步和 `profile set` 更新的已存储自身头像 URL。 +- `initialSyncLimit`:启动同步期间获取的最大事件数。 - `encryption`:启用 E2EE。 -- `allowlistOnly`:当为 `true` 时,会将 `open` 房间策略升级为 `allowlist`,并强制所有活动私信策略(除 `disabled` 外,包括 `pairing` 和 `open`)变为 `allowlist`。不影响 `disabled` 策略。 -- `allowBots`:允许来自其他已配置 OpenClaw Matrix 账户的消息(`true` 或 `"mentions"`)。 +- `allowlistOnly`:为 `true` 时,会将 `open` 房间策略升级为 `allowlist`,并将所有活跃的私信策略(除 `disabled` 外,包括 `pairing` 和 `open`)强制设为 `allowlist`。不影响 `disabled` 策略。 +- `allowBots`:允许来自其他已配置 OpenClaw Matrix 账号的消息(`true` 或 `"mentions"`)。 - `groupPolicy`:`open`、`allowlist` 或 `disabled`。 - `contextVisibility`:补充房间上下文可见性模式(`all`、`allowlist`、`allowlist_quote`)。 -- `groupAllowFrom`:用于房间流量的允许列表用户 ID。完整 Matrix 用户 ID 最安全;当监视器运行时,在启动时以及允许列表变化时会解析精确目录匹配。未解析的名称会被忽略。 +- `groupAllowFrom`:房间流量的 allowlist 用户 ID。完整 Matrix 用户 ID 最安全;精确目录匹配会在启动时以及监控运行期间 allowlist 变化时解析。无法解析的名称会被忽略。 - `historyLimit`:作为群组历史上下文包含的最大房间消息数。会回退到 `messages.groupChat.historyLimit`;如果两者都未设置,则有效默认值为 `0`。设置为 `0` 可禁用。 - `replyToMode`:`off`、`first`、`all` 或 `batched`。 -- `markdown`:用于出站 Matrix 文本的可选 Markdown 渲染配置。 -- `streaming`:`off`(默认)、`"partial"`、`"quiet"`、`true` 或 `false`。`"partial"` 和 `true` 会使用普通 Matrix 文本消息启用“预览优先”的草稿更新。`"quiet"` 会为自托管 push 规则设置使用静默预览通知。`false` 等同于 `"off"`。 -- `blockStreaming`:`true` 会在草稿预览流式传输处于活动状态时,为已完成的助手块启用单独的进度消息。 +- `markdown`:出站 Matrix 文本的可选 Markdown 渲染配置。 +- `streaming`:`off`(默认)、`"partial"`、`"quiet"`、`true` 或 `false`。`"partial"` 和 `true` 会启用使用普通 Matrix 文本消息的“预览优先”草稿更新。`"quiet"` 为自托管推送规则设置使用不触发通知的预览通知。`false` 等同于 `"off"`。 +- `blockStreaming`:`true` 会在草稿预览流式传输激活时,为已完成的智能体输出块启用单独的进度消息。 - `threadReplies`:`off`、`inbound` 或 `always`。 -- `threadBindings`:用于线程绑定会话路由和生命周期的按渠道覆盖。 -- `startupVerification`:启动时的自动自我验证请求模式(`if-unverified`、`off`)。 -- `startupVerificationCooldownHours`:重试自动启动验证请求前的冷却时间。 -- `textChunkLimit`:出站消息按字符数分块时的字符块大小(当 `chunkMode` 为 `length` 时生效)。 +- `threadBindings`:线程绑定会话路由和生命周期的按渠道覆盖。 +- `startupVerification`:启动时的自动自验证请求模式(`if-unverified`、`off`)。 +- `startupVerificationCooldownHours`:自动启动验证请求重试前的冷却时间。 +- `textChunkLimit`:出站消息按字符数分块时的块大小上限(在 `chunkMode` 为 `length` 时生效)。 - `chunkMode`:`length` 按字符数拆分消息;`newline` 按行边界拆分。 -- `responsePrefix`:可选字符串,会添加到该渠道的所有出站回复前。 -- `ackReaction`:该渠道 / 账户的可选 ack 回应覆盖值。 -- `ackReactionScope`:可选 ack 回应作用域覆盖(`group-mentions`、`group-all`、`direct`、`all`、`none`、`off`)。 -- `reactionNotifications`:入站回应通知模式(`own`、`off`)。 +- `responsePrefix`:为该渠道所有出站回复添加的可选前缀字符串。 +- `ackReaction`:该渠道/账号的可选确认 reaction 覆盖。 +- `ackReactionScope`:可选的确认 reaction 作用域覆盖(`group-mentions`、`group-all`、`direct`、`all`、`none`、`off`)。 +- `reactionNotifications`:入站 reaction 通知模式(`own`、`off`)。 - `mediaMaxMb`:出站发送和入站媒体处理的媒体大小上限(MB)。 -- `autoJoin`:邀请自动加入策略(`always`、`allowlist`、`off`)。默认:`off`。适用于所有 Matrix 邀请,包括私信式邀请。 -- `autoJoinAllowlist`:当 `autoJoin` 为 `allowlist` 时允许的房间 / 别名。别名条目会在处理邀请时解析为房间 ID;OpenClaw 不会信任受邀房间声称的别名状态。 +- `autoJoin`:邀请自动加入策略(`always`、`allowlist`、`off`)。默认值:`off`。适用于所有 Matrix 邀请,包括私信式邀请。 +- `autoJoinAllowlist`:当 `autoJoin` 为 `allowlist` 时允许的房间/别名。别名条目会在处理邀请时解析为房间 ID;OpenClaw 不会信任受邀房间声称的别名状态。 - `dm`:私信策略块(`enabled`、`policy`、`allowFrom`、`sessionScope`、`threadReplies`)。 -- `dm.policy`:控制 OpenClaw 加入房间并将其分类为私信之后的私信访问策略。它不会改变邀请是否会被自动加入。 -- `dm.allowFrom`:用于私信流量的允许列表用户 ID。完整 Matrix 用户 ID 最安全;当监视器运行时,在启动时以及允许列表变化时会解析精确目录匹配。未解析的名称会被忽略。 -- `dm.sessionScope`:`per-user`(默认)或 `per-room`。如果你希望即使对端相同,每个 Matrix 私信房间也保持独立上下文,请使用 `per-room`。 -- `dm.threadReplies`:仅私信的线程策略覆盖(`off`、`inbound`、`always`)。它会覆盖顶层 `threadReplies` 设置,影响私信中的回复位置和会话隔离。 +- `dm.policy`:控制 OpenClaw 加入房间并将其识别为私信之后的私信访问权限。它不会改变邀请是否会被自动加入。 +- `dm.allowFrom`:私信流量的 allowlist 用户 ID。完整 Matrix 用户 ID 最安全;精确目录匹配会在启动时以及监控运行期间 allowlist 变化时解析。无法解析的名称会被忽略。 +- `dm.sessionScope`:`per-user`(默认)或 `per-room`。如果你希望每个 Matrix 私信房间都保留独立上下文,即使对端相同,也请使用 `per-room`。 +- `dm.threadReplies`:仅限私信的线程策略覆盖(`off`、`inbound`、`always`)。它会覆盖顶层 `threadReplies` 设置,用于控制私信中的回复位置和会话隔离。 - `execApprovals`:Matrix 原生 exec 审批投递(`enabled`、`approvers`、`target`、`agentFilter`、`sessionFilter`)。 -- `execApprovals.approvers`:允许审批 exec 请求的 Matrix 用户 ID。如果 `dm.allowFrom` 已经标识了审批人,则此项可选。 +- `execApprovals.approvers`:允许批准 exec 请求的 Matrix 用户 ID。当 `dm.allowFrom` 已经标识审批人时,此项可选。 - `execApprovals.target`:`dm | channel | both`(默认:`dm`)。 -- `accounts`:按账户命名的覆盖项。顶层 `channels.matrix` 值会作为这些条目的默认值。 -- `groups`:按房间的策略映射。优先使用房间 ID 或别名;未解析的房间名称会在运行时被忽略。会话 / 群组身份在解析后使用稳定的房间 ID。 -- `groups..account`:在多账户设置中,将某个继承的房间条目限制到特定 Matrix 账户。 +- `accounts`:命名的按账号覆盖。顶层 `channels.matrix` 值会作为这些条目的默认值。 +- `groups`:按房间的策略映射。优先使用房间 ID 或别名;无法解析的房间名称会在运行时被忽略。解析完成后,会话/群组标识使用稳定的房间 ID。 +- `groups..account`:在多账号设置中,将某个继承的房间条目限制到特定 Matrix 账号。 - `groups..allowBots`:针对已配置机器人发送者的房间级覆盖(`true` 或 `"mentions"`)。 -- `groups..users`:按房间的发送者允许列表。 -- `groups..tools`:按房间的工具允许 / 拒绝覆盖。 -- `groups..autoReply`:房间级提及门控覆盖。`true` 会为该房间禁用提及要求;`false` 会强制重新启用。 +- `groups..users`:按房间的发送者 allowlist。 +- `groups..tools`:按房间的工具允许/拒绝覆盖。 +- `groups..autoReply`:房间级提及门控覆盖。`true` 会禁用该房间的提及要求;`false` 会强制重新开启。 - `groups..skills`:可选的房间级 Skills 过滤器。 - `groups..systemPrompt`:可选的房间级系统提示片段。 - `rooms`:`groups` 的旧别名。 - `actions`:按操作的工具门控(`messages`、`reactions`、`pins`、`profile`、`memberInfo`、`channelInfo`、`verification`)。 -## 相关 +## 相关内容 -- [Channels Overview](/zh-CN/channels) — 所有受支持的渠道 -- [Pairing](/zh-CN/channels/pairing) — 私信认证和配对流程 -- [Groups](/zh-CN/channels/groups) — 群聊行为和提及门控 -- [Channel Routing](/zh-CN/channels/channel-routing) — 消息的会话路由 -- [Security](/zh-CN/gateway/security) — 访问模型和安全加固 +- [渠道概览](/zh-CN/channels) — 所有受支持的渠道 +- [配对](/zh-CN/channels/pairing) — 私信认证和配对流程 +- [群组](/zh-CN/channels/groups) — 群聊行为和提及门控 +- [渠道路由](/zh-CN/channels/channel-routing) — 消息的会话路由 +- [安全](/zh-CN/gateway/security) — 访问模型和加固措施 diff --git a/docs/zh-CN/channels/mattermost.md b/docs/zh-CN/channels/mattermost.md index 115a44764..f0d265fa9 100644 --- a/docs/zh-CN/channels/mattermost.md +++ b/docs/zh-CN/channels/mattermost.md @@ -5,10 +5,10 @@ read_when: summary: Mattermost 机器人设置和 OpenClaw 配置 title: Mattermost x-i18n: - generated_at: "2026-04-23T06:40:05Z" + generated_at: "2026-04-23T07:03:25Z" model: gpt-5.4 provider: openai - source_hash: 7288378af9a3b58d51be19cdeee827350f6a4cbd80031d10ef467d482f3259e5 + source_hash: 04913fe38ddce73eba2a7f3953ec3241b6871ce4a06e0393d09331e37a39cc2f source_path: channels/mattermost.md workflow: 15 --- @@ -16,37 +16,36 @@ x-i18n: # Mattermost 状态:内置插件(bot token + WebSocket 事件)。支持渠道、群组和私信。 -Mattermost 是一个可自行托管的团队消息平台;产品详情和下载请参见官方网站 +Mattermost 是一个可自行托管的团队消息平台;有关产品详情和下载,请参阅其官方网站 [mattermost.com](https://mattermost.com)。 ## 内置插件 -Mattermost 在当前的 OpenClaw 版本中作为内置插件提供,因此普通的 -打包构建不需要单独安装。 +在当前的 OpenClaw 版本中,Mattermost 作为内置插件提供,因此普通的打包构建不需要单独安装。 -如果你使用的是较旧的构建,或排除了 Mattermost 的自定义安装, +如果你使用的是较旧的构建版本,或是不包含 Mattermost 的自定义安装, 请手动安装: -通过 CLI 安装(npm 注册表): +通过 CLI 安装(npm registry): ```bash openclaw plugins install @openclaw/mattermost ``` -本地检出(从 git 仓库运行时): +本地检出安装(从 git 仓库运行时): ```bash openclaw plugins install ./path/to/local/mattermost-plugin ``` -详情:[Plugins](/zh-CN/tools/plugin) +详情: [Plugins](/zh-CN/tools/plugin) ## 快速设置 1. 确保 Mattermost 插件可用。 - - 当前打包的 OpenClaw 版本已内置它。 - - 较旧/自定义安装可以使用上面的命令手动添加。 -2. 创建一个 Mattermost 机器人账户并复制 **bot token**。 + - 当前打包发布的 OpenClaw 版本已内置该插件。 + - 较旧/自定义安装可使用上述命令手动添加。 +2. 创建一个 Mattermost 机器人账户,并复制 **bot token**。 3. 复制 Mattermost 的 **base URL**(例如 `https://chat.example.com`)。 4. 配置 OpenClaw 并启动 Gateway 网关。 @@ -67,8 +66,7 @@ openclaw plugins install ./path/to/local/mattermost-plugin ## 原生斜杠命令 -原生斜杠命令为可选启用。启用后,OpenClaw 会通过 -Mattermost API 注册 `oc_*` 斜杠命令,并在 Gateway 网关 HTTP 服务器上接收回调 POST 请求。 +原生斜杠命令为可选启用。启用后,OpenClaw 会通过 Mattermost API 注册 `oc_*` 斜杠命令,并在 Gateway 网关 HTTP 服务器上接收回调 `POST` 请求。 ```json5 { @@ -78,7 +76,7 @@ Mattermost API 注册 `oc_*` 斜杠命令,并在 Gateway 网关 HTTP 服务器 native: true, nativeSkills: true, callbackPath: "/api/channels/mattermost/command", - // 当 Mattermost 无法直接访问 Gateway 网关时使用(反向代理/公共 URL)。 + // 当 Mattermost 无法直接访问 Gateway 网关时使用(反向代理/公网 URL)。 callbackUrl: "https://gateway.example.com/api/channels/mattermost/command", }, }, @@ -88,37 +86,44 @@ Mattermost API 注册 `oc_*` 斜杠命令,并在 Gateway 网关 HTTP 服务器 说明: -- `native: "auto"` 对 Mattermost 默认为禁用。设置 `native: true` 以启用。 -- 如果省略 `callbackUrl`,OpenClaw 会根据 Gateway 网关 host/port 和 `callbackPath` 自动推导。 -- 对于多账户设置,`commands` 可以设置在顶层,或设置在 - `channels.mattermost.accounts..commands` 下(账户值会覆盖顶层字段)。 -- 命令回调会使用 Mattermost 在 OpenClaw 注册 `oc_*` 命令时 - 返回的每个命令 token 进行校验。 -- 当注册失败、启动不完整,或回调 token 与任何已注册命令都不匹配时, - 斜杠命令回调会以默认拒绝的方式失败。 -- 可达性要求:回调端点必须可从 Mattermost 服务器访问。 +- `native: "auto"` 在 Mattermost 中默认禁用。设置 `native: true` 以启用。 +- 如果省略 `callbackUrl`,OpenClaw 会根据 Gateway 网关的 host/port + `callbackPath` 自动推导。 +- 对于多账户设置,`commands` 可设置在顶层,或设置在 + `channels.mattermost.accounts..commands` 下(账户级值会覆盖顶层字段)。 +- 命令回调会使用 OpenClaw 注册 `oc_*` 命令时由 + Mattermost 返回的每个命令对应 token 进行校验。 +- 当注册失败、启动不完整,或 + 回调 token 与任一已注册命令都不匹配时,斜杠命令回调会以失败关闭的方式拒绝处理。 +- 可达性要求:回调端点必须能从 Mattermost 服务器访问。 - 除非 Mattermost 与 OpenClaw 运行在同一主机/网络命名空间中,否则不要将 `callbackUrl` 设置为 `localhost`。 - - 除非该 URL 会将 `/api/channels/mattermost/command` 反向代理到 OpenClaw,否则不要将 `callbackUrl` 设置为你的 Mattermost base URL。 - - 一个快速检查方法是运行 `curl https:///api/channels/mattermost/command`;GET 请求应返回来自 OpenClaw 的 `405 Method Not Allowed`,而不是 `404`。 -- Mattermost 出站允许列表要求: - - 如果你的回调目标是私有/tailnet/内部地址,请设置 Mattermost - `ServiceSettings.AllowedUntrustedInternalConnections` 以包含回调 host/domain。 - - 使用 host/domain 条目,不要使用完整 URL。 + - 除非该 URL 已将 `/api/channels/mattermost/command` 反向代理到 OpenClaw,否则不要将 `callbackUrl` 设置为你的 Mattermost base URL。 + - 一个快速检查方式是执行 `curl https:///api/channels/mattermost/command`;`GET` 请求应返回 OpenClaw 的 `405 Method Not Allowed`,而不是 `404`。 +- Mattermost 出站 allowlist 要求: + - 如果你的回调目标使用私有/tailnet/内部地址,请将 Mattermost 的 + `ServiceSettings.AllowedUntrustedInternalConnections` 设置为包含回调主机/域名。 + - 使用主机/域名条目,而不是完整 URL。 - 正确:`gateway.tailnet-name.ts.net` - 错误:`https://gateway.tailnet-name.ts.net` ## 环境变量(默认账户) -如果你更喜欢使用环境变量,请在 Gateway 网关主机上设置这些变量: +如果你更喜欢使用环境变量,请在 Gateway 网关主机上设置以下变量: - `MATTERMOST_BOT_TOKEN=...` - `MATTERMOST_URL=https://chat.example.com` -环境变量仅适用于**默认**账户(`default`)。其他账户必须使用配置值。 +环境变量仅适用于 **默认** 账户(`default`)。其他账户必须使用配置值。 + + +`MATTERMOST_URL` 位于端点屏蔽列表中,不能从工作区 `.env` 文件中设置。 +它必须来自 shell 环境或 Gateway 网关进程环境, +这样不受信任的工作区就无法将 Mattermost 流量重定向到其他服务器。完整列表请参阅 +[工作区 `.env` 文件](/zh-CN/gateway/security)。 + ## 聊天模式 -Mattermost 会自动响应私信。渠道行为由 `chatmode` 控制: +Mattermost 会自动响应私信。渠道中的行为由 `chatmode` 控制: - `oncall`(默认):仅在渠道中被 @提及时响应。 - `onmessage`:响应每一条渠道消息。 @@ -140,17 +145,17 @@ Mattermost 会自动响应私信。渠道行为由 `chatmode` 控制: 说明: - `onchar` 仍会响应显式的 @提及。 -- `channels.mattermost.requireMention` 会兼容旧版配置,但更推荐使用 `chatmode`。 +- `channels.mattermost.requireMention` 仍兼容旧版配置,但更推荐使用 `chatmode`。 -## 线程和会话 +## 线程与会话 -使用 `channels.mattermost.replyToMode` 控制渠道和群组回复是保留在 -主渠道中,还是在触发消息下开启线程。 +使用 `channels.mattermost.replyToMode` 控制渠道和群组回复是保留在主渠道中, +还是在触发消息下方启动一个线程。 -- `off`(默认):仅当传入帖子本身已经在线程中时,才在线程中回复。 -- `first`:对于顶层渠道/群组帖子,在该帖子下开启线程,并将对话路由到线程范围的会话。 -- `all`:对 Mattermost 当前的行为与 `first` 相同。 -- 私信会忽略此设置,并保持非线程模式。 +- `off`(默认):仅当入站消息本身已在线程中时,才在线程中回复。 +- `first`:对于顶层渠道/群组消息,在该消息下启动一个线程,并将该对话路由到线程作用域的会话。 +- `all`:在当前 Mattermost 中,行为与 `first` 相同。 +- 私信会忽略此设置,并保持为非线程模式。 配置示例: @@ -166,27 +171,27 @@ Mattermost 会自动响应私信。渠道行为由 `chatmode` 控制: 说明: -- 线程范围的会话使用触发帖子的 id 作为线程根。 +- 线程作用域的会话会使用触发消息的 post id 作为线程根。 - `first` 和 `all` 当前等价,因为一旦 Mattermost 有了线程根, - 后续分块和媒体内容都会继续发布到同一线程中。 + 后续分块和媒体内容都会继续发送到同一个线程中。 ## 访问控制(私信) - 默认:`channels.mattermost.dmPolicy = "pairing"`(未知发送者会收到一个配对码)。 -- 通过以下方式批准: +- 通过以下命令批准: - `openclaw pairing list mattermost` - `openclaw pairing approve mattermost ` - 公开私信:`channels.mattermost.dmPolicy="open"` 加上 `channels.mattermost.allowFrom=["*"]`。 -## Channels(群组) +## 渠道(群组) -- 默认:`channels.mattermost.groupPolicy = "allowlist"`(提及门控)。 -- 使用 `channels.mattermost.groupAllowFrom` 将发送者加入允许列表(推荐使用用户 ID)。 -- 每个渠道的提及覆盖配置位于 `channels.mattermost.groups..requireMention` +- 默认:`channels.mattermost.groupPolicy = "allowlist"`(受提及限制)。 +- 使用 `channels.mattermost.groupAllowFrom` 将发送者加入 allowlist(推荐使用用户 ID)。 +- 针对单个渠道的提及覆盖配置位于 `channels.mattermost.groups..requireMention` 或 `channels.mattermost.groups["*"].requireMention`(作为默认值)。 - `@username` 匹配是可变的,且仅在 `channels.mattermost.dangerouslyAllowNameMatching: true` 时启用。 -- 开放渠道:`channels.mattermost.groupPolicy="open"`(提及门控)。 -- 运行时说明:如果 `channels.mattermost` 完全缺失,运行时在群组检查中会回退到 `groupPolicy="allowlist"`(即使设置了 `channels.defaults.groupPolicy` 也是如此)。 +- 开放渠道:`channels.mattermost.groupPolicy="open"`(受提及限制)。 +- 运行时说明:如果完全缺少 `channels.mattermost`,运行时在进行群组检查时会回退为 `groupPolicy="allowlist"`(即使设置了 `channels.defaults.groupPolicy` 也是如此)。 示例: @@ -206,28 +211,28 @@ Mattermost 会自动响应私信。渠道行为由 `chatmode` 控制: ## 出站投递目标 -将以下目标格式与 `openclaw message send` 或 cron/webhooks 搭配使用: +将以下目标格式与 `openclaw message send` 或 cron/webhooks 一起使用: -- `channel:` 表示渠道 -- `user:` 表示私信 -- `@username` 表示私信(通过 Mattermost API 解析) +- `channel:` 用于渠道 +- `user:` 用于私信 +- `@username` 用于私信(通过 Mattermost API 解析) -裸的不透明 ID(如 `64ifufp...`)在 Mattermost 中是**有歧义的**(用户 ID 或渠道 ID)。 +裸的不透明 ID(例如 `64ifufp...`)在 Mattermost 中是 **有歧义** 的(可能是用户 ID,也可能是渠道 ID)。 -OpenClaw 会按**用户优先**进行解析: +OpenClaw 会按 **用户优先** 的顺序解析它们: -- 如果该 ID 作为用户存在(`GET /api/v4/users/` 成功),OpenClaw 会通过 `/api/v4/channels/direct` 解析直连渠道后发送**私信**。 -- 否则该 ID 会被视为**渠道 ID**。 +- 如果该 ID 作为用户存在(`GET /api/v4/users/` 成功),OpenClaw 会通过解析 `/api/v4/channels/direct` 对应的私信渠道来发送 **私信**。 +- 否则,该 ID 会被视为 **渠道 ID**。 -如果你需要确定性行为,请始终使用显式前缀(`user:` / `channel:`)。 +如果你需要确定性的行为,请始终使用显式前缀(`user:` / `channel:`)。 ## 私信渠道重试 -当 OpenClaw 向 Mattermost 私信目标发送消息,且需要先解析直连渠道时, -默认会重试瞬时性的直连渠道创建失败。 +当 OpenClaw 向 Mattermost 私信目标发送消息且需要先解析直连渠道时, +默认会重试临时性的直连渠道创建失败。 -使用 `channels.mattermost.dmChannelRetry` 为 Mattermost 插件全局调整该行为, -或使用 `channels.mattermost.accounts..dmChannelRetry` 为单个账户调整。 +使用 `channels.mattermost.dmChannelRetry` 可以为 Mattermost 插件全局调整该行为, +或使用 `channels.mattermost.accounts..dmChannelRetry` 为单个账户单独设置。 ```json5 { @@ -246,13 +251,13 @@ OpenClaw 会按**用户优先**进行解析: 说明: -- 这仅适用于私信渠道创建(`/api/v4/channels/direct`),而不是每一个 Mattermost API 调用。 -- 重试适用于限流、5xx 响应以及网络或超时错误等瞬时故障。 -- 除 `429` 外的 4xx 客户端错误会被视为永久性错误,不会重试。 +- 这仅适用于私信渠道创建(`/api/v4/channels/direct`),而不是所有 Mattermost API 调用。 +- 重试适用于限流、5xx 响应以及网络或超时错误等临时性故障。 +- 除 `429` 之外的 4xx 客户端错误会被视为永久性错误,不会重试。 ## 预览流式传输 -Mattermost 会将思考过程、工具活动和部分回复文本流式写入同一个**草稿预览帖子**,并在最终答案可安全发送时就地完成。预览会在同一个帖子 id 上更新,而不会用逐块消息刷屏。媒体/错误类最终结果会取消待处理的预览编辑,并改用常规投递,而不是刷新一个一次性的预览帖子。 +Mattermost 会将思考过程、工具活动和部分回复文本流式写入同一个 **草稿预览消息** 中,并在最终答案可安全发送时原位完成。预览会在同一个 post id 上持续更新,而不是用每个分块消息刷屏。媒体/错误类最终消息会取消待处理的预览编辑,并改用常规投递,而不会刷新出一个一次性的预览消息。 通过 `channels.mattermost.streaming` 启用: @@ -268,20 +273,21 @@ Mattermost 会将思考过程、工具活动和部分回复文本流式写入同 说明: -- `partial` 是常见选择:使用一个预览帖子,随着回复增长不断编辑,最后以完整答案完成。 -- `block` 会在预览帖子中使用追加式草稿分块。 -- `progress` 会在生成时显示状态预览,并仅在完成时发布最终答案。 +- `partial` 是常见选择:使用一个预览消息,随着回复增长不断编辑,最后以完整答案完成。 +- `block` 会在预览消息中使用追加式草稿分块。 +- `progress` 会在生成期间显示状态预览,并仅在完成时发布最终答案。 - `off` 会禁用预览流式传输。 -- 如果流无法就地完成(例如帖子在流式过程中被删除),OpenClaw 会回退为发送一个新的最终帖子,以确保回复绝不会丢失。 -- 参见 [Streaming](/zh-CN/concepts/streaming#preview-streaming-modes) 查看渠道映射矩阵。 +- 如果流无法原位完成(例如消息在流式过程中被删除),OpenClaw 会回退为发送一条新的最终消息,以确保回复绝不会丢失。 +- 仅包含推理的负载不会发布到渠道消息中,包括以 `> Reasoning:` 引用块形式到达的文本。设置 `/reasoning on` 可在其他界面中查看思考内容;Mattermost 最终消息仅保留答案。 +- 渠道映射矩阵请参阅 [Streaming](/zh-CN/concepts/streaming#preview-streaming-modes)。 -## Reactions(消息工具) +## 表情回应(消息工具) - 使用 `message action=react`,并设置 `channel=mattermost`。 -- `messageId` 是 Mattermost 帖子 id。 -- `emoji` 接受 `thumbsup` 或 `:+1:` 这类名称(冒号可选)。 -- 设置 `remove=true`(布尔值)以移除 reaction。 -- reaction 添加/移除事件会作为系统事件转发到已路由的智能体会话。 +- `messageId` 是 Mattermost 的 post id。 +- `emoji` 接受如 `thumbsup` 或 `:+1:` 这样的名称(冒号可选)。 +- 设置 `remove=true`(布尔值)可移除一个回应。 +- 回应的添加/移除事件会作为系统事件转发到已路由的智能体会话。 示例: @@ -292,13 +298,13 @@ message action=react channel=mattermost target=channel: messageId=.actions.reactions`。 +- `channels.mattermost.actions.reactions`:启用/禁用回应操作(默认 true)。 +- 按账户覆盖:`channels.mattermost.accounts..actions.reactions`。 ## 交互式按钮(消息工具) 发送带有可点击按钮的消息。当用户点击按钮时,智能体会收到该选择, -并可以作出响应。 +并可作出响应。 通过将 `inlineButtons` 添加到渠道能力中来启用按钮: @@ -320,43 +326,43 @@ message action=send channel=mattermost target=channel: buttons=[[{"te 按钮字段: -- `text`(必填):显示标签。 -- `callback_data`(必填):点击后回传的值(用作 action ID)。 +- `text`(必需):显示标签。 +- `callback_data`(必需):点击后回传的值(用作 action ID)。 - `style`(可选):`"default"`、`"primary"` 或 `"danger"`。 当用户点击按钮时: -1. 所有按钮都会被替换为一行确认文本(例如:“✓ **Yes** selected by @user”)。 +1. 所有按钮都会被替换为一行确认文本(例如,“✓ **Yes** selected by @user”)。 2. 智能体会将该选择作为一条入站消息接收,并作出响应。 说明: - 按钮回调使用 HMAC-SHA256 校验(自动完成,无需配置)。 -- Mattermost 会从其 API 响应中去除 callback data(安全特性),因此点击后所有按钮 - 都会被移除——无法只移除部分按钮。 +- Mattermost 会从其 API 响应中移除回调数据(安全特性),因此按钮在点击后会被全部移除 —— 无法部分移除。 - 包含连字符或下划线的 action ID 会被自动清理 (Mattermost 路由限制)。 配置: - `channels.mattermost.capabilities`:能力字符串数组。添加 `"inlineButtons"` 以 - 在智能体系统提示中启用按钮工具说明。 -- `channels.mattermost.interactions.callbackBaseUrl`:可选的外部基础 URL,用于按钮 - 回调(例如 `https://gateway.example.com`)。当 Mattermost 无法 - 直接通过 Gateway 网关的绑定主机访问它时,请使用此项。 + 在智能体系统提示词中启用按钮工具说明。 +- `channels.mattermost.interactions.callbackBaseUrl`:按钮 + 回调使用的可选外部 base URL(例如 `https://gateway.example.com`)。当 Mattermost 无法 + 直接访问 Gateway 网关绑定主机时使用此项。 - 在多账户设置中,你也可以在 `channels.mattermost.accounts..interactions.callbackBaseUrl` 下设置相同字段。 - 如果省略 `interactions.callbackBaseUrl`,OpenClaw 会根据 `gateway.customBindHost` + `gateway.port` 推导回调 URL,然后回退到 `http://localhost:`。 -- 可达性规则:按钮回调 URL 必须可从 Mattermost 服务器访问。 - `localhost` 仅在 Mattermost 和 OpenClaw 运行于同一主机/网络命名空间时可用。 -- 如果你的回调目标是私有/tailnet/内部地址,请将其 host/domain 添加到 Mattermost +- 可达性规则:按钮回调 URL 必须能从 Mattermost 服务器访问。 + 只有当 Mattermost 与 OpenClaw 运行在同一主机/网络命名空间中时,`localhost` 才可用。 +- 如果你的回调目标是私有/tailnet/内部地址,请将其主机/域名添加到 Mattermost 的 `ServiceSettings.AllowedUntrustedInternalConnections` 中。 ### 直接 API 集成(外部脚本) -外部脚本和 webhook 可以直接通过 Mattermost REST API 发布按钮, -而不必通过智能体的 `message` 工具。尽可能使用插件中的 `buildButtonAttachments()`;如果发布原始 JSON,请遵循以下规则: +外部脚本和 webhook 可以通过 Mattermost REST API 直接发布按钮, +而不是通过智能体的 `message` 工具。尽可能使用插件中的 `buildButtonAttachments()`; +如果直接发布原始 JSON,请遵循以下规则: **负载结构:** @@ -369,7 +375,7 @@ message action=send channel=mattermost target=channel: buttons=[[{"te { actions: [ { - id: "mybutton01", // 仅限字母数字字符 —— 见下文 + id: "mybutton01", // 仅限字母数字 — 见下文 type: "button", // 必填,否则点击会被静默忽略 name: "Approve", // 显示标签 style: "primary", // 可选:"default"、"primary"、"danger" @@ -378,8 +384,8 @@ message action=send channel=mattermost target=channel: buttons=[[{"te context: { action_id: "mybutton01", // 必须与按钮 id 匹配(用于名称查找) action: "approve", - // ... 任何自定义字段 ... - _token: "", // 参见下方 HMAC 章节 + // ... any custom fields ... + _token: "", // 见下方 HMAC 章节 }, }, }, @@ -393,26 +399,26 @@ message action=send channel=mattermost target=channel: buttons=[[{"te **关键规则:** 1. Attachments 必须放在 `props.attachments` 中,而不是顶层 `attachments`(否则会被静默忽略)。 -2. 每个 action 都需要 `type: "button"` —— 没有它,点击会被静默吞掉。 -3. 每个 action 都需要 `id` 字段 —— Mattermost 会忽略没有 ID 的 action。 -4. Action `id` 必须**只包含字母数字字符**(`[a-zA-Z0-9]`)。连字符和下划线会破坏 - Mattermost 服务端的 action 路由(返回 404)。使用前请去掉它们。 +2. 每个操作都需要 `type: "button"` —— 否则点击会被静默吞掉。 +3. 每个操作都需要 `id` 字段 —— 没有 ID 的操作会被 Mattermost 忽略。 +4. 操作 `id` 必须 **仅包含字母数字字符**(`[a-zA-Z0-9]`)。连字符和下划线会破坏 + Mattermost 服务端的操作路由(返回 404)。使用前请先去掉它们。 5. `context.action_id` 必须与按钮的 `id` 匹配,这样确认消息才会显示 按钮名称(例如 “Approve”),而不是原始 ID。 -6. `context.action_id` 是必填项 —— 没有它,交互处理器会返回 400。 +6. `context.action_id` 是必需项 —— 没有它,交互处理器会返回 400。 **HMAC token 生成:** -Gateway 网关使用 HMAC-SHA256 校验按钮点击。外部脚本必须生成与 -Gateway 网关校验逻辑匹配的 token: +Gateway 网关会使用 HMAC-SHA256 校验按钮点击。外部脚本必须生成与 +Gateway 网关校验逻辑一致的 token: 1. 从 bot token 派生 secret: `HMAC-SHA256(key="openclaw-mattermost-interactions", data=botToken)` -2. 构建包含所有字段但**不含** `_token` 的 context 对象。 -3. 使用**排序后的键**和**无空格**进行序列化(Gateway 网关使用带排序键的 `JSON.stringify` - ,会生成紧凑输出)。 +2. 构建包含所有字段但 **不包括** `_token` 的 context 对象。 +3. 使用 **已排序键名** 且 **无空格** 的方式序列化(Gateway 网关使用带排序键的 `JSON.stringify`, + 输出为紧凑格式)。 4. 签名:`HMAC-SHA256(key=secret, data=serializedContext)` -5. 将生成的十六进制摘要作为 `_token` 添加到 context 中。 +5. 将得到的十六进制摘要作为 `_token` 添加到 context 中。 Python 示例: @@ -435,20 +441,20 @@ context = {**ctx, "_token": token} - Python 的 `json.dumps` 默认会添加空格(`{"key": "val"}`)。请使用 `separators=(",", ":")` 以匹配 JavaScript 的紧凑输出(`{"key":"val"}`)。 -- 始终对**所有** context 字段(除 `_token` 外)进行签名。Gateway 网关会去掉 `_token`,然后 - 对剩余的全部内容签名。只签名子集会导致静默校验失败。 -- 使用 `sort_keys=True` —— Gateway 网关会在签名前对键进行排序,而 Mattermost 在存储负载时 +- 始终对 **所有** context 字段签名(除 `_token` 外)。Gateway 网关会先移除 `_token`, + 然后对其余所有内容签名。只对部分字段签名会导致静默校验失败。 +- 使用 `sort_keys=True` —— Gateway 网关在签名前会对键名排序,而 Mattermost 在存储负载时 可能会重排 context 字段。 -- 使用 bot token 派生 secret(确定性),而不是随机字节。这个 secret - 必须在创建按钮的进程与执行校验的 Gateway 网关之间保持一致。 +- secret 应从 bot token 派生(确定性生成),而不是使用随机字节。创建按钮的进程与执行校验的 Gateway 网关 + 必须使用相同的 secret。 ## 目录适配器 -Mattermost 插件包含一个目录适配器,可通过 Mattermost API 解析渠道和用户名。 -这使得在 -`openclaw message send` 和 cron/webhook 投递中可以使用 `#channel-name` 和 `@username` 目标。 +Mattermost 插件包含一个目录适配器,可通过 Mattermost API 解析渠道名和用户名。 +这使得 `openclaw message send` 和 cron/webhook 投递中可以使用 +`#channel-name` 和 `@username` 目标。 -无需配置——该适配器会使用账户配置中的 bot token。 +无需额外配置 —— 该适配器会使用账户配置中的 bot token。 ## 多账户 @@ -469,34 +475,34 @@ Mattermost 支持在 `channels.mattermost.accounts` 下配置多个账户: ## 故障排除 -- 渠道中没有回复:确认机器人已加入该渠道,并 @提及它(oncall)、使用触发前缀(onchar),或设置 `chatmode: "onmessage"`。 -- 认证错误:检查 bot token、base URL,以及该账户是否已启用。 +- 渠道中没有回复:确认 bot 已加入该渠道,并 @提及它(oncall)、使用触发前缀(onchar),或设置 `chatmode: "onmessage"`。 +- 认证错误:检查 bot token、base URL,以及账户是否已启用。 - 多账户问题:环境变量仅适用于 `default` 账户。 - 原生斜杠命令返回 `Unauthorized: invalid command token.`:OpenClaw - 没有接受该回调 token。常见原因: - - 启动时斜杠命令注册失败,或只完成了部分注册 + 未接受该回调 token。常见原因包括: + - 斜杠命令注册失败,或在启动时仅部分完成 - 回调命中了错误的 Gateway 网关/账户 - - Mattermost 仍保留指向旧回调目标的旧命令 - - Gateway 网关重启后没有重新激活斜杠命令 + - Mattermost 仍保留指向先前回调目标的旧命令 + - Gateway 网关重启后未重新激活斜杠命令 - 如果原生斜杠命令停止工作,请检查日志中是否有 `mattermost: failed to register slash commands` 或 `mattermost: native slash commands enabled but no commands could be registered`。 -- 如果省略了 `callbackUrl`,且日志警告回调解析为 - `http://127.0.0.1:18789/...`,该 URL 很可能只有在 - Mattermost 与 OpenClaw 运行于同一主机/网络命名空间时才可访问。请改为设置一个 - 明确的、外部可访问的 `commands.callbackUrl`。 +- 如果省略了 `callbackUrl`,并且日志警告回调被解析为 + `http://127.0.0.1:18789/...`,则该 URL 很可能只有在 + Mattermost 与 OpenClaw 运行在同一主机/网络命名空间时才可访问。请改为设置一个 + 明确的、外部可达的 `commands.callbackUrl`。 - 按钮显示为白色方框:智能体可能发送了格式错误的按钮数据。检查每个按钮是否同时具有 `text` 和 `callback_data` 字段。 -- 按钮能渲染但点击无效:确认 Mattermost 服务器配置中的 `AllowedUntrustedInternalConnections` 包含 `127.0.0.1 localhost`,并且 `ServiceSettings` 中的 `EnablePostActionIntegration` 为 `true`。 -- 按钮点击返回 404:按钮的 `id` 很可能包含连字符或下划线。Mattermost 的 action 路由器在非字母数字 ID 上会失效。仅使用 `[a-zA-Z0-9]`。 -- Gateway 网关日志出现 `invalid _token`:HMAC 不匹配。请检查你是否对所有 context 字段进行了签名(而不是子集)、是否使用了排序后的键,以及是否使用了紧凑 JSON(无空格)。参见上面的 HMAC 章节。 -- Gateway 网关日志出现 `missing _token in context`:按钮的 context 中没有 `_token` 字段。请确保在构建集成负载时包含它。 -- 确认消息显示原始 ID 而不是按钮名称:`context.action_id` 与按钮的 `id` 不匹配。请将两者设置为同一个已清理的值。 +- 按钮能渲染但点击无反应:确认 Mattermost 服务器配置中的 `AllowedUntrustedInternalConnections` 包含 `127.0.0.1 localhost`,并且 `ServiceSettings` 中的 `EnablePostActionIntegration` 为 `true`。 +- 按钮点击后返回 404:按钮的 `id` 很可能包含连字符或下划线。Mattermost 的操作路由器无法处理非字母数字 ID。请仅使用 `[a-zA-Z0-9]`。 +- Gateway 网关日志显示 `invalid _token`:HMAC 不匹配。请检查你是否对所有 context 字段签名(而不是其中一部分)、是否使用了已排序键名,以及是否使用了紧凑 JSON(无空格)。参见上方 HMAC 章节。 +- Gateway 网关日志显示 `missing _token in context`:按钮的 context 中缺少 `_token` 字段。构建集成负载时请确保包含该字段。 +- 确认信息显示原始 ID 而不是按钮名称:`context.action_id` 与按钮的 `id` 不匹配。请将两者都设置为相同的已清理值。 - 智能体不知道按钮功能:在 Mattermost 渠道配置中添加 `capabilities: ["inlineButtons"]`。 ## 相关内容 -- [Channels Overview](/zh-CN/channels) —— 所有支持的渠道 -- [Pairing](/zh-CN/channels/pairing) —— 私信认证和配对流程 -- [Groups](/zh-CN/channels/groups) —— 群聊行为和提及门控 -- [Channel Routing](/zh-CN/channels/channel-routing) —— 消息的会话路由 -- [Security](/zh-CN/gateway/security) —— 访问模型与加固 +- [Channels Overview](/zh-CN/channels) — 所有支持的渠道 +- [Pairing](/zh-CN/channels/pairing) — 私信认证与配对流程 +- [Groups](/zh-CN/channels/groups) — 群聊行为与提及限制 +- [Channel Routing](/zh-CN/channels/channel-routing) — 消息的会话路由 +- [Security](/zh-CN/gateway/security) — 访问模型与安全加固 diff --git a/docs/zh-CN/channels/slack.md b/docs/zh-CN/channels/slack.md index 07c9e325a..b624872b4 100644 --- a/docs/zh-CN/channels/slack.md +++ b/docs/zh-CN/channels/slack.md @@ -1,20 +1,20 @@ --- read_when: - - 设置 Slack 或调试 Slack Socket/HTTP 模式 + - 设置 Slack 或调试 Slack socket/HTTP 模式 summary: Slack 设置与运行时行为(Socket Mode + HTTP 请求 URL) title: Slack x-i18n: - generated_at: "2026-04-22T17:02:14Z" + generated_at: "2026-04-23T07:03:24Z" model: gpt-5.4 provider: openai - source_hash: a1609ab5570daac455005cb00cee578c8954e05b25c25bf5759ae032d2a12c2c + source_hash: 3daf52cd28998bf7d692190468b9d8330f1867f56e49fc69666e7e107d4ba47c source_path: channels/slack.md workflow: 15 --- # Slack -状态:已可用于通过 Slack 应用集成实现私信 + 渠道,达到生产就绪。默认模式为 Socket Mode;也支持 HTTP 请求 URL。 +状态:可用于生产环境,支持通过 Slack 应用集成进行私信和渠道。默认模式为 Socket Mode;也支持 HTTP 请求 URL。 @@ -33,13 +33,13 @@ x-i18n: - + 在 Slack 应用设置中,点击 **[Create New App](https://api.slack.com/apps/new)** 按钮: - 选择 **from a manifest**,并为你的应用选择一个工作区 - 粘贴下方的[示例清单](#manifest-and-scope-checklist),然后继续创建 - - 生成一个带有 `connections:write` 权限的 **App-Level Token**(`xapp-...`) - - 安装应用,并复制显示的 **Bot Token**(`xoxb-...`) + - 生成一个具有 `connections:write` 权限的 **App-Level Token**(`xapp-...`) + - 安装应用并复制显示的 **Bot Token**(`xoxb-...`) @@ -57,7 +57,7 @@ x-i18n: } ``` - 环境变量回退(仅默认账户): + 环境变量回退方式(仅默认账户): ```bash SLACK_APP_TOKEN=xapp-... @@ -79,13 +79,13 @@ openclaw gateway - + 在 Slack 应用设置中,点击 **[Create New App](https://api.slack.com/apps/new)** 按钮: - 选择 **from a manifest**,并为你的应用选择一个工作区 - 粘贴[示例清单](#manifest-and-scope-checklist),并在创建前更新 URL - - 保存用于请求校验的 **Signing Secret** - - 安装应用,并复制显示的 **Bot Token**(`xoxb-...`) + - 保存用于请求验证的 **Signing Secret** + - 安装应用并复制显示的 **Bot Token**(`xoxb-...`) @@ -108,7 +108,7 @@ openclaw gateway 对多账户 HTTP 使用唯一的 webhook 路径 - 为每个账户提供不同的 `webhookPath`(默认为 `/slack/events`),以避免注册冲突。 + 为每个账户设置不同的 `webhookPath`(默认为 `/slack/events`),以避免注册冲突。 @@ -125,7 +125,7 @@ openclaw gateway -## 清单与 scope 检查清单 +## 清单和权限范围检查清单 @@ -134,7 +134,7 @@ openclaw gateway { "display_information": { "name": "OpenClaw", - "description": "用于 OpenClaw 的 Slack 连接器" + "description": "Slack connector for OpenClaw" }, "features": { "bot_user": { @@ -148,7 +148,7 @@ openclaw gateway "slash_commands": [ { "command": "/openclaw", - "description": "向 OpenClaw 发送消息", + "description": "Send a message to OpenClaw", "should_escape": false } ] @@ -211,7 +211,7 @@ openclaw gateway { "display_information": { "name": "OpenClaw", - "description": "用于 OpenClaw 的 Slack 连接器" + "description": "Slack connector for OpenClaw" }, "features": { "bot_user": { @@ -225,7 +225,7 @@ openclaw gateway "slash_commands": [ { "command": "/openclaw", - "description": "向 OpenClaw 发送消息", + "description": "Send a message to OpenClaw", "should_escape": false, "url": "https://gateway-host.example.com/slack/events" } @@ -291,17 +291,17 @@ openclaw gateway ### 其他清单设置 -显示可扩展上述默认值的不同功能。 +展示扩展上述默认配置的不同功能。 - 可以使用多个[原生斜杠命令](#commands-and-slash-behavior)来替代单个已配置命令,但有一些细节需要注意: + 可以使用多个[原生斜杠命令](#commands-and-slash-behavior) 来替代单个已配置命令,但有一些细节需要注意: - 使用 `/agentstatus` 而不是 `/status`,因为 `/status` 命令已被保留。 - 同时可用的斜杠命令不能超过 25 个。 - 将你现有的 `features.slash_commands` 部分替换为[可用命令](/zh-CN/tools/slash-commands#command-list)中的一个子集: + 将现有的 `features.slash_commands` 部分替换为[可用命令](/zh-CN/tools/slash-commands#command-list) 的一个子集: @@ -310,110 +310,110 @@ openclaw gateway "slash_commands": [ { "command": "/new", - "description": "开始一个新会话", + "description": "Start a new session", "usage_hint": "[model]" }, { "command": "/reset", - "description": "重置当前会话" + "description": "Reset the current session" }, { "command": "/compact", - "description": "压缩会话上下文", + "description": "Compact the session context", "usage_hint": "[instructions]" }, { "command": "/stop", - "description": "停止当前运行" + "description": "Stop the current run" }, { "command": "/session", - "description": "管理线程绑定过期时间", - "usage_hint": "idle 或 max-age " + "description": "Manage thread-binding expiry", + "usage_hint": "idle or max-age " }, { "command": "/think", - "description": "设置思考级别", + "description": "Set the thinking level", "usage_hint": "" }, { "command": "/verbose", - "description": "切换详细输出", + "description": "Toggle verbose output", "usage_hint": "on|off|full" }, { "command": "/fast", - "description": "显示或设置快速模式", + "description": "Show or set fast mode", "usage_hint": "[status|on|off]" }, { "command": "/reasoning", - "description": "切换推理可见性", + "description": "Toggle reasoning visibility", "usage_hint": "[on|off|stream]" }, { "command": "/elevated", - "description": "切换 elevated 模式", + "description": "Toggle elevated mode", "usage_hint": "[on|off|ask|full]" }, { "command": "/exec", - "description": "显示或设置 exec 默认值", + "description": "Show or set exec defaults", "usage_hint": "host= security= ask= node=" }, { "command": "/model", - "description": "显示或设置模型", + "description": "Show or set the model", "usage_hint": "[name|#|status]" }, { "command": "/models", - "description": "列出提供商/模型或添加模型", + "description": "List providers/models or add a model", "usage_hint": "[provider] [page] [limit=|size=|all] | add " }, { "command": "/help", - "description": "显示简短帮助摘要" + "description": "Show the short help summary" }, { "command": "/commands", - "description": "显示生成的命令目录" + "description": "Show the generated command catalog" }, { "command": "/tools", - "description": "显示当前智能体此刻可以使用什么", + "description": "Show what the current agent can use right now", "usage_hint": "[compact|verbose]" }, { "command": "/agentstatus", - "description": "显示运行时状态,包括可用时的提供商使用量/配额" + "description": "Show runtime status, including provider usage/quota when available" }, { "command": "/tasks", - "description": "列出当前会话的活动/近期后台任务" + "description": "List active/recent background tasks for the current session" }, { "command": "/context", - "description": "解释上下文是如何组装的", + "description": "Explain how context is assembled", "usage_hint": "[list|detail|json]" }, { "command": "/whoami", - "description": "显示你的发送者身份" + "description": "Show your sender identity" }, { "command": "/skill", - "description": "按名称运行一个 skill", + "description": "Run a skill by name", "usage_hint": " [input]" }, { "command": "/btw", - "description": "在不更改会话上下文的情况下提出一个旁支问题", + "description": "Ask a side question without changing session context", "usage_hint": "" }, { "command": "/usage", - "description": "控制 usage 页脚或显示成本摘要", + "description": "Control the usage footer or show cost summary", "usage_hint": "off|tokens|full|cost" } ] @@ -426,132 +426,132 @@ openclaw gateway "slash_commands": [ { "command": "/new", - "description": "开始一个新会话", + "description": "Start a new session", "usage_hint": "[model]", "url": "https://gateway-host.example.com/slack/events" }, { "command": "/reset", - "description": "重置当前会话", + "description": "Reset the current session", "url": "https://gateway-host.example.com/slack/events" }, { "command": "/compact", - "description": "压缩会话上下文", + "description": "Compact the session context", "usage_hint": "[instructions]", "url": "https://gateway-host.example.com/slack/events" }, { "command": "/stop", - "description": "停止当前运行", + "description": "Stop the current run", "url": "https://gateway-host.example.com/slack/events" }, { "command": "/session", - "description": "管理线程绑定过期时间", - "usage_hint": "idle 或 max-age ", + "description": "Manage thread-binding expiry", + "usage_hint": "idle or max-age ", "url": "https://gateway-host.example.com/slack/events" }, { "command": "/think", - "description": "设置思考级别", + "description": "Set the thinking level", "usage_hint": "", "url": "https://gateway-host.example.com/slack/events" }, { "command": "/verbose", - "description": "切换详细输出", + "description": "Toggle verbose output", "usage_hint": "on|off|full", "url": "https://gateway-host.example.com/slack/events" }, { "command": "/fast", - "description": "显示或设置快速模式", + "description": "Show or set fast mode", "usage_hint": "[status|on|off]", "url": "https://gateway-host.example.com/slack/events" }, { "command": "/reasoning", - "description": "切换推理可见性", + "description": "Toggle reasoning visibility", "usage_hint": "[on|off|stream]", "url": "https://gateway-host.example.com/slack/events" }, { "command": "/elevated", - "description": "切换 elevated 模式", + "description": "Toggle elevated mode", "usage_hint": "[on|off|ask|full]", "url": "https://gateway-host.example.com/slack/events" }, { "command": "/exec", - "description": "显示或设置 exec 默认值", + "description": "Show or set exec defaults", "usage_hint": "host= security= ask= node=", "url": "https://gateway-host.example.com/slack/events" }, { "command": "/model", - "description": "显示或设置模型", + "description": "Show or set the model", "usage_hint": "[name|#|status]", "url": "https://gateway-host.example.com/slack/events" }, { "command": "/models", - "description": "列出提供商,或列出某个提供商的模型", + "description": "List providers or models for a provider", "usage_hint": "[provider] [page] [limit=|size=|all]", "url": "https://gateway-host.example.com/slack/events" }, { "command": "/help", - "description": "显示简短帮助摘要", + "description": "Show the short help summary", "url": "https://gateway-host.example.com/slack/events" }, { "command": "/commands", - "description": "显示生成的命令目录", + "description": "Show the generated command catalog", "url": "https://gateway-host.example.com/slack/events" }, { "command": "/tools", - "description": "显示当前智能体此刻可以使用什么", + "description": "Show what the current agent can use right now", "usage_hint": "[compact|verbose]", "url": "https://gateway-host.example.com/slack/events" }, { "command": "/agentstatus", - "description": "显示运行时状态,包括可用时的提供商使用量/配额", + "description": "Show runtime status, including provider usage/quota when available", "url": "https://gateway-host.example.com/slack/events" }, { "command": "/tasks", - "description": "列出当前会话的活动/近期后台任务", + "description": "List active/recent background tasks for the current session", "url": "https://gateway-host.example.com/slack/events" }, { "command": "/context", - "description": "解释上下文是如何组装的", + "description": "Explain how context is assembled", "usage_hint": "[list|detail|json]", "url": "https://gateway-host.example.com/slack/events" }, { "command": "/whoami", - "description": "显示你的发送者身份", + "description": "Show your sender identity", "url": "https://gateway-host.example.com/slack/events" }, { "command": "/skill", - "description": "按名称运行一个 skill", + "description": "Run a skill by name", "usage_hint": " [input]", "url": "https://gateway-host.example.com/slack/events" }, { "command": "/btw", - "description": "在不更改会话上下文的情况下提出一个旁支问题", + "description": "Ask a side question without changing session context", "usage_hint": "", "url": "https://gateway-host.example.com/slack/events" }, { "command": "/usage", - "description": "控制 usage 页脚或显示成本摘要", + "description": "Control the usage footer or show cost summary", "usage_hint": "off|tokens|full|cost", "url": "https://gateway-host.example.com/slack/events" } @@ -562,17 +562,17 @@ openclaw gateway - - 如果你希望发送消息时使用当前智能体身份(自定义用户名和图标),而不是默认的 Slack 应用身份,请添加 `chat:write.customize` bot scope。 + + 如果你希望发出的消息使用当前智能体身份(自定义用户名和图标),而不是默认的 Slack 应用身份,请添加 `chat:write.customize` bot scope。 - 如果你使用 emoji 图标,Slack 要求采用 `:emoji_name:` 语法。 + 如果你使用表情符号图标,Slack 期望使用 `:emoji_name:` 语法。 - - 如果你配置了 `channels.slack.userToken`,典型的读取 scope 包括: + + 如果你配置了 `channels.slack.userToken`,典型的读取作用域包括: - - `channels:history`, `groups:history`, `im:history`, `mpim:history` - - `channels:read`, `groups:read`, `im:read`, `mpim:read` + - `channels:history`、`groups:history`、`im:history`、`mpim:history` + - `channels:read`、`groups:read`、`im:read`、`mpim:read` - `users:read` - `reactions:read` - `pins:read` @@ -586,40 +586,35 @@ openclaw gateway - Socket Mode 需要 `botToken` + `appToken`。 - HTTP 模式需要 `botToken` + `signingSecret`。 -- `botToken`、`appToken`、`signingSecret` 和 `userToken` 支持明文 - 字符串或 SecretRef 对象。 -- 配置中的令牌会覆盖环境变量回退。 +- `botToken`、`appToken`、`signingSecret` 和 `userToken` 接受明文字符串或 `SecretRef` 对象。 +- 配置中的令牌会覆盖环境变量回退值。 - `SLACK_BOT_TOKEN` / `SLACK_APP_TOKEN` 环境变量回退仅适用于默认账户。 -- `userToken`(`xoxp-...`)仅支持配置方式(无环境变量回退),且默认是只读行为(`userTokenReadOnly: true`)。 +- `userToken`(`xoxp-...`)仅支持通过配置设置(没有环境变量回退),并且默认是只读行为(`userTokenReadOnly: true`)。 状态快照行为: -- Slack 账户检查会跟踪每个凭证对应的 `*Source` 和 `*Status` - 字段(`botToken`、`appToken`、`signingSecret`、`userToken`)。 -- 状态可以是 `available`、`configured_unavailable` 或 `missing`。 -- `configured_unavailable` 表示该账户通过 SecretRef - 或其他非内联 secret 来源进行了配置,但当前命令/运行时路径 - 无法解析出实际值。 -- 在 HTTP 模式下,会包含 `signingSecretStatus`;在 Socket Mode 下, - 必需的状态对是 `botTokenStatus` + `appTokenStatus`。 +- Slack 账户检查会跟踪每个凭证的 `*Source` 和 `*Status` 字段(`botToken`、`appToken`、`signingSecret`、`userToken`)。 +- 状态可能是 `available`、`configured_unavailable` 或 `missing`。 +- `configured_unavailable` 表示该账户通过 `SecretRef` 或其他非内联密钥来源完成了配置,但当前命令/运行时路径无法解析实际值。 +- 在 HTTP 模式下,会包含 `signingSecretStatus`;在 Socket Mode 下,所需字段是 `botTokenStatus` + `appTokenStatus`。 -对于操作/目录读取,如果已配置,可以优先使用用户令牌。对于写入操作,仍然优先使用 bot 令牌;只有当 `userTokenReadOnly: false` 且 bot 令牌不可用时,才允许使用用户令牌写入。 +对于操作/目录读取,如果已配置,则可以优先使用用户令牌。对于写入操作,仍然优先使用 bot 令牌;只有当 `userTokenReadOnly: false` 且 bot 令牌不可用时,才允许使用用户令牌写入。 -## 操作与门控 +## 操作和门控 Slack 操作由 `channels.slack.actions.*` 控制。 -当前 Slack 工具中的可用操作组: +当前 Slack 工具中可用的操作组: -| Group | Default | +| 组 | 默认值 | | ---------- | ------- | -| messages | enabled | -| reactions | enabled | -| pins | enabled | -| memberInfo | enabled | -| emojiList | enabled | +| messages | 启用 | +| reactions | 启用 | +| pins | 启用 | +| memberInfo | 启用 | +| emojiList | 启用 | 当前 Slack 消息操作包括 `send`、`upload-file`、`download-file`、`read`、`edit`、`delete`、`pin`、`unpin`、`list-pins`、`member-info` 和 `emoji-list`。 @@ -636,19 +631,19 @@ Slack 操作由 `channels.slack.actions.*` 控制。 私信标志: - - `dm.enabled`(默认为 true) + - `dm.enabled`(默认 true) - `channels.slack.allowFrom`(推荐) - `dm.allowFrom`(旧版) - - `dm.groupEnabled`(群组私信默认为 false) - - `dm.groupChannels`(可选 MPIM allowlist) + - `dm.groupEnabled`(群组私信默认 false) + - `dm.groupChannels`(可选的 MPIM 允许列表) 多账户优先级: - `channels.slack.accounts.default.allowFrom` 仅适用于 `default` 账户。 - - 已命名账户在自身 `allowFrom` 未设置时,会继承 `channels.slack.allowFrom`。 - - 已命名账户不会继承 `channels.slack.accounts.default.allowFrom`。 + - 当命名账户自己的 `allowFrom` 未设置时,会继承 `channels.slack.allowFrom`。 + - 命名账户不会继承 `channels.slack.accounts.default.allowFrom`。 - 在私信中进行配对时,使用 `openclaw pairing approve slack `。 + 私信中的配对使用 `openclaw pairing approve slack `。 @@ -659,20 +654,20 @@ Slack 操作由 `channels.slack.actions.*` 控制。 - `allowlist` - `disabled` - 渠道 allowlist 位于 `channels.slack.channels` 下,应使用稳定的渠道 ID。 + 渠道允许列表位于 `channels.slack.channels` 下,并应使用稳定的渠道 ID。 - 运行时说明:如果 `channels.slack` 完全缺失(仅环境变量设置),运行时会回退为 `groupPolicy="allowlist"` 并记录一条警告(即使设置了 `channels.defaults.groupPolicy` 也是如此)。 + 运行时说明:如果 `channels.slack` 完全缺失(仅使用环境变量设置),运行时会回退为 `groupPolicy="allowlist"` 并记录一条警告(即使设置了 `channels.defaults.groupPolicy` 也是如此)。 名称/ID 解析: - - 当令牌访问权限允许时,渠道 allowlist 条目和私信 allowlist 条目会在启动时解析 - - 无法解析的渠道名称条目会按配置保留,但默认在路由中被忽略 - - 入站授权和渠道路由默认优先按 ID 处理;如果要直接匹配用户名/slug,需要设置 `channels.slack.dangerouslyAllowNameMatching: true` + - 当令牌访问允许时,渠道允许列表条目和私信允许列表条目会在启动时解析 + - 无法解析的渠道名称条目会按配置保留,但默认会在路由中被忽略 + - 入站授权和渠道路由默认优先使用 ID;直接用户名/slug 匹配需要设置 `channels.slack.dangerouslyAllowNameMatching: true` - 默认情况下,渠道消息受提及门控限制。 + 默认情况下,渠道消息受提及门控控制。 提及来源: @@ -680,57 +675,59 @@ Slack 操作由 `channels.slack.actions.*` 控制。 - 提及正则模式(`agents.list[].groupChat.mentionPatterns`,回退到 `messages.groupChat.mentionPatterns`) - 隐式回复给 bot 的线程行为(当 `thread.requireExplicitMention` 为 `true` 时禁用) - 每个渠道的控制项(`channels.slack.channels.`;仅能通过启动时解析或 `dangerouslyAllowNameMatching` 使用名称): + 每个渠道的控制项(`channels.slack.channels.`;名称仅通过启动解析或 `dangerouslyAllowNameMatching` 支持): - `requireMention` - - `users`(allowlist) + - `users`(允许列表) - `allowBots` - `skills` - `systemPrompt` - - `tools`, `toolsBySender` + - `tools`、`toolsBySender` - `toolsBySender` 键格式:`id:`、`e164:`、`username:`、`name:` 或 `"*"` 通配符 - (旧版无前缀键仍然只会映射到 `id:`) + (旧版无前缀键仍然只映射到 `id:`) -## 线程、会话与回复标签 +## 线程、会话和回复标签 - 私信路由为 `direct`;渠道路由为 `channel`;MPIM 路由为 `group`。 -- 使用默认 `session.dmScope=main` 时,Slack 私信会合并到智能体主会话。 +- 使用默认 `session.dmScope=main` 时,Slack 私信会折叠到智能体主会话。 - 渠道会话:`agent::slack:channel:`。 -- 在线程适用时,线程回复可以创建线程会话后缀(`:thread:`)。 -- `channels.slack.thread.historyScope` 默认为 `thread`;`thread.inheritParent` 默认为 `false`。 -- `channels.slack.thread.initialHistoryLimit` 控制新线程会话启动时要抓取多少条现有线程消息(默认 `20`;设置为 `0` 可禁用)。 -- `channels.slack.thread.requireExplicitMention`(默认 `false`):当设为 `true` 时,会抑制隐式线程提及,因此 bot 仅会响应线程内显式的 `@bot` 提及,即使 bot 已经参与该线程也是如此。如果不这样设置,在 bot 已参与的线程中回复会绕过 `requireMention` 门控。 +- 在线程回复适用时,可以创建线程会话后缀(`:thread:`)。 +- `channels.slack.thread.historyScope` 默认是 `thread`;`thread.inheritParent` 默认是 `false`。 +- `channels.slack.thread.initialHistoryLimit` 控制新线程会话开始时获取多少现有线程消息(默认 `20`;设置为 `0` 可禁用)。 +- `channels.slack.thread.requireExplicitMention`(默认 `false`):当设为 `true` 时,会抑制隐式线程提及,这样 bot 只会在消息线程中响应显式 `@bot` 提及,即使 bot 已经参与该线程也是如此。如果不设置此项,在 bot 已参与的线程中回复会绕过 `requireMention` 门控。 回复线程控制: - `channels.slack.replyToMode`:`off|first|all|batched`(默认 `off`) - `channels.slack.replyToModeByChatType`:按 `direct|group|channel` 分别设置 -- 直聊的旧版回退:`channels.slack.dm.replyToMode` +- 私聊的旧版回退:`channels.slack.dm.replyToMode` 支持手动回复标签: - `[[reply_to_current]]` - `[[reply_to:]]` -注意:`replyToMode="off"` 会禁用 Slack 中**所有**回复线程功能,包括显式的 `[[reply_to_*]]` 标签。这与 Telegram 不同,在 Telegram 中,显式标签在 `"off"` 模式下仍会生效。这种差异反映了平台的线程模型:Slack 线程会将消息隐藏在渠道之外,而 Telegram 回复仍会显示在主聊天流中。 +注意:`replyToMode="off"` 会禁用 Slack 中**所有**回复线程功能,包括显式 `[[reply_to_*]]` 标签。这与 Telegram 不同,在 Telegram 中,即使在 `"off"` 模式下也仍然会遵循显式标签。这个差异反映了平台线程模型的不同:Slack 线程会将消息隐藏在渠道之外,而 Telegram 回复仍然在主聊天流中可见。 + +聚焦的 Slack 线程回复在存在绑定的 ACP 会话时,会通过该绑定会话进行路由,而不是针对默认智能体 shell 准备回复。这样可以保持 `/focus` 和 `/acp spawn ... --bind here` 绑定对线程后续消息继续生效。 ## 确认反应 -`ackReaction` 会在 OpenClaw 处理入站消息期间发送一个确认 emoji。 +`ackReaction` 会在 OpenClaw 处理入站消息期间发送一个确认表情。 解析顺序: - `channels.slack.accounts..ackReaction` - `channels.slack.ackReaction` - `messages.ackReaction` -- 智能体身份 emoji 回退(`agents.list[].identity.emoji`,否则为 `"👀"`) +- 智能体身份表情回退(`agents.list[].identity.emoji`,否则为 `"👀"`) -说明: +注意: -- Slack 要求使用短代码(例如 `"eyes"`)。 +- Slack 期望使用短代码(例如 `"eyes"`)。 - 使用 `""` 可为 Slack 账户或全局禁用该反应。 ## 文本流式传输 @@ -740,19 +737,20 @@ Slack 操作由 `channels.slack.actions.*` 控制。 - `off`:禁用实时预览流式传输。 - `partial`(默认):用最新的部分输出替换预览文本。 - `block`:追加分块的预览更新。 -- `progress`:在生成期间显示进度状态文本,然后发送最终文本。 -- `streaming.preview.toolProgress`:当草稿预览处于激活状态时,将工具/进度更新路由到同一条被编辑的预览消息中(默认:`true`)。设为 `false` 可保留单独的工具/进度消息。 +- `progress`:生成期间显示进度状态文本,然后发送最终文本。 +- `streaming.preview.toolProgress`:当草稿预览处于活动状态时,将工具/进度更新路由到同一条已编辑的预览消息中(默认:`true`)。设置为 `false` 可保留单独的工具/进度消息。 -当 `channels.slack.streaming.mode` 为 `partial` 时,`channels.slack.streaming.nativeTransport` 控制 Slack 原生文本流式传输(默认:`true`)。 +`channels.slack.streaming.nativeTransport` 控制 Slack 原生文本流式传输,此项在 `channels.slack.streaming.mode` 为 `partial` 时生效(默认:`true`)。 -- 原生文本流式传输和 Slack assistant 线程状态显示都必须有可用的回复线程。线程选择仍然遵循 `replyToMode`。 +- 必须有可用的回复线程,原生文本流式传输和 Slack assistant 线程状态才会显示。线程选择仍然遵循 `replyToMode`。 - 当原生流式传输不可用时,渠道和群聊根消息仍可使用普通草稿预览。 -- 顶层 Slack 私信默认保持在线程外,因此不会显示线程样式预览;如果你希望那里有可见进度,请使用线程回复或 `typingReaction`。 -- 媒体和非文本载荷会回退为常规投递。 -- 媒体/错误最终消息会取消待处理的预览编辑,而不会刷新临时草稿;符合条件的文本/块最终消息仅会在能够原地编辑预览时刷新。 -- 如果流式传输在回复中途失败,OpenClaw 会对剩余载荷回退为常规投递。 +- 顶层 Slack 私信默认保持非线程模式,因此不会显示线程式预览;如果你希望在那里看到可见进度,请使用线程回复或 `typingReaction`。 +- 媒体和非文本载荷会回退到普通投递方式。 +- 媒体/错误最终消息会取消待处理的预览编辑,而不会刷新临时草稿;符合条件的文本/块最终消息只有在能够原地编辑预览时才会刷新。 +- 如果流式传输在回复中途失败,OpenClaw 会对剩余载荷回退到普通投递方式。 +- 如果 Slack Connect 渠道在 SDK 刷新其本地缓冲区之前拒绝流,系统会回退到普通 Slack 回复,这样短回复就不会被静默丢弃,也不会在 Slack 确认前被报告为已送达。 -使用草稿预览代替 Slack 原生文本流式传输: +使用草稿预览而不是 Slack 原生文本流式传输: ```json5 { @@ -767,7 +765,7 @@ Slack 操作由 `channels.slack.actions.*` 控制。 } ``` -旧版键: +旧版键名: - `channels.slack.streamMode`(`replace | status_final | append`)会自动迁移到 `channels.slack.streaming.mode`。 - 布尔值 `channels.slack.streaming` 会自动迁移到 `channels.slack.streaming.mode` 和 `channels.slack.streaming.nativeTransport`。 @@ -775,19 +773,19 @@ Slack 操作由 `channels.slack.actions.*` 控制。 ## 输入中反应回退 -`typingReaction` 会在 OpenClaw 处理回复期间,给入站 Slack 消息添加一个临时反应,并在运行结束后移除。它在线程回复之外最有用,因为线程回复默认使用 “is typing...” 状态指示器。 +`typingReaction` 会在 OpenClaw 处理回复期间,给入站 Slack 消息临时添加一个反应,并在运行结束时移除。它在线程回复之外尤其有用,因为线程回复会使用默认的“正在输入...”状态指示器。 解析顺序: - `channels.slack.accounts..typingReaction` - `channels.slack.typingReaction` -说明: +注意: -- Slack 要求使用短代码(例如 `"hourglass_flowing_sand"`)。 -- 该反应采用尽力而为的方式,回复完成或失败路径结束后会自动尝试清理。 +- Slack 期望使用短代码(例如 `"hourglass_flowing_sand"`)。 +- 该反应为尽力而为机制,在回复完成或失败路径结束后会自动尝试清理。 -## 媒体、分块与投递 +## 媒体、分块和投递 @@ -797,11 +795,11 @@ Slack 操作由 `channels.slack.actions.*` 控制。 - + - 文本分块使用 `channels.slack.textChunkLimit`(默认 4000) - - `channels.slack.chunkMode="newline"` 启用优先按段落拆分 + - `channels.slack.chunkMode="newline"` 启用按段落优先拆分 - 文件发送使用 Slack 上传 API,并可包含线程回复(`thread_ts`) - - 如果配置了 `channels.slack.mediaMaxMb`,出站媒体上限将遵循该值;否则渠道发送会使用媒体管道中的 MIME 类型默认值 + - 如果配置了 `channels.slack.mediaMaxMb`,出站媒体上限遵循该值;否则,渠道发送会使用媒体管道中的 MIME 类型默认值 @@ -810,14 +808,14 @@ Slack 操作由 `channels.slack.actions.*` 控制。 - 私信使用 `user:` - 渠道使用 `channel:` - 发送到用户目标时,Slack 私信会通过 Slack 会话 API 打开。 + 向用户目标发送时,Slack 私信会通过 Slack 会话 API 打开。 -## 命令与斜杠行为 +## 命令和斜杠行为 -Slack 中的斜杠命令可以显示为单个已配置命令,或多个原生命令。配置 `channels.slack.slashCommand` 可更改命令默认值: +Slack 中的斜杠命令可以显示为单个已配置命令,也可以显示为多个原生命令。配置 `channels.slack.slashCommand` 可更改命令默认值: - `enabled: false` - `name: "openclaw"` @@ -828,7 +826,7 @@ Slack 中的斜杠命令可以显示为单个已配置命令,或多个原生 /openclaw /help ``` -原生命令需要你在 Slack 应用中配置[其他清单设置](#additional-manifest-settings),并通过 `channels.slack.commands.native: true` 或全局配置中的 `commands.native: true` 启用。 +原生命令要求你在 Slack 应用中设置[其他清单设置](#additional-manifest-settings),并通过 `channels.slack.commands.native: true` 或全局配置中的 `commands.native: true` 启用。 - 对于 Slack,原生命令自动模式默认是 **off**,因此 `commands.native: "auto"` 不会启用 Slack 原生命令。 @@ -839,19 +837,19 @@ Slack 中的斜杠命令可以显示为单个已配置命令,或多个原生 原生参数菜单使用自适应渲染策略,在分发所选选项值之前先显示确认模态框: - 最多 5 个选项:按钮块 -- 6 - 100 个选项:静态选择菜单 -- 超过 100 个选项:当交互式选项处理器可用时,使用带异步选项过滤的外部选择 -- 超出 Slack 限制时:编码后的选项值会回退为按钮 +- 6-100 个选项:静态选择菜单 +- 超过 100 个选项:当交互选项处理器可用时,使用带异步选项过滤的外部选择 +- 超出 Slack 限制:已编码的选项值会回退为按钮 ```txt /think ``` -斜杠会话使用类似 `agent::slack:slash:` 的隔离键,但仍会通过 `CommandTargetSessionKey` 将命令执行路由到目标会话。 +斜杠会话使用独立键,如 `agent::slack:slash:`,同时仍通过 `CommandTargetSessionKey` 将命令执行路由到目标会话。 ## 交互式回复 -Slack 可以渲染由智能体创作的交互式回复控件,但此功能默认禁用。 +Slack 可以渲染由智能体编写的交互式回复控件,但该功能默认禁用。 全局启用: @@ -885,42 +883,42 @@ Slack 可以渲染由智能体创作的交互式回复控件,但此功能默 } ``` -启用后,智能体可以发出仅适用于 Slack 的回复指令: +启用后,智能体可以输出仅适用于 Slack 的回复指令: - `[[slack_buttons: Approve:approve, Reject:reject]]` - `[[slack_select: Choose a target | Canary:canary, Production:production]]` -这些指令会编译为 Slack Block Kit,并通过现有的 Slack 交互事件路径回传点击或选择。 +这些指令会编译为 Slack Block Kit,并将点击或选择通过现有 Slack 交互事件路径路由回来。 -说明: +注意: -- 这是 Slack 专用 UI。其他渠道不会将 Slack Block Kit 指令翻译为它们自己的按钮系统。 -- 交互回调值是 OpenClaw 生成的不透明令牌,而不是智能体创作的原始值。 -- 如果生成的交互块会超出 Slack Block Kit 限制,OpenClaw 会回退为原始文本回复,而不是发送无效的 blocks 载荷。 +- 这是 Slack 专用 UI。其他渠道不会将 Slack Block Kit 指令转换为它们自己的按钮系统。 +- 交互回调值是由 OpenClaw 生成的不透明令牌,而不是智能体编写的原始值。 +- 如果生成的交互块超出 Slack Block Kit 限制,OpenClaw 会回退到原始文本回复,而不是发送无效的 blocks 载荷。 -## Slack 中的 exec 审批 +## Slack 中的 Exec 审批 Slack 可以作为原生审批客户端,使用交互式按钮和交互,而不是回退到 Web UI 或终端。 - Exec 审批使用 `channels.slack.execApprovals.*` 进行原生私信/渠道路由。 -- 当请求已经落在 Slack 中且审批 ID 类型为 `plugin:` 时,插件审批也仍可通过同一套 Slack 原生按钮界面处理。 -- 审批人授权仍会被强制执行:只有被识别为审批人的用户才能通过 Slack 批准或拒绝请求。 +- 当请求已经到达 Slack 且审批 ID 类型为 `plugin:` 时,插件审批也可以通过同一套 Slack 原生按钮界面进行处理。 +- 审批人授权仍然会被强制执行:只有被识别为审批人的用户才能通过 Slack 批准或拒绝请求。 -这使用与其他渠道相同的共享审批按钮界面。当你在 Slack 应用设置中启用 `interactivity` 时,审批提示会直接在会话中渲染为 Block Kit 按钮。 -当这些按钮存在时,它们就是主要审批 UX;只有当工具结果表明聊天审批不可用或手动审批是唯一途径时,OpenClaw +这使用与其他渠道相同的共享审批按钮界面。当你的 Slack 应用设置中启用 `interactivity` 时,审批提示会直接在会话中渲染为 Block Kit 按钮。 +当这些按钮存在时,它们就是主要的审批 UX;只有当工具结果表明聊天审批不可用,或者手动审批是唯一途径时,OpenClaw 才应包含手动 `/approve` 命令。 配置路径: - `channels.slack.execApprovals.enabled` -- `channels.slack.execApprovals.approvers`(可选;如可行会回退到 `commands.ownerAllowFrom`) +- `channels.slack.execApprovals.approvers`(可选;尽可能回退到 `commands.ownerAllowFrom`) - `channels.slack.execApprovals.target`(`dm` | `channel` | `both`,默认:`dm`) - `agentFilter`、`sessionFilter` -当 `enabled` 未设置或为 `"auto"` 且至少解析出一名审批人时,Slack 会自动启用原生 exec 审批。设为 `enabled: false` 可显式禁用 Slack 作为原生审批客户端。 -设为 `enabled: true` 可在审批人解析成功时强制启用原生审批。 +当 `enabled` 未设置或为 `"auto"` 且至少解析出一位审批人时,Slack 会自动启用原生 exec 审批。设置 `enabled: false` 可显式禁用 Slack 作为原生审批客户端。 +设置 `enabled: true` 可在审批人解析成功时强制启用原生审批。 -在没有显式 Slack exec 审批配置时的默认行为: +没有显式 Slack exec 审批配置时的默认行为: ```json5 { @@ -930,7 +928,7 @@ Slack 可以作为原生审批客户端,使用交互式按钮和交互,而 } ``` -只有当你想覆盖审批人、添加过滤器,或选择加入原始聊天投递时,才需要显式的 Slack 原生配置: +只有在你想覆盖审批人、添加过滤器或选择向来源聊天投递时,才需要显式的 Slack 原生配置: ```json5 { @@ -946,23 +944,23 @@ Slack 可以作为原生审批客户端,使用交互式按钮和交互,而 } ``` -共享的 `approvals.exec` 转发是独立的。只有当 exec 审批提示还必须路由到其他聊天或显式的带外目标时才使用它。共享的 `approvals.plugin` 转发也是独立的;当这些请求已经落在 Slack 中时,Slack 原生按钮仍可处理插件审批。 +共享 `approvals.exec` 转发是独立机制。只有当 exec 审批提示还必须路由到其他聊天或显式带外目标时才使用它。共享 `approvals.plugin` 转发也是独立机制;当这些请求已经到达 Slack 时,Slack 原生按钮仍可处理插件审批。 -同一聊天中的 `/approve` 在已经支持命令的 Slack 渠道和私信中也可使用。完整的审批转发模型见[Exec 审批](/zh-CN/tools/exec-approvals)。 +同一聊天中的 `/approve` 在已支持命令的 Slack 渠道和私信中同样可用。完整审批转发模型请参见 [Exec approvals](/zh-CN/tools/exec-approvals)。 -## 事件与运行行为 +## 事件和运行行为 - 消息编辑/删除/线程广播会映射为系统事件。 -- 添加/移除反应事件会映射为系统事件。 -- 成员加入/离开、渠道创建/重命名以及添加/移除 pin 事件会映射为系统事件。 -- 当启用 `configWrites` 时,`channel_id_changed` 可迁移渠道配置键。 -- 渠道 topic/purpose 元数据被视为不可信上下文,并可注入到路由上下文中。 -- 线程发起者和初始线程历史上下文播种在适用时会按已配置的发送者 allowlist 进行过滤。 -- 块操作和模态交互会发出结构化的 `Slack interaction: ...` 系统事件,并包含丰富的载荷字段: - - 块操作:所选值、标签、选择器值以及 `workflow_*` 元数据 - - 模态 `view_submission` 和 `view_closed` 事件,包含已路由的渠道元数据和表单输入 +- 反应添加/移除事件会映射为系统事件。 +- 成员加入/离开、渠道创建/重命名以及固定/取消固定事件会映射为系统事件。 +- 当启用 `configWrites` 时,`channel_id_changed` 可以迁移渠道配置键。 +- 渠道 topic/purpose 元数据会被视为不受信任的上下文,并且可以注入到路由上下文中。 +- 在线程发起者和初始线程历史上下文植入时,会在适用情况下根据已配置的发送者允许列表进行过滤。 +- Block 操作和模态交互会发出结构化的 `Slack interaction: ...` 系统事件,并附带丰富的载荷字段: + - block 操作:选中值、标签、选择器值和 `workflow_*` 元数据 + - 模态框 `view_submission` 和 `view_closed` 事件,带有路由后的渠道元数据和表单输入 -## 配置参考指针 +## 配置参考指引 主要参考: @@ -971,7 +969,7 @@ Slack 可以作为原生审批客户端,使用交互式按钮和交互,而 高信号 Slack 字段: - 模式/认证:`mode`、`botToken`、`appToken`、`signingSecret`、`webhookPath`、`accounts.*` - 私信访问:`dm.enabled`、`dmPolicy`、`allowFrom`(旧版:`dm.policy`、`dm.allowFrom`)、`dm.groupEnabled`、`dm.groupChannels` - - 兼容性开关:`dangerouslyAllowNameMatching`(紧急兜底开关;除非必要,否则保持关闭) + - 兼容性开关:`dangerouslyAllowNameMatching`(紧急开关;除非确有需要,否则保持关闭) - 渠道访问:`groupPolicy`、`channels.*`、`channels.*.users`、`channels.*.requireMention` - 线程/历史:`replyToMode`、`replyToModeByChatType`、`thread.*`、`historyLimit`、`dmHistoryLimit`、`dms.*.historyLimit` - 投递:`textChunkLimit`、`chunkMode`、`mediaMaxMb`、`streaming`、`streaming.nativeTransport`、`streaming.preview.toolProgress` @@ -981,12 +979,12 @@ Slack 可以作为原生审批客户端,使用交互式按钮和交互,而 - 按顺序检查: + 按以下顺序检查: - `groupPolicy` - - 渠道 allowlist(`channels.slack.channels`) + - 渠道允许列表(`channels.slack.channels`) - `requireMention` - - 每个渠道的 `users` allowlist + - 每个渠道的 `users` 允许列表 有用的命令: @@ -1003,7 +1001,7 @@ openclaw doctor - `channels.slack.dm.enabled` - `channels.slack.dmPolicy`(或旧版 `channels.slack.dm.policy`) - - 配对审批 / allowlist 条目 + - 配对批准 / 允许列表条目 ```bash openclaw pairing list slack @@ -1012,11 +1010,11 @@ openclaw pairing list slack - 验证 bot + app 令牌,以及 Slack 应用设置中是否启用了 Socket Mode。 + 验证 bot 和 app 令牌,以及 Slack 应用设置中的 Socket Mode 是否已启用。 如果 `openclaw channels status --probe --json` 显示 `botTokenStatus` 或 - `appTokenStatus: "configured_unavailable"`,说明该 Slack 账户 - 已配置,但当前运行时无法解析由 SecretRef 支持的 + `appTokenStatus: "configured_unavailable"`,则表示 Slack 账户 + 已完成配置,但当前运行时无法解析由 `SecretRef` 支持的 实际值。 @@ -1030,18 +1028,24 @@ openclaw pairing list slack - 每个 HTTP 账户使用唯一的 `webhookPath` 如果账户快照中出现 `signingSecretStatus: "configured_unavailable"`, - 说明该 HTTP 账户已配置,但当前运行时无法 - 解析由 SecretRef 支持的 signing secret。 + 则表示该 HTTP 账户已完成配置,但当前运行时无法 + 解析由 `SecretRef` 支持的 signing secret 实际值。 + + 已注册的 Request URL webhook 会通过与 Slack monitor 设置相同的共享处理器注册表进行分发,因此 HTTP 模式的 Slack 事件会继续通过已注册路径进行路由,而不会在路由注册成功后返回 404。 - - 验证你原本打算使用的是: + + 当调用方传入 `cfg`,但未显式提供 `token` 或预构建客户端时,`downloadFile` 辅助函数会从运行时配置解析其 bot 令牌,从而在 action 运行时路径之外保留仅 `cfg` 的文件下载能力。 + - - 原生命令模式(`channels.slack.commands.native: true`),并在 Slack 中注册了匹配的斜杠命令 + + 验证你是否打算使用以下其中一种: + + - 原生命令模式(`channels.slack.commands.native: true`),并且已在 Slack 中注册匹配的斜杠命令 - 或单一斜杠命令模式(`channels.slack.slashCommand.enabled: true`) - 另请检查 `commands.useAccessGroups` 以及渠道/用户 allowlist。 + 另外还要检查 `commands.useAccessGroups` 以及渠道/用户允许列表。 diff --git a/docs/zh-CN/channels/synology-chat.md b/docs/zh-CN/channels/synology-chat.md index db1c302e7..3bfdae1d4 100644 --- a/docs/zh-CN/channels/synology-chat.md +++ b/docs/zh-CN/channels/synology-chat.md @@ -1,66 +1,68 @@ --- read_when: - - 设置 Synology Chat 以配合 OpenClaw 使用 + - 使用 OpenClaw 设置 Synology Chat - 调试 Synology Chat webhook 路由 summary: Synology Chat webhook 设置和 OpenClaw 配置 title: Synology Chat x-i18n: - generated_at: "2026-04-21T18:02:17Z" + generated_at: "2026-04-23T07:03:24Z" model: gpt-5.4 provider: openai - source_hash: 7288e2aa873ee1a1f57861d839cfb44ff324e3d40a7f36da07c6ba43cbe1e6e6 + source_hash: dda0d5d11e2526f4813b69ca914a63231003eb60d8bc2e1f030bcb3d77c8eda0 source_path: channels/synology-chat.md workflow: 15 --- # Synology Chat -状态:内置插件私信渠道,使用 Synology Chat webhook。 -该插件接收来自 Synology Chat 出站 webhook 的入站消息,并通过 Synology Chat 入站 webhook 发送回复。 +状态:内置的插件私信渠道,使用 Synology Chat webhook。 +该插件接收来自 Synology Chat 出站 webhook 的入站消息,并通过 +Synology Chat 入站 webhook 发送回复。 ## 内置插件 -Synology Chat 在当前的 OpenClaw 版本中作为内置插件提供,因此普通的打包构建不需要单独安装。 +Synology Chat 在当前的 OpenClaw 版本中作为内置插件提供,因此常规的 +打包构建不需要单独安装。 -如果你使用的是较旧的构建版本,或是不包含 Synology Chat 的自定义安装, +如果你使用的是较旧的构建,或排除了 Synology Chat 的自定义安装, 请手动安装: -从本地检出目录安装: +从本地检出安装: ```bash openclaw plugins install ./path/to/local/synology-chat-plugin ``` -详情:[Plugins](/zh-CN/tools/plugin) +详情: [Plugins](/zh-CN/tools/plugin) ## 快速开始 1. 确保 Synology Chat 插件可用。 - - 当前打包的 OpenClaw 版本已内置它。 - - 较旧版本或自定义安装可以使用上面的命令从源码检出目录手动添加。 + - 当前打包的 OpenClaw 版本已经内置了它。 + - 较旧/自定义安装可以使用上述命令从源码检出中手动添加它。 - `openclaw onboard` 现在会在与 `openclaw channels add` 相同的渠道设置列表中显示 Synology Chat。 - - 非交互式设置:`openclaw channels add --channel synology-chat --token --url ` + - 非交互式设置: `openclaw channels add --channel synology-chat --token --url ` 2. 在 Synology Chat 集成中: - 创建一个入站 webhook 并复制其 URL。 - - 创建一个带有你的密钥令牌的出站 webhook。 + - 使用你的密钥令牌创建一个出站 webhook。 3. 将出站 webhook URL 指向你的 OpenClaw Gateway 网关: - 默认是 `https://gateway-host/webhook/synology`。 - - 或使用你自定义的 `channels.synology-chat.webhookPath`。 + - 或者使用你自定义的 `channels.synology-chat.webhookPath`。 4. 在 OpenClaw 中完成设置。 - - 引导式:`openclaw onboard` - - 直接设置:`openclaw channels add --channel synology-chat --token --url ` + - 引导式: `openclaw onboard` + - 直接方式: `openclaw channels add --channel synology-chat --token --url ` 5. 重启 Gateway 网关,并向 Synology Chat 机器人发送一条私信。 Webhook 认证详情: -- OpenClaw 按以下顺序接受出站 webhook 令牌:`body.token`,然后是 +- OpenClaw 按以下顺序接受出站 webhook 令牌:`body.token`,然后 `?token=...`,再然后是请求头。 - 接受的请求头形式: - `x-synology-token` - `x-webhook-token` - `x-openclaw-token` - `Authorization: Bearer ` -- 空令牌或缺失令牌会以失败关闭的方式处理。 +- 空令牌或缺失令牌会默认拒绝。 最小配置: @@ -94,14 +96,21 @@ Webhook 认证详情: 配置值会覆盖环境变量。 + +`SYNOLOGY_CHAT_INCOMING_URL` 在端点屏蔽列表中,不能从工作区 `.env` 文件中设置。 +它必须来自 shell 环境或 Gateway 网关进程环境, +这样不受信任的工作区就无法将 Synology Chat 流量重定向到其他 webhook。完整列表请参见 +[工作区 `.env` 文件](/zh-CN/gateway/security)。 + + ## 私信策略和访问控制 -- `dmPolicy: "allowlist"` 是推荐的默认值。 -- `allowedUserIds` 接受 Synology 用户 ID 列表(或逗号分隔的字符串)。 -- 在 `allowlist` 模式下,空的 `allowedUserIds` 列表会被视为配置错误,webhook 路由将不会启动(如需允许所有人,请使用 `dmPolicy: "open"`)。 +- 推荐默认使用 `dmPolicy: "allowlist"`。 +- `allowedUserIds` 接受 Synology 用户 ID 列表(或逗号分隔字符串)。 +- 在 `allowlist` 模式下,空的 `allowedUserIds` 列表会被视为配置错误,webhook 路由不会启动(如需允许所有用户,请使用 `dmPolicy: "open"`)。 - `dmPolicy: "open"` 允许任何发送者。 - `dmPolicy: "disabled"` 会阻止私信。 -- 回复接收者绑定默认保持在稳定的数字 `user_id` 上。`channels.synology-chat.dangerouslyAllowNameMatching: true` 是应急兼容模式,会重新启用可变用户名/昵称查找以进行回复投递。 +- 默认情况下,回复接收者绑定会保持在稳定的数字 `user_id` 上。`channels.synology-chat.dangerouslyAllowNameMatching: true` 是紧急兼容模式,会重新启用可变用户名/昵称查找来投递回复。 - 配对批准可配合以下命令使用: - `openclaw pairing list synology-chat` - `openclaw pairing approve synology-chat ` @@ -118,19 +127,19 @@ openclaw message send --channel synology-chat --target synology-chat:123456 --te ``` 支持通过基于 URL 的文件投递发送媒体。 -出站文件 URL 必须使用 `http` 或 `https`,私有网络目标或其他被阻止的网络目标会在 OpenClaw 将该 URL 转发到 NAS webhook 之前被拒绝。 +出站文件 URL 必须使用 `http` 或 `https`,私有或其他被屏蔽的网络目标会在 OpenClaw 将该 URL 转发到 NAS webhook 之前被拒绝。 ## 多账户 在 `channels.synology-chat.accounts` 下支持多个 Synology Chat 账户。 -每个账户都可以覆盖 token、入站 URL、webhook 路径、私信策略和限制。 -私信会话会按账户和用户彼此隔离,因此两个不同 Synology 账户上的相同数字 `user_id` +每个账户都可以覆盖令牌、入站 URL、webhook 路径、私信策略和限制。 +私信会话会按账户和用户分别隔离,因此两个不同 Synology 账户上相同的数字 `user_id` 不会共享对话记录状态。 请为每个已启用账户提供不同的 `webhookPath`。OpenClaw 现在会拒绝重复的完全相同路径, -并拒绝启动那些在多账户设置中仅继承共享 webhook 路径的已命名账户。 -如果你确实需要为已命名账户保留旧版继承行为,请在该账户上或在 `channels.synology-chat` +并且在多账户设置中,如果具名账户仅继承共享的 webhook 路径,也会拒绝启动。 +如果你确实需要为具名账户有意使用旧版继承行为,请在该账户上或在 `channels.synology-chat` 上设置 `dangerouslyAllowInheritedWebhookPath: true`, -但重复的完全相同路径仍会以失败关闭的方式被拒绝。建议为每个账户显式设置路径。 +但重复的完全相同路径仍会以默认拒绝的方式被拦截。更推荐为每个账户显式设置路径。 ```json5 { @@ -159,24 +168,24 @@ openclaw message send --channel synology-chat --target synology-chat:123456 --te - 妥善保管 `token`,如果泄露请轮换。 - 保持 `allowInsecureSsl: false`,除非你明确信任自签名的本地 NAS 证书。 -- 入站 webhook 请求会按发送者进行令牌验证和速率限制。 -- 无效令牌检查使用恒定时间密钥比较,并以失败关闭的方式处理。 +- 入站 webhook 请求会进行令牌校验,并按发送者进行速率限制。 +- 无效令牌检查使用常量时间密钥比较,并默认拒绝。 - 生产环境推荐使用 `dmPolicy: "allowlist"`。 - 除非你明确需要基于旧版用户名的回复投递,否则请保持 `dangerouslyAllowNameMatching` 关闭。 -- 除非你明确接受多账户设置中共享路径路由的风险,否则请保持 `dangerouslyAllowInheritedWebhookPath` 关闭。 +- 除非你明确接受多账户设置中的共享路径路由风险,否则请保持 `dangerouslyAllowInheritedWebhookPath` 关闭。 ## 故障排除 - `Missing required fields (token, user_id, text)`: - - 出站 webhook 负载缺少必需字段之一 - - 如果 Synology 通过请求头发送 token,请确保 Gateway 网关/代理保留这些请求头 + - 出站 webhook 负载缺少某个必需字段 + - 如果 Synology 通过请求头发送令牌,请确保 Gateway 网关/代理保留了这些请求头 - `Invalid token`: - 出站 webhook 密钥与 `channels.synology-chat.token` 不匹配 - 请求命中了错误的账户/webhook 路径 - - 反向代理在请求到达 OpenClaw 之前去除了 token 请求头 + - 反向代理在请求到达 OpenClaw 之前去掉了令牌请求头 - `Rate limit exceeded`: - - 来自同一来源的过多无效 token 尝试可能会暂时锁定该来源 - - 已认证的发送者也有单独的按用户计算的消息速率限制 + - 来自同一来源的过多无效令牌尝试,可能会暂时将该来源锁定 + - 已认证的发送者也会受到单独的按用户消息速率限制 - `Allowlist is empty. Configure allowedUserIds or use dmPolicy=open.`: - 已启用 `dmPolicy="allowlist"`,但未配置任何用户 - `User not authorized`: @@ -184,8 +193,8 @@ openclaw message send --channel synology-chat --target synology-chat:123456 --te ## 相关内容 -- [Channels Overview](/zh-CN/channels) — 所有受支持的渠道 -- [Pairing](/zh-CN/channels/pairing) — 私信认证和配对流程 -- [Groups](/zh-CN/channels/groups) — 群聊行为和提及门控 -- [Channel Routing](/zh-CN/channels/channel-routing) — 消息的会话路由 -- [Security](/zh-CN/gateway/security) — 访问模型和加固 +- [渠道概览](/zh-CN/channels) — 所有支持的渠道 +- [配对](/zh-CN/channels/pairing) — 私信认证和配对流程 +- [群组](/zh-CN/channels/groups) — 群聊行为和提及门控 +- [渠道路由](/zh-CN/channels/channel-routing) — 消息的会话路由 +- [安全](/zh-CN/gateway/security) — 访问模型和加固 diff --git a/docs/zh-CN/channels/telegram.md b/docs/zh-CN/channels/telegram.md index 00069722a..bd45fb8d7 100644 --- a/docs/zh-CN/channels/telegram.md +++ b/docs/zh-CN/channels/telegram.md @@ -1,20 +1,20 @@ --- read_when: - - 开发 Telegram 功能或 Webhook 时 + - 处理 Telegram 功能或 Webhook 时 summary: Telegram 机器人支持状态、功能和配置 title: Telegram x-i18n: - generated_at: "2026-04-23T00:41:52Z" + generated_at: "2026-04-23T07:03:23Z" model: gpt-5.4 provider: openai - source_hash: 1575c4e5e932a4a6330d57fa0d1639336aecdb8fa70d37d92dccd0d466d2fccb + source_hash: e2073245079eb48b599c4274cc620eb29211a64c5d396ffb355f7022fecec9a6 source_path: channels/telegram.md workflow: 15 --- # Telegram(Bot API) -状态:已可用于生产环境,支持通过 grammY 处理机器人私信和群组。默认模式为长轮询;Webhook 模式为可选。 +状态:通过 grammY 为机器人私信和群组提供可用于生产环境的支持。长轮询是默认模式;Webhook 模式为可选。 @@ -24,7 +24,7 @@ x-i18n: 跨渠道诊断与修复操作手册。 - 完整的渠道配置模式与示例。 + 完整的渠道配置模式和示例。 @@ -32,9 +32,9 @@ x-i18n: - 打开 Telegram 并与 **@BotFather** 对话(确认用户名完全是 `@BotFather`)。 + 打开 Telegram 并与 **@BotFather** 对话(确认用户名严格为 `@BotFather`)。 - 运行 `/newbot`,按提示操作,并保存令牌。 + 运行 `/newbot`,按照提示操作,并保存令牌。 @@ -54,7 +54,7 @@ x-i18n: ``` 环境变量回退:`TELEGRAM_BOT_TOKEN=...`(仅默认账户)。 - Telegram **不** 使用 `openclaw channels login telegram`;请在配置或环境变量中设置令牌,然后启动 Gateway 网关。 + Telegram **不**使用 `openclaw channels login telegram`;请在配置/环境变量中配置令牌,然后启动 Gateway 网关。 @@ -76,34 +76,34 @@ openclaw pairing approve telegram -令牌解析顺序与账户有关。实际行为是:配置值优先于环境变量回退,而 `TELEGRAM_BOT_TOKEN` 仅适用于默认账户。 +令牌解析顺序会感知账户。在实际情况下,配置值优先于环境变量回退,而 `TELEGRAM_BOT_TOKEN` 仅适用于默认账户。 -## Telegram 端设置 +## Telegram 侧设置 Telegram 机器人默认启用 **隐私模式**,这会限制它们能接收到的群组消息。 - 如果机器人必须看到所有群组消息,可以选择以下任一方式: + 如果机器人必须看到所有群组消息,可选择以下任一方式: - 通过 `/setprivacy` 禁用隐私模式,或 - 将机器人设为群组管理员。 - 切换隐私模式后,请在每个群组中移除并重新添加机器人,以便 Telegram 应用该更改。 + 切换隐私模式时,请在每个群组中移除并重新添加机器人,以便 Telegram 应用该更改。 管理员状态在 Telegram 群组设置中控制。 - 具有管理员身份的机器人会接收所有群组消息,这对始终在线的群组行为很有帮助。 + 管理员机器人会接收所有群组消息,这对于始终在线的群组行为很有用。 - - `/setjoingroups`:允许或禁止加入群组 + - `/setjoingroups`:允许/拒绝加入群组 - `/setprivacy`:控制群组可见性行为 @@ -113,30 +113,30 @@ openclaw pairing approve telegram - `channels.telegram.dmPolicy` 用于控制私信访问: + `channels.telegram.dmPolicy` 控制私信访问: - `pairing`(默认) - `allowlist`(要求 `allowFrom` 中至少有一个发送者 ID) - - `open`(要求 `allowFrom` 包含 `"*"`) + - `open`(要求 `allowFrom` 包含 `"*"`) - `disabled` - `channels.telegram.allowFrom` 接受数值型 Telegram 用户 ID。支持 `telegram:` / `tg:` 前缀,并会标准化处理。 + `channels.telegram.allowFrom` 接受 Telegram 数字用户 ID。支持并会标准化 `telegram:` / `tg:` 前缀。 `dmPolicy: "allowlist"` 且 `allowFrom` 为空时会阻止所有私信,并被配置校验拒绝。 - 设置流程仅要求数值型用户 ID。 - 如果你是升级而来,并且配置中包含 `@username` 形式的 allowlist 条目,请运行 `openclaw doctor --fix` 进行解析(尽力而为;需要 Telegram 机器人令牌)。 - 如果你之前依赖配对存储的 allowlist 文件,`openclaw doctor --fix` 可以在 allowlist 流程中将这些条目恢复到 `channels.telegram.allowFrom`(例如当 `dmPolicy: "allowlist"` 还没有显式 ID 时)。 + 设置过程仅要求填写数字用户 ID。 + 如果你升级后配置中包含 `@username` 形式的 allowlist 条目,请运行 `openclaw doctor --fix` 进行解析(尽力而为;需要 Telegram 机器人令牌)。 + 如果你之前依赖配对存储的 allowlist 文件,在 allowlist 流程中(例如 `dmPolicy: "allowlist"` 还没有显式 ID 时),`openclaw doctor --fix` 可以将条目恢复到 `channels.telegram.allowFrom`。 - 对于单所有者机器人,建议使用带显式数值型 `allowFrom` ID 的 `dmPolicy: "allowlist"`,以便将访问策略稳定保存在配置中(而不是依赖之前的配对批准)。 + 对于单所有者机器人,推荐使用带有显式数字 `allowFrom` ID 的 `dmPolicy: "allowlist"`,以便将访问策略稳定地保存在配置中(而不是依赖之前的配对批准)。 - 常见误解:私信配对获批并不意味着“此发送者在所有地方都已授权”。 + 常见混淆点:批准私信配对并不表示“这个发送者在任何地方都被授权”。 配对只授予私信访问权限。群组发送者授权仍然来自显式配置的 allowlist。 - 如果你希望“我只授权一次,私信和群组命令都能用”,请将你的数值型 Telegram 用户 ID 放入 `channels.telegram.allowFrom`。 + 如果你想实现“我授权一次后,私信和群组命令都能用”,请将你的 Telegram 数字用户 ID 放入 `channels.telegram.allowFrom`。 ### 查找你的 Telegram 用户 ID 更安全的方法(无需第三方机器人): - 1. 给你的机器人发送私信。 + 1. 给你的机器人发私信。 2. 运行 `openclaw logs --follow`。 3. 读取 `from.id`。 @@ -153,26 +153,26 @@ curl "https://api.telegram.org/bot/getUpdates" 有两个控制项会共同生效: - 1. **允许哪些群组**(`channels.telegram.groups`) + 1. **哪些群组被允许**(`channels.telegram.groups`) - 没有 `groups` 配置: - 当 `groupPolicy: "open"` 时:任何群组都可以通过群组 ID 检查 - - 当 `groupPolicy: "allowlist"`(默认)时:群组会被阻止,直到你添加 `groups` 条目(或 `"*"`) - - 已配置 `groups`:它作为 allowlist 生效(显式 ID 或 `"*"`) + - 当 `groupPolicy: "allowlist"`(默认)时:在你添加 `groups` 条目(或 `"*"`)之前,群组会被阻止 + - 已配置 `groups`:充当 allowlist(显式 ID 或 `"*"`) - 2. **群组中允许哪些发送者**(`channels.telegram.groupPolicy`) + 2. **群组中哪些发送者被允许**(`channels.telegram.groupPolicy`) - `open` - `allowlist`(默认) - `disabled` `groupAllowFrom` 用于群组发送者过滤。如果未设置,Telegram 会回退到 `allowFrom`。 - `groupAllowFrom` 条目应为数值型 Telegram 用户 ID(`telegram:` / `tg:` 前缀会被标准化)。 - 不要把 Telegram 群组或超级群组聊天 ID 放在 `groupAllowFrom` 中。负数聊天 ID 应放在 `channels.telegram.groups` 下。 - 非数值条目会在发送者授权时被忽略。 - 安全边界(`2026.2.25+`):群组发送者授权**不会**继承私信配对存储批准。 - 配对仍然仅限私信。对于群组,请设置 `groupAllowFrom` 或按群组 / 按话题设置 `allowFrom`。 + `groupAllowFrom` 条目应为 Telegram 数字用户 ID(`telegram:` / `tg:` 前缀会被标准化)。 + 不要将 Telegram 群组或超级群组聊天 ID 放入 `groupAllowFrom`。负数聊天 ID 应放在 `channels.telegram.groups` 下。 + 非数字条目会在发送者授权中被忽略。 + 安全边界(`2026.2.25+`):群组发送者授权**不会**继承私信配对存储中的批准。 + 配对仍然仅限私信。对于群组,请设置 `groupAllowFrom` 或按群组/按话题的 `allowFrom`。 如果 `groupAllowFrom` 未设置,Telegram 会回退到配置中的 `allowFrom`,而不是配对存储。 - 单所有者机器人的实用模式:将你的用户 ID 放入 `channels.telegram.allowFrom`,保持 `groupAllowFrom` 未设置,并在 `channels.telegram.groups` 下允许目标群组。 - 运行时说明:如果 `channels.telegram` 完全缺失,运行时默认采用故障关闭的 `groupPolicy="allowlist"`,除非已显式设置 `channels.defaults.groupPolicy`。 + 单所有者机器人的实用模式:将你的用户 ID 设置到 `channels.telegram.allowFrom`,保持 `groupAllowFrom` 未设置,并在 `channels.telegram.groups` 下允许目标群组。 + 运行时说明:如果 `channels.telegram` 完全缺失,运行时默认采用失败即关闭的 `groupPolicy="allowlist"`,除非显式设置了 `channels.defaults.groupPolicy`。 示例:允许某个特定群组中的任意成员: @@ -211,15 +211,15 @@ curl "https://api.telegram.org/bot/getUpdates" 常见错误:`groupAllowFrom` 不是 Telegram 群组 allowlist。 - - 将 `-1001234567890` 这样的 Telegram 群组或超级群组负数聊天 ID 放在 `channels.telegram.groups` 下。 - - 当你想限制允许群组中哪些人可以触发机器人时,将像 `8734062810` 这样的 Telegram 用户 ID 放在 `groupAllowFrom` 下。 - - 仅当你希望允许群组中的任意成员都能与机器人对话时,才使用 `groupAllowFrom: ["*"]`。 + - 将 `-1001234567890` 这样的 Telegram 群组或超级群组负数聊天 ID 放到 `channels.telegram.groups` 下。 + - 当你想限制已允许群组中哪些人可以触发机器人时,将 `8734062810` 这样的 Telegram 用户 ID 放到 `groupAllowFrom` 下。 + - 只有在你希望已允许群组中的任意成员都可以与机器人对话时,才使用 `groupAllowFrom: ["*"]`。 - 群组回复默认要求提及。 + 默认情况下,群组回复需要提及。 提及可以来自: @@ -233,9 +233,9 @@ curl "https://api.telegram.org/bot/getUpdates" - `/activation always` - `/activation mention` - 这些仅更新会话状态。要持久化,请使用配置。 + 这些仅更新会话状态。若要持久化,请使用配置。 - 持久化配置示例: + 持久配置示例: ```json5 { @@ -249,9 +249,9 @@ curl "https://api.telegram.org/bot/getUpdates" } ``` - 获取群组聊天 ID: + 获取群组聊天 ID 的方法: - - 将群组消息转发给 `@userinfobot` / `@getidsbot` + - 将一条群组消息转发给 `@userinfobot` / `@getidsbot` - 或从 `openclaw logs --follow` 中读取 `chat.id` - 或检查 Bot API 的 `getUpdates` @@ -261,44 +261,44 @@ curl "https://api.telegram.org/bot/getUpdates" ## 运行时行为 - Telegram 由 Gateway 网关进程持有。 -- 路由是确定性的:Telegram 入站回复会返回到 Telegram(模型不会选择渠道)。 -- 入站消息会标准化为共享渠道信封格式,并包含回复元数据和媒体占位符。 +- 路由是确定性的:Telegram 入站回复会回到 Telegram(模型不会选择渠道)。 +- 入站消息会标准化为共享渠道信封格式,包含回复元数据和媒体占位符。 - 群组会话按群组 ID 隔离。论坛话题会追加 `:topic:` 以保持话题隔离。 -- 私信消息可以携带 `message_thread_id`;OpenClaw 会使用具备线程感知能力的会话键进行路由,并在回复时保留线程 ID。 -- 长轮询使用 grammY runner,并按每个聊天 / 每个线程顺序处理。整体 runner sink 并发度使用 `agents.defaults.maxConcurrent`。 -- 默认情况下,如果 120 秒内没有完成的 `getUpdates` 存活信号,则会触发长轮询看门狗重启。只有当你的部署在长时间运行任务期间仍然出现误判的轮询卡死重启时,才增大 `channels.telegram.pollingStallThresholdMs`。该值以毫秒为单位,允许范围为 `30000` 到 `600000`;支持按账户覆盖。 +- 私信消息可以携带 `message_thread_id`;OpenClaw 会使用具备线程感知能力的会话键进行路由,并为回复保留线程 ID。 +- 长轮询使用带有按聊天/按线程顺序控制的 grammY runner。整体 runner sink 并发使用 `agents.defaults.maxConcurrent`。 +- 默认情况下,如果 120 秒内没有完成的 `getUpdates` 存活信号,就会触发长轮询 watchdog 重启。仅当你的部署在长时间运行的任务期间仍然出现误报的轮询卡死重启时,才增加 `channels.telegram.pollingStallThresholdMs`。该值单位为毫秒,允许范围是 `30000` 到 `600000`;支持按账户覆盖。 - Telegram Bot API 不支持已读回执(`sendReadReceipts` 不适用)。 ## 功能参考 - OpenClaw 可以实时流式输出部分回复: + OpenClaw 可以实时流式传输部分回复: - 私聊:预览消息 + `editMessageText` - - 群组 / 话题:预览消息 + `editMessageText` + - 群组/话题:预览消息 + `editMessageText` 要求: - `channels.telegram.streaming` 为 `off | partial | block | progress`(默认:`partial`) - - 在 Telegram 上,`progress` 会映射为 `partial`(与跨渠道命名兼容) - - `streaming.preview.toolProgress` 控制工具 / 进度更新是否复用同一条被编辑的预览消息(默认:`true`)。设置为 `false` 可保留单独的工具 / 进度消息。 + - `progress` 在 Telegram 上映射为 `partial`(与跨渠道命名兼容) + - `streaming.preview.toolProgress` 控制工具/进度更新是否复用同一条被编辑的预览消息(默认:`true`)。设置为 `false` 可保留单独的工具/进度消息。 - 旧版 `channels.telegram.streamMode` 和布尔型 `streaming` 值会自动映射 对于纯文本回复: - - 私信:OpenClaw 会保留同一条预览消息,并在原地执行最终编辑(不会发送第二条消息) - - 群组 / 话题:OpenClaw 会保留同一条预览消息,并在原地执行最终编辑(不会发送第二条消息) + - 私信:OpenClaw 保留同一条预览消息,并原地执行最终编辑(不会发送第二条消息) + - 群组/话题:OpenClaw 保留同一条预览消息,并原地执行最终编辑(不会发送第二条消息) - 对于复杂回复(例如媒体负载),OpenClaw 会回退到普通最终发送,然后清理预览消息。 + 对于复杂回复(例如媒体负载),OpenClaw 会回退到普通最终投递,然后清理预览消息。 预览流式传输与分块流式传输彼此独立。当为 Telegram 显式启用分块流式传输时,OpenClaw 会跳过预览流,以避免双重流式传输。 - 如果原生草稿传输不可用或被拒绝,OpenClaw 会自动回退到 `sendMessage` + `editMessageText`。 + 如果原生草稿传输不可用/被拒绝,OpenClaw 会自动回退到 `sendMessage` + `editMessageText`。 - 仅限 Telegram 的推理流: + 仅 Telegram 的推理流: - - `/reasoning stream` 会在生成期间将推理发送到实时预览中 + - `/reasoning stream` 会在生成过程中将推理发送到实时预览 - 最终答案发送时不包含推理文本 @@ -306,9 +306,9 @@ curl "https://api.telegram.org/bot/getUpdates" 出站文本使用 Telegram `parse_mode: "HTML"`。 - - 类 Markdown 文本会渲染为 Telegram 安全的 HTML。 + - 类 Markdown 文本会被渲染为 Telegram 安全的 HTML。 - 原始模型 HTML 会被转义,以减少 Telegram 解析失败。 - - 如果 Telegram 拒绝解析后的 HTML,OpenClaw 会重试为纯文本。 + - 如果 Telegram 拒绝已解析的 HTML,OpenClaw 会以纯文本重试。 链接预览默认启用,可通过 `channels.telegram.linkPreview: false` 禁用。 @@ -321,7 +321,7 @@ curl "https://api.telegram.org/bot/getUpdates" - `commands.native: "auto"` 为 Telegram 启用原生命令 - 添加自定义命令菜单项: + 添加自定义命令菜单条目: ```json5 { @@ -341,37 +341,37 @@ curl "https://api.telegram.org/bot/getUpdates" - 名称会被标准化(去掉前导 `/`,转为小写) - 有效模式:`a-z`、`0-9`、`_`,长度 `1..32` - 自定义命令不能覆盖原生命令 - - 冲突或重复项会被跳过并记录日志 + - 冲突/重复项会被跳过并记录日志 说明: - - 自定义命令仅是菜单项;它们不会自动实现行为 - - 即使未显示在 Telegram 菜单中,plugin / skill 命令在手动输入时仍然可以工作 + - 自定义命令只是菜单条目;它们不会自动实现行为 + - 即使未显示在 Telegram 菜单中,plugin/skill 命令在手动输入时仍然可以工作 - 如果禁用原生命令,内置命令会被移除。如果已配置,自定义 / plugin 命令仍可能注册。 + 如果禁用了原生命令,内置命令会被移除。自定义/plugin 命令如果已配置,仍可能会注册。 常见设置失败: - - `setMyCommands failed` 且带有 `BOT_COMMANDS_TOO_MUCH`,表示即使在裁剪后 Telegram 菜单仍然超出限制;请减少 plugin / skill / 自定义命令,或禁用 `channels.telegram.commands.native`。 - - `setMyCommands failed` 且带有 network / fetch 错误,通常表示到 `api.telegram.org` 的出站 DNS / HTTPS 被阻止。 + - `setMyCommands failed` 且报错 `BOT_COMMANDS_TOO_MUCH`,表示 Telegram 菜单在裁剪后仍然超出限制;请减少 plugin/skill/自定义命令,或禁用 `channels.telegram.commands.native`。 + - `setMyCommands failed` 且出现 network/fetch 错误,通常表示到 `api.telegram.org` 的出站 DNS/HTTPS 被阻止。 ### 设备配对命令(`device-pair` plugin) 安装 `device-pair` plugin 后: 1. `/pair` 生成设置代码 - 2. 在 iOS 应用中粘贴该代码 - 3. `/pair pending` 列出待处理请求(包括角色 / 范围) - 4. 批准该请求: + 2. 在 iOS 应用中粘贴代码 + 3. `/pair pending` 列出待处理请求(包括角色/作用域) + 4. 批准请求: - `/pair approve ` 用于显式批准 - - 当只有一个待处理请求时,使用 `/pair approve` - - `/pair approve latest` 用于最近的请求 + - 当只有一个待处理请求时使用 `/pair approve` + - `/pair approve latest` 用于最近的一条 - 设置代码携带短时有效的 bootstrap 令牌。内置 bootstrap 交接会将主节点令牌保持为 `scopes: []`;任何交接出的 operator 令牌都被限制在 `operator.approvals`、`operator.read`、`operator.talk.secrets` 和 `operator.write` 范围内。Bootstrap 范围检查带有角色前缀,因此该 operator allowlist 仅满足 operator 请求;非 operator 角色仍需要其自身角色前缀下的范围。 + 设置代码携带一个短时有效的 bootstrap token。内置 bootstrap 交接会将主节点 token 保持在 `scopes: []`;任何交接出的 operator token 都会限制在 `operator.approvals`、`operator.read`、`operator.talk.secrets` 和 `operator.write`。Bootstrap 作用域检查带有角色前缀,因此该 operator allowlist 只会满足 operator 请求;非 operator 角色仍然需要其自身角色前缀下的作用域。 - 如果设备在重试时变更了认证详情(例如角色 / 范围 / 公钥),之前的待处理请求会被替代,新请求会使用不同的 `requestId`。批准前请重新运行 `/pair pending`。 + 如果设备在重试时更改了认证详情(例如角色/作用域/公钥),之前的待处理请求会被替代,新请求会使用不同的 `requestId`。批准前请重新运行 `/pair pending`。 - 更多详情: [配对](/zh-CN/channels/pairing#pair-via-telegram-recommended-for-ios)。 + 更多详情:[配对](/zh-CN/channels/pairing#pair-via-telegram-recommended-for-ios)。 @@ -425,23 +425,23 @@ curl "https://api.telegram.org/bot/getUpdates" action: "send", channel: "telegram", to: "123456789", - message: "请选择一个选项:", + message: "Choose an option:", buttons: [ [ - { text: "是", callback_data: "yes" }, - { text: "否", callback_data: "no" }, + { text: "Yes", callback_data: "yes" }, + { text: "No", callback_data: "no" }, ], - [{ text: "取消", callback_data: "cancel" }], + [{ text: "Cancel", callback_data: "cancel" }], ], } ``` - 回调点击会作为文本传递给智能体: + 回调点击会以文本形式传递给智能体: `callback_data: ` - + Telegram 工具动作包括: - `sendMessage`(`to`、`content`、可选的 `mediaUrl`、`replyToMessageId`、`messageThreadId`) @@ -450,9 +450,9 @@ curl "https://api.telegram.org/bot/getUpdates" - `editMessage`(`chatId`、`messageId`、`content`) - `createForumTopic`(`chatId`、`name`、可选的 `iconColor`、`iconCustomEmojiId`) - 渠道消息动作提供更易用的别名(`send`、`react`、`delete`、`edit`、`sticker`、`sticker-search`、`topic-create`)。 + 渠道消息动作公开了更易用的别名(`send`、`react`、`delete`、`edit`、`sticker`、`sticker-search`、`topic-create`)。 - 控制开关: + 门控控制: - `channels.telegram.actions.sendMessage` - `channels.telegram.actions.deleteMessage` @@ -460,9 +460,9 @@ curl "https://api.telegram.org/bot/getUpdates" - `channels.telegram.actions.sticker`(默认:禁用) 注意:`edit` 和 `topic-create` 当前默认启用,并且没有单独的 `channels.telegram.actions.*` 开关。 - 运行时发送使用当前激活的配置 / 密钥快照(启动 / 重载时),因此动作路径不会在每次发送时临时重新解析 SecretRef。 + 运行时发送使用的是当前激活的配置/密钥快照(启动/重载时),因此动作路径不会在每次发送时临时重新解析 SecretRef。 - 移除反应的语义:[/tools/reactions](/zh-CN/tools/reactions) + 移除 reaction 的语义:[/tools/reactions](/zh-CN/tools/reactions) @@ -470,7 +470,7 @@ curl "https://api.telegram.org/bot/getUpdates" Telegram 支持在生成输出中使用显式回复线程标签: - `[[reply_to_current]]` 回复触发消息 - - `[[reply_to:]]` 回复特定的 Telegram 消息 ID + - `[[reply_to:]]` 回复指定的 Telegram 消息 ID `channels.telegram.replyToMode` 控制处理方式: @@ -478,7 +478,7 @@ curl "https://api.telegram.org/bot/getUpdates" - `first` - `all` - 注意:`off` 会禁用隐式回复线程处理。显式 `[[reply_to_*]]` 标签仍会被遵循。 + 注意:`off` 会禁用隐式回复线程。显式 `[[reply_to_*]]` 标签仍然会被遵循。 @@ -486,19 +486,19 @@ curl "https://api.telegram.org/bot/getUpdates" 论坛超级群组: - 话题会话键会追加 `:topic:` - - 回复和正在输入状态会定向到该话题线程 + - 回复和输入状态会定向到该话题线程 - 话题配置路径: `channels.telegram.groups..topics.` - 常规话题(`threadId=1`)特殊情况: + 通用话题(`threadId=1`)特殊情况: - 发送消息时会省略 `message_thread_id`(Telegram 会拒绝 `sendMessage(...thread_id=1)`) - - 正在输入动作仍包含 `message_thread_id` + - 输入动作仍会包含 `message_thread_id` - 话题继承:除非覆盖,否则话题条目会继承群组设置(`requireMention`、`allowFrom`、`skills`、`systemPrompt`、`enabled`、`groupPolicy`)。 - `agentId` 仅限话题,不会从群组默认值继承。 + 话题继承:话题条目会继承群组设置,除非被覆盖(`requireMention`、`allowFrom`、`skills`、`systemPrompt`、`enabled`、`groupPolicy`)。 + `agentId` 仅限话题级,不会从群组默认值继承。 - **按话题的智能体路由**:每个话题都可以通过在话题配置中设置 `agentId` 路由到不同的智能体。这样每个话题都有自己独立的工作区、记忆和会话。示例: + **按话题的智能体路由**:每个话题都可以通过在话题配置中设置 `agentId` 路由到不同的智能体。这样每个话题都有自己隔离的工作区、记忆和会话。示例: ```json5 { @@ -507,7 +507,7 @@ curl "https://api.telegram.org/bot/getUpdates" groups: { "-1001234567890": { topics: { - "1": { agentId: "main" }, // 常规话题 → main 智能体 + "1": { agentId: "main" }, // 通用话题 → main 智能体 "3": { agentId: "zu" }, // 开发话题 → zu 智能体 "5": { agentId: "coder" } // 代码审查 → coder 智能体 } @@ -518,11 +518,11 @@ curl "https://api.telegram.org/bot/getUpdates" } ``` - 每个话题随后都会有自己的会话键:`agent:zu:telegram:group:-1001234567890:topic:3` + 此后每个话题都有自己的会话键:`agent:zu:telegram:group:-1001234567890:topic:3` - **持久 ACP 话题绑定**:论坛话题可以通过顶层类型化 ACP 绑定固定 ACP harness 会话: + **持久化 ACP 话题绑定**:论坛话题可以通过顶层类型化 ACP 绑定固定到 ACP harness 会话: - - `bindings[]`,其中 `type: "acp"` 且 `match.channel: "telegram"` + - `bindings[]` 中使用 `type: "acp"` 且 `match.channel: "telegram"` 示例: @@ -571,13 +571,13 @@ curl "https://api.telegram.org/bot/getUpdates" } ``` - 这当前仅适用于群组和超级群组中的论坛话题。 + 这目前仅适用于群组和超级群组中的论坛话题。 - **从聊天中生成线程绑定的 ACP**: + **从聊天中发起线程绑定的 ACP 实例**: - `/acp spawn --thread here|auto` 可以将当前 Telegram 话题绑定到新的 ACP 会话。 - - 后续的话题消息会直接路由到该绑定的 ACP 会话(无需 `/acp steer`)。 - - OpenClaw 在成功绑定后会将生成确认消息固定在该话题内。 + - 后续该话题中的消息会直接路由到绑定的 ACP 会话(无需 `/acp steer`)。 + - 成功绑定后,OpenClaw 会将生成确认消息固定在该话题中。 - 需要 `channels.telegram.threadBindings.spawnAcpSessions=true`。 模板上下文包括: @@ -587,7 +587,7 @@ curl "https://api.telegram.org/bot/getUpdates" 私信线程行为: - - 带有 `message_thread_id` 的私聊会保持私信路由,但使用具备线程感知能力的会话键 / 回复目标。 + - 带有 `message_thread_id` 的私聊会保持私信路由,但使用具备线程感知能力的会话键/回复目标。 @@ -597,7 +597,7 @@ curl "https://api.telegram.org/bot/getUpdates" Telegram 区分语音消息和音频文件。 - 默认:音频文件行为 - - 在智能体回复中使用标签 `[[audio_as_voice]]` 可强制按语音消息发送 + - 在智能体回复中添加标签 `[[audio_as_voice]]` 可强制按语音消息发送 消息动作示例: @@ -627,14 +627,14 @@ curl "https://api.telegram.org/bot/getUpdates" } ``` - 视频便笺不支持说明文字;如果提供了消息文本,会单独发送。 + 视频便笺不支持标题;提供的消息文本会单独发送。 ### 贴纸 入站贴纸处理: - 静态 WEBP:下载并处理(占位符 ``) - - 动画 TGS:跳过 + - 动态 TGS:跳过 - 视频 WEBM:跳过 贴纸上下文字段: @@ -649,7 +649,7 @@ curl "https://api.telegram.org/bot/getUpdates" - `~/.openclaw/telegram/sticker-cache.json` - 贴纸会在可能的情况下只描述一次,并进行缓存,以减少重复的视觉调用。 + 贴纸会在可能时只描述一次并缓存,以减少重复的视觉调用。 启用贴纸动作: @@ -689,8 +689,8 @@ curl "https://api.telegram.org/bot/getUpdates" - - Telegram 反应以 `message_reaction` 更新形式到达(与消息负载分开)。 + + Telegram reaction 会以 `message_reaction` 更新形式到达(与消息负载分离)。 启用后,OpenClaw 会将如下系统事件加入队列: @@ -698,42 +698,42 @@ curl "https://api.telegram.org/bot/getUpdates" 配置: - - `channels.telegram.reactionNotifications`:`off | own | all`(默认:`own`) - - `channels.telegram.reactionLevel`:`off | ack | minimal | extensive`(默认:`minimal`) + - `channels.telegram.reactionNotifications`: `off | own | all`(默认:`own`) + - `channels.telegram.reactionLevel`: `off | ack | minimal | extensive`(默认:`minimal`) 说明: - - `own` 表示仅处理用户对机器人发送消息的反应(通过已发送消息缓存尽力识别)。 - - 反应事件仍遵循 Telegram 访问控制(`dmPolicy`、`allowFrom`、`groupPolicy`、`groupAllowFrom`);未授权发送者会被丢弃。 - - Telegram 不会在反应更新中提供线程 ID。 + - `own` 表示仅处理用户对机器人发送消息的 reaction(通过已发送消息缓存尽力识别)。 + - Reaction 事件仍然遵循 Telegram 访问控制(`dmPolicy`、`allowFrom`、`groupPolicy`、`groupAllowFrom`);未授权发送者会被丢弃。 + - Telegram 不会在 reaction 更新中提供线程 ID。 - 非论坛群组会路由到群聊会话 - - 论坛群组会路由到群组常规话题会话(`:topic:1`),而不是精确的来源话题 + - 论坛群组会路由到群组通用话题会话(`:topic:1`),而不是确切来源话题 - 用于轮询 / Webhook 的 `allowed_updates` 会自动包含 `message_reaction`。 + 轮询/webhook 的 `allowed_updates` 会自动包含 `message_reaction`。 - - `ackReaction` 会在 OpenClaw 处理入站消息时发送一个确认表情符号。 + + `ackReaction` 会在 OpenClaw 处理入站消息时发送一个确认 emoji。 解析顺序: - `channels.telegram.accounts..ackReaction` - `channels.telegram.ackReaction` - `messages.ackReaction` - - 智能体身份 emoji 回退(`agents.list[].identity.emoji`,否则为 “👀”) + - 智能体身份 emoji 回退(`agents.list[].identity.emoji`,否则为 "👀") 说明: - - Telegram 需要 unicode emoji(例如 “👀”)。 - - 使用 `""` 可为某个渠道或账户禁用该反应。 + - Telegram 需要 unicode emoji(例如 "👀")。 + - 使用 `""` 可为某个渠道或账户禁用该 reaction。 - + 默认启用渠道配置写入(`configWrites !== false`)。 - 由 Telegram 触发的写入包括: + Telegram 触发的写入包括: - 群组迁移事件(`migrate_to_chat_id`),用于更新 `channels.telegram.groups` - `/config set` 和 `/config unset`(需要启用命令) @@ -752,21 +752,27 @@ curl "https://api.telegram.org/bot/getUpdates" - + + 群组模型选择器内联按钮需要与 `/models` 相同的授权。未授权参与者可以浏览和点击按钮,但 OpenClaw 会在更改会话模型前拒绝该回调。 + + + 默认:长轮询。 Webhook 模式: - 设置 `channels.telegram.webhookUrl` - - 设置 `channels.telegram.webhookSecret`(设置 webhook URL 时为必填) - - 可选 `channels.telegram.webhookPath`(默认 `/telegram-webhook`) - - 可选 `channels.telegram.webhookHost`(默认 `127.0.0.1`) - - 可选 `channels.telegram.webhookPort`(默认 `8787`) + - 设置 `channels.telegram.webhookSecret`(设置了 webhook URL 时必填) + - 可选:`channels.telegram.webhookPath`(默认 `/telegram-webhook`) + - 可选:`channels.telegram.webhookHost`(默认 `127.0.0.1`) + - 可选:`channels.telegram.webhookPort`(默认 `8787`) - Webhook 模式的默认本地监听器绑定到 `127.0.0.1:8787`。 + webhook 模式下,默认本地监听器绑定到 `127.0.0.1:8787`。 - 如果你的公共端点不同,请在前面放置一个反向代理,并将 `webhookUrl` 指向该公共 URL。 - 当你明确需要外部入口时,请设置 `webhookHost`(例如 `0.0.0.0`)。 + 如果你的公网端点不同,请在前面放置一个反向代理,并将 `webhookUrl` 指向公网 URL。 + 只有在你明确需要外部入口时,才设置 `webhookHost`(例如 `0.0.0.0`)。 + + grammY webhook 回调会在 5 秒内返回 200,这样 Telegram 就不会将长时间运行的更新误判为读取超时并重试;更长时间的工作会在后台继续。轮询在 `getUpdates` 出现 409 冲突后会重建 HTTP 传输,因此重试会使用新的 TCP 连接,而不是在被 Telegram 终止的 keep-alive socket 上循环。 @@ -774,17 +780,17 @@ curl "https://api.telegram.org/bot/getUpdates" - `channels.telegram.textChunkLimit` 默认值为 4000。 - `channels.telegram.chunkMode="newline"` 会在按长度拆分之前优先选择段落边界(空行)。 - `channels.telegram.mediaMaxMb`(默认 100)限制 Telegram 入站和出站媒体大小。 - - `channels.telegram.timeoutSeconds` 会覆盖 Telegram API 客户端超时时间(如果未设置,则使用 grammY 默认值)。 - - `channels.telegram.pollingStallThresholdMs` 默认值为 `120000`;仅在出现误报的轮询卡死重启时,才在 `30000` 到 `600000` 之间调整。 + - `channels.telegram.timeoutSeconds` 会覆盖 Telegram API 客户端超时(如果未设置,则使用 grammY 默认值)。 + - `channels.telegram.pollingStallThresholdMs` 默认是 `120000`;仅在误报轮询卡死重启时,将其调整到 `30000` 到 `600000` 之间。 - 群组上下文历史使用 `channels.telegram.historyLimit` 或 `messages.groupChat.historyLimit`(默认 50);`0` 表示禁用。 - - 回复 / 引用 / 转发的补充上下文当前会按接收时原样传递。 + - reply/quote/forward 补充上下文当前会按接收时原样传递。 - Telegram allowlist 主要控制谁可以触发智能体,而不是完整的补充上下文脱敏边界。 - 私信历史控制: - `channels.telegram.dmHistoryLimit` - `channels.telegram.dms[""].historyLimit` - - `channels.telegram.retry` 配置适用于 Telegram 发送辅助功能(CLI / 工具 / 动作)中的可恢复出站 API 错误。 + - `channels.telegram.retry` 配置会应用于 Telegram 发送辅助函数(CLI/工具/动作),用于处理可恢复的出站 API 错误。 - CLI 发送目标可以是数值型聊天 ID 或用户名: + CLI 发送目标可以是数字聊天 ID 或用户名: ```bash openclaw message send --channel telegram --target 123456789 --message "hi" @@ -801,7 +807,7 @@ openclaw message poll --channel telegram --target -1001234567890:topic:42 \ --poll-duration-seconds 300 --poll-public ``` - 仅 Telegram 支持的投票标志: + 仅 Telegram 的投票参数: - `--poll-duration-seconds`(5-600) - `--poll-anonymous` @@ -810,70 +816,70 @@ openclaw message poll --channel telegram --target -1001234567890:topic:42 \ Telegram 发送还支持: - - 当 `channels.telegram.capabilities.inlineButtons` 允许时,使用带有 `buttons` 块的 `--presentation` 来实现内联键盘 - - 使用 `--pin` 或 `--delivery '{"pin":true}'` 请求固定发送内容,前提是机器人在该聊天中有固定权限 - - 使用 `--force-document` 将出站图片和 GIF 作为文档发送,而不是压缩照片或动画媒体上传 + - `--presentation`,配合 `buttons` 块用于内联键盘,前提是 `channels.telegram.capabilities.inlineButtons` 允许 + - `--pin` 或 `--delivery '{"pin":true}'`,用于在机器人有权限时请求固定发送内容 + - `--force-document`,将出站图片和 GIF 作为文档发送,而不是压缩照片或动画媒体上传 - 动作控制: + 动作门控: - `channels.telegram.actions.sendMessage=false` 会禁用 Telegram 出站消息,包括投票 - - `channels.telegram.actions.poll=false` 会禁用 Telegram 投票创建,同时保留常规发送 + - `channels.telegram.actions.poll=false` 会禁用 Telegram 投票创建,同时保留普通发送功能 - - Telegram 支持在审批人私信中进行执行审批,并且可以选择在原始聊天或话题中发布审批提示。 + + Telegram 支持在审批人私信中进行 exec 审批,也可以选择将审批提示发送到原始聊天或话题中。 配置路径: - `channels.telegram.execApprovals.enabled` - - `channels.telegram.execApprovals.approvers`(可选;在可能的情况下,会回退到从 `allowFrom` 和直接 `defaultTo` 推断出的数值型所有者 ID) + - `channels.telegram.execApprovals.approvers`(可选;如果可能,会回退到从 `allowFrom` 和私信 `defaultTo` 直接推断出的数字所有者 ID) - `channels.telegram.execApprovals.target`(`dm` | `channel` | `both`,默认:`dm`) - `agentFilter`、`sessionFilter` - 审批人必须是数值型 Telegram 用户 ID。当 `enabled` 未设置或为 `"auto"`,且至少能解析出一个审批人时,Telegram 会自动启用原生执行审批;审批人可来自 `execApprovals.approvers`,也可来自账户的数值型所有者配置(`allowFrom` 和直接消息 `defaultTo`)。将 `enabled: false` 设为显式禁用 Telegram 作为原生审批客户端。否则,审批请求会回退到其他已配置的审批路径或执行审批回退策略。 + 审批人必须是 Telegram 数字用户 ID。当 `enabled` 未设置或为 `"auto"`,且至少能解析出一个审批人时,Telegram 会自动启用原生 exec 审批;审批人可以来自 `execApprovals.approvers`,也可以来自账户的数字所有者配置(`allowFrom` 和私信 `defaultTo`)。设置 `enabled: false` 可以显式禁用 Telegram 作为原生审批客户端。否则,审批请求会回退到其他已配置的审批路由或 exec 审批回退策略。 - Telegram 还会渲染其他聊天渠道使用的共享审批按钮。原生 Telegram 适配器主要增加审批人私信路由、渠道 / 话题扇出,以及发送前的正在输入提示。 - 当这些按钮存在时,它们是主要的审批 UX;只有在工具结果表明聊天审批不可用,或手动审批是唯一途径时,OpenClaw + Telegram 也会渲染其他聊天渠道使用的共享审批按钮。原生 Telegram 适配器主要增加了审批人私信路由、渠道/话题扇出,以及投递前的输入状态提示。 + 当这些按钮存在时,它们应是主要的审批 UX;只有在工具结果表明聊天审批不可用或手动审批是唯一途径时,OpenClaw 才应包含手动 `/approve` 命令。 - 发送规则: + 投递规则: - - `target: "dm"` 仅向已解析的审批人私信发送审批提示 - - `target: "channel"` 将提示发送回原始 Telegram 聊天 / 话题 - - `target: "both"` 会发送到审批人私信和原始聊天 / 话题 + - `target: "dm"` 仅将审批提示发送到已解析出的审批人私信 + - `target: "channel"` 将提示发回原始 Telegram 聊天/话题 + - `target: "both"` 同时发送到审批人私信和原始聊天/话题 - 只有已解析的审批人可以批准或拒绝。非审批人不能使用 `/approve`,也不能使用 Telegram 审批按钮。 + 只有已解析出的审批人才可以批准或拒绝。非审批人不能使用 `/approve`,也不能使用 Telegram 审批按钮。 审批解析行为: - - 以 `plugin:` 为前缀的 ID 总是通过 plugin 审批解析。 + - 带有 `plugin:` 前缀的 ID 总是通过 plugin 审批进行解析。 - 其他审批 ID 会先尝试 `exec.approval.resolve`。 - 如果 Telegram 也被授权用于 plugin 审批,并且 Gateway 网关表示 - 执行审批未知 / 已过期,则 Telegram 会通过 - `plugin.approval.resolve` 再重试一次。 - - 真正的执行审批拒绝 / 错误不会悄悄回退到 plugin + exec 审批未知/已过期,Telegram 会再通过 + `plugin.approval.resolve` 重试一次。 + - 真正的 exec 审批拒绝/错误不会静默回退到 plugin 审批解析。 - 渠道发送会在聊天中显示命令文本,因此仅在受信任的群组 / 话题中启用 `channel` 或 `both`。当提示落在论坛话题中时,OpenClaw 会为审批提示和审批后的后续消息都保留该话题。执行审批默认在 30 分钟后过期。 + 渠道内投递会在聊天中显示命令文本,因此仅在受信任的群组/话题中启用 `channel` 或 `both`。当提示发送到论坛话题时,OpenClaw 会为审批提示和审批后的后续消息都保留该话题。exec 审批默认会在 30 分钟后过期。 - 内联审批按钮也依赖 `channels.telegram.capabilities.inlineButtons` 允许目标界面(`dm`、`group` 或 `all`)。 + 内联审批按钮还依赖于 `channels.telegram.capabilities.inlineButtons` 允许目标界面(`dm`、`group` 或 `all`)。 - 相关文档:[执行审批](/zh-CN/tools/exec-approvals) + 相关文档:[Exec 审批](/zh-CN/tools/exec-approvals) ## 错误回复控制 -当智能体遇到发送或提供商错误时,Telegram 可以回复错误文本,也可以抑制该回复。两个配置键控制此行为: +当智能体遇到投递或提供商错误时,Telegram 可以回复错误文本,也可以抑制错误回复。两个配置键控制此行为: -| 键 | 值 | 默认值 | 说明 | -| ----------------------------------- | ----------------- | ------- | ----------------------------------------------------------------------------------------------- | -| `channels.telegram.errorPolicy` | `reply`, `silent` | `reply` | `reply` 会向聊天发送友好的错误消息。`silent` 会完全抑制错误回复。 | -| `channels.telegram.errorCooldownMs` | number (ms) | `60000` | 向同一聊天发送错误回复之间的最短时间。可防止服务中断期间的错误刷屏。 | +| 键 | 值 | 默认值 | 描述 | +| ----------------------------------- | ----------------- | ------- | ---------------------------------------------------------------------------------------------- | +| `channels.telegram.errorPolicy` | `reply`, `silent` | `reply` | `reply` 会向聊天发送一条友好的错误消息。`silent` 会完全抑制错误回复。 | +| `channels.telegram.errorCooldownMs` | 数字(毫秒) | `60000` | 向同一聊天发送错误回复之间的最短时间间隔。可防止故障期间的错误刷屏。 | -支持按账户、按群组和按话题覆盖(继承方式与其他 Telegram 配置键相同)。 +支持按账户、按群组和按话题覆盖(继承规则与其他 Telegram 配置键相同)。 ```json5 { @@ -896,40 +902,40 @@ openclaw message poll --channel telegram --target -1001234567890:topic:42 \ - - 如果 `requireMention=false`,Telegram 隐私模式必须允许完整可见性。 - - BotFather:`/setprivacy` -> 禁用 - - 然后移除并重新添加机器人到群组 - - 当配置期望未提及的群组消息时,`openclaw channels status` 会发出警告。 - - `openclaw channels status --probe` 可以检查显式数值型群组 ID;通配符 `"*"` 无法进行成员资格探测。 + - 如果 `requireMention=false`,Telegram 隐私模式必须允许完全可见。 + - BotFather:`/setprivacy` -> Disable + - 然后移除并重新将机器人添加到群组 + - 当配置期望接收未提及的群组消息时,`openclaw channels status` 会发出警告。 + - `openclaw channels status --probe` 可以检查显式数字群组 ID;通配符 `"*"` 无法探测成员资格。 - 快速会话测试:`/activation always`。 - - 当存在 `channels.telegram.groups` 时,必须列出该群组(或包含 `"*"`) - - 验证机器人是否在群组中 - - 查看日志:使用 `openclaw logs --follow` 了解跳过原因 + - 当存在 `channels.telegram.groups` 时,必须列出该群组(或包含 `"*"`) + - 验证机器人是否已加入群组 + - 查看日志:`openclaw logs --follow` 以了解跳过原因 - - 授权你的发送者身份(配对和 / 或数值型 `allowFrom`) + - 授权你的发送者身份(配对和/或数字 `allowFrom`) - 即使群组策略为 `open`,命令授权仍然适用 - - `setMyCommands failed` 且带有 `BOT_COMMANDS_TOO_MUCH`,表示原生命令菜单条目过多;请减少 plugin / skill / 自定义命令,或禁用原生菜单 - - `setMyCommands failed` 且带有 network / fetch 错误,通常表示到 `api.telegram.org` 的 DNS / HTTPS 可达性存在问题 + - `setMyCommands failed` 且报错 `BOT_COMMANDS_TOO_MUCH`,表示原生命令菜单条目过多;请减少 plugin/skill/自定义命令,或禁用原生菜单 + - `setMyCommands failed` 且出现 network/fetch 错误,通常表示到 `api.telegram.org` 的 DNS/HTTPS 可达性存在问题 - - Node 22+ + 自定义 fetch / proxy 可能会在 AbortSignal 类型不匹配时触发立即中止行为。 - - 某些主机会优先将 `api.telegram.org` 解析为 IPv6;损坏的 IPv6 出站连接会导致 Telegram API 间歇性失败。 - - 如果日志包含 `TypeError: fetch failed` 或 `Network request for 'getUpdates' failed!`,OpenClaw 现在会将其作为可恢复的网络错误进行重试。 - - 如果日志包含 `Polling stall detected`,默认情况下,在 120 秒内没有完成的长轮询存活信号时,OpenClaw 会重启轮询并重建 Telegram 传输。 - - 仅当长时间运行的 `getUpdates` 调用本身健康,但你的主机仍报告误判的轮询卡死重启时,才增加 `channels.telegram.pollingStallThresholdMs`。持续卡死通常指向主机与 `api.telegram.org` 之间的 proxy、DNS、IPv6 或 TLS 出站问题。 - - 在直连出站 / TLS 不稳定的 VPS 主机上,请通过 `channels.telegram.proxy` 路由 Telegram API 调用: + - Node 22+ + 自定义 fetch/proxy 在 AbortSignal 类型不匹配时,可能触发立即中止行为。 + - 某些主机会优先将 `api.telegram.org` 解析为 IPv6;损坏的 IPv6 出站连接可能导致间歇性的 Telegram API 故障。 + - 如果日志包含 `TypeError: fetch failed` 或 `Network request for 'getUpdates' failed!`,OpenClaw 现在会将这些作为可恢复的网络错误进行重试。 + - 如果日志包含 `Polling stall detected`,默认情况下,OpenClaw 会在 120 秒内没有完成的长轮询存活信号后重启轮询并重建 Telegram 传输。 + - 只有当长时间运行的 `getUpdates` 调用本身健康,但你的主机仍然出现误报轮询卡死重启时,才增加 `channels.telegram.pollingStallThresholdMs`。持续卡死通常意味着主机与 `api.telegram.org` 之间存在代理、DNS、IPv6 或 TLS 出站问题。 + - 在直连出站/TLS 不稳定的 VPS 主机上,可通过 `channels.telegram.proxy` 为 Telegram API 调用配置代理: ```yaml channels: @@ -938,7 +944,7 @@ channels: ``` - Node 22+ 默认使用 `autoSelectFamily=true`(WSL2 除外)和 `dnsResultOrder=ipv4first`。 - - 如果你的主机是 WSL2,或明确在仅 IPv4 行为下效果更好,请强制指定地址族选择: + - 如果你的主机是 WSL2,或明确在仅 IPv4 行为下工作得更好,请强制指定地址族选择: ```yaml channels: @@ -947,11 +953,11 @@ channels: autoSelectFamily: false ``` - - RFC 2544 基准测试范围响应(`198.18.0.0/15`)默认已被允许 - 用于 Telegram 媒体下载。如果受信任的 fake-IP 或 - 透明代理在媒体下载期间将 `api.telegram.org` 重写为其他 - 私有 / 内部 / 特殊用途地址,你可以选择启用 - 仅限 Telegram 的绕过: + - RFC 2544 基准范围地址(`198.18.0.0/15`)默认已经允许用于 + Telegram 媒体下载。如果受信任的 fake-IP 或 + 透明代理在媒体下载期间将 `api.telegram.org` 重写到其他 + 私有/内部/特殊用途地址,你可以选择启用 + Telegram 专用绕过: ```yaml channels: @@ -960,25 +966,25 @@ channels: dangerouslyAllowPrivateNetwork: true ``` - - 同样的显式启用也支持按账户设置,路径为 + - 同样的显式启用也可按账户设置,路径为 `channels.telegram.accounts..network.dangerouslyAllowPrivateNetwork`。 - - 如果你的代理将 Telegram 媒体主机解析为 `198.18.x.x`,请先保持 + - 如果你的代理将 Telegram 媒体主机解析到 `198.18.x.x`,请先保持 危险标志关闭。Telegram 媒体默认已经允许 RFC 2544 - 基准测试范围。 + 基准范围。 `channels.telegram.network.dangerouslyAllowPrivateNetwork` 会削弱 Telegram - 媒体 SSRF 防护。仅在受信任、由操作员控制的代理 - 环境中使用,例如 Clash、Mihomo 或 Surge 的 fake-IP 路由,当它们 - 在 RFC 2544 基准测试范围之外生成私有或特殊用途响应时。 - 对于普通公共互联网 Telegram 访问,请保持关闭。 + 媒体 SSRF 防护。仅应在受信任、由操作方控制的代理 + 环境中使用,例如 Clash、Mihomo 或 Surge 的 fake-IP 路由, + 且这些环境会在 RFC 2544 基准范围之外合成私有或特殊用途应答。 + 对于正常的公网 Telegram 访问,请保持关闭。 - 环境变量覆盖(临时): - `OPENCLAW_TELEGRAM_DISABLE_AUTO_SELECT_FAMILY=1` - `OPENCLAW_TELEGRAM_ENABLE_AUTO_SELECT_FAMILY=1` - `OPENCLAW_TELEGRAM_DNS_RESULT_ORDER=ipv4first` - - 验证 DNS 响应: + - 验证 DNS 应答: ```bash dig +short api.telegram.org A @@ -990,90 +996,90 @@ dig +short api.telegram.org AAAA 更多帮助:[渠道故障排除](/zh-CN/channels/troubleshooting)。 -## Telegram 配置参考指引 +## Telegram 配置参考指针 主要参考: -- `channels.telegram.enabled`:启用 / 禁用渠道启动。 +- `channels.telegram.enabled`:启用/禁用渠道启动。 - `channels.telegram.botToken`:机器人令牌(BotFather)。 - `channels.telegram.tokenFile`:从常规文件路径读取令牌。不接受符号链接。 - `channels.telegram.dmPolicy`:`pairing | allowlist | open | disabled`(默认:pairing)。 -- `channels.telegram.allowFrom`:私信 allowlist(数值型 Telegram 用户 ID)。`allowlist` 要求至少一个发送者 ID。`open` 要求 `"*"`。`openclaw doctor --fix` 可以将旧版 `@username` 条目解析为 ID,并可在 allowlist 迁移流程中从配对存储文件恢复 allowlist 条目。 -- `channels.telegram.actions.poll`:启用或禁用 Telegram 投票创建(默认:启用;仍需要 `sendMessage`)。 -- `channels.telegram.defaultTo`:当未提供显式 `--reply-to` 时,CLI `--deliver` 使用的默认 Telegram 目标。 +- `channels.telegram.allowFrom`:私信 allowlist(Telegram 数字用户 ID)。`allowlist` 至少要求一个发送者 ID。`open` 要求包含 `"*"`。`openclaw doctor --fix` 可以将旧版 `@username` 条目解析为 ID,也可以在 allowlist 迁移流程中从配对存储文件恢复 allowlist 条目。 +- `channels.telegram.actions.poll`:启用或禁用 Telegram 投票创建(默认:启用;仍然要求 `sendMessage`)。 +- `channels.telegram.defaultTo`:CLI `--deliver` 在未提供显式 `--reply-to` 时使用的默认 Telegram 目标。 - `channels.telegram.groupPolicy`:`open | allowlist | disabled`(默认:allowlist)。 -- `channels.telegram.groupAllowFrom`:群组发送者 allowlist(数值型 Telegram 用户 ID)。`openclaw doctor --fix` 可以将旧版 `@username` 条目解析为 ID。非数值条目在认证时会被忽略。群组认证不会使用私信配对存储回退(`2026.2.25+`)。 +- `channels.telegram.groupAllowFrom`:群组发送者 allowlist(Telegram 数字用户 ID)。`openclaw doctor --fix` 可以将旧版 `@username` 条目解析为 ID。非数字条目在认证时会被忽略。群组认证不会使用私信配对存储回退(`2026.2.25+`)。 - 多账户优先级: - - 当配置了两个或更多账户 ID 时,请设置 `channels.telegram.defaultAccount`(或包含 `channels.telegram.accounts.default`)以显式指定默认路由。 - - 如果两者都未设置,OpenClaw 会回退到第一个标准化账户 ID,并由 `openclaw doctor` 发出警告。 + - 配置了两个或更多账户 ID 时,请设置 `channels.telegram.defaultAccount`(或包含 `channels.telegram.accounts.default`),以明确默认路由。 + - 如果两者都未设置,OpenClaw 会回退到第一个标准化后的账户 ID,并且 `openclaw doctor` 会发出警告。 - `channels.telegram.accounts.default.allowFrom` 和 `channels.telegram.accounts.default.groupAllowFrom` 仅适用于 `default` 账户。 - 当账户级值未设置时,命名账户会继承 `channels.telegram.allowFrom` 和 `channels.telegram.groupAllowFrom`。 - 命名账户不会继承 `channels.telegram.accounts.default.allowFrom` / `groupAllowFrom`。 -- `channels.telegram.groups`:每群组默认值 + allowlist(使用 `"*"` 作为全局默认值)。 +- `channels.telegram.groups`:按群组的默认值 + allowlist(使用 `"*"` 作为全局默认值)。 - `channels.telegram.groups..groupPolicy`:按群组覆盖 `groupPolicy`(`open | allowlist | disabled`)。 - `channels.telegram.groups..requireMention`:提及门控默认值。 - `channels.telegram.groups..skills`:skill 过滤器(省略 = 所有 Skills,空值 = 无)。 - `channels.telegram.groups..allowFrom`:按群组覆盖发送者 allowlist。 - `channels.telegram.groups..systemPrompt`:该群组的额外系统提示词。 - - `channels.telegram.groups..enabled`:当为 `false` 时禁用该群组。 - - `channels.telegram.groups..topics..*`:按话题覆盖(群组字段 + 仅话题字段 `agentId`)。 + - `channels.telegram.groups..enabled`:当值为 `false` 时禁用该群组。 + - `channels.telegram.groups..topics..*`:按话题覆盖(群组字段 + 仅话题支持的 `agentId`)。 - `channels.telegram.groups..topics..agentId`:将此话题路由到特定智能体(覆盖群组级和绑定路由)。 - `channels.telegram.groups..topics..groupPolicy`:按话题覆盖 `groupPolicy`(`open | allowlist | disabled`)。 - `channels.telegram.groups..topics..requireMention`:按话题覆盖提及门控。 -- 顶层 `bindings[]`,其中 `type: "acp"` 且在 `match.peer.id` 中使用规范话题 ID `chatId:topic:topicId`:持久 ACP 话题绑定字段(参见 [ACP 智能体](/zh-CN/tools/acp-agents#channel-specific-settings))。 +- 顶层 `bindings[]` 中使用 `type: "acp"`,并在 `match.peer.id` 中使用规范话题 ID `chatId:topic:topicId`:持久化 ACP 话题绑定字段(参见 [ACP 智能体](/zh-CN/tools/acp-agents#channel-specific-settings))。 - `channels.telegram.direct..topics..agentId`:将私信话题路由到特定智能体(行为与论坛话题相同)。 -- `channels.telegram.execApprovals.enabled`:为此账户启用 Telegram 作为基于聊天的执行审批客户端。 -- `channels.telegram.execApprovals.approvers`:允许批准或拒绝执行请求的 Telegram 用户 ID。当 `channels.telegram.allowFrom` 或直接的 `channels.telegram.defaultTo` 已经标识所有者时,此项可选。 +- `channels.telegram.execApprovals.enabled`:为该账户启用 Telegram 作为基于聊天的原生 exec 审批客户端。 +- `channels.telegram.execApprovals.approvers`:允许批准或拒绝 exec 请求的 Telegram 用户 ID。当 `channels.telegram.allowFrom` 或直接的 `channels.telegram.defaultTo` 已能识别所有者时,此项可选。 - `channels.telegram.execApprovals.target`:`dm | channel | both`(默认:`dm`)。`channel` 和 `both` 会在存在时保留原始 Telegram 话题。 - `channels.telegram.execApprovals.agentFilter`:用于转发审批提示的可选智能体 ID 过滤器。 -- `channels.telegram.execApprovals.sessionFilter`:用于转发审批提示的可选会话键过滤器(子串或正则)。 -- `channels.telegram.accounts..execApprovals`:按账户覆盖 Telegram 执行审批路由和审批人授权。 +- `channels.telegram.execApprovals.sessionFilter`:用于转发审批提示的可选会话键过滤器(子串或正则表达式)。 +- `channels.telegram.accounts..execApprovals`:按账户覆盖 Telegram exec 审批路由和审批人授权。 - `channels.telegram.capabilities.inlineButtons`:`off | dm | group | all | allowlist`(默认:allowlist)。 - `channels.telegram.accounts..capabilities.inlineButtons`:按账户覆盖。 -- `channels.telegram.commands.nativeSkills`:启用 / 禁用 Telegram 原生 Skills 命令。 +- `channels.telegram.commands.nativeSkills`:启用/禁用 Telegram 原生 Skills 命令。 - `channels.telegram.replyToMode`:`off | first | all`(默认:`off`)。 - `channels.telegram.textChunkLimit`:出站分块大小(字符数)。 -- `channels.telegram.chunkMode`:`length`(默认)或 `newline`,表示在按长度分块前优先按空行(段落边界)拆分。 +- `channels.telegram.chunkMode`:`length`(默认)或 `newline`,会在按长度分块前先按空行(段落边界)拆分。 - `channels.telegram.linkPreview`:切换出站消息的链接预览(默认:true)。 -- `channels.telegram.streaming`:`off | partial | block | progress`(实时流式预览;默认:`partial`;`progress` 映射为 `partial`;`block` 是旧版预览模式兼容项)。Telegram 预览流式传输使用单条预览消息并原地编辑。 -- `channels.telegram.streaming.preview.toolProgress`:当预览流式传输处于激活状态时,复用实时预览消息用于工具 / 进度更新(默认:`true`)。设为 `false` 可保留单独的工具 / 进度消息。 -- `channels.telegram.mediaMaxMb`:Telegram 入站 / 出站媒体上限(MB,默认:100)。 -- `channels.telegram.retry`:Telegram 发送辅助功能(CLI / 工具 / 动作)在可恢复出站 API 错误上的重试策略(attempts、minDelayMs、maxDelayMs、jitter)。 -- `channels.telegram.network.autoSelectFamily`:覆盖 Node `autoSelectFamily`(true=启用,false=禁用)。在 Node 22+ 上默认启用,WSL2 默认禁用。 +- `channels.telegram.streaming`:`off | partial | block | progress`(实时流式预览;默认:`partial`;`progress` 会映射为 `partial`;`block` 是旧版预览模式兼容值)。Telegram 预览流式传输使用一条原地编辑的单一预览消息。 +- `channels.telegram.streaming.preview.toolProgress`:当预览流式传输处于激活状态时,复用实时预览消息显示工具/进度更新(默认:`true`)。设置为 `false` 可保留单独的工具/进度消息。 +- `channels.telegram.mediaMaxMb`:Telegram 入站/出站媒体大小上限(MB,默认:100)。 +- `channels.telegram.retry`:Telegram 发送辅助函数(CLI/工具/动作)在可恢复的出站 API 错误上使用的重试策略(attempts、minDelayMs、maxDelayMs、jitter)。 +- `channels.telegram.network.autoSelectFamily`:覆盖 Node 的 autoSelectFamily(true=启用,false=禁用)。在 Node 22+ 上默认启用,WSL2 默认禁用。 - `channels.telegram.network.dnsResultOrder`:覆盖 DNS 结果顺序(`ipv4first` 或 `verbatim`)。在 Node 22+ 上默认是 `ipv4first`。 -- `channels.telegram.network.dangerouslyAllowPrivateNetwork`:危险的显式启用项,用于受信任的 fake-IP 或透明代理环境;在这些环境中,Telegram 媒体下载会将 `api.telegram.org` 解析到默认 RFC 2544 基准测试范围允许值之外的私有 / 内部 / 特殊用途地址。 -- `channels.telegram.proxy`:Bot API 调用的代理 URL(SOCKS / HTTP)。 -- `channels.telegram.webhookUrl`:启用 Webhook 模式(需要 `channels.telegram.webhookSecret`)。 -- `channels.telegram.webhookSecret`:Webhook 密钥(设置 `webhookUrl` 时必填)。 -- `channels.telegram.webhookPath`:本地 Webhook 路径(默认 `/telegram-webhook`)。 -- `channels.telegram.webhookHost`:本地 Webhook 绑定主机(默认 `127.0.0.1`)。 -- `channels.telegram.webhookPort`:本地 Webhook 绑定端口(默认 `8787`)。 -- `channels.telegram.actions.reactions`:控制 Telegram 工具反应。 -- `channels.telegram.actions.sendMessage`:控制 Telegram 工具消息发送。 -- `channels.telegram.actions.deleteMessage`:控制 Telegram 工具消息删除。 -- `channels.telegram.actions.sticker`:控制 Telegram 贴纸动作——发送和搜索(默认:false)。 -- `channels.telegram.reactionNotifications`:`off | own | all` —— 控制哪些反应会触发系统事件(未设置时默认:`own`)。 -- `channels.telegram.reactionLevel`:`off | ack | minimal | extensive` —— 控制智能体的反应能力(未设置时默认:`minimal`)。 -- `channels.telegram.errorPolicy`:`reply | silent` —— 控制错误回复行为(默认:`reply`)。支持按账户 / 群组 / 话题覆盖。 -- `channels.telegram.errorCooldownMs`:向同一聊天发送错误回复之间的最短毫秒数(默认:`60000`)。可防止服务中断期间的错误刷屏。 +- `channels.telegram.network.dangerouslyAllowPrivateNetwork`:危险的显式启用项,用于受信任的 fake-IP 或透明代理环境,在这些环境中 Telegram 媒体下载会将 `api.telegram.org` 解析到默认 RFC 2544 基准范围许可之外的私有/内部/特殊用途地址。 +- `channels.telegram.proxy`:用于 Bot API 调用的代理 URL(SOCKS/HTTP)。 +- `channels.telegram.webhookUrl`:启用 webhook 模式(要求设置 `channels.telegram.webhookSecret`)。 +- `channels.telegram.webhookSecret`:webhook 密钥(设置了 webhookUrl 时必填)。 +- `channels.telegram.webhookPath`:本地 webhook 路径(默认 `/telegram-webhook`)。 +- `channels.telegram.webhookHost`:本地 webhook 绑定主机(默认 `127.0.0.1`)。 +- `channels.telegram.webhookPort`:本地 webhook 绑定端口(默认 `8787`)。 +- `channels.telegram.actions.reactions`:门控 Telegram 工具 reaction。 +- `channels.telegram.actions.sendMessage`:门控 Telegram 工具消息发送。 +- `channels.telegram.actions.deleteMessage`:门控 Telegram 工具消息删除。 +- `channels.telegram.actions.sticker`:门控 Telegram 贴纸动作——发送和搜索(默认:false)。 +- `channels.telegram.reactionNotifications`:`off | own | all` —— 控制哪些 reaction 会触发系统事件(未设置时默认:`own`)。 +- `channels.telegram.reactionLevel`:`off | ack | minimal | extensive` —— 控制智能体的 reaction 能力(未设置时默认:`minimal`)。 +- `channels.telegram.errorPolicy`:`reply | silent` —— 控制错误回复行为(默认:`reply`)。支持按账户/群组/话题覆盖。 +- `channels.telegram.errorCooldownMs`:向同一聊天发送错误回复之间的最短毫秒数(默认:`60000`)。可防止故障期间错误刷屏。 - [配置参考 - Telegram](/zh-CN/gateway/configuration-reference#telegram) Telegram 特有的高信号字段: -- 启动 / 认证:`enabled`、`botToken`、`tokenFile`、`accounts.*`(`tokenFile` 必须指向常规文件;不接受符号链接) +- 启动/认证:`enabled`、`botToken`、`tokenFile`、`accounts.*`(`tokenFile` 必须指向常规文件;不接受符号链接) - 访问控制:`dmPolicy`、`allowFrom`、`groupPolicy`、`groupAllowFrom`、`groups`、`groups.*.topics.*`、顶层 `bindings[]`(`type: "acp"`) -- 执行审批:`execApprovals`、`accounts.*.execApprovals` -- 命令 / 菜单:`commands.native`、`commands.nativeSkills`、`customCommands` -- 线程 / 回复:`replyToMode` +- exec 审批:`execApprovals`、`accounts.*.execApprovals` +- 命令/菜单:`commands.native`、`commands.nativeSkills`、`customCommands` +- 线程/回复:`replyToMode` - 流式传输:`streaming`(预览)、`streaming.preview.toolProgress`、`block streaming` -- 格式化 / 发送:`textChunkLimit`、`chunkMode`、`linkPreview`、`responsePrefix` -- 媒体 / 网络:`mediaMaxMb`、`timeoutSeconds`、`pollingStallThresholdMs`、`retry`、`network.autoSelectFamily`、`network.dangerouslyAllowPrivateNetwork`、`proxy` -- Webhook:`webhookUrl`、`webhookSecret`、`webhookPath`、`webhookHost` -- 动作 / 功能:`capabilities.inlineButtons`、`actions.sendMessage|editMessage|deleteMessage|reactions|sticker` -- 反应:`reactionNotifications`、`reactionLevel` +- 格式化/投递:`textChunkLimit`、`chunkMode`、`linkPreview`、`responsePrefix` +- 媒体/网络:`mediaMaxMb`、`timeoutSeconds`、`pollingStallThresholdMs`、`retry`、`network.autoSelectFamily`、`network.dangerouslyAllowPrivateNetwork`、`proxy` +- webhook:`webhookUrl`、`webhookSecret`、`webhookPath`、`webhookHost` +- 动作/能力:`capabilities.inlineButtons`、`actions.sendMessage|editMessage|deleteMessage|reactions|sticker` +- reactions:`reactionNotifications`、`reactionLevel` - 错误:`errorPolicy`、`errorCooldownMs` -- 写入 / 历史:`configWrites`、`historyLimit`、`dmHistoryLimit`、`dms.*.historyLimit` +- 写入/历史:`configWrites`、`historyLimit`、`dmHistoryLimit`、`dms.*.historyLimit` ## 相关内容 diff --git a/docs/zh-CN/channels/whatsapp.md b/docs/zh-CN/channels/whatsapp.md index 87b78c25e..7ebd71db2 100644 --- a/docs/zh-CN/channels/whatsapp.md +++ b/docs/zh-CN/channels/whatsapp.md @@ -1,28 +1,28 @@ --- read_when: - - 处理 WhatsApp / web 渠道行为或收件箱路由 + - 处理 WhatsApp/web 渠道行为或收件箱路由 summary: WhatsApp 渠道支持、访问控制、投递行为和运维 title: WhatsApp x-i18n: - generated_at: "2026-04-21T23:42:08Z" + generated_at: "2026-04-23T07:03:52Z" model: gpt-5.4 provider: openai - source_hash: 5c527b9f7f58f4bb7272a6d1c0f9a435d7d46a9b99790243594afb5c305606b3 + source_hash: e14735a33ffb48334b920a5e63645abf3445f56481b1ce8b7c128800e2adc981 source_path: channels/whatsapp.md workflow: 15 --- # WhatsApp(Web 渠道) -状态:通过 WhatsApp Web(Baileys)达到生产就绪。Gateway 网关拥有已关联的会话。 +状态:通过 WhatsApp Web(Baileys)达到生产可用。Gateway 网关拥有已关联的会话。 ## 安装(按需) - 新手引导(`openclaw onboard`)和 `openclaw channels add --channel whatsapp` - 会在你首次选择 WhatsApp 插件时提示安装该插件。 + 会在你首次选择 WhatsApp 插件时提示安装它。 - `openclaw channels login --channel whatsapp` 也会在 - 插件尚未安装时提供安装流程。 -- 开发渠道 + git checkout:默认使用本地插件路径。 + 插件尚未存在时提供安装流程。 +- 开发渠道 + git 检出:默认使用本地插件路径。 - Stable/Beta:默认使用 npm 包 `@openclaw/whatsapp`。 仍然可以手动安装: @@ -33,17 +33,17 @@ openclaw plugins install @openclaw/whatsapp - 对未知发件人的默认私信策略是配对。 + 未知发送者的默认私信策略是配对。 跨渠道诊断与修复操作手册。 - 完整的渠道配置模式与示例。 + 完整的渠道配置模式和示例。 -## 快速设置 +## 快速开始 @@ -63,13 +63,13 @@ openclaw plugins install @openclaw/whatsapp - + ```bash openclaw channels login --channel whatsapp ``` - 对于特定账号: + 针对特定账户: ```bash openclaw channels login --channel whatsapp --account work @@ -98,16 +98,16 @@ openclaw pairing approve whatsapp -OpenClaw 建议在可能的情况下为 WhatsApp 使用单独的号码。(渠道元数据和设置流程已针对该设置进行优化,但也支持个人号码设置。) +OpenClaw 建议在可能的情况下为 WhatsApp 使用单独的号码。(渠道元数据和设置流程已针对这种方式优化,但也支持个人号码设置。) ## 部署模式 - 这是最简洁的运维模式: + 这是最清晰的运维模式: - - 为 OpenClaw 使用独立的 WhatsApp 身份 + - 为 OpenClaw 使用单独的 WhatsApp 身份 - 更清晰的私信允许列表和路由边界 - 更低的自聊混淆概率 @@ -133,12 +133,12 @@ OpenClaw 建议在可能的情况下为 WhatsApp 使用单独的号码。(渠 - `allowFrom` 包含你的个人号码 - `selfChatMode: true` - 在运行时,自聊保护基于已关联的自身号码和 `allowFrom` 生效。 + 在运行时,自聊保护会依据已关联的自身号码和 `allowFrom` 生效。 - 在当前 OpenClaw 渠道架构中,消息平台渠道基于 WhatsApp Web(`Baileys`)。 + 在当前的 OpenClaw 渠道架构中,消息平台渠道基于 WhatsApp Web(`Baileys`)。 内置聊天渠道注册表中没有单独的 Twilio WhatsApp 消息渠道。 @@ -148,95 +148,95 @@ OpenClaw 建议在可能的情况下为 WhatsApp 使用单独的号码。(渠 ## 运行时模型 - Gateway 网关拥有 WhatsApp socket 和重连循环。 -- 向外发送消息要求目标账号存在活动中的 WhatsApp 监听器。 +- 出站发送要求目标账户存在活动的 WhatsApp 监听器。 - 状态和广播聊天会被忽略(`@status`、`@broadcast`)。 -- 直接聊天使用私信会话规则(`session.dmScope`;默认 `main` 会将私信折叠到智能体主会话)。 +- 私聊使用私信会话规则(`session.dmScope`;默认 `main` 会将私信折叠到智能体主会话)。 - 群组会话彼此隔离(`agent::whatsapp:group:`)。 -- WhatsApp Web 传输遵循 Gateway 网关主机上的标准代理环境变量(`HTTPS_PROXY`、`HTTP_PROXY`、`NO_PROXY` 及其小写变体)。优先使用主机级代理配置,而不是渠道专用的 WhatsApp 代理设置。 +- WhatsApp Web 传输会遵循 Gateway 网关主机上的标准代理环境变量(`HTTPS_PROXY`、`HTTP_PROXY`、`NO_PROXY` 及其小写变体)。优先使用主机级代理配置,而不是渠道专用的 WhatsApp 代理设置。 ## 访问控制和激活 - `channels.whatsapp.dmPolicy` 控制直接聊天访问: + `channels.whatsapp.dmPolicy` 控制私聊访问: - `pairing`(默认) - `allowlist` - `open`(要求 `allowFrom` 包含 `"*"`) - `disabled` - `allowFrom` 接受 E.164 风格号码(内部会进行标准化)。 + `allowFrom` 接受 E.164 风格号码(内部会规范化)。 - 多账号覆盖:`channels.whatsapp.accounts..dmPolicy`(以及 `allowFrom`)优先于该账号的渠道级默认值。 + 多账户覆盖:该账户上的 `channels.whatsapp.accounts..dmPolicy`(以及 `allowFrom`)优先于渠道级默认值。 运行时行为细节: - - 配对会持久化到渠道允许存储,并与已配置的 `allowFrom` 合并 + - 配对会持久化到渠道 allow-store,并与配置的 `allowFrom` 合并 - 如果未配置允许列表,则默认允许已关联的自身号码 - - 出站的 `fromMe` 私信绝不会自动配对 + - 出站 `fromMe` 私信永远不会自动配对 - 群组访问有两层: + 群组访问有两层控制: 1. **群组成员允许列表**(`channels.whatsapp.groups`) - - 如果省略 `groups`,则所有群组都有资格 + - 如果省略 `groups`,则所有群组都符合条件 - 如果存在 `groups`,它会作为群组允许列表(允许使用 `"*"`) - 2. **群组发件人策略**(`channels.whatsapp.groupPolicy` + `groupAllowFrom`) - - `open`:绕过发件人允许列表 - - `allowlist`:发件人必须匹配 `groupAllowFrom`(或 `*`) + 2. **群组发送者策略**(`channels.whatsapp.groupPolicy` + `groupAllowFrom`) + - `open`:绕过发送者允许列表 + - `allowlist`:发送者必须匹配 `groupAllowFrom`(或 `*`) - `disabled`:阻止所有群组入站消息 - 发件人允许列表回退: + 发送者允许列表回退: - 如果未设置 `groupAllowFrom`,运行时会在可用时回退到 `allowFrom` - - 发件人允许列表会在提及 / 回复激活之前进行评估 + - 发送者允许列表会在提及/回复激活之前进行评估 - 注意:如果根本不存在 `channels.whatsapp` 配置块,运行时的群组策略回退为 `allowlist`(并记录警告日志),即使已设置 `channels.defaults.groupPolicy` 也是如此。 + 注意:如果根本不存在 `channels.whatsapp` 配置块,运行时群组策略回退值为 `allowlist`(并记录警告日志),即使设置了 `channels.defaults.groupPolicy` 也是如此。 - 群组回复默认需要被提及。 + 默认情况下,群组回复需要被提及。 提及检测包括: - 对机器人身份的显式 WhatsApp 提及 - 已配置的提及正则模式(`agents.list[].groupChat.mentionPatterns`,回退为 `messages.groupChat.mentionPatterns`) - - 隐式回复机器人检测(回复发件人与机器人身份匹配) + - 隐式回复给机器人的检测(回复发送者匹配机器人身份) 安全说明: - - 引用 / 回复只能满足提及门控;它**不会**授予发件人授权 - - 在 `groupPolicy: "allowlist"` 下,即使非允许列表发件人回复了允许列表用户的消息,仍会被阻止 + - 引用/回复只会满足提及门控;它**不会**授予发送者授权 + - 当 `groupPolicy: "allowlist"` 时,即使非允许列表发送者回复了允许列表用户的消息,也仍会被阻止 会话级激活命令: - `/activation mention` - `/activation always` - `activation` 会更新会话状态(不是全局配置)。它受 owner 门控保护。 + `activation` 会更新会话状态(而非全局配置)。它受所有者权限控制。 ## 个人号码和自聊行为 -当已关联的自身号码也出现在 `allowFrom` 中时,WhatsApp 自聊保护会激活: +当已关联的自身号码也存在于 `allowFrom` 中时,WhatsApp 自聊保护会激活: -- 跳过自聊回合的已读回执 -- 忽略本会触发给自己发送提醒的 mention-JID 自动触发行为 +- 跳过自聊轮次的已读回执 +- 忽略原本会提醒你自己的 mention-JID 自动触发行为 - 如果未设置 `messages.responsePrefix`,自聊回复默认使用 `[{identity.name}]` 或 `[openclaw]` -## 消息标准化和上下文 +## 消息规范化和上下文 - 传入的 WhatsApp 消息会被包装到共享入站信封中。 + 传入的 WhatsApp 消息会包装到共享的入站信封中。 - 如果存在引用回复,上下文会按以下形式附加: + 如果存在引用回复,上下文会以下列形式追加: ```text [Replying to id:] @@ -244,12 +244,12 @@ OpenClaw 建议在可能的情况下为 WhatsApp 使用单独的号码。(渠 [/Replying] ``` - 回复元数据字段也会在可用时填充(`ReplyToId`、`ReplyToBody`、`ReplyToSender`、发件人 JID/E.164)。 + 在可用时,也会填充回复元数据字段(`ReplyToId`、`ReplyToBody`、`ReplyToSender`、发送者 JID/E.164)。 - - 仅包含媒体的入站消息会使用如下占位符进行标准化: + + 仅含媒体的入站消息会使用如下占位符进行规范化: - `` - `` @@ -257,14 +257,14 @@ OpenClaw 建议在可能的情况下为 WhatsApp 使用单独的号码。(渠 - `` - `` - 位置和联系人负载会在路由前标准化为文本上下文。 + 位置和联系人负载会在路由前规范化为文本上下文。 - 对于群组,未处理消息可以被缓冲,并在机器人最终被触发时注入为上下文。 + 对于群组,当机器人最终被触发时,未处理消息可以被缓冲并作为上下文注入。 - - 默认限制:`50` + - 默认上限:`50` - 配置:`channels.whatsapp.historyLimit` - 回退:`messages.groupChat.historyLimit` - `0` 表示禁用 @@ -277,7 +277,7 @@ OpenClaw 建议在可能的情况下为 WhatsApp 使用单独的号码。(渠 - 对已接受的入站 WhatsApp 消息,默认启用已读回执。 + 默认会为已接受的入站 WhatsApp 消息发送已读回执。 全局禁用: @@ -291,7 +291,7 @@ OpenClaw 建议在可能的情况下为 WhatsApp 使用单独的号码。(渠 } ``` - 按账号覆盖: + 按账户覆盖: ```json5 { @@ -307,7 +307,7 @@ OpenClaw 建议在可能的情况下为 WhatsApp 使用单独的号码。(渠 } ``` - 即使全局启用,自聊回合也会跳过已读回执。 + 即使全局启用,自聊轮次也会跳过已读回执。 @@ -318,40 +318,62 @@ OpenClaw 建议在可能的情况下为 WhatsApp 使用单独的号码。(渠 - 默认分块限制:`channels.whatsapp.textChunkLimit = 4000` - `channels.whatsapp.chunkMode = "length" | "newline"` - - `newline` 模式优先按段落边界(空行)分块,然后再回退到按长度安全分块 + - `newline` 模式优先按段落边界(空行)分块,然后回退到按长度安全分块 - - 支持图片、视频、音频(PTT 语音便签)和文档负载 - - `audio/ogg` 会被重写为 `audio/ogg; codecs=opus` 以兼容语音便签 - - 通过在视频发送中设置 `gifPlayback: true` 支持动画 GIF 播放 - - 发送多媒体回复负载时,说明文字会应用到第一个媒体项 + - 支持图片、视频、音频(PTT 语音便笺)和文档负载 + - `audio/ogg` 会被改写为 `audio/ogg; codecs=opus` 以兼容语音便笺 + - 视频发送时可通过 `gifPlayback: true` 支持动画 GIF 播放 + - 发送多媒体回复负载时,说明文字会应用到第一项媒体 - 媒体来源可以是 HTTP(S)、`file://` 或本地路径 - 入站媒体保存上限:`channels.whatsapp.mediaMaxMb`(默认 `50`) - 出站媒体发送上限:`channels.whatsapp.mediaMaxMb`(默认 `50`) - - 按账号覆盖使用 `channels.whatsapp.accounts..mediaMaxMb` - - 图片会自动优化(调整大小 / 质量扫描)以符合限制 - - 媒体发送失败时,首项回退会发送文本警告,而不是静默丢弃响应 + - 按账户覆盖使用 `channels.whatsapp.accounts..mediaMaxMb` + - 图片会自动优化(尺寸调整/质量扫描)以适配限制 + - 媒体发送失败时,首项回退会发送文本警告,而不是静默丢弃回复 -## 反应级别 +## 回复引用 -`channels.whatsapp.reactionLevel` 控制智能体在 WhatsApp 上使用 emoji 反应的广泛程度: +WhatsApp 支持原生回复引用,出站回复会可见地引用入站消息。使用 `channels.whatsapp.replyToMode` 控制。 -| 级别 | 确认反应 | 智能体主动发起的反应 | 描述 | -| ------------- | -------- | -------------------- | ---- | -| `"off"` | 否 | 否 | 完全不使用反应 | -| `"ack"` | 是 | 否 | 仅确认反应(回复前回执) | -| `"minimal"` | 是 | 是(保守) | 确认 + 智能体反应,采用保守指导 | -| `"extensive"` | 是 | 是(鼓励) | 确认 + 智能体反应,采用鼓励性指导 | +| 值 | 行为 | +| -------- | ---------------------------------------------------------------------------- | +| `"auto"` | 当提供商支持时引用入站消息;否则跳过引用 | +| `"on"` | 始终引用入站消息;如果引用被拒绝,则回退为普通发送 | +| `"off"` | 从不引用;以普通消息发送 | + +默认值为 `"auto"`。按账户覆盖使用 `channels.whatsapp.accounts..replyToMode`。 + +```json5 +{ + channels: { + whatsapp: { + replyToMode: "on", + }, + }, +} +``` + +## Reaction 级别 + +`channels.whatsapp.reactionLevel` 控制智能体在 WhatsApp 上使用 emoji reaction 的广泛程度: + +| 级别 | 确认 reaction | 智能体主动 reaction | 说明 | +| ------------- | ------------- | ------------------- | -------------------------------------------- | +| `"off"` | 否 | 否 | 完全不使用 reaction | +| `"ack"` | 是 | 否 | 仅确认 reaction(回复前回执) | +| `"minimal"` | 是 | 是(保守) | 确认 + 在保守引导下使用智能体 reaction | +| `"extensive"` | 是 | 是(鼓励) | 确认 + 在鼓励引导下使用智能体 reaction | 默认值:`"minimal"`。 -按账号覆盖使用 `channels.whatsapp.accounts..reactionLevel`。 +按账户覆盖使用 `channels.whatsapp.accounts..reactionLevel`。 ```json5 { @@ -363,10 +385,10 @@ OpenClaw 建议在可能的情况下为 WhatsApp 使用单独的号码。(渠 } ``` -## 确认反应 +## 确认 reaction -WhatsApp 支持通过 `channels.whatsapp.ackReaction` 在接收入站消息时立即发送确认反应。 -确认反应受 `reactionLevel` 门控——当 `reactionLevel` 为 `"off"` 时会被抑制。 +WhatsApp 支持通过 `channels.whatsapp.ackReaction` 在接收入站消息时立即发送确认 reaction。 +确认 reaction 受 `reactionLevel` 控制——当 `reactionLevel` 为 `"off"` 时,它们会被抑制。 ```json5 { @@ -384,49 +406,49 @@ WhatsApp 支持通过 `channels.whatsapp.ackReaction` 在接收入站消息时 行为说明: -- 在接受入站消息后立即发送(回复前) -- 失败会被记录,但不会阻止正常回复投递 -- 群组模式 `mentions` 会对由提及触发的回合做出反应;群组激活 `always` 会绕过此检查 +- 在接收入站消息后立即发送(回复前) +- 失败会被记录日志,但不会阻止正常回复投递 +- 群组模式 `mentions` 会在由提及触发的轮次发送 reaction;群组激活 `always` 会绕过此检查 - WhatsApp 使用 `channels.whatsapp.ackReaction`(这里不会使用旧版 `messages.ackReaction`) -## 多账号和凭证 +## 多账户和凭证 - - - 账号 id 来自 `channels.whatsapp.accounts` - - 默认账号选择:如果存在则为 `default`,否则为第一个已配置的账号 id(排序后) - - 账号 id 会在内部标准化后用于查找 + + - 账户 ID 来自 `channels.whatsapp.accounts` + - 默认账户选择:如果存在则为 `default`,否则为第一个已配置的账户 ID(按排序) + - 账户 ID 会在内部规范化以供查找 - 当前认证路径:`~/.openclaw/credentials/whatsapp//creds.json` - 备份文件:`creds.json.bak` - - `~/.openclaw/credentials/` 中的旧版默认认证仍会被识别 / 迁移,用于默认账号流程 + - 位于 `~/.openclaw/credentials/` 中的旧版默认认证仍会在默认账户流程中被识别/迁移 - - `openclaw channels logout --channel whatsapp [--account ]` 会清除该账号的 WhatsApp 认证状态。 + + `openclaw channels logout --channel whatsapp [--account ]` 会清除该账户的 WhatsApp 认证状态。 - 在旧版认证目录中,会保留 `oauth.json`,同时删除 Baileys 认证文件。 + 在旧版认证目录中,会保留 `oauth.json`,同时移除 Baileys 认证文件。 ## 工具、操作和配置写入 -- 智能体工具支持包括 WhatsApp 反应操作(`react`)。 +- 智能体工具支持包括 WhatsApp reaction 操作(`react`)。 - 操作门控: - `channels.whatsapp.actions.reactions` - `channels.whatsapp.actions.polls` -- 渠道发起的配置写入默认启用(可通过 `channels.whatsapp.configWrites=false` 禁用)。 +- 默认启用渠道发起的配置写入(可通过 `channels.whatsapp.configWrites=false` 禁用)。 ## 故障排除 - - 症状:渠道状态显示未关联。 + + 症状:渠道状态报告为未关联。 - 修复方法: + 修复: ```bash openclaw channels login --channel whatsapp @@ -436,9 +458,9 @@ WhatsApp 支持通过 `channels.whatsapp.ackReaction` 在接收入站消息时 - 症状:已关联账号反复断开连接或重复尝试重连。 + 症状:已关联账户反复断开或重复尝试重连。 - 修复方法: + 修复: ```bash openclaw doctor @@ -450,14 +472,14 @@ WhatsApp 支持通过 `channels.whatsapp.ackReaction` 在接收入站消息时 - 当目标账号不存在活动中的 Gateway 网关监听器时,出站发送会快速失败。 + 当目标账户没有活动的 Gateway 网关监听器时,出站发送会快速失败。 - 请确认 Gateway 网关正在运行,且该账号已关联。 + 请确保 Gateway 网关正在运行,且该账户已关联。 - 按以下顺序检查: + 请按以下顺序检查: - `groupPolicy` - `groupAllowFrom` / `allowFrom` @@ -474,32 +496,32 @@ WhatsApp 支持通过 `channels.whatsapp.ackReaction` 在接收入站消息时 ## 系统提示词 -WhatsApp 通过 `groups` 和 `direct` 映射支持类似 Telegram 风格的群组和直接聊天系统提示词。 +WhatsApp 通过 `groups` 和 `direct` 映射支持类似 Telegram 风格的群组和私聊系统提示词。 群组消息的解析层级: -首先确定生效的 `groups` 映射:如果账号定义了自己的 `groups`,它会完全替换根级 `groups` 映射(不进行深度合并)。随后提示词查找会在结果中的单个映射上运行: +首先确定生效的 `groups` 映射:如果账户定义了自己的 `groups`,它会完全替换根级 `groups` 映射(不进行深度合并)。然后在得到的这个单一映射上执行提示词查找: -1. **群组专用系统提示词**(`groups[""].systemPrompt`):如果特定群组条目定义了 `systemPrompt`,则使用它。 -2. **群组通配系统提示词**(`groups["*"].systemPrompt`):当特定群组条目不存在或未定义 `systemPrompt` 时使用。 +1. **群组专属系统提示词**(`groups[""].systemPrompt`):如果特定群组条目定义了 `systemPrompt`,则使用它。 +2. **群组通配系统提示词**(`groups["*"].systemPrompt`):当特定群组条目不存在,或未定义 `systemPrompt` 时使用。 -直接消息的解析层级: +私聊消息的解析层级: -首先确定生效的 `direct` 映射:如果账号定义了自己的 `direct`,它会完全替换根级 `direct` 映射(不进行深度合并)。随后提示词查找会在结果中的单个映射上运行: +首先确定生效的 `direct` 映射:如果账户定义了自己的 `direct`,它会完全替换根级 `direct` 映射(不进行深度合并)。然后在得到的这个单一映射上执行提示词查找: -1. **直接消息专用系统提示词**(`direct[""].systemPrompt`):如果特定对端条目定义了 `systemPrompt`,则使用它。 -2. **直接消息通配系统提示词**(`direct["*"].systemPrompt`):当特定对端条目不存在或未定义 `systemPrompt` 时使用。 +1. **私聊专属系统提示词**(`direct[""].systemPrompt`):如果特定对端条目定义了 `systemPrompt`,则使用它。 +2. **私聊通配系统提示词**(`direct["*"].systemPrompt`):当特定对端条目不存在,或未定义 `systemPrompt` 时使用。 注意:`dms` 仍然是轻量级的按私信历史记录覆盖桶(`dms..historyLimit`);提示词覆盖位于 `direct` 下。 -**与 Telegram 多账号行为的区别:** 在 Telegram 中,多账号设置下会有意对所有账号抑制根级 `groups`——即使某些账号没有定义自己的 `groups` 也是如此——以防机器人接收到其并不属于的群组消息。WhatsApp 不应用这一保护:对于没有定义账号级覆盖的账号,无论配置了多少个账号,根级 `groups` 和根级 `direct` 都始终会被继承。在多账号 WhatsApp 设置中,如果你希望为每个账号设置独立的群组或直接消息提示词,请在每个账号下显式定义完整映射,而不要依赖根级默认值。 +**与 Telegram 多账户行为的区别:** 在 Telegram 中,多账户设置下,根级 `groups` 会对所有账户有意禁用——即使某些账户没有定义自己的 `groups` 也是如此——以防机器人接收它本不属于的群组消息。WhatsApp 不应用此保护:无论配置了多少账户,未定义账户级覆盖的账户始终会继承根级 `groups` 和根级 `direct`。在多账户 WhatsApp 设置中,如果你希望为每个账户设置不同的群组或私聊提示词,请在每个账户下显式定义完整映射,而不要依赖根级默认值。 重要行为: -- `channels.whatsapp.groups` 既是按群组配置映射,也是聊天级群组允许列表。在根级或账号作用域中,`groups["*"]` 表示该作用域下“允许所有群组进入”。 -- 只有当你本来就希望该作用域允许所有群组进入时,才添加通配群组 `systemPrompt`。如果你仍然只希望固定的一组群组 id 有资格进入,就不要把 `groups["*"]` 用作提示词默认值。相反,应在每个显式加入允许列表的群组条目上重复该提示词。 -- 群组准入和发件人授权是两个独立检查。`groups["*"]` 会扩大可进入群组处理流程的群组集合,但它本身不会为这些群组中的每个发件人授权。发件人访问仍然分别由 `channels.whatsapp.groupPolicy` 和 `channels.whatsapp.groupAllowFrom` 控制。 -- `channels.whatsapp.direct` 对私信没有同样的副作用。`direct["*"]` 只会在某个私信已经通过 `dmPolicy` 加上 `allowFrom` 或配对存储规则获准后,提供默认的直接聊天配置。 +- `channels.whatsapp.groups` 既是按群组配置的映射,也是聊天级群组允许列表。在根级或账户级作用域中,`groups["*"]` 表示“该作用域中允许所有群组”。 +- 只有当你本来就希望该作用域允许所有群组时,才添加通配群组 `systemPrompt`。如果你仍然只希望一组固定的群组 ID 符合条件,不要把 `groups["*"]` 用作提示词默认值。相反,请在每个显式加入允许列表的群组条目上重复设置该提示词。 +- 群组准入和发送者授权是两个独立检查。`groups["*"]` 会扩大可进入群组处理流程的群组范围,但它本身不会授权这些群组中的所有发送者。发送者访问仍由 `channels.whatsapp.groupPolicy` 和 `channels.whatsapp.groupAllowFrom` 单独控制。 +- `channels.whatsapp.direct` 对私信没有相同的副作用。`direct["*"]` 只会在私信已经通过 `dmPolicy` 加上 `allowFrom` 或 pairing-store 规则准入后,提供默认的私聊配置。 示例: @@ -508,31 +530,31 @@ WhatsApp 通过 `groups` 和 `direct` 映射支持类似 Telegram 风格的群 channels: { whatsapp: { groups: { - // 仅当根作用域应允许所有群组时才使用。 - // 适用于所有未定义自己 groups 映射的账号。 + // 仅当根级作用域应允许所有群组时使用。 + // 会应用于所有未定义自己 groups 映射的账户。 "*": { systemPrompt: "所有群组的默认提示词。" }, }, direct: { - // 适用于所有未定义自己 direct 映射的账号。 - "*": { systemPrompt: "所有直接聊天的默认提示词。" }, + // 会应用于所有未定义自己 direct 映射的账户。 + "*": { systemPrompt: "所有私聊的默认提示词。" }, }, accounts: { work: { groups: { - // 该账号定义了自己的 groups,因此根级 groups 会被完全 - // 替换。若要保留通配符,也需要在此处显式定义 "*"。 + // 该账户定义了自己的 groups,因此根级 groups 会被完全 + // 替换。若要保留通配符,也需要在这里显式定义 "*"。 "120363406415684625@g.us": { requireMention: false, - systemPrompt: "专注于项目管理。", + systemPrompt: "聚焦于项目管理。", }, - // 仅当该账号中应允许所有群组时才使用。 + // 仅当该账户中应允许所有群组时使用。 "*": { systemPrompt: "工作群组的默认提示词。" }, }, direct: { - // 该账号定义了自己的 direct 映射,因此根级 direct 条目会被 - // 完全替换。若要保留通配符,也需要在此处显式定义 "*"。 - "+15551234567": { systemPrompt: "特定工作直接聊天的提示词。" }, - "*": { systemPrompt: "工作直接聊天的默认提示词。" }, + // 该账户定义了自己的 direct 映射,因此根级 direct 条目会被 + // 完全替换。若要保留通配符,也需要在这里显式定义 "*"。 + "+15551234567": { systemPrompt: "特定工作私聊的提示词。" }, + "*": { systemPrompt: "工作私聊的默认提示词。" }, }, }, }, @@ -541,7 +563,7 @@ WhatsApp 通过 `groups` 和 `direct` 映射支持类似 Telegram 风格的群 } ``` -## 配置参考指针 +## 配置参考指引 主要参考: @@ -551,7 +573,7 @@ WhatsApp 通过 `groups` 和 `direct` 映射支持类似 Telegram 风格的群 - 访问控制:`dmPolicy`、`allowFrom`、`groupPolicy`、`groupAllowFrom`、`groups` - 投递:`textChunkLimit`、`chunkMode`、`mediaMaxMb`、`sendReadReceipts`、`ackReaction`、`reactionLevel` -- 多账号:`accounts..enabled`、`accounts..authDir`、账号级覆盖 +- 多账户:`accounts..enabled`、`accounts..authDir`、账户级覆盖 - 运维:`configWrites`、`debounceMs`、`web.enabled`、`web.heartbeatSeconds`、`web.reconnect.*` - 会话行为:`session.dmScope`、`historyLimit`、`dmHistoryLimit`、`dms..historyLimit` - 提示词:`groups..systemPrompt`、`groups["*"].systemPrompt`、`direct..systemPrompt`、`direct["*"].systemPrompt` diff --git a/docs/zh-CN/cli/doctor.md b/docs/zh-CN/cli/doctor.md index beaadb430..a67f4b2ee 100644 --- a/docs/zh-CN/cli/doctor.md +++ b/docs/zh-CN/cli/doctor.md @@ -1,14 +1,14 @@ --- read_when: - - 你遇到了连接或认证问题,并希望获得引导式修复。 - - 你刚完成更新,想做一次安装完整性检查。 + - 你遇到了连接性/身份验证问题,并希望获得引导式修复 + - 你已完成更新,并希望进行安装完整性检查 summary: '`openclaw doctor` 的 CLI 参考(健康检查 + 引导式修复)' -title: Doctor +title: doctor x-i18n: - generated_at: "2026-04-23T06:17:35Z" + generated_at: "2026-04-23T07:03:58Z" model: gpt-5.4 provider: openai - source_hash: ad44619b427b938b2f6d4f904fcdc2d9862ff33c569008590f25e17d12e03530 + source_hash: c4b858e8726094c950edcde1e3bdff05d03ae2bd216c3519bbee4805955cf851 source_path: cli/doctor.md workflow: 15 --- @@ -34,29 +34,30 @@ openclaw doctor --generate-gateway-token ## 选项 -- `--no-workspace-suggestions`:禁用工作区记忆/搜索建议 -- `--yes`:不提示,直接接受默认值 -- `--repair`:不提示,直接应用推荐修复 +- `--no-workspace-suggestions`:禁用工作区 memory/search 建议 +- `--yes`:接受默认值,不进行提示 +- `--repair`:不经提示应用推荐修复 - `--fix`:`--repair` 的别名 -- `--force`:应用更激进的修复,包括在需要时覆盖自定义服务配置 +- `--force`:应用激进修复,包括在需要时覆盖自定义服务配置 - `--non-interactive`:以非交互方式运行;仅执行安全迁移 - `--generate-gateway-token`:生成并配置 Gateway 网关令牌 -- `--deep`:扫描系统服务以查找额外的 Gateway 网关安装 +- `--deep`:扫描系统服务中额外的 Gateway 网关安装 说明: -- 交互式提示(如钥匙串 / OAuth 修复)仅在 stdin 为 TTY 且**未**设置 `--non-interactive` 时运行。无头运行(cron、Telegram、无终端)会跳过提示。 -- `--fix`(`--repair` 的别名)会将备份写入 `~/.openclaw/openclaw.json.bak`,并删除未知配置键,同时列出每一项被删除的内容。 -- 状态完整性检查现在会检测会话目录中的孤立转录文件,并可将其归档为 `.deleted.`,以安全回收空间。 -- Doctor 还会扫描 `~/.openclaw/cron/jobs.json`(或 `cron.store`)中的旧版 cron 任务结构,并可在调度器需要在运行时自动规范化之前,直接原地重写它们。 -- Doctor 会修复缺失的内置插件运行时依赖,而不要求对已安装的 OpenClaw 软件包具有写权限。对于 root 拥有的 npm 安装或加固的 systemd 单元,请将 `OPENCLAW_PLUGIN_STAGE_DIR` 设置为可写目录,例如 `/var/lib/openclaw/plugin-runtime-deps`。 -- Doctor 会自动将旧版扁平 Talk 配置(`talk.voiceId`、`talk.modelId` 等)迁移为 `talk.provider` + `talk.providers.`。 -- 重复运行 `doctor --fix` 时,如果唯一差异只是对象键顺序,将不再报告或应用 Talk 规范化。 -- Doctor 包含记忆搜索就绪性检查,并可在缺少嵌入凭证时建议运行 `openclaw configure --section model`。 -- 如果启用了沙箱模式但 Docker 不可用,doctor 会报告高信号警告,并提供修复方法(`install Docker` 或 `openclaw config set agents.defaults.sandbox.mode off`)。 -- 如果 `gateway.auth.token` / `gateway.auth.password` 由 SecretRef 管理,且在当前命令路径中不可用,doctor 会报告只读警告,并且不会写入明文回退凭证。 +- 交互式提示(如钥匙串/OAuth 修复)仅会在 stdin 是 TTY 且**未**设置 `--non-interactive` 时运行。无头运行(cron、Telegram、无终端)会跳过提示。 +- 性能:非交互式 `doctor` 运行会跳过插件的预加载,以保持无头健康检查的快速执行。交互式会话在检查需要插件参与时仍会完整加载插件。 +- `--fix`(`--repair` 的别名)会将备份写入 `~/.openclaw/openclaw.json.bak`,并删除未知配置键,同时列出每一项被删除内容。 +- 状态完整性检查现在会检测会话目录中孤立的 transcript 文件,并可将其归档为 `.deleted.`,以安全回收空间。 +- Doctor 还会扫描 `~/.openclaw/cron/jobs.json`(或 `cron.store`)中的旧版 cron 任务结构,并可在调度器需要在运行时自动规范化之前原地重写它们。 +- Doctor 会修复缺失的内置插件运行时依赖,而无需对已安装的 OpenClaw 软件包具有写入权限。对于 root 拥有的 npm 安装或加固的 systemd 单元,请将 `OPENCLAW_PLUGIN_STAGE_DIR` 设置为可写目录,例如 `/var/lib/openclaw/plugin-runtime-deps`。 +- Doctor 会自动将旧版扁平 Talk 配置(`talk.voiceId`、`talk.modelId` 及相关项)迁移到 `talk.provider` + `talk.providers.`。 +- 重复运行 `doctor --fix` 时,如果唯一差异只是对象键顺序,将不再报告/应用 Talk 规范化。 +- Doctor 包含 memory-search 就绪性检查,并且在缺少嵌入凭证时会建议运行 `openclaw configure --section model`。 +- 如果已启用沙箱模式但 Docker 不可用,doctor 会报告高信号警告并给出修复建议(`install Docker` 或 `openclaw config set agents.defaults.sandbox.mode off`)。 +- 如果 `gateway.auth.token`/`gateway.auth.password` 由 SecretRef 管理,而当前命令路径中不可用,doctor 会报告只读警告,不会写入明文回退凭证。 - 如果渠道 SecretRef 检查在修复路径中失败,doctor 会继续执行并报告警告,而不是提前退出。 -- Telegram `allowFrom` 用户名自动解析(`doctor --fix`)要求在当前命令路径中有可解析的 Telegram 令牌。如果令牌检查不可用,doctor 会报告警告,并在该次运行中跳过自动解析。 +- Telegram `allowFrom` 用户名自动解析(`doctor --fix`)要求当前命令路径中存在可解析的 Telegram 令牌。如果无法检查令牌,doctor 会报告警告,并在该次运行中跳过自动解析。 ## macOS:`launchctl` 环境变量覆盖 diff --git a/docs/zh-CN/cli/gateway.md b/docs/zh-CN/cli/gateway.md index 15c64df6d..2e6837fea 100644 --- a/docs/zh-CN/cli/gateway.md +++ b/docs/zh-CN/cli/gateway.md @@ -1,22 +1,22 @@ --- read_when: - - 从 CLI 运行 Gateway 网关(开发或服务器环境) - - 调试 Gateway 网关认证、绑定模式和连接性 + - 从 CLI 运行 Gateway 网关(开发环境或服务器) + - 调试 Gateway 网关身份验证、绑定模式和连接性 - 通过 Bonjour 发现 Gateway 网关(本地 + 广域 DNS-SD) -summary: OpenClaw Gateway 网关 CLI(`openclaw gateway`)—— 运行、查询和发现 Gateway 网关 -title: Gateway 网关 +summary: OpenClaw Gateway 网关 CLI(`openclaw gateway`)——运行、查询和发现 Gateway 网关 +title: gateway x-i18n: - generated_at: "2026-04-23T06:17:34Z" + generated_at: "2026-04-23T07:04:18Z" model: gpt-5.4 provider: openai - source_hash: 60706df4d3c49271c4b53029eaae16672dde534c7f6f4ce68e04b58fb0cfa467 + source_hash: 30d261a33e54bed10c17c14d09d0dd2b8e227bbf9f0ed415e332e7bda4803f1e source_path: cli/gateway.md workflow: 15 --- -# Gateway 网关 CLI +# Gateway CLI -Gateway 网关是 OpenClaw 的 WebSocket 服务器(渠道、节点、会话、钩子)。 +Gateway 网关是 OpenClaw 的 WebSocket 服务器(渠道、节点、会话、hooks)。 本页中的子命令都位于 `openclaw gateway …` 之下。 @@ -42,38 +42,38 @@ openclaw gateway run 说明: -- 默认情况下,除非在 `~/.openclaw/openclaw.json` 中设置了 `gateway.mode=local`,否则 Gateway 网关会拒绝启动。对于临时 / 开发运行,可使用 `--allow-unconfigured`。 -- `openclaw onboard --mode local` 和 `openclaw setup` 预期会写入 `gateway.mode=local`。如果文件存在但缺少 `gateway.mode`,应将其视为已损坏或被覆盖的配置,并进行修复,而不是隐式假定为本地模式。 -- 如果文件存在且缺少 `gateway.mode`,Gateway 网关会将其视为可疑的配置损坏,并拒绝为你“猜测为 local”。 -- 未启用认证时,禁止绑定到 loopback 之外的地址(安全护栏)。 -- `SIGUSR1` 会在获得授权时触发进程内重启(默认启用 `commands.restart`;将 `commands.restart: false` 设为禁用手动重启,但 gateway 工具 / 配置 apply / update 仍然允许)。 -- `SIGINT` / `SIGTERM` 处理程序会停止 gateway 进程,但不会恢复任何自定义终端状态。如果你用 TUI 或 raw mode 输入包装了 CLI,请在退出前恢复终端。 +- 默认情况下,除非在 `~/.openclaw/openclaw.json` 中设置了 `gateway.mode=local`,否则 Gateway 网关会拒绝启动。对于临时/开发运行,请使用 `--allow-unconfigured`。 +- `openclaw onboard --mode local` 和 `openclaw setup` 预期会写入 `gateway.mode=local`。如果文件存在但缺少 `gateway.mode`,应将其视为损坏或被覆盖的配置,并进行修复,而不是隐式假定为 local 模式。 +- 如果文件存在且缺少 `gateway.mode`,Gateway 网关会将其视为可疑的配置损坏,并拒绝替你“猜测为 local”。 +- 未启用身份验证时,禁止绑定到 loopback 之外的地址(安全护栏)。 +- `SIGUSR1` 会在获得授权时触发进程内重启(默认启用 `commands.restart`;设置 `commands.restart: false` 可阻止手动重启,但 gateway 工具/配置 apply/update 仍然允许)。 +- `SIGINT`/`SIGTERM` 处理器会停止 gateway 进程,但不会恢复任何自定义终端状态。如果你使用 TUI 或 raw-mode 输入包装 CLI,请在退出前恢复终端。 ### 选项 -- `--port `:WebSocket 端口(默认值来自配置 / 环境变量;通常为 `18789`)。 +- `--port `:WebSocket 端口(默认来自配置/环境变量;通常为 `18789`)。 - `--bind `:监听器绑定模式。 -- `--auth `:认证模式覆盖。 -- `--token `:token 覆盖(也会为该进程设置 `OPENCLAW_GATEWAY_TOKEN`)。 -- `--password `:密码覆盖。警告:内联密码可能会暴露在本地进程列表中。 +- `--auth `:身份验证模式覆盖。 +- `--token `:token 覆盖(同时会为该进程设置 `OPENCLAW_GATEWAY_TOKEN`)。 +- `--password `:password 覆盖。警告:内联密码可能会暴露在本地进程列表中。 - `--password-file `:从文件读取 gateway 密码。 - `--tailscale `:通过 Tailscale 暴露 Gateway 网关。 -- `--tailscale-reset-on-exit`:关闭时重置 Tailscale serve / funnel 配置。 -- `--allow-unconfigured`:允许在配置中没有 `gateway.mode=local` 时启动 gateway。此选项仅绕过临时 / 开发引导的启动保护;它不会写入或修复配置文件。 -- `--dev`:如果缺失,则创建开发配置 + 工作区(跳过 `BOOTSTRAP.md`)。 +- `--tailscale-reset-on-exit`:关闭时重置 Tailscale serve/funnel 配置。 +- `--allow-unconfigured`:即使配置中没有 `gateway.mode=local`,也允许启动 gateway。此选项仅绕过临时/开发引导的启动保护;不会写入或修复配置文件。 +- `--dev`:如果缺失,则创建开发配置和工作区(跳过 `BOOTSTRAP.md`)。 - `--reset`:重置开发配置 + 凭证 + 会话 + 工作区(需要 `--dev`)。 -- `--force`:启动前终止所选端口上任何现有的监听器。 +- `--force`:启动前杀掉所选端口上任何现有的监听器。 - `--verbose`:详细日志。 -- `--cli-backend-logs`:仅在控制台显示 CLI 后端日志(并启用 stdout / stderr)。 +- `--cli-backend-logs`:仅在控制台显示 CLI 后端日志(并启用 stdout/stderr)。 - `--ws-log `:websocket 日志样式(默认 `auto`)。 - `--compact`:`--ws-log compact` 的别名。 - `--raw-stream`:将原始模型流事件记录到 jsonl。 - `--raw-stream-path `:原始流 jsonl 路径。 -启动性能分析: +启动分析: -- 设置 `OPENCLAW_GATEWAY_STARTUP_TRACE=1`,可在 Gateway 网关启动期间记录各阶段耗时。 -- 运行 `pnpm test:startup:gateway -- --runs 5 --warmup 1` 以对 Gateway 网关启动进行基准测试。该基准会记录首个进程输出、`/healthz`、`/readyz` 以及启动追踪耗时。 +- 设置 `OPENCLAW_GATEWAY_STARTUP_TRACE=1` 可在 Gateway 网关启动期间记录各阶段耗时。 +- 运行 `pnpm test:startup:gateway -- --runs 5 --warmup 1` 可对 Gateway 网关启动进行基准测试。该基准测试会记录首次进程输出、`/healthz`、`/readyz` 以及启动追踪耗时。 ## 查询正在运行的 Gateway 网关 @@ -81,17 +81,17 @@ openclaw gateway run 输出模式: -- 默认:便于阅读的格式(在 TTY 中带颜色)。 -- `--json`:机器可读 JSON(无样式 / 无 spinner)。 -- `--no-color`(或 `NO_COLOR=1`):禁用 ANSI,同时保留便于阅读的布局。 +- 默认:人类可读(在 TTY 中带颜色)。 +- `--json`:机器可读 JSON(无样式/无 spinner)。 +- `--no-color`(或 `NO_COLOR=1`):禁用 ANSI,同时保留人类可读布局。 共享选项(在支持的地方): - `--url `:Gateway 网关 WebSocket URL。 - `--token `:Gateway 网关 token。 -- `--password `:Gateway 网关密码。 -- `--timeout `:超时 / 预算(因命令而异)。 -- `--expect-final`:等待 “final” 响应(智能体调用)。 +- `--password `:Gateway 网关 password。 +- `--timeout `:超时/预算(因命令而异)。 +- `--expect-final`:等待“final”响应(智能体调用)。 注意:设置 `--url` 时,CLI 不会回退到配置或环境变量凭证。 请显式传入 `--token` 或 `--password`。缺少显式凭证会报错。 @@ -102,11 +102,11 @@ openclaw gateway run openclaw gateway health --url ws://127.0.0.1:18789 ``` -HTTP `/healthz` 端点是存活性探针:一旦服务器可以响应 HTTP,它就会返回。HTTP `/readyz` 端点更严格;当启动 sidecar、渠道或已配置钩子仍在稳定过程中时,它会保持未就绪状态。 +HTTP `/healthz` 端点是存活探针:一旦服务器能够响应 HTTP,它就会返回。HTTP `/readyz` 端点更严格,在启动 sidecar、渠道或已配置 hooks 仍在稳定期间会保持红色状态。 ### `gateway usage-cost` -从会话日志中获取 usage-cost 摘要。 +从会话日志中获取 usage-cost 汇总。 ```bash openclaw gateway usage-cost @@ -120,7 +120,7 @@ openclaw gateway usage-cost --json ### `gateway stability` -从正在运行的 Gateway 网关中获取最近的诊断稳定性记录器信息。 +从正在运行的 Gateway 网关中获取最近的诊断稳定性记录器数据。 ```bash openclaw gateway stability @@ -132,22 +132,22 @@ openclaw gateway stability --json 选项: -- `--limit `:要包含的最近事件最大数量(默认 `25`,最大 `1000`)。 -- `--type `:按诊断事件类型筛选,例如 `payload.large` 或 `diagnostic.memory.pressure`。 -- `--since-seq `:只包含指定诊断序列号之后的事件。 -- `--bundle [path]`:读取持久化的稳定性 bundle,而不是调用正在运行的 Gateway 网关。使用 `--bundle latest`(或仅 `--bundle`)可读取状态目录下最新的 bundle,也可直接传入 bundle JSON 路径。 +- `--limit `:要包含的最近事件的最大数量(默认 `25`,最大 `1000`)。 +- `--type `:按诊断事件类型过滤,例如 `payload.large` 或 `diagnostic.memory.pressure`。 +- `--since-seq `:仅包含指定诊断序列号之后的事件。 +- `--bundle [path]`:读取持久化的 stability bundle,而不是调用正在运行的 Gateway 网关。使用 `--bundle latest`(或仅 `--bundle`)读取状态目录下最新的 bundle,或直接传入 bundle JSON 路径。 - `--export`:写出一个可共享的支持诊断 zip,而不是打印稳定性详情。 - `--output `:`--export` 的输出路径。 说明: -- 记录器默认启用。仅当你需要禁用 Gateway 网关诊断心跳采集时,才设置 `diagnostics.enabled: false`。 -- 记录会保留运维元数据:事件名称、计数、字节大小、内存读数、队列 / 会话状态、渠道 / plugin 名称以及已脱敏的会话摘要。它们不会保留聊天文本、webhook 正文、工具输出、原始请求或响应正文、token、cookie、secret 值、主机名或原始会话 id。 -- 在 Gateway 网关发生致命退出、关闭超时和重启启动失败时,只要记录器中有事件,OpenClaw 就会将相同的诊断快照写入 `~/.openclaw/logs/stability/openclaw-stability-*.json`。可使用 `openclaw gateway stability --bundle latest` 检查最新 bundle;`--limit`、`--type` 和 `--since-seq` 也同样适用于 bundle 输出。 +- 记录器默认启用,且不包含 payload:它只捕获运行元数据,不包含聊天文本、工具输出或原始请求/响应正文。仅当你需要完全禁用 Gateway 网关诊断心跳采集时,才设置 `diagnostics.enabled: false`。 +- 记录会保留运行元数据:事件名称、计数、字节大小、内存读数、队列/会话状态、渠道/插件名称,以及已脱敏的会话摘要。它们不会保留聊天文本、webhook 正文、工具输出、原始请求或响应正文、token、cookie、secret 值、主机名或原始会话 id。 +- 在 Gateway 网关致命退出、关闭超时和重启启动失败时,只要记录器中存在事件,OpenClaw 就会将相同的诊断快照写入 `~/.openclaw/logs/stability/openclaw-stability-*.json`。可使用 `openclaw gateway stability --bundle latest` 检查最新 bundle;`--limit`、`--type` 和 `--since-seq` 也适用于 bundle 输出。 ### `gateway diagnostics export` -写出一个本地诊断 zip,专门用于附加到 bug 报告中。 +写出一个本地诊断 zip,专门设计用于附加到 bug 报告中。 ```bash openclaw gateway diagnostics export @@ -157,23 +157,23 @@ openclaw gateway diagnostics export --json 选项: -- `--output `:输出 zip 路径。默认为状态目录下的支持导出文件。 +- `--output `:输出 zip 路径。默认写入状态目录下的支持导出文件。 - `--log-lines `:要包含的已脱敏日志行最大数量(默认 `5000`)。 -- `--log-bytes `:要检查的最大日志字节数(默认 `1000000`)。 +- `--log-bytes `:要检查的日志最大字节数(默认 `1000000`)。 - `--url `:用于健康快照的 Gateway 网关 WebSocket URL。 - `--token `:用于健康快照的 Gateway 网关 token。 -- `--password `:用于健康快照的 Gateway 网关密码。 -- `--timeout `:状态 / 健康快照超时(默认 `3000`)。 -- `--no-stability-bundle`:跳过持久化稳定性 bundle 查找。 -- `--json`:以 JSON 输出写入路径、大小和清单。 +- `--password `:用于健康快照的 Gateway 网关 password。 +- `--timeout `:状态/健康快照超时(默认 `3000`)。 +- `--no-stability-bundle`:跳过持久化 stability bundle 查找。 +- `--json`:以 JSON 格式打印写入路径、大小和清单。 -该导出内容包括清单、Markdown 摘要、配置形状、已脱敏配置详情、已脱敏日志摘要、已脱敏 Gateway 网关状态 / 健康快照,以及存在时的最新稳定性 bundle。 +该导出包含清单、Markdown 摘要、配置结构、已脱敏配置详情、已脱敏日志摘要、已脱敏 Gateway 网关状态/健康快照,以及存在时的最新 stability bundle。 -它 предназначен 用于共享。它会保留有助于调试的运维细节,例如安全的 OpenClaw 日志字段、子系统名称、状态码、持续时间、已配置模式、端口、plugin id、provider id、非敏感功能设置以及已脱敏的运维日志消息。它会省略或脱敏聊天文本、webhook 正文、工具输出、凭证、cookie、账户 / 消息标识符、提示 / 指令文本、主机名和 secret 值。当某条 LogTape 风格消息看起来像用户 / 聊天 / 工具负载文本时,导出内容只会保留“该消息已省略”以及其字节数。 +它旨在用于共享。它会保留有助于调试的运行细节,例如安全的 OpenClaw 日志字段、子系统名称、状态码、时长、已配置模式、端口、插件 id、提供商 id、非 secret 功能设置以及已脱敏的运行日志消息。它会省略或脱敏聊天文本、webhook 正文、工具输出、凭证、cookie、账户/消息标识符、prompt/instruction 文本、主机名和 secret 值。当某条 LogTape 风格消息看起来像是用户/聊天/工具 payload 文本时,导出仅保留该消息已被省略及其字节数。 ### `gateway status` -`gateway status` 显示 Gateway 网关服务(launchd/systemd/schtasks)以及可选的连接性 / 认证能力探测。 +`gateway status` 会显示 Gateway 网关服务(launchd/systemd/schtasks),并可选探测连接性/身份验证能力。 ```bash openclaw gateway status @@ -183,43 +183,42 @@ openclaw gateway status --require-rpc 选项: -- `--url `:添加显式探测目标。仍会探测已配置的远程目标和 localhost。 -- `--token `:用于探测的 token 认证。 -- `--password `:用于探测的密码认证。 +- `--url `:添加一个显式探测目标。仍会探测已配置的远端 + localhost。 +- `--token `:用于探测的 token 身份验证。 +- `--password `:用于探测的 password 身份验证。 - `--timeout `:探测超时(默认 `10000`)。 - `--no-probe`:跳过连接性探测(仅服务视图)。 -- `--deep`:同时扫描系统级服务。 -- `--require-rpc`:将默认连接性探测升级为读取探测,并在该读取探测失败时以非零状态退出。不能与 `--no-probe` 一起使用。 +- `--deep`:也扫描系统级服务。 +- `--require-rpc`:将默认连接性探测升级为读取探测,并在该读取探测失败时以非零状态退出。不能与 `--no-probe` 组合使用。 说明: - 即使本地 CLI 配置缺失或无效,`gateway status` 仍可用于诊断。 -- 默认的 `gateway status` 可以证明服务状态、WebSocket 连接以及握手时可见的认证能力。它不能证明读 / 写 / 管理操作。 -- 在可能的情况下,`gateway status` 会解析为探测认证而配置的 auth SecretRefs。 -- 如果在该命令路径中某个必需的 auth SecretRef 无法解析,并且探测连接 / 认证失败,`gateway status --json` 会报告 `rpc.authWarning`;请显式传入 `--token` / `--password`,或先解析 secret 来源。 -- 如果探测成功,则会抑制未解析的 auth-ref 警告,以避免误报。 -- 当脚本和自动化场景中仅有监听服务还不够、并且你还需要读范围 RPC 调用也保持健康时,请使用 `--require-rpc`。 -- `--deep` 会尽力扫描额外的 launchd/systemd/schtasks 安装。当检测到多个类似 gateway 的服务时,人类可读输出会打印清理提示,并警告大多数环境应每台机器只运行一个 gateway。 -- 人类可读输出包含已解析的文件日志路径,以及 CLI 与服务之间配置路径 / 有效性的快照,以帮助诊断 profile 或状态目录漂移。 -- 在 Linux systemd 安装中,服务认证漂移检查会同时读取 unit 中 `Environment=` 和 `EnvironmentFile=` 的值(包括 `%h`、带引号的路径、多个文件以及可选的 `-` 文件)。 -- 漂移检查会使用合并后的运行时环境变量解析 `gateway.auth.token` SecretRefs(优先使用服务命令环境变量,其次回退到进程环境变量)。 -- 如果 token 认证实际上未激活(显式 `gateway.auth.mode` 为 `password` / `none` / `trusted-proxy`,或 mode 未设置且 password 可能胜出并且不存在可胜出的 token 候选),则 token 漂移检查会跳过配置 token 解析。 +- 默认的 `gateway status` 可证明服务状态、WebSocket 连接以及握手时可见的身份验证能力。它不能证明读取/写入/管理员操作。 +- `gateway status` 会在可能时解析已配置身份验证 SecretRef,用于探测身份验证。 +- 如果必需的身份验证 SecretRef 在当前命令路径中无法解析,且探测连接性/身份验证失败,`gateway status --json` 会报告 `rpc.authWarning`;请显式传入 `--token`/`--password`,或先解决 secret 来源。 +- 如果探测成功,为避免误报,将抑制未解析 auth-ref 警告。 +- 当仅有监听服务还不够,且你还需要读取范围 RPC 调用保持健康时,请在脚本和自动化中使用 `--require-rpc`。 +- `--deep` 会尽力扫描额外的 launchd/systemd/schtasks 安装。当检测到多个类似 gateway 的服务时,人类可读输出会打印清理提示,并警告大多数设置通常应每台机器只运行一个 gateway。 +- 人类可读输出会包含解析后的文件日志路径,以及 CLI 与服务的配置路径/有效性快照,以帮助诊断 profile 或状态目录漂移。 +- 在 Linux systemd 安装中,服务身份验证漂移检查会同时读取单元中的 `Environment=` 和 `EnvironmentFile=` 值(包括 `%h`、带引号路径、多个文件以及可选的 `-` 文件)。 +- 漂移检查会使用合并后的运行环境变量解析 `gateway.auth.token` SecretRef(优先服务命令环境变量,其次回退到进程环境变量)。 +- 如果 token 身份验证实际上未激活(显式 `gateway.auth.mode` 为 `password`/`none`/`trusted-proxy`,或 mode 未设置且 password 可能胜出、并且没有任何 token 候选能胜出),则 token 漂移检查会跳过配置 token 解析。 ### `gateway probe` -`gateway probe` 是“调试一切”的命令。它始终会探测: +`gateway probe` 是“全量调试”命令。它始终会探测: -- 你已配置的远程 gateway(如果已设置),以及 -- localhost(local loopback),**即使已经配置了远程目标**。 +- 你已配置的远端 gateway(如果已设置),以及 +- localhost(loopback),**即使已配置远端也是如此**。 -如果你传入 `--url`,这个显式目标会被添加到前面。人类可读输出会将 -目标标记为: +如果你传入 `--url`,该显式目标会被添加到前面,位于两者之前。人类可读输出会将目标标记为: -- `URL (explicit)` -- `Remote (configured)` 或 `Remote (configured, inactive)` +- `URL(显式)` +- `Remote(已配置)` 或 `Remote(已配置,未激活)` - `Local loopback` -如果有多个 gateway 可达,它会全部打印出来。当你使用隔离的 profile / 端口(例如救援机器人)时,支持多个 gateway,但大多数安装仍只运行单个 gateway。 +如果有多个 Gateway 网关可达,它会全部打印出来。当你使用隔离的 profile/端口(例如 rescue bot)时,支持多个 gateway,但大多数安装通常仍只运行一个 gateway。 ```bash openclaw gateway probe @@ -229,42 +228,42 @@ openclaw gateway probe --json 解释: - `Reachable: yes` 表示至少有一个目标接受了 WebSocket 连接。 -- `Capability: read-only|write-capable|admin-capable|pairing-pending|connect-only` 表示探测能够证明的认证能力。它与可达性是分开的。 -- `Read probe: ok` 表示读范围的详细 RPC 调用(`health` / `status` / `system-presence` / `config.get`)也成功了。 -- `Read probe: limited - missing scope: operator.read` 表示连接成功,但读范围 RPC 受限。这会被报告为**降级**可达性,而不是完全失败。 -- 仅当所有被探测目标都不可达时,退出码才为非零。 +- `Capability: read-only|write-capable|admin-capable|pairing-pending|connect-only` 表示探测能够证明的身份验证能力。它与可达性是分开的。 +- `Read probe: ok` 表示读取范围的详情 RPC 调用(`health`/`status`/`system-presence`/`config.get`)也成功了。 +- `Read probe: limited - missing scope: operator.read` 表示连接成功了,但读取范围 RPC 受限。这会被报告为**降级**可达性,而不是完全失败。 +- 仅当没有任何被探测目标可达时,退出码才为非零。 JSON 说明(`--json`): - 顶层: - `ok`:至少有一个目标可达。 - - `degraded`:至少有一个目标的详细 RPC 受作用域限制。 + - `degraded`:至少有一个目标的详情 RPC 受作用域限制。 - `capability`:在所有可达目标中看到的最佳能力(`read_only`、`write_capable`、`admin_capable`、`pairing_pending`、`connected_no_operator_scope` 或 `unknown`)。 - - `primaryTargetId`:按以下顺序视为活动优先目标的最佳目标:显式 URL、SSH 隧道、已配置的远程目标,然后是 local loopback。 - - `warnings[]`:尽力提供的警告记录,包含 `code`、`message` 和可选的 `targetIds`。 - - `network`:根据当前配置和主机网络推导出的 local loopback / tailnet URL 提示。 - - `discovery.timeoutMs` 和 `discovery.count`:本次探测实际使用的发现预算 / 结果数量。 + - `primaryTargetId`:按以下顺序选出的最佳目标,作为活动优先目标处理:显式 URL、SSH 隧道、已配置远端、然后是 local loopback。 + - `warnings[]`:尽力而为的警告记录,包含 `code`、`message` 和可选的 `targetIds`。 + - `network`:根据当前配置和主机网络推导出的 local loopback/tailnet URL 提示。 + - `discovery.timeoutMs` 和 `discovery.count`:本次探测实际使用的设备发现预算/结果数量。 - 每个目标(`targets[].connect`): - - `ok`:连接后并经过降级分类后的可达性。 - - `rpcOk`:完整详细 RPC 成功。 - - `scopeLimited`:由于缺少 operator 作用域,详细 RPC 失败。 + - `ok`:连接完成后的可达性 + 降级分类。 + - `rpcOk`:完整详情 RPC 成功。 + - `scopeLimited`:由于缺少 operator 作用域,详情 RPC 失败。 - 每个目标(`targets[].auth`): - - `role`:可用时,在 `hello-ok` 中报告的认证角色。 - - `scopes`:可用时,在 `hello-ok` 中报告的已授予作用域。 - - `capability`:该目标对外呈现的认证能力分类。 + - `role`:在可用时,由 `hello-ok` 报告的身份验证角色。 + - `scopes`:在可用时,由 `hello-ok` 报告的已授予作用域。 + - `capability`:该目标呈现出的身份验证能力分类。 常见警告代码: - `ssh_tunnel_failed`:SSH 隧道建立失败;命令已回退为直接探测。 -- `multiple_gateways`:有多个目标可达;除非你有意运行隔离的 profile(例如救援机器人),否则这并不常见。 -- `auth_secretref_unresolved`:某个已配置的 auth SecretRef 无法为失败目标解析。 +- `multiple_gateways`:有多个目标可达;除非你有意运行隔离的 profiles(例如 rescue bot),否则这并不常见。 +- `auth_secretref_unresolved`:某个已配置的身份验证 SecretRef 无法为失败目标解析。 - `probe_scope_limited`:WebSocket 连接成功,但读取探测因缺少 `operator.read` 而受限。 -#### 通过 SSH 连接远程目标(与 Mac 应用一致) +#### 通过 SSH 连接远端(与 Mac 应用一致) -macOS 应用的“Remote over SSH”模式使用本地端口转发,使远程 gateway(其绑定可能仅限 loopback)能够通过 `ws://127.0.0.1:` 访问。 +macOS 应用中的“通过 SSH 连接远端”模式使用本地端口转发,因此远端 gateway(可能仅绑定到 loopback)会以 `ws://127.0.0.1:` 的形式变得可达。 -CLI 等效命令: +等效 CLI: ```bash openclaw gateway probe --ssh user@gateway-host @@ -274,8 +273,8 @@ openclaw gateway probe --ssh user@gateway-host - `--ssh `:`user@host` 或 `user@host:port`(端口默认为 `22`)。 - `--ssh-identity `:身份文件。 -- `--ssh-auto`:从已解析的发现端点中,将第一个发现到的 gateway 主机选作 SSH 目标 - (`local.` 加上已配置的广域域名(如果有))。仅包含 TXT 的 +- `--ssh-auto`:从已解析的 + 设备发现端点(`local.` 加上已配置的广域域名(如果有))中,选择第一个发现的 gateway 主机作为 SSH 目标。仅 TXT 的 提示会被忽略。 配置(可选,用作默认值): @@ -304,8 +303,8 @@ openclaw gateway call logs.tail --params '{"sinceMs": 60000}' 说明: -- `--params` 必须是有效的 JSON。 -- `--expect-final` 主要用于智能体风格的 RPC,这类调用会先流式发送中间事件,再发送最终负载。 +- `--params` 必须是有效 JSON。 +- `--expect-final` 主要用于智能体风格的 RPC,这类 RPC 会在最终 payload 之前流式发送中间事件。 ## 管理 Gateway 网关服务 @@ -326,31 +325,31 @@ openclaw gateway uninstall 说明: - `gateway install` 支持 `--port`、`--runtime`、`--token`、`--force`、`--json`。 -- 当 token 认证需要 token 且 `gateway.auth.token` 由 SecretRef 管理时,`gateway install` 会验证 SecretRef 可解析,但不会将解析出的 token 持久化到服务环境元数据中。 -- 如果 token 认证需要 token,而配置的 token SecretRef 无法解析,安装会以安全关闭方式失败,而不是持久化后备明文。 -- 对于 `gateway run` 的密码认证,优先使用 `OPENCLAW_GATEWAY_PASSWORD`、`--password-file` 或由 SecretRef 支持的 `gateway.auth.password`,而不是内联 `--password`。 -- 在推断认证模式下,仅在 shell 中设置的 `OPENCLAW_GATEWAY_PASSWORD` 不会放宽安装时的 token 要求;安装托管服务时,请使用持久化配置(`gateway.auth.password` 或配置中的 `env`)。 -- 如果同时配置了 `gateway.auth.token` 和 `gateway.auth.password`,且 `gateway.auth.mode` 未设置,则会阻止安装,直到明确设置 mode。 -- 生命周期命令接受 `--json` 以便脚本使用。 +- 当 token 身份验证需要 token,且 `gateway.auth.token` 由 SecretRef 管理时,`gateway install` 会验证该 SecretRef 可解析,但不会将解析出的 token 持久化到服务环境元数据中。 +- 如果 token 身份验证需要 token,而已配置的 token SecretRef 无法解析,则安装会以关闭方式失败,而不是持久化回退明文。 +- 对于 `gateway run` 的 password 身份验证,优先使用 `OPENCLAW_GATEWAY_PASSWORD`、`--password-file` 或由 SecretRef 支持的 `gateway.auth.password`,而不是内联 `--password`。 +- 在推断身份验证模式下,仅 shell 中的 `OPENCLAW_GATEWAY_PASSWORD` 不会放宽安装时对 token 的要求;安装托管服务时,请使用持久配置(`gateway.auth.password` 或配置 `env`)。 +- 如果同时配置了 `gateway.auth.token` 和 `gateway.auth.password`,但未设置 `gateway.auth.mode`,则安装会被阻止,直到显式设置 mode。 +- 生命周期命令接受 `--json` 以便脚本化使用。 ## 发现 Gateway 网关(Bonjour) `gateway discover` 会扫描 Gateway 网关信标(`_openclaw-gw._tcp`)。 -- 组播 DNS-SD:`local.` -- 单播 DNS-SD(广域 Bonjour):选择一个域名(示例:`openclaw.internal.`),并设置 split DNS + DNS 服务器;参见 [/gateway/bonjour](/zh-CN/gateway/bonjour) +- 多播 DNS-SD:`local.` +- 单播 DNS-SD(广域 Bonjour):选择一个域名(例如:`openclaw.internal.`),并设置 split DNS + DNS 服务器;参见 [/gateway/bonjour](/zh-CN/gateway/bonjour) -只有启用了 Bonjour 发现功能的 gateway(默认启用)才会广播信标。 +只有启用了 Bonjour 设备发现的 gateway(默认启用)才会广播该信标。 -广域发现记录包含(TXT): +广域设备发现记录包含(TXT): - `role`(gateway 角色提示) - `transport`(传输提示,例如 `gateway`) - `gatewayPort`(WebSocket 端口,通常为 `18789`) -- `sshPort`(可选;缺失时客户端会默认 SSH 目标端口为 `22`) +- `sshPort`(可选;缺失时客户端默认 SSH 目标端口为 `22`) - `tailnetDns`(可用时的 MagicDNS 主机名) -- `gatewayTls` / `gatewayTlsSha256`(TLS 是否启用 + 证书指纹) -- `cliPath`(写入广域区域的远程安装提示) +- `gatewayTls` / `gatewayTlsSha256`(是否启用 TLS + 证书指纹) +- `cliPath`(写入广域区域的远端安装提示) ### `gateway discover` @@ -360,8 +359,8 @@ openclaw gateway discover 选项: -- `--timeout `:每条命令的超时时间(browse / resolve);默认 `2000`。 -- `--json`:机器可读输出(也会禁用样式 / spinner)。 +- `--timeout `:每个命令的超时时间(browse/resolve);默认 `2000`。 +- `--json`:机器可读输出(同时禁用样式/spinner)。 示例: @@ -373,8 +372,8 @@ openclaw gateway discover --json | jq '.beacons[].wsUrl' 说明: - CLI 会扫描 `local.` 以及已配置的广域域名(如果已启用)。 -- JSON 输出中的 `wsUrl` 是从已解析的服务端点推导出来的,而不是来自仅 TXT 的 +- JSON 输出中的 `wsUrl` 是根据已解析的服务端点推导出来的,而不是来自仅 TXT 的 提示,例如 `lanHost` 或 `tailnetDns`。 -- 在 `local.` mDNS 上,只有当 +- 在 `local.` mDNS 上,仅当 `discovery.mdns.mode` 为 `full` 时,才会广播 `sshPort` 和 `cliPath`。广域 DNS-SD 仍会写入 `cliPath`;`sshPort` - 在那里也仍然是可选的。 + 在那里同样仍是可选项。 diff --git a/docs/zh-CN/cli/mcp.md b/docs/zh-CN/cli/mcp.md index 59303edbc..9ff06347f 100644 --- a/docs/zh-CN/cli/mcp.md +++ b/docs/zh-CN/cli/mcp.md @@ -1,22 +1,22 @@ --- read_when: - - 将 Codex、Claude Code 或其他 MCP 客户端连接到由 OpenClaw 支持的渠道 + - 将 Codex、Claude Code 或其他 MCP 客户端连接到 OpenClaw 支持的渠道 - 运行 `openclaw mcp serve` - 管理 OpenClaw 保存的 MCP 服务器定义 summary: 通过 MCP 暴露 OpenClaw 渠道会话,并管理已保存的 MCP 服务器定义 title: mcp x-i18n: - generated_at: "2026-04-23T06:17:47Z" + generated_at: "2026-04-23T07:04:36Z" model: gpt-5.4 provider: openai - source_hash: bbc528a7490132f4b505f62bdc4556602243a5e27557c4965c2e1d4f80ad00bd + source_hash: e9783d6270d5ab5526e0f52c72939a6a895d4a92da6193703337ef394655d27c source_path: cli/mcp.md workflow: 15 --- # mcp -`openclaw mcp` 有两个职责: +`openclaw mcp` 有两个用途: - 使用 `openclaw mcp serve` 将 OpenClaw 作为 MCP 服务器运行 - 使用 `list`、`show`、`set` 和 `unset` 管理由 OpenClaw 拥有的出站 MCP 服务器定义 @@ -24,9 +24,9 @@ x-i18n: 换句话说: - `serve` 是 OpenClaw 充当 MCP 服务器 -- `list` / `show` / `set` / `unset` 是 OpenClaw 充当其他 MCP 服务器的客户端侧注册表,供其运行时稍后使用 +- `list` / `show` / `set` / `unset` 是 OpenClaw 充当面向其他 MCP 服务器的客户端注册表,供其运行时稍后使用 -当 OpenClaw 应自行托管一个编码 harness 会话并通过 ACP 路由该运行时时,请使用 [`openclaw acp`](/zh-CN/cli/acp)。 +当 OpenClaw 需要自行托管一个 coding harness 会话,并通过 ACP 路由该运行时时,请使用 [`openclaw acp`](/zh-CN/cli/acp)。 ## OpenClaw 作为 MCP 服务器 @@ -34,58 +34,60 @@ x-i18n: ## 何时使用 `serve` -在以下情况下使用 `openclaw mcp serve`: +在以下情况下,使用 `openclaw mcp serve`: -- Codex、Claude Code 或其他 MCP 客户端应直接与由 OpenClaw 支持的渠道会话通信 -- 你已经有一个带有路由会话的本地或远程 OpenClaw Gateway 网关 -- 你希望使用一个可跨 OpenClaw 渠道后端工作的 MCP 服务器,而不是分别运行各个渠道的独立桥接 +- Codex、Claude Code 或其他 MCP 客户端应直接与 OpenClaw 支持的渠道会话通信 +- 你已经有一个本地或远程的 OpenClaw Gateway 网关,并且其中有已路由的会话 +- 你想要一个可跨 OpenClaw 各渠道后端工作的 MCP 服务器,而不是为每个渠道分别运行桥接 -当 OpenClaw 应自行托管编码运行时并将智能体会话保留在 OpenClaw 内部时,请改用 [`openclaw acp`](/zh-CN/cli/acp)。 +当 OpenClaw 需要自行托管 coding 运行时,并将智能体会话保留在 OpenClaw 内部时,请改用 [`openclaw acp`](/zh-CN/cli/acp)。 ## 工作原理 -`openclaw mcp serve` 会启动一个 stdio MCP 服务器。MCP 客户端拥有该进程。只要客户端保持 stdio 会话打开,桥接就会通过 WebSocket 连接到本地或远程 OpenClaw Gateway 网关,并通过 MCP 暴露已路由的渠道会话。 +`openclaw mcp serve` 会启动一个 stdio MCP 服务器。该进程由 MCP 客户端拥有。只要客户端保持该 stdio 会话开启,桥接器就会通过 WebSocket 连接到本地或远程 OpenClaw Gateway 网关,并通过 MCP 暴露已路由的渠道会话。 生命周期: -1. MCP 客户端生成 `openclaw mcp serve` -2. 桥接连接到 Gateway 网关 -3. 已路由会话会变为 MCP 会话和 transcript/history 工具 -4. 在桥接连接期间,实时事件会在内存中排队 -5. 如果启用了 Claude 渠道模式,同一会话还可以接收 Claude 专用推送通知 +1. MCP 客户端启动 `openclaw mcp serve` +2. 桥接器连接到 Gateway 网关 +3. 已路由的会话变为 MCP 会话以及 transcript/history 工具 +4. 桥接器连接期间,实时事件会在内存中排队 +5. 如果启用了 Claude 渠道模式,同一会话还可以接收 Claude 专用的推送通知 重要行为: -- 实时队列状态从桥接连接时开始 -- 更早的 transcript 历史通过 `messages_read` 读取 -- Claude 推送通知仅在 MCP 会话存活期间存在 -- 当客户端断开连接时,桥接会退出,实时队列也会消失 +- 实时队列状态会在桥接器连接时开始 +- 更早的 transcript 历史会通过 `messages_read` 读取 +- Claude 推送通知仅在 MCP 会话存活时存在 +- 当客户端断开连接时,桥接器退出,实时队列也随之消失 +- 由 OpenClaw 启动的 stdio MCP 服务器(内置或用户配置)会在关闭时按进程树拆除,因此服务器启动的子进程不会在父 stdio 客户端退出后继续存活 +- 删除或重置会话时,会通过共享运行时清理路径释放该会话的 MCP 客户端,因此不会残留绑定到已移除会话的 stdio 连接 ## 选择客户端模式 -以两种不同方式使用同一个桥接: +同一个桥接器可以通过两种不同方式使用: -- 通用 MCP 客户端:仅标准 MCP 工具。使用 `conversations_list`、`messages_read`、`events_poll`、`events_wait`、`messages_send` 和批准工具。 +- 通用 MCP 客户端:仅标准 MCP 工具。使用 `conversations_list`、`messages_read`、`events_poll`、`events_wait`、`messages_send` 以及审批工具。 - Claude Code:标准 MCP 工具加上 Claude 专用渠道适配器。启用 `--claude-channel-mode on`,或保留默认值 `auto`。 目前,`auto` 的行为与 `on` 相同。尚未实现客户端能力检测。 ## `serve` 暴露的内容 -桥接使用现有 Gateway 网关会话路由元数据来暴露由渠道支持的会话。当 OpenClaw 已经拥有带有已知路由的会话状态时,会出现一个会话,例如: +桥接器使用现有的 Gateway 网关会话路由元数据来暴露由渠道支持的会话。当 OpenClaw 已经拥有带有已知路由的会话状态时,会显示一个会话,例如: - `channel` -- recipient 或 destination 元数据 +- 收件人或目标元数据 - 可选的 `accountId` - 可选的 `threadId` -这让 MCP 客户端可以在一个位置完成以下操作: +这让 MCP 客户端可以在一个地方完成以下操作: -- 列出最近的已路由会话 +- 列出最近已路由的会话 - 读取最近的 transcript 历史 - 等待新的入站事件 -- 通过同一路由发回回复 -- 查看桥接连接期间到达的批准请求 +- 通过同一路由发送回复 +- 查看桥接器连接期间到达的审批请求 ## 用法 @@ -108,7 +110,7 @@ openclaw mcp serve --claude-channel-mode off ## 桥接工具 -当前桥接暴露以下 MCP 工具: +当前桥接器暴露以下 MCP 工具: - `conversations_list` - `conversation_get` @@ -122,7 +124,7 @@ openclaw mcp serve --claude-channel-mode off ### `conversations_list` -列出最近的、已具有 Gateway 网关会话状态中路由元数据的会话支持会话。 +列出最近基于会话且在 Gateway 网关会话状态中已经具有路由元数据的会话。 常用过滤器: @@ -134,43 +136,43 @@ openclaw mcp serve --claude-channel-mode off ### `conversation_get` -按 `session_key` 返回一个会话。 +通过 `session_key` 返回一个会话。 ### `messages_read` -读取一个会话支持会话的最近 transcript 消息。 +读取一个基于会话的会话中的最近 transcript 消息。 ### `attachments_fetch` -从一条 transcript 消息中提取非文本消息内容块。这是 transcript 内容上的元数据视图,而不是独立的持久化附件 blob 存储。 +从一条 transcript 消息中提取非文本消息内容块。这是针对 transcript 内容的元数据视图,而不是独立的持久化附件 blob 存储。 ### `events_poll` -读取自某个数字游标以来排队的实时事件。 +从数值游标之后读取已排队的实时事件。 ### `events_wait` -长轮询,直到下一个匹配的排队事件到达或超时过期。 +长轮询,直到下一个匹配的排队事件到达或超时到期。 -当通用 MCP 客户端需要接近实时的传递,而无需使用 Claude 专用推送协议时,可使用此工具。 +当通用 MCP 客户端需要接近实时的投递,而又不使用 Claude 专用推送协议时,请使用此工具。 ### `messages_send` -通过会话上已记录的同一路由发回文本。 +通过会话上已记录的同一路由回发文本。 当前行为: - 需要现有会话路由 -- 使用会话的渠道、接收方、账号 id 和线程 id +- 使用该会话的渠道、收件人、账户 id 和线程 id - 仅发送文本 ### `permissions_list_open` -列出桥接自连接到 Gateway 网关以来观察到的待处理 exec/plugin 批准请求。 +列出桥接器自连接到 Gateway 网关以来观察到的待处理 exec/plugin 审批请求。 ### `permissions_respond` -使用以下值之一处理一个待处理 exec/plugin 批准请求: +通过以下方式之一处理一个待处理的 exec/plugin 审批请求: - `allow-once` - `allow-always` @@ -178,7 +180,7 @@ openclaw mcp serve --claude-channel-mode off ## 事件模型 -桥接在连接期间会在内存中维护一个事件队列。 +桥接器在连接期间会维护一个内存中的事件队列。 当前事件类型: @@ -191,13 +193,13 @@ openclaw mcp serve --claude-channel-mode off 重要限制: -- 队列仅限实时;它从 MCP 桥接启动时开始 +- 队列仅限实时;它会在 MCP 桥接启动时开始 - `events_poll` 和 `events_wait` 本身不会重放更早的 Gateway 网关历史 - 持久化积压应通过 `messages_read` 读取 ## Claude 渠道通知 -桥接也可以暴露 Claude 专用渠道通知。这相当于 OpenClaw 中的 Claude Code 渠道适配器:标准 MCP 工具仍然可用,但实时入站消息也可以作为 Claude 专用 MCP 通知到达。 +桥接器还可以暴露 Claude 专用的渠道通知。这是 OpenClaw 对应的 Claude Code 渠道适配器:标准 MCP 工具仍然可用,但实时入站消息也可以作为 Claude 专用 MCP 通知到达。 标志: @@ -212,16 +214,16 @@ openclaw mcp serve --claude-channel-mode off 当前桥接行为: -- 入站 `user` transcript 消息会被转发为 `notifications/claude/channel` -- 通过 MCP 收到的 Claude 权限请求会在内存中跟踪 -- 如果关联会话随后发送 `yes abcde` 或 `no abcde`,桥接会将其转换为 `notifications/claude/channel/permission` -- 这些通知仅限实时会话;如果 MCP 客户端断开连接,就没有可推送的目标 +- 入站的 `user` transcript 消息会被转发为 `notifications/claude/channel` +- 通过 MCP 接收到的 Claude 权限请求会在内存中跟踪 +- 如果关联的会话之后发送 `yes abcde` 或 `no abcde`,桥接器会将其转换为 `notifications/claude/channel/permission` +- 这些通知仅在实时会话中存在;如果 MCP 客户端断开连接,就没有推送目标了 这是有意设计为客户端专用的。通用 MCP 客户端应依赖标准轮询工具。 ## MCP 客户端配置 -示例 stdio 客户端配置: +stdio 客户端配置示例: ```json { @@ -241,38 +243,38 @@ openclaw mcp serve --claude-channel-mode off } ``` -对于大多数通用 MCP 客户端,请从标准工具面开始,并忽略 Claude 模式。仅对真正理解 Claude 专用通知方法的客户端启用 Claude 模式。 +对于大多数通用 MCP 客户端,先从标准工具面开始,并忽略 Claude 模式。仅在客户端确实理解 Claude 专用通知方法时再开启 Claude 模式。 ## 选项 `openclaw mcp serve` 支持: - `--url `:Gateway 网关 WebSocket URL -- `--token `:Gateway 网关令牌 -- `--token-file `:从文件读取令牌 +- `--token `:Gateway 网关 token +- `--token-file `:从文件读取 token - `--password `:Gateway 网关密码 - `--password-file `:从文件读取密码 - `--claude-channel-mode `:Claude 通知模式 -- `-v`, `--verbose`:在 stderr 上输出详细日志 +- `-v`、`--verbose`:在 stderr 输出详细日志 -可行时,优先使用 `--token-file` 或 `--password-file`,而不是内联机密。 +可能的话,优先使用 `--token-file` 或 `--password-file`,而不是内联 secret。 ## 安全性与信任边界 -桥接不会自行发明路由。它只会暴露 Gateway 网关已经知道如何路由的会话。 +桥接器不会自行创建路由。它只会暴露 Gateway 网关已经知道如何路由的会话。 这意味着: -- 发送方允许列表、配对和渠道级信任仍属于底层 OpenClaw 渠道配置 -- `messages_send` 只能通过现有的已存储路由进行回复 -- 批准状态仅对当前桥接会话实时/内存中有效 -- 桥接认证应使用与你信任任何其他远程 Gateway 网关客户端时相同的 Gateway 网关令牌或密码控制 +- 发送方允许列表、配对和渠道级信任仍属于底层 OpenClaw 渠道配置的范畴 +- `messages_send` 只能通过现有的已存储路由回复 +- 审批状态仅对当前桥接会话实时/以内存方式存在 +- 桥接认证应使用你对任何其他远程 Gateway 网关客户端同样信任的 Gateway 网关 token 或密码控制 -如果 `conversations_list` 中缺少某个会话,通常原因不是 MCP 配置,而是底层 Gateway 网关会话中缺少或不完整的路由元数据。 +如果某个会话没有出现在 `conversations_list` 中,通常原因并不是 MCP 配置,而是底层 Gateway 网关会话中缺少或不完整的路由元数据。 ## 测试 -OpenClaw 为此桥接提供了一个确定性的 Docker smoke 测试: +OpenClaw 为这个桥接提供了一个可确定复现的 Docker smoke 测试: ```bash pnpm test:docker:mcp-channels @@ -280,57 +282,57 @@ pnpm test:docker:mcp-channels 该 smoke 测试会: -- 启动一个已预置数据的 Gateway 网关容器 -- 启动第二个容器,并在其中生成 `openclaw mcp serve` -- 验证会话发现、transcript 读取、附件元数据读取、实时事件队列行为和出站发送路由 +- 启动一个带种子数据的 Gateway 网关容器 +- 启动第二个容器,并在其中启动 `openclaw mcp serve` +- 验证会话发现、transcript 读取、附件元数据读取、实时事件队列行为以及出站发送路由 - 通过真实的 stdio MCP 桥接验证 Claude 风格的渠道和权限通知 -这是在不将真实 Telegram、Discord 或 iMessage 账号接入测试运行的情况下,证明桥接可用的最快方法。 +这是在无需将真实 Telegram、Discord 或 iMessage 账户接入测试运行的情况下,证明该桥接可正常工作的最快方式。 -有关更广泛的测试背景,请参见 [测试](/zh-CN/help/testing)。 +有关更广泛的测试背景,请参见[测试](/zh-CN/help/testing)。 ## 故障排除 ### 没有返回任何会话 -通常意味着 Gateway 网关会话尚不可路由。请确认底层会话已存储渠道/提供商、接收方,以及可选的账号/线程路由元数据。 +通常表示 Gateway 网关会话当前不可路由。请确认底层会话已存储渠道/provider、收件人以及可选的账户/线程路由元数据。 -### `events_poll` 或 `events_wait` 漏掉了较早的消息 +### `events_poll` 或 `events_wait` 漏掉较早的消息 -这是预期行为。实时队列从桥接连接时开始。请使用 `messages_read` 读取较早的 transcript 历史。 +这是预期行为。实时队列会在桥接器连接时开始。较早的 transcript 历史请用 `messages_read` 读取。 -### Claude 通知没有显示 +### Claude 通知未显示 请检查以下各项: -- 客户端保持了 stdio MCP 会话处于打开状态 -- `--claude-channel-mode` 为 `on` 或 `auto` -- 客户端确实理解 Claude 专用通知方法 -- 入站消息发生在桥接连接之后 +- 客户端是否保持 stdio MCP 会话处于打开状态 +- `--claude-channel-mode` 是否为 `on` 或 `auto` +- 客户端是否确实理解 Claude 专用通知方法 +- 入站消息是否发生在桥接器连接之后 -### 批准缺失 +### 审批缺失 -`permissions_list_open` 只显示桥接连接期间观察到的批准请求。它不是持久化的批准历史 API。 +`permissions_list_open` 只显示桥接器连接期间观察到的审批请求。它不是一个持久化审批历史 API。 ## OpenClaw 作为 MCP 客户端注册表 这是 `openclaw mcp list`、`show`、`set` 和 `unset` 路径。 -这些命令不会通过 MCP 暴露 OpenClaw。它们管理 OpenClaw 配置中 `mcp.servers` 下由 OpenClaw 拥有的 MCP 服务器定义。 +这些命令不会通过 MCP 暴露 OpenClaw。它们用于管理 OpenClaw 配置中 `mcp.servers` 下由 OpenClaw 拥有的 MCP 服务器定义。 -这些已保存的定义用于稍后由 OpenClaw 启动或配置的运行时,例如嵌入式 Pi 和其他运行时适配器。OpenClaw 集中存储这些定义,这样这些运行时就不需要维护各自重复的 MCP 服务器列表。 +这些已保存的定义用于 OpenClaw 稍后启动或配置的运行时,例如嵌入式 Pi 和其他运行时适配器。OpenClaw 将这些定义集中存储,这样这些运行时就不需要各自维护重复的 MCP 服务器列表。 重要行为: - 这些命令只读取或写入 OpenClaw 配置 - 它们不会连接到目标 MCP 服务器 - 它们不会验证命令、URL 或远程传输当前是否可达 -- 运行时适配器会在执行时决定自己实际支持哪些传输形式 -- 嵌入式 Pi 会在普通 `coding` 和 `messaging` 工具配置文件中暴露已配置的 MCP 工具;`minimal` 仍会隐藏它们,而 `tools.deny: ["bundle-mcp"]` 会显式禁用它们 +- 运行时适配器会在执行时决定它们实际支持哪些传输形态 +- 嵌入式 Pi 会在常规 `coding` 和 `messaging` 工具配置中暴露已配置的 MCP 工具;`minimal` 仍会隐藏它们,而 `tools.deny: ["bundle-mcp"]` 会显式禁用它们 ## 已保存的 MCP 服务器定义 -OpenClaw 还会在配置中存储一个轻量级 MCP 服务器注册表,供需要 OpenClaw 管理的 MCP 定义的界面使用。 +OpenClaw 还会在配置中存储一个轻量级的 MCP 服务器注册表,供需要 OpenClaw 管理的 MCP 定义的界面使用。 命令: @@ -342,9 +344,9 @@ OpenClaw 还会在配置中存储一个轻量级 MCP 服务器注册表,供需 说明: - `list` 会对服务器名称排序。 -- 不带名称的 `show` 会打印完整的已配置 MCP 服务器对象。 -- `set` 期望在命令行中提供一个 JSON 对象值。 -- 如果指定名称的服务器不存在,`unset` 会失败。 +- `show` 在不带名称时会打印完整的已配置 MCP 服务器对象。 +- `set` 期望在命令行上传入一个 JSON 对象值。 +- `unset` 会在指定服务器不存在时失败。 示例: @@ -356,7 +358,7 @@ openclaw mcp set docs '{"url":"https://mcp.example.com"}' openclaw mcp unset context7 ``` -示例配置结构: +配置形态示例: ```json { @@ -376,30 +378,30 @@ openclaw mcp unset context7 ### Stdio 传输 -启动一个本地子进程,并通过 stdin/stdout 进行通信。 +启动本地子进程,并通过 stdin/stdout 进行通信。 -| 字段 | 描述 | -| ------------------------- | ---------------------------- | -| `command` | 要生成的可执行文件(必需) | -| `args` | 命令行参数数组 | -| `env` | 额外环境变量 | -| `cwd` / `workingDirectory` | 进程的工作目录 | +| 字段 | 描述 | +| -------------------------- | ----------------------- | +| `command` | 要启动的可执行文件(必填) | +| `args` | 命令行参数数组 | +| `env` | 额外的环境变量 | +| `cwd` / `workingDirectory` | 进程的工作目录 | #### Stdio 环境变量安全过滤器 -OpenClaw 会拒绝那些可在第一次 RPC 之前改变 stdio MCP 服务器启动方式的解释器启动环境变量键,即使它们出现在服务器的 `env` 块中也是如此。被阻止的键包括 `NODE_OPTIONS`、`PYTHONSTARTUP`、`PYTHONPATH`、`PERL5OPT`、`RUBYOPT`、`SHELLOPTS`、`PS4` 以及类似的运行时控制变量。启动时会以配置错误拒绝这些键,以防它们注入隐式前导代码、替换解释器,或对 stdio 进程启用调试器。普通的凭证、代理和服务器专用环境变量(`GITHUB_TOKEN`、`HTTP_PROXY`、自定义 `*_API_KEY` 等)不受影响。 +OpenClaw 会拒绝那些可能在第一次 RPC 之前改变 stdio MCP 服务器启动方式的解释器启动环境变量键,即使它们出现在服务器的 `env` 块中也是如此。被阻止的键包括 `NODE_OPTIONS`、`PYTHONSTARTUP`、`PYTHONPATH`、`PERL5OPT`、`RUBYOPT`、`SHELLOPTS`、`PS4` 以及类似的运行时控制变量。启动时会因配置错误而拒绝这些键,这样它们就无法注入隐式前导代码、替换解释器,或对 stdio 进程启用调试器。普通的凭证、代理和服务器专用环境变量(`GITHUB_TOKEN`、`HTTP_PROXY`、自定义 `*_API_KEY` 等)不受影响。 -如果你的 MCP 服务器确实需要其中某个被阻止的变量,请将其设置在 Gateway 网关宿主进程上,而不是设置在 stdio 服务器的 `env` 下。 +如果你的 MCP 服务器确实需要其中某个被阻止的变量,请将它设置在 Gateway 网关宿主进程上,而不是设置在 stdio 服务器的 `env` 下。 ### SSE / HTTP 传输 通过 HTTP Server-Sent Events 连接到远程 MCP 服务器。 -| 字段 | 描述 | -| -------------------- | ------------------------------------------------------- | -| `url` | 远程服务器的 HTTP 或 HTTPS URL(必需) | -| `headers` | 可选的 HTTP 标头键值映射(例如认证令牌) | -| `connectionTimeoutMs` | 每服务器连接超时时间,单位为 ms(可选) | +| 字段 | 描述 | +| --------------------- | ----------------------------------------------------- | +| `url` | 远程服务器的 HTTP 或 HTTPS URL(必填) | +| `headers` | 可选的 HTTP 请求头键值映射(例如认证 token) | +| `connectionTimeoutMs` | 每服务器连接超时时间(毫秒,可选) | 示例: @@ -418,18 +420,18 @@ OpenClaw 会拒绝那些可在第一次 RPC 之前改变 stdio MCP 服务器启 } ``` -`url`(userinfo)和 `headers` 中的敏感值会在日志和状态输出中被脱敏。 +`url` 中的敏感值(userinfo)以及 `headers` 中的敏感值会在日志和状态输出中被脱敏。 ### Streamable HTTP 传输 -`streamable-http` 是除 `sse` 和 `stdio` 之外的另一种传输选项。它使用 HTTP 流式传输与远程 MCP 服务器进行双向通信。 +`streamable-http` 是除 `sse` 和 `stdio` 之外的另一种传输选项。它使用 HTTP 流进行与远程 MCP 服务器的双向通信。 -| 字段 | 描述 | -| -------------------- | ------------------------------------------------------------------------------------ | -| `url` | 远程服务器的 HTTP 或 HTTPS URL(必需) | -| `transport` | 设为 `"streamable-http"` 以选择此传输方式;省略时,OpenClaw 使用 `sse` | -| `headers` | 可选的 HTTP 标头键值映射(例如认证令牌) | -| `connectionTimeoutMs` | 每服务器连接超时时间,单位为 ms(可选) | +| 字段 | 描述 | +| --------------------- | ------------------------------------------------------------------------------------ | +| `url` | 远程服务器的 HTTP 或 HTTPS URL(必填) | +| `transport` | 设为 `"streamable-http"` 以选择此传输方式;若省略,OpenClaw 使用 `sse` | +| `headers` | 可选的 HTTP 请求头键值映射(例如认证 token) | +| `connectionTimeoutMs` | 每服务器连接超时时间(毫秒,可选) | 示例: @@ -450,7 +452,7 @@ OpenClaw 会拒绝那些可在第一次 RPC 之前改变 stdio MCP 服务器启 } ``` -这些命令仅管理已保存的配置。它们不会启动渠道桥接、打开实时 MCP 客户端会话,也不能证明目标服务器当前可达。 +这些命令只管理已保存的配置。它们不会启动渠道桥接,不会打开实时 MCP 客户端会话,也不能证明目标服务器当前可达。 ## 当前限制 @@ -458,8 +460,8 @@ OpenClaw 会拒绝那些可在第一次 RPC 之前改变 stdio MCP 服务器启 当前限制: -- 会话发现依赖现有 Gateway 网关会话路由元数据 +- 会话发现依赖现有的 Gateway 网关会话路由元数据 - 除 Claude 专用适配器外,尚无通用推送协议 -- 还没有消息编辑或回应工具 -- HTTP/SSE/streamable-http 传输会连接到单个远程服务器;尚不支持多路复用上游 -- `permissions_list_open` 仅包含桥接连接期间观察到的批准请求 +- 目前还没有消息编辑或表情回应工具 +- HTTP/SSE/streamable-http 传输连接到单个远程服务器;尚不支持上游多路复用 +- `permissions_list_open` 仅包含桥接器连接期间观察到的审批请求 diff --git a/docs/zh-CN/cli/memory.md b/docs/zh-CN/cli/memory.md index b0a6876be..f04be30c0 100644 --- a/docs/zh-CN/cli/memory.md +++ b/docs/zh-CN/cli/memory.md @@ -1,15 +1,15 @@ --- read_when: - - 你想要索引或搜索语义记忆。 - - 你正在调试记忆可用性或索引问题。 - - 你想将回忆出的短期记忆提升到 `MEMORY.md` 中。 + - 你想要索引或搜索语义记忆 + - 你正在调试记忆可用性或索引问题 + - 你想将召回的短期记忆提升到 `MEMORY.md` 中 summary: '`openclaw memory` 的 CLI 参考(status/index/search/promote/promote-explain/rem-harness)' -title: 记忆 +title: memory x-i18n: - generated_at: "2026-04-23T06:17:53Z" + generated_at: "2026-04-23T07:04:33Z" model: gpt-5.4 provider: openai - source_hash: c9ea7aa2858b18cc6daa6531c45c9e838015b84de1c7a1b88716f2b1323e419c + source_hash: 4a6207037e1097aa793ccb8fbdb8cbf8708ceb7910e31bc286ebb7a5bccb30a2 source_path: cli/memory.md workflow: 15 --- @@ -17,14 +17,14 @@ x-i18n: # `openclaw memory` 管理语义记忆的索引与搜索。 -由当前激活的记忆插件提供(默认:`memory-core`;将 `plugins.slots.memory = "none"` 设为禁用)。 +由当前启用的 memory 插件提供(默认:`memory-core`;设置 `plugins.slots.memory = "none"` 可禁用)。 相关内容: -- 记忆概念:[记忆](/zh-CN/concepts/memory) -- 记忆 wiki:[Memory Wiki](/zh-CN/plugins/memory-wiki) +- Memory 概念:[Memory](/zh-CN/concepts/memory) +- Memory wiki:[Memory Wiki](/zh-CN/plugins/memory-wiki) - wiki CLI:[wiki](/zh-CN/cli/wiki) -- 插件:[插件](/zh-CN/tools/plugin) +- Plugins:[Plugins](/zh-CN/tools/plugin) ## 示例 @@ -53,26 +53,28 @@ openclaw memory index --agent main --verbose `memory status` 和 `memory index`: -- `--agent `:限定到单个智能体。不传时,这些命令会对每个已配置的智能体运行;如果未配置智能体列表,则回退到默认智能体。 +- `--agent `:限定为单个智能体。不使用该选项时,这些命令会对每个已配置的智能体运行;如果未配置智能体列表,则会回退到默认智能体。 - `--verbose`:在探测和索引期间输出详细日志。 `memory status`: -- `--deep`:探测向量 + 嵌入可用性。 -- `--index`:如果存储处于脏状态,则执行重新索引(隐含 `--deep`)。 +- `--deep`:探测向量 + embedding 可用性。 +- `--index`:如果存储已脏,则运行重新索引(隐含 `--deep`)。 - `--fix`:修复过期的 recall 锁并规范化提升元数据。 - `--json`:输出 JSON。 +如果 `memory status` 显示 `Dreaming status: blocked`,则表示托管的 Dreaming cron 已启用,但驱动默认智能体运行它的心跳未触发。两个常见原因请参阅 [Dreaming never runs](/zh-CN/concepts/dreaming#dreaming-never-runs-status-shows-blocked)。 + `memory index`: - `--force`:强制执行完整重新索引。 `memory search`: -- 查询输入:可传位置参数 `[query]` 或 `--query `。 +- 查询输入:可传入位置参数 `[query]` 或 `--query `。 - 如果两者都提供,则以 `--query` 为准。 - 如果两者都未提供,命令会报错退出。 -- `--agent `:限定到单个智能体(默认:默认智能体)。 +- `--agent `:限定为单个智能体(默认:默认智能体)。 - `--max-results `:限制返回结果数量。 - `--min-score `:过滤低分匹配结果。 - `--json`:输出 JSON 结果。 @@ -86,64 +88,65 @@ openclaw memory promote [--apply] [--limit ] [--include-promoted] ``` - `--apply` -- 将提升内容写入 `MEMORY.md`(默认:仅预览)。 -- `--limit ` -- 限制显示的候选数量。 -- `--include-promoted` -- 包含之前周期中已提升的条目。 +- `--limit ` -- 限制显示的候选项数量。 +- `--include-promoted` -- 包含在之前周期中已提升的条目。 完整选项: -- 使用加权提升信号(`frequency`、`relevance`、`query diversity`、`recency`、`consolidation`、`conceptual richness`)对来自 `memory/YYYY-MM-DD.md` 的短期候选进行排序。 -- 使用来自记忆回忆和每日摄取流程的短期信号,以及 light/REM 阶段的强化信号。 +- 使用加权提升信号(`frequency`、`relevance`、`query diversity`、`recency`、`consolidation`、`conceptual richness`)对来自 `memory/YYYY-MM-DD.md` 的短期候选项进行排序。 +- 使用来自记忆召回和每日摄取流程的短期信号,以及 light/REM 阶段的强化信号。 - 启用 Dreaming 时,`memory-core` 会自动管理一个 cron 任务,在后台运行完整流程(`light -> REM -> deep`)(无需手动执行 `openclaw cron add`)。 -- `--agent `:限定到单个智能体(默认:默认智能体)。 -- `--limit `:返回/应用的最大候选数。 -- `--min-score `:最小加权提升分数。 -- `--min-recall-count `:候选项所需的最小回忆次数。 -- `--min-unique-queries `:候选项所需的最小不同查询数。 -- `--apply`:将选中的候选追加到 `MEMORY.md`,并标记为已提升。 -- `--include-promoted`:在输出中包含已提升的候选。 +- `--agent `:限定为单个智能体(默认:默认智能体)。 +- `--limit `:返回/应用的最大候选项数量。 +- `--min-score `:最低加权提升分数。 +- `--min-recall-count `:候选项所需的最小 recall 次数。 +- `--min-unique-queries `:候选项所需的最少不同查询数。 +- `--apply`:将选中的候选项追加到 `MEMORY.md`,并将其标记为已提升。 +- `--include-promoted`:在输出中包含已提升的候选项。 - `--json`:输出 JSON。 `memory promote-explain`: -解释特定提升候选及其分数明细。 +解释某个特定提升候选项及其分数明细。 ```bash openclaw memory promote-explain [--agent ] [--include-promoted] [--json] ``` -- ``:用于查找的候选键、路径片段或片段内容。 -- `--agent `:限定到单个智能体(默认:默认智能体)。 -- `--include-promoted`:包含已提升的候选。 +- ``:用于查找的候选项键、路径片段或片段内容。 +- `--agent `:限定为单个智能体(默认:默认智能体)。 +- `--include-promoted`:包含已提升的候选项。 - `--json`:输出 JSON。 `memory rem-harness`: -预览 REM 反思、候选事实和 deep 提升输出,不会写入任何内容。 +预览 REM 反思、候选真相和 deep 提升输出,不会写入任何内容。 ```bash openclaw memory rem-harness [--agent ] [--include-promoted] [--json] ``` -- `--agent `:限定到单个智能体(默认:默认智能体)。 -- `--include-promoted`:包含已提升的 deep 候选。 +- `--agent `:限定为单个智能体(默认:默认智能体)。 +- `--include-promoted`:包含已提升的 deep 候选项。 - `--json`:输出 JSON。 ## Dreaming -Dreaming 是后台记忆整合系统,由三个协作阶段组成: -**light**(整理/暂存短期材料)、**deep**(将持久事实提升到 `MEMORY.md` 中)和 **REM**(反思并呈现主题)。 +Dreaming 是后台记忆整合系统,由三个协同工作的 +阶段组成:**light**(整理/暂存短期材料)、**deep**(将持久 +事实提升到 `MEMORY.md`)、以及 **REM**(反思并提炼主题)。 - 使用 `plugins.entries.memory-core.config.dreaming.enabled: true` 启用。 -- 可在聊天中通过 `/dreaming on|off` 切换(或使用 `/dreaming status` 查看状态)。 -- Dreaming 按一个受管的完整流程计划(`dreaming.frequency`)运行,并按顺序执行各阶段:light、REM、deep。 +- 可通过聊天中的 `/dreaming on|off` 切换(或通过 `/dreaming status` 查看状态)。 +- Dreaming 在一个托管的完整流程计划上运行(`dreaming.frequency`),并按顺序执行各阶段:light、REM、deep。 - 只有 deep 阶段会将持久记忆写入 `MEMORY.md`。 -- 人类可读的阶段输出和日记条目会写入 `DREAMS.md`(或现有的 `dreams.md`),并可选择将每阶段报告写入 `memory/dreaming//YYYY-MM-DD.md`。 -- 排名使用加权信号:回忆频率、检索相关性、查询多样性、时间新近性、跨日整合程度以及派生概念丰富度。 -- 提升在写入 `MEMORY.md` 前会重新读取实时每日笔记,因此已编辑或删除的短期片段不会基于过期的 recall-store 快照被提升。 -- 计划任务和手动 `memory promote` 运行共享相同的 deep 阶段默认值,除非你传入 CLI 阈值覆盖。 -- 自动运行会在已配置的记忆工作区之间展开执行。 +- 面向人类可读的阶段输出和日志条目会写入 `DREAMS.md`(或已有的 `dreams.md`),并可选写入每阶段报告到 `memory/dreaming//YYYY-MM-DD.md`。 +- 排序使用加权信号:recall 频率、检索相关性、查询多样性、时间新近性、跨日整合,以及派生概念丰富度。 +- 提升在写入 `MEMORY.md` 前会重新读取实时每日笔记,因此经过编辑或删除的短期片段不会基于过期的 recall 存储快照被提升。 +- 计划任务与手动 `memory promote` 运行共享同一套 deep 阶段默认值,除非你通过 CLI 传入阈值覆盖。 +- 自动运行会在已配置的 memory 工作区之间展开执行。 -默认调度: +默认计划: - **完整流程频率**:`dreaming.frequency = 0 3 * * *` - **Deep 阈值**:`minScore=0.8`、`minRecallCount=3`、`minUniqueQueries=3`、`recencyHalfLifeDays=14`、`maxAgeDays=30` @@ -168,13 +171,13 @@ Dreaming 是后台记忆整合系统,由三个协作阶段组成: 说明: -- `memory index --verbose` 会打印各阶段细节(提供商、模型、来源、批处理活动)。 +- `memory index --verbose` 会输出每个阶段的详细信息(提供商、模型、来源、批处理活动)。 - `memory status` 包含通过 `memorySearch.extraPaths` 配置的任何额外路径。 -- 如果实际生效的记忆远程 API 密钥字段被配置为 SecretRef,该命令会从当前激活的 Gateway 网关快照中解析这些值。如果 Gateway 网关不可用,命令会快速失败。 -- Gateway 网关版本偏差说明:此命令路径要求 Gateway 网关支持 `secrets.resolve`;旧版 Gateway 网关会返回 unknown-method 错误。 -- 使用 `dreaming.frequency` 调整计划完整流程频率。Deep 提升策略本身属于内部逻辑;当你需要一次性手动覆盖时,请在 `memory promote` 上使用 CLI 标志。 -- `memory rem-harness --path --grounded` 会从历史每日笔记中预览有依据的 `What Happened`、`Reflections` 和 `Possible Lasting Updates`,不会写入任何内容。 -- `memory rem-backfill --path ` 会将可回滚的有依据日记条目写入 `DREAMS.md` 以供 UI 审查。 -- `memory rem-backfill --path --stage-short-term` 还会将有依据的持久候选植入实时短期提升存储,以便正常 deep 阶段进行排序。 -- `memory rem-backfill --rollback` 会移除先前写入的有依据日记条目,而 `memory rem-backfill --rollback-short-term` 会移除先前暂存的有依据短期候选。 -- 完整的阶段说明和配置参考,请参见 [Dreaming](/zh-CN/concepts/dreaming)。 +- 如果有效启用的 memory 远程 API key 字段被配置为 SecretRefs,该命令会从当前 Gateway 网关快照中解析这些值。如果 Gateway 网关不可用,命令会快速失败。 +- Gateway 网关版本偏差说明:此命令路径要求 Gateway 网关支持 `secrets.resolve`;较旧的 Gateway 网关会返回 unknown-method 错误。 +- 使用 `dreaming.frequency` 调整计划中的完整流程频率。除此之外,deep 提升策略属于内部逻辑;当你需要一次性的手动覆盖时,请在 `memory promote` 上使用 CLI 标志。 +- `memory rem-harness --path --grounded` 会基于历史每日笔记预览 grounded 的 `What Happened`、`Reflections` 和 `Possible Lasting Updates`,不会写入任何内容。 +- `memory rem-backfill --path ` 会将可回滚的 grounded 日志条目写入 `DREAMS.md`,供 UI 审查。 +- `memory rem-backfill --path --stage-short-term` 还会将 grounded 的持久候选项播种到实时短期提升存储中,以便正常的 deep 阶段进行排序。 +- `memory rem-backfill --rollback` 会移除之前写入的 grounded 日志条目,而 `memory rem-backfill --rollback-short-term` 会移除之前暂存的 grounded 短期候选项。 +- 完整阶段说明和配置参考请参阅 [Dreaming](/zh-CN/concepts/dreaming)。 diff --git a/docs/zh-CN/cli/models.md b/docs/zh-CN/cli/models.md index 7d9d5ed38..4b71018a9 100644 --- a/docs/zh-CN/cli/models.md +++ b/docs/zh-CN/cli/models.md @@ -1,26 +1,27 @@ --- read_when: - - 你想更改默认模型或查看提供商凭证状态 - - 你想扫描可用的模型/提供商并调试凭证配置文件 -summary: '`openclaw models` 的 CLI 参考(status/list/set/scan、别名、回退和凭证)' -title: 模型 + - 你想更改默认模型或查看提供商认证状态 + - 你想扫描可用的模型/提供商并调试认证配置文件 +summary: '`openclaw models` 的 CLI 参考(status/list/set/scan、别名、回退、认证)' +title: models x-i18n: - generated_at: "2026-04-23T06:24:04Z" + generated_at: "2026-04-23T07:04:57Z" model: gpt-5.4 provider: openai - source_hash: 3bf7b864ff57af0649bc31443ce77b193d6b3dbb200c53b69ea584fa2e12cbf7 + source_hash: d4ba72ca8acb7cc31796c119fce3816e6a919eb28a4ed4b03664d3b222498f5a source_path: cli/models.md workflow: 15 --- # `openclaw models` -模型发现、扫描与配置(默认模型、回退、凭证配置文件)。 +模型发现、扫描和配置(默认模型、回退、认证配置文件)。 相关内容: -- 提供商 + 模型:[模型](/zh-CN/providers/models) -- 提供商凭证设置:[入门指南](/zh-CN/start/getting-started) +- 提供商 + 模型:[Models](/zh-CN/providers/models) +- 模型选择概念 + `/models` 斜杠命令:[Models 概念](/zh-CN/concepts/models) +- 提供商认证设置:[入门指南](/zh-CN/start/getting-started) ## 常用命令 @@ -31,39 +32,36 @@ openclaw models set openclaw models scan ``` -`openclaw models status` 会显示解析后的默认值/回退配置,以及凭证概览。 -当提供商用量快照可用时,OAuth/API 密钥状态部分还会包含 -提供商用量时间窗口和配额快照。 -当前支持用量时间窗口的提供商有:Anthropic、GitHub Copilot、Gemini CLI、OpenAI -Codex、MiniMax、Xiaomi 和 z.ai。用量凭证信息会在可用时来自提供商特定钩子; -否则,OpenClaw 会回退为匹配来自凭证配置文件、环境变量或配置的 OAuth/API 密钥 +`openclaw models status` 会显示解析后的默认值/回退,以及认证概览。 +当提供商使用情况快照可用时,OAuth/API 密钥状态部分会包含 +提供商使用窗口和配额快照。 +当前支持使用窗口的提供商:Anthropic、GitHub Copilot、Gemini CLI、OpenAI +Codex、MiniMax、Xiaomi 和 z.ai。使用情况认证在可用时来自提供商专用钩子; +否则,OpenClaw 会回退为从认证配置文件、环境变量或配置中匹配 OAuth/API 密钥 凭证。 -在 `--json` 输出中,`auth.providers` 是具备环境变量/配置/存储感知能力的提供商 -概览,而 `auth.oauth` 仅表示凭证存储中的配置文件健康状态。 -添加 `--probe` 可对每个已配置的提供商配置文件运行实时凭证探测。 -探测会发起真实请求(可能消耗 token 并触发速率限制)。 -使用 `--agent ` 可检查某个已配置智能体的模型/凭证状态。省略时, -命令会在设置了 `OPENCLAW_AGENT_DIR`/`PI_CODING_AGENT_DIR` 时使用它们,否则使用 +在 `--json` 输出中,`auth.providers` 是感知环境变量/配置/store 的提供商 +概览,而 `auth.oauth` 仅是 auth-store 配置文件健康状态。 +添加 `--probe` 可针对每个已配置的提供商配置文件运行实时认证探测。 +探测是真实请求(可能会消耗令牌并触发速率限制)。 +使用 `--agent ` 可检查已配置智能体的模型/认证状态。省略时, +该命令会在设置了 `OPENCLAW_AGENT_DIR`/`PI_CODING_AGENT_DIR` 时使用它们,否则使用 已配置的默认智能体。 -探测行可能来自凭证配置文件、环境变量凭证,或 `models.json`。 +探测行可能来自认证配置文件、环境变量凭证或 `models.json`。 -说明: +注意: - `models set ` 接受 `provider/model` 或别名。 -- `models list --all` 会包含由内置提供商拥有的静态目录行,即使 - 你尚未通过该提供商完成认证也是如此。在配置匹配凭证之前,这些行仍会显示 - 为不可用。 -- `models list --provider ` 会按提供商 id 过滤,例如 `moonshot` 或 - `openai-codex`。它不接受交互式提供商选择器中的显示标签,例如 - `Moonshot AI`。 -- 模型引用会通过在**第一个** `/` 处分割来解析。如果模型 ID 本身包含 `/`(OpenRouter 风格),请包含提供商前缀(示例:`openrouter/moonshotai/kimi-k2`)。 +- `models list --all` 包含由内置提供商拥有的静态目录行,即使你尚未为该提供商配置认证 + 也是如此。这些行仍会显示为不可用,直到配置了匹配的认证。 +- `models list --provider ` 按提供商 ID 过滤,例如 `moonshot` 或 + `openai-codex`。它不接受交互式提供商选择器中的显示标签,例如 `Moonshot AI`。 +- 模型引用会通过按**第一个** `/` 分割来解析。如果模型 ID 包含 `/`(OpenRouter 风格),请包含提供商前缀(示例:`openrouter/moonshotai/kimi-k2`)。 - 如果你省略提供商,OpenClaw 会先将输入解析为别名,然后 - 解析为已配置提供商中与该精确模型 id 唯一匹配的项,最后才 - 以弃用警告的方式回退到已配置的默认提供商。 - 如果该提供商不再公开已配置的默认模型,OpenClaw 会 - 回退到第一个已配置的提供商/模型,而不是暴露一个 - 过时的、已移除提供商默认值。 -- `models status` 可能会在凭证输出中显示 `marker()`,用于表示非机密占位符(例如 `OPENAI_API_KEY`、`secretref-managed`、`minimax-oauth`、`oauth:chutes`、`ollama-local`),而不是将它们作为机密进行掩码处理。 + 解析为已配置提供商中与该确切模型 ID 唯一匹配的项,最后才会回退到已配置的默认提供商,并给出弃用警告。 + 如果该提供商不再暴露已配置的默认模型,OpenClaw + 会回退到第一个已配置的提供商/模型,而不是显示一个 + 已失效、已移除提供商的默认值。 +- `models status` 可能会在认证输出中显示 `marker()`,用于表示非敏感占位符(例如 `OPENAI_API_KEY`、`secretref-managed`、`minimax-oauth`、`oauth:chutes`、`ollama-local`),而不是将其作为敏感信息遮蔽。 ### `models status` @@ -71,14 +69,14 @@ Codex、MiniMax、Xiaomi 和 z.ai。用量凭证信息会在可用时来自提 - `--json` - `--plain` -- `--check`(退出码:1 = 已过期/缺失,2 = 即将过期) -- `--probe`(对已配置凭证配置文件进行实时探测) +- `--check`(退出码 1=已过期/缺失,2=即将过期) +- `--probe`(对已配置认证配置文件进行实时探测) - `--probe-provider `(探测单个提供商) -- `--probe-profile `(可重复或使用逗号分隔的配置文件 id) +- `--probe-profile `(可重复或使用逗号分隔的配置文件 ID) - `--probe-timeout ` - `--probe-concurrency ` - `--probe-max-tokens ` -- `--agent `(已配置的智能体 id;覆盖 `OPENCLAW_AGENT_DIR`/`PI_CODING_AGENT_DIR`) +- `--agent `(已配置智能体 ID;会覆盖 `OPENCLAW_AGENT_DIR`/`PI_CODING_AGENT_DIR`) 探测状态分组: @@ -93,12 +91,12 @@ Codex、MiniMax、Xiaomi 和 z.ai。用量凭证信息会在可用时来自提 可预期的探测详情/原因代码情况: -- `excluded_by_auth_order`:存在已存储的配置文件,但显式的 - `auth.order.` 省略了它,因此探测会报告该排除状态,而不是 +- `excluded_by_auth_order`:存在已存储的配置文件,但显式 + `auth.order.` 省略了它,因此探测会报告该排除,而不是 尝试使用它。 - `missing_credential`、`invalid_expires`、`expired`、`unresolved_ref`: 配置文件存在,但不符合资格/无法解析。 -- `no_model`:提供商凭证存在,但 OpenClaw 无法为该提供商解析出可用于探测的 +- `no_model`:提供商认证存在,但 OpenClaw 无法为该提供商解析出可用于探测的 模型候选项。 ## 别名 + 回退 @@ -108,7 +106,7 @@ openclaw models aliases list openclaw models fallbacks list ``` -## 凭证配置文件 +## 认证配置文件 ```bash openclaw models auth add @@ -117,11 +115,11 @@ openclaw models auth setup-token --provider openclaw models auth paste-token ``` -`models auth add` 是交互式凭证辅助工具。它可以启动提供商凭证 -流程(OAuth/API 密钥),或根据你选择的提供商,引导你进入手动粘贴 token 流程。 +`models auth add` 是交互式认证助手。它可以启动提供商认证 +流程(OAuth/API 密钥),或根据你选择的提供商,引导你手动粘贴令牌。 -`models auth login` 会运行提供商插件的凭证流程(OAuth/API 密钥)。使用 -`openclaw plugins list` 可查看已安装了哪些提供商。 +`models auth login` 运行提供商插件的认证流程(OAuth/API 密钥)。使用 +`openclaw plugins list` 查看已安装了哪些提供商。 示例: @@ -129,18 +127,16 @@ openclaw models auth paste-token openclaw models auth login --provider openai-codex --set-default ``` -说明: +注意: -- `setup-token` 和 `paste-token` 仍然是通用 token 命令,适用于 - 暴露了 token 凭证方法的提供商。 -- `setup-token` 需要交互式 TTY,并运行该提供商的 token 凭证 +- `setup-token` 和 `paste-token` 仍然是通用令牌命令,适用于暴露令牌认证方法的提供商。 +- `setup-token` 需要交互式 TTY,并运行该提供商的令牌认证 方法(当该提供商暴露了 `setup-token` 方法时,默认使用 该方法)。 -- `paste-token` 接受在别处或通过自动化生成的 token 字符串。 -- `paste-token` 需要 `--provider`,会提示输入 token 值,并将其写入 - 默认配置文件 id `:manual`,除非你传入 +- `paste-token` 接受在其他地方或自动化流程中生成的令牌字符串。 +- `paste-token` 需要 `--provider`,会提示输入令牌值,并将其写入默认配置文件 ID `:manual`,除非你传入 `--profile-id`。 -- `paste-token --expires-in ` 会根据相对时长(例如 `365d` 或 `12h`) - 存储一个绝对 token 过期时间。 -- Anthropic 说明:Anthropic 员工告诉我们,OpenClaw 风格的 Claude CLI 用法已再次被允许,因此 OpenClaw 将 Claude CLI 复用和 `claude -p` 用法视为此集成的获准方式,除非 Anthropic 发布新的政策。 -- Anthropic 的 `setup-token` / `paste-token` 仍然可作为受支持的 OpenClaw token 路径使用,但 OpenClaw 现在在可用时优先使用 Claude CLI 复用和 `claude -p`。 +- `paste-token --expires-in ` 会根据相对时长(如 `365d` 或 `12h`) + 存储一个绝对令牌过期时间。 +- Anthropic 说明:Anthropic 工作人员告诉我们,OpenClaw 风格的 Claude CLI 用法再次被允许,因此 OpenClaw 将 Claude CLI 复用和 `claude -p` 用法视为此集成的受支持方式,除非 Anthropic 发布新的策略。 +- Anthropic 的 `setup-token` / `paste-token` 仍然可作为受支持的 OpenClaw 令牌路径使用,但 OpenClaw 现在会在可用时优先使用 Claude CLI 复用和 `claude -p`。 diff --git a/docs/zh-CN/cli/plugins.md b/docs/zh-CN/cli/plugins.md index 941937cc0..ec43765fc 100644 --- a/docs/zh-CN/cli/plugins.md +++ b/docs/zh-CN/cli/plugins.md @@ -1,14 +1,14 @@ --- read_when: - - 你想安装或管理 Gateway 网关插件或兼容的捆绑包 - - 你想调试插件加载失败问题 -summary: '`openclaw plugins` 的 CLI 设置参考(list、install、marketplace、uninstall、enable/disable、doctor)' -title: 插件 + - 你想安装或管理 Gateway 网关插件或兼容捆绑包 + - 你想调试插件加载失败 +summary: '`openclaw plugins` 的 CLI 参考(list、install、marketplace、uninstall、enable/disable、doctor)' +title: plugins x-i18n: - generated_at: "2026-04-23T06:40:17Z" + generated_at: "2026-04-23T07:05:01Z" model: gpt-5.4 provider: openai - source_hash: 80e324995fa2dbb5babb9631714eb2449a1c8c00411bf6bf44c4c74bc9a3e2b8 + source_hash: 7dd521db1de47ceb183d98a538005d3d816f52ffeee12593bcbaa8014d6e507b source_path: cli/plugins.md workflow: 15 --- @@ -20,9 +20,9 @@ x-i18n: 相关内容: - 插件系统:[Plugins](/zh-CN/tools/plugin) -- 捆绑包兼容性:[插件捆绑包](/zh-CN/plugins/bundles) -- 插件清单 + schema:[插件清单](/zh-CN/plugins/manifest) -- 安全加固:[安全](/zh-CN/gateway/security) +- 捆绑包兼容性:[Plugin bundles](/zh-CN/plugins/bundles) +- 插件清单 + schema:[Plugin manifest](/zh-CN/plugins/manifest) +- 安全加固:[Security](/zh-CN/gateway/security) ## 命令 @@ -46,45 +46,84 @@ openclaw plugins marketplace list openclaw plugins marketplace list --json ``` -内置插件随 OpenClaw 一起发布。其中一些默认启用(例如内置模型提供商、内置语音提供商以及内置浏览器插件);另一些则需要运行 `plugins enable`。 +内置插件随 OpenClaw 一起提供。其中一些默认启用(例如 +内置模型提供商、内置语音提供商以及内置浏览器 +插件);另一些则需要执行 `plugins enable`。 -原生 OpenClaw 插件必须随附 `openclaw.plugin.json`,并包含内联 JSON Schema(`configSchema`,即使为空也需要提供)。兼容捆绑包则改用它们自己的 bundle manifest。 +原生 OpenClaw 插件必须提供带内联 JSON +Schema 的 `openclaw.plugin.json`(`configSchema`,即使为空也必须存在)。兼容捆绑包则使用它们自己的捆绑包清单。 -`plugins list` 会显示 `Format: openclaw` 或 `Format: bundle`。详细列表 / 信息输出还会显示 bundle 子类型(`codex`、`claude` 或 `cursor`),以及检测到的 bundle 能力。 +`plugins list` 会显示 `Format: openclaw` 或 `Format: bundle`。详细的 list/info +输出还会显示捆绑包子类型(`codex`、`claude` 或 `cursor`)以及检测到的捆绑包 +能力。 ### 安装 ```bash -openclaw plugins install # 先 ClawHub,后 npm +openclaw plugins install # 优先 ClawHub,然后 npm openclaw plugins install clawhub: # 仅 ClawHub openclaw plugins install --force # 覆盖现有安装 openclaw plugins install --pin # 固定版本 openclaw plugins install --dangerously-force-unsafe-install openclaw plugins install # 本地路径 openclaw plugins install @ # marketplace -openclaw plugins install --marketplace # marketplace(显式) +openclaw plugins install --marketplace # marketplace(显式指定) openclaw plugins install --marketplace https://github.com// ``` -裸包名会先在 ClawHub 中查找,然后再查找 npm。安全提示:请将插件安装视为执行代码。优先使用固定版本。 +裸包名会先在 ClawHub 中检查,然后再检查 npm。安全说明: +安装插件等同于运行代码。优先使用固定版本。 -如果配置无效,`plugins install` 通常会以安全关闭方式失败,并提示你先运行 `openclaw doctor --fix`。唯一有文档说明的例外,是一个针对内置插件的窄范围恢复路径,用于那些显式选择加入 `openclaw.install.allowInvalidConfigRecovery` 的插件。 +如果你的 `plugins` 配置部分由单文件 `$include` 支持,`plugins install`、 +`plugins update`、`plugins enable`、`plugins disable` 和 `plugins uninstall` +会直接写入该被包含文件,并保持 `openclaw.json` 不变。根级 +include、include 数组以及带有同级覆盖项的 include 会以失败关闭的方式处理, +而不是被拍平成单一配置。支持的形式请参阅 [Config includes](/zh-CN/gateway/configuration)。 -`--force` 会复用现有安装目标,并原地覆盖已安装的插件或 hook 包。当你明确要从新的本地路径、归档、ClawHub 包或 npm 制品重新安装同一 id 时,请使用它。对于已跟踪 npm 插件的常规升级,优先使用 `openclaw plugins update `。 +如果配置无效,`plugins install` 通常会以失败关闭的方式终止,并提示你先 +运行 `openclaw doctor --fix`。唯一有文档说明的例外是一个针对内置插件的窄范围恢复路径, +适用于显式启用了 +`openclaw.install.allowInvalidConfigRecovery` 的插件。 -`--pin` 仅适用于 npm 安装。不支持与 `--marketplace` 一起使用,因为 marketplace 安装会保存 marketplace 源元数据,而不是 npm spec。 +`--force` 会复用现有安装目标,并原地覆盖一个已安装的 +插件或 hook 包。当你有意从新的本地路径、归档、ClawHub 包或 npm 制品 +重新安装相同 id 时可使用它。 +对于已跟踪 npm 插件的常规升级,优先使用 +`openclaw plugins update `。 -`--dangerously-force-unsafe-install` 是一个紧急兜底选项,用于处理内置危险代码扫描器的误报。即使内置扫描器报告 `critical` 级发现,它也允许继续安装,但它**不会**绕过插件 `before_install` hook 的策略阻止,也**不会**绕过扫描失败。 +如果你对一个已安装的插件 id 运行 `plugins install`,OpenClaw +会停止并提示你:正常升级请使用 `plugins update `, +如果你确实想从不同来源覆盖 +当前安装,则使用 `plugins install --force`。 -这个 CLI 标志适用于插件 install / update 流程。由 Gateway 网关支持的技能依赖安装使用对应的 `dangerouslyForceUnsafeInstall` 请求覆盖项,而 `openclaw skills install` 仍然是独立的 ClawHub Skills 下载 / 安装流程。 +`--pin` 仅适用于 npm 安装。它不支持与 `--marketplace` +一起使用,因为 marketplace 安装会保留 marketplace 来源元数据,而不是 +npm spec。 -`plugins install` 也是暴露了 `openclaw.hooks` 的 hook 包在 `package.json` 中的安装入口。请使用 `openclaw hooks` 来查看经过筛选的 hook 可见性以及按 hook 启用,而不是用于包安装。 +`--dangerously-force-unsafe-install` 是一个应急选项,用于处理内置危险代码扫描器 +的误报。即使内置扫描器报告 `critical` 级别发现, +它也允许安装继续进行,但它 **不会** 绕过插件 `before_install` hook 策略拦截, +也 **不会** 绕过扫描失败。 -npm spec **仅支持 registry**(包名 + 可选的**精确版本**或 **dist-tag**)。Git / URL / file spec 和 semver 范围都会被拒绝。为确保安全,依赖安装会使用 `--ignore-scripts` 运行。 +这个 CLI 标志适用于插件安装/更新流程。由 Gateway 网关支持的 Skills +依赖安装使用对应的 `dangerouslyForceUnsafeInstall` 请求覆盖项,而 `openclaw skills install` 仍然是独立的 ClawHub Skills +下载/安装流程。 -裸 spec 和 `@latest` 会停留在稳定轨道上。如果 npm 将其中任一项解析为预发布版本,OpenClaw 会停止,并要求你通过预发布 tag(例如 `@beta` / `@rc`)或精确的预发布版本(例如 `@1.2.3-beta.4`)显式选择加入。 +`plugins install` 也是暴露 +`openclaw.hooks` 于 `package.json` 中的 hook 包的安装入口。请使用 `openclaw hooks` 查看经过筛选的 hook +可见性和按 hook 启用控制,而不是用于安装包。 -如果一个裸安装 spec 与某个内置插件 id 匹配(例如 `diffs`),OpenClaw 会直接安装该内置插件。若要安装同名的 npm 包,请使用显式的带作用域 spec(例如 `@scope/diffs`)。 +npm spec **仅限 registry**(包名 + 可选的 **精确版本** 或 +**dist-tag**)。Git/URL/file spec 和 semver 范围会被拒绝。出于安全考虑, +依赖安装会使用 `--ignore-scripts` 运行。 + +裸 spec 和 `@latest` 会保持在稳定通道。如果 npm 将其中任一解析为预发布版本, +OpenClaw 会停止,并要求你显式选择加入,例如使用 +`@beta`/`@rc` 这样的预发布标签,或像 +`@1.2.3-beta.4` 这样的精确预发布版本。 + +如果一个裸安装 spec 与某个内置插件 id 匹配(例如 `diffs`),OpenClaw +会直接安装该内置插件。若要安装同名 npm 包,请使用显式作用域 spec(例如 `@scope/diffs`)。 支持的归档格式:`.zip`、`.tgz`、`.tar.gz`、`.tar`。 @@ -97,22 +136,27 @@ openclaw plugins install clawhub:openclaw-codex-app-server openclaw plugins install clawhub:openclaw-codex-app-server@1.2.3 ``` -OpenClaw 现在也会优先为裸 npm-safe 插件 spec 使用 ClawHub。只有当 ClawHub 中没有该包或该版本时,才会回退到 npm: +现在,对于 npm 安全的裸插件 spec,OpenClaw 也会优先使用 ClawHub。只有在 +ClawHub 没有该包或该版本时,才会回退到 npm: ```bash openclaw plugins install openclaw-codex-app-server ``` -OpenClaw 会从 ClawHub 下载包归档,检查声明的插件 API / 最低 Gateway 网关兼容性,然后通过常规归档路径安装。已记录的安装会保留其 ClawHub 源元数据,以便后续更新。 +OpenClaw 会从 ClawHub 下载包归档,检查其声明的 +插件 API / 最低 Gateway 网关兼容性,然后通过常规 +归档路径进行安装。已记录的安装会保留其 ClawHub 来源元数据,以供后续更新使用。 -当 marketplace 名称存在于 Claude 的本地注册表缓存 `~/.claude/plugins/known_marketplaces.json` 中时,可使用 `plugin@marketplace` 简写: +当 marketplace 名称存在于 Claude 的本地注册表缓存 +`~/.claude/plugins/known_marketplaces.json` 中时,使用 `plugin@marketplace` +简写: ```bash openclaw plugins marketplace list openclaw plugins install @ ``` -如果你想显式传递 marketplace 源,请使用 `--marketplace`: +当你想显式传递 marketplace 来源时,请使用 `--marketplace`: ```bash openclaw plugins install --marketplace @@ -121,24 +165,33 @@ openclaw plugins install --marketplace https://github.com// openclaw plugins install --marketplace ./my-marketplace ``` -Marketplace 源可以是: +Marketplace 来源可以是: - `~/.claude/plugins/known_marketplaces.json` 中 Claude 已知 marketplace 名称 - 本地 marketplace 根目录或 `marketplace.json` 路径 -- GitHub 仓库简写,例如 `owner/repo` -- GitHub 仓库 URL,例如 `https://github.com/owner/repo` +- 例如 `owner/repo` 的 GitHub 仓库简写 +- 例如 `https://github.com/owner/repo` 的 GitHub 仓库 URL - git URL -对于从 GitHub 或 git 加载的远程 marketplace,插件条目必须保持在克隆后的 marketplace 仓库内。OpenClaw 接受来自该仓库的相对路径源,并拒绝远程 manifest 中的 HTTP(S)、绝对路径、git、GitHub 以及其他非路径插件源。 +对于从 GitHub 或 git 加载的远程 marketplace,插件条目必须保留在 +克隆得到的 marketplace 仓库内。对于远程清单中的插件来源,OpenClaw 接受来自 +该仓库的相对路径来源,并拒绝 HTTP(S)、绝对路径、git、GitHub 及其他非路径 +来源。 对于本地路径和归档,OpenClaw 会自动检测: - 原生 OpenClaw 插件(`openclaw.plugin.json`) - Codex 兼容捆绑包(`.codex-plugin/plugin.json`) -- Claude 兼容捆绑包(`.claude-plugin/plugin.json` 或默认的 Claude 组件布局) +- Claude 兼容捆绑包(`.claude-plugin/plugin.json` 或默认的 Claude + 组件布局) - Cursor 兼容捆绑包(`.cursor-plugin/plugin.json`) -兼容捆绑包会安装到常规插件根目录中,并参与相同的 list / info / enable / disable 流程。目前,已支持 bundle Skills、Claude command-skills、Claude `settings.json` 默认值、Claude `.lsp.json` / manifest 声明的 `lspServers` 默认值、Cursor command-skills,以及兼容的 Codex hook 目录;其他已检测到的 bundle 能力会在诊断 / 信息中显示,但尚未接入运行时执行。 +兼容捆绑包会安装到常规插件根目录中,并参与 +相同的 list/info/enable/disable 流程。目前,支持捆绑包 Skills、Claude +command-skills、Claude `settings.json` 默认值、Claude `.lsp.json` / +清单声明的 `lspServers` 默认值、Cursor command-skills,以及兼容的 +Codex hook 目录;其他已检测到的捆绑包能力会显示在诊断/info 中, +但尚未接入运行时执行。 ### 列表 @@ -149,7 +202,10 @@ openclaw plugins list --verbose openclaw plugins list --json ``` -使用 `--enabled` 仅显示已加载的插件。使用 `--verbose` 可从表格视图切换到按插件显示的详细行,其中包含 source / origin / version / activation 元数据。使用 `--json` 可获取机器可读的清单以及注册表诊断信息。 +使用 `--enabled` 仅显示已加载插件。使用 `--verbose` 可从 +表格视图切换到按插件显示详情行,其中包含 source/origin/version/activation +元数据。使用 `--json` 可获取适用于机器读取的清单以及注册表 +诊断信息。 使用 `--link` 可避免复制本地目录(会添加到 `plugins.load.paths`): @@ -157,9 +213,11 @@ openclaw plugins list --json openclaw plugins install -l ./my-plugin ``` -`--force` 不支持与 `--link` 一起使用,因为链接安装会复用源路径,而不是复制到受管安装目标上。 +`--force` 不支持与 `--link` 同时使用,因为链接安装会复用 +源路径,而不是复制到受管理的安装目标上。 -在 npm 安装中使用 `--pin`,可将解析出的精确 spec(`name@version`)保存到 `plugins.installs` 中,同时保持默认行为为不固定版本。 +在 npm 安装中使用 `--pin`,可将解析得到的精确 spec(`name@version`)保存到 +`plugins.installs` 中,同时保留默认行为为非固定版本。 ### 卸载 @@ -169,9 +227,13 @@ openclaw plugins uninstall --dry-run openclaw plugins uninstall --keep-files ``` -`uninstall` 会从 `plugins.entries`、`plugins.installs`、插件 allowlist,以及在适用时的已链接 `plugins.load.paths` 条目中移除插件记录。对于活动中的 memory 插件,memory 槽位会重置为 `memory-core`。 +`uninstall` 会从 `plugins.entries`、`plugins.installs`、 +插件 allowlist,以及相关联的 `plugins.load.paths` 条目中移除插件记录。 +对于活动中的 memory 插件,memory slot 会重置为 `memory-core`。 -默认情况下,卸载还会删除活动 state-dir 插件根目录下的插件安装目录。使用 `--keep-files` 可保留磁盘上的文件。 +默认情况下,卸载还会删除活动 +state-dir 插件根目录下的插件安装目录。使用 +`--keep-files` 可保留磁盘上的文件。 `--keep-config` 作为 `--keep-files` 的已弃用别名仍受支持。 @@ -185,19 +247,36 @@ openclaw plugins update @openclaw/voice-call@beta openclaw plugins update openclaw-codex-app-server --dangerously-force-unsafe-install ``` -更新会应用于 `plugins.installs` 中跟踪的安装,以及 `hooks.internal.installs` 中跟踪的 hook 包安装。 +更新会应用于 `plugins.installs` 中已跟踪的安装,以及 `hooks.internal.installs` 中已跟踪的 hook 包 +安装。 -当你传入插件 id 时,OpenClaw 会复用为该插件记录的安装 spec。这意味着此前保存的 dist-tag(例如 `@beta`)和固定的精确版本,之后在运行 `update ` 时仍会继续使用。 +当你传入插件 id 时,OpenClaw 会复用该 +插件已记录的安装 spec。这意味着先前保存的 dist-tag(如 `@beta`)以及固定的精确版本 +会继续用于之后的 `update ` 运行。 -对于 npm 安装,你也可以传入带有 dist-tag 或精确版本的显式 npm 包 spec。OpenClaw 会将该包名回溯解析到已跟踪的插件记录,更新那个已安装插件,并为将来基于 id 的更新记录新的 npm spec。 +对于 npm 安装,你也可以传入带 dist-tag +或精确版本的显式 npm 包 spec。OpenClaw 会将该包名解析回已跟踪的插件 +记录,更新该已安装插件,并为后续基于 id 的更新记录新的 npm spec。 -仅传入不带版本或 tag 的 npm 包名,也会回溯解析到已跟踪的插件记录。当某个插件被固定到精确版本,而你想把它移回 registry 的默认发布线时,可使用这种方式。 +传入不带版本或标签的 npm 包名,也会解析回已跟踪的 +插件记录。当某个插件此前被固定到精确版本,而你 +想将其切回 registry 的默认发布线时,可使用这种方式。 -在实际执行 npm 更新之前,OpenClaw 会将已安装包版本与 npm registry 元数据进行检查。如果已安装版本与记录的制品标识已经匹配解析出的目标版本,则会跳过更新,不会下载、重新安装,也不会重写 `openclaw.json`。 +在执行实际 npm 更新前,OpenClaw 会根据 +npm registry 元数据检查已安装包的版本。如果已安装版本与记录的制品 +标识已经匹配解析目标,更新将被跳过,不会进行 +下载、重新安装,也不会重写 `openclaw.json`。 -当存在已存储的完整性哈希,而获取到的制品哈希发生变化时,OpenClaw 会将其视为 npm 制品漂移。交互式 `openclaw plugins update` 命令会打印预期哈希和实际哈希,并在继续前请求确认。非交互式更新辅助流程会以安全关闭方式失败,除非调用方提供显式的继续策略。 +当存在已存储的完整性哈希且抓取到的制品哈希发生变化时, +OpenClaw 会将其视为 npm 制品漂移。交互式 +`openclaw plugins update` 命令会打印期望哈希和实际哈希,并在继续前请求 +确认。非交互式更新辅助流程会以失败关闭的方式终止, +除非调用方提供显式的继续策略。 -`--dangerously-force-unsafe-install` 也可用于 `plugins update`,作为处理插件更新期间内置危险代码扫描误报的紧急覆盖项。它仍然不会绕过插件 `before_install` 策略阻止或扫描失败阻止,并且只适用于插件更新,不适用于 hook 包更新。 +`--dangerously-force-unsafe-install` 也可用于 `plugins update`,作为 +插件更新期间内置危险代码扫描误报的应急覆盖项。 +它仍不会绕过插件 `before_install` 策略拦截, +也不会绕过扫描失败拦截,并且它只适用于插件更新,不适用于 hook 包更新。 ### 检查 @@ -206,20 +285,25 @@ openclaw plugins inspect openclaw plugins inspect --json ``` -对单个插件进行深度检查。显示标识、加载状态、来源、已注册能力、hooks、工具、命令、服务、Gateway 网关方法、HTTP 路由、策略标志、诊断信息、安装元数据、bundle 能力,以及任何检测到的 MCP 或 LSP 服务器支持。 +对单个插件进行深度检查。显示身份、加载状态、来源、 +已注册能力、hooks、工具、命令、服务、Gateway 网关方法、 +HTTP 路由、策略标记、诊断信息、安装元数据、捆绑包能力, +以及任何检测到的 MCP 或 LSP 服务器支持。 -每个插件都会根据其在运行时实际注册的内容进行分类: +每个插件会根据它在运行时实际注册的内容进行分类: -- **plain-capability** — 一种能力类型(例如仅 provider 插件) -- **hybrid-capability** — 多种能力类型(例如文本 + 语音 + 图像) -- **hook-only** — 只有 hooks,没有能力或表面 -- **non-capability** — 有工具 / 命令 / 服务,但没有能力 +- **plain-capability** — 一种能力类型(例如,仅提供商插件) +- **hybrid-capability** — 多种能力类型(例如,文本 + 语音 + 图像) +- **hook-only** — 只有 hooks,没有能力或外部界面 +- **non-capability** — 有工具/命令/服务,但没有能力 有关能力模型的更多信息,请参阅 [Plugin shapes](/zh-CN/plugins/architecture#plugin-shapes)。 -`--json` 标志会输出适用于脚本处理和审计的机器可读报告。 +`--json` 标志会输出适用于脚本和 +审计的机器可读报告。 -`inspect --all` 会渲染一个全局表格,其中包含 shape、capability kinds、compatibility notices、bundle capabilities 和 hook summary 列。 +`inspect --all` 会渲染一个覆盖整个插件集的表格,其中包含 shape、capability kinds、 +compatibility notices、bundle capabilities 和 hook summary 列。 `info` 是 `inspect` 的别名。 @@ -229,9 +313,13 @@ openclaw plugins inspect --json openclaw plugins doctor ``` -`doctor` 会报告插件加载错误、manifest / 发现诊断信息以及兼容性提示。当一切正常时,它会输出 `No plugin issues detected.` +`doctor` 会报告插件加载错误、manifest/discovery 诊断信息以及 +兼容性提示。当一切正常时,它会输出 `No plugin issues +detected.` -对于缺少 `register` / `activate` 导出之类的模块形状失败问题,请使用 `OPENCLAW_PLUGIN_LOAD_DEBUG=1` 重新运行,以便在诊断输出中包含紧凑的导出形状摘要。 +对于缺少 `register`/`activate` 导出等模块形态故障,请使用 +`OPENCLAW_PLUGIN_LOAD_DEBUG=1` 重新运行,以在 +诊断输出中包含紧凑的导出形态摘要。 ### Marketplace @@ -240,4 +328,7 @@ openclaw plugins marketplace list openclaw plugins marketplace list --json ``` -Marketplace list 接受本地 marketplace 路径、`marketplace.json` 路径、如 `owner/repo` 这样的 GitHub 简写、GitHub 仓库 URL 或 git URL。`--json` 会输出解析后的源标签,以及已解析的 marketplace manifest 和插件条目。 +Marketplace list 接受本地 marketplace 路径、`marketplace.json` 路径、 +如 `owner/repo` 的 GitHub 简写、GitHub 仓库 URL 或 git URL。`--json` +会输出解析后的来源标签,以及已解析的 marketplace manifest 和 +插件条目。 diff --git a/docs/zh-CN/cli/tui.md b/docs/zh-CN/cli/tui.md index d02337212..6aa27bcb8 100644 --- a/docs/zh-CN/cli/tui.md +++ b/docs/zh-CN/cli/tui.md @@ -1,36 +1,37 @@ --- read_when: - - 你想为 Gateway 网关 使用终端 UI(对远程环境友好) - - 你想从脚本中传递 url / token / session - - 你想在没有 Gateway 网关 的情况下以本地内嵌模式运行终端 UI + - 你想要一个用于 Gateway 网关的终端 UI(适合远程使用) + - 你想从脚本传递 url/token/session + - 你想在没有 Gateway 网关的情况下,以本地嵌入模式运行 TUI - 你想使用 `openclaw chat` 或 `openclaw tui --local` -summary: '`openclaw tui` 的 CLI 参考(由 Gateway 网关 支持或本地内嵌终端 UI)' -title: 终端 UI +summary: '`openclaw tui` 的 CLI 参考(基于 Gateway 网关或本地嵌入式终端 UI)' +title: tui x-i18n: - generated_at: "2026-04-23T06:18:32Z" + generated_at: "2026-04-23T07:05:18Z" model: gpt-5.4 provider: openai - source_hash: 5f4b7cf2468779e0711f38a2cc304d783bb115fd5c5e573c9d1bc982da6e2905 + source_hash: 4fca025a15f5e985ca6f2eaf39fcbe784bd716f24841f43450b71936db26d141 source_path: cli/tui.md workflow: 15 --- # `openclaw tui` -打开连接到 Gateway 网关 的终端 UI,或以本地内嵌模式运行它。 +打开连接到 Gateway 网关的终端 UI,或以本地嵌入模式运行它。 相关内容: -- 终端 UI 指南:[终端 UI](/zh-CN/web/tui) +- TUI 指南:[TUI](/zh-CN/web/tui) -说明: +注意: - `chat` 和 `terminal` 是 `openclaw tui --local` 的别名。 - `--local` 不能与 `--url`、`--token` 或 `--password` 组合使用。 -- `tui` 会在可能的情况下,为 token / password 认证解析已配置的 Gateway 网关 凭证 SecretRefs(`env` / `file` / `exec` 提供商)。 -- 当从已配置的智能体工作区目录内启动时,终端 UI 会自动为会话键默认选择该智能体(除非 `--session` 被显式设置为 `agent::...`)。 -- 本地模式会直接使用内嵌智能体运行时。大多数本地工具都可用,但仅限 Gateway 网关 的功能不可用。 -- 本地模式会在终端 UI 命令界面中添加 `/auth [provider]`。 +- `tui` 会在可能的情况下,为 token/password 认证解析已配置的 Gateway 网关认证 `SecretRef`(`env`/`file`/`exec` 提供商)。 +- 当从已配置的智能体工作区目录内启动时,TUI 会自动为会话键默认值选择该智能体(除非 `--session` 明确为 `agent::...`)。 +- 本地模式直接使用嵌入式智能体运行时。大多数本地工具都可用,但仅限 Gateway 网关的功能不可用。 +- 本地模式会在 TUI 命令界面中添加 `/auth [provider]`。 +- 即使在本地模式下,插件审批门控仍然适用。需要审批的工具会在终端中提示你做出决定;不会因为未使用 Gateway 网关而被静默自动批准。 ## 示例 @@ -45,17 +46,18 @@ openclaw chat --message "Compare my config to the docs and tell me what to fix" openclaw tui --session bugfix ``` -## 配置修复流程 +## 配置修复循环 -当当前配置已经通过校验,并且你希望内嵌智能体在同一个终端中检查它、将其与文档进行比较并协助修复时,请使用本地模式: +当当前配置已经通过校验,并且你希望嵌入式智能体检查它、将其与文档对比,并从同一个终端帮助修复时,请使用本地模式: -如果 `openclaw config validate` 已经失败,请先使用 `openclaw configure` 或 `openclaw doctor --fix`。`openclaw chat` 不会绕过无效配置保护。 +如果 `openclaw config validate` 已经失败,请先使用 `openclaw configure` 或 +`openclaw doctor --fix`。`openclaw chat` 不会绕过无效配置保护。 ```bash openclaw chat ``` -然后在终端 UI 内执行: +然后在 TUI 内: ```text !openclaw config file @@ -64,4 +66,5 @@ openclaw chat !openclaw doctor ``` -使用 `openclaw config set` 或 `openclaw configure` 应用有针对性的修复,然后重新运行 `openclaw config validate`。参见 [终端 UI](/zh-CN/web/tui) 和 [配置](/zh-CN/cli/config)。 +使用 `openclaw config set` 或 `openclaw configure` 应用有针对性的修复,然后 +重新运行 `openclaw config validate`。请参见 [TUI](/zh-CN/web/tui) 和 [配置](/zh-CN/cli/config)。 diff --git a/docs/zh-CN/concepts/session-tool.md b/docs/zh-CN/concepts/session-tool.md index 5d427a7d9..3474db1ae 100644 --- a/docs/zh-CN/concepts/session-tool.md +++ b/docs/zh-CN/concepts/session-tool.md @@ -1,111 +1,144 @@ --- read_when: - 你想了解智能体拥有哪些会话工具 - - 你想配置跨会话访问或生成子智能体 + - 你想配置跨会话访问或子智能体生成 - 你想检查状态或控制已生成的子智能体 -summary: 用于跨会话状态、回忆、消息传递和子智能体编排的智能体工具 +summary: 用于跨会话状态、召回、消息传递和子智能体编排的智能体工具 title: 会话工具 x-i18n: - generated_at: "2026-04-23T01:35:27Z" + generated_at: "2026-04-23T07:05:32Z" model: gpt-5.4 provider: openai - source_hash: d99408f3052f4fa461bc26bf79456e7f852069ec101b9d593442cef6dd20a3ac + source_hash: cd8b545429726d0880e6086ba7190497861bf3f3e1e88d53cb38ef9e5e4468c6 source_path: concepts/session-tool.md workflow: 15 --- # 会话工具 -OpenClaw 为智能体提供工具,以便跨会话工作、检查状态并编排子智能体。 +OpenClaw 为智能体提供工具,用于跨会话工作、检查状态以及编排子智能体。 ## 可用工具 -| 工具 | 作用 | -| ------------------ | --------------------------------------------------------------------------- | -| `sessions_list` | 列出会话,并可选使用过滤器(kind、label、agent、最近活动时间、预览) | -| `sessions_history` | 读取特定会话的转录记录 | -| `sessions_send` | 向另一个会话发送消息,并可选择等待 | -| `sessions_spawn` | 为后台工作生成一个隔离的子智能体会话 | -| `sessions_yield` | 结束当前轮次,并等待后续的子智能体结果 | -| `subagents` | 列出、引导或终止当前会话已生成的子智能体 | -| `session_status` | 显示一个类似 `/status` 的卡片,并可选择为单个会话设置模型覆盖 | +| 工具 | 功能 | +| ------------------ | -------------------------------------------------------------------------- | +| `sessions_list` | 列出会话,可附带可选过滤条件(类型、标签、智能体、最近活动、预览) | +| `sessions_history` | 读取特定会话的对话记录 | +| `sessions_send` | 向另一个会话发送消息,并可选择等待 | +| `sessions_spawn` | 为后台工作生成一个隔离的子智能体会话 | +| `sessions_yield` | 结束当前轮次,并等待后续的子智能体结果 | +| `subagents` | 列出、引导或终止为该会话生成的子智能体 | +| `session_status` | 显示类似 `/status` 的卡片,并可选择为每个会话设置模型覆盖 | ## 列出和读取会话 -`sessions_list` 会返回会话及其 key、agentId、kind、channel、model、token 计数和时间戳。你可以按 kind(`main`、`group`、`cron`、`hook`、`node`)、精确的 `label`、精确的 `agentId`、搜索文本或最近活动时间(`activeMinutes`)进行筛选。当你需要类似邮箱收件箱的分诊视图时,它还可以请求派生标题、最后一条消息预览或限定数量的最近消息。预览转录读取会被限制在当前配置的会话工具可见性策略允许看到的会话范围内。 +`sessions_list` 会返回会话及其键名、agentId、类型、渠道、模型、 +token 计数和时间戳。可按类型(`main`、`group`、`cron`、`hook`、 +`node`)、精确 `label`、精确 `agentId`、搜索文本或最近活动时间 +(`activeMinutes`)过滤。当你需要类似邮箱的分流排查时,它还可以为每一行请求 +受可见性范围限制的派生标题、最后一条消息预览片段,或有限数量的 +最近消息。派生标题和预览只会为调用方在当前配置的会话工具 +可见性策略下本来就可以看到的会话生成,因此无关会话会保持隐藏。 -`sessions_history` 会获取特定会话的对话转录记录。默认情况下,工具结果会被排除——传入 `includeTools: true` 可查看它们。返回的视图会被有意限制并经过安全过滤: +`sessions_history` 会获取特定会话的对话记录。 +默认情况下,工具结果会被排除——传入 `includeTools: true` 可查看它们。 +返回的视图会被有意限制并经过安全过滤: -- 在回忆前,assistant 文本会被规范化: +- 助手文本在召回前会被规范化: - 会移除 thinking 标签 - - 会移除 `` / `` 脚手架区块 - - 会移除纯文本工具调用 XML 负载区块,例如 `...`、`...`、`...` 和 `...`,也包括那些被截断且未正常闭合的负载 - - 会移除降级后的工具调用/结果脚手架,例如 `[Tool Call: ...]`、`[Tool Result ...]` 和 `[Historical context ...]` - - 会移除泄露的模型控制 token,例如 `<|assistant|>`、其他 ASCII `<|...|>` token,以及全角 `<|...|>` 变体 - - 会移除格式错误的 MiniMax 工具调用 XML,例如 `` / `` -- 在返回前,类似凭证/token 的文本会被脱敏 -- 长文本区块会被截断 -- 对于非常大的历史记录,可能会丢弃较早的行,或将超大的单行替换为 `[sessions_history omitted: message too large]` -- 该工具会报告摘要标记,例如 `truncated`、`droppedMessages`、`contentTruncated`、`contentRedacted` 和 `bytes` + - 会移除 `` / `` 脚手架块 + - 会移除纯文本工具调用 XML 负载块,例如 `...`、 + `...`、`...` 和 + `...`,包括那些从未正常闭合的截断负载 + - 会移除降级后的工具调用/结果脚手架,例如 `[Tool Call: ...]`、 + `[Tool Result ...]` 和 `[Historical context ...]` + - 会移除泄露的模型控制 token,例如 `<|assistant|>`、其他 ASCII + `<|...|>` token,以及全角变体 `<|...|>` + - 会移除格式错误的 MiniMax 工具调用 XML,例如 `` / + `` +- 返回前会对类似凭证/令牌的文本进行脱敏 +- 过长文本块会被截断 +- 超大的历史记录可能会丢弃较早的行,或将超大行替换为 + `[sessions_history omitted: message too large]` +- 该工具会报告摘要标志,例如 `truncated`、`droppedMessages`、 + `contentTruncated`、`contentRedacted` 和 `bytes` -这两个工具都接受 **会话 key**(例如 `"main"`)或来自之前列表调用的 **会话 ID**。 +这两个工具都接受**会话键名**(例如 `"main"`)或来自之前 list 调用的 +**会话 ID**。 -如果你需要精确到字节、完全一致的转录记录,请直接检查磁盘上的转录文件,而不要把 `sessions_history` 当作原始转储使用。 +如果你需要精确到字节级一致的原始对话记录,请检查磁盘上的转录文件, +不要将 `sessions_history` 当作原始转储使用。 ## 发送跨会话消息 `sessions_send` 会向另一个会话投递消息,并可选择等待响应: -- **只发送不等待:** 设置 `timeoutSeconds: 0` 以入队并立即返回。 -- **等待回复:** 设置一个超时时间,并以内联方式获取响应。 +- **发送后不管:** 设置 `timeoutSeconds: 0` 以入队后立即返回。 +- **等待回复:** 设置超时时间,并以内联方式获得响应。 -目标响应后,OpenClaw 可以运行一个**回复往返循环**,其中智能体会交替发送消息(最多 5 轮)。目标智能体可以回复 `REPLY_SKIP` 以提前停止。 +目标响应后,OpenClaw 可以运行一个**回复往返循环**,让多个 +智能体轮流发送消息(最多 5 轮)。目标智能体可以回复 +`REPLY_SKIP` 以提前停止。 -## 状态与编排辅助工具 +## 状态和编排辅助工具 -`session_status` 是用于当前会话或另一个可见会话的轻量级 `/status` 等效工具。它会报告用量、时间、模型/运行时状态,以及存在时所关联的后台任务上下文。与 `/status` 一样,它可以从最新的转录 usage 条目中回填稀疏的 token/cache 计数器,而 `model=default` 会清除单个会话的覆盖设置。 +`session_status` 是用于当前或其他可见会话的轻量级 `/status` 等效工具。 +它会报告使用情况、时间、模型/运行时状态,以及存在时的已关联后台任务上下文。 +与 `/status` 一样,它可以从最近的对话记录使用条目中回填稀疏的 token/缓存计数, +并且 `model=default` 会清除每会话覆盖。 -`sessions_yield` 会有意结束当前轮次,以便下一条消息成为你正在等待的后续事件。在生成子智能体后,如果你希望完成结果作为下一条消息到达,而不是构建轮询循环,就可以使用它。 +`sessions_yield` 会有意结束当前轮次,以便下一条消息可以成为 +你正在等待的后续事件。在生成子智能体后,如果你希望完成结果作为下一条消息到达, +而不是构建轮询循环,请使用它。 -`subagents` 是用于已生成的 OpenClaw 子智能体的控制平面辅助工具。它支持: +`subagents` 是用于已生成 OpenClaw +子智能体的控制平面辅助工具。它支持: -- `action: "list"`,用于检查活跃/最近运行 -- `action: "steer"`,用于向正在运行的子任务发送后续指导 -- `action: "kill"`,用于停止一个子任务或 `all` +- `action: "list"`:检查活跃/最近运行 +- `action: "steer"`:向正在运行的子智能体发送后续引导 +- `action: "kill"`:停止某个子智能体或 `all` ## 生成子智能体 -`sessions_spawn` 会为后台任务创建一个隔离的会话。它始终是非阻塞的——会立即返回一个 `runId` 和 `childSessionKey`。 +`sessions_spawn` 会为后台任务创建一个隔离会话。它始终 +是非阻塞的——会立即返回 `runId` 和 `childSessionKey`。 -关键选项包括: +关键选项: - `runtime: "subagent"`(默认)或 `"acp"`,用于外部 harness 智能体。 - 为子会话设置 `model` 和 `thinking` 覆盖。 -- `thread: true`,用于将生成绑定到聊天线程(Discord、Slack 等)。 -- `sandbox: "require"`,用于对子任务强制启用沙箱隔离。 +- `thread: true` 可将生成绑定到聊天线程(Discord、Slack 等)。 +- `sandbox: "require"` 可对该子会话强制启用沙箱隔离。 -默认的叶子子智能体不会获得会话工具。当 `maxSpawnDepth >= 2` 时,深度为 1 的编排型子智能体还会额外获得 `sessions_spawn`、`subagents`、`sessions_list` 和 `sessions_history`,以便它们管理自己的子任务。叶子运行仍然不会获得递归编排工具。 +默认的叶子子智能体不会获得会话工具。当 +`maxSpawnDepth >= 2` 时,深度为 1 的编排型子智能体还会额外获得 +`sessions_spawn`、`subagents`、`sessions_list` 和 `sessions_history`, +以便它们管理自己的子级。叶子运行仍然不会获得递归 +编排工具。 -完成后,announce 步骤会将结果发布到请求方的渠道。完成交付会尽可能保留已绑定的线程/主题路由;如果完成来源只标识了一个渠道,OpenClaw 仍可复用请求方会话中存储的路由(`lastChannel` / `lastTo`)来进行直接交付。 +完成后,公告步骤会将结果发布到请求方的渠道。 +完成投递会在可用时保留已绑定的线程/话题路由,并且如果完成来源 +只标识了一个渠道,OpenClaw 仍然可以复用请求方会话中已存储的路由 +(`lastChannel` / `lastTo`)进行直接投递。 -有关 ACP 特定行为,请参见 [ACP 智能体](/zh-CN/tools/acp-agents)。 +有关 ACP 专用行为,请参见 [ACP Agents](/zh-CN/tools/acp-agents)。 ## 可见性 -会话工具的作用域经过限制,以控制智能体可以看到的内容: +会话工具具有作用域限制,以限制智能体可见的内容: -| 级别 | 范围 | -| ------- | ---------------------------------------- | -| `self` | 仅当前会话 | -| `tree` | 当前会话 + 已生成的子智能体 | -| `agent` | 该智能体的所有会话 | -| `all` | 所有会话(如果已配置,也包括跨智能体) | +| 级别 | 范围 | +| ------- | ---------------------------------- | +| `self` | 仅当前会话 | +| `tree` | 当前会话 + 已生成的子智能体 | +| `agent` | 该智能体的所有会话 | +| `all` | 所有会话(如果已配置,则跨智能体) | -默认级别为 `tree`。沙箱隔离会话无论配置如何都会被限制为 `tree`。 +默认值为 `tree`。沙箱隔离会话无论配置如何都会被限制为 `tree`。 ## 延伸阅读 - [会话管理](/zh-CN/concepts/session) -- 路由、生命周期、维护 -- [ACP 智能体](/zh-CN/tools/acp-agents) -- 外部 harness 生成 +- [ACP Agents](/zh-CN/tools/acp-agents) -- 外部 harness 生成 - [多智能体](/zh-CN/concepts/multi-agent) -- 多智能体架构 -- [Gateway 网关配置](/zh-CN/gateway/configuration) -- 会话工具配置选项 +- [Gateway Configuration](/zh-CN/gateway/configuration) -- 会话工具配置项 diff --git a/docs/zh-CN/gateway/cli-backends.md b/docs/zh-CN/gateway/cli-backends.md index 639a0fdfb..3b50ce212 100644 --- a/docs/zh-CN/gateway/cli-backends.md +++ b/docs/zh-CN/gateway/cli-backends.md @@ -1,41 +1,43 @@ --- read_when: - - 当 API 提供商失败时,你希望有一个可靠的回退方案 + - 当 API 提供商失效时,你希望有一个可靠的回退方案 - 你正在运行 Codex CLI 或其他本地 AI CLI,并希望复用它们 - 你想了解用于 CLI 后端工具访问的 MCP loopback bridge -summary: CLI 后端:带可选 MCP 工具桥接的本地 AI CLI 回退方案 +summary: CLI 后端:本地 AI CLI 回退,支持可选的 MCP 工具桥接 title: CLI 后端 x-i18n: - generated_at: "2026-04-23T03:39:22Z" + generated_at: "2026-04-23T07:05:28Z" model: gpt-5.4 provider: openai - source_hash: d36aea09a97b980e6938e12ea3bb5c01aa5f6c4275879d51879e48d5a2225fb2 + source_hash: 475923b36e4580d3e4e57014ff2e6b89e9eb52c11b0a0ab1fc8241655b07836e source_path: gateway/cli-backends.md workflow: 15 --- # CLI 后端(回退运行时) -当 API 提供商不可用、受到速率限制,或暂时表现异常时,OpenClaw 可以运行**本地 AI CLI** 作为**纯文本回退方案**。这是一种有意保持保守的设计: +当 API 提供商宕机、被限流或暂时异常时,OpenClaw 可以运行**本地 AI CLI** 作为**纯文本回退**。这是一种有意保守的设计: -- **不会直接注入 OpenClaw 工具**,但设置了 `bundleMcp: true` 的后端可以通过 loopback MCP bridge 接收 Gateway 网关工具。 -- 对支持的 CLI 提供 **JSONL 流式传输**。 -- **支持会话**(因此后续轮次能够保持连贯)。 +- **OpenClaw 工具不会被直接注入**,但设置了 `bundleMcp: true` 的后端可以通过 loopback MCP bridge 接收 gateway 工具。 +- 为支持该能力的 CLI 提供 **JSONL 流式传输**。 +- **支持会话**(因此后续轮次能保持连贯)。 - 如果 CLI 接受图像路径,**图像可以透传**。 -这被设计为一种**安全兜底机制**,而不是主要路径。当你希望获得“不管怎样都能工作”的文本响应,而不依赖外部 API 时,可以使用它。 +这被设计为一种**安全网**,而不是主路径。当你希望在不依赖外部 API 的情况下获得“始终可用”的文本响应时,可以使用它。 -如果你需要完整的 harness 运行时,包括 ACP 会话控制、后台任务、线程/对话绑定以及持久化的外部编码会话,请改用 [ACP Agents](/zh-CN/tools/acp-agents)。CLI 后端不是 ACP。 +如果你需要具备 ACP 会话控制、后台任务、线程/会话绑定以及持久化外部编码会话的完整 harness 运行时,请改用 [ACP Agents](/zh-CN/tools/acp-agents)。CLI 后端不是 ACP。 ## 面向初学者的快速开始 -你可以**无需任何配置**使用 Codex CLI(内置的 OpenAI 插件会注册一个默认后端): +你可以**无需任何配置**使用 Codex CLI(内置 OpenAI 插件 +会注册一个默认后端): ```bash openclaw agent --message "hi" --model codex-cli/gpt-5.4 ``` -如果你的 Gateway 网关运行在 launchd/systemd 下,且 PATH 很精简,只需添加命令路径: +如果你的 gateway 在 launchd/systemd 下运行,且 PATH 很精简,只需添加 +命令路径: ```json5 { @@ -51,13 +53,15 @@ openclaw agent --message "hi" --model codex-cli/gpt-5.4 } ``` -就是这样。除了 CLI 本身之外,不需要额外的密钥或认证配置。 +就这样。无需 key,也无需除 CLI 本身之外的额外身份验证配置。 -如果你在 Gateway 网关主机上将某个内置 CLI 后端用作**主要消息提供商**,当你的配置在模型引用中或在 `agents.defaults.cliBackends` 下显式引用该后端时,OpenClaw 现在会自动加载其所属的内置插件。 +如果你在 gateway 主机上将某个内置 CLI 后端用作**主要消息提供商**,当你的配置 +在模型引用中或在 +`agents.defaults.cliBackends` 下显式引用该后端时,OpenClaw 现在会自动加载其所属的内置插件。 -## 将其用作回退方案 +## 将其用作回退 -将一个 CLI 后端添加到你的回退列表中,这样它只会在主模型失败时运行: +将 CLI 后端添加到你的回退列表中,这样它只会在主模型失败时运行: ```json5 { @@ -78,8 +82,9 @@ openclaw agent --message "hi" --model codex-cli/gpt-5.4 说明: -- 如果你使用 `agents.defaults.models`(允许列表),你也必须将 CLI 后端模型包含进去。 -- 如果主提供商失败(认证、速率限制、超时),OpenClaw 将接着尝试 CLI 后端。 +- 如果你使用 `agents.defaults.models`(允许列表),也必须在其中包含你的 CLI 后端模型。 +- 如果主提供商失败(身份验证、限流、超时),OpenClaw 将 + 接着尝试 CLI 后端。 ## 配置概览 @@ -89,7 +94,7 @@ openclaw agent --message "hi" --model codex-cli/gpt-5.4 agents.defaults.cliBackends ``` -每个条目都以**提供商 id** 作为键(例如 `codex-cli`、`my-cli`)。 +每个条目都以一个**提供商 id** 作为键(例如 `codex-cli`、`my-cli`)。 该提供商 id 会成为你的模型引用左侧部分: ``` @@ -120,7 +125,7 @@ agents.defaults.cliBackends sessionMode: "existing", sessionIdFields: ["session_id", "conversation_id"], systemPromptArg: "--system", - // 类似 Codex 风格的 CLI 也可以改为指向提示词文件: + // 对于 Codex 风格的 CLI,也可以改为指向 prompt 文件: // systemPromptFileConfigArg: "-c", // systemPromptFileConfigKey: "model_instructions_file", systemPromptWhen: "first", @@ -136,61 +141,58 @@ agents.defaults.cliBackends ## 工作原理 -1. 根据提供商前缀(`codex-cli/...`)**选择一个后端**。 -2. 使用相同的 OpenClaw 提示词和工作区上下文**构建系统提示词**。 -3. 使用会话 id(如果支持)**执行 CLI**,以便保持历史一致。 - 内置的 `claude-cli` 后端会为每个 OpenClaw 会话保持一个 Claude stdio 进程存活, - 并通过 stream-json stdin 发送后续轮次。 -4. **解析输出**(JSON 或纯文本),并返回最终文本。 -5. 按后端**持久化会话 id**,以便后续轮次复用同一个 CLI 会话。 +1. 根据提供商前缀选择后端(`codex-cli/...`)。 +2. 使用相同的 OpenClaw prompt + 工作区上下文构建系统 prompt。 +3. 使用会话 id 执行 CLI(如果支持),以保持历史一致。 + 内置的 `claude-cli` 后端会为每个 + OpenClaw 会话保持一个 Claude stdio 进程存活,并通过 stream-json stdin 发送后续轮次。 +4. 解析输出(JSON 或纯文本),并返回最终文本。 +5. 为每个后端持久化会话 id,使后续轮次复用相同的 CLI 会话。 -内置的 Anthropic `claude-cli` 后端现已再次获得支持。Anthropic 工作人员 -告诉我们,再次允许 OpenClaw 风格的 Claude CLI 用法,因此除非 Anthropic 发布 -新的策略,否则 OpenClaw 会将用于此集成的 `claude -p` 用法视为已获认可。 +内置的 Anthropic `claude-cli` 后端现已重新支持。Anthropic 工作人员 +告诉我们,OpenClaw 风格的 Claude CLI 用法再次被允许,因此除非 Anthropic 发布 +新政策,否则 OpenClaw 会将用于此集成的 `claude -p` 用法视为已获许可。 -内置的 OpenAI `codex-cli` 后端会通过 +内置的 OpenAI `codex-cli` 后端通过 Codex 的 `model_instructions_file` 配置覆盖项(`-c -model_instructions_file="..."`)传递 OpenClaw 的系统提示词。Codex 不提供类似 Claude 的 -`--append-system-prompt` 标志,因此 OpenClaw 会在每次新的 Codex CLI 会话中 -将组装后的提示词写入一个临时文件。 +model_instructions_file="..."`)传递 OpenClaw 的系统 prompt。Codex 不提供类似 Claude 的 +`--append-system-prompt` 标志,因此 OpenClaw 会为每个新的 Codex CLI 会话将组装后的 prompt 写入一个 +临时文件。 内置的 Anthropic `claude-cli` 后端会通过两种方式接收 OpenClaw 的 Skills 快照: -一是在附加的系统提示词中包含精简版 OpenClaw Skills 目录,二是通过 -`--plugin-dir` 传入一个临时 Claude Code 插件。该插件只包含对该智能体/会话 -符合条件的 Skills,因此 Claude Code 原生的 skill 解析器看到的就是 -与 OpenClaw 否则会在提示词中声明的同一组过滤后内容。对于 skill 的环境变量/API 密钥覆盖, -OpenClaw 仍会将其应用到该次运行的子进程环境中。 +一种是附加系统 prompt 中的紧凑型 OpenClaw Skills 目录,另一种是 +通过 `--plugin-dir` 传入的临时 Claude Code 插件。该插件仅包含当前智能体/会话可用的 Skills,因此 Claude Code 的原生 skill 解析器看到的过滤结果,与 OpenClaw 原本会在 prompt 中公开的集合保持一致。Skill 环境变量/API key 覆盖仍然会由 OpenClaw 应用到该次运行的子进程环境中。 ## 会话 - 如果 CLI 支持会话,请设置 `sessionArg`(例如 `--session-id`)或 - `sessionArgs`(占位符为 `{sessionId}`),当该 ID 需要插入 - 多个标志时使用。 -- 如果 CLI 使用具有不同标志的**恢复子命令**,请设置 - `resumeArgs`(恢复时替换 `args`),以及可选的 `resumeOutput` - (用于非 JSON 的恢复输出)。 + `sessionArgs`(占位符 `{sessionId}`),适用于需要将 ID 插入 + 多个标志的场景。 +- 如果 CLI 使用带有不同标志的**恢复子命令**,请设置 + `resumeArgs`(恢复时替换 `args`),并可选设置 `resumeOutput` + (用于非 JSON 恢复)。 - `sessionMode`: - `always`:始终发送会话 id(如果未存储,则生成新的 UUID)。 - - `existing`:仅当之前存储过会话 id 时才发送。 + - `existing`:仅当之前已存储会话 id 时才发送。 - `none`:从不发送会话 id。 - `claude-cli` 默认使用 `liveSession: "claude-stdio"`、`output: "jsonl"`, - 以及 `input: "stdin"`,因此在其处于活动状态时,后续轮次会复用 - 存活中的 Claude 进程。如果 Gateway 网关重启或空闲进程退出, - OpenClaw 会从已存储的 Claude 会话 id 恢复。 -- 已存储的 CLI 会话属于提供商侧的连续性。隐式的每日会话重置 - 不会切断它们;`/reset` 和显式的 `session.reset` 策略仍然会切断。 + 和 `input: "stdin"`,因此只要该 Claude 进程仍然活跃,后续轮次就会复用这个活动进程。现在 warm stdio 已是默认值,包括那些省略传输字段的自定义配置。 + 如果 Gateway 网关重启,或空闲进程退出,OpenClaw 会从已存储的 Claude 会话 id 恢复。已存储的会话 + id 会先针对现有、可读的项目 transcript 进行验证后再恢复,因此虚假的绑定会以 `reason=transcript-missing` + 被清除,而不是在 `--resume` 下静默启动一个新的 Claude CLI 会话。 +- 已存储的 CLI 会话属于提供商拥有的连续性。隐式的每日会话 + 重置不会切断它们;`/reset` 和显式 `session.reset` 策略仍然会切断。 -序列化说明: +串行化说明: - `serialize: true` 会保持同一通道中的运行顺序。 -- 大多数 CLI 会在同一个提供商通道上串行执行。 -- 当所选认证身份发生变化时,OpenClaw 会放弃复用已存储的 CLI 会话, - 包括认证 profile id 变化、静态 API 密钥变化、静态令牌变化, - 或者当 CLI 暴露该信息时,OAuth 账户身份发生变化。OAuth access 和 refresh token 的轮换 - 不会切断已存储的 CLI 会话。如果某个 CLI 没有暴露稳定的 OAuth 账户 id, - OpenClaw 会让该 CLI 自行强制执行恢复权限。 +- 大多数 CLI 会在一个提供商通道中串行执行。 +- 当所选身份验证身份发生变化时,OpenClaw 会丢弃已存储 CLI 会话的复用, + 包括 auth profile id 变化、静态 API key 变化、静态 token 变化,或 + 当 CLI 暴露了稳定 OAuth 账户身份时该身份的变化。OAuth access 和 refresh token + 的轮换不会切断已存储的 CLI 会话。如果某个 CLI 不暴露稳定的 OAuth 账户 id,OpenClaw 会让该 CLI 自行强制执行恢复权限。 ## 图像(透传) @@ -202,29 +204,28 @@ imageMode: "repeat" ``` OpenClaw 会将 base64 图像写入临时文件。如果设置了 `imageArg`,这些 -路径会作为 CLI 参数传入。如果未设置 `imageArg`,OpenClaw 会将 -文件路径附加到提示词中(路径注入),这对于会从普通路径自动加载 -本地文件的 CLI 来说已经足够。 +路径会作为 CLI 参数传递。如果缺少 `imageArg`,OpenClaw 会将 +文件路径附加到 prompt 中(路径注入),这对于那些会从普通路径自动 +加载本地文件的 CLI 已经足够。 ## 输入 / 输出 -- `output: "json"`(默认)会尝试解析 JSON 并提取文本 + 会话 id。 -- 对于 Gemini CLI 的 JSON 输出,当 `usage` 缺失或为空时, - OpenClaw 会从 `response` 读取回复文本,并从 `stats` 读取 - 使用量。 +- `output: "json"`(默认)会尝试解析 JSON,并提取文本 + 会话 id。 +- 对于 Gemini CLI 的 JSON 输出,当 `usage` 缺失或为空时,OpenClaw 会从 `response` 读取回复文本,并从 + `stats` 读取用量。 - `output: "jsonl"` 会解析 JSONL 流(例如 Codex CLI `--json`),并提取最终智能体消息以及存在时的会话 标识符。 -- `output: "text"` 会将 stdout 视为最终响应。 +- `output: "text"` 将 stdout 视为最终响应。 输入模式: -- `input: "arg"`(默认)会将提示词作为最后一个 CLI 参数传递。 -- `input: "stdin"` 会通过 stdin 发送提示词。 -- 如果提示词非常长并且设置了 `maxPromptArgChars`,则会改用 stdin。 +- `input: "arg"`(默认)将 prompt 作为最后一个 CLI 参数传递。 +- `input: "stdin"` 通过 stdin 发送 prompt。 +- 如果 prompt 很长且设置了 `maxPromptArgChars`,则会使用 stdin。 -## 默认值(插件拥有) +## 默认值(由插件拥有) -内置的 OpenAI 插件也为 `codex-cli` 注册了一个默认值: +内置 OpenAI 插件还为 `codex-cli` 注册了一个默认值: - `command: "codex"` - `args: ["exec","--json","--color","never","--sandbox","workspace-write","--skip-git-repo-check"]` @@ -235,7 +236,7 @@ OpenClaw 会将 base64 图像写入临时文件。如果设置了 `imageArg`, - `imageArg: "--image"` - `sessionMode: "existing"` -内置的 Google 插件也为 `google-gemini-cli` 注册了一个默认值: +内置 Google 插件还为 `google-gemini-cli` 注册了一个默认值: - `command: "gemini"` - `args: ["--output-format", "json", "--prompt", "{prompt}"]` @@ -246,31 +247,31 @@ OpenClaw 会将 base64 图像写入临时文件。如果设置了 `imageArg`, - `sessionMode: "existing"` - `sessionIdFields: ["session_id", "sessionId"]` -前提条件:本地 Gemini CLI 必须已安装,并且可通过 -`PATH` 中的 `gemini` 使用(`brew install gemini-cli` 或 +前提条件:本地 Gemini CLI 必须已安装,并且可作为 +`gemini` 在 `PATH` 中使用(`brew install gemini-cli` 或 `npm install -g @google/gemini-cli`)。 Gemini CLI JSON 说明: - 回复文本从 JSON 的 `response` 字段读取。 -- 当 `usage` 不存在或为空时,使用量会回退到 `stats`。 -- `stats.cached` 会被规范化为 OpenClaw 的 `cacheRead`。 -- 如果 `stats.input` 缺失,OpenClaw 会根据 +- 当 `usage` 缺失或为空时,用量会回退到 `stats`。 +- `stats.cached` 会被规范化为 OpenClaw `cacheRead`。 +- 如果 `stats.input` 缺失,OpenClaw 会从 `stats.input_tokens - stats.cached` 推导输入 token 数。 仅在需要时覆盖(常见情况:使用绝对 `command` 路径)。 ## 插件拥有的默认值 -CLI 后端默认值现已成为插件表面的一部分: +CLI 后端默认值现在已成为插件表面的一部分: -- 插件通过 `api.registerCliBackend(...)` 注册它们。 -- 后端的 `id` 会成为模型引用中的提供商前缀。 +- 插件使用 `api.registerCliBackend(...)` 注册它们。 +- 后端 `id` 会成为模型引用中的提供商前缀。 - `agents.defaults.cliBackends.` 中的用户配置仍会覆盖插件默认值。 -- 后端特定的配置清理由插件通过可选的 - `normalizeConfig` hook 负责。 +- 后端特定的配置清理仍由插件通过可选的 + `normalizeConfig` hook 拥有。 -需要进行轻量提示词/消息兼容性调整的插件,可以声明双向文本转换,而无需替换提供商或 CLI 后端: +需要微小 prompt/消息兼容性 shim 的插件,可以声明双向文本转换,而无需替换提供商或 CLI 后端: ```typescript api.registerTextTransforms({ @@ -287,17 +288,16 @@ api.registerTextTransforms({ }); ``` -`input` 会重写传递给 CLI 的系统提示词和用户提示词。`output` -会在 OpenClaw 处理其自身控制标记和渠道投递之前, -重写流式 assistant 增量和解析后的最终文本。 +`input` 会重写传递给 CLI 的系统 prompt 和用户 prompt。`output` +会在 OpenClaw 处理其自身控制标记和渠道投递之前,重写流式 assistant 增量和解析后的最终文本。 -对于会输出兼容 Claude Code stream-json 的 JSONL 的 CLI, -请在该后端的配置上设置 `jsonlDialect: "claude-stream-json"`。 +对于输出 Claude Code stream-json 兼容 JSONL 的 CLI,请在该后端配置上设置 +`jsonlDialect: "claude-stream-json"`。 -## 内置 MCP 覆盖层 +## Bundle MCP 覆盖层 -CLI 后端**不会**直接接收 OpenClaw 工具调用,但后端可以通过 -`bundleMcp: true` 选择启用生成的 MCP 配置覆盖层。 +CLI 后端**不会**直接接收 OpenClaw 工具调用,但某个后端可以 +通过 `bundleMcp: true` 选择加入自动生成的 MCP 配置覆盖层。 当前内置行为: @@ -305,33 +305,32 @@ CLI 后端**不会**直接接收 OpenClaw 工具调用,但后端可以通过 - `codex-cli`:为 `mcp_servers` 提供内联配置覆盖 - `google-gemini-cli`:生成 Gemini 系统设置文件 -启用 bundle MCP 后,OpenClaw 会: +启用 bundle MCP 时,OpenClaw 会: -- 启动一个 loopback HTTP MCP 服务器,向 CLI 进程暴露 Gateway 网关工具 -- 使用按会话生成的令牌(`OPENCLAW_MCP_TOKEN`)对桥接进行认证 -- 将工具访问范围限制在当前会话、账户和渠道上下文内 +- 启动一个 loopback HTTP MCP 服务器,将 gateway 工具暴露给 CLI 进程 +- 使用每会话 token(`OPENCLAW_MCP_TOKEN`)对 bridge 进行身份验证 +- 将工具访问范围限定到当前会话、账户和渠道上下文 - 为当前工作区加载已启用的 bundle-MCP 服务器 -- 将其与任何现有的后端 MCP 配置/设置结构合并 +- 将它们与任何现有的后端 MCP 配置/设置结构合并 - 使用所属扩展中由后端拥有的集成模式重写启动配置 -如果没有启用任何 MCP 服务器,当某个后端选择启用 bundle MCP 时, -OpenClaw 仍会注入严格配置,以便后台运行保持隔离。 +如果未启用任何 MCP 服务器,当某个后端选择启用 bundle MCP 时,OpenClaw 仍会注入严格配置,以便后台运行保持隔离。 ## 限制 -- **没有直接的 OpenClaw 工具调用。** OpenClaw 不会将工具调用注入到 - CLI 后端协议中。后端只有在选择启用 - `bundleMcp: true` 时才会看到 Gateway 网关工具。 -- **流式传输取决于后端。** 某些后端会流式输出 JSONL;另一些则会 - 缓冲到退出时再输出。 +- **不支持直接 OpenClaw 工具调用。** OpenClaw 不会将工具调用注入到 + CLI 后端协议中。只有在后端选择加入 + `bundleMcp: true` 时,它们才会看到 gateway 工具。 +- **流式传输是后端特定的。** 有些后端流式输出 JSONL;另一些则会缓冲 + 直到退出。 - **结构化输出** 取决于 CLI 的 JSON 格式。 -- **Codex CLI 会话** 通过文本输出恢复(不是 JSONL),其结构性 - 不如初始的 `--json` 运行。OpenClaw 会话仍然可以正常工作。 +- **Codex CLI 会话** 通过文本输出恢复(不是 JSONL),其结构化程度 + 低于初始 `--json` 运行。不过 OpenClaw 会话本身仍可正常工作。 ## 故障排除 - **找不到 CLI**:将 `command` 设置为完整路径。 -- **模型名称错误**:使用 `modelAliases` 将 `provider/model` 映射为 CLI 模型。 +- **模型名称错误**:使用 `modelAliases` 将 `provider/model` 映射到 CLI 模型。 - **没有会话连续性**:确保已设置 `sessionArg`,并且 `sessionMode` 不是 - `none`(Codex CLI 目前无法使用 JSON 输出进行恢复)。 + `none`(Codex CLI 当前无法使用 JSON 输出恢复)。 - **图像被忽略**:设置 `imageArg`(并确认 CLI 支持文件路径)。 diff --git a/docs/zh-CN/gateway/configuration.md b/docs/zh-CN/gateway/configuration.md index 82256d898..d5b0dc7f4 100644 --- a/docs/zh-CN/gateway/configuration.md +++ b/docs/zh-CN/gateway/configuration.md @@ -1,35 +1,37 @@ --- read_when: - 首次设置 OpenClaw - - 查找常见的配置模式 + - 查找常见配置模式 - 导航到特定配置章节 -summary: 配置概览:常见任务、快速设置,以及完整参考的链接 +summary: 配置概览:常见任务、快速开始以及完整参考的链接 title: 配置 x-i18n: - generated_at: "2026-04-22T23:04:29Z" + generated_at: "2026-04-23T07:05:32Z" model: gpt-5.4 provider: openai - source_hash: 39a9f521b124026a32064464b6d0ce1f93597c523df6839fde37d61e597bcce7 + source_hash: 8130d29e9fbf5104d0a76f26b26186b6aab2b211030b8c8ba0d1131daf890993 source_path: gateway/configuration.md workflow: 15 --- # 配置 -OpenClaw 会从 `~/.openclaw/openclaw.json` 读取可选的 **JSON5** 配置。 -当前使用的配置路径必须是常规文件。对于由 OpenClaw 管理的写入操作,不支持使用符号链接的 `openclaw.json` -布局;原子写入可能会替换该路径,而不是保留符号链接。如果你将配置保存在默认状态目录之外,请将 `OPENCLAW_CONFIG_PATH` 直接指向真实文件。 +OpenClaw 会从 `~/.openclaw/openclaw.json` 读取一个可选的 **JSON5** 配置。 +当前活动的配置路径必须是一个常规文件。对于 OpenClaw 自有写入操作,不支持 +符号链接形式的 `openclaw.json` 布局;原子写入可能会替换该路径, +而不是保留符号链接。如果你将配置保存在默认状态目录之外,请将 +`OPENCLAW_CONFIG_PATH` 直接指向真实文件。 -如果该文件不存在,OpenClaw 会使用安全的默认设置。添加配置的常见原因包括: +如果该文件不存在,OpenClaw 会使用安全默认值。添加配置的常见原因包括: -- 连接渠道并控制谁可以向机器人发送消息 +- 连接渠道并控制谁可以向 bot 发送消息 - 设置模型、工具、沙箱隔离或自动化(cron、hooks) - 调整会话、媒体、网络或 UI -有关所有可用字段,请参阅[完整参考](/zh-CN/gateway/configuration-reference)。 +有关所有可用字段,请参见[完整参考](/zh-CN/gateway/configuration-reference)。 -**刚开始接触配置?** 可先运行 `openclaw onboard` 进行交互式设置,或查看[配置示例](/zh-CN/gateway/configuration-examples)指南,获取可直接复制粘贴的完整配置。 +**刚开始接触配置?** 从 `openclaw onboard` 开始进行交互式设置,或查看[配置示例](/zh-CN/gateway/configuration-examples)指南,获取完整的可复制粘贴配置。 ## 最小配置 @@ -47,7 +49,7 @@ OpenClaw 会从 `~/.openclaw/openclaw.json` 读取可选的 ```bash - openclaw onboard # 完整的新手引导流程 + openclaw onboard # 完整新手引导流程 openclaw configure # 配置向导 ``` @@ -58,68 +60,75 @@ OpenClaw 会从 `~/.openclaw/openclaw.json` 读取可选的 - 打开 [http://127.0.0.1:18789](http://127.0.0.1:18789),然后使用 **配置** 标签页。 + + 打开 [http://127.0.0.1:18789](http://127.0.0.1:18789) 并使用 **配置** 标签页。 Control UI 会根据实时配置 schema 渲染表单,其中包括字段 - `title` / `description` 文档元数据,以及在可用时提供的插件和渠道 schema, - 同时还提供 **原始 JSON** 编辑器作为兜底方式。对于下钻式 - UI 和其他工具,Gateway 网关 还会暴露 `config.schema.lookup`, - 以获取单个路径范围内的 schema 节点及其直接子节点摘要。 + `title` / `description` 文档元数据,以及在可用时的插件和渠道 schema, + 同时提供 **Raw JSON** 编辑器作为兜底方案。对于下钻式 + UI 和其他工具,gateway 还会暴露 `config.schema.lookup`, + 用于获取一个按路径限定的 schema 节点及其直接子节点摘要。 - 直接编辑 `~/.openclaw/openclaw.json`。Gateway 网关 会监视该文件并自动应用更改(参见[热重载](#config-hot-reload))。 + 直接编辑 `~/.openclaw/openclaw.json`。Gateway 网关会监视该文件并自动应用更改(参见[热重载](#config-hot-reload))。 ## 严格校验 -OpenClaw 仅接受与 schema 完全匹配的配置。未知键名、类型格式错误或无效值都会导致 Gateway 网关 **拒绝启动**。根级别唯一的例外是 `$schema`(字符串),这样编辑器才能附加 JSON Schema 元数据。 +OpenClaw 只接受完全符合 schema 的配置。未知键、类型格式错误或无效值都会导致 Gateway 网关**拒绝启动**。唯一的根级例外是 `$schema`(字符串),这样编辑器就可以附加 JSON Schema 元数据。 Schema 工具说明: -- `openclaw config schema` 会输出与 Control UI 和配置校验所使用的同一套 JSON Schema。 -- 将该 schema 输出视为 `openclaw.json` 的规范机器可读契约;本概览和配置参考是对它的总结。 -- 字段 `title` 和 `description` 的值会被带入 schema 输出,供编辑器和表单工具使用。 -- 嵌套对象、通配符(`*`)和数组项(`[]`)条目在存在对应字段文档时,会继承相同的文档元数据。 -- `anyOf` / `oneOf` / `allOf` 组合分支也会继承相同的文档元数据,因此联合 / 交叉变体会保留相同的字段帮助信息。 -- `config.schema.lookup` 会返回一个规范化的配置路径,包含一个浅层 - schema 节点(`title`、`description`、`type`、`enum`、`const`、常见边界条件 - 以及类似的校验字段)、匹配的 UI 提示元数据,以及直接子节点 +- `openclaw config schema` 会打印与 Control UI + 和配置校验所使用的同一套 JSON Schema。 +- 请将该 schema 输出视为 `openclaw.json` 的规范机器可读契约; + 本概览和配置参考只是对其进行总结。 +- 字段 `title` 和 `description` 的值会被带入 schema 输出中, + 供编辑器和表单工具使用。 +- 嵌套对象、通配符(`*`)和数组项(`[]`)条目会在存在匹配字段文档时, + 继承相同的文档元数据。 +- `anyOf` / `oneOf` / `allOf` 组合分支也会继承相同的文档 + 元数据,因此联合/交叉变体会保留相同的字段帮助信息。 +- `config.schema.lookup` 会返回一个规范化的配置路径及其浅层 + schema 节点(`title`、`description`、`type`、`enum`、`const`、常见边界 + 以及类似校验字段)、匹配的 UI 提示元数据和直接子节点 摘要,供下钻式工具使用。 -- 当 Gateway 网关 能加载当前 manifest 注册表时,会合并运行时插件 / 渠道 schema。 -- `pnpm config:docs:check` 会检测面向文档的配置基线工件与当前 schema 表面之间的漂移。 +- 当 gateway 能够加载当前 manifest 注册表时,会合并运行时插件/渠道 schema。 +- `pnpm config:docs:check` 会检测面向文档的配置基线产物 + 与当前 schema 表面之间的漂移。 当校验失败时: -- Gateway 网关 不会启动 +- Gateway 网关不会启动 - 只有诊断命令可用(`openclaw doctor`、`openclaw logs`、`openclaw health`、`openclaw status`) -- 运行 `openclaw doctor` 查看具体问题 -- 运行 `openclaw doctor --fix`(或 `--yes`)应用修复 +- 运行 `openclaw doctor` 查看精确问题 +- 运行 `openclaw doctor --fix`(或 `--yes`)以应用修复 -在成功启动后,Gateway 网关 还会保留一份可信的“最近一次已知正常”副本。如果 -之后在 OpenClaw 外部修改了 `openclaw.json`,并导致其不再通过校验,启动 -和热重载会将损坏的文件保留为带时间戳的 `.clobbered.*` 快照, -恢复“最近一次已知正常”副本,并以醒目的警告日志记录恢复原因。 -启动时的读取恢复也会将文件大小突然明显缩小、缺失配置元数据以及 -缺失 `gateway.mode` 视为关键的覆盖损坏特征,前提是“最近一次已知正常” -副本中原本包含这些字段。 -如果某条状态 / 日志行被意外地前置到原本有效的 JSON -配置之前,Gateway 网关 启动和 `openclaw doctor --fix` 可以去掉该前缀, -将受污染文件保留为 `.clobbered.*`,并继续使用恢复后的 +Gateway 网关还会在成功启动后保留一份可信的最近一次有效副本。如果 +之后 `openclaw.json` 在 OpenClaw 外部被修改并且不再通过校验,启动 +和热重载会将损坏文件保留为带时间戳的 `.clobbered.*` 快照, +恢复最近一次有效副本,并记录一条明显的警告,说明恢复原因。 +启动读取恢复还会将配置大小大幅缩小、缺少配置元数据以及 +缺少 `gateway.mode` 视为严重的破坏特征,前提是最近一次有效 +副本中原本有这些字段。 +如果某条状态/日志行被意外前置到原本有效的 JSON +配置之前,gateway 启动和 `openclaw doctor --fix` 可以剥离该前缀, +将受污染的文件保留为 `.clobbered.*`,并继续使用恢复后的 JSON。 -下一次主智能体回合还会收到一条系统事件警告,告知其 -配置已被恢复,且不得盲目重写。对于已校验通过的启动以及已接受的热重载, -“最近一次已知正常”副本都会更新,包括由 OpenClaw 管理的配置写入,前提是其持久化 -文件哈希仍与已接受写入一致。如果候选副本包含已脱敏的密钥 -占位符,例如 `***` 或缩短后的令牌值,则会跳过提升。 +下一次主智能体回合也会收到一条系统事件警告,告知其 +配置已被恢复,不能盲目重写。在通过校验的启动之后,以及接受的热重载之后, +都会更新最近一次有效副本的提升状态,包括 +那些其持久化文件哈希仍与已接受写入匹配的 OpenClaw 自有配置写入。 +当候选副本包含已脱敏的密钥占位符, +如 `***` 或缩短后的令牌值时,将跳过提升。 ## 常见任务 - 每个渠道在 `channels.` 下都有自己的配置部分。设置步骤请参阅对应的专用渠道页面: + 每个渠道在 `channels.` 下都有自己的配置部分。设置步骤请参见对应渠道页面: - [WhatsApp](/zh-CN/channels/whatsapp) — `channels.whatsapp` - [Telegram](/zh-CN/channels/telegram) — `channels.telegram` @@ -150,7 +159,7 @@ JSON。 - 设置主模型和可选的回退模型: + 设置主模型和可选回退模型: ```json5 { @@ -169,31 +178,31 @@ JSON。 } ``` - - `agents.defaults.models` 定义模型目录,并作为 `/model` 的 allowlist。 - - 使用 `openclaw config set agents.defaults.models '' --strict-json --merge` 可在不移除现有模型的情况下添加 allowlist 条目。会移除条目的普通替换操作会被拒绝,除非你传入 `--replace`。 + - `agents.defaults.models` 定义模型目录,并充当 `/model` 的允许列表。 + - 使用 `openclaw config set agents.defaults.models '' --strict-json --merge` 可在不移除现有模型的情况下添加允许列表条目。如果普通替换会移除条目,则除非你传入 `--replace`,否则会被拒绝。 - 模型引用使用 `provider/model` 格式(例如 `anthropic/claude-opus-4-6`)。 - - `agents.defaults.imageMaxDimensionPx` 控制转录 / 工具图像的缩放下限(默认值为 `1200`);在大量截图的运行中,较低的值通常可减少视觉 token 使用量。 - - 关于在聊天中切换模型,请参阅[模型 CLI](/zh-CN/concepts/models);关于凭证轮换和回退行为,请参阅[模型故障切换](/zh-CN/concepts/model-failover)。 - - 对于自定义 / 自托管提供商,请参阅参考中的[自定义提供商](/zh-CN/gateway/configuration-reference#custom-providers-and-base-urls)。 + - `agents.defaults.imageMaxDimensionPx` 控制转录/工具图像缩放下采样(默认 `1200`);在大量截图运行中,较低值通常会减少视觉 token 使用量。 + - 在聊天中切换模型请参见[模型 CLI](/zh-CN/concepts/models),认证轮换和回退行为请参见[模型故障转移](/zh-CN/concepts/model-failover)。 + - 对于自定义/自托管提供商,请参见参考中的[自定义提供商](/zh-CN/gateway/configuration-reference#custom-providers-and-base-urls)。 - - 私信访问权限通过每个渠道的 `dmPolicy` 控制: + + 私信访问按渠道通过 `dmPolicy` 控制: - - `"pairing"`(默认):未知发送者会收到一个一次性配对码以供批准 - - `"allowlist"`:仅允许 `allowFrom` 中的发送者(或已配对的允许存储) + - `"pairing"`(默认):未知发送者会收到一个一次性配对码,用于批准 + - `"allowlist"`:仅允许 `allowFrom` 中的发送者(或已配对允许存储中的发送者) - `"open"`:允许所有入站私信(要求 `allowFrom: ["*"]`) - `"disabled"`:忽略所有私信 - 对于群组,请使用 `groupPolicy` + `groupAllowFrom` 或渠道特定的 allowlist。 + 对于群组,请使用 `groupPolicy` + `groupAllowFrom` 或特定渠道的允许列表。 - 每个渠道的详细信息请参阅[完整参考](/zh-CN/gateway/configuration-reference#dm-and-group-access)。 + 每个渠道的详细信息请参见[完整参考](/zh-CN/gateway/configuration-reference#dm-and-group-access)。 - 群组消息默认 **要求提及**。可按智能体配置模式: + 群组消息默认**要求提及**。按智能体配置模式: ```json5 { @@ -217,12 +226,12 @@ JSON。 - **元数据提及**:原生 @ 提及(WhatsApp 点按提及、Telegram @bot 等) - **文本模式**:`mentionPatterns` 中的安全正则模式 - - 每个渠道的覆盖项和自聊模式请参阅[完整参考](/zh-CN/gateway/configuration-reference#group-chat-mention-gating)。 + - 每个渠道的覆盖项和自聊模式请参见[完整参考](/zh-CN/gateway/configuration-reference#group-chat-mention-gating) - 使用 `agents.defaults.skills` 作为共享基线,然后用 `agents.list[].skills` 覆盖特定 + 对共享基线使用 `agents.defaults.skills`,然后通过 `agents.list[].skills` 覆盖特定 智能体: ```json5 @@ -232,7 +241,7 @@ JSON。 skills: ["github", "weather"], }, list: [ - { id: "writer" }, // 继承 github, weather + { id: "writer" }, // 继承 github、weather { id: "docs", skills: ["docs-search"] }, // 替换默认值 { id: "locked-down", skills: [] }, // 无 Skills ], @@ -242,14 +251,14 @@ JSON。 - 省略 `agents.defaults.skills` 表示默认不限制 Skills。 - 省略 `agents.list[].skills` 表示继承默认值。 - - 设置 `agents.list[].skills: []` 表示不启用任何 Skills。 - - 参阅 [Skills](/zh-CN/tools/skills)、[Skills 配置](/zh-CN/tools/skills-config),以及 + - 设置 `agents.list[].skills: []` 表示没有 Skills。 + - 参见 [Skills](/zh-CN/tools/skills)、[Skills 配置](/zh-CN/tools/skills-config) 和 [配置参考](/zh-CN/gateway/configuration-reference#agents-defaults-skills)。 - - 控制 Gateway 网关 对看起来已停滞的渠道执行重启的积极程度: + + 控制 gateway 重启看起来已陈旧渠道的激进程度: ```json5 { @@ -273,13 +282,13 @@ JSON。 - 设置 `gateway.channelHealthCheckMinutes: 0` 可全局禁用健康监控重启。 - `channelStaleEventThresholdMinutes` 应大于或等于检查间隔。 - - 使用 `channels..healthMonitor.enabled` 或 `channels..accounts..healthMonitor.enabled` 可为单个渠道或账户禁用自动重启,而无需关闭全局监控。 - - 运行排障请参阅[健康检查](/zh-CN/gateway/health),所有字段请参阅[完整参考](/zh-CN/gateway/configuration-reference#gateway)。 + - 使用 `channels..healthMonitor.enabled` 或 `channels..accounts..healthMonitor.enabled` 可在不禁用全局监控的情况下,为单个渠道或账户禁用自动重启。 + - 运维调试请参见[健康检查](/zh-CN/gateway/health),所有字段请参见[完整参考](/zh-CN/gateway/configuration-reference#gateway)。 - 会话控制对话的连续性和隔离性: + 会话控制对话连续性和隔离: ```json5 { @@ -301,8 +310,8 @@ JSON。 - `dmScope`:`main`(共享)| `per-peer` | `per-channel-peer` | `per-account-channel-peer` - `threadBindings`:线程绑定会话路由的全局默认值(Discord 支持 `/focus`、`/unfocus`、`/agents`、`/session idle` 和 `/session max-age`)。 - - 有关作用域、身份关联和发送策略,请参阅[会话管理](/zh-CN/concepts/session)。 - - 所有字段请参阅[完整参考](/zh-CN/gateway/configuration-reference#session)。 + - 作用域、身份链接和发送策略请参见[会话管理](/zh-CN/concepts/session)。 + - 所有字段请参见[完整参考](/zh-CN/gateway/configuration-reference#session)。 @@ -324,14 +333,14 @@ JSON。 先构建镜像:`scripts/sandbox-setup.sh` - 完整指南请参阅[沙箱隔离](/zh-CN/gateway/sandboxing),所有选项请参阅[完整参考](/zh-CN/gateway/configuration-reference#agentsdefaultssandbox)。 + 完整指南请参见[沙箱隔离](/zh-CN/gateway/sandboxing),所有选项请参见[完整参考](/zh-CN/gateway/configuration-reference#agentsdefaultssandbox)。 基于 relay 的推送在 `openclaw.json` 中配置。 - 在 Gateway 网关 配置中设置以下内容: + 在 gateway 配置中设置: ```json5 { @@ -349,43 +358,43 @@ JSON。 } ``` - 对应的 CLI 命令: + 等价的 CLI: ```bash openclaw config set gateway.push.apns.relay.baseUrl https://relay.example.com ``` - 这会带来以下效果: + 这会执行以下操作: - - 让 Gateway 网关 能通过外部 relay 发送 `push.test`、唤醒提醒和重连唤醒。 - - 使用由已配对 iOS 应用转发的、按注册范围限定的发送授权。Gateway 网关 不需要部署范围的 relay 令牌。 - - 将每个基于 relay 的注册绑定到 iOS 应用所配对的 Gateway 网关 身份,因此其他 Gateway 网关 无法复用已存储的注册信息。 - - 本地 / 手动构建的 iOS 版本仍使用直接 APNs。基于 relay 的发送仅适用于通过 relay 注册的官方分发构建。 - - 必须与官方 / TestFlight iOS 构建中内置的 relay 基础 URL 一致,这样注册和发送流量才能到达同一个 relay 部署。 + - 让 gateway 能够通过外部 relay 发送 `push.test`、唤醒提示和重连唤醒。 + - 使用由已配对 iOS 应用转发的、按注册范围限定的发送授权。gateway 不需要部署范围的 relay 令牌。 + - 将每个基于 relay 的注册绑定到 iOS 应用所配对的 gateway 身份,因此其他 gateway 无法复用已存储的注册信息。 + - 让本地/手动 iOS 构建继续使用直接 APNs。基于 relay 的发送仅适用于通过 relay 注册的官方分发构建。 + - 必须与编译进官方/TestFlight iOS 构建中的 relay 基础 URL 一致,这样注册和发送流量才能到达同一个 relay 部署。 端到端流程: - 1. 安装使用相同 relay 基础 URL 编译的官方 / TestFlight iOS 构建。 - 2. 在 Gateway 网关 上配置 `gateway.push.apns.relay.baseUrl`。 - 3. 将 iOS 应用与 Gateway 网关 配对,并让节点会话和操作员会话都连接。 - 4. iOS 应用获取 Gateway 网关 身份,使用 App Attest 和应用收据向 relay 注册,然后将基于 relay 的 `push.apns.register` 负载发布到已配对的 Gateway 网关。 - 5. Gateway 网关 存储 relay 句柄和发送授权,然后将其用于 `push.test`、唤醒提醒和重连唤醒。 + 1. 安装一个使用相同 relay 基础 URL 编译的官方/TestFlight iOS 构建。 + 2. 在 gateway 上配置 `gateway.push.apns.relay.baseUrl`。 + 3. 将 iOS 应用与 gateway 配对,并让节点会话和操作员会话都连接。 + 4. iOS 应用获取 gateway 身份,结合 App Attest 和应用收据向 relay 注册,然后将基于 relay 的 `push.apns.register` 载荷发布到已配对的 gateway。 + 5. gateway 存储 relay 句柄和发送授权,然后将它们用于 `push.test`、唤醒提示和重连唤醒。 运行说明: - - 如果你将 iOS 应用切换到另一个 Gateway 网关,请重新连接该应用,以便它发布绑定到新 Gateway 网关 的 relay 注册。 + - 如果你将 iOS 应用切换到其他 gateway,请重新连接应用,以便它发布一个绑定到该 gateway 的新 relay 注册。 - 如果你发布了一个指向不同 relay 部署的新 iOS 构建,应用会刷新其缓存的 relay 注册,而不是复用旧的 relay 来源。 兼容性说明: - `OPENCLAW_APNS_RELAY_BASE_URL` 和 `OPENCLAW_APNS_RELAY_TIMEOUT_MS` 仍可作为临时环境变量覆盖项使用。 - - `OPENCLAW_APNS_RELAY_ALLOW_HTTP=true` 仍然是仅限 local loopback 的开发逃生口;不要在配置中持久化 HTTP relay URL。 + - `OPENCLAW_APNS_RELAY_ALLOW_HTTP=true` 仍然是一个仅限 local loopback 的开发逃生舱;不要在配置中持久化 HTTP relay URL。 - 端到端流程请参阅[iOS App](/zh-CN/platforms/ios#relay-backed-push-for-official-builds),relay 安全模型请参阅[认证与信任流程](/zh-CN/platforms/ios#authentication-and-trust-flow)。 + 端到端流程请参见[iOS 应用](/zh-CN/platforms/ios#relay-backed-push-for-official-builds),relay 安全模型请参见[认证与信任流程](/zh-CN/platforms/ios#authentication-and-trust-flow)。 - + ```json5 { agents: { @@ -401,8 +410,8 @@ JSON。 - `every`:时长字符串(`30m`、`2h`)。设置为 `0m` 可禁用。 - `target`:`last` | `none` | ``(例如 `discord`、`matrix`、`telegram` 或 `whatsapp`) - - `directPolicy`:用于私信式 heartbeat 目标的 `allow`(默认)或 `block` - - 完整指南请参阅[Heartbeat](/zh-CN/gateway/heartbeat)。 + - `directPolicy`:私信风格心跳目标使用 `allow`(默认)或 `block` + - 完整指南请参见[心跳](/zh-CN/gateway/heartbeat)。 @@ -423,12 +432,12 @@ JSON。 - `sessionRetention`:从 `sessions.json` 中清理已完成的隔离运行会话(默认 `24h`;设置为 `false` 可禁用)。 - `runLog`:按大小和保留行数清理 `cron/runs/.jsonl`。 - - 功能概览和 CLI 示例请参阅[Cron 作业](/zh-CN/automation/cron-jobs)。 + - 功能概览和 CLI 示例请参见[Cron 作业](/zh-CN/automation/cron-jobs)。 - 在 Gateway 网关 上启用 HTTP webhook 端点: + 在 Gateway 网关上启用 HTTP webhook 端点: ```json5 { @@ -452,20 +461,20 @@ JSON。 ``` 安全说明: - - 将所有 hook / webhook 负载内容都视为不可信输入。 - - 使用专用的 `hooks.token`;不要复用共享的 Gateway 网关 令牌。 - - Hook 认证仅支持请求头(`Authorization: Bearer ...` 或 `x-openclaw-token`);查询字符串令牌会被拒绝。 - - `hooks.path` 不能为 `/`;应将 webhook 入口保留在专用子路径下,例如 `/hooks`。 - - 保持不安全内容绕过标志为禁用状态(`hooks.gmail.allowUnsafeExternalContent`、`hooks.mappings[].allowUnsafeExternalContent`),除非是在做严格限定范围的调试。 - - 如果你启用了 `hooks.allowRequestSessionKey`,还应设置 `hooks.allowedSessionKeyPrefixes` 以限制调用方可选的会话键。 - - 对于由 hook 驱动的智能体,优先使用强大的现代模型层级和严格的工具策略(例如仅允许消息传递,并尽可能启用沙箱隔离)。 + - 将所有 hook/webhook 载荷内容视为不受信任的输入。 + - 使用专用的 `hooks.token`;不要复用共享 Gateway 网关令牌。 + - Hook 认证仅支持 header(`Authorization: Bearer ...` 或 `x-openclaw-token`);查询字符串中的令牌会被拒绝。 + - `hooks.path` 不能为 `/`;请将 webhook 入口保留在专用子路径下,例如 `/hooks`。 + - 保持不安全内容绕过标志为禁用(`hooks.gmail.allowUnsafeExternalContent`、`hooks.mappings[].allowUnsafeExternalContent`),除非你正在进行范围严格受控的调试。 + - 如果启用 `hooks.allowRequestSessionKey`,还应设置 `hooks.allowedSessionKeyPrefixes` 来限制调用方可选的会话键。 + - 对于由 hook 驱动的智能体,优先选择强大的现代模型层级和严格的工具策略(例如尽可能仅允许消息传递并配合沙箱隔离)。 - 所有映射选项和 Gmail 集成请参阅[完整参考](/zh-CN/gateway/configuration-reference#hooks)。 + 所有映射选项和 Gmail 集成请参见[完整参考](/zh-CN/gateway/configuration-reference#hooks)。 - 运行多个相互隔离的智能体,每个都有独立的工作区和会话: + 运行多个彼此隔离的智能体,并使用独立工作区和会话: ```json5 { @@ -482,12 +491,12 @@ JSON。 } ``` - 绑定规则和每个智能体的访问配置文件请参阅[多智能体](/zh-CN/concepts/multi-agent)和[完整参考](/zh-CN/gateway/configuration-reference#multi-agent-routing)。 + 绑定规则和每个智能体的访问配置请参见[多智能体](/zh-CN/concepts/multi-agent) 和[完整参考](/zh-CN/gateway/configuration-reference#multi-agent-routing)。 - 使用 `$include` 组织大型配置: + 使用 `$include` 来组织大型配置: ```json5 // ~/.openclaw/openclaw.json @@ -500,46 +509,45 @@ JSON。 } ``` - - **单个文件**:替换所在的对象 - - **文件数组**:按顺序深度合并(后者优先) - - **同级键**:在 include 之后合并(覆盖 include 中的值) - - **嵌套 include**:最多支持 10 层嵌套 + - **单个文件**:替换所在对象 + - **文件数组**:按顺序深度合并(后者覆盖前者) + - **同级键**:在 include 之后合并(覆盖引入的值) + - **嵌套 include**:最多支持 10 层 - **相对路径**:相对于包含它的文件解析 - - **由 OpenClaw 管理的写入**:当一次写入仅修改由单文件 include 支持的某个顶级部分时, + - **OpenClaw 自有写入**:当某次写入仅更改一个由单文件 include 支持的顶层部分, 例如 `plugins: { $include: "./plugins.json5" }`, - OpenClaw 会更新该被包含文件,并保持 `openclaw.json` 不变 - - **不支持的透传写入**:对于根 include、include 数组,以及带有同级覆盖项的 include, - 在由 OpenClaw 管理的写入中会采用失败即关闭的策略,而不是 - 扁平化配置 - - **错误处理**:对于缺失文件、解析错误和循环 include,会给出清晰错误 + OpenClaw 会更新该被引入文件,并保持 `openclaw.json` 不变 + - **不支持的透传写入**:根级 include、include 数组以及带有同级覆盖的 include, + 对于 OpenClaw 自有写入会以关闭方式失败, + 而不会将配置拍平 + - **错误处理**:对缺失文件、解析错误和循环 include 提供清晰错误 ## 配置热重载 -Gateway 网关 会监视 `~/.openclaw/openclaw.json` 并自动应用更改——对于大多数设置,无需手动重启。 +Gateway 网关会监视 `~/.openclaw/openclaw.json` 并自动应用更改——对于大多数设置,无需手动重启。 -直接编辑文件在通过校验之前会被视为不可信。监视器会等待 -编辑器临时写入 / 重命名抖动稳定下来,读取最终文件,并通过恢复 -“最近一次已知正常”配置来拒绝无效的外部编辑。由 OpenClaw 管理的 -配置写入在写入前也会经过相同的 schema 闸门;像删除 `gateway.mode` -或将文件缩小到原来一半以下这类破坏性覆盖会被拒绝, -并保存为 `.rejected.*` 以供检查。 +直接文件编辑在通过校验前会被视为不受信任。监视器会等待 +编辑器临时写入/重命名抖动稳定下来,读取最终文件,并通过恢复最近一次有效配置 +来拒绝无效的外部编辑。OpenClaw 自有配置写入在写入前也会经过相同的 schema 门控; +诸如删除 `gateway.mode` 或将文件缩小超过一半之类的破坏性覆盖 +会被拒绝,并保存为 `.rejected.*` 以供检查。 如果你在日志中看到 `Config auto-restored from last-known-good` 或 `config reload restored last-known-good config`,请检查 -`openclaw.json` 同目录下对应的 `.clobbered.*` 文件,修复被拒绝的 -负载,然后运行 `openclaw config validate`。恢复检查清单请参阅[Gateway 网关 故障排除](/zh-CN/gateway/troubleshooting#gateway-restored-last-known-good-config)。 +`openclaw.json` 旁边对应的 `.clobbered.*` 文件,修复被拒绝的载荷,然后运行 +`openclaw config validate`。恢复检查清单请参见 [Gateway 网关故障排除](/zh-CN/gateway/troubleshooting#gateway-restored-last-known-good-config)。 ### 重载模式 | 模式 | 行为 | | ---------------------- | --------------------------------------------------------------------------------------- | -| **`hybrid`**(默认) | 立即热应用安全更改。对关键更改会自动重启。 | -| **`hot`** | 仅热应用安全更改。需要重启时会记录警告——由你自行处理。 | -| **`restart`** | 任何配置更改都会重启 Gateway 网关,无论是否安全。 | -| **`off`** | 禁用文件监视。更改会在下一次手动重启时生效。 | +| **`hybrid`**(默认) | 立即热应用安全更改。对于关键更改会自动重启。 | +| **`hot`** | 仅热应用安全更改。当需要重启时记录警告——由你自行处理。 | +| **`restart`** | 对任何配置更改都重启 Gateway 网关,无论是否安全。 | +| **`off`** | 禁用文件监视。更改将在下一次手动重启时生效。 | ```json5 { @@ -555,57 +563,70 @@ Gateway 网关 会监视 `~/.openclaw/openclaw.json` 并自动应用更改—— | 类别 | 字段 | 需要重启? | | ------------------- | ----------------------------------------------------------------- | --------------- | -| 渠道 | `channels.*`、`web`(WhatsApp)— 所有内置和插件渠道 | 否 | -| 智能体与模型 | `agent`、`agents`、`models`、`routing` | 否 | +| Channels | `channels.*`、`web`(WhatsApp)——所有内置和渠道插件 | 否 | +| 智能体和模型 | `agent`、`agents`、`models`、`routing` | 否 | | 自动化 | `hooks`、`cron`、`agent.heartbeat` | 否 | -| 会话与消息 | `session`、`messages` | 否 | -| 工具与媒体 | `tools`、`browser`、`skills`、`audio`、`talk` | 否 | -| UI 与杂项 | `ui`、`logging`、`identity`、`bindings` | 否 | -| Gateway 网关 服务器 | `gateway.*`(port、bind、auth、tailscale、TLS、HTTP) | **是** | +| 会话和消息 | `session`、`messages` | 否 | +| 工具和媒体 | `tools`、`browser`、`skills`、`audio`、`talk` | 否 | +| UI 和其他 | `ui`、`logging`、`identity`、`bindings` | 否 | +| Gateway 网关服务器 | `gateway.*`(port、bind、auth、tailscale、TLS、HTTP) | **是** | | 基础设施 | `discovery`、`canvasHost`、`plugins` | **是** | `gateway.reload` 和 `gateway.remote` 是例外——更改它们**不会**触发重启。 +### 重载规划 + +当你编辑一个通过 `$include` 引用的源文件时,OpenClaw 会根据源作者编写的布局 +来规划重载,而不是根据拍平后的内存视图。 +即使某个顶层部分单独存在于其自己的 include 文件中, +例如 `plugins: { $include: "./plugins.json5" }`, +这种方式也能让热重载决策(热应用还是重启)保持可预测。 + +如果某次重载无法被安全规划——例如,因为源布局 +将根级 include 与同级覆盖组合在一起——OpenClaw 会以关闭方式失败、记录 +原因,并保留当前正在运行的配置不变,这样你就可以修复源布局 +而不是静默回退到拍平后的重载。 + ## 配置 RPC(程序化更新) -控制平面写入 RPC(`config.apply`、`config.patch`、`update.run`)按每个 `deviceId+clientIp` 做速率限制:**每 60 秒 3 个请求**。触发限制时,RPC 会返回带 `retryAfterMs` 的 `UNAVAILABLE`。 +控制平面写入 RPC(`config.apply`、`config.patch`、`update.run`)按每个 `deviceId+clientIp` 限制为**每 60 秒 3 次请求**。当触发限制时,RPC 会返回 `UNAVAILABLE`,并带有 `retryAfterMs`。 -安全 / 默认流程: +安全/默认流程: -- `config.schema.lookup`:检查单个路径范围内的配置子树,返回一个浅层 - schema 节点、匹配的提示元数据以及直接子节点摘要 -- `config.get`:获取当前快照 + 哈希 -- `config.patch`:首选的局部更新路径 +- `config.schema.lookup`:检查一个按路径限定的配置子树,返回浅层 + schema 节点、匹配的提示元数据和直接子节点摘要 +- `config.get`:获取当前快照 + hash +- `config.patch`:首选的部分更新路径 - `config.apply`:仅用于完整配置替换 -- `update.run`:显式执行自更新 + 重启 +- `update.run`:显式自更新 + 重启 -当你不是要替换整个配置时,优先使用 `config.schema.lookup` -然后再使用 `config.patch`。 +当你不是替换整个配置时,优先使用 `config.schema.lookup` +然后 `config.patch`。 - 在一步中校验并写入完整配置,同时重启 Gateway 网关。 + 校验并写入完整配置,同时一步重启 Gateway 网关。 - `config.apply` 会替换**整个配置**。局部更新请使用 `config.patch`,单个键请使用 `openclaw config set`。 + `config.apply` 会替换**整个配置**。部分更新请使用 `config.patch`,单个键请使用 `openclaw config set`。 参数: - - `raw`(字符串)— 整个配置的 JSON5 负载 - - `baseHash`(可选)— 来自 `config.get` 的配置哈希(当配置已存在时为必填) + - `raw`(string)— 整个配置的 JSON5 载荷 + - `baseHash`(可选)— 来自 `config.get` 的配置 hash(当配置已存在时必填) - `sessionKey`(可选)— 重启后唤醒 ping 使用的会话键 - - `note`(可选)— 重启哨兵使用的备注 + - `note`(可选)— 重启哨兵的备注 - `restartDelayMs`(可选)— 重启前延迟(默认 2000) - 当某个重启请求已在等待 / 进行中时,新的重启请求会被合并;并且两次重启周期之间会有 30 秒冷却时间。 + 当已有重启处于待处理/进行中时,重启请求会被合并;并且两次重启周期之间会应用 30 秒冷却时间。 ```bash - openclaw gateway call config.get --params '{}' # 获取 payload.hash + openclaw gateway call config.get --params '{}' # capture payload.hash openclaw gateway call config.apply --params '{ "raw": "{ agents: { defaults: { workspace: \"~/.openclaw/workspace\" } } }", "baseHash": "", @@ -615,8 +636,8 @@ Gateway 网关 会监视 `~/.openclaw/openclaw.json` 并自动应用更改—— - - 将局部更新合并到现有配置中(JSON merge patch 语义): + + 将部分更新合并到现有配置中(JSON merge patch 语义): - 对象递归合并 - `null` 删除键 @@ -624,11 +645,11 @@ Gateway 网关 会监视 `~/.openclaw/openclaw.json` 并自动应用更改—— 参数: - - `raw`(字符串)— 仅包含要更改键的 JSON5 - - `baseHash`(必填)— 来自 `config.get` 的配置哈希 + - `raw`(string)— 仅包含要更改键的 JSON5 + - `baseHash`(必填)— 来自 `config.get` 的配置 hash - `sessionKey`、`note`、`restartDelayMs` — 与 `config.apply` 相同 - 重启行为与 `config.apply` 一致:等待中的重启会被合并,并且重启周期之间有 30 秒冷却时间。 + 重启行为与 `config.apply` 一致:合并待处理重启,并在两次重启周期之间应用 30 秒冷却时间。 ```bash openclaw gateway call config.patch --params '{ @@ -642,12 +663,12 @@ Gateway 网关 会监视 `~/.openclaw/openclaw.json` 并自动应用更改—— ## 环境变量 -OpenClaw 会从父进程读取环境变量,此外还会读取: +OpenClaw 会从父进程读取环境变量,另外还包括: - 当前工作目录中的 `.env`(如果存在) - `~/.openclaw/.env`(全局回退) -这两个文件都不会覆盖现有环境变量。你也可以在配置中设置内联环境变量: +这两个文件都不会覆盖已存在的环境变量。你也可以在配置中设置内联环境变量: ```json5 { @@ -658,8 +679,8 @@ OpenClaw 会从父进程读取环境变量,此外还会读取: } ``` - - 如果启用,并且预期键名尚未设置,OpenClaw 会运行你的登录 shell,并且仅导入缺失的键: + + 如果启用,并且预期键名未设置,OpenClaw 会运行你的登录 shell,并且只导入缺失的键: ```json5 { @@ -669,11 +690,11 @@ OpenClaw 会从父进程读取环境变量,此外还会读取: } ``` -环境变量对应项:`OPENCLAW_LOAD_SHELL_ENV=1` +环境变量等价项:`OPENCLAW_LOAD_SHELL_ENV=1` - 你可以在任意配置字符串值中使用 `${VAR_NAME}` 引用环境变量: + 可在任何配置字符串值中使用 `${VAR_NAME}` 引用环境变量: ```json5 { @@ -685,15 +706,15 @@ OpenClaw 会从父进程读取环境变量,此外还会读取: 规则: - 仅匹配大写名称:`[A-Z_][A-Z0-9_]*` -- 缺失 / 为空的变量会在加载时抛出错误 -- 使用 `$${VAR}` 可输出字面量 -- 在 `$include` 文件中同样可用 +- 缺失/为空的变量会在加载时报错 +- 使用 `$${VAR}` 转义为字面输出 +- 可在 `$include` 文件中使用 - 内联替换:`"${BASE}/v1"` → `"https://api.example.com/v1"` - 对于支持 SecretRef 对象的字段,你可以使用: + 对于支持 `SecretRef` 对象的字段,你可以使用: ```json5 { @@ -725,15 +746,15 @@ OpenClaw 会从父进程读取环境变量,此外还会读取: } ``` -SecretRef 详情(包括用于 `env` / `file` / `exec` 的 `secrets.providers`)请参阅[Secrets Management](/zh-CN/gateway/secrets)。 -支持的凭证路径列在[SecretRef Credential Surface](/zh-CN/reference/secretref-credential-surface) 中。 +`SecretRef` 详情(包括用于 `env`/`file`/`exec` 的 `secrets.providers`)请参见[密钥管理](/zh-CN/gateway/secrets)。 +支持的凭证路径列在 [SecretRef 凭证表面](/zh-CN/reference/secretref-credential-surface) 中。 -完整优先级和来源请参阅[环境](/zh-CN/help/environment)。 +完整优先级和来源请参见[环境](/zh-CN/help/environment)。 ## 完整参考 -如需完整的逐字段参考,请参阅 **[配置参考](/zh-CN/gateway/configuration-reference)**。 +如需逐字段的完整参考,请参见 **[配置参考](/zh-CN/gateway/configuration-reference)**。 --- diff --git a/docs/zh-CN/gateway/openshell.md b/docs/zh-CN/gateway/openshell.md index 78cf0fc00..d86605283 100644 --- a/docs/zh-CN/gateway/openshell.md +++ b/docs/zh-CN/gateway/openshell.md @@ -2,34 +2,29 @@ read_when: - 你想使用云端托管沙箱,而不是本地 Docker - 你正在设置 OpenShell 插件 - - 你需要在 mirror 和 remote 工作区模式之间做选择 -summary: 使用 OpenShell 作为 OpenClaw 智能体的托管沙箱后端 + - 你需要在 mirror 和 remote workspace 模式之间做出选择 +summary: 将 OpenShell 用作 OpenClaw 智能体的托管沙箱后端 title: OpenShell x-i18n: - generated_at: "2026-04-05T08:24:21Z" + generated_at: "2026-04-23T07:05:48Z" model: gpt-5.4 provider: openai - source_hash: aaf9027d0632a70fb86455f8bc46dc908ff766db0eb0cdf2f7df39c715241ead + source_hash: f93a8350fd48602bc535ec0480d0ed1665e558b37cc23c820ac90097862abd23 source_path: gateway/openshell.md workflow: 15 --- # OpenShell -OpenShell 是 OpenClaw 的一个托管沙箱后端。OpenClaw 不再在本地运行 Docker -容器,而是将沙箱生命周期委托给 `openshell` CLI, -由它来配置带有基于 SSH 命令执行的远程环境。 +OpenShell 是 OpenClaw 的托管沙箱后端。OpenClaw 不再在本地运行 Docker 容器,而是将沙箱生命周期委托给 `openshell` CLI,由它通过基于 SSH 的命令执行来预配远程环境。 -OpenShell 插件复用了与通用 [SSH backend](/gateway/sandboxing#ssh-backend) 相同的核心 SSH 传输和远程文件系统 -桥接能力。它增加了 OpenShell 专用的生命周期管理(`sandbox create/get/delete`, `sandbox ssh-config`) -以及可选的 `mirror` 工作区模式。 +OpenShell 插件复用了与通用 [SSH 后端](/zh-CN/gateway/sandboxing#ssh-backend) 相同的核心 SSH 传输和远程文件系统桥接。它增加了 OpenShell 专用的生命周期管理(`sandbox create/get/delete`、`sandbox ssh-config`)以及可选的 `mirror` 工作区模式。 -## 前置条件 +## 前提条件 -- 已安装 `openshell` CLI,并且可在 `PATH` 中找到(或通过 - `plugins.entries.openshell.config.command` 设置自定义路径) -- 拥有可访问沙箱的 OpenShell 账户 -- 主机上正在运行的 OpenClaw Gateway 网关 +- 已安装 `openshell` CLI,并且在 `PATH` 中可用(或通过 `plugins.entries.openshell.config.command` 设置自定义路径) +- 拥有具备沙箱访问权限的 OpenShell 账户 +- OpenClaw Gateway 网关正在宿主机上运行 ## 快速开始 @@ -61,8 +56,7 @@ OpenShell 插件复用了与通用 [SSH backend](/gateway/sandboxing#ssh-backend } ``` -2. 重启 Gateway 网关。在下一次智能体回合中,OpenClaw 会创建一个 OpenShell - 沙箱,并通过它来路由工具执行。 +2. 重启 Gateway 网关。在下一次智能体轮次时,OpenClaw 会创建一个 OpenShell 沙箱,并通过它路由工具执行。 3. 验证: @@ -73,88 +67,79 @@ openclaw sandbox explain ## 工作区模式 -这是使用 OpenShell 时最重要的决策。 +这是使用 OpenShell 时最重要的决定。 ### `mirror` -当你希望**本地工作区保持为权威来源**时,请使用 `plugins.entries.openshell.config.mode: "mirror"`。 +当你希望**本地工作区保持为权威版本**时,请使用 `plugins.entries.openshell.config.mode: "mirror"`。 行为: -- 在执行 `exec` 之前,OpenClaw 会把本地工作区同步到 OpenShell 沙箱。 -- 在执行 `exec` 之后,OpenClaw 会把远程工作区同步回本地工作区。 -- 文件工具仍然通过沙箱桥接运行,但在各回合之间,本地工作区 - 仍然是事实来源。 +- 在 `exec` 之前,OpenClaw 会将本地工作区同步到 OpenShell 沙箱中。 +- 在 `exec` 之后,OpenClaw 会将远程工作区同步回本地工作区。 +- 文件工具仍然通过沙箱桥接运行,但在轮次之间,本地工作区仍然是事实来源。 最适合: -- 你会在 OpenClaw 之外于本地编辑文件,并希望这些更改能自动在 - 沙箱中可见。 -- 你希望 OpenShell 沙箱尽可能像 Docker 后端一样工作。 -- 你希望主机工作区在每次 exec 回合后反映沙箱中的写入。 +- 你会在 OpenClaw 之外于本地编辑文件,并希望这些更改自动在沙箱中可见。 +- 你希望 OpenShell 沙箱的行为尽可能接近 Docker 后端。 +- 你希望宿主工作区在每次 `exec` 轮次之后反映沙箱中的写入结果。 -权衡:每次 exec 前后都会产生额外的同步开销。 +权衡:每次 `exec` 前后都会增加额外的同步成本。 ### `remote` -当你希望**OpenShell 工作区成为权威来源**时,请使用 `plugins.entries.openshell.config.mode: "remote"`。 +当你希望**OpenShell 工作区成为权威版本**时,请使用 `plugins.entries.openshell.config.mode: "remote"`。 行为: -- 当沙箱首次创建时,OpenClaw 会先将本地工作区一次性初始化到 - 远程工作区。 -- 此后,`exec`、`read`、`write`、`edit` 和 `apply_patch` 会 - 直接作用于远程 OpenShell 工作区。 +- 首次创建沙箱时,OpenClaw 会将本地工作区一次性初始化到远程工作区。 +- 此后,`exec`、`read`、`write`、`edit` 和 `apply_patch` 会直接对远程 OpenShell 工作区进行操作。 - OpenClaw **不会**将远程更改同步回本地工作区。 -- 提示阶段的媒体读取仍然可用,因为文件和媒体工具会通过 - 沙箱桥接读取。 +- 提示阶段的媒体读取仍然有效,因为文件和媒体工具会通过沙箱桥接读取。 最适合: -- 沙箱应主要存在于远程端。 -- 你希望降低每回合的同步开销。 -- 你不希望主机本地编辑悄悄覆盖远程沙箱状态。 +- 沙箱应主要存在于远程侧。 +- 你希望降低每轮的同步开销。 +- 你不希望宿主本地编辑静默覆盖远程沙箱状态。 -重要:如果在初始种子完成后,你在 OpenClaw 之外于主机上编辑文件, -远程沙箱**不会**看到这些更改。请使用 -`openclaw sandbox recreate` 重新播种。 +重要:如果你在初次初始化之后于宿主机上在 OpenClaw 之外编辑文件,远程沙箱**不会**看到这些更改。请使用 `openclaw sandbox recreate` 重新初始化。 ### 如何选择模式 -| | `mirror` | `remote` | -| ------------------------ | -------------------------- | ------------------------- | -| **权威工作区** | 本地主机 | 远程 OpenShell | -| **同步方向** | 双向(每次 exec) | 一次性种子 | -| **每回合开销** | 更高(上传 + 下载) | 更低(直接远程操作) | -| **本地编辑可见?** | 是,下一次 exec 时可见 | 否,直到 recreate | -| **最适合** | 开发工作流 | 长时间运行的智能体、CI | +| | `mirror` | `remote` | +| ------------------------ | ------------------------- | ------------------------ | +| **权威工作区** | 本地宿主 | 远程 OpenShell | +| **同步方向** | 双向(每次 `exec`) | 一次性初始化 | +| **每轮开销** | 更高(上传 + 下载) | 更低(直接远程操作) | +| **本地编辑是否可见?** | 是,下一次 `exec` 时可见 | 否,直到 recreate | +| **最适合** | 开发工作流 | 长时间运行的智能体、CI | ## 配置参考 所有 OpenShell 配置都位于 `plugins.entries.openshell.config` 下: -| 键 | 类型 | 默认值 | 说明 | +| 键 | 类型 | 默认值 | 描述 | | ------------------------- | ------------------------ | ------------- | ----------------------------------------------------- | -| `mode` | `"mirror"` 或 `"remote"` | `"mirror"` | 工作区同步模式 | -| `command` | `string` | `"openshell"` | `openshell` CLI 的路径或名称 | -| `from` | `string` | `"openclaw"` | 首次创建时的沙箱来源 | -| `gateway` | `string` | — | OpenShell Gateway 网关名称(`--gateway`) | -| `gatewayEndpoint` | `string` | — | OpenShell Gateway 网关端点 URL(`--gateway-endpoint`) | -| `policy` | `string` | — | 用于创建沙箱的 OpenShell policy ID | -| `providers` | `string[]` | `[]` | 创建沙箱时要附加的 provider 名称 | -| `gpu` | `boolean` | `false` | 请求 GPU 资源 | -| `autoProviders` | `boolean` | `true` | 在创建沙箱时传入 `--auto-providers` | -| `remoteWorkspaceDir` | `string` | `"/sandbox"` | 沙箱内主要的可写工作区 | -| `remoteAgentWorkspaceDir` | `string` | `"/agent"` | 智能体工作区挂载路径(用于只读访问) | -| `timeoutSeconds` | `number` | `120` | `openshell` CLI 操作的超时时间 | +| `mode` | `"mirror"` 或 `"remote"` | `"mirror"` | 工作区同步模式 | +| `command` | `string` | `"openshell"` | `openshell` CLI 的路径或名称 | +| `from` | `string` | `"openclaw"` | 首次创建时的沙箱来源 | +| `gateway` | `string` | — | OpenShell Gateway 网关名称(`--gateway`) | +| `gatewayEndpoint` | `string` | — | OpenShell Gateway 网关端点 URL(`--gateway-endpoint`)| +| `policy` | `string` | — | 用于创建沙箱的 OpenShell policy ID | +| `providers` | `string[]` | `[]` | 创建沙箱时要附加的 provider 名称 | +| `gpu` | `boolean` | `false` | 请求 GPU 资源 | +| `autoProviders` | `boolean` | `true` | 创建沙箱时传递 `--auto-providers` | +| `remoteWorkspaceDir` | `string` | `"/sandbox"` | 沙箱内主要的可写工作区 | +| `remoteAgentWorkspaceDir` | `string` | `"/agent"` | 智能体工作区挂载路径(用于只读访问) | +| `timeoutSeconds` | `number` | `120` | `openshell` CLI 操作的超时时间 | -沙箱级设置(`mode`、`scope`、`workspaceAccess`)与其他后端一样,配置在 -`agents.defaults.sandbox` 下。完整矩阵请参见 -[沙箱隔离](/gateway/sandboxing)。 +沙箱级设置(`mode`、`scope`、`workspaceAccess`)与其他后端一样,配置在 `agents.defaults.sandbox` 下。完整矩阵请参见[沙箱隔离](/zh-CN/gateway/sandboxing)。 ## 示例 -### 最小 remote 配置 +### 最简 remote 设置 ```json5 { @@ -180,7 +165,7 @@ openclaw sandbox explain } ``` -### 带 GPU 的 mirror 模式 +### 启用 GPU 的 mirror 模式 ```json5 { @@ -211,7 +196,7 @@ openclaw sandbox explain } ``` -### 带自定义 Gateway 网关的按智能体 OpenShell 配置 +### 带自定义 Gateway 网关的按智能体 OpenShell ```json5 { @@ -259,20 +244,17 @@ openclaw sandbox list # 检查生效的策略 openclaw sandbox explain -# 重新创建(删除远程工作区,并在下次使用时重新播种) +# 重建(删除远程工作区,并在下次使用时重新初始化) openclaw sandbox recreate --all ``` -对于 `remote` 模式,**recreate 特别重要**:它会删除该作用域下的权威 -远程工作区。下次使用时,会从 -本地工作区播种出一个全新的远程工作区。 +对于 `remote` 模式,**recreate 尤其重要**:它会删除该作用域下的权威远程工作区。下一次使用时,会从本地工作区重新初始化一个全新的远程工作区。 -对于 `mirror` 模式,recreate 主要是重置远程执行环境,因为 -本地工作区仍然是权威来源。 +对于 `mirror` 模式,recreate 主要是重置远程执行环境,因为本地工作区仍然是权威版本。 ### 何时需要 recreate -在更改以下任一项后执行 recreate: +在更改以下任一项后,请执行 recreate: - `agents.defaults.sandbox.backend` - `plugins.entries.openshell.config.from` @@ -283,28 +265,31 @@ openclaw sandbox recreate --all openclaw sandbox recreate --all ``` +## 安全加固 + +OpenShell 沙箱辅助程序在读取远程工作区文件时,会为工作区根目录使用一个固定的文件描述符,并从该固定 fd 向上遍历祖先,而不是在每次读取时重新解析路径。再加上每次操作时的身份重检,这可以防止在单次轮次中通过符号链接替换或热切换工作区挂载,将读取重定向到预期远程工作区之外。 + +- 工作区根目录只打开一次并固定;后续读取会复用该 fd。 +- 祖先遍历会从固定 fd 出发访问相对条目,因此无法被路径上层目录的替换所重定向。 +- 每次读取前都会重检沙箱身份,因此被重建或重新分配的沙箱无法静默地从其他工作区提供文件。 + ## 当前限制 - OpenShell 后端不支持沙箱浏览器。 - `sandbox.docker.binds` 不适用于 OpenShell。 -- `sandbox.docker.*` 下仅适用于 Docker 的运行时参数 - 只对 Docker 后端生效。 +- `sandbox.docker.*` 下的 Docker 专用运行时参数仅适用于 Docker 后端。 ## 工作原理 -1. OpenClaw 调用 `openshell sandbox create`(按配置传入 `--from`、`--gateway`、 - `--policy`、`--providers`、`--gpu` 标志)。 -2. OpenClaw 调用 `openshell sandbox ssh-config ` 获取该沙箱的 SSH 连接 - 详情。 -3. Core 会把 SSH 配置写入临时文件,并通过与通用 SSH backend 相同的 - 远程文件系统桥接打开 SSH 会话。 -4. 在 `mirror` 模式下:exec 前将本地同步到远程,运行后再同步回来。 -5. 在 `remote` 模式下:创建时只播种一次,之后直接在远程 - 工作区上操作。 +1. OpenClaw 调用 `openshell sandbox create`(根据配置附带 `--from`、`--gateway`、`--policy`、`--providers`、`--gpu` 标志)。 +2. OpenClaw 调用 `openshell sandbox ssh-config ` 以获取该沙箱的 SSH 连接详情。 +3. 核心会将 SSH 配置写入临时文件,并使用与通用 SSH 后端相同的远程文件系统桥接打开一个 SSH 会话。 +4. 在 `mirror` 模式下:先将本地同步到远程,再执行,执行后再同步回来。 +5. 在 `remote` 模式下:创建时初始化一次,之后直接操作远程工作区。 ## 另请参见 -- [沙箱隔离](/gateway/sandboxing) -- 模式、作用域和后端比较 -- [沙箱 vs 工具策略 vs Elevated](/gateway/sandbox-vs-tool-policy-vs-elevated) -- 调试被阻止的工具 -- [多智能体沙箱和工具](/tools/multi-agent-sandbox-tools) -- 按智能体覆盖 -- [沙箱 CLI](/cli/sandbox) -- `openclaw sandbox` 命令 +- [沙箱隔离](/zh-CN/gateway/sandboxing) -- 模式、作用域和后端对比 +- [沙箱 vs 工具策略 vs Elevated](/zh-CN/gateway/sandbox-vs-tool-policy-vs-elevated) -- 调试被阻止的工具 +- [多智能体沙箱和工具](/zh-CN/tools/multi-agent-sandbox-tools) -- 按智能体覆盖 +- [沙箱 CLI](/zh-CN/cli/sandbox) -- `openclaw sandbox` 命令 diff --git a/docs/zh-CN/gateway/pairing.md b/docs/zh-CN/gateway/pairing.md index 0575e9836..b4c8add8c 100644 --- a/docs/zh-CN/gateway/pairing.md +++ b/docs/zh-CN/gateway/pairing.md @@ -1,45 +1,43 @@ --- read_when: - - 在没有 macOS UI 的情况下实现节点配对批准 + - 在没有 macOS UI 的情况下实现节点配对审批 - 添加用于批准远程节点的 CLI 流程 - - 使用节点管理扩展 Gateway protocol -summary: 适用于 iOS 和其他远程节点的 Gateway 网关持有型节点配对(方案 B) -title: Gateway 网关持有型配对 + - 使用节点管理扩展 Gateway 网关协议 +summary: 适用于 iOS 和其他远程节点的 Gateway 网关持有节点配对(选项 B) +title: Gateway 网关持有的配对 x-i18n: - generated_at: "2026-04-05T08:24:11Z" + generated_at: "2026-04-23T07:05:47Z" model: gpt-5.4 provider: openai - source_hash: 8f90818c84daeb190f27df7413e23362372806f2c4250e4954295fbf6df70233 + source_hash: adba3c833b57b1df117c57d3451598e3c84cd78dcc6e9811547cdbb101afda0b source_path: gateway/pairing.md workflow: 15 --- -# Gateway 网关持有型配对(方案 B) +# Gateway 网关持有的配对(选项 B) -在 Gateway 网关持有型配对中,**Gateway 网关**是决定哪些节点 -允许加入的真实来源。UI(macOS 应用、未来的客户端)只是用于 -批准或拒绝待处理请求的前端。 +在 Gateway 网关持有的配对中,**Gateway 网关** 是决定哪些节点被允许加入的事实来源。 +UI(macOS 应用、未来的客户端)只是用于批准或拒绝待处理请求的前端。 **重要:** WS 节点在 `connect` 期间使用**设备配对**(角色 `node`)。 -`node.pair.*` 是单独的配对存储,**不会**控制 WS 握手。 -只有显式调用 `node.pair.*` 的客户端才会使用此流程。 +`node.pair.*` 是一个独立的配对存储,不**会**控制 WS 握手。 +只有显式调用 `node.pair.*` 的客户端才会使用这条流程。 ## 概念 - **待处理请求**:某个节点请求加入;需要批准。 -- **已配对节点**:已批准并获得已签发 auth token 的节点。 -- **传输协议**:Gateway WS 端点负责转发请求,但不决定 - 成员资格。(旧版 TCP bridge 支持已被移除。) +- **已配对节点**:已获批准并已签发认证 token 的节点。 +- **传输协议**:Gateway 网关 WS 端点会转发请求,但不决定成员资格。(旧版 TCP bridge 支持已移除。) ## 配对如何工作 -1. 节点连接到 Gateway WS 并请求配对。 +1. 节点连接到 Gateway 网关 WS 并请求配对。 2. Gateway 网关存储一个**待处理请求**,并发出 `node.pair.requested`。 3. 你批准或拒绝该请求(CLI 或 UI)。 4. 批准后,Gateway 网关会签发一个**新 token**(重新配对时 token 会轮换)。 5. 节点使用该 token 重新连接,此时即为“已配对”。 -待处理请求会在 **5 分钟**后自动过期。 +待处理请求会在 **5 分钟** 后自动过期。 ## CLI 工作流(适合无头环境) @@ -51,34 +49,34 @@ openclaw nodes status openclaw nodes rename --node --name "Living Room iPad" ``` -`nodes status` 会显示已配对/已连接节点及其能力。 +`nodes status` 会显示已配对/已连接的节点及其能力。 -## API surface(Gateway protocol) +## API 接口(Gateway 网关协议) 事件: -- `node.pair.requested` —— 创建新的待处理请求时发出。 -- `node.pair.resolved` —— 请求被批准/拒绝/过期时发出。 +- `node.pair.requested` — 当创建新的待处理请求时发出。 +- `node.pair.resolved` — 当请求被批准/拒绝/过期时发出。 方法: -- `node.pair.request` —— 创建或复用一个待处理请求。 -- `node.pair.list` —— 列出待处理 + 已配对节点(`operator.pairing`)。 -- `node.pair.approve` —— 批准待处理请求(签发 token)。 -- `node.pair.reject` —— 拒绝待处理请求。 -- `node.pair.verify` —— 验证 `{ nodeId, token }`。 +- `node.pair.request` — 创建或复用一个待处理请求。 +- `node.pair.list` — 列出待处理节点和已配对节点(`operator.pairing`)。 +- `node.pair.approve` — 批准待处理请求(签发 token)。 +- `node.pair.reject` — 拒绝待处理请求。 +- `node.pair.verify` — 验证 `{ nodeId, token }`。 说明: -- `node.pair.request` 对每个节点是幂等的:重复调用会返回相同的 +- `node.pair.request` 对每个节点是幂等的:重复调用会返回同一个 待处理请求。 -- 对同一个待处理节点的重复请求,也会刷新已存储的节点 - 元数据,以及最新的已加入 allowlist 的声明命令快照,以便操作员查看。 -- 批准**总是**生成一个新的 token;`node.pair.request` 绝不会返回 +- 对同一待处理节点的重复请求也会刷新已存储的节点 + 元数据,以及最新的 allowlist 声明命令快照,以便操作员查看。 +- 批准**总是**会生成新的 token;`node.pair.request` 绝不会返回 token。 - 请求可以包含 `silent: true`,作为自动批准流程的提示。 -- `node.pair.approve` 使用待处理请求中声明的命令来强制执行 - 额外的批准 scopes: +- `node.pair.approve` 会使用待处理请求声明的命令来强制执行 + 额外的审批作用域: - 无命令请求:`operator.pairing` - 非 exec 命令请求:`operator.pairing` + `operator.write` - `system.run` / `system.run.prepare` / `system.which` 请求: @@ -86,45 +84,74 @@ openclaw nodes rename --node --name "Living Room iPad" 重要说明: -- 节点配对是一个信任/身份流程,并附带 token 签发。 -- 它**不会**按节点固定实时节点命令 surface。 -- 实时节点命令来自节点在 connect 后声明的内容,并会在应用 - Gateway 网关全局节点命令策略(`gateway.nodes.allowCommands` / +- 节点配对是一个信任/身份验证流程,外加 token 签发。 +- 它**不会**按节点固定当前在线的节点命令面。 +- 当前在线的节点命令来自节点在连接后声明的内容,并在应用 + Gateway 网关的全局节点命令策略(`gateway.nodes.allowCommands` / `denyCommands`)后生效。 -- 每节点的 `system.run` allow/ask 策略位于节点本身的 - `exec.approvals.node.*` 中,而不在配对记录中。 +- 每个节点的 `system.run` allow/ask 策略位于节点上的 + `exec.approvals.node.*` 中,而不在配对记录里。 ## 节点命令门控(`2026.3.31+`) -**破坏性变更:** 从 `2026.3.31` 开始,在节点配对获批之前,节点命令将被禁用。仅靠设备配对已不足以暴露已声明的节点命令。 +**破坏性变更:** 从 `2026.3.31` 开始,在节点配对获批之前,节点命令将被禁用。仅有设备配对已不足以暴露声明的节点命令。 -当节点首次连接时,会自动请求配对。在配对请求获批之前,来自该节点的所有待处理节点命令都会被过滤,不会执行。一旦通过配对批准建立信任,该节点声明的命令就会在正常命令策略约束下变得可用。 +当节点首次连接时,会自动请求配对。在该配对请求获批之前,该节点的所有待处理节点命令都会被过滤,不会执行。一旦通过配对批准建立信任,节点声明的命令就会在正常命令策略约束下可用。 这意味着: -- 之前仅依赖设备配对来暴露命令的节点,现在必须完成节点配对。 -- 在配对批准前排队的命令会被丢弃,而不是延后执行。 +- 以前仅依赖设备配对来暴露命令的节点,现在必须完成节点配对。 +- 在配对获批前排队的命令会被丢弃,而不是延后执行。 ## 节点事件信任边界(`2026.3.31+`) -**破坏性变更:** 节点来源的运行现在会保持在收缩后的受信任 surface 内。 +**破坏性变更:** 节点发起的运行现在会保留在收缩后的受信任面内。 -节点来源的摘要和相关会话事件会被限制在预期的受信任 surface 内。之前依赖更广泛宿主级或会话工具访问权限的通知驱动或节点触发流程,可能需要调整。这项加固确保节点事件不能升级为超出节点信任边界允许范围的宿主级工具访问。 +节点发起的摘要及相关会话事件将被限制在预期的受信任范围内。此前依赖更广泛主机或会话工具访问的通知驱动或节点触发流程,可能需要调整。此加固可确保节点事件无法升级为超出该节点信任边界所允许范围的主机级工具访问。 ## 自动批准(macOS 应用) 在以下情况下,macOS 应用可以选择尝试**静默批准**: - 该请求被标记为 `silent`,并且 -- 应用能够验证使用同一用户连接到 Gateway 网关宿主机的 SSH 连接。 +- 应用能够使用同一用户验证到 gateway 主机的 SSH 连接。 -如果静默批准失败,则会回退到正常的“批准/拒绝”提示。 +如果静默批准失败,则会回退到常规的“批准/拒绝”提示。 -## 存储(本地,私有) +## 元数据升级自动批准 + +当已配对设备重新连接,且仅包含非敏感元数据变更 +(例如显示名称或客户端平台提示)时,OpenClaw 会将其视为 +`metadata-upgrade`。静默自动批准的范围很窄:它仅适用于 +已通过 loopback 上的共享 token 或密码证明身份的 +受信任本地 CLI/辅助程序重连。浏览器/Control UI 客户端以及远程 +客户端仍使用显式重新批准流程。作用域升级(从 read 到 +write/admin)以及公钥变更**不**符合元数据升级自动批准条件—— +它们仍然作为显式重新批准请求处理。 + +## QR 配对辅助功能 + +`/pair qr` 会将配对负载渲染为结构化媒体,以便移动端和 +浏览器客户端直接扫描。现在,设备删除也会一并清理相同设备 ID 的 +陈旧待处理配对请求,因此在撤销后,`nodes pending` 不再显示 +孤立条目。 + +## 本地性和转发头 + +Gateway 网关配对仅在原始 socket +和任何上游代理证据都一致的情况下,才会将连接视为 loopback。 +如果请求到达于 loopback,但携带了 `X-Forwarded-For` / `X-Forwarded-Host` / `X-Forwarded-Proto` 头, +且这些头指向非本地来源,那么这些转发头证据会使 +loopback 本地性声明失效。此时配对路径将要求显式批准, +而不是静默地将该请求视为同主机连接。参见 +[Trusted Proxy Auth](/zh-CN/gateway/trusted-proxy-auth) 了解 +operator auth 上的等效规则。 + +## 存储(本地、私有) 配对状态存储在 Gateway 网关状态目录下(默认 `~/.openclaw`): @@ -135,11 +162,11 @@ openclaw nodes rename --node --name "Living Room iPad" 安全说明: -- Token 属于密钥;请将 `paired.json` 视为敏感文件。 +- Token 是密钥;请将 `paired.json` 视为敏感文件。 - 轮换 token 需要重新批准(或删除该节点条目)。 ## 传输协议行为 - 传输协议是**无状态**的;它不存储成员资格。 -- 如果 Gateway 网关离线或禁用了配对,节点将无法配对。 -- 如果 Gateway 网关处于远程模式,配对仍然会针对远程 Gateway 网关的存储进行。 +- 如果 Gateway 网关离线或配对被禁用,节点将无法配对。 +- 如果 Gateway 网关处于远程模式,配对仍会针对远程 Gateway 网关的存储进行。 diff --git a/docs/zh-CN/gateway/security/index.md b/docs/zh-CN/gateway/security/index.md index 74d1103f8..c84c7d121 100644 --- a/docs/zh-CN/gateway/security/index.md +++ b/docs/zh-CN/gateway/security/index.md @@ -1,43 +1,43 @@ --- read_when: - 添加会扩大访问范围或自动化能力的功能 -summary: 运行具有 shell 访问权限的 AI Gateway 网关的安全注意事项和威胁模型 -title: 安全性 +summary: 运行具有 shell 访问能力的 AI Gateway 网关时的安全注意事项和威胁模型 +title: 安全 x-i18n: - generated_at: "2026-04-22T23:04:29Z" + generated_at: "2026-04-23T07:05:46Z" model: gpt-5.4 provider: openai - source_hash: 47f524e57500faff35363f656c199e60bf51364f6aeb94114e1a0885ce04b128 + source_hash: 4bb81b40623203dade0ab168973674a5f5d8809bcd6912c29db41baa955ce2b8 source_path: gateway/security/index.md workflow: 15 --- -# 安全性 +# 安全 **个人助理信任模型:** 本指南假设每个 Gateway 网关只有一个受信任的操作员边界(单用户/个人助理模型)。 -OpenClaw **不是** 供多个对抗性用户共享同一个智能体 / Gateway 网关时的敌对多租户安全边界。 -如果你需要混合信任或对抗性用户场景,请拆分信任边界(单独的 Gateway 网关 + 凭证,最好再配合单独的 OS 用户 / 主机)。 +OpenClaw **不是** 为多个对抗性用户共享同一个智能体/Gateway 网关而设计的敌对多租户安全边界。 +如果你需要混合信任或对抗性用户运行,请拆分信任边界(独立的 Gateway 网关 + 凭证,最好再使用独立的 OS 用户/主机)。 -**本页内容:** [信任模型](#scope-first-personal-assistant-security-model) | [快速审计](#quick-check-openclaw-security-audit) | [加固基线](#hardened-baseline-in-60-seconds) | [私信访问模型](#dm-access-model-pairing-allowlist-open-disabled) | [配置加固](#configuration-hardening-examples) | [事件响应](#incident-response) +**本页内容:** [信任模型](#scope-first-personal-assistant-security-model) | [快速审计](#quick-check-openclaw-security-audit) | [强化基线](#hardened-baseline-in-60-seconds) | [私信访问模型](#dm-access-model-pairing-allowlist-open-disabled) | [配置加固](#configuration-hardening-examples) | [事件响应](#incident-response) ## 先明确范围:个人助理安全模型 -OpenClaw 的安全指南假设采用**个人助理**部署:一个受信任的操作员边界,可能对应多个智能体。 +OpenClaw 的安全指南假设采用**个人助理**部署:一个受信任的操作员边界,可能包含多个智能体。 -- 支持的安全姿态:每个 Gateway 网关对应一个用户 / 信任边界(最好每个边界使用单独的 OS 用户 / 主机 / VPS)。 -- 不受支持的安全边界:多个彼此不受信任或具有对抗关系的用户共享同一个 Gateway 网关 / 智能体。 -- 如果需要对抗性用户隔离,请按信任边界拆分(单独的 Gateway 网关 + 凭证,最好再配合单独的 OS 用户 / 主机)。 -- 如果多个不受信任的用户都可以给同一个启用了工具的智能体发消息,应视为他们共享了该智能体的同一组委托工具权限。 +- 支持的安全姿态:每个 Gateway 网关对应一个用户/信任边界(最好每个边界使用一个 OS 用户/主机/VPS)。 +- 不支持的安全边界:多个彼此不受信任或具有对抗关系的用户,共享一个 Gateway 网关/智能体。 +- 如果需要对抗性用户隔离,请按信任边界拆分(独立的 Gateway 网关 + 凭证,最好再使用独立的 OS 用户/主机)。 +- 如果多个不受信任的用户都能向同一个启用了工具的智能体发送消息,应将他们视为共享该智能体同一组被委托的工具权限。 -本页说明的是**在这一模型内**如何进行加固。它并不声称在单个共享 Gateway 网关上提供敌对多租户隔离。 +本页解释的是**在该模型内**如何进行加固。它并不声称单个共享 Gateway 网关能够提供敌对多租户隔离。 ## 快速检查:`openclaw security audit` 另请参阅:[Formal Verification(Security Models)](/zh-CN/security/formal-verification) -请定期运行此命令(尤其是在更改配置或暴露网络接口之后): +请定期运行此命令(尤其是在更改配置或暴露网络面之后): ```bash openclaw security audit @@ -46,103 +46,103 @@ openclaw security audit --fix openclaw security audit --json ``` -`security audit --fix` 故意保持较窄范围:它会将常见的开放群组策略切换为 allowlist、恢复 `logging.redactSensitive: "tools"`、收紧 state/config/include-file 的权限,并且在 Windows 上运行时会使用 Windows ACL 重置,而不是 POSIX `chmod`。 +`security audit --fix` 的作用范围有意保持较窄:它会将常见的开放组策略切换为 allowlist,恢复 `logging.redactSensitive: "tools"`,收紧状态/配置/include-file 权限,并在 Windows 上使用 ACL 重置而不是 POSIX `chmod`。 -它会标记常见的易错点(Gateway 网关认证暴露、浏览器控制暴露、elevated allowlist、文件系统权限、宽松的 exec 审批,以及开放渠道的工具暴露)。 +它会标记常见的易错点(Gateway 网关鉴权暴露、浏览器控制暴露、高权限 allowlist、文件系统权限、宽松的 exec 审批,以及开放渠道工具暴露)。 -OpenClaw 既是一个产品,也是一个实验:你是在把前沿模型行为接入真实的消息通道和真实工具。**不存在“绝对安全”的配置。** 目标是有意识地明确以下几点: +OpenClaw 既是一个产品,也是一个实验:你正在把前沿模型行为接入真实的消息渠道和真实的工具。**不存在“绝对安全”的配置。** 目标是有意识地明确: - 谁可以和你的机器人对话 -- 机器人被允许在哪些地方执行操作 +- 机器人可以在哪些地方执行操作 - 机器人可以接触什么 -先从仍能正常工作的最小访问范围开始,等你建立足够信心后再逐步放宽。 +先从仍能工作的最小访问范围开始,然后随着你建立信心再逐步放宽。 ### 部署与主机信任 OpenClaw 假设主机和配置边界是受信任的: -- 如果某人可以修改 Gateway 网关主机状态 / 配置(`~/.openclaw`,包括 `openclaw.json`),应将其视为受信任的操作员。 -- 用一个 Gateway 网关服务多个彼此不受信任 / 对抗性的操作员,**不是推荐配置**。 -- 对于混合信任团队,请通过单独的 Gateway 网关(或至少单独的 OS 用户 / 主机)来拆分信任边界。 -- 推荐默认做法:每台机器 / 主机(或 VPS)一个用户,该用户一个 Gateway 网关,在该 Gateway 网关中运行一个或多个智能体。 -- 在一个 Gateway 网关实例内部,经过认证的操作员访问属于受信任的控制平面角色,而不是按用户划分的租户角色。 -- 会话标识符(`sessionKey`、session ID、label)是路由选择器,不是授权令牌。 -- 如果多个人可以给同一个启用了工具的智能体发消息,那么他们都可以驱动同一组权限。按用户隔离 session / Memory 虽然有助于保护隐私,但不会把一个共享智能体变成按用户划分的主机授权体系。 +- 如果有人可以修改 Gateway 网关主机状态/配置(`~/.openclaw`,包括 `openclaw.json`),应将其视为受信任的操作员。 +- 为多个彼此不受信任/对抗性的操作员运行同一个 Gateway 网关**不是推荐配置**。 +- 对于混合信任团队,请使用独立的 Gateway 网关 来拆分信任边界(或至少使用独立的 OS 用户/主机)。 +- 推荐默认做法:每台机器/主机(或 VPS)对应一个用户,该用户运行一个 Gateway 网关,并在该 Gateway 网关中运行一个或多个智能体。 +- 在单个 Gateway 网关实例内部,已鉴权的操作员访问属于受信任的控制平面角色,而不是按用户划分的租户角色。 +- 会话标识符(`sessionKey`、会话 ID、标签)是路由选择器,不是授权令牌。 +- 如果多个人都能给同一个启用了工具的智能体发送消息,那么他们都可以驱动同一组权限。按用户进行会话/记忆隔离有助于隐私,但并不能把共享智能体变成按用户划分的主机授权边界。 ### 共享 Slack 工作区:真实风险 -如果“Slack 里的所有人都可以给机器人发消息”,核心风险是委托工具权限: +如果“Slack 中的每个人都可以给机器人发消息”,核心风险是被委托的工具权限: -- 任何被允许的发送者都可以在该智能体的策略范围内诱导工具调用(`exec`、浏览器、网络 / 文件工具); -- 来自某个发送者的提示注入 / 内容注入,可能导致影响共享状态、设备或输出的操作; -- 如果某个共享智能体拥有敏感凭证 / 文件,那么任何被允许的发送者都可能通过工具使用驱动数据外泄。 +- 任何被允许的发送者都可以在智能体策略范围内触发工具调用(`exec`、浏览器、网络/文件工具); +- 来自某个发送者的提示/内容注入,可能导致影响共享状态、设备或输出的操作; +- 如果某个共享智能体持有敏感凭证/文件,任何被允许的发送者都有可能通过工具使用驱动数据外泄。 -团队工作流应使用最小工具集的单独智能体 / Gateway 网关;涉及个人数据的智能体应保持私有。 +对于团队工作流,请使用工具最小化的独立智能体/Gateway 网关;存有个人数据的智能体应保持私有。 ### 公司共享智能体:可接受模式 -当使用该智能体的所有人都处于同一个信任边界内(例如同一个公司团队),且该智能体严格限定在业务范围内时,这种模式是可接受的。 +当该智能体的所有使用者都处于同一个信任边界内(例如同一个公司团队),并且该智能体严格限定在业务范围内时,这是可接受的。 -- 在专用机器 / VM / 容器中运行它; -- 为该运行时使用专用的 OS 用户 + 专用浏览器 / 配置文件 / 账号; -- 不要让该运行时登录你的个人 Apple / Google 账号,也不要使用个人密码管理器 / 浏览器配置文件。 +- 在专用机器/VM/容器上运行它; +- 为该运行时使用专用 OS 用户 + 专用浏览器/配置文件/账户; +- 不要让该运行时登录个人 Apple/Google 账户,或个人密码管理器/浏览器配置文件。 -如果你在同一运行时中混用个人身份和公司身份,就会打破隔离并增加个人数据暴露风险。 +如果你在同一个运行时中混用个人身份和公司身份,就会破坏隔离并增加个人数据暴露风险。 -## Gateway 网关与节点信任概念 +## Gateway 网关与 node 的信任概念 -应将 Gateway 网关和节点视为同一个操作员信任域中的不同角色: +将 Gateway 网关 和 node 视为同一个操作员信任域中的不同角色: -- **Gateway 网关** 是控制平面和策略层(`gateway.auth`、工具策略、路由)。 -- **节点** 是与该 Gateway 网关配对的远程执行层(命令、设备操作、主机本地能力)。 -- 对 Gateway 网关完成认证的调用方,在 Gateway 网关范围内被视为受信任。完成配对后,节点操作就是该节点上的受信任操作员操作。 -- `sessionKey` 是路由 / 上下文选择键,不是按用户划分的认证。 -- Exec 审批(allowlist + 询问)是对操作员意图的保护措施,不是敌对多租户隔离。 -- OpenClaw 针对受信任单操作员配置的产品默认值是:允许在 `gateway` / `node` 上执行主机 exec,而无需审批提示(`security="full"`、`ask="off"`,除非你手动收紧)。这个默认值是有意设计的 UX,不应因此本身就被视为漏洞。 -- Exec 审批会绑定精确的请求上下文以及尽力识别的直接本地文件操作数;它不会对每一种运行时 / 解释器加载路径做语义建模。若需要强边界,请使用沙箱隔离和主机隔离。 +- **Gateway 网关** 是控制平面和策略表面(`gateway.auth`、工具策略、路由)。 +- **Node** 是与该 Gateway 网关配对的远程执行表面(命令、设备操作、主机本地能力)。 +- 通过 Gateway 网关鉴权的调用方,在 Gateway 网关范围内被视为受信任。完成配对后,node 操作即为该 node 上的受信任操作员操作。 +- `sessionKey` 是路由/上下文选择,不是按用户划分的鉴权。 +- Exec 审批(allowlist + 询问)是对操作员意图的护栏,不是敌对多租户隔离。 +- 对于受信任单操作员场景,OpenClaw 的产品默认行为是允许在 `gateway`/`node` 上进行主机 exec,而无需审批提示(`security="full"`、`ask="off"`,除非你主动收紧)。这是一种有意的 UX 默认值,本身不是漏洞。 +- Exec 审批会绑定精确的请求上下文,以及尽力解析的直接本地文件操作数;它们不会对每一种运行时/解释器加载路径做语义建模。若需要强边界,请使用沙箱隔离和主机隔离。 -如果你需要敌对用户隔离,请按 OS 用户 / 主机拆分信任边界,并运行单独的 Gateway 网关。 +如果你需要敌对用户隔离,请按 OS 用户/主机拆分信任边界,并运行独立的 Gateway 网关。 ## 信任边界矩阵 -在进行风险研判时,可将此表作为快速模型: +在进行风险分级时,可将此作为快速模型: -| 边界或控制 | 含义 | 常见误解 | +| 边界或控制 | 它的含义 | 常见误读 | | --- | --- | --- | -| `gateway.auth`(token/password/trusted-proxy/device auth) | 对 Gateway 网关 API 的调用方进行认证 | “要想安全,每一帧消息都必须有按消息签名” | -| `sessionKey` | 用于上下文 / 会话选择的路由键 | “Session key 是用户认证边界” | -| 提示 / 内容保护措施 | 降低模型被滥用的风险 | “只要有提示注入就说明认证被绕过了” | -| `canvas.eval` / 浏览器 evaluate | 启用时属于有意提供给操作员的能力 | “任何 JS eval 原语在这个信任模型里都自动算漏洞” | +| `gateway.auth`(token/password/trusted-proxy/device auth) | 对 Gateway 网关 API 调用方进行鉴权 | “为了安全,每一帧消息都必须带按消息签名” | +| `sessionKey` | 用于上下文/会话选择的路由键 | “会话键是用户鉴权边界” | +| 提示/内容护栏 | 降低模型滥用风险 | “仅凭 prompt injection 就能证明鉴权绕过” | +| `canvas.eval` / 浏览器 evaluate | 启用时属于有意提供给操作员的能力 | “任何 JS eval 原语在这个信任模型下都会自动成为漏洞” | | 本地 TUI `!` shell | 由操作员显式触发的本地执行 | “本地 shell 便捷命令就是远程注入” | -| 节点配对和节点命令 | 对已配对设备的操作员级远程执行 | “远程设备控制默认应被视为不受信任用户访问” | +| Node 配对和 node 命令 | 对已配对设备的操作员级远程执行 | “默认应把远程设备控制视为不受信任用户访问” | -## 按设计不属于漏洞的问题 +## 按设计不算漏洞的情况 -以下模式经常被报告,但通常会被认定为无需处理,除非展示了真实的边界绕过: +这些模式经常被报告,但通常会被判定为无需处理,除非证明了真实的边界绕过: -- 仅靠提示注入链条、但没有策略 / 认证 / 沙箱绕过的情况。 -- 基于“单个共享主机 / 配置上存在敌对多租户运行”这一前提提出的声明。 -- 把正常的操作员读取路径访问(例如 `sessions.list` / `sessions.preview` / `chat.history`)在共享 Gateway 网关配置中归类为 IDOR 的声明。 -- 仅限 localhost 部署的发现(例如仅 loopback Gateway 网关上的 HSTS 问题)。 +- 仅有 prompt injection 链条,但没有策略/鉴权/沙箱隔离绕过。 +- 假设在同一共享主机/配置上进行敌对多租户运行的论断。 +- 将正常的操作员读取路径访问(例如 `sessions.list`/`sessions.preview`/`chat.history`)在共享 Gateway 网关配置中归类为 IDOR 的报告。 +- 仅限 localhost 部署的发现(例如仅 loopback Gateway 网关缺少 HSTS)。 - 针对本仓库中并不存在的入站路径,报告 Discord 入站 webhook 签名问题。 -- 将节点配对元数据误认为 `system.run` 的隐藏第二层逐命令审批机制的报告,而真实执行边界实际上仍然是 Gateway 网关的全局节点命令策略加上节点自身的 exec 审批。 -- 把 `sessionKey` 当作认证令牌,并据此报告“缺少按用户授权”的问题。 +- 将 node 配对元数据视为 `system.run` 的隐藏式第二层逐命令审批的报告,而实际执行边界仍然是 Gateway 网关的全局 node 命令策略,加上 node 自身的 exec 审批。 +- 将 `sessionKey` 视为 auth token 的“缺少按用户授权”发现。 ## 研究人员预检清单 -在提交 GHSA 之前,请确认以下所有事项: +在提交 GHSA 之前,请确认以下各项: -1. 在最新的 `main` 或最新发布版本上,复现仍然有效。 -2. 报告包含精确的代码路径(`file`、函数、行范围)以及测试所用的版本 / commit。 -3. 影响跨越了文档中定义的信任边界(而不只是提示注入)。 -4. 该声明未列在 [Out of Scope](https://github.com/openclaw/openclaw/blob/main/SECURITY.md#out-of-scope) 中。 -5. 已检查现有公告是否重复(适用时复用规范 GHSA)。 -6. 已明确部署假设(loopback / 本地 或 暴露到外部、受信任操作员 或 不受信任操作员)。 +1. 复现仍可在最新 `main` 或最新发布版本上成立。 +2. 报告包含精确代码路径(`file`、函数、行范围)以及测试版本/commit。 +3. 影响跨越了文档化的信任边界(而不只是 prompt injection)。 +4. 该结论未列在 [Out of Scope](https://github.com/openclaw/openclaw/blob/main/SECURITY.md#out-of-scope) 中。 +5. 已检查现有 advisory 是否重复(适用时复用规范 GHSA)。 +6. 明确写出部署假设(loopback/本地 还是 暴露到外部;受信任操作员 还是 不受信任操作员)。 -## 六十秒建立加固基线 +## 六十秒内建立强化基线 -先使用这个基线,然后再按受信任智能体逐项重新启用工具: +先使用这个基线,然后再按受信任智能体有选择地重新启用工具: ```json5 { @@ -167,205 +167,209 @@ OpenClaw 假设主机和配置边界是受信任的: } ``` -这样会将 Gateway 网关限制为仅本地访问、隔离私信,并默认禁用控制平面 / 运行时工具。 +这样会让 Gateway 网关仅限本地访问、隔离私信,并默认禁用控制平面/运行时工具。 ## 共享收件箱快速规则 -如果超过一个人可以给你的机器人发私信: +如果不止一个人可以给你的机器人发私信: -- 设置 `session.dmScope: "per-channel-peer"`(多账号渠道则使用 `"per-account-channel-peer"`)。 -- 保持 `dmPolicy: "pairing"` 或使用严格的 allowlist。 -- 绝不要把共享私信与宽泛工具访问结合使用。 -- 这能加固协作式 / 共享收件箱,但并不是为在用户共享主机 / 配置写权限时提供敌对共租户隔离而设计的。 +- 设置 `session.dmScope: "per-channel-peer"`(多账户渠道则使用 `"per-account-channel-peer"`)。 +- 保持 `dmPolicy: "pairing"` 或严格的 allowlist。 +- 绝不要把共享私信和宽泛的工具访问组合在一起。 +- 这有助于加固协作式/共享收件箱,但并不是为了在用户共享主机/配置写权限时实现敌对共租户隔离。 ## 上下文可见性模型 -OpenClaw 将两个概念分开处理: +OpenClaw 区分两个概念: -- **触发授权**:谁可以触发智能体(`dmPolicy`、`groupPolicy`、allowlist、mention 门槛)。 -- **上下文可见性**:哪些补充上下文会被注入到模型输入中(回复正文、引用文本、线程历史、转发元数据)。 +- **触发授权**:谁可以触发智能体(`dmPolicy`、`groupPolicy`、allowlist、提及门控)。 +- **上下文可见性**:哪些补充上下文会注入模型输入(回复正文、引用文本、线程历史、转发元数据)。 -Allowlist 控制触发和命令授权。`contextVisibility` 设置则控制如何过滤补充上下文(引用回复、线程根消息、抓取的历史消息): +Allowlists 用于控制触发和命令授权。`contextVisibility` 设置控制如何过滤补充上下文(引用回复、线程根消息、抓取的历史): -- `contextVisibility: "all"`(默认)会保留收到的全部补充上下文。 -- `contextVisibility: "allowlist"` 会将补充上下文过滤为仅包含通过当前 allowlist 检查的发送者内容。 -- `contextVisibility: "allowlist_quote"` 的行为类似 `allowlist`,但仍保留一条显式引用的回复。 +- `contextVisibility: "all"`(默认)按接收原样保留补充上下文。 +- `contextVisibility: "allowlist"` 只保留通过活动 allowlist 检查的发送者提供的补充上下文。 +- `contextVisibility: "allowlist_quote"` 的行为与 `allowlist` 相同,但仍保留一条显式引用回复。 -你可以按渠道或按房间 / 会话设置 `contextVisibility`。配置细节请参阅 [群聊](/zh-CN/channels/groups#context-visibility-and-allowlists)。 +你可以按渠道或按房间/对话设置 `contextVisibility`。有关设置细节,请参阅 [Group Chats](/zh-CN/channels/groups#context-visibility-and-allowlists)。 -公告分诊指引: +Advisory 分级指引: -- 仅展示“模型可以看到来自未列入 allowlist 的发送者的引用文本或历史文本”的声明,属于可通过 `contextVisibility` 处理的加固问题,本身并不构成认证或沙箱边界绕过。 -- 若要构成真正的安全影响,报告仍需证明存在信任边界绕过(认证、策略、沙箱、审批或其他文档化边界)。 +- 仅能证明“模型可以看到来自未在 allowlist 中发送者的引用或历史文本”的说法,属于可通过 `contextVisibility` 处理的加固问题,本身并不构成鉴权或沙箱隔离边界绕过。 +- 若要构成真正的安全影响,报告仍需证明存在信任边界绕过(鉴权、策略、沙箱隔离、审批,或其他文档化边界)。 -## 审计检查的内容(高层级) +## 审计会检查什么(高层级) - **入站访问**(私信策略、群组策略、allowlist):陌生人能否触发机器人? -- **工具影响半径**(elevated 工具 + 开放房间):提示注入是否可能演变为 shell / 文件 / 网络操作? -- **Exec 审批漂移**(`security=full`、`autoAllowSkills`、未启用 `strictInlineEval` 的解释器 allowlist):主机 exec 防护措施是否仍按你的预期工作? - - `security="full"` 是一种宽泛姿态警告,不代表存在 bug。它是面向受信任个人助理配置选择的默认值;只有当你的威胁模型确实需要审批或 allowlist 防护时,才应收紧它。 -- **网络暴露**(Gateway 网关 bind/auth、Tailscale Serve/Funnel、弱或过短的认证 token)。 -- **浏览器控制暴露**(远程节点、relay 端口、远程 CDP 端点)。 +- **工具影响半径**(高权限工具 + 开放房间):prompt injection 是否可能演变为 shell/文件/网络操作? +- **Exec 审批漂移**(`security=full`、`autoAllowSkills`、未启用 `strictInlineEval` 的解释器 allowlist):主机 exec 护栏是否仍按你的预期工作? + - `security="full"` 是一种宽泛姿态警告,不代表存在 bug。它是受信任个人助理场景下选择的默认值;只有当你的威胁模型需要审批或 allowlist 护栏时,才需要收紧它。 +- **网络暴露**(Gateway 网关 bind/auth、Tailscale Serve/Funnel、弱/短鉴权 token)。 +- **浏览器控制暴露**(远程 node、中继端口、远程 CDP 端点)。 - **本地磁盘卫生**(权限、符号链接、配置 includes、“同步文件夹”路径)。 -- **插件**(插件在没有显式 allowlist 的情况下加载)。 -- **策略漂移 / 配置错误**(配置了沙箱 docker 设置但沙箱模式关闭;无效的 `gateway.nodes.denyCommands` 模式,因为匹配仅针对精确命令名,例如 `system.run`,而不会检查 shell 文本;危险的 `gateway.nodes.allowCommands` 条目;全局 `tools.profile="minimal"` 被按智能体的 profile 覆盖;在宽松工具策略下可访问插件自有工具)。 -- **运行时预期漂移**(例如误以为隐式 exec 仍表示 `sandbox`,但 `tools.exec.host` 现在默认是 `auto`;或者明确设置了 `tools.exec.host="sandbox"`,但沙箱模式实际上是关闭的)。 -- **模型卫生**(当配置的模型看起来较旧时发出警告;不是硬性阻断)。 +- **插件**(插件加载不需要显式 allowlist)。 +- **策略漂移/配置错误**(配置了 sandbox docker 设置但 sandbox 模式关闭;无效的 `gateway.nodes.denyCommands` 模式,因为匹配仅基于精确命令名,例如 `system.run`,不会检查 shell 文本;危险的 `gateway.nodes.allowCommands` 条目;全局 `tools.profile="minimal"` 被按智能体的 profile 覆盖;在宽松工具策略下可访问由插件拥有的工具)。 +- **运行时预期漂移**(例如误以为隐式 exec 仍表示 `sandbox`,而 `tools.exec.host` 现在默认是 `auto`;或者显式设置 `tools.exec.host="sandbox"`,但 sandbox 模式实际上已关闭)。 +- **模型卫生**(当配置的模型看起来属于旧版时发出警告;不是硬性阻止)。 -如果你运行 `--deep`,OpenClaw 还会尽力尝试对实时 Gateway 网关进行探测。 +如果你运行 `--deep`,OpenClaw 还会尽力尝试执行实时 Gateway 网关探测。 ## 凭证存储映射 -在审计访问权限或决定备份内容时,可使用此映射: +在审计访问或决定备份内容时,可使用此映射: - **WhatsApp**:`~/.openclaw/credentials/whatsapp//creds.json` -- **Telegram 机器人 token**:config / env 或 `channels.telegram.tokenFile`(仅允许普通文件;拒绝符号链接) -- **Discord 机器人 token**:config / env 或 SecretRef(env/file/exec 提供商) -- **Slack token**:config / env(`channels.slack.*`) +- **Telegram 机器人令牌**:config/env 或 `channels.telegram.tokenFile`(仅常规文件;拒绝符号链接) +- **Discord 机器人令牌**:config/env 或 SecretRef(env/file/exec providers) +- **Slack 令牌**:config/env(`channels.slack.*`) - **配对 allowlist**: - - `~/.openclaw/credentials/-allowFrom.json`(默认账号) - - `~/.openclaw/credentials/--allowFrom.json`(非默认账号) -- **模型认证配置文件**:`~/.openclaw/agents//agent/auth-profiles.json` + - `~/.openclaw/credentials/-allowFrom.json`(默认账户) + - `~/.openclaw/credentials/--allowFrom.json`(非默认账户) +- **模型鉴权配置文件**:`~/.openclaw/agents//agent/auth-profiles.json` - **基于文件的 secrets 负载(可选)**:`~/.openclaw/secrets.json` - **旧版 OAuth 导入**:`~/.openclaw/credentials/oauth.json` ## 安全审计检查清单 -当审计输出发现项时,请按以下优先级处理: +当审计输出发现项时,请按以下优先级顺序处理: -1. **任何“开放” + 已启用工具**:先锁定私信 / 群组(pairing / allowlist),然后收紧工具策略 / 沙箱隔离。 -2. **公共网络暴露**(LAN bind、Funnel、缺少认证):立即修复。 -3. **浏览器控制的远程暴露**:应将其视为操作员级访问(仅限 tailnet、谨慎配对节点、避免公开暴露)。 -4. **权限**:确保 state / config / credentials / auth 不对组用户或所有人可读。 -5. **插件**:只加载你明确信任的插件。 -6. **模型选择**:对于任何启用了工具的机器人,优先使用现代、具备更强指令防护能力的模型。 +1. **任何 “open” + 已启用工具**:先锁定私信/群组(pairing/allowlist),然后收紧工具策略/沙箱隔离。 +2. **公共网络暴露**(LAN bind、Funnel、缺少鉴权):立即修复。 +3. **浏览器控制的远程暴露**:将其视为操作员访问(仅限 tailnet、谨慎配对 node、避免公开暴露)。 +4. **权限**:确保状态/配置/凭证/auth 对 group/world 不可读。 +5. **插件**:只加载你明确信任的内容。 +6. **模型选择**:对于任何带工具的机器人,优先使用现代的、具备更强指令加固能力的模型。 ## 安全审计术语表 -在真实部署中你最可能看到的高信号 `checkId` 值如下(并非完整列表): +你在真实部署中最可能看到的高信号 `checkId` 值如下(并非穷尽): -| `checkId` | 严重级别 | 为什么重要 | 主要修复键 / 路径 | 自动修复 | +| `checkId` | 严重级别 | 为什么重要 | 主要修复键/路径 | 自动修复 | | --- | --- | --- | --- | --- | -| `fs.state_dir.perms_world_writable` | critical | 其他用户 / 进程可以修改整个 OpenClaw 状态 | `~/.openclaw` 的文件系统权限 | 是 | -| `fs.state_dir.perms_group_writable` | warn | 同组用户可以修改整个 OpenClaw 状态 | `~/.openclaw` 的文件系统权限 | 是 | -| `fs.state_dir.perms_readable` | warn | 状态目录可被其他人读取 | `~/.openclaw` 的文件系统权限 | 是 | -| `fs.state_dir.symlink` | warn | 状态目录目标会变成另一个信任边界 | 状态目录的文件系统布局 | 否 | -| `fs.config.perms_writable` | critical | 其他人可以更改 auth / 工具策略 / 配置 | `~/.openclaw/openclaw.json` 的文件系统权限 | 是 | -| `fs.config.symlink` | warn | 不支持通过符号链接配置文件进行写入,而且这会引入另一个信任边界 | 替换为常规配置文件,或将 `OPENCLAW_CONFIG_PATH` 指向真实文件 | 否 | -| `fs.config.perms_group_readable` | warn | 同组用户可以读取配置 token / 设置 | 配置文件的文件系统权限 | 是 | -| `fs.config.perms_world_readable` | critical | 配置可能暴露 token / 设置 | 配置文件的文件系统权限 | 是 | -| `fs.config_include.perms_writable` | critical | 配置 include 文件可被他人修改 | `openclaw.json` 引用的 include 文件权限 | 是 | -| `fs.config_include.perms_group_readable` | warn | 同组用户可以读取 include 的 secrets / 设置 | `openclaw.json` 引用的 include 文件权限 | 是 | -| `fs.config_include.perms_world_readable` | critical | include 的 secrets / 设置对所有人可读 | `openclaw.json` 引用的 include 文件权限 | 是 | -| `fs.auth_profiles.perms_writable` | critical | 其他人可以注入或替换已存储的模型凭证 | `agents//agent/auth-profiles.json` 权限 | 是 | -| `fs.auth_profiles.perms_readable` | warn | 其他人可以读取 API key 和 OAuth token | `agents//agent/auth-profiles.json` 权限 | 是 | -| `fs.credentials_dir.perms_writable` | critical | 其他人可以修改渠道配对 / 凭证状态 | `~/.openclaw/credentials` 的文件系统权限 | 是 | -| `fs.credentials_dir.perms_readable` | warn | 其他人可以读取渠道凭证状态 | `~/.openclaw/credentials` 的文件系统权限 | 是 | -| `fs.sessions_store.perms_readable` | warn | 其他人可以读取会话转录 / 元数据 | session 存储权限 | 是 | -| `fs.log_file.perms_readable` | warn | 其他人可以读取虽已脱敏但仍然敏感的日志 | Gateway 网关日志文件权限 | 是 | -| `fs.synced_dir` | warn | 状态 / 配置位于 iCloud / Dropbox / Drive 中会扩大 token / 转录暴露面 | 将配置 / 状态迁出同步文件夹 | 否 | -| `gateway.bind_no_auth` | critical | 远程 bind 但没有共享密钥 | `gateway.bind`、`gateway.auth.*` | 否 | -| `gateway.loopback_no_auth` | critical | 经反向代理暴露的 loopback 可能变成未认证访问 | `gateway.auth.*`、代理配置 | 否 | -| `gateway.trusted_proxies_missing` | warn | 存在反向代理头,但未将代理标记为受信任 | `gateway.trustedProxies` | 否 | -| `gateway.http.no_auth` | warn/critical | Gateway 网关 HTTP API 在 `auth.mode="none"` 下可访问 | `gateway.auth.mode`、`gateway.http.endpoints.*` | 否 | -| `gateway.http.session_key_override_enabled` | info | HTTP API 调用方可以覆盖 `sessionKey` | `gateway.http.allowSessionKeyOverride` | 否 | -| `gateway.tools_invoke_http.dangerous_allow` | warn/critical | 重新允许通过 HTTP API 调用危险工具 | `gateway.tools.allow` | 否 | -| `gateway.nodes.allow_commands_dangerous` | warn/critical | 启用高影响节点命令(camera/screen/contacts/calendar/SMS) | `gateway.nodes.allowCommands` | 否 | -| `gateway.nodes.deny_commands_ineffective` | warn | 类似模式的 deny 条目不会匹配 shell 文本或命令组 | `gateway.nodes.denyCommands` | 否 | -| `gateway.tailscale_funnel` | critical | 暴露到公共互联网 | `gateway.tailscale.mode` | 否 | -| `gateway.tailscale_serve` | info | 已通过 Serve 启用 tailnet 暴露 | `gateway.tailscale.mode` | 否 | -| `gateway.control_ui.allowed_origins_required` | critical | 非 loopback 的控制 UI 缺少显式浏览器来源 allowlist | `gateway.controlUi.allowedOrigins` | 否 | -| `gateway.control_ui.allowed_origins_wildcard` | warn/critical | `allowedOrigins=["*"]` 会禁用浏览器来源 allowlist | `gateway.controlUi.allowedOrigins` | 否 | -| `gateway.control_ui.host_header_origin_fallback` | warn/critical | 启用 Host header 来源回退(降低 DNS rebinding 防护强度) | `gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback` | 否 | -| `gateway.control_ui.insecure_auth` | warn | 已启用不安全认证兼容开关 | `gateway.controlUi.allowInsecureAuth` | 否 | -| `gateway.control_ui.device_auth_disabled` | critical | 禁用了设备身份检查 | `gateway.controlUi.dangerouslyDisableDeviceAuth` | 否 | -| `gateway.real_ip_fallback_enabled` | warn/critical | 信任 `X-Real-IP` 回退可能因代理配置错误而导致源 IP 欺骗 | `gateway.allowRealIpFallback`、`gateway.trustedProxies` | 否 | -| `gateway.token_too_short` | warn | 过短的共享 token 更容易被暴力破解 | `gateway.auth.token` | 否 | -| `gateway.auth_no_rate_limit` | warn | 暴露的认证接口若没有速率限制,会增加暴力破解风险 | `gateway.auth.rateLimit` | 否 | -| `gateway.trusted_proxy_auth` | critical | 代理身份现在成为认证边界 | `gateway.auth.mode="trusted-proxy"` | 否 | -| `gateway.trusted_proxy_no_proxies` | critical | 使用 trusted-proxy 认证但未配置受信任代理 IP,不安全 | `gateway.trustedProxies` | 否 | -| `gateway.trusted_proxy_no_user_header` | critical | trusted-proxy 认证无法安全解析用户身份 | `gateway.auth.trustedProxy.userHeader` | 否 | -| `gateway.trusted_proxy_no_allowlist` | warn | trusted-proxy 认证会接受任何已通过上游认证的用户 | `gateway.auth.trustedProxy.allowUsers` | 否 | -| `gateway.probe_auth_secretref_unavailable` | warn | 深度探测在当前命令路径下无法解析 auth SecretRef | 深度探测的认证来源 / SecretRef 可用性 | 否 | -| `gateway.probe_failed` | warn/critical | 实时 Gateway 网关探测失败 | Gateway 网关可达性 / 认证 | 否 | -| `discovery.mdns_full_mode` | warn/critical | mDNS 完整模式会在本地网络上广播 `cliPath` / `sshPort` 元数据 | `discovery.mdns.mode`、`gateway.bind` | 否 | -| `config.insecure_or_dangerous_flags` | warn | 启用了任意不安全 / 危险的调试标志 | 多个键(见发现详情) | 否 | -| `config.secrets.gateway_password_in_config` | warn | Gateway 网关密码直接存储在配置中 | `gateway.auth.password` | 否 | -| `config.secrets.hooks_token_in_config` | warn | Hook bearer token 直接存储在配置中 | `hooks.token` | 否 | -| `hooks.token_reuse_gateway_token` | critical | Hook 入站 token 同时可用于解锁 Gateway 网关认证 | `hooks.token`、`gateway.auth.token` | 否 | -| `hooks.token_too_short` | warn | Hook 入站更容易被暴力破解 | `hooks.token` | 否 | -| `hooks.default_session_key_unset` | warn | Hook 智能体运行会分散到按请求生成的 session 中 | `hooks.defaultSessionKey` | 否 | -| `hooks.allowed_agent_ids_unrestricted` | warn/critical | 已认证的 Hook 调用方可以路由到任意已配置智能体 | `hooks.allowedAgentIds` | 否 | -| `hooks.request_session_key_enabled` | warn/critical | 外部调用方可以选择 `sessionKey` | `hooks.allowRequestSessionKey` | 否 | -| `hooks.request_session_key_prefixes_missing` | warn/critical | 对外部 session key 的形状没有限制 | `hooks.allowedSessionKeyPrefixes` | 否 | -| `hooks.path_root` | critical | Hook 路径为 `/`,更容易发生入站冲突或误路由 | `hooks.path` | 否 | -| `hooks.installs_unpinned_npm_specs` | warn | Hook 安装记录未固定到不可变的 npm 规格 | Hook 安装元数据 | 否 | -| `hooks.installs_missing_integrity` | warn | Hook 安装记录缺少完整性元数据 | Hook 安装元数据 | 否 | -| `hooks.installs_version_drift` | warn | Hook 安装记录与已安装包存在版本漂移 | Hook 安装元数据 | 否 | -| `logging.redact_off` | warn | 敏感值会泄露到日志 / 状态中 | `logging.redactSensitive` | 是 | -| `browser.control_invalid_config` | warn | 浏览器控制配置在运行前即无效 | `browser.*` | 否 | -| `browser.control_no_auth` | critical | 浏览器控制在没有 token / 密码认证的情况下暴露 | `gateway.auth.*` | 否 | -| `browser.remote_cdp_http` | warn | 通过纯 HTTP 连接远程 CDP 缺少传输加密 | 浏览器 profile `cdpUrl` | 否 | -| `browser.remote_cdp_private_host` | warn | 远程 CDP 指向私有 / 内部主机 | 浏览器 profile `cdpUrl`、`browser.ssrfPolicy.*` | 否 | -| `sandbox.docker_config_mode_off` | warn | 已存在沙箱 Docker 配置,但当前未启用 | `agents.*.sandbox.mode` | 否 | -| `sandbox.bind_mount_non_absolute` | warn | 相对 bind mount 的解析结果可能不可预测 | `agents.*.sandbox.docker.binds[]` | 否 | -| `sandbox.dangerous_bind_mount` | critical | 沙箱 bind mount 指向被阻止的系统、凭证或 Docker socket 路径 | `agents.*.sandbox.docker.binds[]` | 否 | -| `sandbox.dangerous_network_mode` | critical | 沙箱 Docker 网络使用 `host` 或 `container:*` 命名空间加入模式 | `agents.*.sandbox.docker.network` | 否 | -| `sandbox.dangerous_seccomp_profile` | critical | 沙箱 seccomp profile 会削弱容器隔离 | `agents.*.sandbox.docker.securityOpt` | 否 | -| `sandbox.dangerous_apparmor_profile` | critical | 沙箱 AppArmor profile 会削弱容器隔离 | `agents.*.sandbox.docker.securityOpt` | 否 | -| `sandbox.browser_cdp_bridge_unrestricted` | warn | 沙箱浏览器桥接在没有源范围限制的情况下暴露 | `sandbox.browser.cdpSourceRange` | 否 | -| `sandbox.browser_container.non_loopback_publish` | critical | 现有浏览器容器在非 loopback 接口上发布 CDP | 浏览器沙箱容器发布配置 | 否 | -| `sandbox.browser_container.hash_label_missing` | warn | 现有浏览器容器早于当前配置哈希标签机制 | `openclaw sandbox recreate --browser --all` | 否 | -| `sandbox.browser_container.hash_epoch_stale` | warn | 现有浏览器容器早于当前浏览器配置 epoch | `openclaw sandbox recreate --browser --all` | 否 | -| `tools.exec.host_sandbox_no_sandbox_defaults` | warn | 当沙箱关闭时,`exec host=sandbox` 会以关闭方式失败 | `tools.exec.host`、`agents.defaults.sandbox.mode` | 否 | -| `tools.exec.host_sandbox_no_sandbox_agents` | warn | 当沙箱关闭时,按智能体设置的 `exec host=sandbox` 会以关闭方式失败 | `agents.list[].tools.exec.host`、`agents.list[].sandbox.mode` | 否 | -| `tools.exec.security_full_configured` | warn/critical | 主机 exec 以 `security="full"` 运行 | `tools.exec.security`、`agents.list[].tools.exec.security` | 否 | -| `tools.exec.auto_allow_skills_enabled` | warn | Exec 审批会隐式信任 skill bin | `~/.openclaw/exec-approvals.json` | 否 | -| `tools.exec.allowlist_interpreter_without_strict_inline_eval` | warn | 解释器 allowlist 允许内联 eval,且不会强制重新审批 | `tools.exec.strictInlineEval`、`agents.list[].tools.exec.strictInlineEval`、exec 审批 allowlist | 否 | -| `tools.exec.safe_bins_interpreter_unprofiled` | warn | `safeBins` 中的解释器 / 运行时 bin 若无显式 profile,会扩大 exec 风险 | `tools.exec.safeBins`、`tools.exec.safeBinProfiles`、`agents.list[].tools.exec.*` | 否 | -| `tools.exec.safe_bins_broad_behavior` | warn | `safeBins` 中的宽泛行为工具会削弱低风险 stdin 过滤信任模型 | `tools.exec.safeBins`、`agents.list[].tools.exec.safeBins` | 否 | -| `tools.exec.safe_bin_trusted_dirs_risky` | warn | `safeBinTrustedDirs` 包含可变或高风险目录 | `tools.exec.safeBinTrustedDirs`、`agents.list[].tools.exec.safeBinTrustedDirs` | 否 | -| `skills.workspace.symlink_escape` | warn | 工作区 `skills/**/SKILL.md` 解析到了工作区根目录之外(符号链接链漂移) | 工作区 `skills/**` 文件系统状态 | 否 | -| `plugins.extensions_no_allowlist` | warn | 插件安装时未配置显式插件 allowlist | `plugins.allowlist` | 否 | -| `plugins.installs_unpinned_npm_specs` | warn | 插件安装记录未固定到不可变的 npm 规格 | 插件安装元数据 | 否 | -| `plugins.installs_missing_integrity` | warn | 插件安装记录缺少完整性元数据 | 插件安装元数据 | 否 | -| `plugins.installs_version_drift` | warn | 插件安装记录与已安装包存在版本漂移 | 插件安装元数据 | 否 | -| `plugins.code_safety` | warn/critical | 插件代码扫描发现可疑或危险模式 | 插件代码 / 安装来源 | 否 | -| `plugins.code_safety.entry_path` | warn | 插件入口路径指向隐藏目录或 `node_modules` 位置 | 插件清单中的 `entry` | 否 | -| `plugins.code_safety.entry_escape` | critical | 插件入口逃逸出插件目录 | 插件清单中的 `entry` | 否 | -| `plugins.code_safety.scan_failed` | warn | 插件代码扫描未能完成 | 插件路径 / 扫描环境 | 否 | -| `skills.code_safety` | warn/critical | Skill 安装器元数据 / 代码包含可疑或危险模式 | skill 安装来源 | 否 | -| `skills.code_safety.scan_failed` | warn | Skill 代码扫描未能完成 | skill 扫描环境 | 否 | -| `security.exposure.open_channels_with_exec` | warn/critical | 共享 / 公开房间可以访问启用了 exec 的智能体 | `channels.*.dmPolicy`、`channels.*.groupPolicy`、`tools.exec.*`、`agents.list[].tools.exec.*` | 否 | -| `security.exposure.open_groups_with_elevated` | critical | 开放群组 + elevated 工具会形成高影响的提示注入路径 | `channels.*.groupPolicy`、`tools.elevated.*` | 否 | -| `security.exposure.open_groups_with_runtime_or_fs` | critical/warn | 开放群组在没有沙箱 / 工作区保护时可以访问命令 / 文件工具 | `channels.*.groupPolicy`、`tools.profile/deny`、`tools.fs.workspaceOnly`、`agents.*.sandbox.mode` | 否 | -| `security.trust_model.multi_user_heuristic` | warn | 配置看起来像多用户场景,但 Gateway 网关信任模型是个人助理 | 拆分信任边界,或进行共享用户加固(`sandbox.mode`、工具 deny / 工作区范围限制) | 否 | -| `tools.profile_minimal_overridden` | warn | 智能体覆盖配置绕过了全局 minimal profile | `agents.list[].tools.profile` | 否 | -| `plugins.tools_reachable_permissive_policy` | warn | 在宽松策略上下文中可以访问扩展工具 | `tools.profile` + 工具 allow / deny | 否 | -| `models.legacy` | warn | 仍然配置了旧版模型家族 | 模型选择 | 否 | -| `models.weak_tier` | warn | 已配置模型低于当前推荐等级 | 模型选择 | 否 | -| `models.small_params` | critical/info | 小参数模型 + 不安全工具接口会提高注入风险 | 模型选择 + 沙箱 / 工具策略 | 否 | -| `summary.attack_surface` | info | 对认证、渠道、工具和暴露姿态的汇总摘要 | 多个键(见发现详情) | 否 | +| `fs.state_dir.perms_world_writable` | critical | 其他用户/进程可以修改完整的 OpenClaw 状态 | `~/.openclaw` 的文件系统权限 | yes | +| `fs.state_dir.perms_group_writable` | warn | 同组用户可以修改完整的 OpenClaw 状态 | `~/.openclaw` 的文件系统权限 | yes | +| `fs.state_dir.perms_readable` | warn | 其他人可以读取状态目录 | `~/.openclaw` 的文件系统权限 | yes | +| `fs.state_dir.symlink` | warn | 状态目录目标变成了另一个信任边界 | 状态目录的文件系统布局 | no | +| `fs.config.perms_writable` | critical | 其他人可以更改 auth/工具策略/配置 | `~/.openclaw/openclaw.json` 的文件系统权限 | yes | +| `fs.config.symlink` | warn | 不支持通过符号链接配置文件进行写入,并且会引入另一个信任边界 | 替换为常规配置文件,或将 `OPENCLAW_CONFIG_PATH` 指向真实文件 | no | +| `fs.config.perms_group_readable` | warn | 同组用户可以读取配置 token/设置 | 配置文件的文件系统权限 | yes | +| `fs.config.perms_world_readable` | critical | 配置可能暴露 token/设置 | 配置文件的文件系统权限 | yes | +| `fs.config_include.perms_writable` | critical | 配置 include 文件可被他人修改 | 从 `openclaw.json` 引用的 include 文件权限 | yes | +| `fs.config_include.perms_group_readable` | warn | 同组用户可以读取 include 的 secrets/设置 | 从 `openclaw.json` 引用的 include 文件权限 | yes | +| `fs.config_include.perms_world_readable` | critical | include 的 secrets/设置对所有人可读 | 从 `openclaw.json` 引用的 include 文件权限 | yes | +| `fs.auth_profiles.perms_writable` | critical | 其他人可以注入或替换已存储的模型凭证 | `agents//agent/auth-profiles.json` 权限 | yes | +| `fs.auth_profiles.perms_readable` | warn | 其他人可以读取 API 密钥和 OAuth token | `agents//agent/auth-profiles.json` 权限 | yes | +| `fs.credentials_dir.perms_writable` | critical | 其他人可以修改渠道配对/凭证状态 | `~/.openclaw/credentials` 的文件系统权限 | yes | +| `fs.credentials_dir.perms_readable` | warn | 其他人可以读取渠道凭证状态 | `~/.openclaw/credentials` 的文件系统权限 | yes | +| `fs.sessions_store.perms_readable` | warn | 其他人可以读取会话转录/元数据 | 会话存储权限 | yes | +| `fs.log_file.perms_readable` | warn | 其他人可以读取经过脱敏但仍然敏感的日志 | Gateway 网关日志文件权限 | yes | +| `fs.synced_dir` | warn | 将状态/配置放在 iCloud/Dropbox/Drive 中会扩大 token/转录暴露面 | 将配置/状态移出同步文件夹 | no | +| `gateway.bind_no_auth` | critical | 在没有共享密钥的情况下进行远程 bind | `gateway.bind`、`gateway.auth.*` | no | +| `gateway.loopback_no_auth` | critical | 经过反向代理的 loopback 可能变为未鉴权 | `gateway.auth.*`、代理设置 | no | +| `gateway.trusted_proxies_missing` | warn | 存在反向代理头,但这些代理未被信任 | `gateway.trustedProxies` | no | +| `gateway.http.no_auth` | warn/critical | `auth.mode="none"` 时可访问 Gateway 网关 HTTP API | `gateway.auth.mode`、`gateway.http.endpoints.*` | no | +| `gateway.http.session_key_override_enabled` | info | HTTP API 调用方可以覆盖 `sessionKey` | `gateway.http.allowSessionKeyOverride` | no | +| `gateway.tools_invoke_http.dangerous_allow` | warn/critical | 通过 HTTP API 重新启用了危险工具 | `gateway.tools.allow` | no | +| `gateway.nodes.allow_commands_dangerous` | warn/critical | 启用了高影响 node 命令(camera/screen/contacts/calendar/SMS) | `gateway.nodes.allowCommands` | no | +| `gateway.nodes.deny_commands_ineffective` | warn | 类模式 deny 条目不会匹配 shell 文本或组 | `gateway.nodes.denyCommands` | no | +| `gateway.tailscale_funnel` | critical | 暴露到公共互联网 | `gateway.tailscale.mode` | no | +| `gateway.tailscale_serve` | info | 通过 Serve 启用了 tailnet 暴露 | `gateway.tailscale.mode` | no | +| `gateway.control_ui.allowed_origins_required` | critical | 非 loopback 的 Control UI 未显式设置浏览器来源 allowlist | `gateway.controlUi.allowedOrigins` | no | +| `gateway.control_ui.allowed_origins_wildcard` | warn/critical | `allowedOrigins=["*"]` 会禁用浏览器来源 allowlist | `gateway.controlUi.allowedOrigins` | no | +| `gateway.control_ui.host_header_origin_fallback` | warn/critical | 启用了基于 Host header 的来源回退(降低 DNS rebinding 加固强度) | `gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback` | no | +| `gateway.control_ui.insecure_auth` | warn | 启用了不安全鉴权兼容开关 | `gateway.controlUi.allowInsecureAuth` | no | +| `gateway.control_ui.device_auth_disabled` | critical | 禁用了设备身份检查 | `gateway.controlUi.dangerouslyDisableDeviceAuth` | no | +| `gateway.real_ip_fallback_enabled` | warn/critical | 信任 `X-Real-IP` 回退可能因代理配置错误而导致源 IP 欺骗 | `gateway.allowRealIpFallback`、`gateway.trustedProxies` | no | +| `gateway.token_too_short` | warn | 共享 token 过短,更容易被暴力破解 | `gateway.auth.token` | no | +| `gateway.auth_no_rate_limit` | warn | 暴露的鉴权接口若无速率限制,会增加暴力破解风险 | `gateway.auth.rateLimit` | no | +| `gateway.trusted_proxy_auth` | critical | 代理身份现在成为鉴权边界 | `gateway.auth.mode="trusted-proxy"` | no | +| `gateway.trusted_proxy_no_proxies` | critical | trusted-proxy 鉴权在没有受信任代理 IP 的情况下是不安全的 | `gateway.trustedProxies` | no | +| `gateway.trusted_proxy_no_user_header` | critical | trusted-proxy 鉴权无法安全解析用户身份 | `gateway.auth.trustedProxy.userHeader` | no | +| `gateway.trusted_proxy_no_allowlist` | warn | trusted-proxy 鉴权接受任何已鉴权的上游用户 | `gateway.auth.trustedProxy.allowUsers` | no | +| `checkId` | 严重级别 | 为什么重要 | 主要修复键/路径 | 自动修复 | +| --- | --- | --- | --- | --- | +| `gateway.probe_auth_secretref_unavailable` | warn | 深度探测在当前命令路径下无法解析 auth SecretRef | 深度探测鉴权来源 / SecretRef 可用性 | no | +| `gateway.probe_failed` | warn/critical | 实时 Gateway 网关探测失败 | Gateway 网关可达性/鉴权 | no | +| `discovery.mdns_full_mode` | warn/critical | mDNS full 模式会在本地网络上广播 `cliPath`/`sshPort` 元数据 | `discovery.mdns.mode`、`gateway.bind` | no | +| `config.insecure_or_dangerous_flags` | warn | 启用了任意不安全/危险的调试标志 | 多个键(参见发现详情) | no | +| `config.secrets.gateway_password_in_config` | warn | Gateway 网关密码直接存储在配置中 | `gateway.auth.password` | no | +| `config.secrets.hooks_token_in_config` | warn | Hook bearer token 直接存储在配置中 | `hooks.token` | no | +| `hooks.token_reuse_gateway_token` | critical | Hook 入站 token 同时也能解锁 Gateway 网关鉴权 | `hooks.token`、`gateway.auth.token` | no | +| `hooks.token_too_short` | warn | Hook 入站更容易被暴力破解 | `hooks.token` | no | +| `hooks.default_session_key_unset` | warn | Hook 智能体运行会扇出到自动生成的按请求会话 | `hooks.defaultSessionKey` | no | +| `hooks.allowed_agent_ids_unrestricted` | warn/critical | 已鉴权的 Hook 调用方可以路由到任意已配置智能体 | `hooks.allowedAgentIds` | no | +| `hooks.request_session_key_enabled` | warn/critical | 外部调用方可以选择 `sessionKey` | `hooks.allowRequestSessionKey` | no | +| `hooks.request_session_key_prefixes_missing` | warn/critical | 对外部会话键形状没有限制 | `hooks.allowedSessionKeyPrefixes` | no | +| `hooks.path_root` | critical | Hook 路径为 `/`,更容易发生入站冲突或误路由 | `hooks.path` | no | +| `hooks.installs_unpinned_npm_specs` | warn | Hook 安装记录未固定到不可变的 npm 规格 | Hook 安装元数据 | no | +| `hooks.installs_missing_integrity` | warn | Hook 安装记录缺少完整性元数据 | Hook 安装元数据 | no | +| `hooks.installs_version_drift` | warn | Hook 安装记录与已安装包发生漂移 | Hook 安装元数据 | no | +| `logging.redact_off` | warn | 敏感值会泄露到日志/状态中 | `logging.redactSensitive` | yes | +| `browser.control_invalid_config` | warn | 浏览器控制配置在运行前即无效 | `browser.*` | no | +| `browser.control_no_auth` | critical | 浏览器控制在没有 token/password 鉴权的情况下暴露 | `gateway.auth.*` | no | +| `browser.remote_cdp_http` | warn | 通过纯 HTTP 使用远程 CDP 缺少传输加密 | 浏览器 profile `cdpUrl` | no | +| `browser.remote_cdp_private_host` | warn | 远程 CDP 指向私有/内部主机 | 浏览器 profile `cdpUrl`、`browser.ssrfPolicy.*` | no | +| `sandbox.docker_config_mode_off` | warn | 已配置 Sandbox Docker,但当前未启用 | `agents.*.sandbox.mode` | no | +| `sandbox.bind_mount_non_absolute` | warn | 相对 bind mount 可能解析到不可预测的位置 | `agents.*.sandbox.docker.binds[]` | no | +| `sandbox.dangerous_bind_mount` | critical | Sandbox bind mount 指向被阻止的系统、凭证或 Docker socket 路径 | `agents.*.sandbox.docker.binds[]` | no | +| `sandbox.dangerous_network_mode` | critical | Sandbox Docker 网络使用 `host` 或 `container:*` 命名空间加入模式 | `agents.*.sandbox.docker.network` | no | +| `sandbox.dangerous_seccomp_profile` | critical | Sandbox seccomp profile 削弱了容器隔离 | `agents.*.sandbox.docker.securityOpt` | no | +| `sandbox.dangerous_apparmor_profile` | critical | Sandbox AppArmor profile 削弱了容器隔离 | `agents.*.sandbox.docker.securityOpt` | no | +| `sandbox.browser_cdp_bridge_unrestricted` | warn | Sandbox 浏览器桥接暴露时没有来源范围限制 | `sandbox.browser.cdpSourceRange` | no | +| `sandbox.browser_container.non_loopback_publish` | critical | 现有浏览器容器在非 loopback 接口上发布 CDP | 浏览器 sandbox 容器发布配置 | no | +| `sandbox.browser_container.hash_label_missing` | warn | 现有浏览器容器早于当前配置哈希标签 | `openclaw sandbox recreate --browser --all` | no | +| `sandbox.browser_container.hash_epoch_stale` | warn | 现有浏览器容器早于当前浏览器配置 epoch | `openclaw sandbox recreate --browser --all` | no | +| `tools.exec.host_sandbox_no_sandbox_defaults` | warn | 当 sandbox 关闭时,`exec host=sandbox` 会失败关闭 | `tools.exec.host`、`agents.defaults.sandbox.mode` | no | +| `tools.exec.host_sandbox_no_sandbox_agents` | warn | 当 sandbox 关闭时,按智能体设置的 `exec host=sandbox` 会失败关闭 | `agents.list[].tools.exec.host`、`agents.list[].sandbox.mode` | no | +| `tools.exec.security_full_configured` | warn/critical | 主机 exec 正在以 `security="full"` 运行 | `tools.exec.security`、`agents.list[].tools.exec.security` | no | +| `tools.exec.auto_allow_skills_enabled` | warn | Exec 审批会隐式信任 skill bin | `~/.openclaw/exec-approvals.json` | no | +| `tools.exec.allowlist_interpreter_without_strict_inline_eval` | warn | 解释器 allowlist 允许 inline eval,而不会强制重新审批 | `tools.exec.strictInlineEval`、`agents.list[].tools.exec.strictInlineEval`、exec 审批 allowlist | no | +| `tools.exec.safe_bins_interpreter_unprofiled` | warn | `safeBins` 中的解释器/运行时 bin 如果没有显式 profile,会扩大 exec 风险 | `tools.exec.safeBins`、`tools.exec.safeBinProfiles`、`agents.list[].tools.exec.*` | no | +| `tools.exec.safe_bins_broad_behavior` | warn | `safeBins` 中行为过宽的工具会削弱基于低风险 stdin 过滤的信任模型 | `tools.exec.safeBins`、`agents.list[].tools.exec.safeBins` | no | +| `tools.exec.safe_bin_trusted_dirs_risky` | warn | `safeBinTrustedDirs` 包含可变或高风险目录 | `tools.exec.safeBinTrustedDirs`、`agents.list[].tools.exec.safeBinTrustedDirs` | no | +| `skills.workspace.symlink_escape` | warn | 工作区 `skills/**/SKILL.md` 解析到了工作区根目录之外(符号链接链漂移) | 工作区 `skills/**` 文件系统状态 | no | +| `plugins.extensions_no_allowlist` | warn | 插件安装时没有显式插件 allowlist | `plugins.allowlist` | no | +| `plugins.installs_unpinned_npm_specs` | warn | 插件安装记录未固定到不可变的 npm 规格 | 插件安装元数据 | no | +| `checkId` | 严重级别 | 为什么重要 | 主要修复键/路径 | 自动修复 | +| --- | --- | --- | --- | --- | +| `plugins.installs_missing_integrity` | warn | 插件安装记录缺少完整性元数据 | 插件安装元数据 | no | +| `plugins.installs_version_drift` | warn | 插件安装记录与已安装包发生漂移 | 插件安装元数据 | no | +| `plugins.code_safety` | warn/critical | 插件代码扫描发现可疑或危险模式 | 插件代码 / 安装来源 | no | +| `plugins.code_safety.entry_path` | warn | 插件入口路径指向隐藏目录或 `node_modules` 位置 | 插件清单 `entry` | no | +| `plugins.code_safety.entry_escape` | critical | 插件入口逃逸出插件目录 | 插件清单 `entry` | no | +| `plugins.code_safety.scan_failed` | warn | 插件代码扫描无法完成 | 插件路径 / 扫描环境 | no | +| `skills.code_safety` | warn/critical | Skill 安装器元数据/代码包含可疑或危险模式 | skill 安装来源 | no | +| `skills.code_safety.scan_failed` | warn | Skill 代码扫描无法完成 | skill 扫描环境 | no | +| `security.exposure.open_channels_with_exec` | warn/critical | 共享/公开房间可以访问启用了 exec 的智能体 | `channels.*.dmPolicy`、`channels.*.groupPolicy`、`tools.exec.*`、`agents.list[].tools.exec.*` | no | +| `security.exposure.open_groups_with_elevated` | critical | 开放群组 + 高权限工具会形成高影响的 prompt injection 路径 | `channels.*.groupPolicy`、`tools.elevated.*` | no | +| `security.exposure.open_groups_with_runtime_or_fs` | critical/warn | 开放群组在没有沙箱隔离/工作区防护的情况下可访问命令/文件工具 | `channels.*.groupPolicy`、`tools.profile/deny`、`tools.fs.workspaceOnly`、`agents.*.sandbox.mode` | no | +| `security.trust_model.multi_user_heuristic` | warn | 配置看起来是多用户,但 Gateway 网关信任模型是个人助理 | 拆分信任边界,或使用共享用户加固(`sandbox.mode`、工具 deny/工作区范围限制) | no | +| `tools.profile_minimal_overridden` | warn | 智能体覆盖绕过了全局 minimal profile | `agents.list[].tools.profile` | no | +| `plugins.tools_reachable_permissive_policy` | warn | 扩展工具在宽松策略环境中可访问 | `tools.profile` + 工具 allow/deny | no | +| `models.legacy` | warn | 仍然配置了旧版模型家族 | 模型选择 | no | +| `models.weak_tier` | warn | 已配置模型低于当前推荐层级 | 模型选择 | no | +| `models.small_params` | critical/info | 小模型 + 不安全工具表面会提高注入风险 | 模型选择 + 沙箱隔离/工具策略 | no | +| `summary.attack_surface` | info | 鉴权、渠道、工具和暴露姿态的汇总摘要 | 多个键(参见发现详情) | no | -## 通过 HTTP 使用控制 UI +## 通过 HTTP 使用 Control UI -控制 UI 需要一个**安全上下文**(HTTPS 或 localhost)来生成设备身份。`gateway.controlUi.allowInsecureAuth` 是一个本地兼容性开关: +Control UI 需要一个**安全上下文**(HTTPS 或 localhost)来生成设备身份。`gateway.controlUi.allowInsecureAuth` 是一个本地兼容性开关: -- 在 localhost 上,当页面通过非安全 HTTP 加载时,它允许控制 UI 在没有设备身份的情况下进行认证。 +- 在 localhost 上,当页面通过非安全 HTTP 加载时,它允许 Control UI 在没有设备身份的情况下进行鉴权。 - 它不会绕过配对检查。 - 它不会放宽远程(非 localhost)设备身份要求。 优先使用 HTTPS(Tailscale Serve),或在 `127.0.0.1` 上打开 UI。 -仅用于紧急破窗场景时,`gateway.controlUi.dangerouslyDisableDeviceAuth` 会完全禁用设备身份检查。这是一次严重的安全降级;除非你正在主动调试并且能够快速恢复,否则请保持关闭。 +仅在紧急兜底场景中,`gateway.controlUi.dangerouslyDisableDeviceAuth` 可以完全禁用设备身份检查。这会严重降低安全性;除非你正在积极调试并且可以快速恢复,否则请保持关闭。 -与这些危险标志不同,成功的 `gateway.auth.mode: "trusted-proxy"` 可以允许**操作员**控制 UI 会话在没有设备身份的情况下登录。这是认证模式的有意行为,不是 `allowInsecureAuth` 的捷径,而且它仍然不适用于节点角色的控制 UI 会话。 +与这些危险标志分开的是,成功配置 `gateway.auth.mode: "trusted-proxy"` 后,可以在没有设备身份的情况下允许**操作员** Control UI 会话。这是有意设计的鉴权模式行为,而不是 `allowInsecureAuth` 的捷径,并且它仍不适用于 node 角色的 Control UI 会话。 -当此设置启用时,`openclaw security audit` 会发出警告。 +启用此设置时,`openclaw security audit` 会发出警告。 ## 不安全或危险标志摘要 -当已知的不安全 / 危险调试开关被启用时,`openclaw security audit` 会包含 `config.insecure_or_dangerous_flags`。该检查当前汇总以下内容: +当已启用已知的不安全/危险调试开关时,`openclaw security audit` 会包含 `config.insecure_or_dangerous_flags`。该检查当前聚合以下项: - `gateway.controlUi.allowInsecureAuth=true` - `gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true` @@ -387,15 +391,15 @@ Allowlist 控制触发和命令授权。`contextVisibility` 设置则控制如 - `channels.googlechat.dangerouslyAllowNameMatching` - `channels.googlechat.accounts..dangerouslyAllowNameMatching` - `channels.msteams.dangerouslyAllowNameMatching` -- `channels.synology-chat.dangerouslyAllowNameMatching`(渠道插件) -- `channels.synology-chat.accounts..dangerouslyAllowNameMatching`(渠道插件) -- `channels.synology-chat.dangerouslyAllowInheritedWebhookPath`(渠道插件) -- `channels.zalouser.dangerouslyAllowNameMatching`(渠道插件) -- `channels.zalouser.accounts..dangerouslyAllowNameMatching`(渠道插件) -- `channels.irc.dangerouslyAllowNameMatching`(渠道插件) -- `channels.irc.accounts..dangerouslyAllowNameMatching`(渠道插件) -- `channels.mattermost.dangerouslyAllowNameMatching`(渠道插件) -- `channels.mattermost.accounts..dangerouslyAllowNameMatching`(渠道插件) +- `channels.synology-chat.dangerouslyAllowNameMatching`(plugin 渠道) +- `channels.synology-chat.accounts..dangerouslyAllowNameMatching`(plugin 渠道) +- `channels.synology-chat.dangerouslyAllowInheritedWebhookPath`(plugin 渠道) +- `channels.zalouser.dangerouslyAllowNameMatching`(plugin 渠道) +- `channels.zalouser.accounts..dangerouslyAllowNameMatching`(plugin 渠道) +- `channels.irc.dangerouslyAllowNameMatching`(plugin 渠道) +- `channels.irc.accounts..dangerouslyAllowNameMatching`(plugin 渠道) +- `channels.mattermost.dangerouslyAllowNameMatching`(plugin 渠道) +- `channels.mattermost.accounts..dangerouslyAllowNameMatching`(plugin 渠道) - `channels.telegram.network.dangerouslyAllowPrivateNetwork` - `channels.telegram.accounts..network.dangerouslyAllowPrivateNetwork` - `agents.defaults.sandbox.docker.dangerouslyAllowReservedContainerTargets` @@ -407,29 +411,29 @@ Allowlist 控制触发和命令授权。`contextVisibility` 设置则控制如 ## 反向代理配置 -如果你在反向代理(nginx、Caddy、Traefik 等)后运行 Gateway 网关,请配置 `gateway.trustedProxies` 以正确处理转发客户端 IP。 +如果你在反向代理(nginx、Caddy、Traefik 等)后运行 Gateway 网关,请配置 `gateway.trustedProxies`,以正确处理转发的客户端 IP。 -当 Gateway 网关检测到来自**不在** `trustedProxies` 中地址的代理头时,它**不会**将这些连接视为本地客户端。如果 Gateway 网关认证被禁用,这些连接会被拒绝。这可以防止认证绕过:否则,经代理转发的连接可能会看起来像来自 localhost,从而自动获得信任。 +当 Gateway 网关检测到来自**不在** `trustedProxies` 中地址的代理头时,它将**不会**把这些连接视为本地客户端。如果 Gateway 网关鉴权已禁用,这些连接会被拒绝。这样可以防止鉴权绕过 —— 否则,经代理的连接可能看起来像是来自 localhost,从而自动获得信任。 -`gateway.trustedProxies` 也会影响 `gateway.auth.mode: "trusted-proxy"`,但该认证模式更严格: +`gateway.trustedProxies` 也会用于 `gateway.auth.mode: "trusted-proxy"`,但这种鉴权模式更严格: -- trusted-proxy 认证**会对来自 loopback 源的代理以关闭方式失败** -- 同主机的 loopback 反向代理仍然可以使用 `gateway.trustedProxies` 来进行本地客户端检测和转发 IP 处理 -- 对于同主机的 loopback 反向代理,请使用 token / password 认证,而不是 `gateway.auth.mode: "trusted-proxy"` +- trusted-proxy 鉴权在 loopback 源代理上会**失败关闭** +- 同一主机上的 loopback 反向代理仍可使用 `gateway.trustedProxies` 进行本地客户端检测和转发 IP 处理 +- 对于同一主机上的 loopback 反向代理,请使用 token/password 鉴权,而不要使用 `gateway.auth.mode: "trusted-proxy"` ```yaml gateway: trustedProxies: - "10.0.0.1" # 反向代理 IP - # 可选。默认 false。 - # 只有在你的代理无法提供 X-Forwarded-For 时才启用。 + # 可选。默认值为 false。 + # 仅当你的代理无法提供 X-Forwarded-For 时才启用。 allowRealIpFallback: false auth: mode: password password: ${OPENCLAW_GATEWAY_PASSWORD} ``` -当配置了 `trustedProxies` 后,Gateway 网关会使用 `X-Forwarded-For` 来确定客户端 IP。默认会忽略 `X-Real-IP`,除非显式设置 `gateway.allowRealIpFallback: true`。 +当配置了 `trustedProxies` 时,Gateway 网关会使用 `X-Forwarded-For` 来确定客户端 IP。默认情况下会忽略 `X-Real-IP`,除非明确设置了 `gateway.allowRealIpFallback: true`。 良好的反向代理行为(覆盖传入的转发头): @@ -438,7 +442,7 @@ proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Real-IP $remote_addr; ``` -不良的反向代理行为(追加 / 保留不受信任的转发头): +不良的反向代理行为(追加/保留不受信任的转发头): ```nginx proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; @@ -446,48 +450,47 @@ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; ## HSTS 和来源说明 -- OpenClaw Gateway 网关优先面向本地 / loopback。若你在反向代理处终止 TLS,请在该代理面向外部的 HTTPS 域名上设置 HSTS。 +- OpenClaw Gateway 网关默认优先用于本地/loopback。如果你在反向代理处终止 TLS,请在该代理面向外部的 HTTPS 域名上设置 HSTS。 - 如果由 Gateway 网关本身终止 HTTPS,你可以设置 `gateway.http.securityHeaders.strictTransportSecurity`,让 OpenClaw 响应发出 HSTS 头。 -- 详细部署指南见 [Trusted Proxy Auth](/zh-CN/gateway/trusted-proxy-auth#tls-termination-and-hsts)。 -- 对于非 loopback 的控制 UI 部署,默认必须设置 `gateway.controlUi.allowedOrigins`。 -- `gateway.controlUi.allowedOrigins: ["*"]` 是显式允许所有浏览器来源的策略,不是加固后的默认值。除非是在严格受控的本地测试中,否则应避免使用。 -- 即使启用了通用的 loopback 豁免,loopback 上的浏览器来源认证失败仍然会受到速率限制,但锁定键会按规范化后的 `Origin` 值分别作用,而不是共用一个 localhost 桶。 -- `gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true` 会启用 Host header 来源回退模式;应将其视为由操作员主动选择的危险策略。 -- 应将 DNS rebinding 和代理 Host header 行为视为部署加固问题;保持 `trustedProxies` 尽量严格,避免将 Gateway 网关直接暴露到公共互联网。 +- 详细部署指南请参阅 [Trusted Proxy Auth](/zh-CN/gateway/trusted-proxy-auth#tls-termination-and-hsts)。 +- 对于非 loopback 的 Control UI 部署,默认要求设置 `gateway.controlUi.allowedOrigins`。 +- `gateway.controlUi.allowedOrigins: ["*"]` 是显式的允许所有浏览器来源策略,不是加固后的默认值。除严格受控的本地测试外,应避免使用。 +- 即使启用了通用 loopback 豁免,loopback 上的浏览器来源鉴权失败仍会受到速率限制,但锁定键会按规范化后的 `Origin` 值分别计算,而不是共享一个 localhost 桶。 +- `gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true` 会启用基于 Host header 的来源回退模式;应将其视为由操作员主动选择的危险策略。 +- 将 DNS rebinding 和代理 Host header 行为视为部署加固问题;保持 `trustedProxies` 严格,避免将 Gateway 网关直接暴露到公共互联网。 -## 本地 session 日志存储在磁盘上 +## 本地会话日志会存储在磁盘上 -OpenClaw 会将 session 转录存储在磁盘上的 `~/.openclaw/agents//sessions/*.jsonl` 中。 -这是实现 session 连续性以及(可选)session memory 索引所必需的,但这也意味着 -**任何拥有文件系统访问权限的进程 / 用户都可以读取这些日志**。应将磁盘访问视为信任 -边界,并锁定 `~/.openclaw` 的权限(参见下方审计部分)。如果你需要在智能体之间提供 -更强的隔离,请让它们运行在不同的 OS 用户或不同的主机下。 +OpenClaw 会将会话转录存储到 `~/.openclaw/agents//sessions/*.jsonl` 下的磁盘中。 +这对于会话连续性以及(可选的)会话记忆索引是必需的,但这也意味着 +**任何拥有文件系统访问权限的进程/用户都可以读取这些日志**。应将磁盘访问视为信任边界,并锁定 `~/.openclaw` 的权限(参见下方审计部分)。如果你需要更强的智能体隔离,请让它们运行在独立的 OS 用户下,或使用独立主机。 -## 节点执行(`system.run`) +## Node 执行(system.run) -如果某个 macOS 节点已配对,Gateway 网关就可以在该节点上调用 `system.run`。这属于对 Mac 的**远程代码执行**: +如果已配对一个 macOS node,Gateway 网关就可以在该 node 上调用 `system.run`。这属于 **Mac 上的远程代码执行**: -- 需要节点配对(审批 + token)。 -- Gateway 网关的节点配对并不是按命令逐次审批的接口。它建立的是节点身份 / 信任以及 token 签发。 -- Gateway 网关通过 `gateway.nodes.allowCommands` / `denyCommands` 应用粗粒度的全局节点命令策略。 -- 在 Mac 上通过**设置 → Exec 审批**进行控制(security + ask + allowlist)。 -- 每个节点的 `system.run` 策略由该节点自己的 exec 审批文件(`exec.approvals.node.*`)控制,它可以比 Gateway 网关的全局命令 ID 策略更严格,也可以更宽松。 -- 如果一个节点以 `security="full"` 和 `ask="off"` 运行,那么它遵循的是默认的受信任操作员模型。除非你的部署明确要求更严格的审批或 allowlist 立场,否则应将其视为预期行为。 -- 审批模式会绑定精确的请求上下文,并在可能时绑定一个具体的本地脚本 / 文件操作数。若 OpenClaw 无法为解释器 / 运行时命令准确识别唯一的直接本地文件,基于审批的执行就会被拒绝,而不会声称提供完整的语义覆盖。 -- 对于 `host=node`,基于审批的运行还会存储规范化后的预备 `systemRunPlan`;后续已批准的转发会复用该存储计划,而 Gateway 网关校验会拒绝调用方在审批请求创建之后对 command / cwd / session 上下文所做的修改。 -- 如果你不想允许远程执行,请将 security 设为 **deny**,并移除该 Mac 的节点配对。 +- 需要 node 配对(审批 + token)。 +- Gateway 网关的 node 配对不是逐命令审批表面。它建立的是 node 身份/信任和 token 签发。 +- Gateway 网关通过 `gateway.nodes.allowCommands` / `denyCommands` 应用粗粒度的全局 node 命令策略。 +- 在 Mac 上通过**设置 → Exec approvals**进行控制(security + ask + allowlist)。 +- 每个 node 的 `system.run` 策略是 node 自身的 exec 审批文件(`exec.approvals.node.*`),它可能比 Gateway 网关的全局命令 ID 策略更严格,也可能更宽松。 +- 以 `security="full"` 和 `ask="off"` 运行的 node,遵循的是默认的受信任操作员模型。除非你的部署明确要求更严格的审批或 allowlist 策态,否则应将其视为预期行为。 +- 审批模式会绑定精确的请求上下文,并在可能时绑定一个具体的本地脚本/文件操作数。若 OpenClaw 无法为解释器/运行时命令准确识别出唯一的直接本地文件,则会拒绝基于审批的执行,而不是承诺完全的语义覆盖。 +- 对于 `host=node`,基于审批的运行还会存储规范化的已准备 `systemRunPlan`;后续已批准的转发会复用该计划,并且 Gateway 网关验证会拒绝在审批请求创建后由调用方修改 command/cwd/session 上下文。 -这个区别对分诊很重要: +如果你不希望有远程执行能力,请将安全设置为 **deny**,并移除该 Mac 的 node 配对。 -- 一个重新连接的已配对节点广播了不同的命令列表,这本身**不**构成漏洞,只要 Gateway 网关的全局策略和节点本地 exec 审批仍然在强制执行真实边界。 -- 把节点配对元数据当作隐藏的第二层逐命令审批机制的报告,通常是对策略 / UX 的误解,而不是安全边界绕过。 +这一点对于分级很重要: -## 动态 Skills(watcher / 远程节点) +- 一个重新连接的已配对 node 广播出不同的命令列表,这本身**不是**漏洞,只要 Gateway 网关全局策略和 node 本地 exec 审批仍然强制执行实际的执行边界。 +- 将 node 配对元数据视为第二层隐藏的逐命令审批层的报告,通常属于策略/UX 混淆,而不是安全边界绕过。 -OpenClaw 可以在 session 中途刷新 Skills 列表: +## 动态 Skills(watcher / 远程 nodes) -- **Skills watcher**:对 `SKILL.md` 的更改可以在下一次智能体轮次时更新 Skills 快照。 -- **远程节点**:连接 macOS 节点后,可以使仅限 macOS 的 Skills 变为可用(基于 bin 探测)。 +OpenClaw 可以在会话中途刷新 Skills 列表: + +- **Skills watcher**:`SKILL.md` 的更改可以在下一次智能体轮次中更新 Skills 快照。 +- **远程 nodes**:连接一个 macOS node 后,可以使仅限 macOS 的 Skills 变为可用(基于 bin 探测)。 应将 skill 文件夹视为**受信任代码**,并限制谁可以修改它们。 @@ -496,48 +499,46 @@ OpenClaw 可以在 session 中途刷新 Skills 列表: 你的 AI 助手可以: - 执行任意 shell 命令 -- 读取 / 写入文件 +- 读写文件 - 访问网络服务 -- 向任何人发送消息(如果你授予它 WhatsApp 访问权限) +- 给任何人发送消息(如果你给了它 WhatsApp 访问权限) -给你发送消息的人可以: +向你发送消息的人可以: - 试图诱骗你的 AI 做坏事 -- 通过社会工程方式获取你的数据访问权 -- 探测你的基础设施细节 +- 通过社会工程获取你的数据访问权限 +- 探测基础设施细节 ## 核心概念:先做访问控制,再谈智能 -这里的大多数失败都不是高级利用——而是“有人给机器人发了消息,机器人就照做了”。 +这里的大多数失败都不是花哨的漏洞利用 —— 而是“有人给机器人发了消息,机器人照做了”。 OpenClaw 的立场是: -- **先看身份:** 决定谁可以和机器人对话(私信 pairing / allowlist / 显式 “open”)。 -- **再看范围:** 决定机器人可以在哪些地方执行操作(群组 allowlist + mention 门槛、工具、沙箱隔离、设备权限)。 -- **最后看模型:** 假设模型可能被操控;设计时要让操控的影响半径保持有限。 +- **先身份:** 决定谁可以和机器人对话(私信配对 / allowlist / 显式 “open”)。 +- **再范围:** 决定机器人被允许在哪些地方执行操作(群组 allowlist + 提及门控、工具、沙箱隔离、设备权限)。 +- **最后模型:** 假设模型可以被操控;设计时应让这种操控的影响半径尽可能有限。 ## 命令授权模型 -斜杠命令和指令仅对**已授权发送者**生效。授权来源于 -渠道 allowlist / pairing 以及 `commands.useAccessGroups`(见[配置](/zh-CN/gateway/configuration) -和[斜杠命令](/zh-CN/tools/slash-commands))。如果某个渠道 allowlist 为空或包含 `"*"`, -那么该渠道的命令实际上就是开放的。 +斜杠命令和指令只会对**已授权的发送者**生效。授权来源于 +渠道 allowlist/配对,加上 `commands.useAccessGroups`(参见[配置](/zh-CN/gateway/configuration) +和[斜杠命令](/zh-CN/tools/slash-commands))。如果某个渠道的 allowlist 为空或包含 `"*"`, +那么该渠道中的命令实际上就是开放的。 -`/exec` 是面向已授权操作员的仅限 session 的便捷功能。它**不会**写入配置,也**不会** -更改其他 session。 +`/exec` 是面向已授权操作员的仅会话便捷命令。它**不会**写入配置,也**不会**更改其他会话。 ## 控制平面工具风险 -有两个内置工具可以进行持久化控制平面更改: +有两个内置工具可以进行持久化的控制平面变更: -- `gateway` 可以通过 `config.schema.lookup` / `config.get` 检查配置,也可以通过 `config.apply`、`config.patch` 和 `update.run` 进行持久化更改。 -- `cron` 可以创建定时任务,使其在原始聊天 / 任务结束后继续运行。 +- `gateway` 可以通过 `config.schema.lookup` / `config.get` 检查配置,并可通过 `config.apply`、`config.patch` 和 `update.run` 进行持久化更改。 +- `cron` 可以创建定时任务,使其在原始聊天/任务结束后继续运行。 -仅限 owner 的 `gateway` 运行时工具仍然会拒绝改写 -`tools.exec.ask` 或 `tools.exec.security`;旧版 `tools.bash.*` 别名会 -在写入前被规范化为同样受保护的 exec 路径。 +仅限 owner 的 `gateway` 运行时工具仍然会拒绝重写 +`tools.exec.ask` 或 `tools.exec.security`;旧版 `tools.bash.*` 别名会在写入前标准化为相同的受保护 exec 路径。 -对于任何会处理不受信任内容的智能体 / 接口,默认应禁用这些工具: +对于任何处理不受信任内容的智能体/表面,默认应拒绝这些工具: ```json5 { @@ -547,35 +548,35 @@ OpenClaw 的立场是: } ``` -`commands.restart=false` 只会阻止重启动作。它不会禁用 `gateway` 的配置 / 更新操作。 +`commands.restart=false` 只会阻止重启动作。它不会禁用 `gateway` 配置/更新操作。 ## 插件 -插件会**在 Gateway 网关进程内**运行。应将它们视为受信任代码: +插件以**进程内**方式与 Gateway 网关一起运行。应将它们视为受信任代码: - 只从你信任的来源安装插件。 - 优先使用显式的 `plugins.allow` allowlist。 -- 启用前先检查插件配置。 +- 在启用前审查插件配置。 - 插件变更后重启 Gateway 网关。 - 如果你安装或更新插件(`openclaw plugins install `、`openclaw plugins update `),应将其视为运行不受信任代码: - - 安装路径是活动插件安装根目录下对应插件的专属目录。 - - OpenClaw 会在安装 / 更新前运行内置危险代码扫描。`critical` 发现默认会阻止继续执行。 - - OpenClaw 会先使用 `npm pack`,然后在该目录中运行 `npm install --omit=dev`(npm 生命周期脚本可能在安装期间执行代码)。 - - 优先使用固定、精确版本(`@scope/pkg@1.2.3`),并在启用前检查解包到磁盘上的代码。 - - `--dangerously-force-unsafe-install` 仅用于破窗场景:当插件安装 / 更新流程中的内置扫描出现误报时才使用。它不会绕过插件 `before_install` hook 的策略阻止,也不会绕过扫描失败。 - - 基于 Gateway 网关的 skill 依赖安装遵循相同的危险 / 可疑划分:内置 `critical` 发现默认会阻止执行,除非调用方显式设置 `dangerouslyForceUnsafeInstall`;而可疑发现仍然只会发出警告。`openclaw skills install` 仍然是独立的 ClawHub skill 下载 / 安装流程。 + - 安装路径是活动插件安装根目录下的每插件目录。 + - OpenClaw 会在安装/更新前运行内置的危险代码扫描。`critical` 发现默认会阻止安装。 + - OpenClaw 会先使用 `npm pack`,然后在该目录中运行 `npm install --omit=dev`(npm 生命周期脚本可能会在安装期间执行代码)。 + - 优先使用固定、精确的版本(`@scope/pkg@1.2.3`),并在启用前检查磁盘上解包后的代码。 + - `--dangerously-force-unsafe-install` 仅用于紧急兜底场景,适用于插件安装/更新流程中内置扫描的误报。它不会绕过插件 `before_install` hook 策略阻止,也不会绕过扫描失败。 + - 基于 Gateway 网关的 skill 依赖安装遵循相同的危险/可疑分级:内置 `critical` 发现会阻止安装,除非调用方显式设置 `dangerouslyForceUnsafeInstall`,而可疑发现仍然只会警告。`openclaw skills install` 仍然是独立的 ClawHub skill 下载/安装流程。 -详情见:[插件](/zh-CN/tools/plugin) +详情参见:[插件](/zh-CN/tools/plugin) ## 私信访问模型(pairing / allowlist / open / disabled) -当前所有支持私信的渠道都支持私信策略(`dmPolicy` 或 `*.dm.policy`),会在处理消息**之前**对入站私信进行控制: +当前所有支持私信的渠道都支持私信策略(`dmPolicy` 或 `*.dm.policy`),它会在处理消息**之前**拦截入站私信: -- `pairing`(默认):未知发送者会收到一段简短的配对代码,机器人会忽略其消息,直到获得批准。代码在 1 小时后过期;重复发送私信不会再次发送代码,除非创建了新的请求。默认情况下,每个渠道最多保留 **3 个待处理请求**。 +- `pairing`(默认):未知发送者会收到一个简短的配对码,在获得批准之前,机器人会忽略其消息。配对码 1 小时后过期;重复发送私信不会重复发送配对码,直到创建新的请求。默认情况下,每个渠道最多保留 **3 个待处理请求**。 - `allowlist`:未知发送者会被阻止(没有配对握手)。 -- `open`:允许任何人发送私信(公开)。**要求**该渠道的 allowlist 包含 `"*"`(显式选择加入)。 +- `open`:允许任何人发送私信(公开)。**要求** 该渠道的 allowlist 包含 `"*"`(显式选择启用)。 - `disabled`:完全忽略入站私信。 通过 CLI 批准: @@ -585,11 +586,11 @@ openclaw pairing list openclaw pairing approve ``` -详情及磁盘文件位置见:[配对](/zh-CN/channels/pairing) +详情和磁盘上的文件位置请参阅:[配对](/zh-CN/channels/pairing) -## 私信 session 隔离(多用户模式) +## 私信会话隔离(多用户模式) -默认情况下,OpenClaw 会将**所有私信都路由到主 session**,这样你的助手就能在不同设备和渠道之间保持连续性。如果**多个人**可以给机器人发私信(公开私信或多人 allowlist),请考虑隔离私信 session: +默认情况下,OpenClaw 会将**所有私信都路由到主会话**,以便你的助手在设备和渠道之间保持连续性。如果**有多个人**可以给机器人发私信(开放私信或多人 allowlist),请考虑隔离私信会话: ```json5 { @@ -597,158 +598,160 @@ openclaw pairing approve } ``` -这样可以防止跨用户上下文泄漏,同时保持群聊彼此隔离。 +这样可以防止跨用户上下文泄露,同时保持群聊隔离。 -这是消息上下文边界,不是主机管理边界。如果用户之间彼此对抗且共享同一个 Gateway 网关主机 / 配置,请为每个信任边界分别运行单独的 Gateway 网关。 +这是消息上下文边界,不是主机管理员边界。如果用户彼此对抗,并共享同一个 Gateway 网关主机/配置,请改为按信任边界运行独立的 Gateway 网关。 ### 安全私信模式(推荐) -将上面的配置片段视为**安全私信模式**: +请将上面的片段视为**安全私信模式**: -- 默认:`session.dmScope: "main"`(所有私信共享一个 session,以保持连续性)。 -- 本地 CLI 新手引导默认:若未设置,则写入 `session.dmScope: "per-channel-peer"`(保留已有的显式值)。 -- 安全私信模式:`session.dmScope: "per-channel-peer"`(每个渠道 + 发送者组合都有隔离的私信上下文)。 -- 跨渠道同一联系人隔离:`session.dmScope: "per-peer"`(同一类型的所有渠道中,每个发送者共享一个 session)。 +- 默认:`session.dmScope: "main"`(所有私信共享一个会话,以保持连续性)。 +- 本地 CLI 新手引导默认值:在未设置时写入 `session.dmScope: "per-channel-peer"`(保留现有显式值)。 +- 安全私信模式:`session.dmScope: "per-channel-peer"`(每个渠道 + 发送者组合获得隔离的私信上下文)。 +- 跨渠道对等隔离:`session.dmScope: "per-peer"`(同一发送者在同类型所有渠道中共用一个会话)。 -如果你在同一个渠道上运行多个账号,请改用 `per-account-channel-peer`。如果同一个人通过多个渠道联系你,请使用 `session.identityLinks` 将这些私信 session 合并为一个规范身份。参见[会话管理](/zh-CN/concepts/session)和[配置](/zh-CN/gateway/configuration)。 +如果你在同一个渠道上运行多个账户,请改用 `per-account-channel-peer`。如果同一个人通过多个渠道联系你,请使用 `session.identityLinks` 将这些私信会话合并为一个规范身份。请参阅[会话管理](/zh-CN/concepts/session)和[配置](/zh-CN/gateway/configuration)。 -## Allowlist(私信 + 群组)——术语说明 +## Allowlists(私信 + 群组)—— 术语 -OpenClaw 有两层独立的“谁可以触发我?”控制: +OpenClaw 有两层独立的“谁可以触发我?”机制: - **私信 allowlist**(`allowFrom` / `channels.discord.allowFrom` / `channels.slack.allowFrom`;旧版:`channels.discord.dm.allowFrom`、`channels.slack.dm.allowFrom`):谁被允许在私信中和机器人对话。 - - 当 `dmPolicy="pairing"` 时,批准结果会写入 `~/.openclaw/credentials/` 下按账号作用域划分的 pairing allowlist 存储中(默认账号使用 `-allowFrom.json`,非默认账号使用 `--allowFrom.json`),并与配置中的 allowlist 合并。 -- **群组 allowlist**(渠道特定):机器人总体上会接受哪些群组 / 渠道 / guild 的消息。 + - 当 `dmPolicy="pairing"` 时,批准结果会写入 `~/.openclaw/credentials/` 下按账户划分的配对 allowlist 存储(默认账户为 `-allowFrom.json`,非默认账户为 `--allowFrom.json`),并与配置中的 allowlist 合并。 +- **群组 allowlist**(按渠道定义):机器人总体上会接受哪些群组/频道/服务器的消息。 - 常见模式: - - `channels.whatsapp.groups`、`channels.telegram.groups`、`channels.imessage.groups`:如 `requireMention` 之类的按群组默认值;一旦设置,它也会充当群组 allowlist(包含 `"*"` 可保持允许所有的行为)。 - - `groupPolicy="allowlist"` + `groupAllowFrom`:限制在群组 session **内部**谁可以触发机器人(WhatsApp / Telegram / Signal / iMessage / Microsoft Teams)。 - - `channels.discord.guilds` / `channels.slack.channels`:按表面范围配置的 allowlist + mention 默认值。 - - 群组检查顺序如下:先执行 `groupPolicy` / 群组 allowlist,再执行 mention / reply 激活。 - - 回复机器人消息(隐式 mention)**不会**绕过类似 `groupAllowFrom` 这样的发送者 allowlist。 - - **安全说明:** 应将 `dmPolicy="open"` 和 `groupPolicy="open"` 视为最后手段。应尽量少用;除非你完全信任房间中的每一位成员,否则优先使用 pairing + allowlist。 + - `channels.whatsapp.groups`、`channels.telegram.groups`、`channels.imessage.groups`:像 `requireMention` 这样的按群组默认值;一旦设置,也会充当群组 allowlist(包含 `"*"` 可保持允许全部的行为)。 + - `groupPolicy="allowlist"` + `groupAllowFrom`:限制在群组会话_内部_谁可以触发机器人(WhatsApp/Telegram/Signal/iMessage/Microsoft Teams)。 + - `channels.discord.guilds` / `channels.slack.channels`:按表面定义的 allowlist + 默认提及策略。 + - 群组检查顺序如下:先执行 `groupPolicy`/群组 allowlist,其次执行提及/回复激活。 + - 回复机器人消息(隐式提及)**不会**绕过像 `groupAllowFrom` 这样的发送者 allowlist。 + - **安全说明:** 应将 `dmPolicy="open"` 和 `groupPolicy="open"` 视为最后手段。它们应尽量少用;除非你完全信任房间中的每一位成员,否则优先使用 pairing + allowlists。 -详情见:[配置](/zh-CN/gateway/configuration) 和 [群组](/zh-CN/channels/groups) +详情请参阅:[配置](/zh-CN/gateway/configuration) 和 [群组](/zh-CN/channels/groups) -## 提示注入(是什么,为什么重要) +## Prompt injection(它是什么,为什么重要) -提示注入是指攻击者构造一条消息,操控模型执行不安全操作(“忽略你的指令”、“导出你的文件系统”、“打开这个链接并运行命令”等)。 +Prompt injection 是指攻击者构造一条消息,操纵模型去做不安全的事情(“忽略你的指令”、“导出你的文件系统”、“访问这个链接并运行命令”等)。 -即使系统提示很强,**提示注入也没有被彻底解决**。系统提示防护只是软性指导;真正的硬性约束来自工具策略、exec 审批、沙箱隔离和渠道 allowlist(并且按设计,操作员可以关闭这些机制)。在实践中真正有帮助的是: +即使有很强的系统提示词,**prompt injection 仍然没有被解决**。系统提示词护栏只是软性指导;真正的硬性约束来自工具策略、exec 审批、沙箱隔离和渠道 allowlist(而且操作员可以按设计关闭它们)。在实践中真正有帮助的是: -- 锁定入站私信(pairing / allowlist)。 -- 在群组中优先使用 mention 门槛;避免在公共房间中部署“始终在线”的机器人。 +- 锁定入站私信(pairing/allowlists)。 +- 在群组中优先使用提及门控;避免在公开房间中部署“始终在线”的机器人。 - 默认将链接、附件和粘贴的指令视为敌对内容。 -- 在沙箱中执行敏感工具;让 secrets 远离智能体可访问的文件系统。 -- 注意:沙箱隔离是可选启用的。如果沙箱模式关闭,隐式 `host=auto` 会解析到 Gateway 网关主机。显式 `host=sandbox` 仍会以关闭方式失败,因为没有可用的沙箱运行时。如果你希望这种行为在配置中更明确,请设置 `host=gateway`。 -- 将高风险工具(`exec`、`browser`、`web_fetch`、`web_search`)限制给受信任智能体或显式 allowlist。 -- 如果你对解释器(`python`、`node`、`ruby`、`perl`、`php`、`lua`、`osascript`)使用 allowlist,请启用 `tools.exec.strictInlineEval`,这样内联 eval 形式仍然需要显式审批。 -- Shell 审批分析还会拒绝**未加引号的 heredoc** 中的 POSIX 参数展开形式(`$VAR`、`$?`、`$$`、`$1`、`$@`、`${…}`),因此 allowlist 中的 heredoc 正文不能伪装成普通文本来绕过 allowlist 审查。若要启用字面量正文语义,请给 heredoc 终止符加引号(例如 `<<'EOF'`);任何本会发生变量展开的未加引号 heredoc 都会被拒绝。 -- **模型选择很重要:** 较旧 / 较小 / 旧版模型对提示注入和工具滥用的防御能力明显更弱。对于启用了工具的智能体,请使用当前可用的最强、最新一代、经过指令强化的模型。 +- 在沙箱中执行敏感工具;将 secrets 保持在智能体可访问文件系统之外。 +- 注意:沙箱隔离是选择启用的。如果 sandbox 模式关闭,隐式 `host=auto` 会解析为 gateway 主机。显式 `host=sandbox` 仍会失败关闭,因为没有可用的 sandbox 运行时。如果你希望在配置中明确表达该行为,请设置 `host=gateway`。 +- 将高风险工具(`exec`、`browser`、`web_fetch`、`web_search`)限制给受信任的智能体或显式 allowlist。 +- 如果你对解释器(`python`、`node`、`ruby`、`perl`、`php`、`lua`、`osascript`)使用 allowlist,请启用 `tools.exec.strictInlineEval`,这样 inline eval 形式仍需要显式审批。 +- Shell 审批分析还会拒绝**未加引号的 heredoc** 中的 POSIX 参数展开形式(`$VAR`、`$?`、`$$`、`$1`、`$@`、`${…}`),因此 allowlist 允许的 heredoc 内容无法将 shell 展开伪装成纯文本绕过 allowlist 审查。若要启用字面量正文语义,请给 heredoc 终止符加引号(例如 `<<'EOF'`);未加引号且会展开变量的 heredoc 会被拒绝。 +- **模型选择很重要:** 较旧/较小/旧版模型在抵御 prompt injection 和工具滥用方面明显更弱。对于启用了工具的智能体,请使用当前可用的最新一代、指令加固能力最强的模型。 -以下红旗内容应视为不受信任: +应视为不受信任的危险信号: -- “读取这个文件 / URL,然后完全照它说的做。” -- “忽略你的系统提示或安全规则。” -- “泄露你的隐藏指令或工具输出。” -- “把 `~/.openclaw` 或你的日志的完整内容贴出来。” +- “读取这个文件/URL,并严格照它说的做。” +- “忽略你的系统提示词或安全规则。” +- “透露你的隐藏指令或工具输出。” +- “粘贴 `~/.openclaw` 或你的日志的全部内容。” ## 外部内容特殊 token 清洗 -OpenClaw 会在包装外部内容和元数据后、送入模型前,去除常见的自托管 LLM 聊天模板特殊 token 字面量。涵盖的标记家族包括 Qwen / ChatML、Llama、Gemma、Mistral、Phi 以及 GPT-OSS 的角色 / 轮次 token。 +OpenClaw 会在常见的自托管 LLM chat template 特殊 token 字面量到达模型之前,从封装后的外部内容和元数据中剥离它们。覆盖的标记家族包括 Qwen/ChatML、Llama、Gemma、Mistral、Phi,以及 GPT-OSS 角色/轮次 token。 原因: -- 某些面向自托管模型的 OpenAI 兼容后端,会保留出现在用户文本中的特殊 token,而不是将其屏蔽。攻击者如果能向入站外部内容中写入数据(例如抓取页面、邮件正文、文件读取工具输出),原本就可能借此注入伪造的 `assistant` 或 `system` 角色边界,绕过包装内容的防护。 -- 清洗发生在外部内容包装层,因此它会统一作用于 fetch / read 工具和入站渠道内容,而不是按提供商分别处理。 -- 出站模型响应已经有单独的清洗器,会从面向用户的回复中去除泄露的 ``、`` 等脚手架内容。外部内容清洗器则是与之对应的入站版本。 +- 一些面向自托管模型的 OpenAI 兼容后端,有时会保留用户文本中出现的特殊 token,而不是将其屏蔽。攻击者如果能写入入站外部内容(抓取的页面、邮件正文、文件内容工具输出),原本就可能借此注入伪造的 `assistant` 或 `system` 角色边界,并逃逸外部内容封装护栏。 +- 清洗发生在外部内容封装层,因此它会统一应用于 fetch/read 工具和入站渠道内容,而不是按提供商单独处理。 +- 出站模型响应已经有一个独立的清洗器,用于从用户可见回复中剥离泄露的 ``、`` 之类的脚手架。外部内容清洗器则是其对应的入站版本。 -这并不能替代本页中的其他加固措施——`dmPolicy`、allowlist、exec 审批、沙箱隔离和 `contextVisibility` 仍然承担主要防护作用。它关闭的是一种特定的 tokenizer 层绕过路径,针对的是那些会原样转发带特殊 token 用户文本的自托管技术栈。 +这并不能替代本页中的其他加固措施 —— `dmPolicy`、allowlists、exec 审批、沙箱隔离和 `contextVisibility` 仍然承担主要作用。它只是关闭了一个针对自托管技术栈的特定 tokenizer 层绕过问题,这类技术栈会原样转发带特殊 token 的用户文本。 ## 不安全外部内容绕过标志 -OpenClaw 包含显式绕过标志,可用于禁用外部内容安全包装: +OpenClaw 包含一些显式绕过标志,可禁用外部内容安全封装: - `hooks.mappings[].allowUnsafeExternalContent` - `hooks.gmail.allowUnsafeExternalContent` - Cron 负载字段 `allowUnsafeExternalContent` -建议: +指导建议: -- 在生产环境中保持未设置 / `false`。 +- 在生产环境中保持这些设置为未设置/false。 - 仅在严格限定范围的调试中临时启用。 -- 如果启用,应隔离该智能体(沙箱 + 最小工具集 + 专用 session 命名空间)。 +- 如果启用,请隔离该智能体(沙箱隔离 + 最小工具 + 专用会话命名空间)。 Hooks 风险说明: -- Hook 负载属于不受信任内容,即使投递来自你控制的系统也是如此(邮件 / 文档 / 网页内容都可能携带提示注入)。 -- 较弱模型等级会放大这种风险。对于由 Hook 驱动的自动化,应优先使用强大的现代模型等级,并保持严格的工具策略(`tools.profile: "messaging"` 或更严格),在可能时再加上沙箱隔离。 +- Hook 负载属于不受信任内容,即使投递来自你控制的系统也是如此(邮件/文档/网页内容都可能携带 prompt injection)。 +- 较弱的模型层级会放大这种风险。对于基于 Hook 的自动化,请优先使用强健的现代模型层级,并保持严格的工具策略(`tools.profile: "messaging"` 或更严格),同时尽可能启用沙箱隔离。 -### 提示注入并不需要公开私信 +### Prompt injection 并不要求开放私信 -即使**只有你自己**可以给机器人发消息,只要机器人会读取任何**不受信任内容**, -提示注入仍然可能发生(网页搜索 / 抓取结果、浏览器页面、邮件、文档、附件、粘贴的日志 / 代码)。 -换句话说:威胁面不只有发送者;**内容本身**也可能携带对抗性指令。 +即使**只有你自己**可以给机器人发消息,prompt injection 仍然可以通过 +机器人读取的任何**不受信任内容**发生(网页搜索/抓取结果、浏览器页面、 +电子邮件、文档、附件、粘贴的日志/代码)。换句话说:发送者不是唯一的威胁面; +**内容本身**也可能携带对抗性指令。 -启用工具后,典型风险是外泄上下文或触发工具调用。可以通过以下方式缩小影响半径: +当工具已启用时,典型风险是外泄上下文或触发工具调用。可通过以下方式缩小影响半径: -- 使用只读或禁用工具的**reader 智能体**来总结不受信任内容, - 然后再把总结结果传给你的主智能体。 -- 对启用了工具的智能体,仅在确有需要时才开启 `web_search` / `web_fetch` / `browser`。 -- 对于 OpenResponses URL 输入(`input_file` / `input_image`),请严格设置 +- 使用只读或禁用工具的**读取智能体**来总结不受信任内容, + 然后再将摘要传给你的主智能体。 +- 对启用了工具的智能体,除非确有需要,否则关闭 `web_search` / `web_fetch` / `browser`。 +- 对于 OpenResponses URL 输入(`input_file` / `input_image`),设置严格的 `gateway.http.endpoints.responses.files.urlAllowlist` 和 - `gateway.http.endpoints.responses.images.urlAllowlist`,并将 `maxUrlParts` 保持较低。 + `gateway.http.endpoints.responses.images.urlAllowlist`,并保持较低的 `maxUrlParts`。 空 allowlist 会被视为未设置;如果你想完全禁用 URL 抓取,请使用 `files.allowUrl: false` / `images.allowUrl: false`。 - 对于 OpenResponses 文件输入,解码后的 `input_file` 文本仍会作为 - **不受信任的外部内容** 注入。不要因为 Gateway 网关是在本地解码文件, - 就把文件文本视为受信任内容。注入块仍会带有明确的 - `<<>>` 边界标记以及 `Source: External` + **不受信任外部内容**注入。不要因为 Gateway 网关是在本地解码文件文本,就假设它是可信的。 + 注入的块仍然带有明确的 `<<>>` 边界标记以及 `Source: External` 元数据,尽管这一路径省略了更长的 `SECURITY NOTICE:` 横幅。 -- 当媒体理解在将文档提取文本附加到媒体提示之前提取文本时,也会应用同样基于标记的包装。 -- 对任何接触不受信任输入的智能体启用沙箱隔离和严格工具 allowlist。 -- 不要把 secrets 放进提示中;应通过 Gateway 网关主机上的 env / config 传递。 +- 当 media-understanding 从附加文档中提取文本,并将其附加到媒体提示词时,也会应用同样基于标记的封装。 +- 对任何会接触不受信任输入的智能体,启用沙箱隔离和严格的工具 allowlist。 +- 不要把 secrets 放进提示词中;改为通过 gateway 主机上的 env/config 传递。 ### 自托管 LLM 后端 OpenAI 兼容的自托管后端,例如 vLLM、SGLang、TGI、LM Studio, -或自定义 Hugging Face tokenizer 技术栈,在处理聊天模板特殊 token 的方式上, -可能与托管提供商不同。如果某个后端会把用户内容中的字面字符串, -例如 `<|im_start|>`、`<|start_header_id|>` 或 ``, -在 tokenizer 层面解析为结构化聊天模板 token,那么不受信任文本就可能尝试在 tokenizer 层伪造角色边界。 +或自定义 Hugging Face tokenizer 技术栈,在处理 +chat template 特殊 token 的方式上,可能与托管提供商不同。如果某个后端会将 +诸如 `<|im_start|>`、`<|start_header_id|>` 或 `` 这样的字面字符串 +在用户内容中 token 化为结构性的 chat template token, +那么不受信任的文本就可能尝试在 tokenizer 层伪造角色边界。 -OpenClaw 会在将包装后的外部内容发送给模型之前, -从中移除常见模型家族的特殊 token 字面量。请保持外部内容包装处于启用状态, -并在后端支持的情况下,优先使用能够对用户提供内容中的特殊 token 进行拆分或转义的设置。 -OpenAI 和 Anthropic 等托管提供商已经在请求侧实施了各自的清洗措施。 +OpenClaw 会在将封装后的外部内容分发给模型之前, +剥离其中常见模型家族的特殊 token 字面量。请保持外部内容封装启用, +并在后端支持的情况下,优先使用会对用户提供内容中的特殊 token 进行拆分或转义的后端设置。 +像 OpenAI 和 Anthropic 这样的托管提供商 +已经在请求侧应用了它们自己的清洗机制。 ### 模型强度(安全说明) -不同模型等级对提示注入的抵抗能力**并不一致**。更小 / 更便宜的模型通常更容易受到工具滥用和指令劫持的影响,尤其是在对抗性提示下。 +不同模型层级的 prompt injection 抵抗能力**并不一致**。更小/更便宜的模型通常更容易受到工具滥用和指令劫持的影响,尤其是在对抗性提示下。 -对于启用了工具的智能体,或会读取不受信任内容的智能体,较旧 / 较小模型带来的提示注入风险通常过高。不要在较弱模型等级上运行这些工作负载。 +对于启用了工具的智能体,或会读取不受信任内容的智能体,旧模型/小模型带来的 prompt injection 风险往往过高。不要在弱模型层级上运行这些工作负载。 建议: -- 对于任何可以运行工具或接触文件 / 网络的机器人,**使用最新一代、最高等级的模型**。 -- 对于启用了工具的智能体或不受信任收件箱,**不要使用较旧 / 较弱 / 较小的等级**;提示注入风险过高。 -- 如果你必须使用较小模型,**缩小影响半径**(只读工具、强沙箱隔离、最小文件系统访问、严格 allowlist)。 -- 运行小模型时,**为所有 session 启用沙箱隔离**,并且**禁用 `web_search` / `web_fetch` / `browser`**,除非输入受到严格控制。 -- 对于仅聊天、输入受信任且不使用工具的个人助理,较小模型通常是可以接受的。 +- 对任何能够运行工具或接触文件/网络的机器人,都应**使用最新一代、最佳层级的模型**。 +- 对于启用了工具的智能体或处理不受信任收件箱的智能体,**不要使用较旧/较弱/较小的层级**;prompt injection 风险过高。 +- 如果你必须使用较小模型,务必**缩小影响半径**(只读工具、强沙箱隔离、最小文件系统访问、严格 allowlists)。 +- 运行小模型时,应**为所有会话启用沙箱隔离**,并且除非输入受到严格控制,否则**禁用 `web_search`/`web_fetch`/`browser`**。 +- 对于仅聊天的个人助理,若输入受信任且没有工具,小模型通常是可以接受的。 -## 群组中的推理与详细输出 +## 群组中的 Reasoning 和详细输出 -`/reasoning`、`/verbose` 和 `/trace` 可能暴露内部推理、工具 -输出或插件诊断信息,而这些内容 -原本并不适合公开渠道。在群组环境中,应将它们视为**仅用于调试** -的功能,除非你明确需要,否则请保持关闭。 +`/reasoning`、`/verbose` 和 `/trace` 可能会暴露内部推理、工具 +输出或插件诊断信息,而这些信息 +原本并不适合出现在公开渠道中。在群组环境下,应将它们视为**仅用于调试**, +除非你明确需要,否则请保持关闭。 -建议: +指导建议: -- 在公共房间中保持 `/reasoning`、`/verbose` 和 `/trace` 关闭。 -- 如果你启用它们,也只应在受信任私信或严格受控的房间中启用。 +- 在公开房间中保持 `/reasoning`、`/verbose` 和 `/trace` 关闭。 +- 如果你启用它们,也只应在受信任的私信或严格控制的房间中启用。 - 请记住:verbose 和 trace 输出可能包含工具参数、URL、插件诊断信息,以及模型看到的数据。 ## 配置加固(示例) @@ -762,44 +765,44 @@ OpenAI 和 Anthropic 等托管提供商已经在请求侧实施了各自的清 `openclaw doctor` 可以发出警告,并提供收紧这些权限的选项。 -### 0.4)网络暴露(bind + port + firewall) +### 0.4)网络暴露(bind + port + 防火墙) -Gateway 网关会在单个端口上复用 **WebSocket + HTTP**: +Gateway 网关在单一端口上复用**WebSocket + HTTP**: -- 默认:`18789` -- 配置 / 标志 / 环境变量:`gateway.port`、`--port`、`OPENCLAW_GATEWAY_PORT` +- 默认值:`18789` +- 配置/标志/环境变量:`gateway.port`、`--port`、`OPENCLAW_GATEWAY_PORT` -该 HTTP 接口包括控制 UI 和 canvas host: +这个 HTTP 表面包括 Control UI 和 canvas host: -- 控制 UI(SPA 静态资源)(默认基础路径 `/`) -- Canvas host:`/__openclaw__/canvas/` 和 `/__openclaw__/a2ui/`(任意 HTML / JS;应视为不受信任内容) +- Control UI(SPA 静态资源)(默认基础路径 `/`) +- Canvas host:`/__openclaw__/canvas/` 和 `/__openclaw__/a2ui/`(任意 HTML/JS;应将其视为不受信任内容) -如果你在普通浏览器中加载 canvas 内容,应像对待其他不受信任网页一样对待它: +如果你在普通浏览器中加载 canvas 内容,请像对待任何其他不受信任网页一样对待它: -- 不要将 canvas host 暴露给不受信任的网络 / 用户。 -- 除非你完全理解其影响,否则不要让 canvas 内容与特权 Web 接口共享同一个 origin。 +- 不要将 canvas host 暴露给不受信任的网络/用户。 +- 除非你完全理解其影响,否则不要让 canvas 内容与特权 Web 表面共享同一来源。 -Bind 模式决定 Gateway 网关监听的位置: +Bind 模式控制 Gateway 网关监听的位置: - `gateway.bind: "loopback"`(默认):只有本地客户端可以连接。 -- 非 loopback bind(`"lan"`、`"tailnet"`、`"custom"`)会扩大攻击面。只有在启用了 Gateway 网关认证(共享 token / password,或正确配置的非 loopback trusted proxy)并配合真实防火墙时才应使用。 +- 非 loopback bind(`"lan"`、`"tailnet"`、`"custom"`)会扩大攻击面。只有在启用了 Gateway 网关鉴权(共享 token/password,或正确配置的非 loopback trusted proxy)并配有真实防火墙时才应使用。 经验规则: -- 优先使用 Tailscale Serve,而不是 LAN bind(Serve 会让 Gateway 网关保持在 loopback 上,由 Tailscale 负责访问控制)。 -- 如果你必须绑定到 LAN,请用防火墙把端口限制在严格的源 IP allowlist 中;不要广泛做端口转发。 -- 永远不要把未认证的 Gateway 网关暴露在 `0.0.0.0` 上。 +- 优先使用 Tailscale Serve,而不是 LAN bind(Serve 会让 Gateway 网关保持在 loopback 上,由 Tailscale 处理访问)。 +- 如果你必须绑定到 LAN,请用防火墙将端口限制为严格的源 IP allowlist;不要广泛做端口转发。 +- 绝不要在 `0.0.0.0` 上以未鉴权方式暴露 Gateway 网关。 ### 0.4.1)Docker 端口发布 + UFW(`DOCKER-USER`) -如果你在 VPS 上通过 Docker 运行 OpenClaw,请记住,已发布的容器端口 +如果你在 VPS 上使用 Docker 运行 OpenClaw,请记住,已发布的容器端口 (`-p HOST:CONTAINER` 或 Compose `ports:`)会通过 Docker 的转发链路路由, -而不只是经过主机的 `INPUT` 规则。 +而不仅仅经过主机的 `INPUT` 规则。 为了让 Docker 流量与防火墙策略保持一致,请在 -`DOCKER-USER` 中强制执行规则(该链会在 Docker 自身的 accept 规则之前被评估)。 -在许多现代发行版上,`iptables` / `ip6tables` 使用 `iptables-nft` 前端, -但这些规则仍会应用到 nftables 后端。 +`DOCKER-USER` 中强制执行规则(该链会在 Docker 自身的 accept 规则之前评估)。 +在许多现代发行版上,`iptables`/`ip6tables` 使用 `iptables-nft` 前端, +但这些规则仍会应用到底层 nftables 后端。 最小 allowlist 示例(IPv4): @@ -820,12 +823,11 @@ Bind 模式决定 Gateway 网关监听的位置: COMMIT ``` -IPv6 使用单独的表。如果启用了 Docker IPv6, -请在 `/etc/ufw/after6.rules` 中添加对应策略。 +IPv6 有独立的表。如果启用了 Docker IPv6,请在 `/etc/ufw/after6.rules` 中 +添加匹配的策略。 -避免在文档示例中硬编码类似 `eth0` 这样的接口名。接口名 -会因 VPS 镜像而异(`ens3`、`enp*` 等),一旦不匹配, -可能会意外跳过你的拒绝规则。 +避免在文档片段中硬编码像 `eth0` 这样的接口名。不同 VPS 镜像中的接口名 +各不相同(`ens3`、`enp*` 等),不匹配可能会意外绕过你的拒绝规则。 重载后的快速验证: @@ -836,22 +838,22 @@ ip6tables -S DOCKER-USER nmap -sT -p 1-65535 --open ``` -预期的对外开放端口应只包含你有意暴露的端口(对大多数 -配置来说:SSH + 你的反向代理端口)。 +预期的外部端口应仅包括你有意暴露的端口(对大多数 +配置而言:SSH + 你的反向代理端口)。 -### 0.4.2)mDNS / Bonjour 设备发现(信息泄露) +### 0.4.2)mDNS/Bonjour 发现(信息泄露) -Gateway 网关会通过 mDNS(`_openclaw-gw._tcp`,端口 5353)广播自身存在,以便本地设备发现。在完整模式下,这还包括可能暴露运维细节的 TXT 记录: +Gateway 网关会通过 mDNS(5353 端口上的 `_openclaw-gw._tcp`)广播自身存在,以供本地设备发现。在 full 模式下,这包括可能暴露运维细节的 TXT 记录: -- `cliPath`:CLI 二进制文件的完整文件系统路径(会泄露用户名和安装位置) +- `cliPath`:CLI 二进制文件的完整文件系统路径(会暴露用户名和安装位置) - `sshPort`:广播主机上 SSH 可用 - `displayName`、`lanHost`:主机名信息 -**运维安全注意事项:** 广播基础设施细节会让本地网络中的任何人更容易进行侦察。即使是文件系统路径、SSH 可用性这类“看似无害”的信息,也有助于攻击者绘制你的环境地图。 +**运维安全注意事项:** 广播基础设施细节会让本地网络上的任何人更容易进行侦察。即使是文件系统路径和 SSH 可用性这类“看似无害”的信息,也有助于攻击者绘制你的环境图谱。 **建议:** -1. **最小模式**(默认,推荐用于已暴露的 Gateway 网关):从 mDNS 广播中省略敏感字段: +1. **Minimal 模式**(默认,推荐用于已暴露的 Gateway 网关):从 mDNS 广播中省略敏感字段: ```json5 { @@ -861,7 +863,7 @@ Gateway 网关会通过 mDNS(`_openclaw-gw._tcp`,端口 5353)广播自身 } ``` -2. 如果你不需要本地设备发现,**可完全禁用**: +2. 如果你不需要本地设备发现,可**完全禁用**: ```json5 { @@ -871,7 +873,7 @@ Gateway 网关会通过 mDNS(`_openclaw-gw._tcp`,端口 5353)广播自身 } ``` -3. **完整模式**(显式启用):在 TXT 记录中包含 `cliPath` + `sshPort`: +3. **Full 模式**(选择启用):在 TXT 记录中包含 `cliPath` + `sshPort`: ```json5 { @@ -881,19 +883,19 @@ Gateway 网关会通过 mDNS(`_openclaw-gw._tcp`,端口 5353)广播自身 } ``` -4. **环境变量**(另一种方式):设置 `OPENCLAW_DISABLE_BONJOUR=1`,无需改配置即可禁用 mDNS。 +4. **环境变量**(替代方式):设置 `OPENCLAW_DISABLE_BONJOUR=1`,无需修改配置即可禁用 mDNS。 -在最小模式下,Gateway 网关仍会广播设备发现所需的足够信息(`role`、`gatewayPort`、`transport`),但会省略 `cliPath` 和 `sshPort`。需要 CLI 路径信息的应用可以改为通过经过认证的 WebSocket 连接获取。 +在 minimal 模式下,Gateway 网关仍然会广播足够用于设备发现的信息(`role`、`gatewayPort`、`transport`),但会省略 `cliPath` 和 `sshPort`。需要 CLI 路径信息的应用,仍可以通过已鉴权的 WebSocket 连接获取它。 -### 0.5)锁定 Gateway 网关 WebSocket(本地认证) +### 0.5)锁定 Gateway 网关 WebSocket(本地鉴权) -Gateway 网关认证默认**必须启用**。如果没有配置有效的 Gateway 网关认证路径, -Gateway 网关会拒绝 WebSocket 连接(以关闭方式失败)。 +默认情况下**必须启用** Gateway 网关鉴权。如果未配置有效的 Gateway 网关鉴权路径, +Gateway 网关会拒绝 WebSocket 连接(失败关闭)。 新手引导默认会生成一个 token(即使在 loopback 上也是如此),因此 -本地客户端也必须进行认证。 +本地客户端也必须完成鉴权。 -设置一个 token,这样**所有** WS 客户端都必须认证: +设置一个 token,使**所有** WS 客户端都必须鉴权: ```json5 { @@ -903,141 +905,151 @@ Gateway 网关会拒绝 WebSocket 连接(以关闭方式失败)。 } ``` -Doctor 可以为你生成:`openclaw doctor --generate-gateway-token`。 +Doctor 可以为你生成一个:`openclaw doctor --generate-gateway-token`。 注意:`gateway.remote.token` / `.password` 是客户端凭证来源。 -它们本身**不会**保护本地 WS 访问。 -只有在 `gateway.auth.*` 未设置时, -本地调用路径才会把 `gateway.remote.*` 作为回退。 -如果通过 SecretRef 显式配置了 `gateway.auth.token` / `gateway.auth.password` 但无法解析, -解析会以关闭方式失败(不会用远程回退来掩盖问题)。 -可选:当使用 `wss://` 时,可通过 `gateway.remote.tlsFingerprint` 固定远程 TLS。 -默认情况下,明文 `ws://` 仅限 loopback。对于受信任的私有网络 -路径,可在客户端进程上设置 `OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1` 作为破窗选项。 +它们**本身并不会**保护本地 WS 访问。 +只有当 `gateway.auth.*` 未设置时,本地调用路径才可以将 `gateway.remote.*` +用作回退。 +如果 `gateway.auth.token` / `gateway.auth.password` 通过 +SecretRef 显式配置但无法解析,则解析会失败关闭(不会用远程回退来掩盖)。 +可选项:使用 `wss://` 时,可通过 `gateway.remote.tlsFingerprint` 固定远程 TLS。 +纯文本 `ws://` 默认仅限 loopback。对于受信任的私有网络 +路径,可在客户端进程上设置 `OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1` 作为紧急兜底。 本地设备配对: -- 对于直接的本地 loopback 连接,设备配对会自动批准, - 以保持同主机客户端体验顺畅。 -- OpenClaw 还提供了一条窄范围的后端 / 容器本地自连接路径, - 用于受信任的共享密钥辅助流程。 -- Tailnet 和 LAN 连接,包括同主机的 tailnet bind,都会被视为远程连接,因此仍然需要审批配对。 +- 对于直接的本地 loopback 连接,设备配对会自动批准,以保持 + 同主机客户端使用顺畅。 +- OpenClaw 还提供了一个狭窄的后端/容器本地自连接路径,用于 + 受信任的共享密钥辅助流程。 +- Tailnet 和 LAN 连接,包括同一主机上的 tailnet bind,都会被视为远程连接, + 仍然需要批准。 +- **转发头证据会取消 loopback 本地性资格。** 如果某个请求 + 到达 loopback,但携带了 `X-Forwarded-For` / `X-Forwarded-Host` / + `X-Forwarded-Proto` 头,并指向非本地来源,则该请求 + 会被视为远程连接,用于配对、trusted-proxy 鉴权以及 Control UI 设备 + 身份门控 —— 它不再符合 loopback 自动批准条件。 +- **元数据升级自动批准** 仅适用于那些已配对、受信任的本地 CLI/辅助客户端在 loopback 上证明持有共享 token 或密码后发生的非敏感重连变化。浏览器/Control UI 客户端和远程客户端仍然需要显式重新批准。范围升级(从只读到写入/管理员)以及公钥变更绝不会被静默升级。 -认证模式: +鉴权模式: - `gateway.auth.mode: "token"`:共享 bearer token(推荐用于大多数配置)。 -- `gateway.auth.mode: "password"`:password 认证(建议通过环境变量设置:`OPENCLAW_GATEWAY_PASSWORD`)。 -- `gateway.auth.mode: "trusted-proxy"`:信任具备身份感知能力的反向代理来认证用户,并通过请求头传递身份(见 [Trusted Proxy Auth](/zh-CN/gateway/trusted-proxy-auth))。 +- `gateway.auth.mode: "password"`:密码鉴权(建议通过 env 设置:`OPENCLAW_GATEWAY_PASSWORD`)。 +- `gateway.auth.mode: "trusted-proxy"`:信任具备身份感知能力的反向代理来对用户进行鉴权,并通过头传递身份(参见 [Trusted Proxy Auth](/zh-CN/gateway/trusted-proxy-auth))。 -轮换检查清单(token / password): +轮换检查清单(token/password): -1. 生成 / 设置新的 secret(`gateway.auth.token` 或 `OPENCLAW_GATEWAY_PASSWORD`)。 -2. 重启 Gateway 网关(如果由 macOS 应用监管 Gateway 网关,则重启该应用)。 -3. 更新所有远程客户端(调用 Gateway 网关的机器上的 `gateway.remote.token` / `.password`)。 -4. 验证旧凭证已无法再连接。 +1. 生成/设置新的 secret(`gateway.auth.token` 或 `OPENCLAW_GATEWAY_PASSWORD`)。 +2. 重启 Gateway 网关(如果由 macOS 应用托管 Gateway 网关,则重启该应用)。 +3. 更新任何远程客户端(调用 Gateway 网关的机器上配置的 `gateway.remote.token` / `.password`)。 +4. 验证你已无法再使用旧凭证连接。 -### 0.6)Tailscale Serve 身份请求头 +### 0.6)Tailscale Serve 身份头 -当 `gateway.auth.allowTailscale` 为 `true` 时(Serve 的默认值),OpenClaw -会接受 Tailscale Serve 身份请求头(`tailscale-user-login`)用于控制 UI / WebSocket 认证。OpenClaw 会通过本地 Tailscale 守护进程(`tailscale whois`)解析 -`x-forwarded-for` 地址,并将其与请求头进行匹配,从而验证该身份。只有当请求命中 loopback, -并且同时包含由 Tailscale 注入的 `x-forwarded-for`、`x-forwarded-proto` 和 `x-forwarded-host` 时,才会触发这一路径。 -对于这条异步身份检查路径,来自同一 `{scope, ip}` -的失败尝试会在限流器记录失败之前被串行化。因此,同一个 Serve 客户端发起的并发错误重试 -可能会让第二次尝试立即被锁定,而不是像两次普通不匹配那样并发穿过。 +当 `gateway.auth.allowTailscale` 为 `true`(Serve 的默认值)时,OpenClaw +会接受 Tailscale Serve 身份头(`tailscale-user-login`)用于 Control +UI/WebSocket 鉴权。OpenClaw 会通过本地 Tailscale 守护进程 +(`tailscale whois`)解析 `x-forwarded-for` 地址并将其与该头匹配,从而验证身份。此逻辑仅在请求命中 loopback +且包含由 Tailscale 注入的 `x-forwarded-for`、`x-forwarded-proto` 和 `x-forwarded-host` +时触发。 +对于这一路径中的异步身份检查,相同 `{scope, ip}` 的失败尝试 +会在限流器记录失败之前被串行化处理。因此,来自某个 Serve 客户端的并发错误重试 +可能会立即锁定第二次尝试,而不是像两个普通不匹配请求那样相互竞态。 HTTP API 端点(例如 `/v1/*`、`/tools/invoke` 和 `/api/channels/*`) -**不会**使用 Tailscale 身份请求头认证。它们仍遵循 Gateway 网关 -已配置的 HTTP 认证模式。 +**不会**使用 Tailscale 身份头鉴权。它们仍然遵循 Gateway 网关 +已配置的 HTTP 鉴权模式。 重要边界说明: -- Gateway 网关 HTTP bearer 认证实际上等同于全权限操作员访问。 -- 应将能够调用 `/v1/chat/completions`、`/v1/responses` 或 `/api/channels/*` 的凭证视为该 Gateway 网关的全访问操作员 secret。 -- 在 OpenAI 兼容 HTTP 接口上,共享密钥 bearer 认证会恢复完整的默认操作员作用域(`operator.admin`、`operator.approvals`、`operator.pairing`、`operator.read`、`operator.talk.secrets`、`operator.write`)以及智能体轮次的 owner 语义;更窄的 `x-openclaw-scopes` 值不会缩减这一路径上的共享密钥权限。 -- HTTP 上的按请求作用域语义仅在请求来自带身份的模式时才适用,例如 trusted proxy 认证,或私有入口上的 `gateway.auth.mode="none"`。 -- 在这些带身份的模式下,如果省略 `x-openclaw-scopes`,则会回退为普通的默认操作员作用域集合;若你希望使用更窄的作用域集合,请显式发送该请求头。 -- `/tools/invoke` 也遵循同样的共享密钥规则:在那里,token / password bearer 认证同样被视为完整操作员访问,而带身份的模式仍会遵循声明的作用域。 -- 不要与不受信任的调用方共享这些凭证;应优先为不同信任边界使用单独的 Gateway 网关。 +- Gateway 网关 HTTP bearer 鉴权实际上等同于全有或全无的操作员访问权限。 +- 能够调用 `/v1/chat/completions`、`/v1/responses` 或 `/api/channels/*` 的凭证,应视为该 Gateway 网关的完全访问级操作员 secrets。 +- 在 OpenAI 兼容 HTTP 表面上,共享密钥 bearer 鉴权会恢复完整的默认操作员作用域(`operator.admin`、`operator.approvals`、`operator.pairing`、`operator.read`、`operator.talk.secrets`、`operator.write`)以及智能体轮次的 owner 语义;较窄的 `x-openclaw-scopes` 值不会缩小这条共享密钥路径。 +- HTTP 上的逐请求作用域语义,仅在请求来自携带身份的模式时才适用,例如 trusted proxy 鉴权,或私有入站上的 `gateway.auth.mode="none"`。 +- 在这些携带身份的模式中,如果省略 `x-openclaw-scopes`,会回退为正常的默认操作员作用域集合;当你想要更窄的作用域集时,请显式发送该头。 +- `/tools/invoke` 遵循同样的共享密钥规则:token/password bearer 鉴权在这里同样被视为完整操作员访问,而携带身份的模式仍会遵循声明的作用域。 +- 不要与不受信任的调用方共享这些凭证;应优先按信任边界拆分独立的 Gateway 网关。 -**信任假设:** 无 token 的 Serve 认证假设 Gateway 网关主机是受信任的。 -不要把它当成针对同主机敌对进程的保护措施。如果不受信任的 -本地代码可能会在 Gateway 网关主机上运行,请禁用 `gateway.auth.allowTailscale`, -并要求显式共享密钥认证,即使用 `gateway.auth.mode: "token"` 或 +**信任假设:** 无 token 的 Serve 鉴权假设 Gateway 网关主机是受信任的。 +不要把它视为针对同主机恶意进程的保护措施。如果 +不受信任的本地代码可能在 Gateway 网关主机上运行,请禁用 `gateway.auth.allowTailscale`, +并要求显式的共享密钥鉴权,使用 `gateway.auth.mode: "token"` 或 `"password"`。 -**安全规则:** 不要从你自己的反向代理转发这些请求头。如果 -你在 Gateway 网关前终止 TLS 或进行代理,请禁用 -`gateway.auth.allowTailscale`,并改用共享密钥认证(`gateway.auth.mode: +**安全规则:** 不要从你自己的反向代理转发这些头。如果 +你在 Gateway 网关前终止 TLS 或做代理,请禁用 +`gateway.auth.allowTailscale`,并改用共享密钥鉴权(`gateway.auth.mode: "token"` 或 `"password"`)或 [Trusted Proxy Auth](/zh-CN/gateway/trusted-proxy-auth)。 受信任代理: - 如果你在 Gateway 网关前终止 TLS,请将 `gateway.trustedProxies` 设置为你的代理 IP。 -- OpenClaw 会信任来自这些 IP 的 `x-forwarded-for`(或 `x-real-ip`),以确定客户端 IP,用于本地配对检查以及 HTTP 认证 / 本地检查。 +- OpenClaw 会信任来自这些 IP 的 `x-forwarded-for`(或 `x-real-ip`),以确定客户端 IP,用于本地配对检查以及 HTTP 鉴权/本地检查。 - 确保你的代理会**覆盖** `x-forwarded-for`,并阻止对 Gateway 网关端口的直接访问。 -参见 [Tailscale](/zh-CN/gateway/tailscale) 和 [Web 概览](/web)。 +参阅 [Tailscale](/zh-CN/gateway/tailscale) 和 [Web 概览](/zh-CN/web)。 -### 0.6.1)通过节点主机进行浏览器控制(推荐) +### 0.6.1)通过 node host 进行浏览器控制(推荐) -如果你的 Gateway 网关是远程的,但浏览器运行在另一台机器上,请在浏览器所在机器上运行一个**节点主机**, -让 Gateway 网关代理浏览器操作(见[浏览器工具](/zh-CN/tools/browser))。 -应将节点配对视为管理员级访问。 +如果你的 Gateway 网关位于远程,但浏览器运行在另一台机器上,请在浏览器所在机器上运行一个 **node host**, +并让 Gateway 网关代理浏览器操作(参见[浏览器工具](/zh-CN/tools/browser))。 +应将 node 配对视为管理员级访问。 推荐模式: -- 让 Gateway 网关和节点主机位于同一个 tailnet(Tailscale)中。 -- 有意识地对节点进行配对;如果不需要浏览器代理路由,请将其禁用。 +- 让 Gateway 网关 和 node host 处于同一个 tailnet(Tailscale)中。 +- 有意识地完成 node 配对;如果你不需要浏览器代理路由,请关闭它。 -应避免: +避免: -- 通过 LAN 或公共互联网暴露 relay / control 端口。 +- 通过 LAN 或公共互联网暴露中继/控制端口。 - 对浏览器控制端点使用 Tailscale Funnel(公共暴露)。 ### 0.7)磁盘上的 secrets(敏感数据) 应假设 `~/.openclaw/`(或 `$OPENCLAW_STATE_DIR/`)下的任何内容都可能包含 secrets 或私密数据: -- `openclaw.json`:配置中可能包含 token(Gateway 网关、远程 Gateway 网关)、提供商设置和 allowlist。 -- `credentials/**`:渠道凭证(例如 WhatsApp 凭证)、pairing allowlist、旧版 OAuth 导入。 -- `agents//agent/auth-profiles.json`:API key、token 配置文件、OAuth token,以及可选的 `keyRef` / `tokenRef`。 -- `secrets.json`(可选):供 `file` SecretRef 提供商(`secrets.providers`)使用的基于文件的 secret 负载。 -- `agents//agent/auth.json`:旧版兼容文件。发现静态 `api_key` 条目时会进行清理。 -- `agents//sessions/**`:session 转录(`*.jsonl`)+ 路由元数据(`sessions.json`),其中可能包含私信和工具输出。 +- `openclaw.json`:配置中可能包含 token(Gateway 网关、远程 Gateway 网关)、provider 设置和 allowlists。 +- `credentials/**`:渠道凭证(例如:WhatsApp 凭证)、配对 allowlists、旧版 OAuth 导入。 +- `agents//agent/auth-profiles.json`:API 密钥、token 配置文件、OAuth token,以及可选的 `keyRef`/`tokenRef`。 +- `secrets.json`(可选):供 `file` SecretRef providers(`secrets.providers`)使用的基于文件的 secret 负载。 +- `agents//agent/auth.json`:旧版兼容文件。发现后会清理其中静态的 `api_key` 条目。 +- `agents//sessions/**`:会话转录(`*.jsonl`)+ 路由元数据(`sessions.json`),其中可能包含私密消息和工具输出。 - 内置插件包:已安装的插件(以及它们的 `node_modules/`)。 -- `sandboxes/**`:工具沙箱工作区;可能积累你在沙箱内读取 / 写入文件的副本。 +- `sandboxes/**`:工具沙箱工作区;可能会累积你在沙箱内读写文件的副本。 加固建议: -- 保持严格权限(目录使用 `700`,文件使用 `600`)。 -- 在 Gateway 网关主机上启用全盘加密。 -- 如果主机是共享的,最好为 Gateway 网关使用专用 OS 用户账号。 +- 保持严格权限(目录 `700`,文件 `600`)。 +- 在 Gateway 网关主机上使用全盘加密。 +- 如果主机是共享的,优先为 Gateway 网关使用专用的 OS 用户账户。 ### 0.8)工作区 `.env` 文件 -OpenClaw 会为智能体和工具加载工作区本地 `.env` 文件,但绝不会让这些文件悄悄覆盖 Gateway 网关运行时控制项。 +OpenClaw 会为智能体和工具加载工作区本地 `.env` 文件,但绝不会允许这些文件静默覆盖 Gateway 网关运行时控制。 -- 任何以 `OPENCLAW_*` 开头的键,都会被不受信任的工作区 `.env` 文件阻止。 -- 该阻止机制是以关闭方式失败的:未来版本新增的运行时控制变量,无法从已提交到仓库或由攻击者提供的 `.env` 中继承;该键会被忽略,而 Gateway 网关会保持自己的值。 -- 受信任的进程 / OS 环境变量(Gateway 网关自身的 shell、launchd/systemd 单元、app bundle)仍然会生效——此限制仅约束 `.env` 文件加载。 +- 任何以 `OPENCLAW_*` 开头的键,都会被来自不受信任工作区 `.env` 文件的值阻止。 +- Matrix、Mattermost、IRC 和 Synology Chat 的渠道端点设置也会被阻止通过工作区 `.env` 覆盖,因此克隆的工作区无法通过本地端点配置重定向内置连接器流量。端点环境变量键(如 `MATRIX_HOMESERVER`、`MATTERMOST_URL`、`IRC_HOST`、`SYNOLOGY_CHAT_INCOMING_URL`)必须来自 Gateway 网关进程环境或 `env.shellEnv`,而不能来自工作区加载的 `.env`。 +- 这种阻止是失败关闭的:未来版本中新增加的运行时控制变量,无法从已提交或攻击者提供的 `.env` 中被继承;该键会被忽略,Gateway 网关会保留自己的值。 +- 受信任的进程/OS 环境变量(Gateway 网关自己的 shell、launchd/systemd unit、app bundle)仍然有效 —— 这项限制仅针对 `.env` 文件加载。 -原因:工作区 `.env` 文件通常与智能体代码放在一起,容易被意外提交,或由工具写入。阻止整个 `OPENCLAW_*` 前缀意味着即使未来新增 `OPENCLAW_*` 标志,也绝不会退化为从工作区状态静默继承。 +原因:工作区 `.env` 文件经常与智能体代码放在一起,容易被误提交,或者被工具写入。阻止整个 `OPENCLAW_*` 前缀意味着以后新增任何 `OPENCLAW_*` 标志时,都不可能退化为从工作区状态中静默继承。 ### 0.9)日志 + 转录(脱敏 + 保留) -即使访问控制是正确的,日志和转录也可能泄露敏感信息: +即使访问控制正确,日志和转录也可能泄露敏感信息: - Gateway 网关日志可能包含工具摘要、错误和 URL。 -- Session 转录可能包含粘贴的 secrets、文件内容、命令输出和链接。 +- 会话转录可能包含粘贴的 secrets、文件内容、命令输出和链接。 建议: - 保持工具摘要脱敏开启(`logging.redactSensitive: "tools"`;默认值)。 - 通过 `logging.redactPatterns` 为你的环境添加自定义模式(token、主机名、内部 URL)。 -- 分享诊断信息时,优先使用 `openclaw status --all`(可直接粘贴,secrets 已脱敏),而不是原始日志。 -- 如果你不需要长期保留,请清理旧的 session 转录和日志文件。 +- 共享诊断信息时,优先使用 `openclaw status --all`(可直接粘贴,secrets 已脱敏),而不是原始日志。 +- 如果你不需要长期保留,请清理旧的会话转录和日志文件。 -详情见:[日志](/zh-CN/gateway/logging) +详情参见:[日志](/zh-CN/gateway/logging) ### 1)私信:默认使用 pairing @@ -1047,7 +1059,7 @@ OpenClaw 会为智能体和工具加载工作区本地 `.env` 文件,但绝不 } ``` -### 2)群组:所有地方都要求 mention +### 2)群组:所有地方都要求提及 ```json { @@ -1069,31 +1081,31 @@ OpenClaw 会为智能体和工具加载工作区本地 `.env` 文件,但绝不 } ``` -在群聊中,仅当被明确提及时才响应。 +在群聊中,只有在被明确提及时才回复。 -### 3)分离号码(WhatsApp、Signal、Telegram) +### 3)分开号码(WhatsApp、Signal、Telegram) -对于基于电话号码的渠道,可以考虑让你的 AI 使用与你个人号码不同的单独号码: +对于基于电话号码的渠道,请考虑让你的 AI 使用与个人号码不同的独立号码: - 个人号码:你的对话保持私密 -- 机器人号码:由 AI 处理,并设置合适的边界 +- 机器人号码:AI 处理这些消息,并设置适当边界 -### 4)只读模式(通过沙箱 + 工具) +### 4)只读模式(通过沙箱隔离 + 工具) 你可以通过以下组合构建只读配置: -- `agents.defaults.sandbox.workspaceAccess: "ro"`(或 `"none"`,表示无工作区访问) -- 阻止 `write`、`edit`、`apply_patch`、`exec`、`process` 等的工具 allow / deny 列表 +- `agents.defaults.sandbox.workspaceAccess: "ro"`(或 `"none"` 表示无工作区访问) +- 阻止 `write`、`edit`、`apply_patch`、`exec`、`process` 等操作的工具 allow/deny 列表 其他加固选项: -- `tools.exec.applyPatch.workspaceOnly: true`(默认):确保即使关闭沙箱隔离,`apply_patch` 也无法在工作区目录之外写入 / 删除。只有在你明确希望 `apply_patch` 触及工作区之外文件时,才设置为 `false`。 -- `tools.fs.workspaceOnly: true`(可选):将 `read` / `write` / `edit` / `apply_patch` 路径以及原生提示图片自动加载路径限制在工作区目录内(如果你当前允许绝对路径,并希望增加一个统一防护,这会很有用)。 -- 保持文件系统根目录范围尽可能窄:避免将主目录这类宽泛根目录作为智能体工作区 / 沙箱工作区。宽泛根目录可能会让文件系统工具接触到敏感本地文件(例如 `~/.openclaw` 下的状态 / 配置)。 +- `tools.exec.applyPatch.workspaceOnly: true`(默认):确保即使沙箱隔离关闭,`apply_patch` 也不能在工作区目录之外写入/删除。只有当你明确希望 `apply_patch` 操作工作区之外文件时,才设置为 `false`。 +- `tools.fs.workspaceOnly: true`(可选):将 `read`/`write`/`edit`/`apply_patch` 路径,以及原生提示图片自动加载路径限制在工作区目录内(如果你现在允许绝对路径,并希望有一个统一护栏,这会很有用)。 +- 保持文件系统根目录范围狭窄:避免把像你的主目录这样宽泛的根目录用作智能体工作区/沙箱工作区。宽泛根目录可能会让文件系统工具接触到敏感本地文件(例如 `~/.openclaw` 下的状态/配置)。 -### 5)安全基线(可直接复制 / 粘贴) +### 5)安全基线(复制/粘贴) -一个“默认较安全”的配置:保持 Gateway 网关私有、要求私信 pairing,并避免群组中始终在线的机器人: +一个“安全默认”的配置,可保持 Gateway 网关私有、要求私信 pairing,并避免始终在线的群组机器人: ```json5 { @@ -1112,9 +1124,9 @@ OpenClaw 会为智能体和工具加载工作区本地 `.env` 文件,但绝不 } ``` -如果你还希望工具执行也“默认更安全”,请为任何非 owner 智能体添加沙箱,并禁用危险工具(见下方“按智能体划分的访问配置”示例)。 +如果你还想让工具执行也“默认更安全”,可以为任何非 owner 智能体增加沙箱隔离,并拒绝危险工具(下面“按智能体的访问配置文件”部分有示例)。 -面向聊天驱动智能体轮次的内置基线:非 owner 发送者不能使用 `cron` 或 `gateway` 工具。 +内置的聊天驱动智能体轮次基线:非 owner 发送者不能使用 `cron` 或 `gateway` 工具。 ## 沙箱隔离(推荐) @@ -1123,58 +1135,58 @@ OpenClaw 会为智能体和工具加载工作区本地 `.env` 文件,但绝不 两种互补方式: - **在 Docker 中运行整个 Gateway 网关**(容器边界):[Docker](/zh-CN/install/docker) -- **工具沙箱**(`agents.defaults.sandbox`,主机上的 Gateway 网关 + 沙箱隔离的工具;Docker 是默认后端):[沙箱隔离](/zh-CN/gateway/sandboxing) +- **工具沙箱**(`agents.defaults.sandbox`,主机 Gateway 网关 + 沙箱隔离工具;Docker 是默认后端):[沙箱隔离](/zh-CN/gateway/sandboxing) -注意:为防止跨智能体访问,请将 `agents.defaults.sandbox.scope` 保持为 `"agent"`(默认) -或使用 `"session"` 以获得更严格的按 session 隔离。`scope: "shared"` 会使用 -单个容器 / 工作区。 +注意:为了防止跨智能体访问,请将 `agents.defaults.sandbox.scope` 保持为 `"agent"`(默认) +或使用 `"session"` 以实现更严格的按会话隔离。`scope: "shared"` 会使用 +单个容器/工作区。 -还应考虑沙箱内的智能体工作区访问: +同时也要考虑沙箱中的智能体工作区访问: -- `agents.defaults.sandbox.workspaceAccess: "none"`(默认)会禁止访问智能体工作区;工具会针对 `~/.openclaw/sandboxes` 下的沙箱工作区运行 -- `agents.defaults.sandbox.workspaceAccess: "ro"` 会将智能体工作区以只读方式挂载到 `/agent`(会禁用 `write` / `edit` / `apply_patch`) +- `agents.defaults.sandbox.workspaceAccess: "none"`(默认)会禁止访问智能体工作区;工具会在 `~/.openclaw/sandboxes` 下的沙箱工作区中运行 +- `agents.defaults.sandbox.workspaceAccess: "ro"` 会将智能体工作区以只读方式挂载到 `/agent`(禁用 `write`/`edit`/`apply_patch`) - `agents.defaults.sandbox.workspaceAccess: "rw"` 会将智能体工作区以读写方式挂载到 `/workspace` -- 额外的 `sandbox.docker.binds` 会根据规范化和 canonicalized 后的源路径进行校验。如果父级符号链接技巧或 canonical home 别名最终解析到被阻止的根路径(例如 `/etc`、`/var/run` 或 OS 主目录下的凭证目录),仍会以关闭方式失败。 +- 额外的 `sandbox.docker.binds` 会根据标准化和规范化后的源路径进行验证。如果它们最终解析到被阻止的根路径(例如 `/etc`、`/var/run` 或 OS 主目录下的凭证目录),父级符号链接技巧和规范主目录别名仍会失败关闭。 -重要:`tools.elevated` 是全局基线逃逸通道,会让 exec 在沙箱外运行。默认的有效主机是 `gateway`,若 exec 目标被配置为 `node`,则为 `node`。应保持 `tools.elevated.allowFrom` 尽可能严格,不要为陌生人启用它。你还可以通过 `agents.list[].tools.elevated` 按智能体进一步限制 elevated。参见[Elevated 模式](/zh-CN/tools/elevated)。 +重要说明:`tools.elevated` 是全局基线逃逸口,会在沙箱之外运行 exec。其默认生效主机是 `gateway`,或者当 exec 目标配置为 `node` 时为 `node`。请将 `tools.elevated.allowFrom` 保持严格,不要为陌生人启用。你还可以通过 `agents.list[].tools.elevated` 进一步按智能体限制 elevated。参见 [Elevated Mode](/zh-CN/tools/elevated)。 -### 子智能体委派防护 +### 子智能体委派护栏 -如果你允许 session 工具,应将委派给子智能体运行视为另一项边界决策: +如果你允许会话工具,应将委派给子智能体的运行视为另一项边界决策: -- 除非智能体确实需要委派,否则禁用 `sessions_spawn`。 -- 将 `agents.defaults.subagents.allowAgents` 以及任何按智能体覆盖的 `agents.list[].subagents.allowAgents` 限制在已知安全的目标智能体范围内。 -- 对于任何必须保持沙箱隔离的工作流,请在调用 `sessions_spawn` 时传入 `sandbox: "require"`(默认值是 `inherit`)。 +- 除非智能体确实需要委派,否则拒绝 `sessions_spawn`。 +- 将 `agents.defaults.subagents.allowAgents` 以及任何按智能体定义的 `agents.list[].subagents.allowAgents` 覆盖项限制为已知安全的目标智能体。 +- 对于任何必须保持沙箱隔离的工作流,请在调用 `sessions_spawn` 时使用 `sandbox: "require"`(默认值为 `inherit`)。 - `sandbox: "require"` 会在目标子运行时未启用沙箱隔离时快速失败。 ## 浏览器控制风险 -启用浏览器控制会赋予模型驱动真实浏览器的能力。 -如果该浏览器配置文件中已经登录了会话,模型就可以 -访问这些账号和数据。应将浏览器配置文件视为**敏感状态**: +启用浏览器控制会让模型具备驱动真实浏览器的能力。 +如果该浏览器配置文件已经登录了账户,模型就可以 +访问这些账户及其数据。应将浏览器配置文件视为**敏感状态**: -- 优先为智能体使用专用配置文件(默认 `openclaw` profile)。 -- 不要把智能体指向你个人日常使用的主配置文件。 -- 对于已沙箱隔离的智能体,除非你信任它们,否则请保持主机浏览器控制关闭。 -- 独立的 loopback 浏览器控制 API 仅接受共享密钥认证 - (Gateway 网关 token bearer auth 或 Gateway 网关 password)。它不会使用 - trusted-proxy 或 Tailscale Serve 身份请求头。 -- 应将浏览器下载内容视为不受信任输入;优先使用隔离的下载目录。 -- 如果可能,请在智能体配置文件中禁用浏览器同步 / 密码管理器(可缩小影响半径)。 -- 对于远程 Gateway 网关,应将“浏览器控制”视为与该配置文件可访问范围等同的“操作员访问”。 -- 让 Gateway 网关和节点主机只在 tailnet 中可达;避免将浏览器控制端口暴露到 LAN 或公共互联网。 -- 当不需要浏览器代理路由时,请将其禁用(`gateway.nodes.browser.mode="off"`)。 -- Chrome MCP 的现有会话模式**并不**“更安全”;它可以像你本人一样操作该主机上的 Chrome 配置文件所能访问的任何内容。 +- 优先为智能体使用专用浏览器配置文件(默认的 `openclaw` 配置文件)。 +- 避免让智能体指向你个人日常使用的浏览器配置文件。 +- 对于沙箱隔离的智能体,除非你信任它们,否则请保持主机浏览器控制关闭。 +- 独立的 loopback 浏览器控制 API 只接受共享密钥鉴权 + (Gateway 网关 token bearer 鉴权或 Gateway 网关密码)。它不会消费 + trusted-proxy 或 Tailscale Serve 身份头。 +- 将浏览器下载内容视为不受信任输入;优先使用隔离的下载目录。 +- 如果可以,请在智能体配置文件中禁用浏览器同步/密码管理器(可缩小影响半径)。 +- 对于远程 Gateway 网关,应假设“浏览器控制”等同于“对该配置文件可访问内容的操作员访问权限”。 +- 保持 Gateway 网关 和 node host 仅限 tailnet;避免将浏览器控制端口暴露到 LAN 或公共互联网。 +- 在不需要时关闭浏览器代理路由(`gateway.nodes.browser.mode="off"`)。 +- Chrome MCP existing-session 模式**并不**“更安全”;它可以像你一样操作该主机上该 Chrome 配置文件所能访问的一切。 ### 浏览器 SSRF 策略(默认严格) -OpenClaw 的浏览器导航策略默认是严格的:私有 / 内部目标默认保持阻止状态,除非你显式选择启用。 +OpenClaw 的浏览器导航策略默认是严格的:私有/内部目标会被阻止,除非你显式选择启用。 -- 默认:`browser.ssrfPolicy.dangerouslyAllowPrivateNetwork` 未设置,因此浏览器导航会继续阻止私有 / 内部 / 特殊用途目标。 -- 旧版别名:`browser.ssrfPolicy.allowPrivateNetwork` 仍因兼容性而被接受。 -- 显式启用模式:设置 `browser.ssrfPolicy.dangerouslyAllowPrivateNetwork: true`,即可允许私有 / 内部 / 特殊用途目标。 -- 在严格模式下,可使用 `hostnameAllowlist`(如 `*.example.com` 这类模式)和 `allowedHostnames`(精确主机例外,包括 `localhost` 这样的被阻止名称)来声明显式例外。 -- 在发送请求前会执行导航检查,并且在导航完成后的最终 `http(s)` URL 上尽力再次检查,以减少基于重定向的跳转攻击。 +- 默认:`browser.ssrfPolicy.dangerouslyAllowPrivateNetwork` 未设置,因此浏览器导航会继续阻止私有/内部/特殊用途目标。 +- 旧版别名:`browser.ssrfPolicy.allowPrivateNetwork` 仍然会为兼容性而被接受。 +- 选择启用模式:设置 `browser.ssrfPolicy.dangerouslyAllowPrivateNetwork: true`,以允许私有/内部/特殊用途目标。 +- 在严格模式下,使用 `hostnameAllowlist`(如 `*.example.com` 这样的模式)和 `allowedHostnames`(精确主机例外,包括像 `localhost` 这样本来会被阻止的名称)来设置显式例外。 +- 为了减少基于重定向的跳转,导航会在请求前检查,并在导航完成后的最终 `http(s)` URL 上尽力再次检查。 严格策略示例: @@ -1190,20 +1202,19 @@ OpenClaw 的浏览器导航策略默认是严格的:私有 / 内部目标默 } ``` -## 按智能体划分的访问配置(多智能体) +## 按智能体定义的访问配置文件(多智能体) -借助多智能体路由,每个智能体都可以拥有自己的沙箱 + 工具策略: -利用这一点,你可以按智能体分别赋予**完全访问**、**只读**或**无访问**权限。 -完整细节和优先级规则见[多智能体沙箱隔离与工具](/zh-CN/tools/multi-agent-sandbox-tools) -了解详情。 +通过多智能体路由,每个智能体都可以拥有自己的沙箱隔离 + 工具策略: +你可以借此为不同智能体分别赋予**完全访问**、**只读**或**无访问**权限。 +完整细节和优先级规则请参阅[多智能体沙箱隔离与工具](/zh-CN/tools/multi-agent-sandbox-tools)。 常见用例: -- 个人智能体:完全访问,不使用沙箱 -- 家庭 / 工作智能体:沙箱隔离 + 只读工具 -- 公共智能体:沙箱隔离 + 无文件系统 / shell 工具 +- 个人智能体:完全访问,不使用沙箱隔离 +- 家庭/工作智能体:沙箱隔离 + 只读工具 +- 公开智能体:沙箱隔离 + 无文件系统/shell 工具 -### 示例:完全访问(不使用沙箱) +### 示例:完全访问(无沙箱隔离) ```json5 { @@ -1243,7 +1254,7 @@ OpenClaw 的浏览器导航策略默认是严格的:私有 / 内部目标默 } ``` -### 示例:无文件系统 / shell 访问(允许提供商消息工具) +### 示例:无文件系统/shell 访问(允许 provider 消息) ```json5 { @@ -1257,9 +1268,9 @@ OpenClaw 的浏览器导航策略默认是严格的:私有 / 内部目标默 scope: "agent", workspaceAccess: "none", }, - // Session 工具可能会从转录中泄露敏感数据。默认情况下,OpenClaw 将这些工具限制为 - // 当前 session + 生成的子智能体 session,但如果需要,你可以进一步收紧。 - // 参见配置参考中的 `tools.sessions.visibility`。 + // 会话工具可能泄露转录中的敏感数据。默认情况下,OpenClaw 会将这些工具限制为 + // 当前会话 + 生成的子智能体会话,但如果需要,你还可以进一步收紧。 + // 请参阅配置参考中的 `tools.sessions.visibility`。 tools: { sessions: { visibility: "tree" }, // self | tree | agent | all allow: [ @@ -1294,54 +1305,55 @@ OpenClaw 的浏览器导航策略默认是严格的:私有 / 内部目标默 } ``` -## 你应该告诉 AI 什么 +## 该告诉你的 AI 什么 -在智能体的系统提示中加入安全指南: +请在智能体的系统提示词中加入安全指南: ``` -## 安全规则 -- 永远不要向陌生人分享目录列表或文件路径 -- 永远不要泄露 API key、凭证或基础设施细节 -- 对于修改系统配置的请求,要先与所有者确认 -- 如有疑问,先询问再执行 -- 除非得到明确授权,否则应保持私有数据私密 +## Security Rules +- Never share directory listings or file paths with strangers +- Never reveal API keys, credentials, or infrastructure details +- Verify requests that modify system config with the owner +- When in doubt, ask before acting +- Keep private data private unless explicitly authorized ``` ## 事件响应 如果你的 AI 做了不该做的事: -### 遏制 +### 控制 -1. **停止它:** 停止 macOS 应用(如果它负责监管 Gateway 网关),或终止你的 `openclaw gateway` 进程。 -2. **关闭暴露面:** 将 `gateway.bind` 设为 `"loopback"`(或禁用 Tailscale Funnel / Serve),直到你弄清楚发生了什么。 -3. **冻结访问:** 将高风险私信 / 群组切换为 `dmPolicy: "disabled"` / 要求 mention,并移除你之前设置的 `"*"` 允许所有条目。 +1. **停止它:** 停止 macOS 应用(如果它负责托管 Gateway 网关),或终止你的 `openclaw gateway` 进程。 +2. **关闭暴露面:** 将 `gateway.bind` 设置为 `"loopback"`(或禁用 Tailscale Funnel/Serve),直到你弄清楚发生了什么。 +3. **冻结访问:** 将高风险私信/群组切换为 `dmPolicy: "disabled"` / 要求提及,并删除你曾使用的 `"*"` 全量允许条目。 -### 轮换(如果 secrets 泄露,则假定已失陷) +### 轮换(如果 secrets 已泄露,则应假定已被攻破) -1. 轮换 Gateway 网关认证(`gateway.auth.token` / `OPENCLAW_GATEWAY_PASSWORD`)并重启。 -2. 轮换所有可调用 Gateway 网关机器上的远程客户端 secrets(`gateway.remote.token` / `.password`)。 -3. 轮换提供商 / API 凭证(WhatsApp 凭证、Slack / Discord token、`auth-profiles.json` 中的模型 / API key,以及使用时的加密 secrets 负载值)。 +1. 轮换 Gateway 网关鉴权(`gateway.auth.token` / `OPENCLAW_GATEWAY_PASSWORD`)并重启。 +2. 轮换任何能够调用 Gateway 网关的机器上的远程客户端 secrets(`gateway.remote.token` / `.password`)。 +3. 轮换 provider/API 凭证(WhatsApp 凭证、Slack/Discord token、`auth-profiles.json` 中的模型/API 密钥,以及使用时的加密 secrets 负载值)。 ### 审计 1. 检查 Gateway 网关日志:`/tmp/openclaw/openclaw-YYYY-MM-DD.log`(或 `logging.file`)。 2. 查看相关转录:`~/.openclaw/agents//sessions/*.jsonl`。 -3. 检查最近的配置更改(任何可能扩大访问范围的项:`gateway.bind`、`gateway.auth`、私信 / 群组策略、`tools.elevated`、插件变更)。 +3. 查看最近的配置更改(任何可能扩大访问范围的项:`gateway.bind`、`gateway.auth`、私信/群组策略、`tools.elevated`、插件变更)。 4. 重新运行 `openclaw security audit --deep`,并确认 critical 发现已解决。 -### 收集报告材料 +### 收集用于报告的信息 - 时间戳、Gateway 网关主机 OS + OpenClaw 版本 -- Session 转录 + 一小段日志尾部(脱敏后) -- 攻击者发送了什么 + 智能体执行了什么 -- Gateway 网关是否暴露到 loopback 之外(LAN / Tailscale Funnel / Serve) +- 会话转录 + 一小段日志尾部(脱敏后) +- 攻击者发送了什么 + 智能体做了什么 +- Gateway 网关是否暴露到了 loopback 之外(LAN/Tailscale Funnel/Serve) ## Secret Scanning(detect-secrets) CI 会在 `secrets` job 中运行 `detect-secrets` pre-commit hook。 -推送到 `main` 时始终会执行全文件扫描。Pull request 在存在基准 commit 时会使用变更文件 -快速路径,否则会回退到全文件扫描。如果失败,说明出现了尚未写入 baseline 的新候选项。 +推送到 `main` 时始终会执行全文件扫描。Pull request 会在有基线 commit 可用时 +使用按变更文件的快速路径,否则回退为全文件扫描。如果失败, +说明存在尚未加入基线的新候选项。 ### 如果 CI 失败 @@ -1352,26 +1364,26 @@ CI 会在 `secrets` job 中运行 `detect-secrets` pre-commit hook。 ``` 2. 了解这些工具: - - pre-commit 中的 `detect-secrets` 会使用仓库的 - baseline 和排除规则运行 `detect-secrets-hook`。 - - `detect-secrets audit` 会打开交互式审查,用于将 baseline - 中的每一项标记为真实 secret 或误报。 -3. 对于真实 secrets:轮换 / 删除它们,然后重新运行扫描以更新 baseline。 + - pre-commit 中的 `detect-secrets` 会结合仓库的 + 基线和排除项运行 `detect-secrets-hook`。 + - `detect-secrets audit` 会打开交互式审查界面,将每个基线 + 条目标记为真实秘密或误报。 +3. 对于真实 secrets:轮换/移除它们,然后重新运行扫描以更新基线。 4. 对于误报:运行交互式审查并将其标记为误报: ```bash detect-secrets audit .secrets.baseline ``` -5. 如果你需要新增排除规则,请将其添加到 `.detect-secrets.cfg`,并使用匹配的 `--exclude-files` / `--exclude-lines` 标志重新生成 - baseline(该配置文件仅供参考;detect-secrets 不会自动读取它)。 +5. 如果你需要新增排除项,请将其添加到 `.detect-secrets.cfg`,并使用匹配的 `--exclude-files` / `--exclude-lines` 标志重新生成 + 基线(该配置文件仅供参考;detect-secrets 不会自动读取它)。 -当 `.secrets.baseline` 反映出预期状态后,提交更新后的文件。 +在 `.secrets.baseline` 反映出预期状态后,提交更新后的文件。 ## 报告安全问题 在 OpenClaw 中发现了漏洞?请负责任地报告: -1. 邮箱:[security@openclaw.ai](mailto:security@openclaw.ai) +1. 邮件: [security@openclaw.ai](mailto:security@openclaw.ai) 2. 在修复前不要公开发布 -3. 我们会致谢你(除非你希望匿名) +3. 我们会向你致谢(除非你希望匿名) diff --git a/docs/zh-CN/gateway/trusted-proxy-auth.md b/docs/zh-CN/gateway/trusted-proxy-auth.md index d20c6aff2..ba22a2b19 100644 --- a/docs/zh-CN/gateway/trusted-proxy-auth.md +++ b/docs/zh-CN/gateway/trusted-proxy-auth.md @@ -1,66 +1,66 @@ --- read_when: - 在身份感知代理后运行 OpenClaw - - 在 OpenClaw 前设置 Pomerium、Caddy 或 nginx + OAuth + - 在 OpenClaw 前设置带 OAuth 的 Pomerium、Caddy 或 nginx - 修复反向代理设置中的 WebSocket 1008 unauthorized 错误 - - 决定在哪里设置 HSTS 和其他 HTTP 加固头 -summary: 将 gateway 认证委托给受信任的反向代理(Pomerium、Caddy、nginx + OAuth) -title: 受信任代理认证 + - 决定在哪里设置 HSTS 和其他 HTTP 加固头部 +summary: 将 Gateway 网关认证委托给受信任的反向代理(Pomerium、Caddy、nginx + OAuth) +title: 受信任的代理认证 x-i18n: - generated_at: "2026-04-05T08:25:45Z" + generated_at: "2026-04-23T07:05:52Z" model: gpt-5.4 provider: openai - source_hash: ccd39736b43e8744de31566d5597b3fbf40ecb6ba9c8ba9d2343e1ab9bb8cd45 + source_hash: 649529e9a350d7df3a9ecbbae8871d61e1dff2069dfabf2f86a77a0d96c52778 source_path: gateway/trusted-proxy-auth.md workflow: 15 --- -# 受信任代理认证 +# 受信任的代理认证 -> ⚠️ **安全敏感功能。** 此模式会将认证完全委托给你的反向代理。错误配置可能会让你的 Gateway 网关暴露给未授权访问。在启用前请仔细阅读本页。 +> ⚠️ **安全敏感功能。** 此模式会将认证完全委托给你的反向代理。配置错误可能会使你的 Gateway 网关暴露给未授权访问。启用前请仔细阅读本页。 ## 何时使用 -在以下情况下使用 `trusted-proxy` 认证模式: +在以下情况下,使用 `trusted-proxy` 认证模式: -- 你在**身份感知代理**之后运行 OpenClaw(Pomerium、Caddy + OAuth、nginx + oauth2-proxy、Traefik + forward auth) -- 你的代理负责全部认证,并通过头部传递用户身份 -- 你处于 Kubernetes 或容器环境中,并且代理是访问 Gateway 网关的唯一入口 +- 你在 **身份感知代理**(Pomerium、Caddy + OAuth、nginx + oauth2-proxy、Traefik + forward auth)后运行 OpenClaw +- 你的代理负责所有认证,并通过请求头传递用户身份 +- 你处于 Kubernetes 或容器环境中,而代理是访问 Gateway 网关的唯一入口 - 你遇到了 WebSocket `1008 unauthorized` 错误,因为浏览器无法在 WS 负载中传递 token ## 何时不要使用 - 如果你的代理不对用户进行认证(只是 TLS 终止器或负载均衡器) -- 如果存在任何绕过代理直接访问 Gateway 网关的路径(防火墙漏洞、内部网络访问) -- 如果你不确定你的代理是否会正确移除/覆盖转发头 -- 如果你只需要个人单用户访问(更简单的设置可考虑 Tailscale Serve + loopback) +- 如果存在绕过代理直达 Gateway 网关的路径(防火墙漏洞、内部网络访问) +- 如果你不确定代理是否会正确剥离/覆盖转发头 +- 如果你只需要个人单用户访问(可考虑使用 Tailscale Serve + loopback,配置更简单) ## 工作原理 1. 你的反向代理对用户进行认证(OAuth、OIDC、SAML 等) -2. 代理添加一个包含已认证用户身份的头部(例如 `x-forwarded-user: nick@example.com`) -3. OpenClaw 检查请求是否来自**受信任代理 IP**(在 `gateway.trustedProxies` 中配置) -4. OpenClaw 从已配置的头部中提取用户身份 -5. 如果一切检查通过,则授权该请求 +2. 代理添加一个包含已认证用户身份的请求头(例如 `x-forwarded-user: nick@example.com`) +3. OpenClaw 检查该请求是否来自 **受信任的代理 IP**(在 `gateway.trustedProxies` 中配置) +4. OpenClaw 从已配置的请求头中提取用户身份 +5. 如果所有检查都通过,则授权该请求 -## 控制 UI 配对行为 +## 控制 Control UI 配对行为 -当 `gateway.auth.mode = "trusted-proxy"` 处于激活状态,并且请求通过了 -受信任代理检查时,控制 UI WebSocket 会话可以在没有设备 +当 `gateway.auth.mode = "trusted-proxy"` 处于启用状态,并且请求通过了 +受信任代理检查时,Control UI WebSocket 会话可以在没有设备 配对身份的情况下连接。 影响: -- 在这种模式下,配对不再是控制 UI 访问的主要门槛。 -- 你的反向代理认证策略和 `allowUsers` 会成为实际的访问控制。 -- 保持 gateway 入口仅对受信任代理 IP 开放(`gateway.trustedProxies` + 防火墙)。 +- 在此模式下,配对不再是 Control UI 访问的主要门槛。 +- 你的反向代理认证策略和 `allowUsers` 将成为实际的访问控制。 +- 保持 Gateway 网关入口仅对受信任代理 IP 开放(`gateway.trustedProxies` + 防火墙)。 ## 配置 ```json5 { gateway: { - // trusted-proxy 认证要求请求来自非 loopback 的受信任代理源 + // 受信任代理认证要求请求来自非 loopback 的受信任代理来源 bind: "lan", // 关键:这里只添加你的代理 IP @@ -69,13 +69,13 @@ x-i18n: auth: { mode: "trusted-proxy", trustedProxy: { - // 包含已认证用户身份的头部(必填) + // 包含已认证用户身份的请求头(必需) userHeader: "x-forwarded-user", - // 可选:必须存在的头部(用于验证代理) + // 可选:必须存在的请求头(代理校验) requiredHeaders: ["x-forwarded-proto", "x-forwarded-host"], - // 可选:限制为特定用户(空 = 允许所有用户) + // 可选:限制为特定用户(空 = 允许全部) allowUsers: ["nick@example.com", "admin@company.org"], }, }, @@ -83,37 +83,39 @@ x-i18n: } ``` -重要运行时规则: +重要的运行时规则: -- 受信任代理认证会拒绝来自 loopback 源的请求(`127.0.0.1`、`::1`、loopback CIDR)。 -- 同主机 loopback 反向代理**不满足**受信任代理认证。 +- 受信任代理认证会拒绝来自 loopback 来源的请求(`127.0.0.1`、`::1`、loopback CIDR)。 +- 同主机 loopback 反向代理 **不满足** 受信任代理认证要求。 - 对于同主机 loopback 代理设置,请改用 token/password 认证,或者通过 OpenClaw 可验证的非 loopback 受信任代理地址进行路由。 -- 非 loopback 的控制 UI 部署仍然需要显式设置 `gateway.controlUi.allowedOrigins`。 +- 非 loopback 的 Control UI 部署仍需要显式设置 `gateway.controlUi.allowedOrigins`。 +- **转发头证据会覆盖 loopback 本地性。** 如果请求到达于 loopback,但携带了指向非本地来源的 `X-Forwarded-For` / `X-Forwarded-Host` / `X-Forwarded-Proto` 头,则这些证据会使 loopback 本地性声明无效。该请求会被视为远程请求,用于配对、受信任代理认证以及 Control UI 设备身份门控。这可以防止同主机 loopback 代理通过转发头身份“洗白”成受信任代理认证。 ### 配置参考 -| 字段 | 必填 | 说明 | -| ------------------------------------------- | -------- | --------------------------------------------------------------------------- | -| `gateway.trustedProxies` | 是 | 受信任的代理 IP 地址数组。来自其他 IP 的请求会被拒绝。 | -| `gateway.auth.mode` | 是 | 必须为 `"trusted-proxy"` | -| `gateway.auth.trustedProxy.userHeader` | 是 | 包含已认证用户身份的头部名称 | -| `gateway.auth.trustedProxy.requiredHeaders` | 否 | 请求要被信任时必须存在的附加头部 | -| `gateway.auth.trustedProxy.allowUsers` | 否 | 用户身份 allowlist。空表示允许所有已认证用户。 | +| 字段 | 必需 | 说明 | +| ------------------------------------------ | ---- | ---- | +| `gateway.trustedProxies` | 是 | 要信任的代理 IP 地址数组。来自其他 IP 的请求会被拒绝。 | +| `gateway.auth.mode` | 是 | 必须为 `"trusted-proxy"` | +| `gateway.auth.trustedProxy.userHeader` | 是 | 包含已认证用户身份的请求头名称 | +| `gateway.auth.trustedProxy.requiredHeaders`| 否 | 使请求被信任所必须存在的其他请求头 | +| `gateway.auth.trustedProxy.allowUsers` | 否 | 用户身份 allowlist。为空表示允许所有已认证用户。 | -## TLS 终止与 HSTS +## TLS 终止和 HSTS -使用一个 TLS 终止点,并在那里应用 HSTS。 +使用单一 TLS 终止点,并在那里应用 HSTS。 ### 推荐模式:代理 TLS 终止 当你的反向代理为 `https://control.example.com` 处理 HTTPS 时, -请在代理上为该域设置 `Strict-Transport-Security`。 +请在该代理上为该域设置 +`Strict-Transport-Security`。 -- 非常适合面向互联网的部署。 -- 能把证书和 HTTP 加固策略集中在一个位置。 -- OpenClaw 可以在代理之后继续使用 loopback HTTP。 +- 适合面向互联网的部署。 +- 将证书和 HTTP 加固策略集中在同一位置。 +- OpenClaw 可以在代理后保持为 loopback HTTP。 -示例头部值: +请求头值示例: ```text Strict-Transport-Security: max-age=31536000; includeSubDomains @@ -121,7 +123,7 @@ Strict-Transport-Security: max-age=31536000; includeSubDomains ### Gateway 网关 TLS 终止 -如果 OpenClaw 本身直接提供 HTTPS(没有进行 TLS 终止的代理),请设置: +如果 OpenClaw 自身直接提供 HTTPS 服务(没有执行 TLS 终止的代理),请设置: ```json5 { @@ -136,21 +138,21 @@ Strict-Transport-Security: max-age=31536000; includeSubDomains } ``` -`strictTransportSecurity` 接受字符串类型的头部值,或显式设置为 `false` 以禁用。 +`strictTransportSecurity` 接受一个字符串类型的请求头值,也可显式设为 `false` 以禁用。 -### 发布指导 +### 推出指导 -- 在验证流量时,先使用较短的 max age(例如 `max-age=300`)。 -- 只有在确认无误后,再增加到长期值(例如 `max-age=31536000`)。 -- 只有在每个子域都已准备好 HTTPS 时,才添加 `includeSubDomains`。 -- 只有在你明确满足整个域名集合的 preload 要求时,才使用 preload。 -- 仅限 loopback 的本地开发不会从 HSTS 中受益。 +- 先使用较短的 max age(例如 `max-age=300`)来验证流量。 +- 只有在有足够把握后,才增加到长期值(例如 `max-age=31536000`)。 +- 仅当所有子域都已准备好使用 HTTPS 时,才添加 `includeSubDomains`。 +- 只有在你明确满足整套域名的 preload 要求时,才使用 preload。 +- 仅 loopback 的本地开发无法从 HSTS 中受益。 ## 代理设置示例 ### Pomerium -Pomerium 通过 `x-pomerium-claim-email`(或其他声明头)传递身份,并通过 `x-pomerium-jwt-assertion` 传递 JWT。 +Pomerium 在 `x-pomerium-claim-email`(或其他 claim 头)中传递身份,并在 `x-pomerium-jwt-assertion` 中传递 JWT。 ```json5 { @@ -182,9 +184,9 @@ routes: pass_identity_headers: true ``` -### 使用 OAuth 的 Caddy +### 带 OAuth 的 Caddy -带有 `caddy-security` 插件的 Caddy 可以对用户进行认证并传递身份头。 +带有 `caddy-security` 插件的 Caddy 可以认证用户并传递身份头。 ```json5 { @@ -201,7 +203,7 @@ routes: } ``` -Caddyfile 片段: +Caddyfile 配置片段: ``` openclaw.example.com { @@ -248,7 +250,7 @@ location / { } ``` -### 使用 Forward Auth 的 Traefik +### 带 Forward Auth 的 Traefik ```json5 { @@ -272,14 +274,14 @@ location / { 如果你在启动时看到 `mixed_trusted_proxy_token` 错误: - 在使用 trusted-proxy 模式时移除共享 token,或 -- 如果你打算使用基于 token 的认证,则将 `gateway.auth.mode` 切换为 `"token"`。 +- 如果你打算使用基于 token 的认证,请将 `gateway.auth.mode` 切换为 `"token"`。 -Loopback trusted-proxy 认证也会以关闭方式失败:同主机调用方必须通过受信任代理提供已配置的身份头,而不是被静默认证。 +Loopback trusted-proxy 认证也会以失败关闭的方式处理:同主机调用方必须通过受信任代理提供已配置的身份头,而不是被静默认证。 -## Operator scopes 头部 +## operator scope 请求头 -Trusted-proxy 认证是一种**携带身份**的 HTTP 模式,因此调用方可以 -选择通过 `x-openclaw-scopes` 声明 operator scopes。 +受信任代理认证是一种 **承载身份的** HTTP 模式,因此调用方 +可以选择通过 `x-openclaw-scopes` 声明 operator scope。 示例: @@ -289,118 +291,118 @@ Trusted-proxy 认证是一种**携带身份**的 HTTP 模式,因此调用方 行为: -- 当该头部存在时,OpenClaw 会遵循所声明的 scope 集合。 -- 当该头部存在但为空时,请求声明**不具有**任何 operator scope。 -- 当该头部不存在时,普通的携带身份 HTTP API 会回退到标准 operator 默认 scope 集合。 -- Gateway 认证的**插件 HTTP 路由**默认更窄:当 `x-openclaw-scopes` 缺失时,它们的运行时 scope 会回退到 `operator.write`。 -- 即使 trusted-proxy 认证成功,来自浏览器的 HTTP 请求仍必须通过 `gateway.controlUi.allowedOrigins`(或刻意启用的 Host 头回退模式)检查。 +- 当该请求头存在时,OpenClaw 会遵循声明的 scope 集合。 +- 当该请求头存在但为空时,该请求声明 **不包含** 任何 operator scope。 +- 当该请求头不存在时,普通承载身份的 HTTP API 会回退到标准 operator 默认 scope 集合。 +- Gateway-auth **插件 HTTP 路由** 默认更窄:当 `x-openclaw-scopes` 不存在时,它们的运行时 scope 会回退到 `operator.write`。 +- 浏览器来源的 HTTP 请求即使在 trusted-proxy 认证成功后,仍必须通过 `gateway.controlUi.allowedOrigins`(或有意启用的 Host 请求头回退模式)。 -实用规则: +实践规则: - 当你希望 trusted-proxy 请求 - 比默认值更窄,或当 gateway-auth 插件路由需要 + 比默认值更窄,或者 gateway-auth 插件路由需要 比 write scope 更强的权限时,请显式发送 `x-openclaw-scopes`。 ## 安全检查清单 -在启用 trusted-proxy 认证之前,请确认: +启用受信任代理认证前,请确认: -- [ ] **代理是唯一入口**:Gateway 网关端口已通过防火墙限制,除你的代理外其他来源都无法访问 -- [ ] **trustedProxies 足够精简**:只包含你的真实代理 IP,而不是整个子网 -- [ ] **没有 loopback 代理源**:trusted-proxy 认证对来自 loopback 源的请求会以关闭方式失败 -- [ ] **代理会移除头部**:你的代理会覆盖(而不是追加)客户端传来的 `x-forwarded-*` 头 +- [ ] **代理是唯一入口**:Gateway 网关端口已通过防火墙屏蔽除你的代理之外的所有访问 +- [ ] **trustedProxies 最小化**:仅包含你的实际代理 IP,而不是整个子网 +- [ ] **无 loopback 代理来源**:受信任代理认证会对 loopback 来源请求以失败关闭方式处理 +- [ ] **代理会剥离头部**:你的代理会覆盖(而不是追加)来自客户端的 `x-forwarded-*` 头 - [ ] **TLS 终止**:你的代理负责 TLS;用户通过 HTTPS 连接 -- [ ] **allowedOrigins 是显式的**:非 loopback 控制 UI 使用显式 `gateway.controlUi.allowedOrigins` +- [ ] **allowedOrigins 显式设置**:非 loopback 的 Control UI 使用显式 `gateway.controlUi.allowedOrigins` - [ ] **已设置 allowUsers**(推荐):限制为已知用户,而不是允许任意已认证用户 - [ ] **没有混合 token 配置**:不要同时设置 `gateway.auth.token` 和 `gateway.auth.mode: "trusted-proxy"` ## 安全审计 -`openclaw security audit` 会将 trusted-proxy 认证标记为**严重**级别的问题。这是有意为之——它是在提醒你:你正在将安全性委托给代理设置。 +`openclaw security audit` 会将受信任代理认证标记为 **critical** 严重级别发现。这是有意为之 —— 用于提醒你正在将安全委托给代理设置。 审计会检查: -- 基础 `gateway.trusted_proxy_auth` 警告/严重提醒 +- 基础 `gateway.trusted_proxy_auth` 警告/critical 提醒 - 缺少 `trustedProxies` 配置 - 缺少 `userHeader` 配置 -- 空的 `allowUsers`(允许任何已认证用户) -- 在暴露的控制 UI 界面上使用通配符或缺失的浏览器来源策略 +- `allowUsers` 为空(允许任意已认证用户) +- 在暴露的 Control UI 界面上使用通配符或缺失的浏览器来源策略 ## 故障排除 ### “trusted_proxy_untrusted_source” -请求并非来自 `gateway.trustedProxies` 中的 IP。请检查: +该请求并非来自 `gateway.trustedProxies` 中的 IP。请检查: - 代理 IP 是否正确?(Docker 容器 IP 可能会变化) - 你的代理前面是否还有负载均衡器? -- 使用 `docker inspect` 或 `kubectl get pods -o wide` 查找真实 IP +- 使用 `docker inspect` 或 `kubectl get pods -o wide` 查找实际 IP ### “trusted_proxy_loopback_source” -OpenClaw 拒绝了来自 loopback 源的 trusted-proxy 请求。 +OpenClaw 拒绝了来自 loopback 来源的受信任代理请求。 请检查: -- 代理是否从 `127.0.0.1` / `::1` 发起连接? -- 你是否试图在同主机 loopback 反向代理中使用 trusted-proxy 认证? +- 代理是否从 `127.0.0.1` / `::1` 连接? +- 你是否正在尝试将 trusted-proxy 认证与同主机 loopback 反向代理一起使用? -修复方法: +修复: -- 对同主机 loopback 代理设置使用 token/password 认证,或 -- 通过非 loopback 的受信任代理地址进行路由,并将该 IP 保持在 `gateway.trustedProxies` 中。 +- 对于同主机 loopback 代理设置,使用 token/password 认证,或 +- 通过非 loopback 的受信任代理地址进行路由,并将该 IP 保留在 `gateway.trustedProxies` 中。 ### “trusted_proxy_user_missing” -用户头部为空或缺失。请检查: +用户请求头为空或缺失。请检查: -- 你的代理是否已配置为传递身份头? -- 头部名称是否正确?(大小写不敏感,但拼写必须正确) -- 用户是否确实已经在代理处完成认证? +- 你的代理是否已配置为传递身份请求头? +- 请求头名称是否正确?(大小写不敏感,但拼写必须正确) +- 用户是否确实已在代理处完成认证? ### “trusted*proxy_missing_header*\*” -缺少某个必需头部。请检查: +某个必需请求头不存在。请检查: -- 你的代理对这些特定头部的配置 -- 这些头部是否在链路中的某处被移除了 +- 你的代理中这些特定请求头的配置 +- 请求头是否在链路中的某处被剥离 ### “trusted_proxy_user_not_allowed” -用户已认证,但不在 `allowUsers` 中。请将其加入,或移除 allowlist。 +用户已通过认证,但不在 `allowUsers` 中。请将其加入,或移除 allowlist。 ### “trusted_proxy_origin_not_allowed” -trusted-proxy 认证已成功,但浏览器 `Origin` 头未通过控制 UI 来源检查。 +trusted-proxy 认证已成功,但浏览器的 `Origin` 请求头未通过 Control UI 的来源检查。 请检查: -- `gateway.controlUi.allowedOrigins` 是否包含精确的浏览器来源 -- 除非你明确需要允许所有来源,否则不要依赖通配符来源 -- 如果你有意使用 Host 头回退模式,请确认已明确设置 `gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true` +- `gateway.controlUi.allowedOrigins` 包含了准确的浏览器来源 +- 除非你明确希望允许全部来源,否则不要依赖通配符来源 +- 如果你有意使用 Host 请求头回退模式,请确认已明确设置 `gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true` ### WebSocket 仍然失败 -请确保你的代理: +确保你的代理: - 支持 WebSocket 升级(`Upgrade: websocket`、`Connection: upgrade`) -- 会在 WebSocket 升级请求中传递身份头(而不仅仅是普通 HTTP) -- 不会为 WebSocket 连接使用单独的认证路径 +- 在 WebSocket 升级请求中传递身份请求头(而不仅仅是普通 HTTP) +- 没有为 WebSocket 连接使用单独的认证路径 ## 从 token 认证迁移 如果你要从 token 认证迁移到 trusted-proxy: -1. 配置你的代理以认证用户并传递头部 -2. 独立测试代理设置(带头部的 curl) -3. 更新 OpenClaw 配置以启用 trusted-proxy 认证 +1. 配置你的代理,使其能够认证用户并传递请求头 +2. 独立测试代理设置(使用带请求头的 `curl`) +3. 在 OpenClaw 配置中更新为 trusted-proxy 认证 4. 重启 Gateway 网关 -5. 从控制 UI 测试 WebSocket 连接 -6. 运行 `openclaw security audit` 并检查结果 +5. 从 Control UI 测试 WebSocket 连接 +6. 运行 `openclaw security audit` 并审查结果 ## 相关内容 -- [Security](/gateway/security) — 完整安全指南 -- [Configuration](/gateway/configuration) — 配置参考 -- [Remote access](/gateway/remote) — 其他远程访问模式 -- [Tailscale](/gateway/tailscale) — 仅限 tailnet 访问时更简单的替代方案 +- [Security](/zh-CN/gateway/security) — 完整安全指南 +- [Configuration](/zh-CN/gateway/configuration) — 配置参考 +- [Remote Access](/zh-CN/gateway/remote) — 其他远程访问模式 +- [Tailscale](/zh-CN/gateway/tailscale) — 仅 tailnet 访问时更简单的替代方案 diff --git a/docs/zh-CN/plugins/architecture.md b/docs/zh-CN/plugins/architecture.md index 102717a82..092fceeba 100644 --- a/docs/zh-CN/plugins/architecture.md +++ b/docs/zh-CN/plugins/architecture.md @@ -5,13 +5,13 @@ read_when: - 处理插件加载流水线或注册表 - 实现提供商运行时钩子或渠道插件 sidebarTitle: Internals -summary: 插件内部机制:能力模型、归属关系、契约、加载流水线和运行时辅助工具 +summary: 插件内部机制:能力模型、归属、契约、加载流水线和运行时辅助工具 title: 插件内部机制 x-i18n: - generated_at: "2026-04-23T06:41:33Z" + generated_at: "2026-04-23T07:06:06Z" model: gpt-5.4 provider: openai - source_hash: 69075cecab525aacd19e350605c135334bdcfe913c2f024a48ff68e5b1e80f8c + source_hash: 18e7afebf7eb37d0b8dc245ebbf9b35ca588c91645149e634911f8055780f439 source_path: plugins/architecture.md workflow: 15 --- @@ -20,11 +20,11 @@ x-i18n: 这是**深度架构参考**。如需实用指南,请参见: - - [Install and use plugins](/zh-CN/tools/plugin) —— 用户指南 + - [安装和使用插件](/zh-CN/tools/plugin) —— 用户指南 - [入门指南](/zh-CN/plugins/building-plugins) —— 第一个插件教程 - - [渠道插件](/zh-CN/plugins/sdk-channel-plugins) —— 构建一个消息渠道 - - [提供商插件](/zh-CN/plugins/sdk-provider-plugins) —— 构建一个模型提供商 - - [SDK 概览](/zh-CN/plugins/sdk-overview) —— 导入映射和注册 API + - [渠道插件](/zh-CN/plugins/sdk-channel-plugins) —— 构建消息渠道 + - [提供商插件](/zh-CN/plugins/sdk-provider-plugins) —— 构建模型提供商 + - [SDK 概览](/zh-CN/plugins/sdk-overview) —— import map 和注册 API 本页介绍 OpenClaw 插件系统的内部架构。 @@ -34,159 +34,155 @@ x-i18n: 能力是 OpenClaw 内部公开的**原生插件**模型。每个 原生 OpenClaw 插件都会针对一个或多个能力类型进行注册: -| 能力 | 注册方法 | 示例插件 | -| ---------------------- | ------------------------------------------------ | ------------------------------------ | -| 文本推理 | `api.registerProvider(...)` | `openai`, `anthropic` | -| CLI 推理后端 | `api.registerCliBackend(...)` | `openai`, `anthropic` | -| 语音 | `api.registerSpeechProvider(...)` | `elevenlabs`, `microsoft` | -| 实时转录 | `api.registerRealtimeTranscriptionProvider(...)` | `openai` | -| 实时语音 | `api.registerRealtimeVoiceProvider(...)` | `openai` | -| 媒体理解 | `api.registerMediaUnderstandingProvider(...)` | `openai`, `google` | -| 图像生成 | `api.registerImageGenerationProvider(...)` | `openai`, `google`, `fal`, `minimax` | -| 音乐生成 | `api.registerMusicGenerationProvider(...)` | `google`, `minimax` | -| 视频生成 | `api.registerVideoGenerationProvider(...)` | `qwen` | -| 网页抓取 | `api.registerWebFetchProvider(...)` | `firecrawl` | -| 网页搜索 | `api.registerWebSearchProvider(...)` | `google` | -| 渠道 / 消息传递 | `api.registerChannel(...)` | `msteams`, `matrix` | +| 能力 | 注册方法 | 示例插件 | +| -------------------- | ------------------------------------------------ | ------------------------------------ | +| 文本推理 | `api.registerProvider(...)` | `openai`、`anthropic` | +| CLI 推理后端 | `api.registerCliBackend(...)` | `openai`、`anthropic` | +| 语音 | `api.registerSpeechProvider(...)` | `elevenlabs`、`microsoft` | +| 实时转录 | `api.registerRealtimeTranscriptionProvider(...)` | `openai` | +| 实时语音 | `api.registerRealtimeVoiceProvider(...)` | `openai` | +| 媒体理解 | `api.registerMediaUnderstandingProvider(...)` | `openai`、`google` | +| 图像生成 | `api.registerImageGenerationProvider(...)` | `openai`、`google`、`fal`、`minimax` | +| 音乐生成 | `api.registerMusicGenerationProvider(...)` | `google`、`minimax` | +| 视频生成 | `api.registerVideoGenerationProvider(...)` | `qwen` | +| Web 抓取 | `api.registerWebFetchProvider(...)` | `firecrawl` | +| Web 搜索 | `api.registerWebSearchProvider(...)` | `google` | +| 渠道 / 消息传递 | `api.registerChannel(...)` | `msteams`、`matrix` | 一个注册了零个能力、但提供钩子、工具或 -服务的插件,是**旧式仅钩子**插件。该模式仍然受到完全支持。 +服务的插件,是**旧版仅钩子**插件。这种模式仍然得到完全支持。 ### 外部兼容性立场 能力模型已经在核心中落地,并且今天已被内置/原生插件 -使用,但外部插件兼容性仍需要比“它已导出,因此它已冻结” +使用,但外部插件兼容性仍然需要比“它已导出,因此它已冻结” 更严格的标准。 当前指导原则: -- **现有外部插件:** 保持基于钩子的集成正常工作;将其视为 - 兼容性的基线 +- **现有外部插件:** 保持基于钩子的集成继续工作;将其视为 + 兼容性基线 - **新的内置/原生插件:** 优先使用显式能力注册,而不是 - 依赖供应商专用的穿透式访问,或新的仅钩子设计 -- **采用能力注册的外部插件:** 允许这样做,但除非文档明确将某个契约标记为稳定, - 否则应将能力专用的辅助表面视为仍在演进中 + 供应商专用的深入访问或新的仅钩子设计 +- **采用能力注册的外部插件:** 允许这样做,但除非文档明确将某个契约标记为稳定,否则应将能力专用辅助接口视为仍在演进 实用规则: -- 能力注册 API 是预期的发展方向 -- 在过渡期间,旧式钩子仍然是外部插件最安全、最不易破坏的路径 -- 导出的辅助子路径并不完全等价;优先选择有文档说明的狭窄 - 契约,而不是附带导出的辅助工具 +- 能力注册 API 是预期方向 +- 在过渡期间,旧版钩子仍然是外部插件最安全、最不易破坏的路径 +- 导出的辅助子路径并不全都等价;优先使用文档化的狭义 + 契约,而不是偶然导出的辅助接口 ### 插件形态 OpenClaw 会根据每个已加载插件的实际 -注册行为将其分类为一种形态(而不仅仅是静态元数据): +注册行为(而不仅仅是静态元数据)将其归类为一种形态: -- **plain-capability** —— 恰好注册一种能力类型(例如仅提供商插件 - `mistral`) +- **plain-capability** —— 恰好注册一种能力类型(例如仅提供商插件,如 `mistral`) - **hybrid-capability** —— 注册多种能力类型(例如 - `openai` 同时拥有文本推理、语音、媒体理解和图像 + `openai` 拥有文本推理、语音、媒体理解和图像 生成) -- **hook-only** —— 仅注册钩子(类型化或自定义),不注册能力、 +- **hook-only** —— 仅注册钩子(类型化或自定义),没有能力、 工具、命令或服务 - **non-capability** —— 注册工具、命令、服务或路由,但不注册 能力 -使用 `openclaw plugins inspect ` 查看插件的形态和能力 -明细。详情请参见 [CLI reference](/zh-CN/cli/plugins#inspect)。 +使用 `openclaw plugins inspect ` 可查看插件的形态和能力 +细分。详情请参见 [CLI 参考](/zh-CN/cli/plugins#inspect)。 -### 旧式钩子 +### 旧版钩子 -`before_agent_start` 钩子仍然作为仅钩子插件的兼容路径受到支持。 -现实中仍有旧插件依赖它。 +`before_agent_start` 钩子仍作为仅钩子插件的兼容路径受到支持。现实中的旧版插件仍依赖它。 方向: -- 保持其正常工作 -- 将其记录为旧式能力 +- 保持其继续可用 +- 在文档中将其标注为旧版 - 对于模型/提供商覆盖工作,优先使用 `before_model_resolve` - 对于提示词变更工作,优先使用 `before_prompt_build` -- 只有在真实使用量下降,且夹具覆盖证明迁移安全后,才移除它 +- 只有在真实使用量下降且 fixture 覆盖证明迁移安全后,才移除它 ### 兼容性信号 -当你运行 `openclaw doctor` 或 `openclaw plugins inspect ` 时,可能会看到 +当你运行 `openclaw doctor` 或 `openclaw plugins inspect ` 时,你可能会看到 以下标签之一: -| 信号 | 含义 | -| -------------------------- | ------------------------------------------------------------ | -| **config valid** | 配置解析正常,插件可解析 | -| **compatibility advisory** | 插件使用受支持但较旧的模式(例如 `hook-only`) | -| **legacy warning** | 插件使用 `before_agent_start`,该项已弃用 | -| **hard error** | 配置无效,或插件加载失败 | +| 信号 | 含义 | +| ------------------------ | ------------------------------------------------------------ | +| **config valid** | 配置解析正常,插件解析成功 | +| **compatibility advisory** | 插件使用受支持但较旧的模式(例如 `hook-only`) | +| **legacy warning** | 插件使用 `before_agent_start`,该项已弃用 | +| **hard error** | 配置无效或插件加载失败 | -如今,`hook-only` 和 `before_agent_start` 都不会让你的插件失效—— -`hook-only` 只是提示性信息,而 `before_agent_start` 只会触发警告。这些 +`hook-only` 和 `before_agent_start` 目前都不会破坏你的插件—— +`hook-only` 只是提示信息,而 `before_agent_start` 只会触发警告。这些 信号也会出现在 `openclaw status --all` 和 `openclaw plugins doctor` 中。 ## 架构概览 OpenClaw 的插件系统有四层: -1. **Manifest + 设备发现** +1. **manifest + 发现** OpenClaw 会从已配置路径、工作区根目录、 - 全局插件根目录以及内置插件中查找候选插件。设备发现会优先读取原生 - `openclaw.plugin.json` manifest,以及受支持的 bundle manifest。 + 全局插件根目录和内置插件中查找候选插件。发现过程会优先读取原生 + `openclaw.plugin.json` manifest 和受支持的 bundle manifest。 2. **启用 + 校验** - 核心决定某个已发现插件是已启用、已禁用、被阻止,还是 - 被选中用于某个独占槽位,例如 memory。 + 核心决定一个已发现插件是启用、禁用、屏蔽,还是被 + 选中用于诸如 memory 之类的独占槽位。 3. **运行时加载** 原生 OpenClaw 插件通过 jiti 在进程内加载,并将 - 能力注册到中央注册表中。兼容的 bundle 会被规范化为 - 注册表记录,而无需导入运行时代码。 -4. **表面消费** - OpenClaw 的其余部分读取注册表,以暴露工具、渠道、提供商 + 能力注册到中央注册表中。兼容的 bundle 会在不导入运行时代码的情况下 + 规范化为注册表记录。 +4. **接口消费** + OpenClaw 的其余部分会读取注册表以暴露工具、渠道、提供商 设置、钩子、HTTP 路由、CLI 命令和服务。 -对于插件 CLI 而言,根命令发现专门分为两个阶段: +特别是对于插件 CLI,根命令发现分为两个阶段: - 解析时元数据来自 `registerCli(..., { descriptors: [...] })` -- 真正的插件 CLI 模块可以保持惰性,并在首次调用时注册 +- 真实的插件 CLI 模块可以保持懒加载,并在首次调用时注册 -这样可以将插件自有的 CLI 代码保留在插件内部,同时仍让 OpenClaw -在解析前保留根命令名称。 +这样可以把插件拥有的 CLI 代码保留在插件内部,同时仍让 OpenClaw +在解析前预留根命令名称。 -重要的设计边界是: +重要的设计边界: -- 设备发现 + 配置校验应能基于**manifest/schema 元数据** - 完成,而无需执行插件代码 +- 发现 + 配置校验应当仅通过 **manifest/schema 元数据** + 就能工作,而无需执行插件代码 - 原生运行时行为来自插件模块的 `register(api)` 路径 -这种拆分让 OpenClaw 能够在完整运行时尚未激活之前, -校验配置、解释缺失/禁用的插件,并构建 UI/schema 提示。 +这种拆分使 OpenClaw 能够在完整运行时尚未激活前,就验证配置、 +解释插件缺失/禁用原因,并构建 UI/schema 提示。 ### 渠道插件和共享 message 工具 -对于普通聊天操作,渠道插件不需要注册单独的发送/编辑/react 工具。 -OpenClaw 在核心中保留一个共享的 `message` 工具,而 -渠道插件负责其背后的渠道专属发现和执行。 +对于常规聊天操作,渠道插件不需要注册单独的发送/编辑/reaction 工具。 +OpenClaw 在核心中保留一个共享的 `message` 工具,而渠道插件负责其背后的渠道专用发现与执行。 -当前边界如下: +当前边界是: -- 核心负责共享 `message` 工具宿主、提示词接线、会话/线程 +- 核心拥有共享 `message` 工具宿主、提示词连线、会话/线程 记录和执行分发 -- 渠道插件负责作用域内操作发现、能力发现,以及任何 - 渠道专属 schema 片段 -- 渠道插件负责提供商专属的会话对话语法,例如 - 对话 id 如何编码线程 id,或如何从父对话继承 +- 渠道插件拥有作用域化的操作发现、能力发现,以及任何 + 渠道专用 schema 片段 +- 渠道插件拥有提供商专用的会话对话语法,例如 + 对话 ID 如何编码线程 ID 或如何从父对话继承 - 渠道插件通过其 action adapter 执行最终操作 -对于渠道插件,SDK 表面是 +对于渠道插件,SDK 接口是 `ChannelMessageActionAdapter.describeMessageTool(...)`。这个统一的发现 -调用让插件可以将其可见操作、能力和 schema 贡献一起返回, -从而避免这些部分彼此漂移。 +调用允许插件一起返回其可见操作、能力和 schema +贡献,从而避免这些部分相互漂移。 -当某个渠道专属 message-tool 参数携带媒体源,例如 +当某个渠道专用 message-tool 参数承载媒体来源,例如 本地路径或远程媒体 URL 时,插件还应从 -`describeMessageTool(...)` 返回 `mediaSourceParams`。核心使用这份显式 -列表来应用沙箱路径规范化和出站媒体访问提示,而无需硬编码插件自有的参数名称。 -在这里优先使用按 action 分组的映射,而不是整个渠道范围的单一平面列表, -这样仅用于 profile 的媒体参数就不会在诸如 -`send` 之类无关操作上被规范化。 +`describeMessageTool(...)` 返回 `mediaSourceParams`。核心会使用这个显式 +列表来应用沙箱路径规范化和出站媒体访问提示, +而无需硬编码插件拥有的参数名称。 +在这里优先使用按操作划分的映射,而不是整个渠道范围内的扁平列表,这样 +仅配置文件使用的媒体参数就不会在像 `send` 这样的无关操作上被规范化。 -核心会将运行时作用域传入该发现步骤。重要字段包括: +核心会把运行时作用域传入该发现步骤。重要字段包括: - `accountId` - `currentChannelId` @@ -197,117 +193,119 @@ OpenClaw 在核心中保留一个共享的 `message` 工具,而 - `agentId` - 受信任的入站 `requesterSenderId` -这对于上下文敏感的插件很重要。一个渠道可以根据活跃账户、 -当前房间/线程/消息或受信任的请求者身份来隐藏或暴露 -message 操作,而无需在核心 `message` 工具中硬编码渠道专属分支。 +这对上下文敏感型插件很重要。渠道可以根据活动账户、 +当前房间/线程/消息或受信任的请求方身份来隐藏或暴露 +消息操作,而无需在核心 `message` 工具中硬编码渠道专用分支。 -这也是为什么嵌入式运行器路由变更仍然属于插件工作:运行器 +这就是为什么嵌入式 runner 路由变更仍然属于插件工作:runner 负责将当前聊天/会话身份转发到插件发现边界,以便共享的 `message` -工具为当前轮次暴露正确的插件自有表面。 +工具为当前轮次暴露正确的渠道拥有接口。 -对于渠道自有的执行辅助工具,内置插件应将执行运行时保留在其 -自有的扩展模块中。核心不再在 `src/agents/tools` 下拥有 Discord、 -Slack、Telegram 或 WhatsApp 的消息操作运行时。 +对于渠道拥有的执行辅助工具,内置插件应将执行运行时保留在它们 +自己的扩展模块中。核心不再拥有位于 `src/agents/tools` 下的 Discord、 +Slack、Telegram 或 WhatsApp 消息操作运行时。 我们不会发布单独的 `plugin-sdk/*-action-runtime` 子路径,内置 -插件应直接从其扩展自有模块导入本地运行时代码。 +插件应直接从自己扩展拥有的模块中导入本地运行时代码。 -同样的边界也适用于一般的提供商命名 SDK 接缝:核心 -不应导入 Slack、Discord、Signal、 -WhatsApp 或类似扩展的渠道专用便捷 barrel。如果核心需要某个行为, -要么消费内置插件自己的 `api.ts` / `runtime-api.ts` barrel,要么将该需求提升为共享 SDK 中狭窄的通用能力。 +相同的边界通常也适用于带提供商名称的 SDK 接缝:核心不应 +导入 Slack、Discord、Signal、 +WhatsApp 或类似扩展的渠道专用便捷 barrel。如果核心需要某种行为,要么 +消费该内置插件自己的 `api.ts` / `runtime-api.ts` barrel,要么将该需求 +提升为共享 SDK 中的狭义通用能力。 对于投票,具体有两条执行路径: - `outbound.sendPoll` 是适用于符合通用 投票模型渠道的共享基线 -- `actions.handleAction("poll")` 是更推荐的路径,适用于渠道专属 - 投票语义或额外投票参数 +- `actions.handleAction("poll")` 是处理渠道专用 + 投票语义或额外投票参数的首选路径 -现在,核心会在插件投票分发拒绝该操作之后,才延迟进行共享投票解析, -因此插件自有的投票处理器可以接受渠道专属的投票字段,而不会先被通用投票解析器拦住。 +现在,核心会在插件投票分发拒绝该操作之后,才延迟执行共享投票解析,因此 +插件拥有的投票处理器可以接受渠道专用投票字段,而不会先被 +通用投票解析器阻塞。 -完整启动顺序请参见 [Load pipeline](#load-pipeline)。 +完整启动顺序请参见 [加载流水线](#load-pipeline)。 ## 能力归属模型 -OpenClaw 将原生插件视为**公司**或 -**功能**的归属边界,而不是一堆无关集成的杂货袋。 +OpenClaw 将原生插件视为**公司**或**功能**的归属边界, +而不是一堆互不相关集成的集合。 这意味着: -- 一个公司插件通常应拥有该公司所有面向 OpenClaw 的 - 表面 -- 一个功能插件通常应拥有它引入的完整功能表面 -- 渠道应消费共享核心能力,而不是临时重新实现 - 提供商行为 +- 公司插件通常应拥有该公司的所有 OpenClaw 对外接口 +- 功能插件通常应拥有它引入的完整功能接口 +- 渠道应消费共享核心能力,而不是临时重新实现提供商行为 示例: -- 内置的 `openai` 插件拥有 OpenAI 模型提供商行为,以及 OpenAI +- 内置的 `openai` 插件拥有 OpenAI 模型提供商行为,以及 OpenAI 的 语音 + 实时语音 + 媒体理解 + 图像生成行为 - 内置的 `elevenlabs` 插件拥有 ElevenLabs 语音行为 - 内置的 `microsoft` 插件拥有 Microsoft 语音行为 -- 内置的 `google` 插件拥有 Google 模型提供商行为,以及 Google - 媒体理解 + 图像生成 + 网页搜索行为 -- 内置的 `firecrawl` 插件拥有 Firecrawl 网页抓取行为 -- 内置的 `minimax`、`mistral`、`moonshot` 和 `zai` 插件拥有它们各自的 +- 内置的 `google` 插件拥有 Google 模型提供商行为,以及 Google 的 + 媒体理解 + 图像生成 + Web 搜索行为 +- 内置的 `firecrawl` 插件拥有 Firecrawl Web 抓取行为 +- 内置的 `minimax`、`mistral`、`moonshot` 和 `zai` 插件拥有它们的 媒体理解后端 - 内置的 `qwen` 插件拥有 Qwen 文本提供商行为,以及 媒体理解和视频生成行为 - `voice-call` 插件是一个功能插件:它拥有通话传输、工具、 - CLI、路由和 Twilio 媒体流桥接,但它消费共享语音 + CLI、路由和 Twilio 媒体流桥接,但它会消费共享的语音 以及实时转录和实时语音能力,而不是直接导入供应商插件 预期的最终状态是: -- OpenAI 即使横跨文本模型、语音、图像以及未来的视频,也应存在于同一个插件中 -- 其他供应商也可以对其自己的表面范围采用同样方式 -- 渠道并不关心是哪个供应商插件拥有该提供商;它们消费的是由核心暴露的共享能力契约 +- OpenAI 位于一个插件中,即使它涵盖文本模型、语音、图像以及 + 未来的视频 +- 其他供应商也可以用同样方式处理自己的接口范围 +- 渠道不关心哪个供应商插件拥有该提供商;它们消费的是由核心暴露的 + 共享能力契约 -这就是关键区别: +这是关键区别: - **plugin** = 归属边界 - **capability** = 多个插件都可以实现或消费的核心契约 -因此,如果 OpenClaw 添加了一个新领域,例如视频,第一个问题 -不应是“哪个提供商应该硬编码视频处理?”第一个问题应是“核心视频能力契约 -是什么?”一旦这个契约存在,供应商插件 +因此,如果 OpenClaw 添加一个新领域,例如视频,第一个问题 +不是“哪个提供商应该硬编码视频处理?”第一个问题是“什么是 +核心视频能力契约?”一旦该契约存在,供应商插件 就可以针对它进行注册,而渠道/功能插件也可以消费它。 如果该能力尚不存在,通常正确的做法是: 1. 在核心中定义缺失的能力 -2. 以类型化的方式通过插件 API/运行时暴露它 -3. 让渠道/功能针对该能力进行接线 +2. 以类型化方式通过插件 API/运行时公开它 +3. 让渠道/功能对接到该能力 4. 让供应商插件注册实现 -这样可以在保持归属明确的同时,避免核心行为依赖于某个 -单一供应商或某条一次性的插件专属代码路径。 +这样可以在保持归属明确的同时,避免核心行为依赖于 +单个供应商或某条一次性的插件专用代码路径。 ### 能力分层 -在决定代码应放在哪里时,请使用这个思维模型: +在决定代码归属位置时,请使用以下心智模型: - **核心能力层**:共享编排、策略、回退、配置 合并规则、投递语义和类型化契约 -- **供应商插件层**:供应商专属 API、认证、模型目录、语音 - 合成、图像生成、未来的视频后端、用量端点 +- **供应商插件层**:供应商专用 API、认证、模型目录、语音 + 合成、图像生成、未来视频后端、使用情况端点 - **渠道/功能插件层**:Slack/Discord/voice-call 等集成, - 它们消费核心能力并将其呈现在某个表面上 + 它们消费核心能力并在某个界面上呈现出来 -例如,TTS 遵循这种结构: +例如,TTS 遵循以下结构: -- 核心负责回复时 TTS 策略、回退顺序、偏好设置和渠道投递 -- `openai`、`elevenlabs` 和 `microsoft` 负责合成实现 +- 核心拥有回复时 TTS 策略、回退顺序、偏好和渠道投递 +- `openai`、`elevenlabs` 和 `microsoft` 拥有合成实现 - `voice-call` 消费电话 TTS 运行时辅助工具 -对于未来的能力,也应优先采用同样的模式。 +对于未来能力,也应优先采用相同模式。 ### 多能力公司插件示例 -一个公司插件从外部看应当是内聚的。如果 OpenClaw 具有针对模型、语音、实时转录、实时语音、媒体 -理解、图像生成、视频生成、网页抓取和网页搜索的共享 -契约,那么一个供应商可以在一个地方拥有其所有表面: +从外部来看,公司插件应当是内聚的。如果 OpenClaw 具有适用于模型、语音、实时转录、实时语音、媒体 +理解、图像生成、视频生成、Web 抓取和 Web 搜索的共享契约, +那么某个供应商就可以在一个地方拥有其所有接口: ```ts import type { OpenClawPluginDefinition } from "openclaw/plugin-sdk/plugin-entry"; @@ -361,232 +359,237 @@ const plugin: OpenClawPluginDefinition = { export default plugin; ``` -重要的不是辅助函数的确切名称。重要的是这种结构: +重要的不是精确的辅助工具名称。重要的是这种结构: -- 一个插件拥有供应商表面 +- 一个插件拥有该供应商接口 - 核心仍然拥有能力契约 -- 渠道和功能插件消费的是 `api.runtime.*` 辅助工具,而不是供应商代码 -- 契约测试可以断言插件确实注册了它 - 声称拥有的能力 +- 渠道和功能插件消费 `api.runtime.*` 辅助工具,而不是供应商代码 +- 契约测试可以断言该插件注册了其声称拥有的能力 ### 能力示例:视频理解 OpenClaw 已经将图像/音频/视频理解视为一种共享 -能力。相同的归属模型也适用于此: +能力。相同的归属模型也适用于这里: 1. 核心定义媒体理解契约 2. 供应商插件按需注册 `describeImage`、`transcribeAudio` 和 `describeVideo` 3. 渠道和功能插件消费共享核心行为,而不是 - 直接接线到供应商代码 + 直接连接供应商代码 -这样可避免将某个提供商对视频的假设固化到核心中。插件拥有 -供应商表面;核心拥有能力契约和回退行为。 +这样可以避免把某个提供商对视频的假设固化进核心。插件拥有 +供应商接口;核心拥有能力契约和回退行为。 -视频生成已经采用了同样的顺序:核心拥有类型化的 +视频生成已经采用了相同顺序:核心拥有类型化的 能力契约和运行时辅助工具,而供应商插件则注册 `api.registerVideoGenerationProvider(...)` 实现来对接它。 -需要一份具体的发布检查清单?请参见 +需要一个具体的发布检查清单吗?请参见 [能力扩展手册](/zh-CN/plugins/architecture)。 -## 契约与强制执行 +## 契约和强制机制 -插件 API 表面被有意设计为类型化并集中在 -`OpenClawPluginApi` 中。该契约定义了受支持的注册点,以及 -插件可以依赖的运行时辅助工具。 +插件 API 接口是有意类型化并集中在 +`OpenClawPluginApi` 中的。该契约定义了受支持的注册点,以及 +插件可依赖的运行时辅助工具。 -这很重要,因为: +这很重要,原因如下: -- 插件作者可以获得一个稳定的内部标准 -- 核心可以拒绝重复归属,例如两个插件注册相同的 +- 插件作者会获得一个稳定的内部标准 +- 核心可以拒绝重复归属,例如两个插件注册同一个 provider id -- 启动过程可以为格式错误的注册暴露可执行的诊断信息 -- 契约测试可以强制执行内置插件归属,并防止悄然漂移 +- 启动时可以为格式错误的注册暴露可操作的诊断信息 +- 契约测试可以强制执行内置插件归属,并防止静默漂移 -存在两层强制执行: +有两层强制机制: -1. **运行时注册强制执行** - 插件注册表会在插件加载时校验注册。例如: - 重复的 provider id、重复的语音提供商 id,以及格式错误的 +1. **运行时注册强制机制** + 插件注册表会在插件加载时验证注册内容。例如: + 重复的 provider id、重复的语音 provider id,以及格式错误的 注册,都会产生插件诊断,而不是未定义行为。 2. **契约测试** - 在测试运行期间,内置插件会被记录到契约注册表中, - 因此 OpenClaw 可以显式断言归属。今天这被用于模型 - 提供商、语音提供商、网页搜索提供商以及内置注册归属。 + 在测试运行期间,内置插件会被捕获到契约注册表中,因此 + OpenClaw 可以显式断言归属。如今,这用于模型 + providers、语音 providers、Web 搜索 providers,以及内置注册归属。 实际效果是,OpenClaw 能够预先知道,哪个插件拥有哪个 -表面。这让核心和渠道可以无缝组合,因为归属是被声明、类型化且可测试的,而不是隐式的。 +接口。这使核心和渠道能够无缝组合,因为归属是 +已声明、已类型化并且可测试的,而不是隐式的。 ### 什么内容应属于契约 -好的插件契约应当是: +好的插件契约应该是: - 类型化的 - 小而精的 -- 能力专属的 +- 能力专用的 - 由核心拥有 - 可被多个插件复用 -- 可被渠道/功能消费,而无需了解供应商知识 +- 可被渠道/功能在不了解供应商的情况下消费 不好的插件契约包括: -- 隐藏在核心中的供应商专属策略 -- 绕过注册表的一次性插件逃逸口 -- 渠道代码直接伸手访问某个供应商实现 +- 隐藏在核心中的供应商专用策略 +- 绕过注册表的一次性插件逃生口 +- 直接深入供应商实现的渠道代码 - 不属于 `OpenClawPluginApi` 或 `api.runtime` 的临时运行时对象 -如有疑问,请提升抽象层级:先定义能力,再让插件接入它。 +如有疑问,请提升抽象层级:先定义能力,再 +让插件接入它。 ## 执行模型 -原生 OpenClaw 插件与 Gateway 网关**在同一进程内**运行。它们并未 -沙箱隔离。一个已加载的原生插件与核心代码具有相同的进程级信任边界。 +原生 OpenClaw 插件与 Gateway 网关**在同一进程内**运行。它们 +不是沙箱隔离的。已加载的原生插件与核心代码具有相同的进程级信任边界。 -其含义是: +其影响包括: -- 一个原生插件可以注册工具、网络处理器、钩子和服务 +- 原生插件可以注册工具、网络处理器、钩子和服务 - 原生插件中的 bug 可能导致 gateway 崩溃或不稳定 - 恶意原生插件等同于在 OpenClaw 进程内部执行任意代码 -兼容的 bundle 默认更安全,因为 OpenClaw 当前将它们视为 +兼容 bundle 默认更安全,因为 OpenClaw 目前将它们视为 元数据/内容包。在当前版本中,这主要意味着内置 Skills。 对于非内置插件,请使用允许列表和显式安装/加载路径。将 -工作区插件视为开发期代码,而不是生产环境默认值。 +工作区插件视为开发阶段代码,而不是生产默认值。 -对于内置工作区 package 名称,请让插件 id 锚定在 npm -名称中:默认使用 `@openclaw/`,或者在包有意暴露更窄插件角色时, -使用已批准的类型化后缀,例如 -`-provider`、`-plugin`、`-speech`、`-sandbox` 或 `-media-understanding`。 +对于内置工作区包名,请让插件 id 锚定在 npm +名称中:默认使用 `@openclaw/`,或者使用经批准的类型化后缀,例如 +`-provider`、`-plugin`、`-speech`、`-sandbox` 或 `-media-understanding`,当 +该包有意暴露更窄的插件角色时。 重要的信任说明: -- `plugins.allow` 信任的是**插件 id**,而不是来源证明。 -- 与内置插件具有相同 id 的工作区插件,在该工作区插件被启用/加入允许列表时, - 会有意遮蔽内置副本。 -- 这属于正常且有用的行为,可用于本地开发、补丁测试和热修复。 +- `plugins.allow` 信任的是**插件 id**,而不是来源出处。 +- 与某个内置插件拥有相同 id 的工作区插件,在该工作区插件被启用/加入允许列表时,会有意覆盖内置副本。 +- 这属于正常且有用的行为,适用于本地开发、补丁测试和热修复。 +- 内置插件信任是根据源快照解析的——即加载时磁盘上的 manifest 和代码——而不是根据安装元数据解析。损坏或被替换的安装记录无法静默扩大某个内置插件的信任范围,超出实际源代码所声明的内容。 ## 导出边界 -OpenClaw 导出的是能力,而不是实现便捷工具。 +OpenClaw 导出的是能力,而不是实现层面的便捷接口。 -保持能力注册为公开。裁剪非契约辅助导出: +保持能力注册公开。裁剪非契约辅助导出: -- 内置插件专属的辅助子路径 -- 不打算作为公开 API 的运行时接线子路径 -- 供应商专属便捷辅助工具 +- 内置插件专用辅助子路径 +- 无意作为公共 API 的运行时管道子路径 +- 供应商专用便捷辅助工具 - 属于实现细节的设置/新手引导辅助工具 -出于兼容性和内置插件维护需要,一些内置插件辅助子路径 -仍保留在生成的 SDK 导出映射中。当前示例包括 +某些内置插件辅助子路径仍然保留在生成的 SDK 导出 +映射中,用于兼容性和内置插件维护。当前示例包括 `plugin-sdk/feishu`、`plugin-sdk/feishu-setup`、`plugin-sdk/zalo`、 `plugin-sdk/zalo-setup` 以及若干 `plugin-sdk/matrix*` 接缝。请将这些视为 保留的实现细节导出,而不是新第三方插件推荐采用的 SDK 模式。 ## 加载流水线 -在启动时,OpenClaw 大致会执行以下步骤: +启动时,OpenClaw 大致会执行以下步骤: 1. 发现候选插件根目录 -2. 读取原生或兼容 bundle 的 manifest 与 package 元数据 +2. 读取原生或兼容 bundle 的 manifest 和包元数据 3. 拒绝不安全的候选项 4. 规范化插件配置(`plugins.enabled`、`allow`、`deny`、`entries`、 `slots`、`load.paths`) -5. 为每个候选项决定启用状态 -6. 通过 jiti 加载已启用的原生模块 -7. 调用原生 `register(api)`(或 `activate(api)` —— 旧式别名)钩子,并将注册内容收集到插件注册表中 -8. 将注册表暴露给命令/运行时表面 +5. 决定每个候选项是否启用 +6. 加载已启用的原生模块——已构建的 `dist/*` 内置模块会走 + 原生加载器路径,而未构建的原生插件模块会通过 + jiti 加载 +7. 调用原生 `register(api)`(或 `activate(api)`——旧版别名)钩子,并将注册内容收集到插件注册表中 +8. 将注册表暴露给命令/运行时接口 -`activate` 是 `register` 的旧式别名 —— 加载器会解析二者中存在的那个(`def.register ?? def.activate`),并在同一时机调用。所有内置插件都使用 `register`;新插件请优先使用 `register`。 +`activate` 是 `register` 的旧版别名——加载器会解析存在的那一个(`def.register ?? def.activate`),并在相同位置调用它。所有内置插件都使用 `register`;新插件请优先使用 `register`。 -安全门控发生在**运行时执行之前**。当候选项出现以下情况时会被阻止: -入口逃逸出插件根目录、路径可被所有人写入,或者对于非内置插件而言, -路径归属看起来可疑。 +安全门会在运行时执行**之前**发生。当候选项满足以下条件时会被阻止: +入口逃逸出插件根目录、路径对所有人可写,或者对于非内置插件来说路径所有权看起来可疑。 -### Manifest 优先行为 +### Manifest-first 行为 -manifest 是控制平面的事实来源。OpenClaw 使用它来: +manifest 是控制平面的真实来源。OpenClaw 用它来: - 标识插件 - 发现已声明的渠道/Skills/配置 schema 或 bundle 能力 -- 校验 `plugins.entries..config` +- 验证 `plugins.entries..config` - 增强 Control UI 标签/占位符 - 显示安装/目录元数据 -- 在不加载插件运行时的情况下保留轻量级激活和设置描述符 +- 在不加载插件运行时的情况下保留轻量的激活和设置描述符 -对于原生插件,运行时模块是数据平面部分。它负责注册 +对于原生插件,运行时模块是数据平面部分。它会注册 实际行为,例如钩子、工具、命令或提供商流程。 可选的 manifest `activation` 和 `setup` 块仍属于控制平面。 它们是用于激活规划和设置发现的纯元数据描述符; -不会取代运行时注册、`register(...)` 或 `setupEntry`。 -首批实时激活消费者现在会使用 manifest 中的命令、渠道和提供商提示, +并不能替代运行时注册、`register(...)` 或 `setupEntry`。 +当前首批实时激活使用方现在会使用 manifest 中的命令、渠道和提供商提示, 在更广泛的注册表实体化之前先缩小插件加载范围: - CLI 加载会缩小到拥有所请求主命令的插件 - 渠道设置/插件解析会缩小到拥有所请求 channel id 的插件 -- 显式提供商设置/运行时解析会缩小到拥有所请求 - provider id 的插件 +- 显式提供商设置/运行时解析会缩小到拥有所请求 provider id 的插件 -设置发现现在会优先使用描述符自有的 id,例如 `setup.providers` 和 -`setup.cliBackends`,以便在回退到 -`setup-api` 之前先缩小候选插件范围;`setup-api` 仅用于那些仍然需要设置阶段运行时钩子的插件。如果多个已发现插件声称拥有同一个已规范化的设置提供商或 CLI 后端 id,设置查找会拒绝这个存在歧义的归属者,而不是依赖发现顺序。 +设置发现现在优先使用描述符拥有的 ID,例如 `setup.providers` 和 +`setup.cliBackends`,先缩小候选插件范围,然后才会回退到 +`setup-api`,用于那些仍然需要设置时运行时钩子的插件。 +如果多个已发现插件声称拥有相同规范化后的 setup provider 或 CLI backend +id,设置查找会拒绝这个歧义归属,而不是依赖发现顺序。 -### 加载器会缓存什么 +### 加载器缓存的内容 -OpenClaw 会保留以下短生命周期的进程内缓存: +OpenClaw 会为以下内容保留短期的进程内缓存: - 发现结果 - manifest 注册表数据 - 已加载的插件注册表 -这些缓存可减少突发式启动开销和重复命令的开销。可以安全地将它们视为短期性能缓存,而不是持久化机制。 +这些缓存可以减少突发启动和重复命令开销。可以安全地将它们视为 +短生命周期的性能缓存,而不是持久化机制。 性能说明: - 设置 `OPENCLAW_DISABLE_PLUGIN_DISCOVERY_CACHE=1` 或 `OPENCLAW_DISABLE_PLUGIN_MANIFEST_CACHE=1` 可禁用这些缓存。 - 使用 `OPENCLAW_PLUGIN_DISCOVERY_CACHE_MS` 和 - `OPENCLAW_PLUGIN_MANIFEST_CACHE_MS` 调整缓存时间窗口。 + `OPENCLAW_PLUGIN_MANIFEST_CACHE_MS` 调整缓存窗口。 ## 注册表模型 -已加载插件不会直接修改随意的核心全局状态。它们会注册到一个 +已加载的插件不会直接修改随意的核心全局状态。它们会注册到 中央插件注册表中。 -该注册表会跟踪: +注册表会跟踪: -- 插件记录(身份、来源、出处、状态、诊断) +- 插件记录(身份、来源、起源、状态、诊断) - 工具 -- 旧式钩子和类型化钩子 +- 旧版钩子和类型化钩子 - 渠道 - 提供商 - Gateway 网关 RPC 处理器 - HTTP 路由 - CLI 注册器 - 后台服务 -- 插件自有命令 +- 插件拥有的命令 -然后,核心功能从该注册表中读取,而不是直接与插件模块交互。 -这使得加载保持单向: +然后核心功能会从该注册表读取,而不是直接与插件模块通信。 +这使加载保持单向: - 插件模块 -> 注册表注册 - 核心运行时 -> 注册表消费 -这种分离对可维护性很重要。这意味着大多数核心表面只需要一个集成点: -“读取注册表”,而不是“为每个插件模块做特殊处理”。 +这种分离对可维护性很重要。它意味着大多数核心接口只 +需要一个集成点:“读取注册表”,而不是“为每个插件模块写特殊处理”。 -## 会话绑定回调 +## 对话绑定回调 -绑定会话的插件可以在批准结果确定时作出响应。 +绑定某个对话的插件可以在批准结果确定时作出响应。 -使用 `api.onConversationBindingResolved(...)` 在绑定请求被批准或拒绝后接收回调: +使用 `api.onConversationBindingResolved(...)` 可在绑定 +请求获批或被拒后接收回调: ```ts export default { @@ -594,12 +597,12 @@ export default { register(api) { api.onConversationBindingResolved(async (event) => { if (event.status === "approved") { - // 现在已为此插件 + 会话建立绑定。 + // A binding now exists for this plugin + conversation. console.log(event.binding?.conversationId); return; } - // 请求被拒绝;清除任何本地待定状态。 + // The request was denied; clear any local pending state. console.log(event.request.conversation.conversationId); }); }, @@ -610,23 +613,23 @@ export default { - `status`:`"approved"` 或 `"denied"` - `decision`:`"allow-once"`、`"allow-always"` 或 `"deny"` -- `binding`:已批准请求的已解析绑定 -- `request`:原始请求摘要、分离提示、发送者 id,以及 - 会话元数据 +- `binding`:已批准请求的解析后绑定 +- `request`:原始请求摘要、detach 提示、sender id 以及 + 对话元数据 -此回调仅用于通知。它不会改变谁被允许绑定某个 -会话,并且它会在核心的批准处理完成后运行。 +该回调仅用于通知。它不会改变谁被允许绑定某个 +对话,并且会在核心批准处理完成后运行。 ## 提供商运行时钩子 提供商插件现在有两层: -- manifest 元数据:`providerAuthEnvVars` 用于在运行时加载前 - 进行轻量级提供商环境变量认证查找,`providerAuthAliases` 用于共享 - 认证的提供商变体,`channelEnvVars` 用于在运行时 - 加载前进行轻量级渠道环境变量/设置查找,以及 `providerAuthChoices` 用于在运行时加载前 - 提供轻量级新手引导/认证选择标签和 CLI flag 元数据 -- 配置阶段钩子:`catalog` / 旧式 `discovery`,以及 `applyConfigDefaults` +- manifest 元数据:`providerAuthEnvVars` 用于在运行时加载前进行低成本的提供商环境认证查找, + `providerAuthAliases` 用于共享认证的提供商变体, + `channelEnvVars` 用于在运行时 + 加载前进行低成本的渠道环境/设置查找,以及 `providerAuthChoices` 用于在运行时加载前提供低成本的新手引导/认证选择标签和 + CLI 标志元数据 +- 配置时钩子:`catalog` / 旧版 `discovery` 以及 `applyConfigDefaults` - 运行时钩子:`normalizeModelId`、`normalizeTransport`、 `normalizeConfig`、 `applyNativeStreamingUsageCompat`、`resolveConfigApiKey`、 @@ -647,79 +650,81 @@ export default { `buildReplayPolicy`、 `sanitizeReplayHistory`、`validateReplayTurns`、`onModelSelected` -OpenClaw 仍然拥有通用智能体循环、故障切换、转录处理和 -工具策略。这些钩子是提供商专属行为的扩展表面, -无需为此实现整个自定义推理传输。 +OpenClaw 仍然拥有通用智能体循环、故障切换、对话记录处理和 +工具策略。这些钩子是在不需要完整自定义推理传输的情况下,为提供商专用行为提供的扩展接口。 -当某个提供商具有基于环境变量的凭证,且通用认证/状态/模型选择器路径应当在不加载插件运行时的情况下看到这些凭证时,请使用 manifest `providerAuthEnvVars`。当一个 provider id 应复用另一个 provider id 的环境变量、认证配置文件、基于配置的认证和 API key 新手引导选项时,请使用 manifest `providerAuthAliases`。当新手引导/认证选择 CLI 表面应在不加载提供商运行时的情况下知道该提供商的 choice id、分组标签和简单的单 flag 认证接线时,请使用 manifest `providerAuthChoices`。将提供商运行时的 `envVars` 保留给面向运维人员的提示,例如新手引导标签或 OAuth -client-id/client-secret 设置变量。 +当提供商具有基于环境变量的凭证,并且通用认证/状态/模型选择器路径应当在不加载插件运行时的情况下看到这些凭证时,请使用 manifest `providerAuthEnvVars`。 +当某个 provider id 应复用另一个 provider id 的环境变量、认证配置文件、配置支持的认证和 API 密钥新手引导选项时,请使用 manifest `providerAuthAliases`。 +当新手引导/认证选择 CLI 界面应在不加载提供商运行时的情况下,了解该提供商的选择 ID、分组标签和简单单标志认证接线时,请使用 manifest `providerAuthChoices`。 +将提供商运行时的 `envVars` 保留给面向运维人员的提示,例如新手引导标签或 OAuth +client-id/client-secret 设置环境变量。 -当某个渠道具有基于环境变量驱动的认证或设置,且通用 shell 环境变量回退、配置/状态检查或设置提示应当在不加载渠道运行时的情况下看到这些内容时,请使用 manifest `channelEnvVars`。 +当某个渠道具有由环境变量驱动的认证或设置,并且通用 shell 环境变量回退、配置/状态检查或设置提示应当在不加载渠道运行时的情况下看到它时,请使用 manifest `channelEnvVars`。 -### 钩子顺序与用法 +### 钩子顺序和使用方式 -对于模型/提供商插件,OpenClaw 大致按如下顺序调用这些钩子。 -“何时使用”这一列可作为快速决策指南。 +对于模型/提供商插件,OpenClaw 大致按以下顺序调用钩子。 +“何时使用”这一列是快速决策指南。 -| # | 钩子 | 它的作用 | 何时使用 | +| # | 钩子 | 功能 | 何时使用 | | --- | --------------------------------- | -------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | -| 1 | `catalog` | 在生成 `models.json` 期间将提供商配置发布到 `models.providers` 中 | 提供商拥有目录或 base URL 默认值 | -| 2 | `applyConfigDefaults` | 在配置实体化期间应用提供商自有的全局配置默认值 | 默认值依赖于认证模式、环境变量或提供商模型家族语义 | -| -- | _(内置模型查找)_ | OpenClaw 会先尝试正常的注册表/目录路径 | _(不是插件钩子)_ | -| 3 | `normalizeModelId` | 在查找前规范化旧式或预览版 model-id 别名 | 提供商在规范模型解析前拥有别名清理逻辑 | -| 4 | `normalizeTransport` | 在通用模型组装前规范化提供商家族的 `api` / `baseUrl` | 提供商拥有同一传输家族内自定义 provider id 的传输清理逻辑 | -| 5 | `normalizeConfig` | 在运行时/提供商解析前规范化 `models.providers.` | 提供商需要将配置清理逻辑放在插件中;内置的 Google 家族辅助工具也会为受支持的 Google 配置条目提供兜底 | -| 6 | `applyNativeStreamingUsageCompat` | 对配置提供商应用原生流式用量兼容性重写 | 提供商需要基于端点对原生流式用量元数据进行修正 | -| 7 | `resolveConfigApiKey` | 在运行时认证加载前,为配置提供商解析环境变量标记认证 | 提供商拥有自己的环境变量标记 API key 解析逻辑;`amazon-bedrock` 在这里也有一个内置的 AWS 环境变量标记解析器 | -| 8 | `resolveSyntheticAuth` | 在不持久化明文的情况下暴露本地/自托管或基于配置的认证 | 提供商可使用合成/本地凭证标记运行 | -| 9 | `resolveExternalAuthProfiles` | 覆盖提供商自有的外部认证配置文件;`persistence` 默认为 `runtime-only`,适用于 CLI/应用自有凭证 | 提供商在不持久化复制的 refresh token 的情况下复用外部认证凭证;请在 manifest 中声明 `contracts.externalAuthProviders` | -| 10 | `shouldDeferSyntheticProfileAuth` | 将已存储的合成配置文件占位符降低到环境变量/基于配置的认证之后 | 提供商会存储合成占位配置文件,而这些占位符不应具有更高优先级 | -| 11 | `resolveDynamicModel` | 对本地注册表中尚不存在的提供商自有模型 id 执行同步回退解析 | 提供商接受任意上游模型 id | -| 12 | `prepareDynamicModel` | 执行异步预热,然后再次运行 `resolveDynamicModel` | 提供商在解析未知 id 前需要网络元数据 | -| 13 | `normalizeResolvedModel` | 在嵌入式运行器使用已解析模型前执行最终重写 | 提供商需要传输重写,但仍使用核心传输 | -| 14 | `contributeResolvedModelCompat` | 为位于其他兼容传输之后的供应商模型贡献兼容性标志 | 提供商能在代理传输上识别自己的模型,而无需接管该提供商 | -| 15 | `capabilities` | 由提供商拥有、被共享核心逻辑使用的转录/工具元数据 | 提供商需要处理转录或提供商家族特性 | -| 16 | `normalizeToolSchemas` | 在嵌入式运行器看到工具 schema 之前对其进行规范化 | 提供商需要传输家族级别的 schema 清理 | -| 17 | `inspectToolSchemas` | 在规范化之后暴露提供商自有的 schema 诊断 | 提供商希望提供关键字警告,而不必让核心理解提供商专属规则 | -| 18 | `resolveReasoningOutputMode` | 选择原生或带标签的推理输出契约 | 提供商需要使用带标签的推理/最终输出,而不是原生字段 | -| 19 | `prepareExtraParams` | 在通用流式选项包装器之前规范化请求参数 | 提供商需要默认请求参数或按提供商执行参数清理 | -| 20 | `createStreamFn` | 使用自定义传输完全替换正常流路径 | 提供商需要自定义线协议,而不只是包装器 | -| 21 | `wrapStreamFn` | 在应用通用包装器之后对流进行包装 | 提供商需要请求头/请求体/模型兼容性包装器,而不是自定义传输 | -| 22 | `resolveTransportTurnState` | 附加原生的逐轮传输头或元数据 | 提供商希望通用传输发送提供商原生的轮次标识 | -| 23 | `resolveWebSocketSessionPolicy` | 附加原生 WebSocket 请求头或会话冷却策略 | 提供商希望通用 WS 传输调整会话请求头或回退策略 | -| 24 | `formatApiKey` | 认证配置文件格式化器:已存储的配置文件会变成运行时 `apiKey` 字符串 | 提供商存储了额外认证元数据,并需要自定义运行时 token 形态 | -| 25 | `refreshOAuth` | 针对自定义刷新端点或刷新失败策略的 OAuth 刷新覆盖 | 提供商不适配共享的 `pi-ai` 刷新器 | -| 26 | `buildAuthDoctorHint` | 当 OAuth 刷新失败时附加的修复提示 | 提供商在刷新失败后需要提供商自有的认证修复指导 | -| 27 | `matchesContextOverflowError` | 提供商自有的上下文窗口溢出匹配器 | 提供商存在通用启发式无法捕获的原始溢出错误 | -| 28 | `classifyFailoverReason` | 提供商自有的故障切换原因分类 | 提供商可以将原始 API/传输错误映射为限流、过载等 | -| 29 | `isCacheTtlEligible` | 面向代理/回程提供商的提示词缓存策略 | 提供商需要代理专属的缓存 TTL 门控 | -| 30 | `buildMissingAuthMessage` | 替代通用缺失认证恢复消息 | 提供商需要提供商专属的缺失认证恢复提示 | -| 31 | `suppressBuiltInModel` | 抑制过时的上游模型,并可选提供面向用户的错误提示 | 提供商需要隐藏过时的上游条目,或用供应商提示替换它们 | -| 32 | `augmentModelCatalog` | 在发现之后追加合成/最终目录条目 | 提供商需要在 `models list` 和选择器中提供合成的前向兼容条目 | -| 33 | `resolveThinkingProfile` | 设置特定于模型的 `/think` 级别、显示标签和默认值 | 提供商为选定模型暴露自定义思考等级体系或二元标签 | -| 34 | `isBinaryThinking` | 开/关推理切换兼容性钩子 | 提供商只暴露二元的思考开/关 | -| 35 | `supportsXHighThinking` | `xhigh` 推理支持兼容性钩子 | 提供商只希望在部分模型上支持 `xhigh` | -| 36 | `resolveDefaultThinkingLevel` | 默认 `/think` 级别兼容性钩子 | 提供商拥有某个模型家族的默认 `/think` 策略 | -| 37 | `isModernModelRef` | 用于实时配置文件过滤和冒烟选择的现代模型匹配器 | 提供商拥有实时/冒烟首选模型匹配逻辑 | -| 38 | `prepareRuntimeAuth` | 在推理前将已配置的凭证交换为实际运行时 token/key | 提供商需要执行 token 交换或使用短生命周期请求凭证 | -| 39 | `resolveUsageAuth` | 为 `/usage` 及相关状态表面解析用量/计费凭证 | 提供商需要自定义用量/配额 token 解析,或使用不同的用量凭证 | -| 40 | `fetchUsageSnapshot` | 在认证解析后获取并规范化提供商专属的用量/配额快照 | 提供商需要提供商专属的用量端点或负载解析器 | -| 41 | `createEmbeddingProvider` | 为 memory/search 构建由提供商拥有的 embedding adapter | Memory 的 embedding 行为应归属于提供商插件 | -| 42 | `buildReplayPolicy` | 返回一个控制该提供商转录处理方式的重放策略 | 提供商需要自定义转录策略(例如剥离 thinking 块) | -| 43 | `sanitizeReplayHistory` | 在通用转录清理后重写重放历史 | 提供商需要在共享压缩辅助工具之外执行提供商专属的重放重写 | -| 44 | `validateReplayTurns` | 在嵌入式运行器之前对重放轮次做最终校验或重塑 | 提供商传输在通用净化后仍需要更严格的轮次校验 | -| 45 | `onModelSelected` | 在模型被选中后运行提供商自有的后续副作用 | 当某个模型变为活跃时,提供商需要遥测或提供商自有状态 | +| 1 | `catalog` | 在生成 `models.json` 期间,将提供商配置发布到 `models.providers` 中 | 提供商拥有目录,或拥有基础 URL 默认值 | +| 2 | `applyConfigDefaults` | 在配置实体化期间应用由提供商拥有的全局配置默认值 | 默认值依赖于认证模式、环境变量或提供商模型家族语义 | +| -- | _(内置模型查找)_ | OpenClaw 会先尝试常规注册表/目录路径 | _(不是插件钩子)_ | +| 3 | `normalizeModelId` | 在查找前规范化旧版或预览版 model-id 别名 | 提供商拥有在规范模型解析前进行的别名清理逻辑 | +| 4 | `normalizeTransport` | 在通用模型组装前规范化同一传输家族中的提供商家族 `api` / `baseUrl` | 提供商拥有针对同一传输家族中自定义 provider id 的传输清理逻辑 | +| 5 | `normalizeConfig` | 在运行时/提供商解析前规范化 `models.providers.` | 提供商需要应与插件一同维护的配置清理逻辑;内置的 Google 家族辅助工具也会为受支持的 Google 配置条目提供兜底 | +| 6 | `applyNativeStreamingUsageCompat` | 将原生流式使用情况兼容重写应用到配置提供商 | 提供商需要基于端点的原生流式使用情况元数据修复 | +| 7 | `resolveConfigApiKey` | 在加载运行时认证前,为配置提供商解析 env-marker 认证 | 提供商拥有自己的 env-marker API 密钥解析逻辑;`amazon-bedrock` 在这里也有内置的 AWS env-marker 解析器 | +| 8 | `resolveSyntheticAuth` | 在不持久化明文的前提下暴露本地/自托管或配置支持的认证 | 提供商可以通过合成/本地凭证标记运行 | +| 9 | `resolveExternalAuthProfiles` | 叠加由提供商拥有的外部认证配置文件;默认 `persistence` 为 `runtime-only`,用于 CLI/应用拥有的凭证 | 提供商在不持久化复制的 refresh token 的情况下复用外部认证凭证;需在 manifest 中声明 `contracts.externalAuthProviders` | +| 10 | `shouldDeferSyntheticProfileAuth` | 将已存储的合成配置文件占位符降到 env/配置支持的认证之后 | 提供商会存储不应获得更高优先级的合成占位配置文件 | +| 11 | `resolveDynamicModel` | 为尚未出现在本地注册表中的提供商模型 ID 提供同步回退解析 | 提供商接受任意上游模型 ID | +| 12 | `prepareDynamicModel` | 先进行异步预热,然后再次运行 `resolveDynamicModel` | 提供商在解析未知 ID 之前需要网络元数据 | +| 13 | `normalizeResolvedModel` | 在嵌入式 runner 使用解析后模型之前进行最终重写 | 提供商需要传输重写,但仍使用核心传输 | +| 14 | `contributeResolvedModelCompat` | 为经由另一个兼容传输的供应商模型贡献兼容标志 | 提供商可在不接管该提供商的情况下,通过代理传输识别自己的模型 | +| 15 | `capabilities` | 由提供商拥有、供共享核心逻辑使用的对话记录/工具元数据 | 提供商需要处理对话记录/提供商家族特有的差异 | +| 16 | `normalizeToolSchemas` | 在嵌入式 runner 看到工具 schema 之前对其进行规范化 | 提供商需要进行传输家族级 schema 清理 | +| 17 | `inspectToolSchemas` | 在规范化后暴露由提供商拥有的 schema 诊断信息 | 提供商希望给出关键字警告,而无需让核心了解提供商专用规则 | +| 18 | `resolveReasoningOutputMode` | 选择原生推理输出契约还是带标签的推理输出契约 | 提供商需要使用带标签的推理/最终输出,而不是原生字段 | +| 19 | `prepareExtraParams` | 在通用流选项包装器之前进行请求参数规范化 | 提供商需要默认请求参数,或进行按提供商划分的参数清理 | +| 20 | `createStreamFn` | 用自定义传输完全替换常规流式路径 | 提供商需要自定义线路协议,而不只是包装器 | +| 21 | `wrapStreamFn` | 在应用通用包装器后再对流函数进行包装 | 提供商需要请求头/请求体/模型兼容包装器,但不需要自定义传输 | +| 22 | `resolveTransportTurnState` | 附加原生的逐轮传输头或元数据 | 提供商希望通用传输发送提供商原生的轮次身份 | +| 23 | `resolveWebSocketSessionPolicy` | 附加原生 WebSocket 请求头或会话冷却策略 | 提供商希望通用 WS 传输调节会话请求头或回退策略 | +| 24 | `formatApiKey` | auth-profile 格式化器:将存储的配置文件转换为运行时 `apiKey` 字符串 | 提供商存储额外认证元数据,并需要自定义运行时令牌格式 | +| 25 | `refreshOAuth` | 为自定义刷新端点或刷新失败策略覆盖 OAuth 刷新逻辑 | 提供商不适用于共享的 `pi-ai` 刷新器 | +| 26 | `buildAuthDoctorHint` | 在 OAuth 刷新失败时附加修复提示 | 提供商在刷新失败后需要提供由自己拥有的认证修复指导 | +| 27 | `matchesContextOverflowError` | 由提供商拥有的上下文窗口溢出匹配器 | 提供商存在通用启发式无法识别的原始溢出错误 | +| 28 | `classifyFailoverReason` | 由提供商拥有的故障切换原因分类 | 提供商可以将原始 API/传输错误映射为 rate-limit/overload 等类型 | +| 29 | `isCacheTtlEligible` | 面向代理/回程提供商的提示词缓存策略 | 提供商需要代理专用的缓存 TTL 门控 | +| 30 | `buildMissingAuthMessage` | 替换通用的缺失认证恢复消息 | 提供商需要提供商专用的缺失认证恢复提示 | +| 31 | `suppressBuiltInModel` | 过时上游模型抑制,并可附带面向用户的错误提示 | 提供商需要隐藏过时的上游条目,或用供应商提示替换它们 | +| 32 | `augmentModelCatalog` | 在发现后追加合成/最终目录行 | 提供商需要在 `models list` 和选择器中加入前向兼容的合成条目 | +| 33 | `resolveThinkingProfile` | 模型专用的 `/think` 级别集、显示标签和默认值 | 提供商为选定模型暴露自定义 thinking 阶梯或二元标签 | +| 34 | `isBinaryThinking` | 开/关推理切换兼容钩子 | 提供商仅暴露二元的 thinking 开/关 | +| 35 | `supportsXHighThinking` | `xhigh` 推理支持兼容钩子 | 提供商只希望在部分模型上启用 `xhigh` | +| 36 | `resolveDefaultThinkingLevel` | 默认 `/think` 级别兼容钩子 | 提供商拥有某个模型家族的默认 `/think` 策略 | +| 37 | `isModernModelRef` | 用于实时配置文件过滤和冒烟选择的现代模型匹配器 | 提供商拥有实时/冒烟首选模型匹配逻辑 | +| 38 | `prepareRuntimeAuth` | 在推理前将已配置凭证交换为实际运行时令牌/密钥 | 提供商需要令牌交换或短生命周期请求凭证 | +| 39 | `resolveUsageAuth` | 为 `/usage` 和相关状态界面解析使用情况/计费凭证 | 提供商需要自定义使用情况/配额令牌解析,或需要不同的使用情况凭证 | +| 40 | `fetchUsageSnapshot` | 在认证解析后获取并规范化提供商专用的使用情况/配额快照 | 提供商需要提供商专用的使用情况端点或负载解析器 | +| 41 | `createEmbeddingProvider` | 为 memory/search 构建由提供商拥有的嵌入适配器 | memory 嵌入行为应归属于提供商插件 | +| 42 | `buildReplayPolicy` | 返回控制该提供商对话记录处理方式的重放策略 | 提供商需要自定义对话记录策略(例如移除 thinking 块) | +| 43 | `sanitizeReplayHistory` | 在通用对话记录清理之后重写重放历史 | 提供商需要超出共享压缩辅助工具范围的提供商专用重放重写 | +| 44 | `validateReplayTurns` | 在嵌入式 runner 之前对重放轮次进行最终验证或重塑 | 提供商传输在通用净化之后需要更严格的轮次验证 | +| 45 | `onModelSelected` | 当某个模型变为活动状态时运行由提供商拥有的选择后副作用 | 提供商在模型激活时需要遥测或提供商自有状态 | `normalizeModelId`、`normalizeTransport` 和 `normalizeConfig` 会先检查 -匹配到的提供商插件,然后继续传递给其他具备钩子能力的提供商插件, -直到其中某个插件实际修改了模型 id 或传输/配置为止。这样可以让 -别名/兼容性提供商 shim 正常工作,而不要求调用方知道究竟是哪个 -内置插件拥有该重写逻辑。如果没有任何提供商钩子重写某个受支持的 -Google 家族配置条目,内置的 Google 配置规范化器仍会执行该兼容性清理。 +匹配到的提供商插件,然后继续落到其他具备相应钩子能力的提供商插件, +直到其中某个插件实际修改了模型 ID 或传输/配置为止。 +这样可以让别名/兼容提供商 shim 持续工作,而不要求调用方知道 +哪个内置插件拥有该重写逻辑。如果没有任何提供商钩子重写某个受支持的 +Google 家族配置条目,内置的 Google 配置规范化器仍会应用该兼容性清理。 -如果提供商需要完全自定义的线协议或自定义请求执行器, -那属于另一类扩展。这些钩子适用于仍然运行在 OpenClaw -正常推理循环上的提供商行为。 +如果提供商需要完全自定义的线路协议或自定义请求执行器, +那属于另一类扩展。这些钩子适用于仍在 OpenClaw 正常推理循环上运行的 +提供商行为。 ### 提供商示例 @@ -781,111 +786,107 @@ api.registerProvider({ `resolveUsageAuth`、`fetchUsageSnapshot`、`isCacheTtlEligible`、 `resolveThinkingProfile`、`applyConfigDefaults`、`isModernModelRef` 和 `wrapStreamFn`,因为它拥有 Claude 4.6 前向兼容、 - 提供商家族提示、认证修复指导、用量端点集成、 - 提示词缓存可用性、具备认证感知能力的配置默认值、Claude - 默认/自适应思考策略,以及面向 - beta headers、`/fast` / `serviceTier` 和 `context1m` 的 Anthropic 专属流整形能力。 -- Anthropic 的 Claude 专属流辅助工具目前保留在内置插件自身公开的 - `api.ts` / `contract-api.ts` 接缝中。该 package 表面 + 提供商家族提示、认证修复指导、使用情况端点集成、 + 提示词缓存适用性、感知认证的配置默认值、Claude + 默认/自适应 thinking 策略,以及面向 + beta headers、`/fast` / `serviceTier` 和 `context1m` 的 Anthropic 专用流式整形。 +- Anthropic 的 Claude 专用流辅助工具目前保留在该内置插件自己的 + 公共 `api.ts` / `contract-api.ts` 接缝中。该包接口 导出 `wrapAnthropicProviderStream`、`resolveAnthropicBetas`、 `resolveAnthropicFastMode`、`resolveAnthropicServiceTier` 以及更底层的 - Anthropic wrapper builder,而不是围绕某一个 - 提供商的 beta-header 规则扩展通用 SDK。 + Anthropic wrapper builder,而不是仅为了某个提供商的 beta-header 规则去扩大通用 SDK。 - OpenAI 使用 `resolveDynamicModel`、`normalizeResolvedModel` 和 `capabilities`,以及 `buildMissingAuthMessage`、`suppressBuiltInModel`、 `augmentModelCatalog`、`resolveThinkingProfile` 和 `isModernModelRef`, 因为它拥有 GPT-5.4 前向兼容、直接的 OpenAI - `openai-completions` -> `openai-responses` 规范化、面向 Codex 的认证 - 提示、Spark 抑制、合成 OpenAI 列表条目,以及 GPT-5 的思考 / - 实时模型策略;`openai-responses-defaults` 流家族拥有共享的原生 OpenAI Responses 包装器,用于处理归因请求头、 - `/fast`/`serviceTier`、文本冗长度、原生 Codex 网页搜索、 - 推理兼容性负载整形,以及 Responses 上下文管理。 + `openai-completions` -> `openai-responses` 规范化、感知 Codex 的认证 + 提示、Spark 抑制、合成的 OpenAI 列表行,以及 GPT-5 thinking / + 实时模型策略;`openai-responses-defaults` 流家族拥有共享的原生 OpenAI Responses 包装器,用于 attribution headers、 + `/fast`/`serviceTier`、文本 verbosity、原生 Codex Web 搜索、 + 推理兼容负载整形和 Responses 上下文管理。 - OpenRouter 使用 `catalog`,以及 `resolveDynamicModel` 和 - `prepareDynamicModel`,因为该提供商是透传型的,并且可能在 - OpenClaw 静态目录更新之前暴露新的模型 id;它还使用 - `capabilities`、`wrapStreamFn` 和 `isCacheTtlEligible`,以便将 - 提供商专属请求头、路由元数据、推理补丁以及 - 提示词缓存策略放在核心之外。其重放策略来自 + `prepareDynamicModel`,因为该提供商是透传型的,可能会在 + OpenClaw 的静态目录更新前暴露新的模型 ID;它还使用 + `capabilities`、`wrapStreamFn` 和 `isCacheTtlEligible`,以将 + 提供商专用请求头、路由元数据、推理补丁和 + 提示词缓存策略保留在核心之外。其重放策略来自 `passthrough-gemini` 家族,而 `openrouter-thinking` 流家族 拥有代理推理注入以及对不受支持模型 / `auto` 的跳过逻辑。 - GitHub Copilot 使用 `catalog`、`auth`、`resolveDynamicModel` 和 - `capabilities`,以及 `prepareRuntimeAuth` 和 `fetchUsageSnapshot`, - 因为它需要提供商自有的设备登录、模型回退行为、Claude 转录 - 特性、GitHub token -> Copilot token 交换,以及提供商自有的用量端点。 + `capabilities`,以及 `prepareRuntimeAuth` 和 `fetchUsageSnapshot`,因为它 + 需要由提供商拥有的设备登录、模型回退行为、Claude 对话记录 + 差异、GitHub token -> Copilot token 交换,以及由提供商拥有的使用情况端点。 - OpenAI Codex 使用 `catalog`、`resolveDynamicModel`、 `normalizeResolvedModel`、`refreshOAuth` 和 `augmentModelCatalog`,以及 `prepareExtraParams`、`resolveUsageAuth` 和 `fetchUsageSnapshot`,因为它 - 虽然仍运行在核心 OpenAI 传输之上,但拥有自己的传输/base URL + 仍运行在核心 OpenAI 传输之上,但拥有自己的传输/base URL 规范化、OAuth 刷新回退策略、默认传输选择、 - 合成 Codex 目录条目,以及 ChatGPT 用量端点集成;它 - 与直接 OpenAI 共享相同的 `openai-responses-defaults` 流家族。 + 合成 Codex 目录行,以及 ChatGPT 使用情况端点集成;它 + 与直接 OpenAI 共享同一个 `openai-responses-defaults` 流家族。 - Google AI Studio 和 Gemini CLI OAuth 使用 `resolveDynamicModel`、 `buildReplayPolicy`、`sanitizeReplayHistory`、 `resolveReasoningOutputMode`、`wrapStreamFn` 和 `isModernModelRef`,因为 `google-gemini` 重放家族拥有 Gemini 3.1 前向兼容回退、 - 原生 Gemini 重放校验、引导式重放净化、 - 带标签的推理输出模式,以及现代模型匹配,而 + 原生 Gemini 重放校验、bootstrap 重放净化、带标签的 + 推理输出模式以及现代模型匹配,而 `google-thinking` 流家族拥有 Gemini thinking 负载规范化; Gemini CLI OAuth 还使用 `formatApiKey`、`resolveUsageAuth` 和 - `fetchUsageSnapshot`,用于 token 格式化、token 解析以及配额端点 + `fetchUsageSnapshot` 来处理令牌格式化、令牌解析和配额端点 接线。 - Anthropic Vertex 通过 - `anthropic-by-model` 重放家族使用 `buildReplayPolicy`,这样 Claude 专属的重放清理 - 只会限定在 Claude id 上,而不是作用于每个 `anthropic-messages` 传输。 + `anthropic-by-model` 重放家族使用 `buildReplayPolicy`,这样 Claude 专用重放清理就能仅限于 Claude ID,而不是作用于每个 `anthropic-messages` 传输。 - Amazon Bedrock 使用 `buildReplayPolicy`、`matchesContextOverflowError`、 `classifyFailoverReason` 和 `resolveThinkingProfile`,因为它拥有 - 针对 Anthropic-on-Bedrock 流量的 Bedrock 专属限流/未就绪/上下文溢出错误分类; - 其重放策略仍与相同的 - 仅 Claude 的 `anthropic-by-model` 防护共享。 + 面向 Anthropic-on-Bedrock 流量的 Bedrock 专用 throttle/not-ready/context-overflow 错误分类; + 其重放策略仍共享同一个 + 仅限 Claude 的 `anthropic-by-model` 防护。 - OpenRouter、Kilocode、Opencode 和 Opencode Go 通过 `buildReplayPolicy` 使用 `passthrough-gemini` 重放家族,因为它们通过 OpenAI 兼容传输代理 Gemini 模型,并且需要 Gemini thought-signature 净化,而不需要原生 Gemini 重放校验或 - 引导式重写。 + bootstrap 重写。 - MiniMax 通过 `hybrid-anthropic-openai` 重放家族使用 `buildReplayPolicy`,因为一个提供商同时拥有 - Anthropic-message 和 OpenAI 兼容语义;它在 Anthropic 一侧保留仅 Claude 的 - thinking 块丢弃逻辑,同时将推理 + Anthropic-message 和 OpenAI 兼容语义;它会在 Anthropic + 一侧保留仅限 Claude 的 thinking 块丢弃,同时将推理 输出模式覆盖回原生,而 `minimax-fast-mode` 流家族则拥有 共享流路径上的 fast-mode 模型重写。 -- Moonshot 使用 `catalog`、`resolveThinkingProfile` 和 `wrapStreamFn`,因为它仍使用共享的 - OpenAI 传输,但需要提供商自有的 thinking 负载规范化;而 - `moonshot-thinking` 流家族则将配置加上 `/think` 状态映射到其 - 原生的二元 thinking 负载。 +- Moonshot 使用 `catalog`、`resolveThinkingProfile` 和 `wrapStreamFn`,因为它仍然使用共享的 + OpenAI 传输,但需要由提供商拥有的 thinking 负载规范化;`moonshot-thinking` 流家族会将配置和 `/think` 状态映射到其原生的二元 thinking 负载。 - Kilocode 使用 `catalog`、`capabilities`、`wrapStreamFn` 和 - `isCacheTtlEligible`,因为它需要提供商自有的请求头、 - 推理负载规范化、Gemini 转录提示以及 Anthropic + `isCacheTtlEligible`,因为它需要由提供商拥有的请求头、 + 推理负载规范化、Gemini 对话记录提示和 Anthropic 缓存 TTL 门控;`kilocode-thinking` 流家族会在共享代理流路径上保留 Kilo thinking - 注入,同时跳过 `kilo/auto` 和其他 - 不支持显式推理负载的代理模型 id。 + 注入,同时跳过 `kilo/auto` 及其他 + 不支持显式推理负载的代理模型 ID。 - Z.AI 使用 `resolveDynamicModel`、`prepareExtraParams`、`wrapStreamFn`、 `isCacheTtlEligible`、`resolveThinkingProfile`、`isModernModelRef`、 `resolveUsageAuth` 和 `fetchUsageSnapshot`,因为它拥有 GLM-5 回退、 `tool_stream` 默认值、二元 thinking UX、现代模型匹配,以及 - 用量认证和配额获取;`tool-stream-default-on` 流家族则将默认开启的 `tool_stream` 包装器从各提供商手写胶水代码中抽离出来。 + 使用情况认证 + 配额获取;`tool-stream-default-on` 流家族会把默认开启的 `tool_stream` 包装器保留在每提供商手写 glue 之外。 - xAI 使用 `normalizeResolvedModel`、`normalizeTransport`、 `contributeResolvedModelCompat`、`prepareExtraParams`、`wrapStreamFn`、 `resolveSyntheticAuth`、`resolveDynamicModel` 和 `isModernModelRef`, 因为它拥有原生 xAI Responses 传输规范化、Grok fast-mode - 别名重写、默认 `tool_stream`、严格工具 / 推理负载 - 清理、面向插件自有工具的回退认证复用、前向兼容的 Grok - 模型解析,以及提供商自有的兼容性补丁,例如 xAI 工具 schema - 配置、受支持性不足的 schema 关键字、原生 `web_search` 和 HTML 实体 + 别名重写、默认 `tool_stream`、strict-tool / 推理负载 + 清理、对插件拥有工具的回退认证复用、前向兼容的 Grok + 模型解析,以及由提供商拥有的兼容补丁,例如 xAI 工具 schema + 配置、不可支持的 schema 关键字、原生 `web_search` 和 HTML 实体 工具调用参数解码。 - Mistral、OpenCode Zen 和 OpenCode Go 仅使用 `capabilities`, - 以便将转录/工具特性留在核心之外。 -- 仅目录型的内置提供商,例如 `byteplus`、`cloudflare-ai-gateway`、 + 以便将对话记录/工具差异保留在核心之外。 +- 仅目录型内置提供商,例如 `byteplus`、`cloudflare-ai-gateway`、 `huggingface`、`kimi-coding`、`nvidia`、`qianfan`、 - `synthetic`、`together`、`venice`、`vercel-ai-gateway` 和 `volcengine` - 只使用 `catalog`。 -- Qwen 使用 `catalog` 作为其文本提供商能力,同时为其多模态表面注册共享的媒体理解和 - 视频生成能力。 -- MiniMax 和 Xiaomi 使用 `catalog` 加上用量钩子,因为它们的 `/usage` - 行为归插件所有,尽管推理仍通过共享传输运行。 + `synthetic`、`together`、`venice`、`vercel-ai-gateway` 和 `volcengine`,仅使用 + `catalog`。 +- Qwen 对其文本提供商使用 `catalog`,并通过共享的媒体理解和 + 视频生成注册来处理其多模态接口。 +- MiniMax 和 Xiaomi 使用 `catalog` 加上使用情况钩子,因为它们的 `/usage` + 行为归插件所有,即使推理仍通过共享传输运行。 ## 运行时辅助工具 -插件可以通过 `api.runtime` 访问经过挑选的核心辅助工具。对于 TTS: +插件可以通过 `api.runtime` 访问部分核心辅助工具。对于 TTS: ```ts const clip = await api.runtime.tts.textToSpeech({ @@ -904,16 +905,16 @@ const voices = await api.runtime.tts.listVoices({ }); ``` -说明: +注意: -- `textToSpeech` 返回适用于文件/语音便笺表面的常规核心 TTS 输出负载。 +- `textToSpeech` 返回适用于文件/语音便笺界面的正常核心 TTS 输出负载。 - 使用核心 `messages.tts` 配置和提供商选择。 -- 返回 PCM 音频缓冲区 + 采样率。插件必须为各自提供商完成重采样/编码。 -- `listVoices` 对每个提供商而言是可选的。可将其用于供应商自有的语音选择器或设置流程。 -- 语音列表可以包含更丰富的元数据,例如区域设置、性别和个性标签,以供具备提供商感知能力的选择器使用。 -- 当前 OpenAI 和 ElevenLabs 支持电话场景。Microsoft 不支持。 +- 返回 PCM 音频缓冲区 + 采样率。插件必须为提供商重新采样/编码。 +- `listVoices` 对某些提供商而言是可选的。可将其用于供应商拥有的语音选择器或设置流程。 +- 语音列表可以包含更丰富的元数据,例如 locale、gender 和 personality tags,以便用于感知提供商的选择器。 +- 当前 OpenAI 和 ElevenLabs 支持电话语音。Microsoft 不支持。 -插件也可以通过 `api.registerSpeechProvider(...)` 注册语音提供商。 +插件还可以通过 `api.registerSpeechProvider(...)` 注册语音提供商。 ```ts api.registerSpeechProvider({ @@ -931,14 +932,14 @@ api.registerSpeechProvider({ }); ``` -说明: +注意: - 将 TTS 策略、回退和回复投递保留在核心中。 -- 使用语音提供商来承载供应商自有的合成行为。 -- 旧式 Microsoft `edge` 输入会被规范化为 `microsoft` 提供商 id。 -- 更推荐的归属模型是面向公司:随着 OpenClaw 增加这些 - 能力契约,一个供应商插件可以同时拥有 - 文本、语音、图像和未来的媒体提供商能力。 +- 使用语音提供商处理由供应商拥有的合成行为。 +- 旧版 Microsoft `edge` 输入会规范化为 `microsoft` provider id。 +- 首选的归属模型是面向公司的:随着 OpenClaw 添加这些 + 能力契约,一个供应商插件可以拥有文本、语音、图像和未来媒体 + 提供商。 对于图像/音频/视频理解,插件会注册一个类型化的 媒体理解提供商,而不是通用的键值包: @@ -953,13 +954,13 @@ api.registerMediaUnderstandingProvider({ }); ``` -说明: +注意: - 将编排、回退、配置和渠道接线保留在核心中。 - 将供应商行为保留在提供商插件中。 - 增量扩展应保持类型化:新的可选方法、新的可选 结果字段、新的可选能力。 -- 视频生成已经遵循同样的模式: +- 视频生成已经遵循相同模式: - 核心拥有能力契约和运行时辅助工具 - 供应商插件注册 `api.registerVideoGenerationProvider(...)` - 功能/渠道插件消费 `api.runtime.videoGeneration.*` @@ -986,17 +987,16 @@ const video = await api.runtime.mediaUnderstanding.describeVideoFile({ const { text } = await api.runtime.mediaUnderstanding.transcribeAudioFile({ filePath: "/tmp/inbound-audio.ogg", cfg: api.config, - // 当无法可靠推断 MIME 时可选: + // Optional when MIME cannot be inferred reliably: mime: "audio/ogg", }); ``` -说明: +注意: -- `api.runtime.mediaUnderstanding.*` 是图像/音频/视频理解 - 首选的共享表面。 +- `api.runtime.mediaUnderstanding.*` 是图像/音频/视频理解的首选共享接口。 - 使用核心媒体理解音频配置(`tools.media.audio`)和提供商回退顺序。 -- 当没有生成转录输出时(例如输入被跳过/不受支持),返回 `{ text: undefined }`。 +- 当未产生转录输出时,返回 `{ text: undefined }`(例如输入被跳过/不受支持)。 - `api.runtime.stt.transcribeAudioFile(...)` 仍保留为兼容性别名。 插件还可以通过 `api.runtime.subagent` 启动后台子智能体运行: @@ -1011,16 +1011,16 @@ const result = await api.runtime.subagent.run({ }); ``` -说明: +注意: -- `provider` 和 `model` 是每次运行的可选覆盖项,而不是持久化的会话更改。 -- OpenClaw 只会对受信任调用方应用这些覆盖字段。 -- 对于插件自有的回退运行,运维人员必须通过 `plugins.entries..subagent.allowModelOverride: true` 显式启用。 -- 使用 `plugins.entries..subagent.allowedModels` 可将受信任插件限制为特定的规范 `provider/model` 目标,或使用 `"*"` 明确允许任意目标。 +- `provider` 和 `model` 是每次运行的可选覆盖,不是持久化的会话变更。 +- OpenClaw 仅对受信任的调用方应用这些覆盖字段。 +- 对于插件拥有的回退运行,运维人员必须通过 `plugins.entries..subagent.allowModelOverride: true` 显式启用。 +- 使用 `plugins.entries..subagent.allowedModels` 将受信任插件限制为特定的规范 `provider/model` 目标,或使用 `"*"` 显式允许任意目标。 - 不受信任的插件子智能体运行仍然可用,但覆盖请求会被拒绝,而不是静默回退。 -对于网页搜索,插件可以消费共享运行时辅助工具,而不是 -直接深入智能体工具接线: +对于 Web 搜索,插件可以消费共享运行时辅助工具,而不是 +深入智能体工具接线: ```ts const providers = api.runtime.webSearch.listProviders({ @@ -1036,14 +1036,14 @@ const result = await api.runtime.webSearch.search({ }); ``` -插件也可以通过 -`api.registerWebSearchProvider(...)` 注册网页搜索提供商。 +插件还可以通过 +`api.registerWebSearchProvider(...)` 注册 Web 搜索提供商。 -说明: +注意: - 将提供商选择、凭证解析和共享请求语义保留在核心中。 -- 使用网页搜索提供商来承载供应商专属搜索传输。 -- `api.runtime.webSearch.*` 是首选的共享表面,适用于需要搜索行为但不依赖智能体工具包装器的功能/渠道插件。 +- 使用 Web 搜索提供商处理供应商专用搜索传输。 +- `api.runtime.webSearch.*` 是需要搜索行为而又不依赖智能体工具包装器的功能/渠道插件的首选共享接口。 ### `api.runtime.imageGeneration` @@ -1081,31 +1081,31 @@ api.registerHttpRoute({ 路由字段: - `path`:Gateway 网关 HTTP 服务器下的路由路径。 -- `auth`:必填。使用 `"gateway"` 以要求普通 Gateway 网关认证,或使用 `"plugin"` 以启用插件管理的认证/webhook 校验。 +- `auth`:必填。使用 `"gateway"` 表示要求常规 Gateway 网关认证,或使用 `"plugin"` 表示插件自管认证/webhook 校验。 - `match`:可选。`"exact"`(默认)或 `"prefix"`。 -- `replaceExisting`:可选。允许同一个插件替换自己现有的路由注册。 -- `handler`:当路由处理了请求时返回 `true`。 +- `replaceExisting`:可选。允许同一个插件替换自己已有的路由注册。 +- `handler`:当路由已处理请求时返回 `true`。 -说明: +注意: - `api.registerHttpHandler(...)` 已被移除,并会导致插件加载错误。请改用 `api.registerHttpRoute(...)`。 - 插件路由必须显式声明 `auth`。 -- 除非设置了 `replaceExisting: true`,否则精确的 `path + match` 冲突会被拒绝,并且一个插件不能替换另一个插件的路由。 -- 具有不同 `auth` 级别的重叠路由会被拒绝。仅在相同认证级别下保留 `exact`/`prefix` 回退链。 -- `auth: "plugin"` 路由**不会**自动接收运维人员运行时作用域。它们用于插件管理的 webhook/签名校验,而不是特权 Gateway 网关辅助调用。 -- `auth: "gateway"` 路由运行在 Gateway 网关请求运行时作用域内,但该作用域被有意保持为保守模式: - - 共享密钥 bearer 认证(`gateway.auth.mode = "token"` / `"password"`)会将插件路由运行时作用域固定为 `operator.write`,即使调用方发送了 `x-openclaw-scopes` - - 带有受信任身份信息的 HTTP 模式(例如 `trusted-proxy` 或私有入口上的 `gateway.auth.mode = "none"`)仅在显式存在该请求头时才会尊重 `x-openclaw-scopes` - - 如果这些带身份信息的插件路由请求缺少 `x-openclaw-scopes`,运行时作用域会回退到 `operator.write` -- 实际规则:不要假设一个使用 gateway 认证的插件路由天然就是管理员表面。如果你的路由需要仅管理员可用的行为,请要求使用带身份信息的认证模式,并记录显式的 `x-openclaw-scopes` 请求头契约。 +- 完全相同的 `path + match` 冲突会被拒绝,除非设置了 `replaceExisting: true`,并且一个插件不能替换另一个插件的路由。 +- 具有不同 `auth` 级别的重叠路由会被拒绝。仅在相同认证级别下保留 `exact`/`prefix` 级联链。 +- `auth: "plugin"` 路由**不会**自动获得运维人员运行时作用域。它们用于插件自管的 webhook/签名校验,而不是特权的 Gateway 网关辅助调用。 +- `auth: "gateway"` 路由会在 Gateway 网关请求运行时作用域内运行,但该作用域是有意保守的: + - 共享密钥 bearer 认证(`gateway.auth.mode = "token"` / `"password"`)会将插件路由运行时作用域固定为 `operator.write`,即使调用方发送了 `x-openclaw-scopes` 也是如此 + - 受信任的带身份 HTTP 模式(例如 `trusted-proxy` 或私有入口上的 `gateway.auth.mode = "none"`)仅会在显式提供该请求头时应用 `x-openclaw-scopes` + - 如果这些带身份的插件路由请求中缺少 `x-openclaw-scopes`,运行时作用域会回退到 `operator.write` +- 实用规则:不要假设通过 gateway-auth 的插件路由天然就是管理员接口。如果你的路由需要仅管理员可用的行为,请要求使用带身份的认证模式,并记录明确的 `x-openclaw-scopes` 请求头契约。 ## 插件 SDK 导入路径 -在编写插件时,请使用 SDK 子路径,而不是使用单体式的 `openclaw/plugin-sdk` 导入: +在编写插件时,请使用 SDK 子路径,而不是整体式的 `openclaw/plugin-sdk` 导入: -- `openclaw/plugin-sdk/plugin-entry` 用于插件注册原语。 -- `openclaw/plugin-sdk/core` 用于通用共享的面向插件契约。 -- `openclaw/plugin-sdk/config-schema` 用于根 `openclaw.json` Zod schema +- `openclaw/plugin-sdk/plugin-entry`:用于插件注册原语。 +- `openclaw/plugin-sdk/core`:用于通用共享的面向插件契约。 +- `openclaw/plugin-sdk/config-schema`:用于根级 `openclaw.json` Zod schema 导出(`OpenClawSchema`)。 - 稳定的渠道原语,例如 `openclaw/plugin-sdk/channel-setup`、 `openclaw/plugin-sdk/setup-runtime`、 @@ -1118,15 +1118,15 @@ api.registerHttpRoute({ `openclaw/plugin-sdk/channel-lifecycle`、 `openclaw/plugin-sdk/channel-reply-pipeline`、 `openclaw/plugin-sdk/command-auth`、 - `openclaw/plugin-sdk/secret-input` 以及 + `openclaw/plugin-sdk/secret-input` 和 `openclaw/plugin-sdk/webhook-ingress`,用于共享设置/认证/回复/webhook - 接线。`channel-inbound` 是防抖、提及匹配、 + 接线。`channel-inbound` 是 debounce、提及匹配、 入站提及策略辅助工具、信封格式化以及入站信封 上下文辅助工具的共享归属位置。 - `channel-setup` 是狭窄的可选安装设置接缝。 + `channel-setup` 是狭义的可选安装设置接缝。 `setup-runtime` 是 `setupEntry` / - 延迟启动所使用的运行时安全设置表面,其中包括导入安全的设置补丁适配器。 - `setup-adapter-runtime` 是具备环境感知能力的账户设置适配器接缝。 + 延迟启动使用的运行时安全设置接口,包括对导入安全的设置补丁适配器。 + `setup-adapter-runtime` 是感知环境变量的账户设置适配器接缝。 `setup-tools` 是小型 CLI/归档/文档辅助工具接缝(`formatCliCommand`、 `detectBinary`、`extractArchive`、`resolveBrewExecutable`、`formatDocsLink`、 `CONFIG_DIR`)。 @@ -1147,115 +1147,112 @@ api.registerHttpRoute({ `openclaw/plugin-sdk/routing`、 `openclaw/plugin-sdk/status-helpers`、 `openclaw/plugin-sdk/text-runtime`、 - `openclaw/plugin-sdk/runtime-store` 以及 + `openclaw/plugin-sdk/runtime-store` 和 `openclaw/plugin-sdk/directory-runtime`,用于共享运行时/配置辅助工具。 `telegram-command-config` 是 Telegram 自定义 - 命令规范化/校验的狭窄公开接缝,即使内置的 - Telegram 契约表面暂时不可用,它仍会保持可用。 - `text-runtime` 是共享的文本/Markdown/日志接缝,其中包括 - 面向助手可见文本的剥离、Markdown 渲染/分块辅助工具、脱敏 + 命令规范化/校验的狭义公共接缝,即使内置 + Telegram 契约接口暂时不可用,它仍然可用。 + `text-runtime` 是共享的文本/Markdown/日志接缝,包括 + 助手可见文本剥离、Markdown 渲染/分块辅助工具、脱敏 辅助工具、directive-tag 辅助工具以及安全文本工具。 -- 审批专用的渠道接缝应优先在插件上使用单一的 `approvalCapability` +- 审批专用渠道接缝应优先在插件上使用一个 `approvalCapability` 契约。然后核心会通过这一项能力读取审批认证、投递、渲染、 - 原生路由和惰性原生处理器行为,而不是将审批行为混入无关的插件字段中。 -- `openclaw/plugin-sdk/channel-runtime` 已弃用,当前仅作为 - 旧插件的兼容性 shim 保留。新代码应改用更狭窄的 - 通用原语导入,而仓库代码不应新增对该 shim 的导入。 + 原生路由和延迟原生处理器行为,而不是把审批行为混进不相关的插件字段中。 +- `openclaw/plugin-sdk/channel-runtime` 已弃用,只作为 + 旧插件的兼容性 shim 保留。新代码应改为导入更狭义的 + 通用原语,仓库代码也不应新增对该 shim 的导入。 - 内置扩展内部实现仍然是私有的。外部插件应只使用 - `openclaw/plugin-sdk/*` 子路径。OpenClaw 核心/测试代码可以使用 - 插件 package 根目录下的仓库公开入口点,例如 `index.js`、`api.js`、 - `runtime-api.js`、`setup-entry.js` 以及狭窄范围的文件,例如 - `login-qr-api.js`。绝不要从核心或另一个扩展中导入某个插件 package 的 `src/*`。 + `openclaw/plugin-sdk/*` 子路径。OpenClaw 核心/测试代码可以使用插件包根目录下的仓库公共入口点,例如 `index.js`、`api.js`、 + `runtime-api.js`、`setup-entry.js`,以及狭义文件,例如 + `login-qr-api.js`。绝不要从核心或其他扩展中导入某个插件包的 `src/*`。 - 仓库入口点拆分: `/api.js` 是辅助工具/类型 barrel, `/runtime-api.js` 是仅运行时 barrel, `/index.js` 是内置插件入口, `/setup-entry.js` 是设置插件入口。 - 当前内置提供商示例: - - Anthropic 使用 `api.js` / `contract-api.js` 提供 Claude 流辅助工具,例如 - `wrapAnthropicProviderStream`、beta-header 辅助工具以及 `service_tier` + - Anthropic 使用 `api.js` / `contract-api.js` 处理 Claude 流辅助工具,例如 + `wrapAnthropicProviderStream`、beta-header 辅助工具和 `service_tier` 解析。 - - OpenAI 使用 `api.js` 提供 provider builder、默认模型辅助工具以及 - realtime provider builder。 - - OpenRouter 使用 `api.js` 提供其 provider builder 以及新手引导/配置 - 辅助工具,而 `register.runtime.js` 仍可为仓库本地用途重新导出通用 + - OpenAI 使用 `api.js` 处理提供商 builder、默认模型辅助工具和 + 实时提供商 builder。 + - OpenRouter 使用 `api.js` 处理其提供商 builder 以及新手引导/配置 + 辅助工具,而 `register.runtime.js` 仍可为仓库内本地使用重新导出通用 `plugin-sdk/provider-stream` 辅助工具。 -- 由 facade 加载的公开入口点在存在活动运行时配置快照时会优先使用该快照, - 否则当 OpenClaw 尚未提供运行时快照时,会回退到磁盘上已解析的配置文件。 -- 通用共享原语仍然是首选的公开 SDK 契约。仍然存在一小组保留的、兼容性用途的内置渠道品牌化辅助工具接缝。请将这些视为内置维护/兼容性接缝,而不是新的第三方导入目标;新的跨渠道契约仍应落在通用 `plugin-sdk/*` 子路径或插件本地 `api.js` / +- facade 加载的公共入口点在存在活动运行时配置快照时优先使用它, + 否则在 OpenClaw 尚未提供运行时快照时回退到磁盘上的解析后配置文件。 +- 通用共享原语仍然是首选的公共 SDK 契约。仍然存在一小组保留的、带内置渠道品牌的辅助工具接缝,用于兼容性。请将这些视为内置维护/兼容接缝,而不是新的第三方导入目标;新的跨渠道契约仍应落在通用 `plugin-sdk/*` 子路径或插件本地 `api.js` / `runtime-api.js` barrel 上。 兼容性说明: - 新代码应避免使用根级 `openclaw/plugin-sdk` barrel。 -- 优先使用狭窄且稳定的原语。较新的 setup/pairing/reply/ +- 优先使用狭义且稳定的原语。较新的 setup/pairing/reply/ feedback/contract/inbound/threading/command/secret-input/webhook/infra/ - allowlist/status/message-tool 子路径,才是新的 - 内置和外部插件工作的预期契约。 - 目标解析/匹配应放在 `openclaw/plugin-sdk/channel-targets` 上。 + allowlist/status/message-tool 子路径,是新内置和外部插件工作的预期契约。 + 目标解析/匹配应放在 `openclaw/plugin-sdk/channel-targets`。 消息操作门控和 reaction message-id 辅助工具应放在 - `openclaw/plugin-sdk/channel-actions` 上。 -- 内置扩展专用的辅助 barrel 默认并不稳定。如果某个 - 辅助工具只被内置扩展需要,应将其保留在扩展本地的 - `api.js` 或 `runtime-api.js` 接缝之后,而不是提升到 + `openclaw/plugin-sdk/channel-actions`。 +- 默认情况下,内置扩展专用辅助工具 barrel 并不稳定。如果某个 + 辅助工具只被某个内置扩展需要,请将其保留在该扩展本地的 `api.js` 或 `runtime-api.js` 接缝后面,而不是将其提升到 `openclaw/plugin-sdk/` 中。 -- 新的共享辅助工具接缝应当是通用的,而不是带渠道品牌的。共享目标 - 解析应放在 `openclaw/plugin-sdk/channel-targets`;渠道专属 - 内部实现则保留在归属插件本地的 `api.js` 或 `runtime-api.js` - 接缝之后。 +- 新的共享辅助工具接缝应是通用的,而不是带渠道品牌的。共享目标 + 解析应放在 `openclaw/plugin-sdk/channel-targets`;渠道专用 + 内部实现应保留在归属插件的本地 `api.js` 或 `runtime-api.js` + 接缝后面。 - `image-generation`、 - `media-understanding` 和 `speech` 等能力专属子路径之所以存在,是因为今天 - 内置/原生插件正在使用它们。它们的存在本身并不意味着每个导出的辅助工具 - 都是长期冻结的外部契约。 + `media-understanding` 和 `speech` 等能力专用子路径之所以存在,是因为内置/原生插件 + 当前就在使用它们。它们的存在本身并不意味着每个导出的辅助工具都是长期冻结的外部契约。 -## 消息工具 schema +## Message 工具 schema -对于 reaction、已读和投票等非消息原语, -插件应拥有渠道专属的 `describeMessageTool(...)` schema -贡献。共享发送展示应使用通用 `MessagePresentation` 契约, -而不是提供商原生的按钮、组件、区块或卡片字段。 -有关该契约、回退规则、提供商映射以及插件作者检查清单,请参见 [Message Presentation](/zh-CN/plugins/message-presentation)。 +插件应拥有针对非消息原语(例如 reactions、已读和 polls)的 +渠道专用 `describeMessageTool(...)` schema +贡献。共享发送展示应使用通用的 `MessagePresentation` 契约, +而不是提供商原生的 button、component、block 或 card 字段。 +契约、回退规则、提供商映射和插件作者检查清单,请参见 [Message Presentation](/zh-CN/plugins/message-presentation)。 -具备发送能力的插件通过消息能力声明自己可以渲染什么: +具备发送能力的插件通过消息能力声明其可渲染内容: -- `presentation`:语义化展示区块(`text`、`context`、`divider`、`buttons`、`select`) -- `delivery-pin`:置顶投递请求 +- `presentation`:用于语义化展示块(`text`、`context`、`divider`、`buttons`、`select`) +- `delivery-pin`:用于固定投递请求 核心决定是原生渲染该展示,还是将其降级为文本。 -不要从通用消息工具中暴露提供商原生 UI 的逃逸口。 -面向旧原生 schema 的已弃用 SDK 辅助工具仍会为现有 -第三方插件导出,但新插件不应使用它们。 +不要从通用 message 工具中暴露提供商原生 UI 逃生口。 +为旧版原生 schema 保留的已弃用 SDK 辅助工具仍会导出,以兼容现有 +第三方插件,但新插件不应使用它们。 ## 渠道目标解析 -渠道插件应拥有渠道专属的目标语义。保持共享出站宿主通用, -并通过消息适配器表面处理提供商规则: +渠道插件应拥有渠道专用的目标语义。请保持共享 +出站宿主是通用的,并使用消息适配器接口处理提供商规则: -- `messaging.inferTargetChatType({ to })` 用于决定一个已规范化目标 +- `messaging.inferTargetChatType({ to })` 决定规范化目标 在目录查找前应被视为 `direct`、`group` 还是 `channel`。 -- `messaging.targetResolver.looksLikeId(raw, normalized)` 用于告诉核心, - 某个输入是否应直接跳到类似 id 的解析,而不是进行目录搜索。 -- `messaging.targetResolver.resolveTarget(...)` 是插件回退路径, - 当核心在规范化后或目录未命中后需要最终的提供商自有解析时使用。 -- `messaging.resolveOutboundSessionRoute(...)` 用于在目标解析完成后, - 拥有提供商专属的会话路由构造逻辑。 +- `messaging.targetResolver.looksLikeId(raw, normalized)` 告诉核心某个 + 输入是否应直接跳到类似 ID 的解析,而不是目录搜索。 +- `messaging.targetResolver.resolveTarget(...)` 是在 + 规范化后或目录未命中后,核心需要最终由提供商拥有的解析时,插件使用的回退路径。 +- `messaging.resolveOutboundSessionRoute(...)` 在目标解析完成后 + 拥有提供商专用的会话路由构造逻辑。 推荐拆分: -- 对于应在搜索 peers/groups 之前完成的分类决策,使用 `inferTargetChatType`。 -- 对于“将此视为显式/原生目标 id”的检查,使用 `looksLikeId`。 -- 将 `resolveTarget` 用于提供商专属的规范化回退,而不是广泛的目录搜索。 -- 将 chat id、thread id、JID、handle 和 room id 等提供商原生 id 保留在 `target` 值或提供商专属参数中,而不是放入通用 SDK 字段。 +- 对于应在搜索 peers/groups 之前发生的类别决策,使用 `inferTargetChatType`。 +- 对于“将其视为显式/原生目标 ID”的检查,使用 `looksLikeId`。 +- 将 `resolveTarget` 用于提供商专用规范化回退,而不是广泛的目录搜索。 +- 将聊天 ID、线程 ID、JID、handle 和房间 + ID 等提供商原生 ID 保留在 `target` 值或提供商专用参数中,而不是放在通用 SDK 字段中。 -## 基于配置的目录 +## 配置支持的目录 -如果插件从配置中派生目录条目,请将该逻辑保留在 -插件内部,并复用 +如果插件从配置派生目录条目,请将该逻辑保留在 +插件中,并复用 `openclaw/plugin-sdk/directory-runtime` 中的共享辅助工具。 -适用于渠道需要基于配置的 peers/groups 的场景,例如: +当某个渠道需要配置支持的 peers/groups 时,请使用这种方式,例如: -- 基于 allowlist 驱动的私信 peers +- 由允许列表驱动的私信 peers - 已配置的渠道/群组映射 - 按账户划分的静态目录回退 @@ -1266,69 +1263,68 @@ api.registerHttpRoute({ - 去重/规范化辅助工具 - 构建 `ChannelDirectoryEntry[]` -渠道专属的账户检查和 id 规范化仍应保留在 +渠道专用的账户检查和 ID 规范化应保留在 插件实现中。 ## 提供商目录 提供商插件可以通过 -`registerProvider({ catalog: { run(...) { ... } } })` 定义用于推理的模型目录。 +`registerProvider({ catalog: { run(...) { ... } } })` 为推理定义模型目录。 `catalog.run(...)` 返回与 OpenClaw 写入 `models.providers` 相同的结构: -- `{ provider }`:一个提供商条目 +- `{ provider }`:单个提供商条目 - `{ providers }`:多个提供商条目 -当插件拥有提供商专属的模型 id、base URL 默认值,或需要认证门控的模型元数据时,请使用 `catalog`。 +当插件拥有提供商专用模型 ID、base URL 默认值或受认证控制的模型元数据时,请使用 `catalog`。 -`catalog.order` 控制插件目录相对于 OpenClaw 内置隐式提供商的合并时机: +`catalog.order` 控制插件目录相对于 OpenClaw +内置隐式提供商的合并时机: -- `simple`:普通 API key 或环境变量驱动的提供商 -- `profile`:存在认证配置文件时出现的提供商 -- `paired`:合成多个相关提供商条目的提供商 +- `simple`:普通 API 密钥或环境变量驱动的提供商 +- `profile`:当存在认证配置文件时出现的提供商 +- `paired`:会合成多个相关提供商条目的提供商 - `late`:最后一轮,在其他隐式提供商之后 -后出现的提供商在键冲突时获胜,因此插件可以有意使用相同 provider id 覆盖内置提供商条目。 +后出现的提供商在键冲突时获胜,因此插件可以有意用相同 provider id 覆盖内置提供商条目。 兼容性: -- `discovery` 仍可作为旧式别名使用 +- `discovery` 仍可作为旧版别名使用 - 如果同时注册了 `catalog` 和 `discovery`,OpenClaw 会使用 `catalog` ## 只读渠道检查 -如果你的插件注册了一个渠道,建议在 `resolveAccount(...)` 之外,同时实现 -`plugin.config.inspectAccount(cfg, accountId)`。 +如果你的插件注册了一个渠道,请优先实现 +`plugin.config.inspectAccount(cfg, accountId)`,并与 `resolveAccount(...)` 一起提供。 原因: -- `resolveAccount(...)` 是运行时路径。它可以假定凭证 - 已被完全实体化,并且在缺少所需密钥时快速失败。 +- `resolveAccount(...)` 是运行时路径。它可以假设凭证 + 已完全实体化,并且在缺少必需密钥时快速失败。 - 只读命令路径,例如 `openclaw status`、`openclaw status --all`、 - `openclaw channels status`、`openclaw channels resolve`,以及 doctor/config - 修复流程,不应为了描述配置而需要实体化运行时凭证。 + `openclaw channels status`、`openclaw channels resolve`,以及 Doctor/配置 + 修复流程,不应为了描述配置而必须实体化运行时凭证。 推荐的 `inspectAccount(...)` 行为: -- 仅返回描述性的账户状态。 +- 只返回描述性的账户状态。 - 保留 `enabled` 和 `configured`。 - 在相关时包含凭证来源/状态字段,例如: - `tokenSource`、`tokenStatus` - `botTokenSource`、`botTokenStatus` - `appTokenSource`、`appTokenStatus` - `signingSecretSource`、`signingSecretStatus` -- 你不需要为了报告只读可用性而返回原始 token 值。 - 返回 `tokenStatus: "available"`(以及对应的来源字段) - 就足以满足状态类命令。 -- 当凭证通过 SecretRef 配置、但在当前命令路径中不可用时, - 使用 `configured_unavailable`。 +- 你不需要为了报告只读 + 可用性而返回原始令牌值。对于类似状态的命令,返回 `tokenStatus: "available"`(以及匹配的来源字段)就足够了。 +- 当凭证通过 SecretRef 配置,但在当前命令路径中不可用时,请使用 `configured_unavailable`。 -这样一来,只读命令就可以报告“已配置,但在当前命令路径中不可用”,而不是崩溃或错误地将该账户报告为未配置。 +这样可以让只读命令报告“已配置但在当前命令路径中不可用”,而不是崩溃或错误地将该账户报告为未配置。 -## Package packs +## 包集合 -一个插件目录可以包含带有 `openclaw.extensions` 的 `package.json`: +插件目录可以包含一个带有 `openclaw.extensions` 的 `package.json`: ```json { @@ -1340,59 +1336,60 @@ api.registerHttpRoute({ } ``` -每个条目都会成为一个插件。如果该 pack 列出多个扩展,则插件 id +每个条目都会成为一个插件。如果该包列出了多个扩展,插件 id 会变成 `name/`。 -如果你的插件导入了 npm 依赖,请在该目录中安装它们, -以便 `node_modules` 可用(`npm install` / `pnpm install`)。 +如果你的插件导入了 npm 依赖,请在该目录中安装它们,以便 +`node_modules` 可用(`npm install` / `pnpm install`)。 -安全护栏:每个 `openclaw.extensions` 条目在解析符号链接后都必须保留在插件 -目录内。逃逸出 package 目录的条目会被拒绝。 +安全护栏:每个 `openclaw.extensions` 条目在解析 symlink 后都必须保留在插件 +目录内。逃逸出包目录的条目会被拒绝。 安全说明:`openclaw plugins install` 会使用 -`npm install --omit=dev --ignore-scripts` 安装插件依赖(无生命周期脚本,运行时无开发依赖)。请保持插件依赖树为“纯 JS/TS”,并避免依赖需要 `postinstall` 构建的 package。 +`npm install --omit=dev --ignore-scripts` 安装插件依赖(无生命周期脚本,运行时不安装 dev dependencies)。请保持插件依赖 +树为“纯 JS/TS”,并避免需要 `postinstall` 构建的包。 可选:`openclaw.setupEntry` 可以指向一个轻量级的仅设置模块。 -当 OpenClaw 需要为一个已禁用的渠道插件提供设置表面时,或 -当某个渠道插件已启用但尚未配置时,它会加载 `setupEntry` -而不是完整插件入口。这样可以在你的主插件入口还会接线工具、钩子或其他仅运行时代码时, -让启动和设置过程更轻量。 +当 OpenClaw 需要为一个已禁用的渠道插件提供设置接口时,或者 +当某个渠道插件已启用但仍未配置时,它会加载 `setupEntry` +而不是完整插件入口。这样可以在你的主插件入口还会接线工具、钩子或其他仅运行时代码时,让启动和设置更轻量。 可选:`openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen` -可以让渠道插件在 Gateway 网关监听前的启动阶段,即便该渠道已完成配置, -也选择使用同样的 `setupEntry` 路径。 +可以让某个渠道插件在 Gateway 网关的 +监听前启动阶段,即使渠道已经配置好,也选择使用相同的 `setupEntry` 路径。 -仅当 `setupEntry` 完整覆盖了 Gateway 网关开始监听前必须存在的启动表面时, -才应使用此项。实际上,这意味着设置入口 -必须注册启动所依赖的每一个渠道自有能力,例如: +只有当 `setupEntry` 完全覆盖了 gateway 开始监听前 +必须存在的启动接口时,才使用此选项。实践中,这意味着设置入口 +必须注册启动所依赖的每一项渠道拥有能力,例如: - 渠道注册本身 -- 任何必须在 Gateway 网关开始监听前可用的 HTTP 路由 -- 任何在同一时间窗口内必须存在的 Gateway 网关方法、工具或服务 +- 任何必须在 gateway 开始监听前可用的 HTTP 路由 +- 任何在同一时间窗口内必须存在的 gateway 方法、工具或服务 如果你的完整入口仍然拥有任何必需的启动能力,请不要启用 -此标志。保持插件默认行为,并让 OpenClaw 在启动期间加载完整入口。 +此标志。保持插件使用默认行为,并让 OpenClaw 在启动期间加载 +完整入口。 -内置渠道还可以发布仅设置用的契约表面辅助工具,供核心在完整渠道运行时加载前进行查询。当前的设置 -提升表面是: +内置渠道还可以发布仅设置用的契约接口辅助工具,以便核心 +在完整渠道运行时加载前进行查询。当前的设置 +提升接口是: - `singleAccountKeysToMove` - `namedAccountPromotionKeys` - `resolveSingleAccountPromotionTarget(...)` -当核心需要在不加载完整插件入口的情况下,将旧式单账户渠道 -配置提升到 `channels..accounts.*` 时,会使用这一表面。 -Matrix 是当前的内置示例:当已存在命名账户时,它只会将认证/引导键移动到 -某个命名提升账户中,并且它可以保留一个已配置的非规范默认账户键,而不是始终创建 +当核心需要在不加载完整插件入口的情况下,将旧版单账户渠道 +配置提升到 `channels..accounts.*` 时,会使用该接口。 +Matrix 是当前的内置示例:当已存在具名账户时,它只会将认证/bootstrap 键移动到某个已提升的具名账户中,并且可以保留已配置的非规范默认账户键,而不是总是创建 `accounts.default`。 -这些设置补丁适配器会让内置契约表面发现保持惰性。导入时 -保持轻量;提升表面只会在首次使用时加载,而不是在模块导入时重新进入内置渠道启动流程。 +这些设置补丁适配器让内置契约接口发现保持懒加载。导入 +时间保持轻量;提升接口只会在首次使用时加载,而不会在模块导入时重新进入内置渠道启动流程。 -当这些启动表面包含 Gateway 网关 RPC 方法时,请将它们保留在 -插件专属前缀下。核心管理员命名空间(`config.*`、 -`exec.approvals.*`、`wizard.*`、`update.*`)仍然是保留的,并且始终解析 -为 `operator.admin`,即使某个插件请求更窄的作用域也是如此。 +当这些启动接口包含 Gateway 网关 RPC 方法时,请将它们保留在 +插件专用前缀下。核心管理命名空间(`config.*`、 +`exec.approvals.*`、`wizard.*`、`update.*`)仍然保留,并且总是解析 +为 `operator.admin`,即使某个插件请求了更窄的作用域也是如此。 示例: @@ -1411,8 +1408,7 @@ Matrix 是当前的内置示例:当已存在命名账户时,它只会将认 ### 渠道目录元数据 -渠道插件可以通过 `openclaw.channel` 宣告设置/发现元数据,并通过 -`openclaw.install` 宣告安装提示。这使核心目录保持无数据化。 +渠道插件可以通过 `openclaw.channel` 广告设置/发现元数据,并通过 `openclaw.install` 提供安装提示。这样可以让核心目录不携带数据。 示例: @@ -1440,23 +1436,23 @@ Matrix 是当前的内置示例:当已存在命名账户时,它只会将认 } ``` -除最小示例外,其他有用的 `openclaw.channel` 字段包括: +除最小示例外,有用的 `openclaw.channel` 字段还包括: -- `detailLabel`:用于更丰富目录/状态表面的次级标签 +- `detailLabel`:用于更丰富目录/状态界面的次级标签 - `docsLabel`:用于覆盖文档链接的链接文本 -- `preferOver`:此目录条目应优先于的低优先级插件/渠道 id -- `selectionDocsPrefix`、`selectionDocsOmitLabel`、`selectionExtras`:选择表面的文案控制项 -- `markdownCapable`:将该渠道标记为支持 Markdown,以用于出站格式化决策 -- `exposure.configured`:设置为 `false` 时,在已配置渠道列表表面中隐藏该渠道 -- `exposure.setup`:设置为 `false` 时,在交互式设置/配置选择器中隐藏该渠道 -- `exposure.docs`:将该渠道标记为内部/私有,用于文档导航表面 -- `showConfigured` / `showInSetup`:为兼容性仍接受的旧式别名;优先使用 `exposure` +- `preferOver`:该目录条目应优先于的低优先级 plugin/channel id +- `selectionDocsPrefix`、`selectionDocsOmitLabel`、`selectionExtras`:选择界面文案控制 +- `markdownCapable`:将该渠道标记为支持 Markdown,用于出站格式化决策 +- `exposure.configured`:设为 `false` 时,在已配置渠道列表界面中隐藏该渠道 +- `exposure.setup`:设为 `false` 时,在交互式设置/配置选择器中隐藏该渠道 +- `exposure.docs`:在文档导航界面中将该渠道标记为内部/私有 +- `showConfigured` / `showInSetup`:旧版别名,出于兼容性仍然接受;优先使用 `exposure` - `quickstartAllowFrom`:让该渠道加入标准快速开始 `allowFrom` 流程 - `forceAccountBinding`:即使只存在一个账户,也要求显式账户绑定 -- `preferSessionLookupForAnnounceTarget`:在解析 announce 目标时优先使用会话查找 +- `preferSessionLookupForAnnounceTarget`:在解析公告目标时优先使用会话查找 OpenClaw 还可以合并**外部渠道目录**(例如 MPM -注册表导出)。将 JSON 文件放到以下位置之一: +注册表导出)。将 JSON 文件放到以下任一位置: - `~/.openclaw/mpm/plugins.json` - `~/.openclaw/mpm/catalog.json` @@ -1464,18 +1460,17 @@ OpenClaw 还可以合并**外部渠道目录**(例如 MPM 或者将 `OPENCLAW_PLUGIN_CATALOG_PATHS`(或 `OPENCLAW_MPM_CATALOG_PATHS`)指向 一个或多个 JSON 文件(以逗号/分号/`PATH` 分隔)。每个文件应 -包含 `{ "entries": [ { "name": "@scope/pkg", "openclaw": { "channel": {...}, "install": {...} } } ] }`。解析器也接受 `"packages"` 或 `"plugins"` 作为 -`"entries"` 键的旧式别名。 +包含 `{ "entries": [ { "name": "@scope/pkg", "openclaw": { "channel": {...}, "install": {...} } } ] }`。解析器也接受 `"packages"` 或 `"plugins"` 作为 `"entries"` 键的旧版别名。 ## 上下文引擎插件 上下文引擎插件拥有会话上下文编排,负责摄取、组装 -和压缩。使用 -`api.registerContextEngine(id, factory)` 从你的插件中注册它们,然后通过 +和压缩。通过 +`api.registerContextEngine(id, factory)` 从你的插件中注册它们,然后用 `plugins.slots.contextEngine` 选择活动引擎。 当你的插件需要替换或扩展默认上下文 -流水线,而不仅仅是增加 memory search 或钩子时,请使用此方式。 +流水线,而不是仅仅添加 memory 搜索或钩子时,请使用这种方式。 ```ts import { buildMemorySystemPromptAddition } from "openclaw/plugin-sdk/core"; @@ -1541,44 +1536,44 @@ export default function (api) { ## 添加新能力 -当插件需要当前 API 不适配的行为时,不要通过私有穿透方式绕过 -插件系统。请添加缺失的能力。 +当某个插件需要当前 API 无法容纳的行为时,不要通过私有深入访问 +绕过插件系统。请添加缺失的能力。 推荐顺序: 1. 定义核心契约 - 决定哪些共享行为应由核心拥有:策略、回退、配置合并、 - 生命周期、面向渠道的语义,以及运行时辅助工具形态。 -2. 添加类型化的插件注册/运行时表面 + 决定应由核心拥有的共享行为:策略、回退、配置合并、 + 生命周期、面向渠道的语义,以及运行时辅助工具结构。 +2. 添加类型化的插件注册/运行时接口 使用最小但有用的 - 类型化能力表面扩展 `OpenClawPluginApi` 和/或 `api.runtime`。 -3. 接线核心 + 渠道/功能消费者 - 渠道和功能插件应通过核心消费该新能力, + 类型化能力接口扩展 `OpenClawPluginApi` 和/或 `api.runtime`。 +3. 对接核心 + 渠道/功能使用方 + 渠道和功能插件应通过核心消费新能力, 而不是直接导入某个供应商实现。 4. 注册供应商实现 - 然后由供应商插件将其后端注册到该能力上。 + 然后由供应商插件针对该能力注册其后端。 5. 添加契约覆盖 - 添加测试,以便随着时间推移,归属和注册形态仍保持明确。 + 添加测试,使归属和注册结构能够随着时间推移保持明确。 -这就是 OpenClaw 如何在保持鲜明设计立场的同时,不被硬编码到某个 -供应商的世界观上。具体文件检查清单和完整示例,请参见 [能力扩展手册](/zh-CN/plugins/architecture)。 +这就是 OpenClaw 在保持有主见的同时,又不会被硬编码到某一个 +提供商世界观中的方式。具体文件清单和示例请参见 [能力扩展手册](/zh-CN/plugins/architecture)。 ### 能力检查清单 -当你添加一个新能力时,通常实现应同时触及以下 -表面: +当你添加一个新能力时,通常应同时涉及以下 +接口: - `src//types.ts` 中的核心契约类型 -- `src//runtime.ts` 中的核心运行器/运行时辅助工具 -- `src/plugins/types.ts` 中的插件 API 注册表面 +- `src//runtime.ts` 中的核心 runner/运行时辅助工具 +- `src/plugins/types.ts` 中的插件 API 注册接口 - `src/plugins/registry.ts` 中的插件注册表接线 -- `src/plugins/runtime/*` 中的插件运行时暴露,当功能/渠道 - 插件需要消费它时 +- 当功能/渠道 + 插件需要消费它时,位于 `src/plugins/runtime/*` 的插件运行时暴露 - `src/test-utils/plugin-registration.ts` 中的捕获/测试辅助工具 - `src/plugins/contracts/registry.ts` 中的归属/契约断言 - `docs/` 中的运维人员/插件文档 -如果这些表面中有某一项缺失,通常意味着这个能力 +如果缺少其中某个接口,通常说明该能力 尚未完全集成。 ### 能力模板 @@ -1615,7 +1610,7 @@ const clip = await api.runtime.videoGeneration.generate({ expect(findVideoGenerationProviderIdsForPlugin("openai")).toEqual(["openai"]); ``` -这让规则保持简单: +这样可以保持规则简单: - 核心拥有能力契约 + 编排 - 供应商插件拥有供应商实现 diff --git a/docs/zh-CN/plugins/bundles.md b/docs/zh-CN/plugins/bundles.md index 286b2fc86..28c301d43 100644 --- a/docs/zh-CN/plugins/bundles.md +++ b/docs/zh-CN/plugins/bundles.md @@ -1,35 +1,42 @@ --- read_when: - - 你想安装一个与 Codex、Claude 或 Cursor 兼容的套件 - - 你需要了解 OpenClaw 如何将套件内容映射到原生功能 - - 你正在调试套件检测或缺失的能力 -summary: 将 Codex、Claude 和 Cursor 套件安装并作为 OpenClaw 插件使用 -title: 插件套件 + - 你想安装一个兼容 Codex、Claude 或 Cursor 的套装 + - 你需要了解 OpenClaw 如何将套装内容映射到原生功能 + - 你正在调试套装检测或缺失的能力 +summary: 将 Codex、Claude 和 Cursor 套装作为 OpenClaw plugin 安装并使用 +title: Plugin 套装 x-i18n: - generated_at: "2026-04-22T23:49:43Z" + generated_at: "2026-04-23T07:06:20Z" model: gpt-5.4 provider: openai - source_hash: 91fec13cb1f807231c706318f3e81e27b350d5a0266821cb96c8494c45f01de0 + source_hash: 8c9e48738e059c302157dd8733178109cf34840f32a3d7b5b767ac019fbc581b source_path: plugins/bundles.md workflow: 15 --- -# 插件套件 +# Plugin 套装 -OpenClaw 可以从三个外部生态系统安装插件:**Codex**、**Claude** 和 **Cursor**。这些被称为 **套件** —— 内容和元数据包,OpenClaw 会将其映射到 Skills、hooks 和 MCP 工具等原生功能中。 +OpenClaw 可以从三个外部生态安装 plugin:**Codex**、**Claude**、 +和 **Cursor**。这些被称为 **套装** —— 即内容与元数据包,OpenClaw +会将其映射为原生功能,例如 skills、hooks 和 MCP 工具。 - 套件**不同于**原生 OpenClaw 插件。原生插件在进程内运行,并且可以注册任何能力。套件是内容包,只支持选择性的功能映射,并且信任边界更窄。 + 套装**不**等同于原生 OpenClaw plugin。原生 plugin 在进程内运行, + 可以注册任意能力。套装是内容包,只支持选择性的功能映射,并且 + 具有更窄的信任边界。 -## 为什么需要套件 +## 为什么会有套装 -许多实用插件以 Codex、Claude 或 Cursor 格式发布。OpenClaw 不要求作者将它们重写为原生 OpenClaw 插件,而是会检测这些格式,并将其中受支持的内容映射到原生功能集中。这意味着你可以安装一个 Claude 命令包或一个 Codex Skills 套件,并立即使用它。 +许多有用的 plugin 是以 Codex、Claude 或 Cursor 格式发布的。OpenClaw +不会要求作者将它们重写为原生 OpenClaw plugin,而是会检测这些格式, +并将其中受支持的内容映射到原生功能集中。这意味着你可以安装 Claude +命令包或 Codex skill 套装,并立即使用它。 -## 安装一个套件 +## 安装套装 - + ```bash # 本地目录 openclaw plugins install ./my-bundle @@ -37,7 +44,7 @@ OpenClaw 可以从三个外部生态系统安装插件:**Codex**、**Claude** # 归档文件 openclaw plugins install ./my-bundle.tgz - # Claude 市场 + # Claude marketplace openclaw plugins marketplace list openclaw plugins install @ ``` @@ -50,7 +57,7 @@ OpenClaw 可以从三个外部生态系统安装插件:**Codex**、**Claude** openclaw plugins inspect ``` - 套件会显示为 `Format: bundle`,其子类型为 `codex`、`claude` 或 `cursor`。 + 套装会显示为 `Format: bundle`,其子类型为 `codex`、`claude` 或 `cursor`。 @@ -59,50 +66,55 @@ OpenClaw 可以从三个外部生态系统安装插件:**Codex**、**Claude** openclaw gateway restart ``` - 映射后的功能(Skills、hooks、MCP 工具、LSP 默认值)会在下一个会话中可用。 + 已映射的功能(skills、hooks、MCP 工具、LSP 默认值)会在下一个会话中可用。 -## OpenClaw 会从套件中映射哪些内容 +## OpenClaw 会从套装中映射什么 -并非套件中的每个功能目前都能在 OpenClaw 中运行。下面列出了当前可用的功能,以及那些已检测到但尚未接线启用的功能。 +并不是套装中的每项功能当前都能在 OpenClaw 中运行。下面说明了哪些功能 +当前可用,哪些功能虽能被检测到但尚未接线。 ### 当前支持 | 功能 | 映射方式 | 适用范围 | | ------------- | ------------------------------------------------------------------------------------------- | -------------- | -| Skill 内容 | 套件的 Skill 根目录会作为普通 OpenClaw Skills 加载 | 所有格式 | -| Commands | `commands/` 和 `.cursor/commands/` 会被视为 Skill 根目录 | Claude、Cursor | +| Skill 内容 | 套装 skill 根目录会像普通 OpenClaw Skills 一样加载 | 所有格式 | +| 命令 | `commands/` 和 `.cursor/commands/` 被视为 skill 根目录 | Claude、Cursor | | Hook 包 | OpenClaw 风格的 `HOOK.md` + `handler.ts` 布局 | Codex | -| MCP 工具 | 套件 MCP 配置会合并到内置 Pi 设置中;支持的 stdio 和 HTTP 服务器会被加载 | 所有格式 | -| LSP 服务器 | Claude 的 `.lsp.json` 和清单中声明的 `lspServers` 会合并到内置 Pi 的 LSP 默认值中 | Claude | -| Settings | Claude 的 `settings.json` 会作为内置 Pi 默认值导入 | Claude | +| MCP 工具 | 套装 MCP 配置会合并到内置 Pi 设置中;支持的 stdio 和 HTTP 服务器会被加载 | 所有格式 | +| LSP 服务器 | Claude `.lsp.json` 和清单中声明的 `lspServers` 会合并到内置 Pi 的 LSP 默认值中 | Claude | +| 设置 | Claude `settings.json` 会作为内置 Pi 默认值导入 | Claude | #### Skill 内容 -- 套件的 Skill 根目录会作为普通 OpenClaw Skill 根目录加载 -- Claude 的 `commands` 根目录会被视为额外的 Skill 根目录 -- Cursor 的 `.cursor/commands` 根目录会被视为额外的 Skill 根目录 +- 套装 skill 根目录会像普通 OpenClaw skill 根目录一样加载 +- Claude `commands` 根目录会被视为附加的 skill 根目录 +- Cursor `.cursor/commands` 根目录会被视为附加的 skill 根目录 -这意味着 Claude 的 Markdown 命令文件会通过普通的 OpenClaw Skills 加载器运行。Cursor 的命令 Markdown 文件也会通过同一路径运行。 +这意味着 Claude Markdown 命令文件会通过普通的 OpenClaw skill +加载器运行。Cursor 命令 Markdown 也通过同一路径运行。 #### Hook 包 -- 只有当套件的 hook 根目录使用普通的 OpenClaw hook 包布局时,才会生效 - 。目前主要是与 Codex 兼容的情况: +- 只有当套装 hook 根目录使用普通的 OpenClaw hook-pack + 布局时,套装 hook 根目录才会工作。当前这主要是兼容 Codex 的情况: - `HOOK.md` - `handler.ts` 或 `handler.js` #### 用于 Pi 的 MCP -- 已启用的套件可以提供 MCP 服务器配置 -- OpenClaw 会将套件的 MCP 配置合并到生效中的内置 Pi 设置中,键名为 +- 已启用的套装可以提供 MCP 服务器配置 +- OpenClaw 会将套装 MCP 配置合并到生效的内置 Pi 设置中,键名为 `mcpServers` -- OpenClaw 会在内置 Pi 智能体轮次中,通过启动 stdio 服务器或连接到 HTTP 服务器,暴露受支持的套件 MCP 工具 -- `coding` 和 `messaging` 工具配置默认包含套件 MCP 工具;如需禁用,可为某个智能体或 Gateway 网关使用 `tools.deny: ["bundle-mcp"]` -- 在套件默认值之后,项目级本地 Pi 设置仍然会生效,因此在需要时,工作区设置可以覆盖套件的 MCP 条目 -- 在注册之前,套件 MCP 工具目录会按确定性顺序排序,因此上游 `listTools()` 顺序的变化不会导致 prompt-cache 工具块频繁抖动 +- OpenClaw 会在内置 Pi 智能体回合期间公开受支持的套装 MCP 工具,方式是 + 启动 stdio 服务器或连接到 HTTP 服务器 +- `coding` 和 `messaging` 工具配置默认包含套装 MCP 工具;可使用 `tools.deny: ["bundle-mcp"]` 为某个智能体或 Gateway 网关选择退出 +- 项目本地 Pi 设置仍会在套装默认值之后生效,因此在需要时, + 工作区设置可以覆盖套装 MCP 条目 +- 套装 MCP 工具目录在注册前会按确定性顺序排序,因此上游 + `listTools()` 顺序变化不会扰动 prompt-cache 工具块 ##### 传输协议 @@ -124,7 +136,7 @@ MCP 服务器可以使用 stdio 或 HTTP 传输协议: } ``` -**HTTP** 默认通过 `sse` 连接到正在运行的 MCP 服务器;如有请求,也可以使用 `streamable-http`: +**HTTP** 会连接到一个正在运行的 MCP 服务器,默认使用 `sse`,如有请求则使用 `streamable-http`: ```json { @@ -143,30 +155,35 @@ MCP 服务器可以使用 stdio 或 HTTP 传输协议: } ``` -- `transport` 可以设置为 `"streamable-http"` 或 `"sse"`;省略时,OpenClaw 使用 `sse` -- 仅允许 `http:` 和 `https:` URL 协议 +- `transport` 可设置为 `"streamable-http"` 或 `"sse"`;省略时,OpenClaw 使用 `sse` +- 仅允许 `http:` 和 `https:` URL scheme - `headers` 的值支持 `${ENV_VAR}` 插值 -- 如果一个服务器条目同时包含 `command` 和 `url`,则会被拒绝 -- URL 凭证(userinfo 和查询参数)会从工具描述和日志中被脱敏 -- `connectionTimeoutMs` 会覆盖 stdio 和 HTTP 传输协议默认的 30 秒连接超时时间 +- 同时包含 `command` 和 `url` 的服务器条目会被拒绝 +- URL 凭证(userinfo 和查询参数)会从工具 + 描述和日志中脱敏 +- `connectionTimeoutMs` 会覆盖默认的 30 秒连接超时, + 对 stdio 和 HTTP 传输协议都生效 ##### 工具命名 -OpenClaw 会使用对提供商安全的名称来注册套件 MCP 工具,格式为 -`serverName__toolName`。例如,一个键名为 `"vigil-harbor"` 且暴露了 -`memory_search` 工具的服务器,会被注册为 `vigil-harbor__memory_search`。 +OpenClaw 会以提供商安全的名称格式注册套装 MCP 工具: +`serverName__toolName`。例如,键名为 `"vigil-harbor"` 的服务器公开了一个 +`memory_search` 工具,它会注册为 `vigil-harbor__memory_search`。 - `A-Za-z0-9_-` 之外的字符会被替换为 `-` -- 服务器名前缀最长为 30 个字符 +- 服务器前缀最长为 30 个字符 - 完整工具名最长为 64 个字符 -- 空的服务器名会回退为 `mcp` -- 冲突的清洗后名称会通过数字后缀进行区分 -- 最终暴露的工具顺序会按安全名称确定性排序,以保持重复 Pi 轮次的缓存稳定 -- 配置过滤会将来自同一个套件 MCP 服务器的所有工具都视为由 `bundle-mcp` 拥有的插件,因此配置允许列表和拒绝列表可以包含单个暴露的工具名称,也可以包含 `bundle-mcp` 插件键 +- 空服务器名会回退为 `mcp` +- 发生清洗后重名时,会使用数字后缀消歧 +- 最终公开的工具顺序会按安全名称确定性排序,以保持重复的 Pi + 回合在缓存上稳定 +- 配置过滤会将来自同一个套装 MCP 服务器的所有工具视为由 + `bundle-mcp` plugin 拥有,因此配置 allowlist 和 deny list 可以包含 + 单个公开工具名,也可以包含 `bundle-mcp` plugin 键 #### 内置 Pi 设置 -- 启用套件时,Claude 的 `settings.json` 会作为默认内置 Pi 设置导入 +- 启用套装后,Claude `settings.json` 会作为默认内置 Pi 设置导入 - OpenClaw 会在应用前清洗 shell 覆盖键 已清洗的键: @@ -176,32 +193,34 @@ OpenClaw 会使用对提供商安全的名称来注册套件 MCP 工具,格式 #### 内置 Pi LSP -- 已启用的 Claude 套件可以提供 LSP 服务器配置 -- OpenClaw 会加载 `.lsp.json` 以及清单中声明的任何 `lspServers` 路径 -- 套件 LSP 配置会合并到生效中的内置 Pi LSP 默认值中 -- 目前只有受支持的基于 stdio 的 LSP 服务器可以运行;不受支持的传输协议仍会显示在 `openclaw plugins inspect ` 中 +- 已启用的 Claude 套装可以提供 LSP 服务器配置 +- OpenClaw 会加载 `.lsp.json` 以及清单中声明的所有 `lspServers` 路径 +- 套装 LSP 配置会合并到生效的内置 Pi LSP 默认值中 +- 当前只有受支持的基于 stdio 的 LSP 服务器可以运行;不受支持的 + 传输协议仍会显示在 `openclaw plugins inspect ` 中 ### 已检测到但不会执行 这些内容会被识别并显示在诊断信息中,但 OpenClaw 不会运行它们: -- Claude 的 `agents`、`hooks.json` 自动化、`outputStyles` -- Cursor 的 `.cursor/agents`、`.cursor/hooks.json`、`.cursor/rules` -- Codex 的内联/应用元数据(能力报告之外的部分) +- Claude `agents`、`hooks.json` 自动化、`outputStyles` +- Cursor `.cursor/agents`、`.cursor/hooks.json`、`.cursor/rules` +- Codex 行内/应用元数据(能力报告之外的部分) -## 套件格式 +## 套装格式 - + 标记:`.codex-plugin/plugin.json` 可选内容:`skills/`、`hooks/`、`.mcp.json`、`.app.json` - 当 Codex 套件使用 Skill 根目录和 OpenClaw 风格的 hook 包目录(`HOOK.md` + `handler.ts`)时,最适合 OpenClaw。 + 当 Codex 套装使用 skill 根目录和 OpenClaw 风格的 + hook-pack 目录(`HOOK.md` + `handler.ts`)时,与 OpenClaw 最契合。 - + 两种检测模式: - **基于清单:** `.claude-plugin/plugin.json` @@ -209,21 +228,21 @@ OpenClaw 会使用对提供商安全的名称来注册套件 MCP 工具,格式 Claude 特有行为: - - `commands/` 会被视为 Skill 内容 + - `commands/` 被视为 skill 内容 - `settings.json` 会导入到内置 Pi 设置中(shell 覆盖键会被清洗) - - `.mcp.json` 会向内置 Pi 暴露受支持的 stdio 工具 + - `.mcp.json` 会向内置 Pi 公开受支持的 stdio 工具 - `.lsp.json` 加上清单中声明的 `lspServers` 路径会加载到内置 Pi LSP 默认值中 - `hooks/hooks.json` 会被检测到,但不会执行 - - 清单中的自定义组件路径是增量添加的(它们会扩展默认值,而不是替换默认值) + - 清单中的自定义组件路径是增量式的(扩展默认值,而不是替换默认值) - + 标记:`.cursor-plugin/plugin.json` 可选内容:`skills/`、`.cursor/commands/`、`.cursor/agents/`、`.cursor/rules/`、`.cursor/hooks.json`、`.mcp.json` - - `.cursor/commands/` 会被视为 Skill 内容 + - `.cursor/commands/` 被视为 skill 内容 - `.cursor/rules/`、`.cursor/agents/` 和 `.cursor/hooks.json` 仅检测,不执行 @@ -231,46 +250,64 @@ OpenClaw 会使用对提供商安全的名称来注册套件 MCP 工具,格式 ## 检测优先级 -OpenClaw 会先检查原生插件格式: +OpenClaw 会先检查原生 plugin 格式: -1. `openclaw.plugin.json` 或带有 `openclaw.extensions` 的有效 `package.json` —— 视为**原生插件** -2. 套件标记(`.codex-plugin/`、`.claude-plugin/` 或默认 Claude/Cursor 布局)—— 视为**套件** +1. `openclaw.plugin.json` 或带有 `openclaw.extensions` 的有效 `package.json` —— 视为**原生 plugin** +2. 套装标记(`.codex-plugin/`、`.claude-plugin/` 或默认 Claude/Cursor 布局)—— 视为**套装** -如果一个目录同时包含两者,OpenClaw 会使用原生路径。这可以防止双格式包被部分作为套件安装。 +如果一个目录同时包含两者,OpenClaw 会使用原生路径。这样可以防止 +双格式包被部分地当作套装安装。 + +## 运行时依赖与清理 + +- 内置 plugin 的运行时依赖会随 OpenClaw 包一起发布,位于 + `dist/*` 下。OpenClaw **不会**在启动时为内置 + plugin 运行 `npm install`;发布流水线负责提供完整的内置 + 依赖负载(参见 + [发布](/zh-CN/reference/RELEASING) 中的 postpublish 校验规则)。 +- 启动套装 MCP 服务器的子智能体运行,会在子智能体退出时通过共享的 + 运行时清理路径释放这些 MCP 客户端,因此 + 子智能体生命周期不会在多个回合之间泄漏 stdio 子进程或长期存活的 MCP + 连接。 ## 安全性 -与原生插件相比,套件的信任边界更窄: +与原生 plugin 相比,套装具有更窄的信任边界: -- OpenClaw **不会**在进程内加载任意套件运行时模块 -- Skills 和 hook 包路径必须保留在插件根目录内(带边界检查) -- Settings 文件会使用相同的边界检查来读取 -- 受支持的 stdio MCP 服务器可以作为子进程启动 +- OpenClaw **不会**在进程内加载任意套装运行时模块 +- Skills 和 hook-pack 路径必须保持在 plugin 根目录内(带边界检查) +- 设置文件会使用相同的边界检查进行读取 +- 受支持的 stdio MCP 服务器可能会作为子进程启动 -这让套件在默认情况下更安全,但对于第三方套件,你仍应将其视为对其所暴露功能具有可信访问权限的内容。 +这使套装在默认情况下更安全,但对于它们所暴露功能所涉及的第三方 +套装内容,你仍应将其视为受信任内容。 ## 故障排除 - - 运行 `openclaw plugins inspect `。如果某项能力被列出,但标记为未接线启用,那是产品限制——并不是安装损坏。 + + 运行 `openclaw plugins inspect `。如果某项能力已列出,但标记为 + 未接线,那是产品限制——并非安装损坏。 - - 请确认套件已启用,并且 Markdown 文件位于已检测到的 `commands/` 或 `skills/` 根目录中。 + + 请确认套装已启用,并且 Markdown 文件位于已检测到的 + `commands/` 或 `skills/` 根目录中。 - - 仅支持来自 `settings.json` 的内置 Pi 设置。OpenClaw 不会将套件设置视为原始配置补丁。 + + 当前仅支持来自 `settings.json` 的内置 Pi 设置。OpenClaw 不会 + 将套装设置视为原始配置补丁。 - `hooks/hooks.json` 仅用于检测。如果你需要可运行的 hooks,请使用 OpenClaw hook 包布局,或者提供一个原生插件。 + `hooks/hooks.json` 仅检测,不执行。如果你需要可运行的 hooks,请使用 + OpenClaw hook-pack 布局,或提供原生 plugin。 ## 相关内容 -- [安装和配置插件](/zh-CN/tools/plugin) -- [构建插件](/zh-CN/plugins/building-plugins) —— 创建一个原生插件 -- [插件清单](/zh-CN/plugins/manifest) —— 原生清单模式 +- [安装并配置 Plugins](/zh-CN/tools/plugin) +- [构建 Plugins](/zh-CN/plugins/building-plugins) — 创建原生 plugin +- [Plugin 清单](/zh-CN/plugins/manifest) — 原生清单 schema diff --git a/docs/zh-CN/plugins/codex-harness.md b/docs/zh-CN/plugins/codex-harness.md index e61709e9a..4e430c8ef 100644 --- a/docs/zh-CN/plugins/codex-harness.md +++ b/docs/zh-CN/plugins/codex-harness.md @@ -1,59 +1,75 @@ --- read_when: - - 你想使用内置的 Codex app-server 测试框架 + - 你想使用内置的 Codex app-server harness - 你需要 Codex 模型引用和配置示例 - 你想为仅使用 Codex 的部署禁用 PI 回退 -summary: 通过内置的 Codex app-server 测试框架运行 OpenClaw 嵌入式智能体回合 -title: Codex 测试框架 +summary: 通过内置的 Codex app-server harness 运行 OpenClaw 嵌入式智能体回合 +title: Codex Harness x-i18n: - generated_at: "2026-04-23T02:13:11Z" + generated_at: "2026-04-23T07:06:26Z" model: gpt-5.4 provider: openai - source_hash: dc2acc3dc906d12e12a837a25a52ec0e72d44325786106771045d456e6327040 + source_hash: f5eff5a2af66033d575bc05c9f31a23ed0367bedc518dc25364e60a3012bfdff source_path: plugins/codex-harness.md workflow: 15 --- -# Codex 测试框架 +# Codex Harness -内置的 `codex` 插件让 OpenClaw 通过 Codex app-server,而不是内置的 PI 测试框架,来运行嵌入式智能体回合。 +内置的 `codex` 插件允许 OpenClaw 通过 Codex app-server 运行嵌入式智能体回合,而不是使用内置的 PI harness。 -当你希望由 Codex 接管底层智能体会话时,请使用此方式:模型发现、原生线程恢复、原生压缩,以及 app-server 执行。 -OpenClaw 仍然负责聊天渠道、会话文件、模型选择、工具、审批、媒体传递,以及可见的转录镜像。 +当你希望由 Codex 接管低层智能体会话时,请使用它:模型发现、原生线程恢复、原生压缩,以及 app-server 执行。 +OpenClaw 仍然负责聊天渠道、会话文件、模型选择、工具、 +审批、媒体投递,以及可见的转录镜像。 -原生 Codex 回合同样遵循共享的 `before_prompt_build`、`before_compaction` 和 `after_compaction` 插件钩子,因此提示词垫片和具备压缩感知能力的自动化可以与 PI 测试框架保持一致。 -原生 Codex 回合同样遵循共享的 `before_prompt_build`、`before_compaction`、`after_compaction`、`llm_input`、`llm_output` 和 `agent_end` 插件钩子,因此提示词垫片、具备压缩感知能力的自动化,以及生命周期观察器都可以与 PI 测试框架保持一致。 +原生 Codex 回合同样遵循共享插件钩子,因此 prompt shim、 +压缩感知自动化、工具中间件和生命周期观察器都能与 PI harness 保持一致: -该测试框架默认关闭。只有在启用 `codex` 插件且解析后的模型为 `codex/*` 模型时,或者你显式强制设置 `embeddedHarness.runtime: "codex"` 或 `OPENCLAW_AGENT_RUNTIME=codex` 时,才会选用它。 -如果你从未配置 `codex/*`,现有的 PI、OpenAI、Anthropic、Gemini、本地和自定义提供商运行将保持当前行为。 +- `before_prompt_build` +- `before_compaction`, `after_compaction` +- `llm_input`, `llm_output` +- `tool_result`, `after_tool_call` +- `before_message_write` +- `agent_end` + +内置插件还可以注册一个 Codex app-server 扩展工厂,以添加 +异步 `tool_result` 中间件,而镜像的 Codex 转录写入会通过 `before_message_write` 路由。 + +该 harness 默认关闭。只有在启用了 `codex` 插件并且解析后的模型是 `codex/*` 模型时, +或者你显式强制设置 `embeddedHarness.runtime: "codex"` 或 `OPENCLAW_AGENT_RUNTIME=codex` 时,才会选择它。 +如果你从未配置 `codex/*`,现有的 PI、OpenAI、Anthropic、Gemini、local +和自定义 provider 运行将保持当前行为。 ## 选择正确的模型前缀 -OpenClaw 为 OpenAI 访问和 Codex 形态访问提供了不同的路由: +OpenClaw 为 OpenAI 访问和 Codex 形态访问提供了不同路径: -| 模型引用 | 运行时路径 | 适用场景 | -| ---------------------- | -------------------------------------------- | ----------------------------------------------------------------------- | -| `openai/gpt-5.4` | 通过 OpenClaw/PI 管线的 OpenAI 提供商 | 你希望使用 `OPENAI_API_KEY` 直接访问 OpenAI Platform API。 | -| `openai-codex/gpt-5.4` | 通过 PI 的 OpenAI Codex OAuth 提供商 | 你希望使用 ChatGPT/Codex OAuth,而不使用 Codex app-server 测试框架。 | -| `codex/gpt-5.4` | 内置 Codex 提供商加 Codex 测试框架 | 你希望为嵌入式智能体回合使用原生 Codex app-server 执行。 | +| 模型引用 | 运行时路径 | 适用场景 | +| ---------------------- | ------------------------------------------ | ------------------------------------------------------------------------ | +| `openai/gpt-5.4` | 通过 OpenClaw/PI 管线的 OpenAI provider | 你希望使用 `OPENAI_API_KEY` 直接访问 OpenAI Platform API。 | +| `openai-codex/gpt-5.4` | 通过 PI 的 OpenAI Codex OAuth provider | 你希望使用 ChatGPT/Codex OAuth,但不使用 Codex app-server harness。 | +| `codex/gpt-5.4` | 内置 Codex provider + Codex harness | 你希望嵌入式智能体回合使用原生 Codex app-server 执行。 | -Codex 测试框架只接管 `codex/*` 模型引用。现有的 `openai/*`、`openai-codex/*`、Anthropic、Gemini、xAI、本地和自定义提供商引用将继续使用其正常路径。 +Codex harness 只接管 `codex/*` 模型引用。现有的 `openai/*`、 +`openai-codex/*`、Anthropic、Gemini、xAI、local 和自定义 provider 引用会保持 +其正常路径。 ## 要求 - OpenClaw,并且可用内置的 `codex` 插件。 - Codex app-server `0.118.0` 或更高版本。 -- app-server 进程可用的 Codex 凭证。 +- app-server 进程可用的 Codex 认证。 -该插件会阻止较旧或未带版本信息的 app-server 握手。 -这样可以确保 OpenClaw 运行在其已针对的协议表面上。 +该插件会阻止过旧或未带版本信息的 app-server 握手。 +这样可以确保 OpenClaw 运行在其已测试过的协议表面之上。 -对于 live 和 Docker 冒烟测试,凭证通常来自 `OPENAI_API_KEY`,以及可选的 Codex CLI 文件,例如 `~/.codex/auth.json` 和 -`~/.codex/config.toml`。请使用与你本地 Codex app-server 相同的凭证材料。 +对于 live 和 Docker smoke 测试,认证通常来自 `OPENAI_API_KEY`,以及 +可选的 Codex CLI 文件,例如 `~/.codex/auth.json` 和 +`~/.codex/config.toml`。请使用与你本地 Codex app-server 相同的认证材料。 ## 最小配置 -使用 `codex/gpt-5.4`,启用内置插件,并强制使用 `codex` 测试框架: +使用 `codex/gpt-5.4`,启用内置插件,并强制使用 `codex` harness: ```json5 { @@ -76,7 +92,7 @@ Codex 测试框架只接管 `codex/*` 模型引用。现有的 `openai/*`、`ope } ``` -如果你的配置使用 `plugins.allow`,也请把 `codex` 包含进去: +如果你的配置使用 `plugins.allow`,也请将 `codex` 包含进去: ```json5 { @@ -91,11 +107,14 @@ Codex 测试框架只接管 `codex/*` 模型引用。现有的 `openai/*`、`ope } ``` -将 `agents.defaults.model` 或某个智能体模型设置为 `codex/` 也会自动启用内置的 `codex` 插件。显式的插件条目在共享配置中仍然有用,因为它能明确表明部署意图。 +将 `agents.defaults.model` 或某个智能体模型设置为 `codex/` 也会 +自动启用内置的 `codex` 插件。显式插件条目在共享配置中仍然很有用, +因为它能清楚表明部署意图。 -## 在不替换其他模型的情况下添加 Codex +## 添加 Codex 而不替换其他模型 -如果你希望 `codex/*` 模型使用 Codex,而其他所有模型继续使用 PI,请保持 `runtime: "auto"`: +如果你希望 `codex/*` 模型使用 Codex,而其他所有模型使用 PI, +请保持 `runtime: "auto"`: ```json5 { @@ -127,16 +146,16 @@ Codex 测试框架只接管 `codex/*` 模型引用。现有的 `openai/*`、`ope } ``` -采用这种形式时: +在这种配置下: -- `/model codex` 或 `/model codex/gpt-5.4` 使用 Codex app-server 测试框架。 -- `/model gpt` 或 `/model openai/gpt-5.4` 使用 OpenAI 提供商路径。 -- `/model opus` 使用 Anthropic 提供商路径。 -- 如果选择的是非 Codex 模型,PI 仍然是兼容性测试框架。 +- `/model codex` 或 `/model codex/gpt-5.4` 使用 Codex app-server harness。 +- `/model gpt` 或 `/model openai/gpt-5.4` 使用 OpenAI provider 路径。 +- `/model opus` 使用 Anthropic provider 路径。 +- 如果选择了非 Codex 模型,PI 仍然是兼容性 harness。 ## 仅使用 Codex 的部署 -当你需要证明每个嵌入式智能体回合都使用 Codex 测试框架时,请禁用 PI 回退: +当你需要证明每个嵌入式智能体回合都使用 Codex harness 时,请禁用 PI 回退: ```json5 { @@ -160,11 +179,14 @@ OPENCLAW_AGENT_HARNESS_FALLBACK=none \ openclaw gateway run ``` -禁用回退后,如果 Codex 插件被禁用、请求的模型不是 `codex/*` 引用、app-server 版本过旧,或者 app-server 无法启动,OpenClaw 会尽早失败。 +在禁用回退的情况下,如果 Codex 插件被禁用、 +请求的模型不是 `codex/*` 引用、app-server 版本过旧,或者 +app-server 无法启动,OpenClaw 会提前失败。 ## 按智能体使用 Codex -你可以让某一个智能体仅使用 Codex,同时默认智能体继续保留普通的自动选择: +你可以让某一个智能体仅使用 Codex,而默认智能体仍保持正常的 +自动选择: ```json5 { @@ -195,11 +217,14 @@ openclaw gateway run } ``` -使用常规会话命令切换智能体和模型。`/new` 会创建一个全新的 OpenClaw 会话,而 Codex 测试框架会根据需要创建或恢复其 sidecar app-server 线程。`/reset` 会清除该线程的 OpenClaw 会话绑定。 +使用常规会话命令切换智能体和模型。`/new` 会创建一个新的 +OpenClaw 会话,而 Codex harness 会按需创建或恢复其 sidecar app-server +线程。`/reset` 会清除该线程的 OpenClaw 会话绑定。 ## 模型发现 -默认情况下,`codex` 插件会向 app-server 请求可用模型。如果发现失败或超时,它会使用内置的回退目录: +默认情况下,Codex 插件会向 app-server 查询可用模型。如果 +发现失败或超时,它会使用内置的回退目录: - `codex/gpt-5.4` - `codex/gpt-5.4-mini` @@ -225,7 +250,8 @@ openclaw gateway run } ``` -当你希望启动时避免探测 Codex,并固定使用回退目录时,请禁用发现: +当你希望启动时避免探测 Codex,并固定使用回退目录时, +请禁用发现: ```json5 { @@ -246,17 +272,19 @@ openclaw gateway run ## App-server 连接和策略 -默认情况下,该插件会通过以下方式在本地启动 Codex: +默认情况下,插件会使用以下命令在本地启动 Codex: ```bash codex app-server --listen stdio:// ``` -默认情况下,OpenClaw 会以 YOLO 模式启动本地 Codex 测试框架会话: +默认情况下,OpenClaw 以 YOLO 模式启动本地 Codex harness 会话: `approvalPolicy: "never"`、`approvalsReviewer: "user"`,以及 -`sandbox: "danger-full-access"`。这是用于自主心跳的受信任本地操作员姿态:Codex 可以使用 shell 和网络工具,而不会停在无人响应的原生审批提示上。 +`sandbox: "danger-full-access"`。这是用于自主心跳的受信任本地操作员姿态: +Codex 可以使用 shell 和网络工具,而无需停下来等待原生审批提示, +因为现场并没有人来响应这些提示。 -若要选择启用由 Codex Guardian 审核的审批,请设置 `appServer.mode: +如果你想启用由 Codex guardian 审查的审批,请设置 `appServer.mode: "guardian"`: ```json5 @@ -299,11 +327,17 @@ Guardian 模式会展开为: } ``` -Guardian 是原生 Codex 审批审核器。当 Codex 请求离开沙箱、在工作区之外写入,或添加诸如网络访问之类的权限时,Codex 会将该审批请求路由给一个审核子智能体,而不是向人工发出提示。审核器会收集上下文并应用 Codex 的风险框架,然后批准或拒绝该具体请求。若你希望比 YOLO 模式有更多防护措施,但仍需要无人值守的智能体和心跳持续推进,Guardian 会很有用。 +Guardian 是一个原生 Codex 审批审查者。当 Codex 请求离开 +沙箱、在工作区外写入,或者添加诸如网络访问之类的权限时, +Codex 会将该审批请求路由给审查子智能体,而不是通过人工提示。 +该审查者会收集上下文并应用 Codex 的风险框架,然后批准或拒绝该具体请求。对于你希望获得比 YOLO 模式更多防护措施,但仍需要无人值守智能体和心跳继续推进的场景,Guardian 很有用。 -当 `OPENCLAW_LIVE_CODEX_HARNESS_GUARDIAN_PROBE=1` 时,Docker live 测试框架会包含一个 Guardian 探针。它会以 Guardian 模式启动 Codex 测试框架,验证一个良性的提权 shell 命令会被批准,并验证向不受信任的外部目标上传伪造密钥会被拒绝,从而让智能体回过头来请求显式批准。 +当 +`OPENCLAW_LIVE_CODEX_HARNESS_GUARDIAN_PROBE=1` 时,Docker live harness 会包含一个 Guardian 探针。它会以 +Guardian 模式启动 Codex harness,验证一个无害的提权 shell 命令会被批准,并验证一个向不受信任外部目标上传伪造密钥的请求会被拒绝,从而让智能体回头请求显式审批。 -各个单独的策略字段仍然优先于 `mode`,因此高级部署可以将该预设与显式选择混合使用。 +单独的策略字段仍然优先于 `mode`,因此高级部署可以 +将该预设与显式选择混合使用。 对于已经在运行的 app-server,请使用 WebSocket 传输: @@ -329,22 +363,22 @@ Guardian 是原生 Codex 审批审核器。当 Codex 请求离开沙箱、在工 支持的 `appServer` 字段: -| 字段 | 默认值 | 含义 | -| ------------------- | ---------------------------------------- | --------------------------------------------------------------------------------------------------------- | -| `transport` | `"stdio"` | `"stdio"` 会启动 Codex;`"websocket"` 会连接到 `url`。 | -| `command` | `"codex"` | 用于 stdio 传输的可执行文件。 | -| `args` | `["app-server", "--listen", "stdio://"]` | 用于 stdio 传输的参数。 | -| `url` | 未设置 | WebSocket app-server URL。 | -| `authToken` | 未设置 | 用于 WebSocket 传输的 Bearer token。 | -| `headers` | `{}` | 额外的 WebSocket 标头。 | -| `requestTimeoutMs` | `60000` | app-server 控制平面调用的超时时间。 | -| `mode` | `"yolo"` | 用于 YOLO 或 Guardian 审核执行的预设。 | -| `approvalPolicy` | `"never"` | 发送给线程启动 / 恢复 / 回合的原生 Codex 审批策略。 | -| `sandbox` | `"danger-full-access"` | 发送给线程启动 / 恢复的原生 Codex 沙箱模式。 | -| `approvalsReviewer` | `"user"` | 使用 `"guardian_subagent"` 让 Codex Guardian 审核提示。 | -| `serviceTier` | 未设置 | 可选的 Codex app-server 服务层级:`"fast"`、`"flex"` 或 `null`。无效的旧版值会被忽略。 | +| 字段 | 默认值 | 含义 | +| ------------------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------- | +| `transport` | `"stdio"` | `"stdio"` 会生成 Codex;`"websocket"` 会连接到 `url`。 | +| `command` | `"codex"` | `stdio` 传输使用的可执行文件。 | +| `args` | `["app-server", "--listen", "stdio://"]` | `stdio` 传输使用的参数。 | +| `url` | 未设置 | WebSocket app-server URL。 | +| `authToken` | 未设置 | WebSocket 传输使用的 Bearer 令牌。 | +| `headers` | `{}` | 额外的 WebSocket 标头。 | +| `requestTimeoutMs` | `60000` | app-server 控制平面调用的超时时间。 | +| `mode` | `"yolo"` | YOLO 或 guardian 审查执行的预设。 | +| `approvalPolicy` | `"never"` | 发送给线程启动/恢复/回合的原生 Codex 审批策略。 | +| `sandbox` | `"danger-full-access"` | 发送给线程启动/恢复的原生 Codex 沙箱模式。 | +| `approvalsReviewer` | `"user"` | 使用 `"guardian_subagent"` 可让 Codex Guardian 审查提示。 | +| `serviceTier` | 未设置 | 可选的 Codex app-server 服务层级:`"fast"`、`"flex"` 或 `null`。无效的旧值会被忽略。 | -当匹配的配置字段未设置时,较旧的环境变量仍可作为本地测试的回退方式: +当匹配的配置字段未设置时,较旧的环境变量仍可作为本地测试的回退: - `OPENCLAW_CODEX_APP_SERVER_BIN` - `OPENCLAW_CODEX_APP_SERVER_ARGS` @@ -355,11 +389,11 @@ Guardian 是原生 Codex 审批审核器。当 Codex 请求离开沙箱、在工 `OPENCLAW_CODEX_APP_SERVER_GUARDIAN=1` 已被移除。请改用 `plugins.entries.codex.config.appServer.mode: "guardian"`,或者在一次性的本地测试中使用 `OPENCLAW_CODEX_APP_SERVER_MODE=guardian`。对于可重复部署,优先使用配置, -因为它会将插件行为与 Codex 测试框架其余设置一起保存在同一个经过审查的文件中。 +因为这样可以将插件行为与其余 Codex harness 设置一起保存在同一个已审查文件中。 -## 常用方案 +## 常见方案 -使用默认 stdio 传输的本地 Codex: +使用默认 `stdio` 传输的本地 Codex: ```json5 { @@ -373,7 +407,7 @@ Guardian 是原生 Codex 审批审核器。当 Codex 请求离开沙箱、在工 } ``` -仅使用 Codex 的测试框架验证,并禁用 PI 回退: +仅使用 Codex 的 harness 验证,禁用 PI 回退: ```json5 { @@ -390,7 +424,7 @@ Guardian 是原生 Codex 审批审核器。当 Codex 请求离开沙箱、在工 } ``` -由 Guardian 审核的 Codex 审批: +由 Guardian 审查的 Codex 审批: ```json5 { @@ -435,83 +469,73 @@ Guardian 是原生 Codex 审批审核器。当 Codex 请求离开沙箱、在工 } ``` -模型切换仍由 OpenClaw 控制。当某个 OpenClaw 会话附加到现有的 Codex 线程时, -下一回合会再次将当前选中的 `codex/*` 模型、提供商、审批策略、沙箱和服务层级发送给 -app-server。从 `codex/gpt-5.4` 切换到 `codex/gpt-5.2` 会保留线程绑定,但会要求 -Codex 使用新选择的模型继续。 +模型切换仍由 OpenClaw 控制。当某个 OpenClaw 会话附加到现有的 +Codex 线程时,下一回合会再次将当前选定的 +`codex/*` 模型、provider、审批策略、沙箱和服务层级发送给 +app-server。从 `codex/gpt-5.4` 切换到 `codex/gpt-5.2` 会保留 +线程绑定,但会要求 Codex 使用新选定的模型继续执行。 ## Codex 命令 -内置插件将 `/codex` 注册为已授权的斜杠命令。它是通用的,并且可在任何支持 -OpenClaw 文本命令的渠道上工作。 +内置插件将 `/codex` 注册为一个已授权的 slash command。它是通用的, +适用于任何支持 OpenClaw 文本命令的渠道。 常见形式: -- `/codex status` 显示实时的 app-server 连接状态、模型、账户、速率限制、MCP 服务器和 Skills。 -- `/codex models` 列出实时的 Codex app-server 模型。 +- `/codex status` 显示实时 app-server 连接性、模型、账号、速率限制、MCP 服务器和 skills。 +- `/codex models` 列出实时 Codex app-server 模型。 - `/codex threads [filter]` 列出最近的 Codex 线程。 - `/codex resume ` 将当前 OpenClaw 会话附加到现有的 Codex 线程。 - `/codex compact` 请求 Codex app-server 压缩已附加的线程。 -- `/codex review` 为已附加的线程启动 Codex 原生审查。 -- `/codex account` 显示账户和速率限制状态。 +- `/codex review` 为已附加线程启动 Codex 原生审查。 +- `/codex account` 显示账号和速率限制状态。 - `/codex mcp` 列出 Codex app-server MCP 服务器状态。 -- `/codex skills` 列出 Codex app-server Skills。 +- `/codex skills` 列出 Codex app-server skills。 -`/codex resume` 会写入与测试框架正常回合使用的同一个 sidecar 绑定文件。 -在下一条消息中,OpenClaw 会恢复该 Codex 线程,将当前选中的 OpenClaw `codex/*` -模型传入 app-server,并保持启用扩展历史记录。 +`/codex resume` 会写入与 harness 在正常回合中使用的同一个 sidecar 绑定文件。 +在下一条消息时,OpenClaw 会恢复该 Codex 线程,将当前选定的 OpenClaw `codex/*` 模型传入 app-server,并保持扩展历史处于启用状态。 -该命令表面要求 Codex app-server `0.118.0` 或更高版本。如果未来版本或自定义 -app-server 未暴露某个 JSON-RPC 方法,各个单独的控制方法会报告为 -`unsupported by this Codex app-server`。 +该命令面需要 Codex app-server `0.118.0` 或更高版本。如果未来版本或自定义 app-server 未暴露某个 JSON-RPC 方法,各个控制方法会被报告为 `unsupported by this Codex app-server`。 ## 工具、媒体和压缩 -Codex 测试框架只会改变底层的嵌入式智能体执行器。 +Codex harness 只会改变低层嵌入式智能体执行器。 -OpenClaw 仍然会构建工具列表,并从测试框架接收动态工具结果。文本、图像、视频、 -音乐、TTS、审批以及消息工具输出,都会继续通过 OpenClaw 的常规传递路径处理。 +OpenClaw 仍然构建工具列表,并从 harness 接收动态工具结果。文本、图像、视频、音乐、TTS、审批和 messaging-tool 输出仍然通过普通的 OpenClaw 投递路径进行。 当 Codex 将 `_meta.codex_approval_kind` 标记为 -`"mcp_tool_call"` 时,Codex MCP 工具审批征求会通过 OpenClaw 的插件审批流程路由; -其他征求和自由形式输入请求仍然会默认拒绝。 +`"mcp_tool_call"` 时,Codex MCP 工具审批征询会通过 OpenClaw 的插件审批流程路由;其他征询和自由输入请求仍然会以默认拒绝方式失败。 -当所选模型使用 Codex 测试框架时,原生线程压缩会委托给 Codex app-server。 -OpenClaw 会保留一个转录镜像,用于渠道历史记录、搜索、`/new`、`/reset`,以及未来的 -模型或测试框架切换。该镜像包括用户提示、最终助手文本,以及当 app-server 发出时的轻量级 -Codex 推理或计划记录。目前,OpenClaw 仅记录原生压缩开始和完成信号。它尚未公开 -人类可读的压缩摘要,也尚未公开 Codex 在压缩后保留了哪些条目的可审计列表。 +当所选模型使用 Codex harness 时,原生线程压缩会委托给 +Codex app-server。OpenClaw 会保留一个转录镜像,用于渠道历史、搜索、`/new`、`/reset` 以及未来的模型或 harness 切换。该镜像包含用户 prompt、最终的助手文本,以及在 app-server 发出时的轻量级 Codex 推理或计划记录。目前,OpenClaw 只记录原生压缩开始和完成信号。它尚未提供人类可读的压缩摘要,也未提供 Codex 在压缩后保留了哪些条目的可审计列表。 -媒体生成不需要 PI。图像、视频、音乐、PDF、TTS 和媒体理解会继续使用相应的提供商 / 模型设置, -例如 `agents.defaults.imageGenerationModel`、`videoGenerationModel`、`pdfModel` 和 -`messages.tts`。 +媒体生成不需要 PI。图像、视频、音乐、PDF、TTS 和媒体理解仍然使用相应的 provider/模型设置,例如 `agents.defaults.imageGenerationModel`、`videoGenerationModel`、`pdfModel` 和 `messages.tts`。 ## 故障排除 **`/model` 中没有出现 Codex:** 启用 `plugins.entries.codex.enabled`, -设置一个 `codex/*` 模型引用,或者检查 `plugins.allow` 是否排除了 `codex`。 +设置一个 `codex/*` 模型引用,或检查 `plugins.allow` 是否排除了 `codex`。 -**OpenClaw 使用的是 PI 而不是 Codex:** 如果没有任何 Codex 测试框架接管此次运行, +**OpenClaw 使用了 PI 而不是 Codex:** 如果没有 Codex harness 接管该运行, OpenClaw 可能会使用 PI 作为兼容性后端。测试时请设置 `embeddedHarness.runtime: "codex"` 以强制选择 Codex,或者设置 -`embeddedHarness.fallback: "none"`,在没有匹配的插件测试框架时直接失败。一旦选中 -Codex app-server,其故障会直接暴露,而无需额外的回退配置。 +`embeddedHarness.fallback: "none"` 以在没有匹配插件 harness 时直接失败。一旦选择了 Codex app-server,其失败会直接暴露,而不需要额外的回退配置。 -**app-server 被拒绝:** 升级 Codex,使 app-server 握手报告版本为 `0.118.0` -或更高。 +**app-server 被拒绝:** 升级 Codex,使 app-server 握手报告的版本为 +`0.118.0` 或更高。 -**模型发现很慢:** 调低 `plugins.entries.codex.config.discovery.timeoutMs` +**模型发现很慢:** 降低 `plugins.entries.codex.config.discovery.timeoutMs` 或禁用发现。 **WebSocket 传输立即失败:** 检查 `appServer.url`、`authToken`, -并确认远程 app-server 使用相同版本的 Codex app-server 协议。 +以及远程 app-server 是否使用相同版本的 Codex app-server 协议。 -**非 Codex 模型使用了 PI:** 这是预期行为。Codex 测试框架只接管 +**某个非 Codex 模型使用了 PI:** 这是预期行为。Codex harness 只接管 `codex/*` 模型引用。 ## 相关内容 -- [智能体测试框架插件](/zh-CN/plugins/sdk-agent-harness) +- [智能体 Harness 插件](/zh-CN/plugins/sdk-agent-harness) - [模型提供商](/zh-CN/concepts/model-providers) - [配置参考](/zh-CN/gateway/configuration-reference) - [测试](/zh-CN/help/testing#live-codex-app-server-harness-smoke) diff --git a/docs/zh-CN/reference/RELEASING.md b/docs/zh-CN/reference/RELEASING.md index c75aa17b0..07c13c640 100644 --- a/docs/zh-CN/reference/RELEASING.md +++ b/docs/zh-CN/reference/RELEASING.md @@ -1,153 +1,197 @@ --- read_when: - - 正在查找公开发布渠道的定义 - - 正在查找版本命名和发布节奏 + - 查找公开发布渠道定义 + - 查找版本命名和发布节奏 summary: 公开发布渠道、版本命名和发布节奏 title: 发布策略 x-i18n: - generated_at: "2026-04-23T05:24:49Z" + generated_at: "2026-04-23T07:06:23Z" model: gpt-5.4 provider: openai - source_hash: 979fd30ec717e107858ff812ef4b46060b9a00a0b5a3c23085d95b8fb81723b8 + source_hash: b31a9597d656ef33633e6aa1c1019287f7197bebff1e6b11d572e41c149c7cff source_path: reference/RELEASING.md workflow: 15 --- # 发布策略 -OpenClaw 有三个公开发布渠道: +OpenClaw 有三个公开发布通道: -- stable:带标签的发布版本,默认发布到 npm `beta`,或在明确请求时发布到 npm `latest` +- stable:带标签的发布,默认发布到 npm `beta`,或在明确请求时发布到 npm `latest` - beta:预发布标签,发布到 npm `beta` -- dev:`main` 的持续更新头部版本 +- dev:`main` 的滚动最新版本 ## 版本命名 -- stable 发布版本:`YYYY.M.D` +- Stable 发布版本:`YYYY.M.D` - Git 标签:`vYYYY.M.D` -- stable 修正版发布版本:`YYYY.M.D-N` +- Stable 修正版发布版本:`YYYY.M.D-N` - Git 标签:`vYYYY.M.D-N` -- beta 预发布版本:`YYYY.M.D-beta.N` +- Beta 预发布版本:`YYYY.M.D-beta.N` - Git 标签:`vYYYY.M.D-beta.N` - 不要为月份或日期补零 -- `latest` 表示当前已提升为正式版的 stable npm 发布 +- `latest` 表示当前已提升的 stable npm 发布 - `beta` 表示当前 beta 安装目标 -- stable 和 stable 修正版默认发布到 npm `beta`;发布操作人员可以显式指定 `latest`,或者在之后将经过验证的 beta 构建提升上去 -- 每个 stable OpenClaw 发布都会同时交付 npm 包和 macOS 应用; - beta 发布通常会先验证并发布 npm/package 路径,而 mac 应用的构建 / 签名 / 公证默认保留给 stable,除非明确要求 +- Stable 和 stable 修正版发布默认发布到 npm `beta`;发布操作人员可以显式指定发布到 `latest`,或者稍后再提升已验证的 beta 构建 +- 每个 stable OpenClaw 发布都会同时发布 npm 包和 macOS 应用; + beta 发布通常先验证并发布 npm/package 路径,而 mac 应用的构建/签名/公证默认保留给 stable,除非明确提出要求 ## 发布节奏 -- 发布采用 beta 优先 -- 只有在最新 beta 验证完成后,才会跟进 stable -- 维护者通常会从当前 `main` 创建 `release/YYYY.M.D` 分支来切发布, - 这样发布验证和修复就不会阻塞 `main` 上的新开发 -- 如果某个 beta 标签已经推送或发布后需要修复,维护者会切下一个 `-beta.N` 标签,而不是删除或重建旧的 beta 标签 -- 详细的发布流程、审批、凭证和恢复说明仅面向维护者 +- 发布流程先走 beta +- 只有在最新 beta 完成验证后,才会进入 stable +- 维护者通常会从当前的 `main` 创建 `release/YYYY.M.D` 分支来进行发布 + ,这样发布验证和修复就不会阻塞 `main` 上的新 + 开发 +- 如果某个 beta 标签已经推送或发布后还需要修复,维护者会创建 + 下一个 `-beta.N` 标签,而不是删除或重新创建旧的 beta 标签 +- 详细的发布流程、审批、凭证和恢复说明 + 仅对维护者开放 -## 发布前检查 +## 发布预检 -- 在发布前检查前运行 `pnpm check:test-types`,这样测试 TypeScript 仍然会被覆盖,而不只依赖更快的本地 `pnpm check` 门禁 -- 在发布前检查前运行 `pnpm check:architecture`,这样更广泛的导入环和架构边界检查会在更快的本地门禁之外保持通过 -- 在 `pnpm release:check` 之前运行 `pnpm build && pnpm ui:build`,这样打包验证步骤所需的 `dist/*` 发布产物和 Control UI bundle 都会存在 -- 每次带标签发布前都运行 `pnpm release:check` +- 在发布预检之前运行 `pnpm check:test-types`,以确保测试 TypeScript 仍然 + 在更快的本地 `pnpm check` 关卡之外得到覆盖 +- 在发布预检之前运行 `pnpm check:architecture`,以确保更广泛的导入 + 环和架构边界检查在更快的本地关卡之外保持绿色 +- 在 `pnpm release:check` 之前运行 `pnpm build && pnpm ui:build`,以确保 + 期望的 `dist/*` 发布产物和 Control UI bundle 存在,从而通过 + pack 验证步骤 +- 在每次带标签发布之前运行 `pnpm release:check` - 发布检查现在在单独的手动工作流中运行: `OpenClaw Release Checks` -- `OpenClaw Release Checks` 还会在发布审批前运行 QA Lab mock 一致性门禁,以及实时的 Matrix 和 Telegram QA 通道。实时通道使用 `qa-live-shared` 环境;Telegram 还使用 Convex CI 凭证租约。 -- 跨操作系统的安装与升级运行时验证由私有调用方工作流分发: - `openclaw/releases-private/.github/workflows/openclaw-cross-os-release-checks.yml`, - 它会调用可复用的公开工作流 +- `OpenClaw Release Checks` 还会在发布审批前运行 QA Lab mock 一致性关卡,以及实时的 + Matrix 和 Telegram QA 通道。实时通道使用 + `qa-live-shared` 环境;Telegram 还使用 Convex CI 凭证租约。 +- 跨 OS 的安装和升级运行时验证由私有调用方工作流 + `openclaw/releases-private/.github/workflows/openclaw-cross-os-release-checks.yml` + 分发,该工作流会调用可复用的公开工作流 `.github/workflows/openclaw-cross-os-release-checks-reusable.yml` -- 这种拆分是刻意设计的:让真实的 npm 发布路径保持简短、确定性强,并聚焦于产物;而较慢的实时检查放在各自独立的通道中,这样它们不会拖慢或阻塞发布 -- 发布检查必须从 `main` 工作流引用,或从 - `release/YYYY.M.D` 工作流引用发起,这样工作流逻辑和密钥才能保持受控 -- 该工作流接受现有发布标签,或当前完整的 40 位工作流分支提交 SHA -- 在提交 SHA 模式下,它只接受当前工作流分支的 HEAD;较旧的发布提交请使用发布标签 -- `OpenClaw NPM Release` 的仅验证前检查也接受当前完整的 40 位工作流分支提交 SHA,而不要求已有推送的标签 -- 该 SHA 路径仅用于验证,不能提升为真实发布 -- 在 SHA 模式下,工作流只会为包元数据检查合成 `v`;真实发布仍然需要真实的发布标签 -- 两个工作流都会将真实发布和提升路径保留在 GitHub 托管的 runner 上,而不修改状态的验证路径则可以使用更大的 Blacksmith Linux runner +- 这种拆分是有意设计的:让真实 npm 发布路径保持简短、 + 可预测,并聚焦于产物,而较慢的实时检查则留在它们 + 自己的通道中,这样它们就不会拖慢或阻塞发布 +- 发布检查必须从 `main` 工作流引用或 + `release/YYYY.M.D` 工作流引用分发,以便工作流逻辑和 secret 始终 + 受控 +- 该工作流接受现有发布标签,或当前完整的 + 40 字符工作流分支提交 SHA +- 在提交 SHA 模式下,它只接受当前工作流分支 HEAD;如果要验证更早的发布提交,请使用 + 发布标签 +- `OpenClaw NPM Release` 的仅验证预检也接受当前 + 完整的 40 字符工作流分支提交 SHA,而不要求先推送标签 +- 该 SHA 路径仅用于验证,不能被提升为真实发布 +- 在 SHA 模式下,工作流仅为包元数据检查合成 + `v`;真实发布仍然需要真实的发布标签 +- 两个工作流都将真实发布和提升路径保留在 GitHub 托管 + runner 上,而非变更型验证路径则可以使用更大的 + Blacksmith Linux runner - 该工作流会运行 `OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_CACHE_TEST=1 pnpm test:live:cache` - 并使用 `OPENAI_API_KEY` 和 `ANTHROPIC_API_KEY` 两个工作流密钥 -- npm 发布前检查不再等待单独的发布检查通道 + ,并使用 `OPENAI_API_KEY` 和 `ANTHROPIC_API_KEY` 两个工作流 secret +- npm 发布预检不再等待单独的发布检查通道 - 在审批前运行 `RELEASE_TAG=vYYYY.M.D node --import tsx scripts/openclaw-npm-release-check.ts` - (或匹配的 beta / 修正标签) + (或对应的 beta/修正版标签) - npm 发布后,运行 `node --import tsx scripts/openclaw-npm-postpublish-verify.ts YYYY.M.D` - (或匹配的 beta / 修正版本),以在全新的临时前缀中验证已发布的注册表安装路径 -- 维护者发布自动化现在采用“先前检查,再提升”: - - 真实的 npm 发布必须通过成功的 npm `preflight_run_id` - - 真实的 npm 发布必须从与成功前检查运行相同的 `main` 或 `release/YYYY.M.D` 分支发起 - - stable npm 发布默认使用 `beta` - - stable npm 发布可以通过工作流输入显式指定 `latest` - - 基于令牌的 npm dist-tag 变更现在位于 + (或对应的 beta/修正版版本),以在全新的临时前缀中验证已发布的注册表 + 安装路径 +- 维护者发布自动化现在采用先预检再提升的流程: + - 真实 npm 发布必须通过成功的 npm `preflight_run_id` + - 真实 npm 发布必须从与成功预检运行相同的 `main` 或 + `release/YYYY.M.D` 分支分发 + - stable npm 发布默认指向 `beta` + - stable npm 发布可以通过工作流输入显式指定为 `latest` + - 基于 token 的 npm dist-tag 修改现在位于 `openclaw/releases-private/.github/workflows/openclaw-npm-dist-tags.yml` - 中,以提高安全性,因为 `npm dist-tag add` 仍然需要 `NPM_TOKEN`,而公开仓库保持仅使用 OIDC 发布 + 中,以提高安全性,因为 `npm dist-tag add` 仍然需要 `NPM_TOKEN`,而 + 公开仓库保持仅 OIDC 发布 - 公开的 `macOS Release` 仅用于验证 - 真实的私有 mac 发布必须通过成功的私有 mac `preflight_run_id` 和 `validate_run_id` - - 真实发布路径会提升已准备好的产物,而不是再次重新构建它们 -- 对于 `YYYY.M.D-N` 这样的 stable 修正版发布,发布后验证器还会检查从 `YYYY.M.D` 到 `YYYY.M.D-N` 的同一临时前缀升级路径,这样发布修正就不会悄悄让旧的全局安装仍停留在基础 stable 负载上 -- npm 发布前检查采用默认失败关闭策略,除非 tarball 同时包含 `dist/control-ui/index.html` 和非空的 `dist/control-ui/assets/` 载荷,这样我们就不会再次发布空的浏览器仪表板 -- `pnpm test:install:smoke` 还会对候选更新 tarball 的 npm pack `unpackedSize` 预算进行强制检查,因此安装器端到端流程会在发布路径之前捕获意外的打包膨胀 -- 如果本次发布工作涉及 CI 规划、扩展时序清单或扩展测试矩阵,请在批准前重新生成并审查来自 `.github/workflows/ci.yml` 的、由 planner 负责的 `checks-node-extensions` 工作流矩阵输出,这样发布说明就不会描述过时的 CI 布局 -- stable macOS 发布准备情况还包括更新器相关表面: - - GitHub 发布最终必须包含打包后的 `.zip`、`.dmg` 和 `.dSYM.zip` + - 真实发布路径会提升已准备好的产物,而不是再次重新构建 +- 对于像 `YYYY.M.D-N` 这样的 stable 修正版发布,发布后验证器 + 还会检查从 `YYYY.M.D` 升级到 `YYYY.M.D-N` 的同一临时前缀升级路径, + 以确保发布修正不会悄悄让旧的全局安装仍停留在基础 stable 负载上 +- 除非 tarball 同时包含 + `dist/control-ui/index.html` 和非空的 `dist/control-ui/assets/` 负载, + 否则 npm 发布预检会以关闭方式失败,以避免再次发布空的浏览器仪表板 +- 发布后验证还会检查,已发布的注册表安装中是否在根 `dist/*` + 布局下包含非空的内置插件运行时依赖。若某个发布缺失或带有空的内置插件 + 依赖负载,则其会在发布后验证器中失败,且不能被提升 + 为 `latest`。 +- `pnpm test:install:smoke` 还会对候选更新 tarball 的 npm pack `unpackedSize` 预算进行强制检查, + 这样安装器 e2e 就能在发布路径之前捕获意外的打包膨胀 +- 如果发布工作涉及 CI 规划、扩展时序清单,或 + 扩展测试矩阵,请在审批前重新生成并审查由规划器拥有的 + 来自 `.github/workflows/ci.yml` 的 `checks-node-extensions` 工作流矩阵输出, + 以避免发布说明描述过时的 CI 布局 +- Stable macOS 发布就绪性还包括更新器表面: + - GitHub 发布最终必须包含已打包的 `.zip`、`.dmg` 和 `.dSYM.zip` - 发布后,`main` 上的 `appcast.xml` 必须指向新的 stable zip - - 打包后的应用必须保持非调试 bundle id、非空的 Sparkle feed URL,以及不低于该发布版本规范 Sparkle build 下限的 `CFBundleVersion` + - 已打包的应用必须保持非调试 bundle id、非空 Sparkle feed + URL,以及不低于该发布版本规范 Sparkle 构建下限的 `CFBundleVersion` ## NPM 工作流输入 `OpenClaw NPM Release` 接受以下由操作人员控制的输入: - `tag`:必填发布标签,例如 `v2026.4.2`、`v2026.4.2-1` 或 - `v2026.4.2-beta.1`;当 `preflight_only=true` 时,也可以是当前完整的 - 40 位工作流分支提交 SHA,用于仅验证的前检查 -- `preflight_only`:仅验证 / 构建 / 打包时为 `true`,真实发布路径时为 `false` -- `preflight_run_id`:真实发布路径必填,以便工作流复用成功前检查运行中准备好的 tarball + `v2026.4.2-beta.1`;当 `preflight_only=true` 时,也可以是当前 + 完整的 40 字符工作流分支提交 SHA,用于仅验证预检 +- `preflight_only`:`true` 表示仅验证/构建/打包,`false` 表示 + 真实发布路径 +- `preflight_run_id`:真实发布路径中必填,以便工作流复用成功预检运行 + 中准备好的 tarball - `npm_dist_tag`:发布路径的 npm 目标标签;默认值为 `beta` `OpenClaw Release Checks` 接受以下由操作人员控制的输入: -- `ref`:现有发布标签,或从 `main` 发起时用于验证的当前完整 40 位 `main` 提交 - SHA;如果从发布分支发起,则使用现有发布标签,或当前完整的 40 位发布分支提交 +- `ref`:现有发布标签,或从 `main` 分发时用于验证的当前完整 + 40 字符 `main` 提交 SHA;如果从发布分支分发,请使用现有 + 发布标签或当前完整的 40 字符发布分支提交 SHA 规则: -- stable 和修正标签可以发布到 `beta` 或 `latest` -- beta 预发布标签只能发布到 `beta` -- 对于 `OpenClaw NPM Release`,只有在 - `preflight_only=true` 时才允许使用完整提交 SHA 作为输入 -- `OpenClaw Release Checks` 始终仅用于验证,也接受当前工作流分支提交 SHA -- 发布检查的提交 SHA 模式也要求当前工作流分支 HEAD -- 真实发布路径必须使用与前检查相同的 `npm_dist_tag`;工作流会在继续发布前验证该元数据 +- Stable 和修正版标签可以发布到 `beta` 或 `latest` +- Beta 预发布标签只能发布到 `beta` +- 对于 `OpenClaw NPM Release`,仅当 + `preflight_only=true` 时才允许输入完整提交 SHA +- `OpenClaw Release Checks` 始终仅用于验证,同时也接受 + 当前工作流分支提交 SHA +- 发布检查的提交 SHA 模式还要求当前工作流分支 HEAD +- 真实发布路径必须使用与预检期间相同的 `npm_dist_tag`; + 工作流会在继续发布前验证该元数据 ## Stable npm 发布顺序 -切 stable npm 发布时: +发布 stable npm 版本时: -1. 运行 `OpenClaw NPM Release`,并设置 `preflight_only=true` +1. 运行 `OpenClaw NPM Release`,设置 `preflight_only=true` - 在标签尚不存在时,你可以使用当前完整工作流分支提交 - SHA,对前检查工作流进行仅验证的试运行 -2. 选择 `npm_dist_tag=beta` 用于正常的 beta 优先流程;只有在你明确想直接发布 stable 时,才选择 `latest` -3. 单独运行 `OpenClaw Release Checks`,使用相同标签,或在你希望获得实时 prompt cache、 - QA Lab 一致性、Matrix 和 Telegram 覆盖时,使用当前完整工作流分支提交 SHA - - 这样刻意拆开,是为了让实时覆盖保持可用,而不会将长时间运行或不稳定的检查重新耦合到发布工作流中 + SHA 对预检工作流进行一次仅验证的 dry run +2. 对于正常的 beta-first 流程,选择 `npm_dist_tag=beta`;只有当你有意直接发布 stable 时才选择 `latest` +3. 单独运行 `OpenClaw Release Checks`,使用相同的标签或 + 当前完整工作流分支提交 SHA,以便获得实时 prompt cache、 + QA Lab 一致性、Matrix 和 Telegram 覆盖 + - 之所以刻意拆分,是为了让实时覆盖始终可用,同时避免 + 将长时间运行或不稳定的检查重新耦合到发布工作流中 4. 保存成功的 `preflight_run_id` -5. 再次运行 `OpenClaw NPM Release`,并设置 `preflight_only=false`、相同的 - `tag`、相同的 `npm_dist_tag`,以及保存的 `preflight_run_id` -6. 如果该发布先落在 `beta`,请使用私有的 +5. 再次运行 `OpenClaw NPM Release`,设置 `preflight_only=false`,并使用相同的 + `tag`、相同的 `npm_dist_tag` 以及保存的 `preflight_run_id` +6. 如果该发布先落在 `beta`,请使用私有 `openclaw/releases-private/.github/workflows/openclaw-npm-dist-tags.yml` 工作流,将该 stable 版本从 `beta` 提升到 `latest` -7. 如果该发布有意直接发布到 `latest`,并且 `beta` - 也应立即跟随同一个 stable 构建,请使用同一个私有工作流让两个 dist-tag 都指向该 stable 版本,或者让其计划中的自愈同步稍后移动 `beta` +7. 如果该发布有意直接发布到了 `latest`,并且 `beta` + 也应立即跟随同一个 stable 构建,请使用同一个私有 + 工作流将两个 dist-tag 都指向该 stable 版本,或者让其计划中的 + 自愈同步稍后再移动 `beta` -出于安全原因,dist-tag 变更位于私有仓库中,因为它仍然 -需要 `NPM_TOKEN`,而公开仓库保持仅使用 OIDC 发布。 +dist-tag 修改位于私有仓库中是出于安全考虑,因为它仍然 +需要 `NPM_TOKEN`,而公开仓库保持仅 OIDC 发布。 -这样可以让直接发布路径和 beta 优先提升路径都保持文档化,并且对操作人员可见。 +这样既能让直接发布路径,也能让 beta-first 提升路径都被 +文档化,并对操作人员可见。 ## 公开参考 diff --git a/docs/zh-CN/tools/acp-agents.md b/docs/zh-CN/tools/acp-agents.md index 01dd5814e..c1e65db33 100644 --- a/docs/zh-CN/tools/acp-agents.md +++ b/docs/zh-CN/tools/acp-agents.md @@ -1,199 +1,197 @@ --- read_when: - - 通过 ACP 运行编程 harness - - 在消息渠道上设置绑定到对话的 ACP 会话 - - 将消息渠道中的对话绑定到持久化 ACP 会话 - - 排查 ACP 后端和插件连接问题 - - 调试 ACP 完成结果投递或智能体之间的循环 - - 从聊天中操作 `/acp` 命令 -summary: 对 Codex、Claude Code、Cursor、Gemini CLI、OpenClaw ACP 和其他 harness 智能体使用 ACP 运行时会话 + - 通过 ACP 运行 coding harness + - 在消息渠道上设置绑定到会话的 ACP 会话 + - 将消息渠道会话绑定到持久化 ACP 会话 + - 排查 ACP 后端和插件接线问题 + - 调试 ACP 完成投递或智能体到智能体循环 + - 从聊天中操作 /acp 命令 +summary: 为 Codex、Claude Code、Cursor、Gemini CLI、OpenClaw ACP 和其他 harness 智能体使用 ACP 运行时会话 title: ACP 智能体 x-i18n: - generated_at: "2026-04-22T22:21:17Z" + generated_at: "2026-04-23T07:06:31Z" model: gpt-5.4 provider: openai - source_hash: df4c4c38e7a93c240f6bf30a4cc093e8717ef6459425d56a9287245adc625e51 + source_hash: 617103fe47ef90592bad4882da719c47c801ebc916d3614c148a66e6601e8cf5 source_path: tools/acp-agents.md workflow: 15 --- # ACP 智能体 -[Agent Client Protocol(ACP)](https://agentclientprotocol.com/) 会话让 OpenClaw 能够通过 ACP 后端插件运行外部编程 harness(例如 Pi、Claude Code、Codex、Cursor、Copilot、OpenClaw ACP、OpenCode、Gemini CLI 以及其他受支持的 ACPX harness)。 +[Agent Client Protocol(ACP)](https://agentclientprotocol.com/) 会话让 OpenClaw 能通过 ACP 后端插件运行外部 coding harness(例如 Pi、Claude Code、Codex、Cursor、Copilot、OpenClaw ACP、OpenCode、Gemini CLI,以及其他受支持的 ACPX harness)。 -如果你用自然语言要求 OpenClaw “在 Codex 里运行这个” 或 “在线程里启动 Claude Code”,OpenClaw 应该将该请求路由到 ACP 运行时(而不是原生子智能体运行时)。每次 ACP 会话启动都会作为一个[后台任务](/zh-CN/automation/tasks)进行跟踪。 +如果你用自然语言要求 OpenClaw “在 Codex 中运行这个”或“在线程中启动 Claude Code”,OpenClaw 应将该请求路由到 ACP 运行时(而不是原生子智能体运行时)。每次 ACP 会话启动都会被记录为一个[后台任务](/zh-CN/automation/tasks)。 -如果你想让 Codex 或 Claude Code 作为外部 MCP 客户端,直接连接 -到现有的 OpenClaw 渠道会话,请使用 [`openclaw mcp serve`](/cli/mcp) -而不是 ACP。 +如果你希望 Codex 或 Claude Code 作为外部 MCP 客户端直接连接到现有的 OpenClaw 渠道会话,请使用 [`openclaw mcp serve`](/zh-CN/cli/mcp),而不是 ACP。 -## 我需要哪个页面? +## 我该看哪一页? -这里有三个相近但很容易混淆的入口: +这里有三个很接近、也很容易混淆的入口: -| 你想要…… | 使用这里 | 说明 | -| ---------------------------------------------------------------------------------- | ------------------------------------- | ----------------------------------------------------------------------------------------------------------- | -| 通过 OpenClaw _运行_ Codex、Claude Code、Gemini CLI 或其他外部 harness | 本页:ACP 智能体 | 绑定聊天的会话、`/acp spawn`、`sessions_spawn({ runtime: "acp" })`、后台任务、运行时控制 | -| 将 OpenClaw Gateway 网关会话作为 ACP 服务器 _暴露给_ 编辑器或客户端 | [`openclaw acp`](/cli/acp) | 桥接模式。IDE/客户端 通过 stdio/WebSocket 使用 ACP 与 OpenClaw 通信 | +| 你想要…… | 使用这个 | 说明 | +| ---------- | -------- | ---- | +| 通过 OpenClaw 运行 Codex、Claude Code、Gemini CLI 或其他外部 harness | 本页:ACP 智能体 | 绑定到聊天的会话、`/acp spawn`、`sessions_spawn({ runtime: "acp" })`、后台任务、运行时控制 | +| 将一个 OpenClaw Gateway 网关会话作为 ACP 服务器暴露给编辑器或客户端 | [`openclaw acp`](/zh-CN/cli/acp) | 桥接模式。IDE/客户端 通过 stdio/WebSocket 向 OpenClaw 发起 ACP 通信 | | 将本地 AI CLI 复用为纯文本回退模型 | [CLI 后端](/zh-CN/gateway/cli-backends) | 不是 ACP。没有 OpenClaw 工具、没有 ACP 控制、没有 harness 运行时 | -## 这开箱即用吗? +## 开箱即用吗? 通常可以。 -- 全新安装现在默认启用内置的 `acpx` 运行时插件。 -- 内置的 `acpx` 插件优先使用其插件本地固定版本的 `acpx` 二进制文件。 -- 在启动时,OpenClaw 会探测该二进制文件,并在需要时自行修复。 -- 如果你想快速检查就绪状态,请从 `/acp doctor` 开始。 +- 全新安装现在会默认启用内置的 `acpx` 运行时插件。 +- 内置的 `acpx` 插件会优先使用其插件本地固定版本的 `acpx` 二进制文件。 +- 启动时,OpenClaw 会探测该二进制文件,并在需要时自我修复。 +- 如果你想快速检查可用性,请先运行 `/acp doctor`。 -首次使用时仍然可能发生的情况: +首次使用时仍可能发生的情况: -- 目标 harness 适配器可能会在你首次使用该 harness 时通过 `npx` 按需获取。 -- 该 harness 的厂商身份验证仍然必须已存在于主机上。 -- 如果主机没有 npm/网络访问能力,则首次运行时的适配器获取可能失败,直到缓存被预热或通过其他方式安装适配器。 +- 第一次使用某个 harness 时,目标 harness 适配器可能会按需通过 `npx` 拉取。 +- 该 harness 对应的厂商认证仍必须存在于宿主机上。 +- 如果宿主机没有 npm/网络访问,首次运行的适配器拉取可能失败,直到缓存被预热或该适配器通过其他方式安装。 示例: -- `/acp spawn codex`:OpenClaw 应该已准备好引导 `acpx`,但 Codex ACP 适配器仍可能需要首次运行时获取。 -- `/acp spawn claude`:Claude ACP 适配器也是同样情况,另外该主机上还需要 Claude 侧身份验证。 +- `/acp spawn codex`:OpenClaw 应该已准备好引导 `acpx`,但 Codex ACP 适配器可能仍需要首次运行拉取。 +- `/acp spawn claude`:Claude ACP 适配器也是同样的情况,另外还需要该宿主机上存在 Claude 侧认证。 -## 面向操作员的快速流程 +## 面向操作人员的快速流程 如果你想要一个实用的 `/acp` 操作手册,请使用这个流程: 1. 启动一个会话: - `/acp spawn codex --bind here` - `/acp spawn codex --mode persistent --thread auto` -2. 在绑定的对话或线程中工作(或者显式指定该会话键)。 +2. 在已绑定的会话或线程中工作(或显式指定该会话键)。 3. 检查运行时状态: - `/acp status` -4. 按需调整运行时选项: +4. 根据需要调整运行时选项: - `/acp model ` - `/acp permissions ` - `/acp timeout ` -5. 在不替换上下文的情况下推动一个活动会话继续进行: +5. 在不替换上下文的情况下推动一个活动会话继续: - `/acp steer tighten logging and continue` 6. 停止工作: - `/acp cancel`(停止当前轮次),或 - `/acp close`(关闭会话并移除绑定) -## 面向用户的快速开始 +## 面向人的快速开始 自然语言请求示例: - “把这个 Discord 渠道绑定到 Codex。” -- “在这里的线程中启动一个持久 Codex 会话,并保持聚焦。” -- “把这个作为一次性的 Claude Code ACP 会话运行,并总结结果。” -- “把这个 iMessage 聊天绑定到 Codex,并让后续消息继续使用同一个工作区。” -- “这个任务用 Gemini CLI 在线程里处理,然后让后续消息继续使用同一个线程。” +- “在这里的线程里启动一个持久化 Codex 会话,并让它保持专注。” +- “把这个作为一次性 Claude Code ACP 会话运行,并总结结果。” +- “把这个 iMessage 聊天绑定到 Codex,并让后续继续使用同一个工作区。” +- “为这个任务使用 Gemini CLI,并放在线程里,然后让后续继续在同一个线程中进行。” -OpenClaw 应该执行的操作: +OpenClaw 应执行的操作: 1. 选择 `runtime: "acp"`。 -2. 解析所请求的 harness 目标(`agentId`,例如 `codex`)。 -3. 如果请求了“绑定当前对话”,并且当前渠道支持,就将 ACP 会话绑定到该对话。 -4. 否则,如果请求了线程绑定,并且当前渠道支持,就将 ACP 会话绑定到该线程。 -5. 将后续绑定消息路由到同一个 ACP 会话,直到取消聚焦、关闭或过期。 +2. 解析请求的 harness 目标(`agentId`,例如 `codex`)。 +3. 如果请求的是当前会话绑定,并且活动渠道支持该能力,就将 ACP 会话绑定到该会话。 +4. 否则,如果请求的是线程绑定,并且当前渠道支持该能力,就将 ACP 会话绑定到该线程。 +5. 将后续已绑定的消息继续路由到同一个 ACP 会话,直到失焦/关闭/过期。 ## ACP 与子智能体的区别 -当你需要外部 harness 运行时时,请使用 ACP。当你需要 OpenClaw 原生委派运行时,请使用子智能体。 +当你需要外部 harness 运行时时,请使用 ACP。当你需要 OpenClaw 原生的委派运行时,请使用子智能体。 -| 区域 | ACP 会话 | 子智能体运行 | -| ------------- | ------------------------------------- | ---------------------------------- | +| 领域 | ACP 会话 | 子智能体运行 | +| ---- | -------- | ------------ | | 运行时 | ACP 后端插件(例如 acpx) | OpenClaw 原生子智能体运行时 | | 会话键 | `agent::acp:` | `agent::subagent:` | -| 主要命令 | `/acp ...` | `/subagents ...` | -| 启动工具 | `sessions_spawn` 配合 `runtime:"acp"` | `sessions_spawn`(默认运行时) | +| 主命令 | `/acp ...` | `/subagents ...` | +| 启动工具 | 带 `runtime:"acp"` 的 `sessions_spawn` | `sessions_spawn`(默认运行时) | -另见[子智能体](/zh-CN/tools/subagents)。 +另请参见[子智能体](/zh-CN/tools/subagents)。 ## ACP 如何运行 Claude Code -对于通过 ACP 运行的 Claude Code,其堆栈如下: +对于通过 ACP 运行的 Claude Code,调用栈如下: 1. OpenClaw ACP 会话控制平面 2. 内置的 `acpx` 运行时插件 3. Claude ACP 适配器 4. Claude 侧运行时/会话机制 -重要区别: +一个重要区别是: -- ACP Claude 是一种 harness 会话,带有 ACP 控制、会话恢复、后台任务跟踪,以及可选的对话/线程绑定。 -- CLI 后端是独立的纯文本本地回退运行时。参见 [CLI 后端](/zh-CN/gateway/cli-backends)。 +- ACP Claude 是 harness 会话,具备 ACP 控制、会话恢复、后台任务跟踪,以及可选的会话/线程绑定。 +- CLI 后端则是独立的纯文本本地回退运行时。参见 [CLI 后端](/zh-CN/gateway/cli-backends)。 -对于操作员,实用规则是: +对于操作人员,实用规则如下: - 想要 `/acp spawn`、可绑定会话、运行时控制或持久化 harness 工作:使用 ACP - 想要通过原始 CLI 获得简单的本地文本回退:使用 CLI 后端 -## 绑定会话 +## 已绑定会话 -### 绑定当前对话 +### 当前会话绑定 -当你希望当前对话变成一个持久的 ACP 工作区,而不创建子线程时,请使用 `/acp spawn --bind here`。 +当你希望当前会话变成一个持久 ACP 工作区,且不创建子线程时,请使用 `/acp spawn --bind here`。 -行为如下: +行为: -- OpenClaw 继续负责渠道传输、身份验证、安全性和投递。 -- 当前对话会固定绑定到已启动的 ACP 会话键。 -- 该对话中的后续消息会路由到同一个 ACP 会话。 -- `/new` 和 `/reset` 会在原地重置同一个已绑定的 ACP 会话。 -- `/acp close` 会关闭该会话并移除当前对话绑定。 +- OpenClaw 继续负责渠道传输、认证、安全和投递。 +- 当前会话会被固定到已启动的 ACP 会话键。 +- 该会话中的后续消息会继续路由到同一个 ACP 会话。 +- `/new` 和 `/reset` 会就地重置同一个已绑定的 ACP 会话。 +- `/acp close` 会关闭会话并移除当前会话绑定。 -这在实践中的含义: +这在实践中的含义是: -- `--bind here` 会保留同一个聊天界面。在 Discord 上,当前渠道仍然是当前渠道。 -- 如果你正在启动新的工作,`--bind here` 仍然可以创建一个新的 ACP 会话。该绑定会将该会话附加到当前对话。 -- `--bind here` 本身不会创建子 Discord 线程或 Telegram 话题。 -- ACP 运行时仍然可以拥有自己的工作目录(`cwd`)或由后端管理的磁盘工作区。该运行时工作区与聊天界面是分开的,并不意味着会创建新的消息线程。 -- 如果你启动到另一个 ACP 智能体,并且没有传递 `--cwd`,OpenClaw 默认会继承**目标智能体的**工作区,而不是请求者的工作区。 -- 如果继承的工作区路径不存在(`ENOENT`/`ENOTDIR`),OpenClaw 会回退到后端默认的 cwd,而不是静默复用错误的目录树。 +- `--bind here` 会保持同一个聊天界面。例如在 Discord 上,当前渠道仍然是当前渠道。 +- 当你启动新工作时,`--bind here` 仍然可以创建一个新的 ACP 会话。绑定会将该会话附加到当前会话。 +- `--bind here` 本身不会创建 Discord 子线程或 Telegram 话题。 +- ACP 运行时仍然可以拥有自己的工作目录(`cwd`)或由后端管理的磁盘工作区。该运行时工作区与聊天界面是分离的,并不意味着会创建新的消息线程。 +- 如果你启动到另一个 ACP 智能体,且未传入 `--cwd`,OpenClaw 默认会继承**目标智能体的**工作区,而不是请求者的工作区。 +- 如果继承的工作区路径不存在(`ENOENT`/`ENOTDIR`),OpenClaw 会回退到后端默认 `cwd`,而不是静默复用错误的目录树。 - 如果继承的工作区存在但无法访问(例如 `EACCES`),启动会返回真实的访问错误,而不是丢弃 `cwd`。 心智模型: - 聊天界面:人们继续交流的地方(`Discord channel`、`Telegram topic`、`iMessage chat`) - ACP 会话:OpenClaw 路由到的持久 Codex/Claude/Gemini 运行时状态 -- 子线程/话题:仅由 `--thread ...` 创建的可选额外消息界面 -- 运行时工作区:harness 运行的文件系统位置(`cwd`、代码仓库检出目录、后端工作区) +- 子线程/话题:仅在使用 `--thread ...` 时创建的可选额外消息界面 +- 运行时工作区:harness 运行的文件系统位置(`cwd`、代码仓库 checkout、后端工作区) 示例: -- `/acp spawn codex --bind here`:保留当前聊天,启动或附加一个 Codex ACP 会话,并将这里的未来消息路由到它 -- `/acp spawn codex --thread auto`:OpenClaw 可以创建一个子线程/话题,并将 ACP 会话绑定到那里 +- `/acp spawn codex --bind here`:保留当前聊天,启动或附加一个 Codex ACP 会话,并将后续消息继续路由到它 +- `/acp spawn codex --thread auto`:OpenClaw 可能会创建一个子线程/话题,并将 ACP 会话绑定到那里 - `/acp spawn codex --bind here --cwd /workspace/repo`:与上面相同的聊天绑定,但 Codex 在 `/workspace/repo` 中运行 -当前对话绑定支持: +当前会话绑定支持: -- 声明支持当前对话绑定的聊天/消息渠道,可以通过共享的对话绑定路径使用 `--bind here`。 -- 带有自定义线程/话题语义的渠道,仍然可以在同一个共享接口之后提供特定于渠道的规范化。 -- `--bind here` 始终表示“在当前位置绑定当前对话”。 -- 通用的当前对话绑定使用共享的 OpenClaw 绑定存储,并且在普通 Gateway 网关重启后仍会保留。 +- 声明支持当前会话绑定的聊天/消息渠道,可以通过共享的会话绑定路径使用 `--bind here`。 +- 具有自定义线程/话题语义的渠道,仍可在相同的共享接口背后提供渠道专用的规范化。 +- `--bind here` 始终表示“就地绑定当前会话”。 +- 通用的当前会话绑定使用共享的 OpenClaw 绑定存储,并能在正常的 Gateway 网关重启后继续保留。 说明: -- 在 `/acp spawn` 中,`--bind here` 和 `--thread ...` 互斥。 -- 在 Discord 上,`--bind here` 会在原位置绑定当前渠道或线程。只有当 OpenClaw 需要为 `--thread auto|here` 创建子线程时,才需要 `spawnAcpSessions`。 -- 如果当前渠道未暴露当前对话 ACP 绑定能力,OpenClaw 会返回明确的“不支持”消息。 -- `resume` 和“新建会话”问题属于 ACP 会话问题,而不是渠道问题。你可以复用或替换运行时状态,而不改变当前聊天界面。 +- 在 `/acp spawn` 中,`--bind here` 与 `--thread ...` 互斥。 +- 在 Discord 上,`--bind here` 会就地绑定当前渠道或线程。只有当 OpenClaw 需要为 `--thread auto|here` 创建子线程时,才需要 `spawnAcpSessions`。 +- 如果当前渠道不暴露当前会话 ACP 绑定能力,OpenClaw 会返回清晰的不支持消息。 +- `resume` 和“新会话”问题是 ACP 会话层面的问题,而不是渠道层面的问题。你可以复用或替换运行时状态,而无需改变当前聊天界面。 -### 绑定到线程的会话 +### 线程绑定会话 -当渠道适配器启用线程绑定时,ACP 会话可以绑定到线程: +当渠道适配器启用了线程绑定时,ACP 会话可以绑定到线程: -- OpenClaw 将线程绑定到目标 ACP 会话。 +- OpenClaw 将某个线程绑定到目标 ACP 会话。 - 该线程中的后续消息会路由到已绑定的 ACP 会话。 -- ACP 输出会投递回同一个线程。 -- 取消聚焦、关闭、归档、空闲超时或最大生命周期到期时,会移除绑定。 +- ACP 输出会回传到同一个线程。 +- 失焦/关闭/归档/空闲超时或最大存活时间到期时,绑定会被移除。 -线程绑定支持取决于具体适配器。如果当前渠道适配器不支持线程绑定,OpenClaw 会返回明确的“不支持/不可用”消息。 +线程绑定支持取决于适配器。如果当前渠道适配器不支持线程绑定,OpenClaw 会返回清晰的不支持/不可用消息。 -绑定到线程的 ACP 所需功能标志: +线程绑定 ACP 所需的功能开关: - `acp.enabled=true` - `acp.dispatch.enabled` 默认开启(设为 `false` 可暂停 ACP 调度) -- 渠道适配器的 ACP 线程启动标志已启用(适配器特定) +- 启用渠道适配器的 ACP 线程启动开关(适配器专用) - Discord:`channels.discord.threadBindings.spawnAcpSessions=true` - Telegram:`channels.telegram.threadBindings.spawnAcpSessions=true` @@ -202,25 +200,25 @@ OpenClaw 应该执行的操作: - 任何暴露会话/线程绑定能力的渠道适配器。 - 当前内置支持: - Discord 线程/渠道 - - Telegram 话题(群组/超级群组中的论坛话题和私信话题) + - Telegram 话题(群组/超级群组中的论坛话题,以及私信话题) - 渠道插件也可以通过相同的绑定接口添加支持。 -## 渠道特定设置 +## 渠道专用设置 -对于非临时工作流,请在顶层 `bindings[]` 条目中配置持久 ACP 绑定。 +对于非临时性工作流,请在顶层 `bindings[]` 条目中配置持久化 ACP 绑定。 ### 绑定模型 -- `bindings[].type="acp"` 表示持久 ACP 对话绑定。 -- `bindings[].match` 用于标识目标对话: +- `bindings[].type="acp"` 表示一个持久化 ACP 会话绑定。 +- `bindings[].match` 用于标识目标会话: - Discord 渠道或线程:`match.channel="discord"` + `match.peer.id=""` - Telegram 论坛话题:`match.channel="telegram"` + `match.peer.id=":topic:"` - - BlueBubbles 私信/群聊:`match.channel="bluebubbles"` + `match.peer.id=""` + - BlueBubbles 私信/群聊:`match.channel="bluebubbles"` + `match.peer.id=""` 对于稳定的群组绑定,优先使用 `chat_id:*` 或 `chat_identifier:*`。 - - iMessage 私信/群聊:`match.channel="imessage"` + `match.peer.id=""` + - iMessage 私信/群聊:`match.channel="imessage"` + `match.peer.id=""` 对于稳定的群组绑定,优先使用 `chat_id:*`。 - `bindings[].agentId` 是所属的 OpenClaw 智能体 id。 -- 可选的 ACP 覆盖项位于 `bindings[].acp` 下: +- 可选的 ACP 覆盖位于 `bindings[].acp` 下: - `mode`(`persistent` 或 `oneshot`) - `label` - `cwd` @@ -236,7 +234,7 @@ OpenClaw 应该执行的操作: - `agents.list[].runtime.acp.mode` - `agents.list[].runtime.acp.cwd` -ACP 绑定会话的覆盖优先级: +ACP 已绑定会话的覆盖优先级: 1. `bindings[].acp.*` 2. `agents.list[].runtime.acp.*` @@ -324,18 +322,18 @@ ACP 绑定会话的覆盖优先级: 行为: -- OpenClaw 会确保已配置的 ACP 会话在使用前存在。 +- OpenClaw 会在使用前确保已配置的 ACP 会话存在。 - 该渠道或话题中的消息会路由到已配置的 ACP 会话。 -- 在已绑定的对话中,`/new` 和 `/reset` 会在原地重置同一个 ACP 会话键。 -- 临时运行时绑定(例如由线程聚焦流程创建的绑定)在存在时仍然适用。 -- 对于未显式指定 `cwd` 的跨智能体 ACP 启动,OpenClaw 会从智能体配置中继承目标智能体的工作区。 -- 缺失的继承工作区路径会回退到后端默认 cwd;而非缺失的访问失败会作为启动错误暴露出来。 +- 在已绑定的会话中,`/new` 和 `/reset` 会就地重置同一个 ACP 会话键。 +- 临时运行时绑定(例如由线程聚焦流程创建的绑定)在存在时仍会生效。 +- 对于未显式指定 `cwd` 的跨智能体 ACP 启动,OpenClaw 会从智能体配置继承目标智能体的工作区。 +- 继承的工作区路径若不存在,会回退到后端默认 `cwd`;若是非缺失型访问失败,则会作为启动错误直接返回。 ## 启动 ACP 会话(接口) -### 从 `sessions_spawn` 启动 +### 从 `sessions_spawn` -使用 `runtime: "acp"` 可从智能体轮次或工具调用中启动 ACP 会话。 +要从智能体轮次或工具调用中启动 ACP 会话,请使用 `runtime: "acp"`。 ```json { @@ -349,67 +347,68 @@ ACP 绑定会话的覆盖优先级: 说明: -- `runtime` 默认是 `subagent`,因此对于 ACP 会话,请显式设置 `runtime: "acp"`。 -- 如果省略 `agentId`,OpenClaw 会在已配置时使用 `acp.defaultAgent`。 -- `mode: "session"` 需要 `thread: true`,以保持持久的绑定对话。 +- `runtime` 默认是 `subagent`,因此对于 ACP 会话必须显式设置 `runtime: "acp"`。 +- 如果省略 `agentId`,则在已配置时 OpenClaw 会使用 `acp.defaultAgent`。 +- `mode: "session"` 需要 `thread: true`,以保持一个持久化的已绑定会话。 接口细节: -- `task`(必填):发送给 ACP 会话的初始提示。 +- `task`(必填):发送到 ACP 会话的初始提示。 - `runtime`(ACP 必填):必须为 `"acp"`。 -- `agentId`(可选):ACP 目标 harness id。若已设置,则回退到 `acp.defaultAgent`。 -- `thread`(可选,默认 `false`):在支持时请求线程绑定流程。 +- `agentId`(可选):ACP 目标 harness id。如果已设置,则回退到 `acp.defaultAgent`。 +- `thread`(可选,默认 `false`):在受支持时请求线程绑定流程。 - `mode`(可选):`run`(一次性)或 `session`(持久化)。 - 默认值为 `run` - - 如果 `thread: true` 且未指定 mode,OpenClaw 可能会根据运行时路径默认采用持久化行为 + - 如果 `thread: true` 且省略 `mode`,OpenClaw 可能会根据运行时路径默认采用持久化行为 - `mode: "session"` 需要 `thread: true` -- `cwd`(可选):请求的运行时工作目录(由后端/运行时策略校验)。如果省略,ACP 启动会在已配置时继承目标智能体工作区;缺失的继承路径会回退到后端默认值,而真实的访问错误会被返回。 -- `label`(可选):面向操作员的标签,用于会话/横幅文本。 -- `resumeSessionId`(可选):恢复现有 ACP 会话,而不是创建新会话。智能体会通过 `session/load` 重放其对话历史。需要 `runtime: "acp"`。 -- `streamTo`(可选):`"parent"` 将初始 ACP 运行进度摘要以系统事件形式流式回传给请求方会话。 - - 在可用时,接受的响应会包含 `streamLogPath`,指向一个按会话划分的 JSONL 日志(`.acp-stream.jsonl`),你可以对其执行 tail 以查看完整的转发历史。 +- `cwd`(可选):请求的运行时工作目录(由后端/运行时策略验证)。如果省略,ACP 启动会在已配置时继承目标智能体工作区;继承路径缺失时会回退到后端默认值,而真实访问错误会直接返回。 +- `label`(可选):面向操作人员的标签,用于会话/横幅文本。 +- `resumeSessionId`(可选):恢复现有 ACP 会话,而不是创建新会话。智能体会通过 `session/load` 重放其会话历史。要求 `runtime: "acp"`。 +- `streamTo`(可选):`"parent"` 会将初始 ACP 运行的进度摘要作为系统事件流式回传给请求者会话。 + - 可用时,接受的响应还会包含 `streamLogPath`,指向一个按会话划分的 JSONL 日志(`.acp-stream.jsonl`),你可以 tail 它以查看完整的中继历史。 +- `model`(可选):显式的 ACP 子会话模型覆盖。对于 `runtime: "acp"` 会生效,因此子会话会使用请求的模型,而不是静默回退到目标智能体的默认模型。 ## 投递模型 -ACP 会话既可以是交互式工作区,也可以是由父级拥有的后台工作。投递路径取决于其形态。 +ACP 会话既可以是交互式工作区,也可以是由父级拥有的后台工作。投递路径取决于它的形态。 ### 交互式 ACP 会话 交互式会话旨在持续在可见聊天界面中对话: -- `/acp spawn ... --bind here` 将当前对话绑定到 ACP 会话。 -- `/acp spawn ... --thread ...` 将渠道线程/话题绑定到 ACP 会话。 -- 持久化配置的 `bindings[].type="acp"` 会将匹配的对话路由到同一个 ACP 会话。 +- `/acp spawn ... --bind here` 会将当前会话绑定到 ACP 会话。 +- `/acp spawn ... --thread ...` 会将某个渠道线程/话题绑定到 ACP 会话。 +- 持久化配置的 `bindings[].type="acp"` 会将匹配的会话路由到同一个 ACP 会话。 -已绑定对话中的后续消息会直接路由到 ACP 会话,而 ACP 输出会投递回同一个渠道/线程/话题。 +已绑定会话中的后续消息会直接路由到 ACP 会话,而 ACP 输出会回传到相同的渠道/线程/话题。 ### 父级拥有的一次性 ACP 会话 -由另一个智能体运行启动的一次性 ACP 会话属于后台子会话,类似于子智能体: +由另一个智能体运行启动的一次性 ACP 会话属于后台子任务,类似于子智能体: - 父级通过 `sessions_spawn({ runtime: "acp", mode: "run" })` 请求工作。 -- 子级在其自己的 ACP harness 会话中运行。 -- 完成结果通过内部任务完成通知路径回报。 -- 当需要面向用户的回复时,父级会以普通助手口吻重写子级结果。 +- 子级在自己的 ACP harness 会话中运行。 +- 完成情况通过内部任务完成播报路径回传。 +- 当需要面向用户的回复时,父级会用正常 assistant 语气重写子级结果。 -不要将此路径视为父级与子级之间的点对点聊天。子级已经有一个返回父级的完成通道。 +不要将此路径视为父子之间的点对点聊天。子级本身已经有一条回传给父级的完成通道。 ### `sessions_send` 与 A2A 投递 -`sessions_send` 可在启动后将目标指向另一个会话。对于普通对等会话,OpenClaw 在注入消息后使用智能体到智能体(A2A)的后续路径: +在启动之后,`sessions_send` 可以以另一个会话为目标。对于普通对等会话,OpenClaw 会在注入消息后使用一条智能体到智能体(A2A)的后续路径: - 等待目标会话的回复 -- 可选地允许请求方与目标交换有限次数的后续轮次 -- 要求目标生成一条通知消息 -- 将该通知投递到可见渠道或线程 +- 可选地让请求者与目标进行有限轮次的后续交互 +- 要求目标生成一条 announce 消息 +- 将该 announce 投递到可见的渠道或线程 -对于发送方需要可见后续结果的对等发送,A2A 路径是一种回退机制。当不相关会话能够看到并向 ACP 目标发送消息时,例如在较宽泛的 `tools.sessions.visibility` 设置下,该路径仍会保持启用。 +这条 A2A 路径是对等发送的回退方案,用于发送方需要一个可见后续回复的场景。当某个无关会话可以看见并向 ACP 目标发消息时,例如在较宽松的 `tools.sessions.visibility` 设置下,它仍会保持启用。 -只有当请求方是其自有、由父级拥有的一次性 ACP 子会话的父级时,OpenClaw 才会跳过 A2A 后续。在这种情况下,如果在任务完成之上再运行 A2A,可能会因子级结果唤醒父级,再将父级回复转发回子级,从而形成父子回声循环。对于这种“自有子会话”情况,`sessions_send` 结果会报告 `delivery.status="skipped"`,因为完成路径已经负责处理结果。 +仅当请求者是其自己所拥有的父级拥有型一次性 ACP 子会话的父级时,OpenClaw 才会跳过 A2A 后续。在这种情况下,如果在任务完成之上再运行 A2A,可能会用子级结果唤醒父级,再把父级回复转发回子级,从而形成父子回声循环。对于这种拥有型子级情况,`sessions_send` 结果会报告 `delivery.status="skipped"`,因为结果已经由完成路径负责处理。 ### 恢复现有会话 -使用 `resumeSessionId` 可继续先前的 ACP 会话,而不是重新开始。智能体会通过 `session/load` 重放其对话历史,因此它会带着之前的完整上下文继续工作。 +使用 `resumeSessionId` 可以继续之前的 ACP 会话,而不是重新开始。智能体会通过 `session/load` 重放其会话历史,因此会带着完整的先前上下文继续。 ```json { @@ -422,41 +421,38 @@ ACP 会话既可以是交互式工作区,也可以是由父级拥有的后台 常见用例: -- 将一个 Codex 会话从你的笔记本电脑切换到手机上 —— 告诉你的智能体从你上次离开的地方继续 -- 继续一个你先前在 CLI 中交互式启动、现在通过智能体无头运行的编程会话 +- 将 Codex 会话从你的笔记本交接到手机 —— 告诉你的智能体从你上次停下的地方继续 +- 继续你之前在 CLI 中以交互方式启动、现在要通过智能体无头继续的 coding 会话 - 接着处理因 Gateway 网关重启或空闲超时而中断的工作 说明: -- `resumeSessionId` 需要 `runtime: "acp"` —— 如果与子智能体运行时一起使用,会返回错误。 -- `resumeSessionId` 会恢复上游 ACP 对话历史;`thread` 和 `mode` 仍会正常应用于你正在创建的新 OpenClaw 会话,因此 `mode: "session"` 仍需要 `thread: true`。 +- `resumeSessionId` 需要 `runtime: "acp"` —— 若与子智能体运行时一起使用会返回错误。 +- `resumeSessionId` 会恢复上游 ACP 会话历史;`thread` 和 `mode` 仍会像平常一样作用于你正在创建的新 OpenClaw 会话,因此 `mode: "session"` 仍需要 `thread: true`。 - 目标智能体必须支持 `session/load`(Codex 和 Claude Code 支持)。 -- 如果找不到该会话 id,启动会以明确错误失败 —— 不会静默回退到新会话。 +- 如果找不到该会话 ID,启动会以清晰的错误失败 —— 不会静默回退到新会话。 -### 操作员冒烟测试 +### 面向操作人员的 smoke 测试 -当 Gateway 网关部署完成后,如果你希望快速进行一次在线检查,确认 ACP 启动 -确实能端到端正常工作,而不仅仅是通过单元测试,请使用此方法。 +在 Gateway 网关部署之后,如果你想快速进行一次 live 检查,以确认 ACP 启动在端到端路径上确实可用,而不只是通过了单元测试,请使用此方法。 -推荐检查流程: +推荐检查门槛: -1. 在目标主机上验证已部署的 Gateway 网关版本/提交。 -2. 确认已部署源码包含 ACP 血缘关系接受逻辑,位置在 - `src/gateway/sessions-patch.ts`(`subagent:* or acp:* sessions`)。 -3. 打开一个临时 ACPX bridge 会话,连接到在线智能体(例如 - `jpclawhq` 上的 `razor(main)`)。 -4. 要求该智能体调用 `sessions_spawn`,参数如下: +1. 在目标宿主机上验证已部署的 Gateway 网关版本/提交。 +2. 确认已部署源码在 `src/gateway/sessions-patch.ts` 中包含 ACP 谱系接受逻辑(`subagent:* or acp:* sessions`)。 +3. 打开一个到 live 智能体的临时 ACPX 桥接会话(例如 `jpclawhq` 上的 `razor(main)`)。 +4. 让该智能体调用 `sessions_spawn`,参数如下: - `runtime: "acp"` - `agentId: "codex"` - `mode: "run"` - task:`Reply with exactly LIVE-ACP-SPAWN-OK` -5. 验证该智能体报告: +5. 验证智能体报告: - `accepted=yes` - 一个真实的 `childSessionKey` - 没有校验器错误 -6. 清理临时 ACPX bridge 会话。 +6. 清理临时 ACPX 桥接会话。 -发送给在线智能体的示例提示: +发给 live 智能体的示例提示: ```text Use the sessions_spawn tool now with runtime: "acp", agentId: "codex", and mode: "run". @@ -466,26 +462,26 @@ Then report only: accepted=; childSessionKey=; error=` | -| `/acp steer` | 向正在运行的会话发送引导指令。 | `/acp steer --session support inbox prioritize failing tests` | +| `/acp cancel` | 取消目标会话中正在进行的轮次。 | `/acp cancel agent:codex:acp:` | +| `/acp steer` | 向运行中的会话发送引导指令。 | `/acp steer --session support inbox prioritize failing tests` | | `/acp close` | 关闭会话并解绑线程目标。 | `/acp close` | -| `/acp status` | 显示后端、模式、状态、运行时选项、能力。 | `/acp status` | +| `/acp status` | 显示后端、模式、状态、运行时选项和能力。 | `/acp status` | | `/acp set-mode` | 为目标会话设置运行时模式。 | `/acp set-mode plan` | | `/acp set` | 通用运行时配置项写入。 | `/acp set model openai/gpt-5.4` | -| `/acp cwd` | 设置运行时工作目录覆盖值。 | `/acp cwd /Users/user/Projects/repo` | +| `/acp cwd` | 设置运行时工作目录覆盖。 | `/acp cwd /Users/user/Projects/repo` | | `/acp permissions` | 设置审批策略配置文件。 | `/acp permissions strict` | | `/acp timeout` | 设置运行时超时(秒)。 | `/acp timeout 120` | -| `/acp model` | 设置运行时模型覆盖值。 | `/acp model anthropic/claude-opus-4-6` | -| `/acp reset-options` | 移除会话运行时选项覆盖值。 | `/acp reset-options` | +| `/acp model` | 设置运行时模型覆盖。 | `/acp model anthropic/claude-opus-4-6` | +| `/acp reset-options` | 移除会话运行时选项覆盖。 | `/acp reset-options` | | `/acp sessions` | 列出存储中的最近 ACP 会话。 | `/acp sessions` | -| `/acp doctor` | 后端健康状态、能力、可执行修复。 | `/acp doctor` | -| `/acp install` | 输出确定性的安装和启用步骤。 | `/acp install` | +| `/acp doctor` | 后端健康状态、能力和可执行修复建议。 | `/acp doctor` | +| `/acp install` | 打印确定性的安装和启用步骤。 | `/acp install` | -`/acp sessions` 会读取当前绑定会话或请求方会话的存储。接受 `session-key`、`session-id` 或 `session-label` 标记的命令,会通过 Gateway 网关会话发现来解析目标,包括每个智能体自定义的 `session.store` 根目录。 +`/acp sessions` 会读取当前绑定会话或请求者会话对应的存储。接受 `session-key`、`session-id` 或 `session-label` token 的命令,会通过 Gateway 网关会话发现来解析目标,包括按智能体自定义的 `session.store` 根目录。 ## 运行时选项映射 -`/acp` 提供便捷命令和一个通用设置器。 +`/acp` 同时提供便捷命令和通用设置器。 -等效操作: +等价操作: - `/acp model ` 映射到运行时配置键 `model`。 - `/acp permissions ` 映射到运行时配置键 `approval_policy`。 - `/acp timeout ` 映射到运行时配置键 `timeout`。 -- `/acp cwd ` 直接更新运行时 cwd 覆盖值。 +- `/acp cwd ` 会直接更新运行时 `cwd` 覆盖。 - `/acp set ` 是通用路径。 - - 特殊情况:`key=cwd` 使用 cwd 覆盖路径。 -- `/acp reset-options` 会清除目标会话的所有运行时覆盖值。 + - 特殊情况:`key=cwd` 会使用 `cwd` 覆盖路径。 +- `/acp reset-options` 会清除目标会话的所有运行时覆盖。 ## acpx harness 支持(当前) @@ -634,10 +630,10 @@ ACP 会话当前运行在主机运行时上,而不是在 OpenClaw 沙箱内运 - `pi` - `qwen` -当 OpenClaw 使用 acpx 后端时,除非你的 acpx 配置定义了自定义智能体别名,否则 `agentId` 优先使用这些值。 -如果你的本地 Cursor 安装仍将 ACP 暴露为 `agent acp`,请在你的 acpx 配置中覆盖 `cursor` 智能体命令,而不是修改内置默认值。 +当 OpenClaw 使用 acpx 后端时,除非你的 acpx 配置定义了自定义智能体别名,否则优先将这些值用作 `agentId`。 +如果你的本地 Cursor 安装仍将 ACP 暴露为 `agent acp`,请在 acpx 配置中覆盖 `cursor` 智能体命令,而不是修改内置默认值。 -直接使用 acpx CLI 也可以通过 `--agent ` 指向任意适配器,但这个原始逃生口是 acpx CLI 功能(不是标准的 OpenClaw `agentId` 路径)。 +直接使用 acpx CLI 也可以通过 `--agent ` 定位任意适配器,但这类原始逃生口是 acpx CLI 功能(而不是常规的 OpenClaw `agentId` 路径)。 ## 必需配置 @@ -647,7 +643,7 @@ ACP 会话当前运行在主机运行时上,而不是在 OpenClaw 沙箱内运 { acp: { enabled: true, - // 可选。默认是 true;设为 false 可暂停 ACP 调度,同时保留 /acp 控制。 + // 可选。默认值为 true;设为 false 可暂停 ACP 调度,同时保留 /acp 控制。 dispatch: { enabled: true }, backend: "acpx", defaultAgent: "codex", @@ -679,7 +675,7 @@ ACP 会话当前运行在主机运行时上,而不是在 OpenClaw 沙箱内运 } ``` -线程绑定配置取决于具体渠道适配器。Discord 示例: +线程绑定配置取决于具体的渠道适配器。Discord 示例: ```json5 { @@ -701,27 +697,25 @@ ACP 会话当前运行在主机运行时上,而不是在 OpenClaw 沙箱内运 } ``` -如果绑定到线程的 ACP 启动无法工作,请先验证适配器功能标志: +如果线程绑定的 ACP 启动无法工作,请先验证适配器功能开关: - Discord:`channels.discord.threadBindings.spawnAcpSessions=true` -当前对话绑定不需要创建子线程。它们需要活动对话上下文,以及暴露 ACP 对话绑定能力的渠道适配器。 +当前会话绑定不要求创建子线程。它们要求存在活动会话上下文,以及一个暴露 ACP 会话绑定能力的渠道适配器。 参见[配置参考](/zh-CN/gateway/configuration-reference)。 ## acpx 后端的插件设置 -全新安装默认启用内置的 `acpx` 运行时插件,因此 ACP -通常无需手动安装插件即可工作。 +全新安装默认会启用内置的 `acpx` 运行时插件,因此 ACP 通常无需手动安装插件即可工作。 -请从以下命令开始: +先运行: ```text /acp doctor ``` -如果你禁用了 `acpx`、通过 `plugins.allow` / `plugins.deny` 拒绝了它,或者想 -切换到本地开发检出版本,请使用显式插件路径: +如果你禁用了 `acpx`、通过 `plugins.allow` / `plugins.deny` 拒绝了它,或者想切换到本地开发 checkout,请使用显式插件路径: ```bash openclaw plugins install acpx @@ -742,14 +736,14 @@ openclaw plugins install ./path/to/local/acpx-plugin ### acpx 命令和版本配置 -默认情况下,内置的 acpx 后端插件(`acpx`)使用插件本地固定版本的二进制文件: +默认情况下,内置的 acpx 后端插件(`acpx`)会使用插件本地固定版本的二进制文件: 1. 命令默认指向 ACPX 插件包内部插件本地的 `node_modules/.bin/acpx`。 2. 预期版本默认使用扩展固定版本。 3. 启动时会立即将 ACP 后端注册为未就绪。 -4. 后台 ensure 任务会校验 `acpx --version`。 +4. 后台 ensure 任务会验证 `acpx --version`。 5. 如果插件本地二进制文件缺失或版本不匹配,它会运行: - `npm install --omit=dev --no-save acpx@` 并重新校验。 + `npm install --omit=dev --no-save acpx@`,然后重新验证。 你可以在插件配置中覆盖命令/版本: @@ -771,147 +765,134 @@ openclaw plugins install ./path/to/local/acpx-plugin 说明: -- `command` 接受绝对路径、相对路径或命令名(`acpx`)。 -- 相对路径从 OpenClaw 工作区目录解析。 +- `command` 接受绝对路径、相对路径或命令名称(`acpx`)。 +- 相对路径相对于 OpenClaw 工作区目录解析。 - `expectedVersion: "any"` 会禁用严格版本匹配。 -- 当 `command` 指向自定义二进制文件/路径时,会禁用插件本地自动安装。 -- 在后端健康检查运行期间,OpenClaw 启动仍保持非阻塞。 +- 当 `command` 指向自定义二进制文件/路径时,插件本地自动安装会被禁用。 +- 在后端健康检查运行期间,OpenClaw 启动仍然保持非阻塞。 参见[插件](/zh-CN/tools/plugin)。 -### 自动安装依赖项 +### 自动依赖安装 -当你通过 `npm install -g openclaw` 全局安装 OpenClaw 时,acpx -运行时依赖项(平台特定二进制文件)会通过 postinstall 钩子自动安装。 -如果自动安装失败,Gateway 网关仍会正常启动, -并通过 `openclaw acp doctor` 报告缺失的依赖项。 +当你通过 `npm install -g openclaw` 全局安装 OpenClaw 时,acpx 运行时依赖(平台相关二进制文件)会通过 postinstall hook 自动安装。如果自动安装失败,Gateway 网关仍会正常启动,并通过 `openclaw acp doctor` 报告缺失的依赖。 -### 插件工具 MCP bridge +### 插件工具 MCP 桥接 -默认情况下,ACPX 会话**不会**将 OpenClaw 插件注册的工具暴露给 -ACP harness。 +默认情况下,ACPX 会话**不会**向 ACP harness 暴露 OpenClaw 已注册的插件工具。 -如果你希望 Codex 或 Claude Code 之类的 ACP 智能体能够调用已安装的 -OpenClaw 插件工具,例如 memory recall/store,请启用专用 bridge: +如果你希望像 Codex 或 Claude Code 这样的 ACP 智能体可以调用已安装的 OpenClaw 插件工具,例如 memory recall/store,请启用专用桥接: ```bash openclaw config set plugins.entries.acpx.config.pluginToolsMcpBridge true ``` -这样做会: +这会执行以下操作: -- 在 ACPX 会话引导过程中注入一个名为 `openclaw-plugin-tools` 的内置 MCP 服务器。 -- 暴露已安装并启用的 OpenClaw 插件已经注册的插件工具。 -- 保持该功能为显式启用,且默认关闭。 +- 在 ACPX 会话引导中注入一个名为 `openclaw-plugin-tools` 的内置 MCP 服务器。 +- 暴露已安装并启用的 OpenClaw 插件所注册的插件工具。 +- 使该功能保持显式启用,且默认关闭。 -安全和信任说明: +安全性和信任说明: -- 这会扩大 ACP harness 的工具暴露面。 -- ACP 智能体只能访问 Gateway 网关中已激活的插件工具。 -- 将其视为与允许这些插件在 OpenClaw 本身中执行相同的信任边界。 -- 启用前请检查已安装的插件。 +- 这会扩大 ACP harness 的工具面。 +- ACP 智能体只能访问 Gateway 网关中已经激活的插件工具。 +- 应将它视为与允许这些插件在 OpenClaw 本身中执行相同的信任边界。 +- 启用前请审查已安装的插件。 -自定义 `mcpServers` 仍会像以前一样工作。内置插件工具 bridge 是 -额外的可选便捷功能,而不是通用 MCP 服务器配置的替代方案。 +自定义 `mcpServers` 仍像以前一样可用。内置的插件工具桥接是额外的可选便利功能,而不是通用 MCP 服务器配置的替代品。 -### OpenClaw 工具 MCP bridge +### OpenClaw 工具 MCP 桥接 -默认情况下,ACPX 会话也**不会**通过 -MCP 暴露内置的 OpenClaw 工具。当 ACP 智能体需要选定的 -内置工具(如 `cron`)时,请启用独立的核心工具 bridge: +默认情况下,ACPX 会话也**不会**通过 MCP 暴露内置 OpenClaw 工具。当 ACP 智能体需要某些选定的内置工具(例如 `cron`)时,请启用单独的核心工具桥接: ```bash openclaw config set plugins.entries.acpx.config.openClawToolsMcpBridge true ``` -这样做会: +这会执行以下操作: -- 在 ACPX 会话引导过程中注入一个名为 `openclaw-tools` 的内置 MCP 服务器。 -- 暴露选定的内置 OpenClaw 工具。初始服务器暴露 `cron`。 -- 保持核心工具暴露为显式启用,且默认关闭。 +- 在 ACPX 会话引导中注入一个名为 `openclaw-tools` 的内置 MCP 服务器。 +- 暴露选定的内置 OpenClaw 工具。初始服务器会暴露 `cron`。 +- 使核心工具暴露保持显式启用,且默认关闭。 ### 运行时超时配置 -内置 `acpx` 插件默认将嵌入式运行时轮次设置为 120 秒 -超时。这为 Gemini CLI 等较慢的 harness 留出了足够时间完成 -ACP 启动和初始化。如果你的主机需要不同的 -运行时限制,可以覆盖它: +内置的 `acpx` 插件默认将嵌入式运行时轮次的超时设为 120 秒。这为 Gemini CLI 之类较慢的 harness 预留了足够时间,以完成 ACP 启动和初始化。如果你的宿主需要不同的运行时限制,可以覆盖此值: ```bash openclaw config set plugins.entries.acpx.config.timeoutSeconds 180 ``` -修改此值后请重启 Gateway 网关。 +更改此值后请重启 Gateway 网关。 -### 健康探测智能体配置 +### 健康探针智能体配置 -内置的 `acpx` 插件在判断嵌入式运行时后端是否就绪时, -会探测一个 harness 智能体。默认是 `codex`。如果你的部署 -使用不同的默认 ACP 智能体,请将探测智能体设置为相同 id: +内置的 `acpx` 插件在判断嵌入式运行时后端是否就绪时,会探测一个 harness 智能体。默认值为 `codex`。如果你的部署使用其他默认 ACP 智能体,请将探针智能体设为相同 id: ```bash openclaw config set plugins.entries.acpx.config.probeAgent claude ``` -修改此值后请重启 Gateway 网关。 +更改此值后请重启 Gateway 网关。 ## 权限配置 ACP 会话以非交互方式运行 —— 没有 TTY 可用于批准或拒绝文件写入和 shell 执行权限提示。acpx 插件提供两个配置键来控制权限处理方式: -这些 ACPX harness 权限与 OpenClaw exec 审批是分开的,也与 CLI 后端厂商绕过标志分开,例如 Claude CLI `--permission-mode bypassPermissions`。ACPX 的 `approve-all` 是 ACP 会话在 harness 级别的紧急放行开关。 +这些 ACPX harness 权限与 OpenClaw exec 审批是分开的,也与 CLI 后端的厂商绕过标志分开,例如 Claude CLI 的 `--permission-mode bypassPermissions`。对于 ACP 会话,ACPX 的 `approve-all` 是 harness 级别的 break-glass 开关。 ### `permissionMode` -控制 harness 智能体在无需提示的情况下可执行哪些操作。 +控制 harness 智能体无需提示即可执行哪些操作。 -| 值 | 行为 | -| --------------- | --------------------------------------------------------- | -| `approve-all` | 自动批准所有文件写入和 shell 命令。 | -| `approve-reads` | 仅自动批准读取;写入和执行需要提示。 | -| `deny-all` | 拒绝所有权限提示。 | +| 值 | 行为 | +| --------------- | --------------------------------------------- | +| `approve-all` | 自动批准所有文件写入和 shell 命令。 | +| `approve-reads` | 仅自动批准读取;写入和 exec 仍需要提示。 | +| `deny-all` | 拒绝所有权限提示。 | ### `nonInteractivePermissions` -控制本应显示权限提示、但没有可交互 TTY 可用时会发生什么(对于 ACP 会话,这种情况始终成立)。 +控制在本应显示权限提示、但没有可交互 TTY 可用时会发生什么(ACP 会话始终属于这种情况)。 -| 值 | 行为 | -| ------ | ----------------------------------------------------------------- | -| `fail` | 以 `AcpRuntimeError` 中止会话。**(默认)** | -| `deny` | 静默拒绝该权限并继续(平滑降级)。 | +| 值 | 行为 | +| ------ | ----------------------------------------------------------- | +| `fail` | 以 `AcpRuntimeError` 中止会话。**(默认)** | +| `deny` | 静默拒绝该权限并继续(平滑降级)。 | ### 配置 -通过插件配置设置: +通过插件配置进行设置: ```bash openclaw config set plugins.entries.acpx.config.permissionMode approve-all openclaw config set plugins.entries.acpx.config.nonInteractivePermissions fail ``` -修改这些值后请重启 Gateway 网关。 +更改这些值后请重启 Gateway 网关。 -> **重要:** OpenClaw 当前默认使用 `permissionMode=approve-reads` 和 `nonInteractivePermissions=fail`。在非交互式 ACP 会话中,任何触发权限提示的写入或执行操作都可能因 `AcpRuntimeError: Permission prompt unavailable in non-interactive mode` 而失败。 +> **重要:** OpenClaw 当前默认使用 `permissionMode=approve-reads` 和 `nonInteractivePermissions=fail`。在非交互式 ACP 会话中,任何触发权限提示的写入或 exec 都可能因 `AcpRuntimeError: Permission prompt unavailable in non-interactive mode` 而失败。 > -> 如果你需要限制权限,请将 `nonInteractivePermissions` 设置为 `deny`,这样会话会平滑降级,而不是崩溃。 +> 如果你需要限制权限,请将 `nonInteractivePermissions` 设为 `deny`,这样会话就会平滑降级,而不是直接崩溃。 ## 故障排除 | 症状 | 可能原因 | 修复方法 | -| --------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| ---- | -------- | -------- | | `ACP runtime backend is not configured` | 后端插件缺失或已禁用。 | 安装并启用后端插件,然后运行 `/acp doctor`。 | -| `ACP is disabled by policy (acp.enabled=false)` | ACP 已被全局禁用。 | 设置 `acp.enabled=true`。 | -| `ACP dispatch is disabled by policy (acp.dispatch.enabled=false)` | 来自普通线程消息的调度已禁用。 | 设置 `acp.dispatch.enabled=true`。 | -| `ACP agent "" is not allowed by policy` | 智能体不在允许列表中。 | 使用允许的 `agentId` 或更新 `acp.allowedAgents`。 | -| `Unable to resolve session target: ...` | key/id/label 标记错误。 | 运行 `/acp sessions`,复制准确的 key/label,然后重试。 | -| `--bind here requires running /acp spawn inside an active ... conversation` | 在没有活动可绑定对话的情况下使用了 `--bind here`。 | 移动到目标聊天/渠道后重试,或使用未绑定启动。 | -| `Conversation bindings are unavailable for .` | 适配器缺少当前对话 ACP 绑定能力。 | 在支持时使用 `/acp spawn ... --thread ...`,配置顶层 `bindings[]`,或切换到受支持的渠道。 | +| `ACP is disabled by policy (acp.enabled=false)` | ACP 在全局范围内被禁用。 | 设置 `acp.enabled=true`。 | +| `ACP dispatch is disabled by policy (acp.dispatch.enabled=false)` | 普通线程消息的调度已禁用。 | 设置 `acp.dispatch.enabled=true`。 | +| `ACP agent "" is not allowed by policy` | 智能体不在允许列表中。 | 使用允许的 `agentId`,或更新 `acp.allowedAgents`。 | +| `Unable to resolve session target: ...` | 错误的 key/id/label token。 | 运行 `/acp sessions`,复制精确的 key/label,然后重试。 | +| `--bind here requires running /acp spawn inside an active ... conversation` | 在没有活动且可绑定会话的情况下使用了 `--bind here`。 | 移动到目标聊天/渠道后重试,或使用不绑定的启动方式。 | +| `Conversation bindings are unavailable for .` | 适配器缺少当前会话 ACP 绑定能力。 | 在受支持时使用 `/acp spawn ... --thread ...`,配置顶层 `bindings[]`,或切换到受支持的渠道。 | | `--thread here requires running /acp spawn inside an active ... thread` | 在线程上下文之外使用了 `--thread here`。 | 移动到目标线程,或使用 `--thread auto`/`off`。 | -| `Only can rebind this channel/conversation/thread.` | 另一个用户拥有当前活动绑定目标。 | 由拥有者重新绑定,或使用其他对话或线程。 | +| `Only can rebind this channel/conversation/thread.` | 另一个用户拥有当前活动绑定目标。 | 由所有者重新绑定,或使用其他会话或线程。 | | `Thread bindings are unavailable for .` | 适配器缺少线程绑定能力。 | 使用 `--thread off`,或切换到受支持的适配器/渠道。 | -| `Sandboxed sessions cannot spawn ACP sessions ...` | ACP 运行时位于主机侧;请求方会话处于沙箱隔离中。 | 在沙箱隔离会话中使用 `runtime="subagent"`,或从非沙箱隔离会话发起 ACP 启动。 | -| `sessions_spawn sandbox="require" is unsupported for runtime="acp" ...` | 为 ACP 运行时请求了 `sandbox="require"`。 | 对需要沙箱隔离的情况使用 `runtime="subagent"`,或从非沙箱隔离会话中使用带 `sandbox="inherit"` 的 ACP。 | -| 绑定会话缺少 ACP 元数据 | ACP 会话元数据已过期/被删除。 | 使用 `/acp spawn` 重新创建,然后重新绑定/聚焦线程。 | -| `AcpRuntimeError: Permission prompt unavailable in non-interactive mode` | `permissionMode` 在非交互式 ACP 会话中阻止写入/执行。 | 将 `plugins.entries.acpx.config.permissionMode` 设置为 `approve-all` 并重启 Gateway 网关。参见[权限配置](#permission-configuration)。 | -| ACP 会话很早失败且几乎没有输出 | 权限提示被 `permissionMode`/`nonInteractivePermissions` 阻止。 | 检查 Gateway 网关日志中的 `AcpRuntimeError`。若需完整权限,设置 `permissionMode=approve-all`;若需平滑降级,设置 `nonInteractivePermissions=deny`。 | -| ACP 会话在完成工作后无限期卡住 | harness 进程已结束,但 ACP 会话未报告完成。 | 使用 `ps aux \| grep acpx` 监控;手动终止陈旧进程。 | +| `Sandboxed sessions cannot spawn ACP sessions ...` | ACP 运行时位于宿主侧;请求者会话处于沙箱中。 | 在沙箱会话中使用 `runtime="subagent"`,或从非沙箱会话中运行 ACP 启动。 | +| `sessions_spawn sandbox="require" is unsupported for runtime="acp" ...` | 为 ACP 运行时请求了 `sandbox="require"`。 | 对于必需的沙箱隔离,请使用 `runtime="subagent"`;或者从非沙箱会话中配合 `sandbox="inherit"` 使用 ACP。 | +| 已绑定会话缺少 ACP 元数据 | ACP 会话元数据已过期/被删除。 | 使用 `/acp spawn` 重新创建,然后重新绑定/聚焦线程。 | +| `AcpRuntimeError: Permission prompt unavailable in non-interactive mode` | `permissionMode` 在非交互式 ACP 会话中阻止了写入/exec。 | 将 `plugins.entries.acpx.config.permissionMode` 设为 `approve-all`,并重启 Gateway 网关。参见[权限配置](#permission-configuration)。 | +| ACP 会话很早失败且输出很少 | 权限提示被 `permissionMode`/`nonInteractivePermissions` 阻止。 | 检查 Gateway 网关日志中的 `AcpRuntimeError`。若要完全开放权限,请设 `permissionMode=approve-all`;若要平滑降级,请设 `nonInteractivePermissions=deny`。 | +| ACP 会话在完成工作后无限期停滞 | Harness 进程已结束,但 ACP 会话未报告完成。 | 使用 `ps aux \| grep acpx` 监控;手动杀掉陈旧进程。 | diff --git a/docs/zh-CN/tools/slash-commands.md b/docs/zh-CN/tools/slash-commands.md index a2506f72b..2312ef112 100644 --- a/docs/zh-CN/tools/slash-commands.md +++ b/docs/zh-CN/tools/slash-commands.md @@ -2,35 +2,35 @@ read_when: - 使用或配置聊天命令 - 调试命令路由或权限 -summary: 斜杠命令:文本版与原生版、配置以及受支持的命令 +summary: 斜杠命令:文本与原生、配置以及支持的命令 title: 斜杠命令 x-i18n: - generated_at: "2026-04-23T06:43:54Z" + generated_at: "2026-04-23T07:06:41Z" model: gpt-5.4 provider: openai - source_hash: d591ba4e692d77ca5b4549987ad9db557fc5c6d00a3f152381b74eae73c4ea81 + source_hash: 0f6b454afa77cf02b2c307efcc99ef35d002cb560c427affaf03ac12b2b666e8 source_path: tools/slash-commands.md workflow: 15 --- # 斜杠命令 -命令由 Gateway 网关处理。大多数命令必须作为以 `/` 开头的**独立**消息发送。 -仅限主机的 bash 聊天命令使用 `! `(`/bash ` 是其别名)。 +命令由 Gateway 网关处理。大多数命令必须作为**独立**消息发送,并且以 `/` 开头。 +仅主机可用的 bash 聊天命令使用 `! `(`/bash ` 是其别名)。 这里有两个相关系统: - **命令**:独立的 `/...` 消息。 - **指令**:`/think`、`/fast`、`/verbose`、`/trace`、`/reasoning`、`/elevated`、`/exec`、`/model`、`/queue`。 - - 指令会在模型看到消息之前从消息中剥离。 - - 在普通聊天消息中(非纯指令消息),它们会被视为“内联提示”,且**不会**持久化会话设置。 - - 在纯指令消息中(消息只包含指令),它们会持久化到会话,并回复一条确认信息。 - - 指令只会应用于**已授权发送者**。如果设置了 `commands.allowFrom`,它就是唯一使用的 - allowlist;否则授权来自渠道 allowlist/配对以及 `commands.useAccessGroups`。 - 未授权发送者会看到指令被当作普通文本处理。 + - 指令会在模型看到消息前被剥离。 + - 在普通聊天消息中(非纯指令消息),它们会被视为“内联提示”,并且**不会**持久化会话设置。 + - 在纯指令消息中(消息仅包含指令),它们会持久化到会话,并回复一条确认信息。 + - 指令仅对**已授权发送者**生效。如果设置了 `commands.allowFrom`,它就是唯一使用的 + allowlist;否则授权来源于渠道 allowlist/配对,以及 `commands.useAccessGroups`。 + 未授权发送者看到的指令会被当作普通文本处理。 -还有少量**内联快捷命令**(仅限 allowlist/已授权发送者):`/help`、`/commands`、`/status`、`/whoami`(`/id`)。 -它们会立即运行,在模型看到消息前被剥离,剩余文本会继续走正常流程。 +还有一些**内联快捷方式**(仅 allowlist/已授权发送者可用):`/help`、`/commands`、`/status`、`/whoami`(`/id`)。 +它们会立即运行,在模型看到消息前被剥离,剩余文本则继续按正常流程处理。 ## 配置 @@ -60,86 +60,88 @@ x-i18n: ``` - `commands.text`(默认 `true`)启用在聊天消息中解析 `/...`。 - - 在没有原生命令的界面上(WhatsApp/WebChat/Signal/iMessage/Google Chat/Microsoft Teams),即使你将其设为 `false`,文本命令仍然可用。 + - 在没有原生命令的界面上(WhatsApp/WebChat/Signal/iMessage/Google Chat/Microsoft Teams),即使你将其设置为 `false`,文本命令仍然可用。 - `commands.native`(默认 `"auto"`)注册原生命令。 - - Auto:Discord/Telegram 上开启;Slack 上关闭(直到你添加 slash commands);对于不支持原生能力的提供商会被忽略。 - - 可设置 `channels.discord.commands.native`、`channels.telegram.commands.native` 或 `channels.slack.commands.native`,以按提供商覆盖(布尔值或 `"auto"`)。 - - `false` 会在启动时清除 Discord/Telegram 上先前注册的命令。Slack 命令在 Slack 应用中管理,不会自动移除。 -- `commands.nativeSkills`(默认 `"auto"`)会在支持时以原生方式注册 **skill** 命令。 - - Auto:Discord/Telegram 上开启;Slack 上关闭(Slack 需要为每个 skill 单独创建一个 slash command)。 - - 可设置 `channels.discord.commands.nativeSkills`、`channels.telegram.commands.nativeSkills` 或 `channels.slack.commands.nativeSkills`,以按提供商覆盖(布尔值或 `"auto"`)。 -- `commands.bash`(默认 `false`)启用 `! ` 来运行主机 shell 命令(`/bash ` 是别名;需要 `tools.elevated` allowlist)。 -- `commands.bashForegroundMs`(默认 `2000`)控制 bash 在切换到后台模式前等待多久(`0` 表示立即转入后台)。 + - 自动:对 Discord/Telegram 开启;对 Slack 关闭(直到你添加 slash commands);对不支持原生命令的提供商忽略。 + - 设置 `channels.discord.commands.native`、`channels.telegram.commands.native` 或 `channels.slack.commands.native` 可按提供商覆盖(布尔值或 `"auto"`)。 + - `false` 会在启动时清除先前在 Discord/Telegram 上注册的命令。Slack 命令由 Slack 应用管理,不会自动移除。 +- `commands.nativeSkills`(默认 `"auto"`)在支持时原生注册 **skill** 命令。 + - 自动:对 Discord/Telegram 开启;对 Slack 关闭(Slack 要求为每个 skill 创建一个斜杠命令)。 + - 设置 `channels.discord.commands.nativeSkills`、`channels.telegram.commands.nativeSkills` 或 `channels.slack.commands.nativeSkills` 可按提供商覆盖(布尔值或 `"auto"`)。 +- `commands.bash`(默认 `false`)启用 `! ` 以运行主机 shell 命令(`/bash ` 是别名;需要 `tools.elevated` allowlist)。 +- `commands.bashForegroundMs`(默认 `2000`)控制 bash 在切换到后台模式前等待多久(`0` 表示立即放到后台)。 - `commands.config`(默认 `false`)启用 `/config`(读取/写入 `openclaw.json`)。 - `commands.mcp`(默认 `false`)启用 `/mcp`(读取/写入由 OpenClaw 管理的 `mcp.servers` 下的 MCP 配置)。 - `commands.plugins`(默认 `false`)启用 `/plugins`(插件发现/状态,以及安装 + 启用/禁用控制)。 - `commands.debug`(默认 `false`)启用 `/debug`(仅运行时覆盖)。 - `commands.restart`(默认 `true`)启用 `/restart` 以及 Gateway 网关重启工具操作。 -- `commands.ownerAllowFrom`(可选)为仅限所有者的命令/工具界面设置显式所有者 allowlist。这与 `commands.allowFrom` 是分开的。 -- 每渠道的 `channels..commands.enforceOwnerForCommands`(可选,默认 `false`)会让该界面上的仅限所有者命令必须由**所有者身份**才能运行。为 `true` 时,发送者必须匹配已解析的所有者候选项(例如 `commands.ownerAllowFrom` 中的条目或提供商原生所有者元数据),或者在内部消息渠道上持有内部 `operator.admin` 作用域。渠道 `allowFrom` 中的通配符条目,或空/未解析的所有者候选列表,**都不**足够——该渠道上的仅限所有者命令会以关闭默认放行的方式失败。如果你希望仅限所有者命令只受 `ownerAllowFrom` 和标准命令 allowlist 约束,请保持此项关闭。 -- `commands.ownerDisplay` 控制系统提示中所有者 id 的显示方式:`raw` 或 `hash`。 -- `commands.ownerDisplaySecret` 可选设置当 `commands.ownerDisplay="hash"` 时使用的 HMAC 密钥。 -- `commands.allowFrom`(可选)为命令授权设置按提供商划分的 allowlist。配置后,它将成为命令和指令的唯一授权来源(渠道 allowlist/配对和 `commands.useAccessGroups` 会被忽略)。使用 `"*"` 作为全局默认值;提供商特定键会覆盖它。 +- `commands.ownerAllowFrom`(可选)为仅限所有者的命令/工具界面设置显式所有者 allowlist。这与 `commands.allowFrom` 分开。 +- 每个渠道的 `channels..commands.enforceOwnerForCommands`(可选,默认 `false`)会使该界面上的仅限所有者命令必须由**所有者身份**运行。当为 `true` 时,发送者必须要么匹配某个已解析的所有者候选项(例如 `commands.ownerAllowFrom` 中的条目或提供商原生所有者元数据),要么在内部消息渠道上持有内部 `operator.admin` scope。渠道 `allowFrom` 中的通配符条目,或空的/无法解析的所有者候选列表,**都不足以**满足要求 —— 仅限所有者命令会在该渠道上以失败关闭的方式拒绝执行。如果你希望仅限所有者命令只受 `ownerAllowFrom` 和标准命令 allowlist 控制,请保持此项关闭。 +- `commands.ownerDisplay` 控制系统提示词中所有者 id 的显示方式:`raw` 或 `hash`。 +- `commands.ownerDisplaySecret` 可选设置在 `commands.ownerDisplay="hash"` 时使用的 HMAC secret。 +- `commands.allowFrom`(可选)为命令授权设置按提供商划分的 allowlist。配置后,它将成为命令和指令的 + 唯一授权来源(渠道 allowlist/配对以及 `commands.useAccessGroups` + 都会被忽略)。使用 `"*"` 作为全局默认值;提供商专用键会覆盖它。 - `commands.useAccessGroups`(默认 `true`)在未设置 `commands.allowFrom` 时,对命令强制执行 allowlist/策略。 ## 命令列表 -当前权威来源: +当前事实来源: -- 核心内置命令来自 `src/auto-reply/commands-registry.shared.ts` +- core 内置命令来自 `src/auto-reply/commands-registry.shared.ts` - 生成的 dock 命令来自 `src/auto-reply/commands-registry.data.ts` - 插件命令来自插件的 `registerCommand()` 调用 -- 你网关中的实际可用性仍取决于配置标志、渠道界面以及已安装/已启用的插件 +- 你网关上的实际可用性仍取决于配置标志、渠道界面以及已安装/启用的插件 -### 核心内置命令 +### Core 内置命令 当前可用的内置命令: -- `/new [model]` 启动新会话;`/reset` 是重置别名。 -- `/reset soft [message]` 保留当前转录,丢弃复用的 CLI 后端会话 id,并原地重新运行启动/系统提示加载。 +- `/new [model]` 启动一个新会话;`/reset` 是 reset 别名。 +- `/reset soft [message]` 保留当前转录,丢弃复用的 CLI 后端会话 id,并原地重新运行启动/系统提示词加载。 - `/compact [instructions]` 压缩会话上下文。参见 [/concepts/compaction](/zh-CN/concepts/compaction)。 - `/stop` 中止当前运行。 -- `/session idle ` 和 `/session max-age ` 管理线程绑定过期。 -- `/think ` 设置 thinking 级别。可选值来自活动模型的提供商配置文件;常见级别有 `off`、`minimal`、`low`、`medium` 和 `high`,也有仅在支持时可用的自定义级别,如 `xhigh`、`adaptive`、`max` 或二元值 `on`。别名:`/thinking`、`/t`。 +- `/session idle ` 和 `/session max-age ` 管理线程绑定过期时间。 +- `/think ` 设置思考级别。可选项来自当前模型的提供商 profile;常见级别有 `off`、`minimal`、`low`、`medium` 和 `high`,也包括仅在支持时才有的自定义级别,如 `xhigh`、`adaptive`、`max`,或二元 `on`。别名:`/thinking`、`/t`。 - `/verbose on|off|full` 切换详细输出。别名:`/v`。 -- `/trace on|off` 为当前会话切换插件跟踪输出。 -- `/fast [status|on|off]` 显示或设置快速模式。 +- `/trace on|off` 为当前会话切换插件 trace 输出。 +- `/fast [status|on|off]` 显示或设置 fast 模式。 - `/reasoning [on|off|stream]` 切换 reasoning 可见性。别名:`/reason`。 - `/elevated [on|off|ask|full]` 切换 elevated 模式。别名:`/elev`。 - `/exec host= security= ask= node=` 显示或设置 exec 默认值。 - `/model [name|#|status]` 显示或设置模型。 -- `/models [provider] [page] [limit=|size=|all]` 列出提供商或某个提供商下的模型。 +- `/models [provider] [page] [limit=|size=|all]` 列出提供商,或列出某提供商的模型。 - `/queue ` 管理队列行为(`steer`、`interrupt`、`followup`、`collect`、`steer-backlog`),以及如 `debounce:2s cap:25 drop:summarize` 之类的选项。 -- `/help` 显示简要帮助摘要。 +- `/help` 显示简短帮助摘要。 - `/commands` 显示生成的命令目录。 -- `/tools [compact|verbose]` 显示当前智能体此刻可用的工具。 +- `/tools [compact|verbose]` 显示当前智能体现在可用的能力。 - `/status` 显示运行时状态,包括可用时的提供商使用量/配额。 -- `/tasks` 列出当前会话活跃/最近的后台任务。 +- `/tasks` 列出当前会话中活跃/最近的后台任务。 - `/context [list|detail|json]` 解释上下文是如何组装的。 - `/export-session [path]` 将当前会话导出为 HTML。别名:`/export`。 -- `/export-trajectory [path]` 为当前会话导出 JSONL 轨迹包。别名:`/trajectory`。 +- `/export-trajectory [path]` 为当前会话导出一个 JSONL [trajectory bundle](/zh-CN/tools/trajectory)。别名:`/trajectory`。 - `/whoami` 显示你的发送者 id。别名:`/id`。 - `/skill [input]` 按名称运行一个 skill。 -- `/allowlist [list|add|remove] ...` 管理 allowlist 条目。仅文本版。 +- `/allowlist [list|add|remove] ...` 管理 allowlist 条目。仅文本。 - `/approve ` 处理 exec 审批提示。 -- `/btw ` 提出一个旁支问题,但不改变未来会话上下文。参见 [/tools/btw](/zh-CN/tools/btw)。 +- `/btw ` 提出一个旁路问题,而不会改变未来的会话上下文。参见 [/tools/btw](/zh-CN/tools/btw)。 - `/subagents list|kill|log|info|send|steer|spawn` 管理当前会话的子智能体运行。 - `/acp spawn|cancel|steer|close|sessions|status|set-mode|set|cwd|permissions|timeout|model|reset-options|doctor|install|help` 管理 ACP 会话和运行时选项。 -- `/focus ` 将当前 Discord 线程或 Telegram 话题/会话绑定到一个会话目标。 +- `/focus ` 将当前 Discord 线程或 Telegram topic/conversation 绑定到一个会话目标。 - `/unfocus` 移除当前绑定。 -- `/agents` 列出当前会话中线程绑定的智能体。 +- `/agents` 列出当前会话中与线程绑定的智能体。 - `/kill ` 中止一个或所有正在运行的子智能体。 -- `/steer ` 向正在运行的子智能体发送引导。别名:`/tell`。 +- `/steer ` 向一个正在运行的子智能体发送引导。别名:`/tell`。 - `/config show|get|set|unset` 读取或写入 `openclaw.json`。仅限所有者。需要 `commands.config: true`。 - `/mcp show|get|set|unset` 读取或写入 OpenClaw 管理的 `mcp.servers` 下的 MCP 服务器配置。仅限所有者。需要 `commands.mcp: true`。 - `/plugins list|inspect|show|get|install|enable|disable` 检查或修改插件状态。`/plugin` 是别名。写操作仅限所有者。需要 `commands.plugins: true`。 - `/debug show|set|unset|reset` 管理仅运行时配置覆盖。仅限所有者。需要 `commands.debug: true`。 -- `/usage off|tokens|full|cost` 控制每次响应的使用量页脚,或打印本地成本摘要。 +- `/usage off|tokens|full|cost` 控制每条响应的 usage 页脚,或输出本地成本摘要。 - `/tts on|off|status|provider|limit|summary|audio|help` 控制 TTS。参见 [/tools/tts](/zh-CN/tools/tts)。 - `/restart` 在启用时重启 OpenClaw。默认:启用;设置 `commands.restart: false` 可禁用。 - `/activation mention|always` 设置群组激活模式。 - `/send on|off|inherit` 设置发送策略。仅限所有者。 -- `/bash ` 运行主机 shell 命令。仅文本版。别名:`! `。需要 `commands.bash: true` 加 `tools.elevated` allowlist。 +- `/bash ` 运行主机 shell 命令。仅文本。别名:`! `。需要 `commands.bash: true` 加上 `tools.elevated` allowlist。 - `!poll [sessionId]` 检查后台 bash 作业。 - `!stop [sessionId]` 停止后台 bash 作业。 @@ -156,13 +158,13 @@ Dock 命令由支持原生命令的渠道插件生成。当前内置集合: 内置插件可以添加更多斜杠命令。此仓库中当前的内置命令: -- `/dreaming [on|off|status|help]` 切换记忆 Dreaming。参见 [Dreaming](/zh-CN/concepts/dreaming)。 +- `/dreaming [on|off|status|help]` 切换 memory Dreaming。参见 [Dreaming](/zh-CN/concepts/dreaming)。 - `/pair [qr|status|pending|approve|cleanup|notify]` 管理设备配对/设置流程。参见 [Pairing](/zh-CN/channels/pairing)。 - `/phone status|arm [duration]|disarm` 临时启用高风险手机节点命令。 -- `/voice status|list [limit]|set ` 管理 Talk 语音配置。在 Discord 上,原生命令名为 `/talkvoice`。 +- `/voice status|list [limit]|set ` 管理 Talk 语音配置。在 Discord 上,原生命令名称为 `/talkvoice`。 - `/card ...` 发送 LINE 富卡片预设。参见 [LINE](/zh-CN/channels/line)。 - `/codex status|models|threads|resume|compact|review|account|mcp|skills` 检查并控制内置 Codex app-server harness。参见 [Codex Harness](/zh-CN/plugins/codex-harness)。 -- 仅 QQ Bot 命令: +- 仅 QQBot 命令: - `/bot-ping` - `/bot-version` - `/bot-help` @@ -171,75 +173,75 @@ Dock 命令由支持原生命令的渠道插件生成。当前内置集合: ### 动态 skill 命令 -用户可调用的 Skills 也会作为斜杠命令暴露: +用户可调用的 Skills 也会暴露为斜杠命令: - `/skill [input]` 始终可作为通用入口点使用。 -- 当 skill/插件注册了直接命令时,它们也可能显示为像 `/prose` 这样的直接命令。 +- 当 skill/plugin 注册它们时,Skills 也可能显示为直接命令,例如 `/prose`。 - 原生 skill 命令注册由 `commands.nativeSkills` 和 `channels..commands.nativeSkills` 控制。 说明: -- 命令接受一个可选的 `:` 作为命令与参数之间的分隔(例如 `/think: high`、`/send: on`、`/help:`)。 -- `/new ` 接受模型别名、`provider/model` 或提供商名称(模糊匹配);如果未匹配到,则该文本会被视为消息正文。 +- 命令支持在命令和参数之间使用可选的 `:`(例如 `/think: high`、`/send: on`、`/help:`)。 +- `/new ` 接受模型别名、`provider/model` 或提供商名称(模糊匹配);如果没有匹配项,则该文本会被视为消息正文。 - 如需完整的提供商使用量明细,请使用 `openclaw status --usage`。 -- `/allowlist add|remove` 需要 `commands.config=true`,并遵循渠道 `configWrites`。 +- `/allowlist add|remove` 需要 `commands.config=true`,并遵循渠道的 `configWrites`。 - 在多账户渠道中,面向配置目标的 `/allowlist --account ` 和 `/config set channels..accounts....` 也会遵循目标账户的 `configWrites`。 -- `/usage` 控制每条响应的使用量页脚;`/usage cost` 会根据 OpenClaw 会话日志打印本地成本摘要。 +- `/usage` 控制每条响应的 usage 页脚;`/usage cost` 会根据 OpenClaw 会话日志输出本地成本摘要。 - `/restart` 默认启用;设置 `commands.restart: false` 可禁用。 -- `/plugins install ` 接受与 `openclaw plugins install` 相同的插件规格:本地路径/归档、npm 包或 `clawhub:`。 -- `/plugins enable|disable` 会更新插件配置,并可能提示重启。 -- 仅限 Discord 的原生命令:`/vc join|leave|status` 用于控制语音频道(需要 `channels.discord.voice` 和原生命令;文本版不可用)。 -- Discord 线程绑定命令(`/focus`、`/unfocus`、`/agents`、`/session idle`、`/session max-age`)要求已有效启用线程绑定(`session.threadBindings.enabled` 和/或 `channels.discord.threadBindings.enabled`)。 -- ACP 命令参考和运行时行为: [ACP Agents](/zh-CN/tools/acp-agents)。 -- `/verbose` 用于调试和提供更多可见性;在正常使用中请保持**关闭**。 -- `/trace` 比 `/verbose` 更窄:它只显示插件拥有的 trace/debug 行,并保持普通的详细工具输出关闭。 -- `/fast on|off` 会持久化一个会话覆盖值。使用 Sessions UI 的 `inherit` 选项可清除该值并回退到配置默认值。 -- `/fast` 具有提供商特异性:OpenAI/OpenAI Codex 会在原生 Responses 端点上将其映射为 `service_tier=priority`,而直接发往 `api.anthropic.com` 的公开 Anthropic 请求(包括通过 OAuth 认证发送的流量)则会将其映射为 `service_tier=auto` 或 `standard_only`。参见 [OpenAI](/zh-CN/providers/openai) 和 [Anthropic](/zh-CN/providers/anthropic)。 -- 工具失败摘要仍会在相关时显示,但详细失败文本只有在 `/verbose` 为 `on` 或 `full` 时才会包含。 -- `/reasoning`、`/verbose` 和 `/trace` 在群组环境中具有风险:它们可能暴露你原本无意公开的内部推理、工具输出或插件诊断信息。建议保持关闭,尤其是在群聊中。 +- `/plugins install ` 接受与 `openclaw plugins install` 相同的插件 spec:本地路径/归档、npm 包或 `clawhub:`。 +- `/plugins enable|disable` 会更新插件配置,并且可能提示需要重启。 +- 仅 Discord 的原生命令:`/vc join|leave|status` 用于控制语音频道(需要 `channels.discord.voice` 和原生命令;不提供文本版本)。 +- Discord 线程绑定命令(`/focus`、`/unfocus`、`/agents`、`/session idle`、`/session max-age`)要求有效启用线程绑定(`session.threadBindings.enabled` 和/或 `channels.discord.threadBindings.enabled`)。 +- ACP 命令参考与运行时行为: [ACP Agents](/zh-CN/tools/acp-agents)。 +- `/verbose` 用于调试和获取更多可见性;正常使用时请保持 **关闭**。 +- `/trace` 比 `/verbose` 更窄:它只显示插件拥有的 trace/debug 行,并保持普通详细工具输出关闭。 +- `/fast on|off` 会持久化一个会话级覆盖。使用 Sessions UI 中的 `inherit` 选项可清除此覆盖并回退到配置默认值。 +- `/fast` 具有提供商特定行为:OpenAI/OpenAI Codex 会在原生 Responses 端点上将其映射为 `service_tier=priority`,而直接发送到 `api.anthropic.com` 的公开 Anthropic 请求(包括经 OAuth 认证的流量)则会将其映射为 `service_tier=auto` 或 `standard_only`。参见 [OpenAI](/zh-CN/providers/openai) 和 [Anthropic](/zh-CN/providers/anthropic)。 +- 工具失败摘要仍会在相关时显示,但详细失败文本仅在 `/verbose` 为 `on` 或 `full` 时包含。 +- `/reasoning`、`/verbose` 和 `/trace` 在群组环境中存在风险:它们可能暴露你原本不打算公开的内部推理、工具输出或插件诊断信息。建议保持关闭,尤其是在群聊中。 - `/model` 会立即持久化新的会话模型。 -- 如果智能体处于空闲状态,下次运行会立即使用它。 -- 如果某次运行已经处于活动状态,OpenClaw 会将实时切换标记为待处理,并仅在一个干净的重试点重启到新模型。 -- 如果工具活动或回复输出已经开始,待处理切换可能会一直排队,直到后续的重试机会或下一个用户轮次。 -- **快速路径:** 来自 allowlist 发送者的纯命令消息会被立即处理(绕过队列 + 模型)。 +- 如果智能体处于空闲状态,下一次运行会立即使用它。 +- 如果当前已有运行中的任务,OpenClaw 会将实时切换标记为待处理,并仅在一个干净的重试点切换到新模型。 +- 如果工具活动或回复输出已经开始,该待切换状态可能会一直排队,直到后续某个重试机会或下一轮用户输入。 +- **快速路径:** 来自 allowlist 发送者的纯命令消息会立即处理(绕过队列 + 模型)。 - **群组提及门控:** 来自 allowlist 发送者的纯命令消息会绕过提及要求。 -- **内联快捷命令(仅限 allowlist 发送者):** 某些命令在嵌入普通消息时也可工作,并会在模型看到剩余文本前被剥离。 - - 示例:`hey /status` 会触发一条状态回复,剩余文本继续按正常流程处理。 -- 当前包括:`/help`、`/commands`、`/status`、`/whoami`(`/id`)。 -- 未授权的纯命令消息会被静默忽略,而内联 `/...` 令牌会被视为普通文本。 -- **Skill 命令:** `user-invocable` 的 Skills 会暴露为斜杠命令。名称会被清理为 `a-z0-9_`(最多 32 个字符);冲突时会追加数字后缀(例如 `_2`)。 - - `/skill [input]` 按名称运行一个 skill(当原生命令限制阻止为每个 skill 创建单独命令时,这很有用)。 +- **内联快捷方式(仅 allowlist 发送者):** 某些命令嵌入在普通消息中时也可生效,并会在模型看到其余文本前被剥离。 + - 示例:`hey /status` 会触发一条状态回复,而剩余文本会继续按正常流程处理。 +- 当前支持:`/help`、`/commands`、`/status`、`/whoami`(`/id`)。 +- 未授权的纯命令消息会被静默忽略,而内联 `/...` token 会被当作普通文本。 +- **Skill 命令:** `user-invocable` Skills 会作为斜杠命令暴露。名称会被清理为 `a-z0-9_`(最长 32 个字符);冲突名称会追加数字后缀(例如 `_2`)。 + - `/skill [input]` 会按名称运行一个 skill(当原生命令限制导致无法为每个 skill 提供单独命令时,这很有用)。 - 默认情况下,skill 命令会作为普通请求转发给模型。 - - Skills 可以选择声明 `command-dispatch: tool`,将命令直接路由到某个工具(确定性,不经过模型)。 + - Skills 也可选择声明 `command-dispatch: tool`,以将命令直接路由到工具(确定性、无模型)。 - 示例:`/prose`(OpenProse 插件)—— 参见 [OpenProse](/zh-CN/prose)。 -- **原生命令参数:** Discord 对动态选项使用自动补全(当你省略必需参数时,也会使用按钮菜单)。Telegram 和 Slack 则会在某个命令支持可选项且你省略该参数时显示一个按钮菜单。 +- **原生命令参数:** Discord 对动态选项使用自动补全(当你省略必填参数时,也会使用按钮菜单)。Telegram 和 Slack 会在命令支持可选值且你省略参数时显示按钮菜单。 ## `/tools` -`/tools` 回答的是一个运行时问题,而不是配置问题:**这个智能体当前在 -这段对话中实际能使用什么**。 +`/tools` 回答的是一个运行时问题,而不是配置问题:**这个智能体现在在 +此对话中能使用什么**。 -- 默认的 `/tools` 是精简版,针对快速浏览进行了优化。 +- 默认 `/tools` 为紧凑模式,适合快速浏览。 - `/tools verbose` 会添加简短说明。 -- 支持参数的原生命令界面会以 `compact|verbose` 暴露相同的模式切换。 -- 结果是会话范围的,因此更换智能体、渠道、线程、发送者授权或模型都可能 +- 支持参数的原生命令界面也会暴露相同的模式切换:`compact|verbose`。 +- 结果是会话作用域的,因此更改智能体、渠道、线程、发送者授权状态或模型,都可能 改变输出。 -- `/tools` 包括运行时实际可达的工具,包括核心工具、已连接的 - 插件工具以及渠道自有工具。 +- `/tools` 包含运行时实际可达的工具,包括 core 工具、已连接的 + plugin 工具以及渠道自有工具。 -对于配置文件和覆盖项编辑,请使用 Control UI 的 Tools 面板或配置/目录界面, -而不要把 `/tools` 当作静态目录。 +如需编辑 profile 和覆盖项,请使用 Control UI 的 Tools 面板或配置/目录界面, +而不要将 `/tools` 视为静态目录。 -## 使用量界面(各处显示内容) +## Usage 界面(各处显示内容) -- **提供商使用量/配额**(例如:“Claude 剩余 80%”)会在启用使用量跟踪时显示于当前模型提供商的 `/status` 中。OpenClaw 会将提供商窗口统一规范化为“剩余百分比”;对于 MiniMax,仅剩余量百分比字段会在显示前取反,而 `model_remains` 响应会优先选择聊天模型条目以及带模型标签的套餐标签。 -- `/status` 中的 **token/cache 行** 在实时会话快照信息稀疏时,可以回退到最新的转录使用量条目。现有的非零实时值仍然优先,而转录回退还可以在存储总量缺失或更小时恢复活动运行时模型标签以及更大的、面向提示的总量。 -- **每条响应的 token/成本** 由 `/usage off|tokens|full` 控制(附加到普通回复后)。 -- `/model status` 关注的是**模型/认证/端点**,不是使用量。 +- **提供商 usage/配额**(例如:“Claude 剩余 80%”)会在 `/status` 中针对当前模型提供商显示,前提是已启用 usage 跟踪。OpenClaw 会将提供商窗口统一归一化为“剩余百分比”;对于 MiniMax,仅剩余百分比字段会在显示前取反,而 `model_remains` 响应会优先使用聊天模型条目以及带模型标记的套餐标签。 +- `/status` 中的 **token/cache 行** 在实时会话快照信息不足时,可以回退到最近的转录 usage 条目。现有的非零实时值仍然优先,而转录回退还可以在已存储总量缺失或较小时,恢复当前活跃运行时模型标签以及更大的、以提示词为导向的总量。 +- **每条响应的 token/cost** 由 `/usage off|tokens|full` 控制(附加在普通回复后)。 +- `/model status` 针对的是 **模型/认证/端点**,而不是 usage。 ## 模型选择(`/model`) -`/model` 被实现为一个指令。 +`/model` 实现为一个指令。 示例: @@ -254,14 +256,14 @@ Dock 命令由支持原生命令的渠道插件生成。当前内置集合: 说明: -- `/model` 和 `/model list` 会显示一个紧凑的编号选择器(模型系列 + 可用提供商)。 -- 在 Discord 上,`/model` 和 `/models` 会打开一个交互式选择器,其中包含提供商和模型下拉菜单以及 Submit 步骤。 -- `/model <#>` 会从该选择器中进行选择(并尽可能优先使用当前提供商)。 -- `/model status` 会显示详细视图,包括已配置的提供商端点(`baseUrl`)和 API 模式(`api`),如果可用的话。 +- `/model` 和 `/model list` 会显示一个紧凑的编号选择器(模型家族 + 可用提供商)。 +- 在 Discord 上,`/model` 和 `/models` 会打开一个交互式选择器,带有提供商和模型下拉框以及 Submit 步骤。 +- `/model <#>` 会从该选择器中进行选择(并在可能时优先当前提供商)。 +- `/model status` 会显示详细视图,包括已配置的提供商端点(`baseUrl`)和 API 模式(`api`,若可用)。 -## Debug 覆盖项 +## 调试覆盖项 -`/debug` 允许你设置**仅运行时**的配置覆盖项(位于内存中,不写入磁盘)。仅限所有者。默认禁用;使用 `commands.debug: true` 启用。 +`/debug` 允许你设置**仅运行时**的配置覆盖项(保存在内存中,不写入磁盘)。仅限所有者。默认禁用;通过 `commands.debug: true` 启用。 示例: @@ -280,7 +282,7 @@ Dock 命令由支持原生命令的渠道插件生成。当前内置集合: ## 插件 trace 输出 -`/trace` 允许你切换**会话范围的插件 trace/debug 行**,而无需启用完整详细模式。 +`/trace` 允许你切换**会话作用域的插件 trace/debug 行**,而无需打开完整 verbose 模式。 示例: @@ -293,15 +295,15 @@ Dock 命令由支持原生命令的渠道插件生成。当前内置集合: 说明: - 不带参数的 `/trace` 会显示当前会话的 trace 状态。 -- `/trace on` 为当前会话启用插件 trace 行。 +- `/trace on` 会为当前会话启用插件 trace 行。 - `/trace off` 会再次将其关闭。 -- 插件 trace 行可以出现在 `/status` 中,也可以在普通助手回复之后作为一条后续诊断消息出现。 +- 插件 trace 行可能出现在 `/status` 中,也可能作为普通助手回复之后的一条跟进诊断消息出现。 - `/trace` 不能替代 `/debug`;`/debug` 仍用于管理仅运行时的配置覆盖项。 -- `/trace` 不能替代 `/verbose`;普通的详细工具/状态输出仍属于 `/verbose`。 +- `/trace` 也不能替代 `/verbose`;普通详细工具/状态输出仍归属 `/verbose`。 ## 配置更新 -`/config` 会写入你磁盘上的配置(`openclaw.json`)。仅限所有者。默认禁用;使用 `commands.config: true` 启用。 +`/config` 会写入你磁盘上的配置(`openclaw.json`)。仅限所有者。默认禁用;通过 `commands.config: true` 启用。 示例: @@ -315,12 +317,12 @@ Dock 命令由支持原生命令的渠道插件生成。当前内置集合: 说明: -- 写入前会对配置进行验证;无效更改会被拒绝。 -- `/config` 更新会在重启后保留。 +- 写入前会验证配置;无效更改会被拒绝。 +- `/config` 更新在重启后仍会保留。 ## MCP 更新 -`/mcp` 会将 OpenClaw 管理的 MCP 服务器定义写入 `mcp.servers` 下。仅限所有者。默认禁用;使用 `commands.mcp: true` 启用。 +`/mcp` 会将 OpenClaw 管理的 MCP 服务器定义写入 `mcp.servers`。仅限所有者。默认禁用;通过 `commands.mcp: true` 启用。 示例: @@ -333,12 +335,12 @@ Dock 命令由支持原生命令的渠道插件生成。当前内置集合: 说明: -- `/mcp` 将配置存储在 OpenClaw 配置中,而不是 Pi 自有项目设置中。 -- 运行时适配器决定哪些传输实际上可执行。 +- `/mcp` 将配置存储在 OpenClaw 配置中,而不是 Pi 拥有的项目设置中。 +- 运行时适配器决定哪些传输方式实际上可执行。 ## 插件更新 -`/plugins` 允许操作员检查已发现的插件,并在配置中切换启用状态。只读流程可以使用 `/plugin` 作为别名。默认禁用;使用 `commands.plugins: true` 启用。 +`/plugins` 允许操作员检查已发现的插件并在配置中切换启用状态。只读流程可以使用 `/plugin` 作为别名。默认禁用;通过 `commands.plugins: true` 启用。 示例: @@ -352,35 +354,34 @@ Dock 命令由支持原生命令的渠道插件生成。当前内置集合: 说明: -- `/plugins list` 和 `/plugins show` 会基于当前工作区和磁盘上的配置执行真实的插件发现。 -- `/plugins enable|disable` 只会更新插件配置;不会安装或卸载插件。 -- 启用/禁用变更后,请重启 gateway 以使其生效。 +- `/plugins list` 和 `/plugins show` 会根据当前工作区和磁盘上的配置执行真实的插件发现。 +- `/plugins enable|disable` 只会更新插件配置;它不会安装或卸载插件。 +- 在 enable/disable 变更后,重启 Gateway 网关以应用这些更改。 ## 界面说明 -- **文本命令** 在普通聊天会话中运行(私信共享 `main`,群组有各自的会话)。 +- **文本命令** 运行在正常聊天会话中(私信共享 `main`,群组拥有自己的会话)。 - **原生命令** 使用隔离会话: - Discord:`agent::discord:slash:` - Slack:`agent::slack:slash:`(前缀可通过 `channels.slack.slashCommand.sessionPrefix` 配置) - Telegram:`telegram:slash:`(通过 `CommandTargetSessionKey` 指向聊天会话) -- **`/stop`** 以活动聊天会话为目标,因此它可以中止当前运行。 -- **Slack:** `channels.slack.slashCommand` 仍支持用于单个 `/openclaw` 风格命令。如果你启用了 `commands.native`,则必须为每个内置命令创建一个 Slack slash command(名称与 `/help` 等相同)。Slack 的命令参数菜单会以临时的 Block Kit 按钮形式传递。 - - Slack 原生命令例外:请注册 `/agentstatus`(而不是 `/status`),因为 Slack 保留了 `/status`。文本版 `/status` 在 Slack 消息中仍然可用。 +- **`/stop`** 会针对当前活跃聊天会话,以便中止当前运行。 +- **Slack:** `channels.slack.slashCommand` 仍支持单个 `/openclaw` 风格命令。如果你启用了 `commands.native`,则必须为每个内置命令创建一个 Slack 斜杠命令(名称与 `/help` 相同)。Slack 的命令参数菜单以临时 Block Kit 按钮形式传递。 + - Slack 原生命令例外:注册 `/agentstatus`(而不是 `/status`),因为 Slack 保留了 `/status`。文本 `/status` 在 Slack 消息中仍可使用。 -## BTW 旁支问题 +## BTW 旁路问题 -`/btw` 是一个关于当前会话的快速**旁支问题**。 +`/btw` 是一个关于当前会话的快速**旁路问题**。 与普通聊天不同: - 它会使用当前会话作为背景上下文, -- 它会以单独的**无工具**一次性调用运行, -- 它不会改变未来会话上下文, +- 它会作为一次独立的**无工具**单次调用运行, +- 它不会改变未来的会话上下文, - 它不会写入转录历史, -- 它会以实时旁支结果的形式交付,而不是普通助手消息。 +- 它会作为实时旁路结果投递,而不是普通助手消息。 -这使得 `/btw` 在你希望主任务继续进行的同时, -临时获得一个澄清时非常有用。 +这使得 `/btw` 在你希望主任务继续进行的同时,临时获取澄清信息时非常有用。 示例: @@ -388,4 +389,4 @@ Dock 命令由支持原生命令的渠道插件生成。当前内置集合: /btw what are we doing right now? ``` -完整行为和客户端 UX 细节请参见 [BTW 旁支问题](/zh-CN/tools/btw)。 +完整行为和客户端 UX 细节请参阅 [BTW Side Questions](/zh-CN/tools/btw)。 diff --git a/docs/zh-CN/tools/trajectory.md b/docs/zh-CN/tools/trajectory.md new file mode 100644 index 000000000..2767fca7b --- /dev/null +++ b/docs/zh-CN/tools/trajectory.md @@ -0,0 +1,190 @@ +--- +read_when: + - 调试智能体为何会以特定方式回答、失败或调用工具 + - 为 OpenClaw 会话导出支持套装 + - 调查提示词上下文、工具调用、运行时错误或使用情况元数据 + - 禁用或重新定位轨迹捕获 +summary: 导出已脱敏的轨迹套装以调试 OpenClaw 智能体会话 +title: 轨迹套装 +x-i18n: + generated_at: "2026-04-23T07:07:11Z" + model: gpt-5.4 + provider: openai + source_hash: 18f18c9b0a57fcc85624ae8592778447f61ffbd2aa455f8f92893955af744b23 + source_path: tools/trajectory.md + workflow: 15 +--- + +# 轨迹套装 + +轨迹捕获是 OpenClaw 的按会话飞行记录器。它会为每次智能体运行记录一条 +结构化时间线,然后 `/export-trajectory` 会将当前会话打包为一个已脱敏的 +支持套装。 + +当你需要回答以下问题时,请使用它: + +- 发送给模型的提示词、系统提示词和工具是什么? +- 哪些转录消息和工具调用导致了这个回答? +- 此次运行是超时、中止、压缩,还是遇到了提供商错误? +- 当时启用了哪些模型、plugin、Skills 和运行时设置? +- 提供商返回了哪些使用情况和 prompt-cache 元数据? + +## 快速开始 + +在当前活动会话中发送: + +```text +/export-trajectory +``` + +别名: + +```text +/trajectory +``` + +OpenClaw 会将套装写入工作区下: + +```text +.openclaw/trajectory-exports/openclaw-trajectory--/ +``` + +你可以选择一个相对输出目录名: + +```text +/export-trajectory bug-1234 +``` + +自定义路径会在 `.openclaw/trajectory-exports/` 内解析。绝对路径和 `~` +路径会被拒绝。 + +## 访问 + +轨迹导出是所有者命令。发送者必须通过该渠道的常规命令 +授权检查和所有者检查。 + +## 会记录什么 + +对于 OpenClaw 智能体运行,轨迹捕获默认开启。 + +运行时事件包括: + +- `session.started` +- `trace.metadata` +- `context.compiled` +- `prompt.submitted` +- `model.completed` +- `trace.artifacts` +- `session.ended` + +转录事件也会从当前活跃会话分支中重建: + +- 用户消息 +- 助手消息 +- 工具调用 +- 工具结果 +- 压缩 +- 模型变更 +- 标签和自定义会话条目 + +事件会以 JSON Lines 格式写入,并带有如下 schema 标记: + +```json +{ + "traceSchema": "openclaw-trajectory", + "schemaVersion": 1 +} +``` + +## 套装文件 + +导出的套装可能包含: + +| 文件 | 内容 | +| --------------------- | ---------------------------------------------------------------------------------------------- | +| `manifest.json` | 套装 schema、源文件、事件计数和生成文件列表 | +| `events.jsonl` | 按顺序排列的运行时和转录时间线 | +| `session-branch.json` | 已脱敏的活动转录分支和会话头 | +| `metadata.json` | OpenClaw 版本、OS/运行时、模型、配置快照、plugin、Skills 和提示词元数据 | +| `artifacts.json` | 最终状态、错误、使用情况、prompt cache、压缩计数、助手文本和工具元数据 | +| `prompts.json` | 已提交的提示词和选定的提示词构建细节 | +| `system-prompt.txt` | 最新编译后的系统提示词(若已捕获) | +| `tools.json` | 发送给模型的工具定义(若已捕获) | + +`manifest.json` 会列出该套装中实际存在的文件。当会话未捕获相应的运行时数据时, +某些文件会被省略。 + +## 捕获位置 + +默认情况下,运行时轨迹事件会写在会话文件旁边: + +```text +.trajectory.jsonl +``` + +OpenClaw 还会尽力在会话旁边写入一个指针文件: + +```text +.trajectory-path.json +``` + +设置 `OPENCLAW_TRAJECTORY_DIR` 可将运行时轨迹 sidecar 存储到 +专用目录中: + +```bash +export OPENCLAW_TRAJECTORY_DIR=/var/lib/openclaw/trajectories +``` + +设置该变量后,OpenClaw 会在该目录中按每个会话 ID 写入一个 JSONL 文件。 + +## 禁用捕获 + +在启动 OpenClaw 之前设置 `OPENCLAW_TRAJECTORY=0`: + +```bash +export OPENCLAW_TRAJECTORY=0 +``` + +这会禁用运行时轨迹捕获。`/export-trajectory` 仍然可以导出 +转录分支,但仅运行时文件(例如编译后的上下文、 +提供商产物和提示词元数据)可能会缺失。 + +## 隐私和限制 + +轨迹套装是为支持和调试设计的,不适合公开发布。 +OpenClaw 会在写入导出文件前对敏感值进行脱敏: + +- 凭证和已知类似密钥的负载字段 +- 图像数据 +- 本地状态路径 +- 工作区路径,会替换为 `$WORKSPACE_DIR` +- 已检测到的主目录路径 + +导出器还会限制输入大小: + +- 运行时 sidecar 文件:50 MiB +- 会话文件:50 MiB +- 运行时事件:200,000 +- 导出的总事件数:250,000 +- 单条运行时事件行超过 256 KiB 时会被截断 + +在将套装分享给团队外部之前,请先审查。脱敏是尽力而为, +无法识别所有特定于应用的密钥。 + +## 故障排除 + +如果导出内容没有运行时事件: + +- 确认 OpenClaw 启动时未设置 `OPENCLAW_TRAJECTORY=0` +- 检查 `OPENCLAW_TRAJECTORY_DIR` 是否指向可写目录 +- 在该会话中再运行一条消息,然后重新导出 +- 检查 `manifest.json` 中的 `runtimeEventCount` + +如果命令拒绝输出路径: + +- 使用类似 `bug-1234` 的相对名称 +- 不要传入 `/tmp/...` 或 `~/...` +- 保持导出路径位于 `.openclaw/trajectory-exports/` 内 + +如果导出因大小错误失败,说明会话或 sidecar 超过了 +导出的安全限制。请开始一个新会话,或导出更小的复现。 diff --git a/docs/zh-CN/web/control-ui.md b/docs/zh-CN/web/control-ui.md index 719936303..36d8d9d18 100644 --- a/docs/zh-CN/web/control-ui.md +++ b/docs/zh-CN/web/control-ui.md @@ -1,51 +1,57 @@ --- read_when: - 你希望通过浏览器操作 Gateway 网关 - - 你希望在不使用 SSH 隧道的情况下通过 Tailnet 访问 + - 你希望在不使用 SSH 隧道的情况下通过 tailnet 访问 summary: 基于浏览器的 Gateway 网关控制 UI(聊天、节点、配置) -title: Control UI +title: 控制 UI x-i18n: - generated_at: "2026-04-23T06:44:13Z" + generated_at: "2026-04-23T07:07:16Z" model: gpt-5.4 provider: openai - source_hash: 05c5a1b9c0527d230b1657e15b1adf681817d279128af8197a14eb9bdde3d211 + source_hash: 05bed9a917878d4849eb7502952e27b7c7a3bf848223735d513d545d51baef6d source_path: web/control-ui.md workflow: 15 --- -# Control UI(浏览器) +# 控制 UI(浏览器) -Control UI 是一个由 Gateway 网关提供的小型 **Vite + Lit** 单页应用: +控制 UI 是一个由 Gateway 网关提供的小型 **Vite + Lit** 单页应用: - 默认:`http://:18789/` - 可选前缀:设置 `gateway.controlUi.basePath`(例如 `/openclaw`) -它会**直接连接到同一端口上的 Gateway 网关 WebSocket**。 +它会在同一端口上**直接连接到 Gateway 网关 WebSocket**。 ## 快速打开(本地) -如果 Gateway 网关运行在同一台电脑上,请打开: +如果 Gateway 网关运行在同一台计算机上,请打开: - [http://127.0.0.1:18789/](http://127.0.0.1:18789/)(或 [http://localhost:18789/](http://localhost:18789/)) -如果页面加载失败,请先启动 Gateway 网关:`openclaw gateway`。 +如果页面无法加载,请先启动 Gateway 网关:`openclaw gateway`。 身份验证会在 WebSocket 握手期间通过以下方式提供: - `connect.params.auth.token` - `connect.params.auth.password` -- 当 `gateway.auth.allowTailscale: true` 时使用 Tailscale Serve 身份请求头 -- 当 `gateway.auth.mode: "trusted-proxy"` 时使用受信任代理身份请求头 +- 当 `gateway.auth.allowTailscale: true` 时使用 Tailscale Serve 身份标头 +- 当 `gateway.auth.mode: "trusted-proxy"` 时使用 trusted-proxy 身份标头 -仪表板设置面板会为当前浏览器标签页会话和所选 Gateway 网关 URL 保留一个 token;密码不会被持久化。新手引导通常会在首次连接时为共享密钥身份验证生成一个 Gateway 网关 token,但当 `gateway.auth.mode` 为 `"password"` 时,也可以使用密码身份验证。 +仪表板设置面板会为当前浏览器标签页会话 +以及所选 gateway URL 保存 token;password 不会被持久化。新手引导通常会在首次连接时 +为共享密钥身份验证生成一个 gateway token,但当 `gateway.auth.mode` 为 `"password"` 时, +password 身份验证同样可用。 ## 设备配对(首次连接) -当你从新的浏览器或设备连接到 Control UI 时,Gateway 网关会要求一次**一次性配对批准**——即使你位于同一个 Tailnet 中,并且设置了 `gateway.auth.allowTailscale: true` 也是如此。这是一项安全措施,用于防止未授权访问。 +当你从新的浏览器或设备连接到控制 UI 时,Gateway 网关 +会要求进行一次性**配对审批**——即使你位于同一个 Tailnet 上, +并启用了 `gateway.auth.allowTailscale: true` 也是如此。这是一项安全措施,用于防止 +未授权访问。 -**你会看到:** “disconnected (1008): pairing required” +**你会看到:**“disconnected (1008): pairing required” -**批准该设备:** +**批准设备:** ```bash # 列出待处理请求 @@ -55,91 +61,128 @@ openclaw devices list openclaw devices approve ``` -如果浏览器在更改了身份验证详情(角色/作用域/公钥)后重试配对,之前的待处理请求会被替换,并生成新的 `requestId`。批准前请重新运行 `openclaw devices list`。 +如果浏览器在重试配对时更改了身份验证详情(role/scopes/public +key),之前的待处理请求会被替代,并创建新的 `requestId`。 +批准前请重新运行 `openclaw devices list`。 -如果浏览器已经配对,而你将其从只读访问更改为写入/管理员访问,这会被视为一次权限升级批准,而不是静默重连。OpenClaw 会保持旧批准有效,阻止权限更高的重连,并要求你显式批准新的作用域集合。 +如果浏览器已经配对,而你又将其从只读权限改为 +写入/管理员权限,这会被视为一次审批升级,而不是静默 +重连。OpenClaw 会保持旧审批仍然有效,阻止更高权限的重连, +并要求你显式批准新的作用域集合。 -一旦获批,该设备会被记住,除非你使用 `openclaw devices revoke --device --role ` 撤销它,否则无需再次批准。有关 token 轮换和撤销,请参见 [Devices CLI](/zh-CN/cli/devices)。 +一旦获得批准,该设备就会被记住,除非你使用 `openclaw devices revoke --device --role ` 撤销,否则无需再次批准。有关 +token 轮换和撤销,请参阅 [Devices CLI](/zh-CN/cli/devices)。 **说明:** -- 直接本地 local loopback 浏览器连接(`127.0.0.1` / `localhost`)会自动获批。 -- Tailnet 和 LAN 浏览器连接即使来自同一台机器,仍然需要显式批准。 -- 每个浏览器配置文件都会生成唯一的设备 ID,因此切换浏览器或清除浏览器数据后都需要重新配对。 +- 直接的本地 loopback 浏览器连接(`127.0.0.1` / `localhost`)会 + 自动获批。 +- Tailnet 和 LAN 浏览器连接仍然需要显式批准,即使 + 它们来自同一台机器。 +- 每个浏览器 profile 都会生成唯一设备 ID,因此切换浏览器或 + 清除浏览器数据都需要重新配对。 + +## 个人身份(浏览器本地) + +控制 UI 支持按浏览器区分的个人身份——一个显示名称和 +头像,会附加到发出的消息中,用于在共享 +会话中标明归属。该身份保存在浏览器存储中,作用域限定为当前 +浏览器 profile,除非你显式随请求提交,否则不会离开 gateway 主机。 + +- 身份**仅保存在浏览器本地**。它不会同步到其他设备,也 + 不属于 gateway 配置文件的一部分。 +- 清除站点数据或切换浏览器会将身份重置为空; + 控制 UI 不会尝试从服务器状态中重建身份。 +- 关于个人身份的任何内容都不会在服务端持久化, + 除了你实际发送的消息上正常 transcript 作者元数据之外。 + +## 运行时配置端点 + +控制 UI 会从 +`/__openclaw/control-ui-config.json` 获取其运行时设置。该端点受与其余 +gateway HTTP 表面相同的身份验证保护:未认证的浏览器无法 +获取它,而成功获取则需要已经有效的 gateway +token/password、Tailscale Serve 身份,或 trusted-proxy 身份。这样可以防止控制 UI 功能标志和端点元数据泄露给共享主机上的 +未认证扫描器。 ## 语言支持 -Control UI 可在首次加载时根据你的浏览器区域设置进行本地化。若要之后覆盖它,请打开 **Overview -> Gateway Access -> Language**。语言选择器位于 Gateway Access 卡片中,而不在 Appearance 下。 +控制 UI 可以在首次加载时根据你的浏览器语言环境进行本地化。 +如需稍后覆盖,请打开**概览 -> Gateway 访问 -> 语言**。语言选择器位于 Gateway 访问卡片中,而不是外观设置下。 -- 支持的区域设置:`en`、`zh-CN`、`zh-TW`、`pt-BR`、`de`、`es`、`ja-JP`、`ko`、`fr`、`tr`、`uk`、`id`、`pl`、`th` +- 支持的语言环境:`en`、`zh-CN`、`zh-TW`、`pt-BR`、`de`、`es`、`ja-JP`、`ko`、`fr`、`tr`、`uk`、`id`、`pl`、`th` - 非英语翻译会在浏览器中按需懒加载。 -- 所选区域设置会保存到浏览器存储中,并在后续访问时复用。 +- 所选语言环境会保存在浏览器存储中,并在后续访问时复用。 - 缺失的翻译键会回退到英语。 -## 当前可执行的操作 +## 当前可以做什么 - 通过 Gateway 网关 WS 与模型聊天(`chat.history`、`chat.send`、`chat.abort`、`chat.inject`) -- 在 Chat 中流式显示工具调用 + 实时工具输出卡片(智能体事件) -- Channels:内置以及内置/外部渠道插件状态、QR 登录和按渠道配置(`channels.status`、`web.login.*`、`config.patch`) -- 实例:在线状态列表 + 刷新(`system-presence`) -- Sessions:列表 + 按会话覆盖 model/thinking/fast/verbose/trace/reasoning(`sessions.list`、`sessions.patch`) -- Dreams:Dreaming 状态、启用/禁用开关,以及 Dream Diary 阅读器(`doctor.memory.status`、`doctor.memory.dreamDiary`、`config.patch`) -- Cron 作业:列出/添加/编辑/运行/启用/禁用 + 运行历史(`cron.*`) -- Skills:状态、启用/禁用、安装、API 密钥更新(`skills.*`) -- 节点:列表 + 能力(`node.list`) -- Exec 批准:编辑 gateway 或节点 allowlist + `exec host=gateway/node` 的询问策略(`exec.approvals.*`) +- 在聊天中流式显示工具调用 + 实时工具输出卡片(智能体事件) +- 渠道:内置以及内置/外部插件渠道的状态、QR 登录和按渠道配置(`channels.status`、`web.login.*`、`config.patch`) +- 实例:presence 列表 + 刷新(`system-presence`) +- 会话:列表 + 每会话 model/thinking/fast/verbose/trace/reasoning 覆盖(`sessions.list`、`sessions.patch`) +- Dreams:dreaming 状态、启用/禁用切换,以及 Dream Diary 读取器(`doctor.memory.status`、`doctor.memory.dreamDiary`、`config.patch`) +- Cron 任务:列出/添加/编辑/运行/启用/禁用 + 运行历史(`cron.*`) +- Skills:状态、启用/禁用、安装、API key 更新(`skills.*`) +- 节点:列表 + caps(`node.list`) +- Exec 审批:编辑 gateway 或节点允许列表 + 为 `exec host=gateway/node` 设置询问策略(`exec.approvals.*`) - 配置:查看/编辑 `~/.openclaw/openclaw.json`(`config.get`、`config.set`) -- 配置:带验证的应用 + 重启(`config.apply`),并唤醒最后一个活跃会话 +- 配置:带验证地应用 + 重启(`config.apply`),并唤醒上一个活动会话 - 配置写入包含 base-hash 保护,以防覆盖并发编辑 -- 配置写入(`config.set`/`config.apply`/`config.patch`)还会在写入前,对已提交配置负载中的活动 SecretRef 执行预检解析;无法解析的活动已提交引用会在写入前被拒绝 -- 配置模式 + 表单渲染(`config.schema` / `config.schema.lookup`, - 包括字段 `title` / `description`、匹配的 UI 提示、直接子项摘要、嵌套对象/通配符/数组/组合节点上的文档元数据, - 以及可用时的插件 + 渠道模式);仅当快照具备安全的原始往返能力时,才提供 Raw JSON 编辑器 -- 如果某个快照无法安全地进行原始文本往返,Control UI 会强制使用 Form 模式,并对该快照禁用 Raw 模式 -- 结构化 SecretRef 对象值会在表单文本输入中以只读方式渲染,以防意外将对象破坏成字符串 +- 配置写入(`config.set`/`config.apply`/`config.patch`)还会对已提交配置负载中的活动 SecretRef 解析进行预检;未解析的活动已提交 ref 会在写入前被拒绝 +- 配置 schema + 表单渲染(`config.schema` / `config.schema.lookup`, + 包括字段 `title` / `description`、匹配的 UI 提示、直接子项 + 摘要、嵌套对象/通配符/数组/组合节点上的文档元数据, + 以及在可用时的插件 + 渠道 schema);Raw JSON 编辑器 + 仅在快照具有安全 raw 往返能力时可用 +- 如果某个快照无法安全地进行 raw 往返,控制 UI 会强制使用表单模式,并对该快照禁用 Raw 模式 +- Raw JSON 编辑器中的“重置为已保存”会保留以 raw 方式编写的结构(格式、注释、`$include` 布局),而不是重新渲染展平后的快照,因此在快照能安全往返时,外部编辑在重置后仍会保留 +- 结构化 SecretRef 对象值会在表单文本输入中以只读方式渲染,以防止意外将对象损坏为字符串 - 调试:状态/健康/模型快照 + 事件日志 + 手动 RPC 调用(`status`、`health`、`models.list`) -- 日志:Gateway 网关文件日志实时 tail,支持筛选/导出(`logs.tail`) -- 更新:执行包/git 更新 + 重启(`update.run`),并附带重启报告 +- 日志:带过滤/导出的 gateway 文件日志实时 tail(`logs.tail`) +- 更新:运行 package/git 更新 + 重启(`update.run`),并附带重启报告 -Cron 作业面板说明: +Cron 任务面板说明: -- 对于隔离作业,投递默认是公告摘要。如果你只想内部运行,可以切换为 none。 -- 当选择 announce 时,会显示渠道/目标字段。 -- webhook 模式使用 `delivery.mode = "webhook"`,并将 `delivery.to` 设置为有效的 HTTP(S) webhook URL。 -- 对于主会话作业,可使用 webhook 和 none 投递模式。 -- 高级编辑控件包括运行后删除、清除智能体覆盖、cron 精确/错峰选项、 - 智能体 model/thinking 覆盖,以及尽力投递开关。 -- 表单验证为内联方式,并显示字段级错误;无效值会禁用保存按钮,直到修复。 -- 设置 `cron.webhookToken` 可发送专用 bearer token;若省略,则发送 webhook 时不带身份验证请求头。 -- 已弃用的回退:已存储的旧作业若带有 `notify: true`,在迁移前仍可使用 `cron.webhook`。 +- 对于隔离任务,默认投递方式为播报摘要。若你只想内部运行,可切换为 none。 +- 选择 announce 后会显示渠道/目标字段。 +- Webhook 模式使用 `delivery.mode = "webhook"`,并将 `delivery.to` 设置为有效的 HTTP(S) webhook URL。 +- 对于主会话任务,可用的投递模式包括 webhook 和 none。 +- 高级编辑控件包括运行后删除、清除智能体覆盖、cron 精确/错开选项、 + 智能体 model/thinking 覆盖,以及尽力投递切换。 +- 表单验证为内联方式,带字段级错误;在修复前,无效值会禁用保存按钮。 +- 设置 `cron.webhookToken` 可发送专用 bearer token;如果省略,则 webhook 将在没有身份验证标头的情况下发送。 +- 已弃用的回退方式:如果尚未迁移,带有 `notify: true` 的旧版已存储任务仍可使用 `cron.webhook`。 ## 聊天行为 -- `chat.send` 是**非阻塞**的:它会立即确认并返回 `{ runId, status: "started" }`,响应则通过 `chat` 事件流式返回。 -- 使用相同的 `idempotencyKey` 重新发送时,运行中会返回 `{ status: "in_flight" }`,完成后返回 `{ status: "ok" }`。 -- `chat.history` 响应有大小限制,以保障 UI 安全。当转录条目过大时,Gateway 网关可能会截断长文本字段、省略体积较大的元数据块,并用占位符替换超大消息(`[chat.history omitted: message too large]`)。 -- `chat.history` 还会从可见助手文本中剥离仅用于显示的内联指令标签(例如 `[[reply_to_*]]` 和 `[[audio_as_voice]]`)、纯文本工具调用 XML 负载(包括 `...`、`...`、`...`、`...` 以及被截断的工具调用块),并移除泄露出的 ASCII/全角模型控制 token;同时会省略那些完整可见文本仅为精确静默 token `NO_REPLY` / `no_reply` 的助手条目。 -- `chat.inject` 会向会话转录追加一条助手说明,并广播一个 `chat` 事件用于仅 UI 更新(不会触发智能体运行,也不会进行渠道投递)。 -- 聊天头部的 model 和 thinking 选择器会通过 `sessions.patch` 立即修补当前活跃会话;它们是持久化的会话覆盖,而不是单轮发送选项。 +- `chat.send` 是**非阻塞**的:它会立即确认并返回 `{ runId, status: "started" }`,随后响应会通过 `chat` 事件流式传输。 +- 使用相同 `idempotencyKey` 重新发送时,运行中会返回 `{ status: "in_flight" }`,完成后返回 `{ status: "ok" }`。 +- 出于 UI 安全考虑,`chat.history` 响应有大小限制。当 transcript 条目过大时,Gateway 网关可能会截断长文本字段、省略较重的元数据块,并用占位符替换超大消息(`[chat.history omitted: message too large]`)。 +- `chat.history` 还会从可见的 assistant 文本中移除仅用于显示的内联指令标签(例如 `[[reply_to_*]]` 和 `[[audio_as_voice]]`)、纯文本工具调用 XML 负载(包括 `...`、`...`、`...`、`...` 以及被截断的工具调用块),并移除泄露的 ASCII/全角模型控制 token,同时省略那些其全部可见文本恰好只是静默 token `NO_REPLY` / `no_reply` 的 assistant 条目。 +- `chat.inject` 会向会话 transcript 追加一条 assistant 注释,并广播一个 `chat` 事件用于仅 UI 的更新(不会触发智能体运行,也不会向渠道投递)。 +- 聊天头部中的 model 和 thinking 选择器会通过 `sessions.patch` 立即修补当前活动会话;它们是持久的会话覆盖,而不是单轮发送选项。 - 停止: - - 点击 **Stop**(调用 `chat.abort`) - - 输入 `/stop`(或独立的中止短语,如 `stop`、`stop action`、`stop run`、`stop openclaw`、`please stop`)以带外中止 - - `chat.abort` 支持 `{ sessionKey }`(无需 `runId`),可中止该会话的所有活跃运行 + - 点击**停止**(调用 `chat.abort`) + - 输入 `/stop`(或单独的中止短语,例如 `stop`、`stop action`、`stop run`、`stop openclaw`、`please stop`)以进行带外中止 + - `chat.abort` 支持 `{ sessionKey }`(无需 `runId`)来中止该会话的所有活动运行 - 中止后的部分保留: - - 当某次运行被中止时,部分助手文本仍可能显示在 UI 中 - - 如果存在缓冲输出,Gateway 网关会将被中止的部分助手文本持久化到转录历史中 - - 持久化条目包含中止元数据,以便转录消费者区分中止产生的部分文本和正常完成输出 + - 当某次运行被中止时,部分 assistant 文本仍然可以在 UI 中显示 + - 当存在缓冲输出时,Gateway 网关会将中止后的部分 assistant 文本持久化到 transcript 历史中 + - 持久化条目会包含中止元数据,以便 transcript 使用方区分中止部分和正常完成输出 -## 托管 embed +## 托管嵌入 -助手消息可以通过 `[embed ...]` +Assistant 消息可以通过 `[embed ...]` 短代码以内联方式渲染托管网页内容。iframe 沙箱策略由 `gateway.controlUi.embedSandbox` 控制: -- `strict`:禁止在托管 embed 中执行脚本 -- `scripts`:允许交互式 embed,同时保持源隔离;这是 - 默认值,通常足以满足自包含的浏览器游戏/小部件 -- `trusted`:在 `allow-scripts` 基础上再添加 `allow-same-origin`,适用于有意需要更高权限的同站文档 +- `strict`:禁用托管嵌入中的脚本执行 +- `scripts`:允许交互式嵌入,同时保持源隔离;这是 + 默认值,通常足以支持自包含的浏览器游戏/小组件 +- `trusted`:在 `allow-scripts` 之上再添加 `allow-same-origin`,用于同站点 + 文档,这些文档确实有意需要更强权限 示例: @@ -153,19 +196,19 @@ Cron 作业面板说明: } ``` -仅当嵌入文档确实需要同源行为时才使用 `trusted`。 -对于大多数由智能体生成的游戏和交互式 canvas,`scripts` 是 +仅当嵌入文档确实需要 same-origin +行为时,才使用 `trusted`。对于大多数由智能体生成的游戏和交互式画布,`scripts` 是 更安全的选择。 -默认情况下,绝对外部 `http(s)` embed URL 仍会被阻止。如果你 +默认仍然会阻止绝对外部 `http(s)` 嵌入 URL。如果你 确实希望 `[embed url="https://..."]` 加载第三方页面,请设置 `gateway.controlUi.allowExternalEmbedUrls: true`。 ## Tailnet 访问(推荐) -### 集成 Tailscale Serve(首选) +### 集成式 Tailscale Serve(首选) -让 Gateway 网关保持绑定在 loopback 上,并由 Tailscale Serve 通过 HTTPS 代理它: +让 Gateway 网关保持在 loopback 上,并让 Tailscale Serve 通过 HTTPS 为其提供代理: ```bash openclaw gateway --tailscale serve @@ -175,13 +218,17 @@ openclaw gateway --tailscale serve - `https:///`(或你配置的 `gateway.controlUi.basePath`) -默认情况下,当 `gateway.auth.allowTailscale` 为 `true` 时,Control UI/WebSocket Serve 请求可以通过 Tailscale 身份请求头 -(`tailscale-user-login`)完成身份验证。OpenClaw -会通过 `tailscale whois` 解析 `x-forwarded-for` 地址并与该请求头匹配来验证身份,并且仅在请求通过 Tailscale 的 `x-forwarded-*` 请求头命中 loopback 时接受这些请求。若你希望即使对于 Serve 流量也要求显式共享密钥凭证,请设置 -`gateway.auth.allowTailscale: false`。然后使用 `gateway.auth.mode: "token"` 或 +默认情况下,当 `gateway.auth.allowTailscale` 为 `true` 时,控制 UI/WebSocket Serve 请求可以通过 Tailscale 身份标头 +(`tailscale-user-login`)进行身份验证。OpenClaw +会通过使用 `tailscale whois` 解析 `x-forwarded-for` 地址并将其与标头匹配来验证该身份,并且只有当 +请求携带 Tailscale 的 `x-forwarded-*` 标头并命中 loopback 时才会接受这些身份。若你希望即使对于 Serve 流量也要求显式共享密钥 +凭证,请设置 `gateway.auth.allowTailscale: false`。然后使用 `gateway.auth.mode: "token"` 或 `"password"`。 -对于该异步 Serve 身份路径,来自同一客户端 IP 和相同身份验证作用域的失败身份验证尝试,会在写入限流数据之前串行化处理。因此,同一浏览器的并发错误重试在第二次请求时可能会显示 `retry later`,而不是出现两个并行竞争的普通不匹配。 -无 token 的 Serve 身份验证假设 Gateway 网关主机是可信的。如果该主机上可能运行不可信本地代码,请要求使用 token/password 身份验证。 +对于该异步 Serve 身份路径,来自同一客户端 IP +和同一身份验证作用域的失败身份验证尝试会在写入速率限制之前串行化。 +因此,同一浏览器发起的并发错误重试中,第二个请求可能会显示 `retry later`,而不是两个普通不匹配并行竞争。 +无 token 的 Serve 身份验证假定 gateway 主机是受信任的。如果该主机上可能运行不受信任的本地 +代码,请要求使用 token/password 身份验证。 ### 绑定到 tailnet + token @@ -200,15 +247,15 @@ openclaw gateway --bind tailnet --token "$(openssl rand -hex 32)" 如果你通过纯 HTTP 打开仪表板(`http://` 或 `http://`), 浏览器会运行在**非安全上下文**中,并阻止 WebCrypto。默认情况下, -OpenClaw 会**阻止**没有设备身份的 Control UI 连接。 +OpenClaw **会阻止**没有设备身份的控制 UI 连接。 文档化的例外情况: -- 仅限 localhost 的不安全 HTTP 兼容模式:`gateway.controlUi.allowInsecureAuth=true` -- 通过 `gateway.auth.mode: "trusted-proxy"` 成功进行的操作员 Control UI 身份验证 -- 紧急兜底:`gateway.controlUi.dangerouslyDisableDeviceAuth=true` +- 仅限 localhost 的不安全 HTTP 兼容模式,使用 `gateway.controlUi.allowInsecureAuth=true` +- 通过 `gateway.auth.mode: "trusted-proxy"` 成功进行的操作员控制 UI 身份验证 +- 应急开关 `gateway.controlUi.dangerouslyDisableDeviceAuth=true` -**推荐修复方式:** 使用 HTTPS(Tailscale Serve)或在本地打开 UI: +**推荐修复方式:**使用 HTTPS(Tailscale Serve)或在本地打开 UI: - `https:///`(Serve) - `http://127.0.0.1:18789/`(在 gateway 主机上) @@ -225,14 +272,14 @@ OpenClaw 会**阻止**没有设备身份的 Control UI 连接。 } ``` -`allowInsecureAuth` 仅是一个本地兼容性开关: +`allowInsecureAuth` 只是本地兼容性开关: -- 它允许 localhost 的 Control UI 会话在非安全 HTTP 上下文中, - 无需设备身份即可继续进行。 +- 它允许 localhost 控制 UI 会话在 + 非安全 HTTP 上下文中无设备身份继续进行。 - 它不会绕过配对检查。 -- 它不会放宽远程(非 localhost)设备身份要求。 +- 它不会放宽远端(非 localhost)设备身份要求。 -**仅限紧急兜底:** +**仅限紧急情况:** ```json5 { @@ -244,56 +291,56 @@ OpenClaw 会**阻止**没有设备身份的 Control UI 连接。 } ``` -`dangerouslyDisableDeviceAuth` 会禁用 Control UI 设备身份检查,是一种 +`dangerouslyDisableDeviceAuth` 会禁用控制 UI 设备身份检查,这是一次 严重的安全降级。紧急使用后请尽快恢复。 -受信任代理说明: +Trusted-proxy 说明: -- 成功的 trusted-proxy 身份验证可以让**操作员** Control UI 会话在没有 - 设备身份的情况下接入 -- 这**不**适用于 node-role 的 Control UI 会话 -- 同一主机上的 loopback 反向代理仍然不能满足 trusted-proxy 身份验证;请参见 +- 成功的 trusted-proxy 身份验证可以允许**操作员**控制 UI 会话在无 + 设备身份的情况下进入 +- 这**不适用于** node 角色控制 UI 会话 +- 同一主机上的 loopback 反向代理仍然不满足 trusted-proxy 身份验证;参见 [Trusted Proxy Auth](/zh-CN/gateway/trusted-proxy-auth) 有关 HTTPS 设置指导,请参见 [Tailscale](/zh-CN/gateway/tailscale)。 ## 内容安全策略 -Control UI 采用严格的 `img-src` 策略:只允许**同源**资源和 `data:` URL。远程 `http(s)` 和协议相对图片 URL 会被浏览器拒绝,也不会发起网络请求。 +控制 UI 带有严格的 `img-src` 策略:只允许**同源**资源和 `data:` URL。远端 `http(s)` 和协议相对图片 URL 会被浏览器拒绝,不会发起网络获取请求。 -这在实际中的含义: +这在实践中的含义是: -- 通过相对路径提供的头像和图片(例如 `/avatars/`)仍可正常渲染。 -- 内联 `data:image/...` URL 仍可正常渲染(对协议内负载很有用)。 -- 渠道元数据输出的远程头像 URL 会在 Control UI 的头像辅助函数中被剥离,并替换为内置 logo/badge,因此即使某个渠道被攻破或存在恶意行为,也无法强制操作员浏览器任意拉取远程图片。 +- 通过相对路径提供的头像和图片(例如 `/avatars/`)仍然可以渲染。 +- 内联 `data:image/...` URL 仍然可以渲染(对协议内负载很有用)。 +- 由渠道元数据发出的远端头像 URL 会在控制 UI 的头像辅助函数中被剥离,并替换为内置 logo/badge,因此受损或恶意渠道无法强迫操作员浏览器发起任意远端图片请求。 -你无需进行任何更改即可获得此行为——它始终开启,且不可配置。 +你无需做任何修改即可获得此行为——它始终开启,且不可配置。 ## 头像路由身份验证 -当配置了 Gateway 网关身份验证时,Control UI 的头像端点要求使用与其余 API 相同的 Gateway 网关 token: +配置了 gateway 身份验证时,控制 UI 头像端点要求与其余 API 相同的 gateway token: -- `GET /avatar/` 仅向已通过身份验证的调用者返回头像图片。`GET /avatar/?meta=1` 也会在相同规则下返回头像元数据。 -- 对这两个路由的未认证请求都会被拒绝(与相邻的 assistant-media 路由保持一致)。这可以防止头像路由在其他部分已受保护的主机上泄露智能体身份。 -- Control UI 本身在获取头像时会将 Gateway 网关 token 作为 bearer 请求头转发,并使用已认证的 blob URL,因此图片仍能在仪表板中正常渲染。 +- `GET /avatar/` 仅向已认证调用方返回头像图片。`GET /avatar/?meta=1` 在相同规则下返回头像元数据。 +- 对这两个路由的未认证请求都会被拒绝(与相邻的 assistant-media 路由保持一致)。这可以防止头像路由在其他方面已受保护的主机上泄露智能体身份。 +- 控制 UI 本身在获取头像时会将 gateway token 作为 bearer 标头转发,并使用经过身份验证的 blob URL,因此图像仍能在仪表板中渲染。 -如果你禁用了 Gateway 网关身份验证(不建议在共享主机上这样做),则头像路由也会像网关其余部分一样变为无身份验证。 +如果你禁用了 gateway 身份验证(不建议在共享主机上这样做),头像路由也会变为未认证,与 gateway 的其余部分保持一致。 ## 构建 UI -Gateway 网关会从 `dist/control-ui` 提供静态文件。请使用以下命令构建: +Gateway 网关会从 `dist/control-ui` 提供静态文件。使用以下命令构建它们: ```bash pnpm ui:build ``` -可选的绝对 base(当你想要固定资源 URL 时): +可选绝对 base(当你希望固定资源 URL 时): ```bash OPENCLAW_CONTROL_UI_BASE_PATH=/openclaw/ pnpm ui:build ``` -用于本地开发(独立 dev server): +本地开发(独立开发服务器): ```bash pnpm ui:dev @@ -301,20 +348,20 @@ pnpm ui:dev 然后将 UI 指向你的 Gateway 网关 WS URL(例如 `ws://127.0.0.1:18789`)。 -## 调试/测试:dev server + 远程 Gateway 网关 +## 调试/测试:开发服务器 + 远端 Gateway 网关 -Control UI 是静态文件;WebSocket 目标可配置,并且可以 -与 HTTP 源不同。当你想在本地运行 Vite dev server, -但 Gateway 网关运行在别处时,这非常有用。 +控制 UI 是静态文件;WebSocket 目标可配置,并且可以 +不同于 HTTP 源。当你希望在本地运行 Vite 开发服务器, +但 Gateway 网关运行在其他地方时,这会很方便。 -1. 启动 UI dev server:`pnpm ui:dev` +1. 启动 UI 开发服务器:`pnpm ui:dev` 2. 打开如下 URL: ```text http://localhost:5173/?gatewayUrl=ws://:18789 ``` -可选的一次性身份验证(如需要): +可选的一次性身份验证(如有需要): ```text http://localhost:5173/?gatewayUrl=wss://:18789#token= @@ -322,19 +369,20 @@ http://localhost:5173/?gatewayUrl=wss://:18789#token=:18789#token=