chore(i18n): refresh zh-CN translations
This commit is contained in:
parent
bfa64c42a4
commit
4e74d640e1
@ -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 <job-id>
|
||||
|
||||
@ -38,60 +38,61 @@ openclaw cron show <job-id>
|
||||
openclaw cron runs --id <job-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:<jobId>` 会话所跟踪的浏览器标签页/进程,这样分离的浏览器自动化就不会留下孤儿进程。
|
||||
- 独立 cron 运行还会防止陈旧的确认回复。如果第一个结果只是一个中间状态更新(例如 `on it`、`pulling everything together` 以及类似提示),并且没有后代子智能体运行仍然负责最终答案,OpenClaw 会在投递前再次提示一次以获取实际结果。
|
||||
- 一次性任务(`--at`)默认在成功后自动删除。
|
||||
- 独立 cron 运行会在运行完成时尽力关闭其 `cron:<jobId>` 会话所跟踪的浏览器标签页/进程,这样分离的浏览器自动化就不会留下孤儿进程。
|
||||
- 独立 cron 运行还会防止过时的确认回复。如果第一个结果只是中间状态更新(如 `on it`、`pulling everything together` 以及类似提示),并且没有任何后代子智能体运行仍负责最终答案,OpenClaw 会在投递前再次提示一次,以获取实际结果。
|
||||
|
||||
<a id="maintenance"></a>
|
||||
|
||||
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:<jobId>` | 报告、后台杂务 |
|
||||
| 当前会话 | `current` | 在创建时绑定 | 依赖上下文的周期性工作 |
|
||||
| 自定义会话 | `session:custom-id`| 持久命名会话 | 基于历史持续推进的工作流 |
|
||||
| 方式 | `--session` 值 | 运行位置 | 最适合 |
|
||||
| --------------- | ------------------- | ------------------------ | ----------------------------- |
|
||||
| 主会话 | `main` | 下一次 heartbeat 轮次 | 提醒、系统事件 |
|
||||
| 独立 | `isolated` | 专用 `cron:<jobId>` | 报告、后台杂务 |
|
||||
| 当前会话 | `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:<id>`、`user:<id>`)。
|
||||
使用 `--announce --channel telegram --to "-1001234567890"` 可投递到渠道。对于 Telegram 论坛话题,请使用 `-1001234567890:topic:123`。Slack/Discord/Mattermost 目标应使用显式前缀(`channel:<id>`、`user:<id>`)。
|
||||
|
||||
对于独立任务,聊天投递是共享的。如果有可用聊天路由,即使任务使用了 `--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 <token>`(推荐)
|
||||
- `x-openclaw-token: <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/\<name\>)
|
||||
|
||||
自定义 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 <project-id>
|
||||
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 <jobId> --clear-agent
|
||||
模型覆盖说明:
|
||||
|
||||
- `openclaw cron add|edit --model ...` 会更改任务所选的模型。
|
||||
- 如果该模型被允许,那个确切的提供商/模型就会传递到独立智能体运行中。
|
||||
- 如果该模型被允许,独立智能体运行将使用这个精确的 provider/模型。
|
||||
- 如果不被允许,cron 会发出警告,并回退到任务的智能体/默认模型选择。
|
||||
- 已配置的回退链仍然适用,但普通的 `--model` 覆盖若没有显式的按任务回退列表,将不再静默回落到智能体主模型作为额外重试目标。
|
||||
- 已配置的回退链仍然适用,但普通的 `--model` 覆盖如果没有显式的逐任务回退列表,就不再静默回落到智能体主模型作为额外的重试目标。
|
||||
|
||||
## 配置
|
||||
|
||||
@ -352,19 +353,19 @@ openclaw cron edit <jobId> --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 <jobId> --due` 检查时,该任务尚未到期。
|
||||
- 确认 Gateway 网关正在持续运行。
|
||||
- 对于 `cron` 调度,请核对时区(`--tz`)与主机时区是否一致。
|
||||
- 运行输出中的 `reason: not-due` 表示你通过 `openclaw cron run <jobId> --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) — 时区配置
|
||||
|
||||
@ -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 网关用于私信和服务器频道。
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="配对" icon="link" href="/zh-CN/channels/pairing">
|
||||
@ -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**)。
|
||||
|
||||
<Steps>
|
||||
<Step title="创建 Discord 应用和机器人">
|
||||
前往 [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 智能体的称呼。
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="启用特权 intents">
|
||||
仍然在 **Bot** 页面,向下滚动到 **Privileged Gateway Intents** 并启用:
|
||||
仍在 **Bot** 页面时,向下滚动到 **Privileged Gateway Intents**,并启用:
|
||||
|
||||
- **Message Content Intent**(必需)
|
||||
- **Server Members Intent**(推荐;角色允许列表和名称到 ID 匹配所必需)
|
||||
- **Presence Intent**(可选;仅在需要在线状态更新时才需要)
|
||||
- **Server Members Intent**(推荐;角色 allowlist 和名称到 ID 匹配时必需)
|
||||
- **Presence Intent**(可选;仅在需要在线状态更新时使用)
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="复制你的机器人令牌">
|
||||
向上滚动回 **Bot** 页面顶部并点击 **Reset Token**。
|
||||
向上滚动回 **Bot** 页面顶部,点击 **Reset Token**。
|
||||
|
||||
<Note>
|
||||
尽管名字如此,这会生成你的第一个令牌——并不会“重置”任何东西。
|
||||
尽管名字叫这样,但这里会生成你的第一个令牌 —— 并没有任何内容被“重置”。
|
||||
</Note>
|
||||
|
||||
复制该令牌并将其保存在某处。这就是你的 **Bot Token**,你很快就会用到它。
|
||||
复制该令牌并保存到某处。这就是你的 **Bot Token**,你很快就会用到它。
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="生成邀请 URL 并将机器人添加到你的服务器">
|
||||
点击侧边栏中的 **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 服务器中看到你的机器人。
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="启用开发者模式并收集你的 ID">
|
||||
回到 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。
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="允许来自服务器成员的私信">
|
||||
为了让配对正常工作,Discord 需要允许你的机器人向你发送私信。右键点击你的**服务器图标** → **Privacy Settings** → 打开 **Direct Messages**。
|
||||
要让配对正常工作,Discord 需要允许你的机器人向你发送私信。右键点击你的 **server icon** → **Privacy Settings** → 打开 **Direct Messages**。
|
||||
|
||||
这会允许服务器成员(包括机器人)向你发送私信。如果你想通过 Discord 私信使用 OpenClaw,请保持启用。如果你只打算使用服务器频道,则可在配对完成后禁用私信。
|
||||
这样服务器成员(包括机器人)就可以向你发送私信。如果你想在 OpenClaw 中使用 Discord 私信,请保持该选项启用。如果你只打算使用服务器频道,那么在完成配对后可以关闭私信。
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="安全设置你的机器人令牌(不要在聊天中发送它)">
|
||||
你的 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` 进程。
|
||||
|
||||
</Step>
|
||||
|
||||
@ -121,9 +121,9 @@ openclaw gateway
|
||||
|
||||
<Tabs>
|
||||
<Tab title="询问你的智能体">
|
||||
在任何现有渠道(例如 Telegram)中与你的 OpenClaw 智能体聊天,并告诉它。如果 Discord 是你的第一个渠道,请改用 CLI / 配置标签页。
|
||||
在任何现有渠道(例如 Telegram)上与你的 OpenClaw 智能体聊天,并告诉它。如果 Discord 是你的第一个渠道,请改用 CLI / config 标签页。
|
||||
|
||||
> “我已经在配置中设置了 Discord 机器人令牌。请使用 User ID `<user_id>` 和 Server ID `<server_id>` 完成 Discord 设置。”
|
||||
> “我已经在配置中设置好了 Discord 机器人令牌。请使用 User ID `<user_id>` 和 Server ID `<server_id>` 完成 Discord 设置。”
|
||||
</Tab>
|
||||
<Tab title="CLI / 配置">
|
||||
如果你更喜欢基于文件的配置,请设置:
|
||||
@ -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)。
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
@ -161,7 +161,7 @@ DISCORD_BOT_TOKEN=...
|
||||
|
||||
<Tabs>
|
||||
<Tab title="询问你的智能体">
|
||||
在你现有的渠道中把配对码发给你的智能体:
|
||||
在你现有的渠道中,把配对码发送给你的智能体:
|
||||
|
||||
> “批准这个 Discord 配对码:`<CODE>`”
|
||||
</Tab>
|
||||
@ -175,29 +175,29 @@ openclaw pairing approve discord <CODE>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
配对码将在 1 小时后过期。
|
||||
配对码会在 1 小时后过期。
|
||||
|
||||
现在你应该可以通过私信在 Discord 中与你的智能体聊天了。
|
||||
现在你应该已经可以通过私信在 Discord 中与你的智能体聊天了。
|
||||
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Note>
|
||||
令牌解析具有账户感知能力。配置中的令牌值优先于环境变量回退。`DISCORD_BOT_TOKEN` 仅用于默认账户。
|
||||
对于高级出站调用(消息工具/渠道操作),会对该次调用使用显式的每次调用 `token`。这适用于发送以及读取/探测类操作(例如 read/search/fetch/thread/pins/permissions)。账户策略/重试设置仍来自活动运行时快照中所选账户。
|
||||
令牌解析是账户感知的。配置中的令牌值优先于环境变量回退。`DISCORD_BOT_TOKEN` 仅用于默认账户。
|
||||
对于高级出站调用(消息工具/渠道操作),会为该次调用使用显式的逐调用 `token`。这适用于发送以及读取/探测类操作(例如 read/search/fetch/thread/pins/permissions)。账户策略和重试设置仍然来自活动运行时快照中所选的账户。
|
||||
</Note>
|
||||
|
||||
## 推荐:设置服务器工作区
|
||||
|
||||
当私信可用后,你可以将 Discord 服务器设置为完整工作区,其中每个频道都会获得各自独立的智能体会话和上下文。对于只有你和机器人参与的私有服务器,我们推荐这样做。
|
||||
私信可用后,你可以把 Discord 服务器设置为一个完整工作区,其中每个频道都会获得自己的智能体会话和独立上下文。对于只有你和机器人使用的私有服务器,我们推荐这样做。
|
||||
|
||||
<Steps>
|
||||
<Step title="将你的服务器添加到服务器允许列表">
|
||||
这会让你的智能体能够在服务器上的任何频道中回复,而不仅仅是私信。
|
||||
<Step title="将你的服务器添加到服务器 allowlist">
|
||||
这样你的智能体就可以在服务器中的任意频道内响应,而不仅仅是私信。
|
||||
|
||||
<Tabs>
|
||||
<Tab title="询问你的智能体">
|
||||
> “将我的 Discord Server ID `<server_id>` 添加到服务器允许列表”
|
||||
> “把我的 Discord Server ID `<server_id>` 添加到服务器 allowlist”
|
||||
</Tab>
|
||||
<Tab title="配置">
|
||||
|
||||
@ -223,14 +223,14 @@ openclaw pairing approve discord <CODE>
|
||||
</Step>
|
||||
|
||||
<Step title="允许在不使用 @mention 的情况下回复">
|
||||
默认情况下,你的智能体只有在被 @ 提及时才会在服务器频道中回复。对于私有服务器,你大概率会希望它对每条消息都进行回复。
|
||||
默认情况下,你的智能体只有在服务器频道中被 @ 提及时才会回复。对于私有服务器,你可能更希望它对每条消息都进行回复。
|
||||
|
||||
<Tabs>
|
||||
<Tab title="询问你的智能体">
|
||||
> “允许我的智能体在这个服务器中无需被 @ 提及也能回复”
|
||||
> “允许我的智能体在这个服务器中回复,而不需要被 @ 提及”
|
||||
</Tab>
|
||||
<Tab title="配置">
|
||||
在你的服务器配置中设置 `requireMention: false`:
|
||||
在你的服务器配置中将 `requireMention: false` 设置为:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -259,68 +259,68 @@ openclaw pairing approve discord <CODE>
|
||||
> “当我在 Discord 频道中提问时,如果你需要来自 MEMORY.md 的长期上下文,请使用 memory_search 或 memory_get。”
|
||||
</Tab>
|
||||
<Tab title="手动">
|
||||
如果你需要在每个频道中共享上下文,请将稳定的说明放入 `AGENTS.md` 或 `USER.md`(它们会注入到每个会话中)。将长期笔记保存在 `MEMORY.md` 中,并按需通过记忆工具访问。
|
||||
如果你需要在每个频道中共享上下文,请把稳定的指令放在 `AGENTS.md` 或 `USER.md` 中(它们会注入到每个会话)。把长期笔记保存在 `MEMORY.md` 中,并在需要时通过 memory 工具访问它们。
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
现在,在你的 Discord 服务器中创建一些频道并开始聊天。你的智能体可以看到频道名称,并且每个频道都会获得各自隔离的会话——因此你可以设置 `#coding`、`#home`、`#research`,或任何适合你工作流的频道。
|
||||
现在,在你的 Discord 服务器中创建一些频道并开始聊天吧。你的智能体可以看到频道名称,并且每个频道都会获得自己隔离的会话 —— 因此你可以设置 `#coding`、`#home`、`#research`,或者任何适合你工作流的频道。
|
||||
|
||||
## 运行时模型
|
||||
|
||||
- Gateway 网关拥有 Discord 连接。
|
||||
- 回复路由是确定性的:来自 Discord 的入站回复会返回到 Discord。
|
||||
- Gateway 网关负责 Discord 连接。
|
||||
- 回复路由是确定性的:来自 Discord 的入站消息会回复到 Discord。
|
||||
- 默认情况下(`session.dmScope=main`),私聊共享智能体主会话(`agent:main:main`)。
|
||||
- 服务器频道使用隔离的会话键(`agent:<agentId>:discord:channel:<channelId>`)。
|
||||
- 群组私信默认会被忽略(`channels.discord.dm.groupEnabled=false`)。
|
||||
- 原生斜杠命令在隔离的命令会话中运行(`agent:<agentId>:discord:slash:<userId>`),同时仍携带 `CommandTargetSessionKey` 指向被路由的对话会话。
|
||||
- 默认忽略群组私信(`channels.discord.dm.groupEnabled=false`)。
|
||||
- 原生斜杠命令在隔离的命令会话中运行(`agent:<agentId>:discord:slash:<userId>`),同时仍会将 `CommandTargetSessionKey` 传递到路由后的对话会话。
|
||||
|
||||
## 论坛频道
|
||||
## forum 渠道
|
||||
|
||||
Discord 论坛和媒体频道只接受线程帖子。OpenClaw 支持两种创建方式:
|
||||
Discord forum 和 media 渠道只接受帖子串。OpenClaw 支持两种创建方式:
|
||||
|
||||
- 向论坛父级频道(`channel:<forumId>`)发送消息以自动创建线程。线程标题使用你消息中的第一行非空内容。
|
||||
- 使用 `openclaw message thread create` 直接创建线程。对于论坛频道,不要传递 `--message-id`。
|
||||
- 向 forum 父频道(`channel:<forumId>`)发送消息以自动创建帖子串。帖子串标题使用你消息中的第一行非空内容。
|
||||
- 使用 `openclaw message thread create` 直接创建帖子串。对于 forum 渠道,不要传递 `--message-id`。
|
||||
|
||||
示例:向论坛父级频道发送消息以创建线程
|
||||
示例:发送到 forum 父频道以创建帖子串
|
||||
|
||||
```bash
|
||||
openclaw message send --channel discord --target channel:<forumId> \
|
||||
--message "Topic title\nBody of the post"
|
||||
```
|
||||
|
||||
示例:显式创建论坛线程
|
||||
示例:显式创建 forum 帖子串
|
||||
|
||||
```bash
|
||||
openclaw message thread create --channel discord --target channel:<forumId> \
|
||||
--thread-name "Topic title" --message "Body of the post"
|
||||
```
|
||||
|
||||
论坛父级频道不接受 Discord 组件。如果你需要组件,请发送到线程本身(`channel:<threadId>`)。
|
||||
forum 父频道不接受 Discord components。如果你需要 components,请发送到帖子串本身(`channel:<threadId>`)。
|
||||
|
||||
## 交互式组件
|
||||
## 交互式 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://<filename>`)
|
||||
- `file` 块必须指向一个附件引用(`attachment://<filename>`)
|
||||
- 通过 `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>`
|
||||
- `<@id>` mention
|
||||
- `<@id>` 提及
|
||||
|
||||
裸数字 ID 含义不明确,会被拒绝,除非显式提供用户/频道目标类型。
|
||||
裸数字 ID 存在歧义,除非提供了明确的用户/频道目标类型,否则会被拒绝。
|
||||
|
||||
</Tab>
|
||||
|
||||
@ -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` 也是如此。
|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab title="提及和群组私信">
|
||||
服务器消息默认受提及门控限制。
|
||||
默认情况下,服务器消息受提及门控。
|
||||
|
||||
提及检测包括:
|
||||
|
||||
- 显式提及机器人
|
||||
- 已配置的提及模式(`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)
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### 基于角色的智能体路由
|
||||
|
||||
使用 `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`)并不要求为成员启用在线状态更新。
|
||||
|
||||
</Accordion>
|
||||
|
||||
@ -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`。
|
||||
|
||||
</Accordion>
|
||||
|
||||
@ -551,20 +551,20 @@ OpenClaw 支持在智能体消息中使用 Discord components v2 容器。请使
|
||||
- channel ID
|
||||
- user ID
|
||||
|
||||
在 OpenClaw 配置中优先使用数字 ID,以获得可靠的审计和探测结果。
|
||||
在 OpenClaw 配置中优先使用数字 ID,以获得更可靠的审计和探测结果。
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 原生命令和命令认证
|
||||
## 原生命令和命令鉴权
|
||||
|
||||
- `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 会在上下文/历史记录中呈现,因此智能体可以定位特定消息。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="实时流式预览">
|
||||
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 会跳过预览流,以避免重复流式传输。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="历史、上下文和线程行为">
|
||||
<Accordion title="历史记录、上下文和帖子串行为">
|
||||
服务器历史上下文:
|
||||
|
||||
- `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["<user_id>"].historyLimit`
|
||||
|
||||
线程行为:
|
||||
帖子串行为:
|
||||
|
||||
- Discord 线程会被路由为频道会话
|
||||
- 父线程元数据可用于父会话关联
|
||||
- 线程配置会继承父频道配置,除非存在线程专用条目
|
||||
- Discord 帖子串作为频道会话进行路由
|
||||
- 父帖子串元数据可用于父会话关联
|
||||
- 除非存在特定于帖子串的条目,否则帖子串配置会继承父频道配置
|
||||
- 新创建的自动帖子串是否继承父转录内容,由 `channels.discord.thread.inheritParent` 选择启用(默认 `false`)。当为 `false` 时,新创建的 Discord 帖子串会话会与父频道转录内容隔离;当为 `true` 时,父频道历史会为新帖子串会话提供初始上下文
|
||||
- 按账户覆盖位于 `channels.discord.accounts.<id>.thread.inheritParent`
|
||||
- 消息工具的 reaction 除了频道目标外,也可以解析 `user:<id>` 私信目标
|
||||
- `channels.discord.guilds.<guild>.channels.<channel>.requireMention: false` 会在回复阶段激活回退期间被保留,因此即使运行回复阶段回退,已配置为始终开启的频道仍会保持始终开启
|
||||
|
||||
频道主题会作为**不受信任**的上下文注入(而不是作为系统提示词)。
|
||||
回复和引用消息的上下文目前会按接收时的原样保留。
|
||||
Discord 允许列表主要用于控制谁可以触发智能体,而不是完整的补充上下文脱敏边界。
|
||||
回复和引用消息上下文目前会按接收时的样子保留。
|
||||
Discord allowlist 主要用于限制谁可以触发智能体,而不是完整的补充上下文脱敏边界。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="子智能体的线程绑定会话">
|
||||
Discord 可以将一个线程绑定到某个会话目标,这样该线程中的后续消息会持续路由到同一会话(包括子智能体会话)。
|
||||
<Accordion title="用于子智能体的线程绑定会话">
|
||||
Discord 可以将一个帖子串绑定到某个会话目标,这样该帖子串中的后续消息会持续路由到同一个会话(包括子智能体会话)。
|
||||
|
||||
命令:
|
||||
|
||||
- `/focus <target>` 将当前/新线程绑定到子智能体/会话目标
|
||||
- `/unfocus` 移除当前线程绑定
|
||||
- `/focus <target>` 将当前/新帖子串绑定到一个子智能体/会话目标
|
||||
- `/unfocus` 移除当前帖子串绑定
|
||||
- `/agents` 显示活动运行和绑定状态
|
||||
- `/session idle <duration|off>` 检查/更新已聚焦绑定的不活动自动取消聚焦设置
|
||||
- `/session max-age <duration|off>` 检查/更新已聚焦绑定的硬性最大存活时长
|
||||
- `/session idle <duration|off>` 查看/更新聚焦绑定的空闲自动取消聚焦时间
|
||||
- `/session max-age <duration|off>` 查看/更新聚焦绑定的硬性最大存活时间
|
||||
|
||||
配置:
|
||||
|
||||
@ -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)。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="持久化 ACP 渠道绑定">
|
||||
对于稳定的“始终在线” 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)。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="反应通知">
|
||||
按服务器配置的反应通知模式:
|
||||
<Accordion title="Reaction 通知">
|
||||
按服务器配置的 reaction 通知模式:
|
||||
|
||||
- `off`
|
||||
- `own`(默认)
|
||||
- `all`
|
||||
- `allowlist`(使用 `guilds.<id>.users`)
|
||||
|
||||
反应事件会被转换为系统事件,并附加到被路由的 Discord 会话中。
|
||||
Reaction 事件会被转换为系统事件,并附加到路由后的 Discord 会话。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="确认反应">
|
||||
<Accordion title="确认 Reaction">
|
||||
`ackReaction` 会在 OpenClaw 处理入站消息时发送一个确认 emoji。
|
||||
|
||||
解析顺序:
|
||||
@ -806,7 +810,7 @@ OpenClaw 支持在智能体消息中使用 Discord components v2 容器。请使
|
||||
说明:
|
||||
|
||||
- Discord 接受 unicode emoji 或自定义 emoji 名称。
|
||||
- 使用 `""` 可为某个渠道或账户禁用该反应。
|
||||
- 使用 `""` 可为某个渠道或账户禁用该 reaction。
|
||||
|
||||
</Accordion>
|
||||
|
||||
@ -815,7 +819,7 @@ OpenClaw 支持在智能体消息中使用 Discord components v2 容器。请使
|
||||
|
||||
这会影响 `/config set|unset` 流程(当命令功能启用时)。
|
||||
|
||||
禁用方式:
|
||||
禁用:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -830,7 +834,7 @@ OpenClaw 支持在智能体消息中使用 Discord components v2 容器。请使
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Gateway 网关代理">
|
||||
使用 `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 容器。请使
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="PluralKit 支持">
|
||||
启用 PluralKit 解析,将代理消息映射到系统成员身份:
|
||||
启用 PluralKit 解析,将代理消息映射到 system member 身份:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -878,8 +882,8 @@ OpenClaw 支持在智能体消息中使用 Discord components v2 容器。请使
|
||||
|
||||
说明:
|
||||
|
||||
- 允许列表可使用 `pk:<memberId>`
|
||||
- 只有在 `channels.discord.dangerouslyAllowNameMatching: true` 时,才会按名称/slug 匹配成员显示名
|
||||
- allowlist 可以使用 `pk:<memberId>`
|
||||
- 只有当 `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 容器。请使
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Discord 中的审批">
|
||||
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.<id>.ui.components.accentColor` 设置。
|
||||
- 可通过 `channels.discord.accounts.<id>.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
|
||||
## 故障排除
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="使用了不允许的 intents,或机器人看不到服务器消息">
|
||||
<Accordion title="使用了不允许的 intents,或机器人看不到任何服务器消息">
|
||||
|
||||
- 启用 Message Content Intent
|
||||
- 当你依赖用户/成员解析时,启用 Server Members Intent
|
||||
@ -1121,14 +1125,14 @@ message(action="send", channel="discord", target="channel:123", path="/path/to/a
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="服务器消息被意外拦截">
|
||||
<Accordion title="服务器消息被意外阻止">
|
||||
|
||||
- 检查 `groupPolicy`
|
||||
- 检查 `channels.discord.guilds` 下的服务器允许列表
|
||||
- 如果存在服务器 `channels` 映射,则仅允许列出的频道
|
||||
- 检查 `requireMention` 行为和提及模式
|
||||
- 验证 `groupPolicy`
|
||||
- 验证 `channels.discord.guilds` 下的服务器 allowlist
|
||||
- 如果存在服务器 `channels` 映射,则只允许列出的频道
|
||||
- 验证 `requireMention` 行为和提及模式
|
||||
|
||||
有用的检查命令:
|
||||
有用的检查:
|
||||
|
||||
```bash
|
||||
openclaw doctor
|
||||
@ -1138,12 +1142,12 @@ openclaw logs --follow
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="已设置 require mention 为 false,但仍被拦截">
|
||||
<Accordion title="requireMention 为 false,但仍然被阻止">
|
||||
常见原因:
|
||||
|
||||
- `groupPolicy="allowlist"`,但没有匹配的服务器/频道允许列表
|
||||
- `requireMention` 配置在错误位置(必须位于 `channels.discord.guilds` 或频道条目下)
|
||||
- 发送者被服务器/频道 `users` 允许列表拦截
|
||||
- `groupPolicy="allowlist"`,但没有匹配的服务器/频道 allowlist
|
||||
- `requireMention` 配置在错误的位置(必须位于 `channels.discord.guilds` 或频道条目下)
|
||||
- 发送者被服务器/频道 `users` allowlist 阻止
|
||||
|
||||
</Accordion>
|
||||
|
||||
@ -1155,12 +1159,12 @@ openclaw logs --follow
|
||||
- `Slow listener detected ...`
|
||||
- `discord inbound worker timed out after ...`
|
||||
|
||||
监听器预算调节项:
|
||||
监听器预算旋钮:
|
||||
|
||||
- 单账户:`channels.discord.eventQueue.listenerTimeout`
|
||||
- 多账户:`channels.discord.accounts.<accountId>.eventQueue.listenerTimeout`
|
||||
|
||||
Worker 运行超时调节项:
|
||||
Worker 运行超时旋钮:
|
||||
|
||||
- 单账户:`channels.discord.inboundWorker.runTimeoutMs`
|
||||
- 多账户:`channels.discord.accounts.<accountId>.inboundWorker.runTimeoutMs`
|
||||
@ -1187,14 +1191,14 @@ openclaw logs --follow
|
||||
}
|
||||
```
|
||||
|
||||
对于缓慢的监听器初始化,请使用 `eventQueue.listenerTimeout`;仅当你希望为排队中的智能体轮次提供单独的安全阀时,才使用 `inboundWorker.runTimeoutMs`。
|
||||
对于缓慢的监听器初始化,请使用 `eventQueue.listenerTimeout`;只有在你希望为排队的智能体轮次设置单独的安全阀时,才使用 `inboundWorker.runTimeoutMs`。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="权限审计不匹配">
|
||||
`channels status --probe` 的权限检查仅适用于数字频道 ID。
|
||||
`channels status --probe` 权限检查仅适用于数字频道 ID。
|
||||
|
||||
如果你使用 slug 键,运行时匹配仍然可能正常工作,但探测无法完整验证权限。
|
||||
如果你使用 slug 键,运行时匹配仍然可以工作,但探测无法完整验证权限。
|
||||
|
||||
</Accordion>
|
||||
|
||||
@ -1207,22 +1211,22 @@ openclaw logs --follow
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="机器人到机器人的循环">
|
||||
默认情况下,会忽略由机器人发送的消息。
|
||||
默认情况下,由机器人发送的消息会被忽略。
|
||||
|
||||
如果你设置了 `channels.discord.allowBots=true`,请使用严格的提及和允许列表规则以避免循环行为。
|
||||
更推荐使用 `channels.discord.allowBots="mentions"`,仅接受提及机器人的机器人消息。
|
||||
如果你设置了 `channels.discord.allowBots=true`,请使用严格的提及和 allowlist 规则,以避免循环行为。
|
||||
建议使用 `channels.discord.allowBots="mentions"`,仅接受提及该机器人的机器人消息。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="语音 STT 因 DecryptionFailed(...) 丢失">
|
||||
|
||||
- 保持 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) 进行对比
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
@ -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` 重新检查。
|
||||
|
||||
|
||||
@ -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`
|
||||
|
||||
<Note>
|
||||
`IRC_HOST` 位于端点屏蔽列表中,不能通过工作区 `.env` 文件设置。
|
||||
它必须来自 shell 环境或 Gateway 网关进程环境,
|
||||
以防止不受信任的工作区将 IRC 流量重定向到其他服务器。
|
||||
完整列表请参见 [工作区 `.env` 文件](/zh-CN/gateway/security)。
|
||||
</Note>
|
||||
|
||||
## 故障排除
|
||||
|
||||
- 如果机器人已连接,但在频道中始终不回复,请检查 `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) — 访问模型与加固措施
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -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.<id>.commands` 下(账户值会覆盖顶层字段)。
|
||||
- 命令回调会使用 Mattermost 在 OpenClaw 注册 `oc_*` 命令时
|
||||
返回的每个命令 token 进行校验。
|
||||
- 当注册失败、启动不完整,或回调 token 与任何已注册命令都不匹配时,
|
||||
斜杠命令回调会以默认拒绝的方式失败。
|
||||
- 可达性要求:回调端点必须可从 Mattermost 服务器访问。
|
||||
- `native: "auto"` 在 Mattermost 中默认禁用。设置 `native: true` 以启用。
|
||||
- 如果省略 `callbackUrl`,OpenClaw 会根据 Gateway 网关的 host/port + `callbackPath` 自动推导。
|
||||
- 对于多账户设置,`commands` 可设置在顶层,或设置在
|
||||
`channels.mattermost.accounts.<id>.commands` 下(账户级值会覆盖顶层字段)。
|
||||
- 命令回调会使用 OpenClaw 注册 `oc_*` 命令时由
|
||||
Mattermost 返回的每个命令对应 token 进行校验。
|
||||
- 当注册失败、启动不完整,或
|
||||
回调 token 与任一已注册命令都不匹配时,斜杠命令回调会以失败关闭的方式拒绝处理。
|
||||
- 可达性要求:回调端点必须能从 Mattermost 服务器访问。
|
||||
- 除非 Mattermost 与 OpenClaw 运行在同一主机/网络命名空间中,否则不要将 `callbackUrl` 设置为 `localhost`。
|
||||
- 除非该 URL 会将 `/api/channels/mattermost/command` 反向代理到 OpenClaw,否则不要将 `callbackUrl` 设置为你的 Mattermost base URL。
|
||||
- 一个快速检查方法是运行 `curl https://<gateway-host>/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://<gateway-host>/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`)。其他账户必须使用配置值。
|
||||
|
||||
<Note>
|
||||
`MATTERMOST_URL` 位于端点屏蔽列表中,不能从工作区 `.env` 文件中设置。
|
||||
它必须来自 shell 环境或 Gateway 网关进程环境,
|
||||
这样不受信任的工作区就无法将 Mattermost 流量重定向到其他服务器。完整列表请参阅
|
||||
[工作区 `.env` 文件](/zh-CN/gateway/security)。
|
||||
</Note>
|
||||
|
||||
## 聊天模式
|
||||
|
||||
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 <CODE>`
|
||||
- 公开私信:`channels.mattermost.dmPolicy="open"` 加上 `channels.mattermost.allowFrom=["*"]`。
|
||||
|
||||
## Channels(群组)
|
||||
## 渠道(群组)
|
||||
|
||||
- 默认:`channels.mattermost.groupPolicy = "allowlist"`(提及门控)。
|
||||
- 使用 `channels.mattermost.groupAllowFrom` 将发送者加入允许列表(推荐使用用户 ID)。
|
||||
- 每个渠道的提及覆盖配置位于 `channels.mattermost.groups.<channelId>.requireMention`
|
||||
- 默认:`channels.mattermost.groupPolicy = "allowlist"`(受提及限制)。
|
||||
- 使用 `channels.mattermost.groupAllowFrom` 将发送者加入 allowlist(推荐使用用户 ID)。
|
||||
- 针对单个渠道的提及覆盖配置位于 `channels.mattermost.groups.<channelId>.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:<id>` 表示渠道
|
||||
- `user:<id>` 表示私信
|
||||
- `@username` 表示私信(通过 Mattermost API 解析)
|
||||
- `channel:<id>` 用于渠道
|
||||
- `user:<id>` 用于私信
|
||||
- `@username` 用于私信(通过 Mattermost API 解析)
|
||||
|
||||
裸的不透明 ID(如 `64ifufp...`)在 Mattermost 中是**有歧义的**(用户 ID 或渠道 ID)。
|
||||
裸的不透明 ID(例如 `64ifufp...`)在 Mattermost 中是 **有歧义** 的(可能是用户 ID,也可能是渠道 ID)。
|
||||
|
||||
OpenClaw 会按**用户优先**进行解析:
|
||||
OpenClaw 会按 **用户优先** 的顺序解析它们:
|
||||
|
||||
- 如果该 ID 作为用户存在(`GET /api/v4/users/<id>` 成功),OpenClaw 会通过 `/api/v4/channels/direct` 解析直连渠道后发送**私信**。
|
||||
- 否则该 ID 会被视为**渠道 ID**。
|
||||
- 如果该 ID 作为用户存在(`GET /api/v4/users/<id>` 成功),OpenClaw 会通过解析 `/api/v4/channels/direct` 对应的私信渠道来发送 **私信**。
|
||||
- 否则,该 ID 会被视为 **渠道 ID**。
|
||||
|
||||
如果你需要确定性行为,请始终使用显式前缀(`user:<id>` / `channel:<id>`)。
|
||||
如果你需要确定性的行为,请始终使用显式前缀(`user:<id>` / `channel:<id>`)。
|
||||
|
||||
## 私信渠道重试
|
||||
|
||||
当 OpenClaw 向 Mattermost 私信目标发送消息,且需要先解析直连渠道时,
|
||||
默认会重试瞬时性的直连渠道创建失败。
|
||||
当 OpenClaw 向 Mattermost 私信目标发送消息且需要先解析直连渠道时,
|
||||
默认会重试临时性的直连渠道创建失败。
|
||||
|
||||
使用 `channels.mattermost.dmChannelRetry` 为 Mattermost 插件全局调整该行为,
|
||||
或使用 `channels.mattermost.accounts.<id>.dmChannelRetry` 为单个账户调整。
|
||||
使用 `channels.mattermost.dmChannelRetry` 可以为 Mattermost 插件全局调整该行为,
|
||||
或使用 `channels.mattermost.accounts.<id>.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:<channelId> messageId=<po
|
||||
|
||||
配置:
|
||||
|
||||
- `channels.mattermost.actions.reactions`:启用/禁用 reaction 操作(默认 true)。
|
||||
- 每账户覆盖:`channels.mattermost.accounts.<id>.actions.reactions`。
|
||||
- `channels.mattermost.actions.reactions`:启用/禁用回应操作(默认 true)。
|
||||
- 按账户覆盖:`channels.mattermost.accounts.<id>.actions.reactions`。
|
||||
|
||||
## 交互式按钮(消息工具)
|
||||
|
||||
发送带有可点击按钮的消息。当用户点击按钮时,智能体会收到该选择,
|
||||
并可以作出响应。
|
||||
并可作出响应。
|
||||
|
||||
通过将 `inlineButtons` 添加到渠道能力中来启用按钮:
|
||||
|
||||
@ -320,43 +326,43 @@ message action=send channel=mattermost target=channel:<channelId> 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.<id>.interactions.callbackBaseUrl` 下设置相同字段。
|
||||
- 如果省略 `interactions.callbackBaseUrl`,OpenClaw 会根据
|
||||
`gateway.customBindHost` + `gateway.port` 推导回调 URL,然后回退到 `http://localhost:<port>`。
|
||||
- 可达性规则:按钮回调 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:<channelId> 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:<channelId> buttons=[[{"te
|
||||
context: {
|
||||
action_id: "mybutton01", // 必须与按钮 id 匹配(用于名称查找)
|
||||
action: "approve",
|
||||
// ... 任何自定义字段 ...
|
||||
_token: "<hmac>", // 参见下方 HMAC 章节
|
||||
// ... any custom fields ...
|
||||
_token: "<hmac>", // 见下方 HMAC 章节
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -393,26 +399,26 @@ message action=send channel=mattermost target=channel:<channelId> 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) — 访问模型与安全加固
|
||||
|
||||
@ -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。
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="配对" icon="link" href="/zh-CN/channels/pairing">
|
||||
@ -33,13 +33,13 @@ x-i18n:
|
||||
<Tabs>
|
||||
<Tab title="Socket Mode(默认)">
|
||||
<Steps>
|
||||
<Step title="创建新的 Slack 应用">
|
||||
<Step title="创建一个新的 Slack 应用">
|
||||
在 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-...`)
|
||||
</Step>
|
||||
|
||||
<Step title="配置 OpenClaw">
|
||||
@ -57,7 +57,7 @@ x-i18n:
|
||||
}
|
||||
```
|
||||
|
||||
环境变量回退(仅默认账户):
|
||||
环境变量回退方式(仅默认账户):
|
||||
|
||||
```bash
|
||||
SLACK_APP_TOKEN=xapp-...
|
||||
@ -79,13 +79,13 @@ openclaw gateway
|
||||
|
||||
<Tab title="HTTP 请求 URL">
|
||||
<Steps>
|
||||
<Step title="创建新的 Slack 应用">
|
||||
<Step title="创建一个新的 Slack 应用">
|
||||
在 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-...`)
|
||||
|
||||
</Step>
|
||||
|
||||
@ -108,7 +108,7 @@ openclaw gateway
|
||||
<Note>
|
||||
对多账户 HTTP 使用唯一的 webhook 路径
|
||||
|
||||
为每个账户提供不同的 `webhookPath`(默认为 `/slack/events`),以避免注册冲突。
|
||||
为每个账户设置不同的 `webhookPath`(默认为 `/slack/events`),以避免注册冲突。
|
||||
</Note>
|
||||
|
||||
</Step>
|
||||
@ -125,7 +125,7 @@ openclaw gateway
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## 清单与 scope 检查清单
|
||||
## 清单和权限范围检查清单
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Socket Mode(默认)">
|
||||
@ -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
|
||||
|
||||
### 其他清单设置
|
||||
|
||||
显示可扩展上述默认值的不同功能。
|
||||
展示扩展上述默认配置的不同功能。
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="可选的原生斜杠命令">
|
||||
|
||||
可以使用多个[原生斜杠命令](#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) 的一个子集:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Socket Mode(默认)">
|
||||
@ -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 <duration|off> 或 max-age <duration|off>"
|
||||
"description": "Manage thread-binding expiry",
|
||||
"usage_hint": "idle <duration|off> or max-age <duration|off>"
|
||||
},
|
||||
{
|
||||
"command": "/think",
|
||||
"description": "设置思考级别",
|
||||
"description": "Set the thinking level",
|
||||
"usage_hint": "<level>"
|
||||
},
|
||||
{
|
||||
"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=<auto|sandbox|gateway|node> security=<deny|allowlist|full> ask=<off|on-miss|always> node=<id>"
|
||||
},
|
||||
{
|
||||
"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=<n>|size=<n>|all] | add <provider> <modelId>"
|
||||
},
|
||||
{
|
||||
"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": "<name> [input]"
|
||||
},
|
||||
{
|
||||
"command": "/btw",
|
||||
"description": "在不更改会话上下文的情况下提出一个旁支问题",
|
||||
"description": "Ask a side question without changing session context",
|
||||
"usage_hint": "<question>"
|
||||
},
|
||||
{
|
||||
"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 <duration|off> 或 max-age <duration|off>",
|
||||
"description": "Manage thread-binding expiry",
|
||||
"usage_hint": "idle <duration|off> or max-age <duration|off>",
|
||||
"url": "https://gateway-host.example.com/slack/events"
|
||||
},
|
||||
{
|
||||
"command": "/think",
|
||||
"description": "设置思考级别",
|
||||
"description": "Set the thinking level",
|
||||
"usage_hint": "<level>",
|
||||
"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=<auto|sandbox|gateway|node> security=<deny|allowlist|full> ask=<off|on-miss|always> node=<id>",
|
||||
"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=<n>|size=<n>|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": "<name> [input]",
|
||||
"url": "https://gateway-host.example.com/slack/events"
|
||||
},
|
||||
{
|
||||
"command": "/btw",
|
||||
"description": "在不更改会话上下文的情况下提出一个旁支问题",
|
||||
"description": "Ask a side question without changing session context",
|
||||
"usage_hint": "<question>",
|
||||
"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
|
||||
</Tabs>
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="可选作者身份 scope(写入操作)">
|
||||
如果你希望发送消息时使用当前智能体身份(自定义用户名和图标),而不是默认的 Slack 应用身份,请添加 `chat:write.customize` bot scope。
|
||||
<Accordion title="可选的作者身份作用域(写入操作)">
|
||||
如果你希望发出的消息使用当前智能体身份(自定义用户名和图标),而不是默认的 Slack 应用身份,请添加 `chat:write.customize` bot scope。
|
||||
|
||||
如果你使用 emoji 图标,Slack 要求采用 `:emoji_name:` 语法。
|
||||
如果你使用表情符号图标,Slack 期望使用 `:emoji_name:` 语法。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="可选用户令牌 scope(读取操作)">
|
||||
如果你配置了 `channels.slack.userToken`,典型的读取 scope 包括:
|
||||
<Accordion title="可选的用户令牌作用域(读取操作)">
|
||||
如果你配置了 `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`。
|
||||
|
||||
<Tip>
|
||||
对于操作/目录读取,如果已配置,可以优先使用用户令牌。对于写入操作,仍然优先使用 bot 令牌;只有当 `userTokenReadOnly: false` 且 bot 令牌不可用时,才允许使用用户令牌写入。
|
||||
对于操作/目录读取,如果已配置,则可以优先使用用户令牌。对于写入操作,仍然优先使用 bot 令牌;只有当 `userTokenReadOnly: false` 且 bot 令牌不可用时,才允许使用用户令牌写入。
|
||||
</Tip>
|
||||
|
||||
## 操作与门控
|
||||
## 操作和门控
|
||||
|
||||
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 <code>`。
|
||||
私信中的配对使用 `openclaw pairing approve slack <code>`。
|
||||
|
||||
</Tab>
|
||||
|
||||
@ -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`
|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab title="提及与渠道用户">
|
||||
默认情况下,渠道消息受提及门控限制。
|
||||
默认情况下,渠道消息受提及门控控制。
|
||||
|
||||
提及来源:
|
||||
|
||||
@ -680,57 +675,59 @@ Slack 操作由 `channels.slack.actions.*` 控制。
|
||||
- 提及正则模式(`agents.list[].groupChat.mentionPatterns`,回退到 `messages.groupChat.mentionPatterns`)
|
||||
- 隐式回复给 bot 的线程行为(当 `thread.requireExplicitMention` 为 `true` 时禁用)
|
||||
|
||||
每个渠道的控制项(`channels.slack.channels.<id>`;仅能通过启动时解析或 `dangerouslyAllowNameMatching` 使用名称):
|
||||
每个渠道的控制项(`channels.slack.channels.<id>`;名称仅通过启动解析或 `dangerouslyAllowNameMatching` 支持):
|
||||
|
||||
- `requireMention`
|
||||
- `users`(allowlist)
|
||||
- `users`(允许列表)
|
||||
- `allowBots`
|
||||
- `skills`
|
||||
- `systemPrompt`
|
||||
- `tools`, `toolsBySender`
|
||||
- `tools`、`toolsBySender`
|
||||
- `toolsBySender` 键格式:`id:`、`e164:`、`username:`、`name:` 或 `"*"` 通配符
|
||||
(旧版无前缀键仍然只会映射到 `id:`)
|
||||
(旧版无前缀键仍然只映射到 `id:`)
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## 线程、会话与回复标签
|
||||
## 线程、会话和回复标签
|
||||
|
||||
- 私信路由为 `direct`;渠道路由为 `channel`;MPIM 路由为 `group`。
|
||||
- 使用默认 `session.dmScope=main` 时,Slack 私信会合并到智能体主会话。
|
||||
- 使用默认 `session.dmScope=main` 时,Slack 私信会折叠到智能体主会话。
|
||||
- 渠道会话:`agent:<agentId>:slack:channel:<channelId>`。
|
||||
- 在线程适用时,线程回复可以创建线程会话后缀(`:thread:<threadTs>`)。
|
||||
- `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:<threadTs>`)。
|
||||
- `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:<id>]]`
|
||||
|
||||
注意:`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.<accountId>.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.<accountId>.typingReaction`
|
||||
- `channels.slack.typingReaction`
|
||||
|
||||
说明:
|
||||
注意:
|
||||
|
||||
- Slack 要求使用短代码(例如 `"hourglass_flowing_sand"`)。
|
||||
- 该反应采用尽力而为的方式,回复完成或失败路径结束后会自动尝试清理。
|
||||
- Slack 期望使用短代码(例如 `"hourglass_flowing_sand"`)。
|
||||
- 该反应为尽力而为机制,在回复完成或失败路径结束后会自动尝试清理。
|
||||
|
||||
## 媒体、分块与投递
|
||||
## 媒体、分块和投递
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="入站附件">
|
||||
@ -797,11 +795,11 @@ Slack 操作由 `channels.slack.actions.*` 控制。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="出站文本与文件">
|
||||
<Accordion title="出站文本和文件">
|
||||
- 文本分块使用 `channels.slack.textChunkLimit`(默认 4000)
|
||||
- `channels.slack.chunkMode="newline"` 启用优先按段落拆分
|
||||
- `channels.slack.chunkMode="newline"` 启用按段落优先拆分
|
||||
- 文件发送使用 Slack 上传 API,并可包含线程回复(`thread_ts`)
|
||||
- 如果配置了 `channels.slack.mediaMaxMb`,出站媒体上限将遵循该值;否则渠道发送会使用媒体管道中的 MIME 类型默认值
|
||||
- 如果配置了 `channels.slack.mediaMaxMb`,出站媒体上限遵循该值;否则,渠道发送会使用媒体管道中的 MIME 类型默认值
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="投递目标">
|
||||
@ -810,14 +808,14 @@ Slack 操作由 `channels.slack.actions.*` 控制。
|
||||
- 私信使用 `user:<id>`
|
||||
- 渠道使用 `channel:<id>`
|
||||
|
||||
发送到用户目标时,Slack 私信会通过 Slack 会话 API 打开。
|
||||
向用户目标发送时,Slack 私信会通过 Slack 会话 API 打开。
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 命令与斜杠行为
|
||||
## 命令和斜杠行为
|
||||
|
||||
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:<agentId>:slack:slash:<userId>` 的隔离键,但仍会通过 `CommandTargetSessionKey` 将命令执行路由到目标会话。
|
||||
斜杠会话使用独立键,如 `agent:<agentId>:slack:slash:<userId>`,同时仍通过 `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 可以作为原生审批客户端,使用交互式按钮和交互,而
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="渠道中没有回复">
|
||||
按顺序检查:
|
||||
按以下顺序检查:
|
||||
|
||||
- `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
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Socket 模式未连接">
|
||||
验证 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` 支持的
|
||||
实际值。
|
||||
|
||||
</Accordion>
|
||||
@ -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。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="原生/斜杠命令未触发">
|
||||
验证你原本打算使用的是:
|
||||
<Accordion title="使用自定义 bot 令牌进行文件下载">
|
||||
当调用方传入 `cfg`,但未显式提供 `token` 或预构建客户端时,`downloadFile` 辅助函数会从运行时配置解析其 bot 令牌,从而在 action 运行时路径之外保留仅 `cfg` 的文件下载能力。
|
||||
</Accordion>
|
||||
|
||||
- 原生命令模式(`channels.slack.commands.native: true`),并在 Slack 中注册了匹配的斜杠命令
|
||||
<Accordion title="原生命令/斜杠命令未触发">
|
||||
验证你是否打算使用以下其中一种:
|
||||
|
||||
- 原生命令模式(`channels.slack.commands.native: true`),并且已在 Slack 中注册匹配的斜杠命令
|
||||
- 或单一斜杠命令模式(`channels.slack.slashCommand.enabled: true`)
|
||||
|
||||
另请检查 `commands.useAccessGroups` 以及渠道/用户 allowlist。
|
||||
另外还要检查 `commands.useAccessGroups` 以及渠道/用户允许列表。
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
@ -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 <token> --url <incoming-webhook-url>`
|
||||
- 非交互式设置: `openclaw channels add --channel synology-chat --token <token> --url <incoming-webhook-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 <token> --url <incoming-webhook-url>`
|
||||
- 引导式: `openclaw onboard`
|
||||
- 直接方式: `openclaw channels add --channel synology-chat --token <token> --url <incoming-webhook-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 <token>`
|
||||
- 空令牌或缺失令牌会以失败关闭的方式处理。
|
||||
- 空令牌或缺失令牌会默认拒绝。
|
||||
|
||||
最小配置:
|
||||
|
||||
@ -94,14 +96,21 @@ Webhook 认证详情:
|
||||
|
||||
配置值会覆盖环境变量。
|
||||
|
||||
<Note>
|
||||
`SYNOLOGY_CHAT_INCOMING_URL` 在端点屏蔽列表中,不能从工作区 `.env` 文件中设置。
|
||||
它必须来自 shell 环境或 Gateway 网关进程环境,
|
||||
这样不受信任的工作区就无法将 Synology Chat 流量重定向到其他 webhook。完整列表请参见
|
||||
[工作区 `.env` 文件](/zh-CN/gateway/security)。
|
||||
</Note>
|
||||
|
||||
## 私信策略和访问控制
|
||||
|
||||
- `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 <CODE>`
|
||||
@ -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) — 访问模型和加固
|
||||
|
||||
@ -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 模式为可选。
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="配对" icon="link" href="/zh-CN/channels/pairing">
|
||||
@ -24,7 +24,7 @@ x-i18n:
|
||||
跨渠道诊断与修复操作手册。
|
||||
</Card>
|
||||
<Card title="Gateway 网关配置" icon="settings" href="/zh-CN/gateway/configuration">
|
||||
完整的渠道配置模式与示例。
|
||||
完整的渠道配置模式和示例。
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@ -32,9 +32,9 @@ x-i18n:
|
||||
|
||||
<Steps>
|
||||
<Step title="在 BotFather 中创建机器人令牌">
|
||||
打开 Telegram 并与 **@BotFather** 对话(确认用户名完全是 `@BotFather`)。
|
||||
打开 Telegram 并与 **@BotFather** 对话(确认用户名严格为 `@BotFather`)。
|
||||
|
||||
运行 `/newbot`,按提示操作,并保存令牌。
|
||||
运行 `/newbot`,按照提示操作,并保存令牌。
|
||||
|
||||
</Step>
|
||||
|
||||
@ -54,7 +54,7 @@ x-i18n:
|
||||
```
|
||||
|
||||
环境变量回退:`TELEGRAM_BOT_TOKEN=...`(仅默认账户)。
|
||||
Telegram **不** 使用 `openclaw channels login telegram`;请在配置或环境变量中设置令牌,然后启动 Gateway 网关。
|
||||
Telegram **不**使用 `openclaw channels login telegram`;请在配置/环境变量中配置令牌,然后启动 Gateway 网关。
|
||||
|
||||
</Step>
|
||||
|
||||
@ -76,34 +76,34 @@ openclaw pairing approve telegram <CODE>
|
||||
</Steps>
|
||||
|
||||
<Note>
|
||||
令牌解析顺序与账户有关。实际行为是:配置值优先于环境变量回退,而 `TELEGRAM_BOT_TOKEN` 仅适用于默认账户。
|
||||
令牌解析顺序会感知账户。在实际情况下,配置值优先于环境变量回退,而 `TELEGRAM_BOT_TOKEN` 仅适用于默认账户。
|
||||
</Note>
|
||||
|
||||
## Telegram 端设置
|
||||
## Telegram 侧设置
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="隐私模式和群组可见性">
|
||||
Telegram 机器人默认启用 **隐私模式**,这会限制它们能接收到的群组消息。
|
||||
|
||||
如果机器人必须看到所有群组消息,可以选择以下任一方式:
|
||||
如果机器人必须看到所有群组消息,可选择以下任一方式:
|
||||
|
||||
- 通过 `/setprivacy` 禁用隐私模式,或
|
||||
- 将机器人设为群组管理员。
|
||||
|
||||
切换隐私模式后,请在每个群组中移除并重新添加机器人,以便 Telegram 应用该更改。
|
||||
切换隐私模式时,请在每个群组中移除并重新添加机器人,以便 Telegram 应用该更改。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="群组权限">
|
||||
管理员状态在 Telegram 群组设置中控制。
|
||||
|
||||
具有管理员身份的机器人会接收所有群组消息,这对始终在线的群组行为很有帮助。
|
||||
管理员机器人会接收所有群组消息,这对于始终在线的群组行为很有用。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="有用的 BotFather 开关">
|
||||
|
||||
- `/setjoingroups`:允许或禁止加入群组
|
||||
- `/setjoingroups`:允许/拒绝加入群组
|
||||
- `/setprivacy`:控制群组可见性行为
|
||||
|
||||
</Accordion>
|
||||
@ -113,30 +113,30 @@ openclaw pairing approve telegram <CODE>
|
||||
|
||||
<Tabs>
|
||||
<Tab title="私信策略">
|
||||
`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<bot_token>/getUpdates"
|
||||
<Tab title="群组策略和 allowlist">
|
||||
有两个控制项会共同生效:
|
||||
|
||||
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<bot_token>/getUpdates"
|
||||
<Warning>
|
||||
常见错误:`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: ["*"]`。
|
||||
</Warning>
|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab title="提及行为">
|
||||
群组回复默认要求提及。
|
||||
默认情况下,群组回复需要提及。
|
||||
|
||||
提及可以来自:
|
||||
|
||||
@ -233,9 +233,9 @@ curl "https://api.telegram.org/bot<bot_token>/getUpdates"
|
||||
- `/activation always`
|
||||
- `/activation mention`
|
||||
|
||||
这些仅更新会话状态。要持久化,请使用配置。
|
||||
这些仅更新会话状态。若要持久化,请使用配置。
|
||||
|
||||
持久化配置示例:
|
||||
持久配置示例:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -249,9 +249,9 @@ curl "https://api.telegram.org/bot<bot_token>/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<bot_token>/getUpdates"
|
||||
## 运行时行为
|
||||
|
||||
- Telegram 由 Gateway 网关进程持有。
|
||||
- 路由是确定性的:Telegram 入站回复会返回到 Telegram(模型不会选择渠道)。
|
||||
- 入站消息会标准化为共享渠道信封格式,并包含回复元数据和媒体占位符。
|
||||
- 路由是确定性的:Telegram 入站回复会回到 Telegram(模型不会选择渠道)。
|
||||
- 入站消息会标准化为共享渠道信封格式,包含回复元数据和媒体占位符。
|
||||
- 群组会话按群组 ID 隔离。论坛话题会追加 `:topic:<threadId>` 以保持话题隔离。
|
||||
- 私信消息可以携带 `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` 不适用)。
|
||||
|
||||
## 功能参考
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="实时流式预览(消息编辑)">
|
||||
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` 会在生成过程中将推理发送到实时预览
|
||||
- 最终答案发送时不包含推理文本
|
||||
|
||||
</Accordion>
|
||||
@ -306,9 +306,9 @@ curl "https://api.telegram.org/bot<bot_token>/getUpdates"
|
||||
<Accordion title="格式化和 HTML 回退">
|
||||
出站文本使用 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<bot_token>/getUpdates"
|
||||
|
||||
- `commands.native: "auto"` 为 Telegram 启用原生命令
|
||||
|
||||
添加自定义命令菜单项:
|
||||
添加自定义命令菜单条目:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -341,37 +341,37 @@ curl "https://api.telegram.org/bot<bot_token>/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 <requestId>` 用于显式批准
|
||||
- 当只有一个待处理请求时,使用 `/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)。
|
||||
|
||||
</Accordion>
|
||||
|
||||
@ -425,23 +425,23 @@ curl "https://api.telegram.org/bot<bot_token>/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: <value>`
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="供智能体和自动化使用的 Telegram 消息动作">
|
||||
<Accordion title="用于智能体和自动化的 Telegram 消息动作">
|
||||
Telegram 工具动作包括:
|
||||
|
||||
- `sendMessage`(`to`、`content`、可选的 `mediaUrl`、`replyToMessageId`、`messageThreadId`)
|
||||
@ -450,9 +450,9 @@ curl "https://api.telegram.org/bot<bot_token>/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<bot_token>/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)
|
||||
|
||||
</Accordion>
|
||||
|
||||
@ -470,7 +470,7 @@ curl "https://api.telegram.org/bot<bot_token>/getUpdates"
|
||||
Telegram 支持在生成输出中使用显式回复线程标签:
|
||||
|
||||
- `[[reply_to_current]]` 回复触发消息
|
||||
- `[[reply_to:<id>]]` 回复特定的 Telegram 消息 ID
|
||||
- `[[reply_to:<id>]]` 回复指定的 Telegram 消息 ID
|
||||
|
||||
`channels.telegram.replyToMode` 控制处理方式:
|
||||
|
||||
@ -478,7 +478,7 @@ curl "https://api.telegram.org/bot<bot_token>/getUpdates"
|
||||
- `first`
|
||||
- `all`
|
||||
|
||||
注意:`off` 会禁用隐式回复线程处理。显式 `[[reply_to_*]]` 标签仍会被遵循。
|
||||
注意:`off` 会禁用隐式回复线程。显式 `[[reply_to_*]]` 标签仍然会被遵循。
|
||||
|
||||
</Accordion>
|
||||
|
||||
@ -486,19 +486,19 @@ curl "https://api.telegram.org/bot<bot_token>/getUpdates"
|
||||
论坛超级群组:
|
||||
|
||||
- 话题会话键会追加 `:topic:<threadId>`
|
||||
- 回复和正在输入状态会定向到该话题线程
|
||||
- 回复和输入状态会定向到该话题线程
|
||||
- 话题配置路径:
|
||||
`channels.telegram.groups.<chatId>.topics.<threadId>`
|
||||
|
||||
常规话题(`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<bot_token>/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<bot_token>/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<bot_token>/getUpdates"
|
||||
}
|
||||
```
|
||||
|
||||
这当前仅适用于群组和超级群组中的论坛话题。
|
||||
这目前仅适用于群组和超级群组中的论坛话题。
|
||||
|
||||
**从聊天中生成线程绑定的 ACP**:
|
||||
**从聊天中发起线程绑定的 ACP 实例**:
|
||||
|
||||
- `/acp spawn <agent> --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<bot_token>/getUpdates"
|
||||
|
||||
私信线程行为:
|
||||
|
||||
- 带有 `message_thread_id` 的私聊会保持私信路由,但使用具备线程感知能力的会话键 / 回复目标。
|
||||
- 带有 `message_thread_id` 的私聊会保持私信路由,但使用具备线程感知能力的会话键/回复目标。
|
||||
|
||||
</Accordion>
|
||||
|
||||
@ -597,7 +597,7 @@ curl "https://api.telegram.org/bot<bot_token>/getUpdates"
|
||||
Telegram 区分语音消息和音频文件。
|
||||
|
||||
- 默认:音频文件行为
|
||||
- 在智能体回复中使用标签 `[[audio_as_voice]]` 可强制按语音消息发送
|
||||
- 在智能体回复中添加标签 `[[audio_as_voice]]` 可强制按语音消息发送
|
||||
|
||||
消息动作示例:
|
||||
|
||||
@ -627,14 +627,14 @@ curl "https://api.telegram.org/bot<bot_token>/getUpdates"
|
||||
}
|
||||
```
|
||||
|
||||
视频便笺不支持说明文字;如果提供了消息文本,会单独发送。
|
||||
视频便笺不支持标题;提供的消息文本会单独发送。
|
||||
|
||||
### 贴纸
|
||||
|
||||
入站贴纸处理:
|
||||
|
||||
- 静态 WEBP:下载并处理(占位符 `<media:sticker>`)
|
||||
- 动画 TGS:跳过
|
||||
- 动态 TGS:跳过
|
||||
- 视频 WEBM:跳过
|
||||
|
||||
贴纸上下文字段:
|
||||
@ -649,7 +649,7 @@ curl "https://api.telegram.org/bot<bot_token>/getUpdates"
|
||||
|
||||
- `~/.openclaw/telegram/sticker-cache.json`
|
||||
|
||||
贴纸会在可能的情况下只描述一次,并进行缓存,以减少重复的视觉调用。
|
||||
贴纸会在可能时只描述一次并缓存,以减少重复的视觉调用。
|
||||
|
||||
启用贴纸动作:
|
||||
|
||||
@ -689,8 +689,8 @@ curl "https://api.telegram.org/bot<bot_token>/getUpdates"
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="反应通知">
|
||||
Telegram 反应以 `message_reaction` 更新形式到达(与消息负载分开)。
|
||||
<Accordion title="Reaction 通知">
|
||||
Telegram reaction 会以 `message_reaction` 更新形式到达(与消息负载分离)。
|
||||
|
||||
启用后,OpenClaw 会将如下系统事件加入队列:
|
||||
|
||||
@ -698,42 +698,42 @@ curl "https://api.telegram.org/bot<bot_token>/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`。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="确认反应">
|
||||
`ackReaction` 会在 OpenClaw 处理入站消息时发送一个确认表情符号。
|
||||
<Accordion title="确认 reaction">
|
||||
`ackReaction` 会在 OpenClaw 处理入站消息时发送一个确认 emoji。
|
||||
|
||||
解析顺序:
|
||||
|
||||
- `channels.telegram.accounts.<accountId>.ackReaction`
|
||||
- `channels.telegram.ackReaction`
|
||||
- `messages.ackReaction`
|
||||
- 智能体身份 emoji 回退(`agents.list[].identity.emoji`,否则为 “👀”)
|
||||
- 智能体身份 emoji 回退(`agents.list[].identity.emoji`,否则为 "👀")
|
||||
|
||||
说明:
|
||||
|
||||
- Telegram 需要 unicode emoji(例如 “👀”)。
|
||||
- 使用 `""` 可为某个渠道或账户禁用该反应。
|
||||
- Telegram 需要 unicode emoji(例如 "👀")。
|
||||
- 使用 `""` 可为某个渠道或账户禁用该 reaction。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="来自 Telegram 事件和命令的配置写入">
|
||||
<Accordion title="由 Telegram 事件和命令触发的配置写入">
|
||||
默认启用渠道配置写入(`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<bot_token>/getUpdates"
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="长轮询与 Webhook">
|
||||
<Accordion title="群组中的模型选择器授权">
|
||||
群组模型选择器内联按钮需要与 `/models` 相同的授权。未授权参与者可以浏览和点击按钮,但 OpenClaw 会在更改会话模型前拒绝该回调。
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="长轮询与 webhook">
|
||||
默认:长轮询。
|
||||
|
||||
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 上循环。
|
||||
|
||||
</Accordion>
|
||||
|
||||
@ -774,17 +780,17 @@ curl "https://api.telegram.org/bot<bot_token>/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["<user_id>"].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 投票创建,同时保留普通发送功能
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Telegram 中的执行审批">
|
||||
Telegram 支持在审批人私信中进行执行审批,并且可以选择在原始聊天或话题中发布审批提示。
|
||||
<Accordion title="Telegram 中的 exec 审批">
|
||||
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)
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 错误回复控制
|
||||
|
||||
当智能体遇到发送或提供商错误时,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 \
|
||||
<AccordionGroup>
|
||||
<Accordion title="机器人不响应未提及的群组消息">
|
||||
|
||||
- 如果 `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`。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="机器人完全看不到群组消息">
|
||||
|
||||
- 当存在 `channels.telegram.groups` 时,必须列出该群组(或包含 `"*"`)
|
||||
- 验证机器人是否在群组中
|
||||
- 查看日志:使用 `openclaw logs --follow` 了解跳过原因
|
||||
- 当存在 `channels.telegram.groups` 时,必须列出该群组(或包含 `"*"`)
|
||||
- 验证机器人是否已加入群组
|
||||
- 查看日志:`openclaw logs --follow` 以了解跳过原因
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="命令部分可用或完全不可用">
|
||||
|
||||
- 授权你的发送者身份(配对和 / 或数值型 `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 可达性存在问题
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="轮询或网络不稳定">
|
||||
|
||||
- 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.<accountId>.network.dangerouslyAllowPrivateNetwork`。
|
||||
- 如果你的代理将 Telegram 媒体主机解析为 `198.18.x.x`,请先保持
|
||||
- 如果你的代理将 Telegram 媒体主机解析到 `198.18.x.x`,请先保持
|
||||
危险标志关闭。Telegram 媒体默认已经允许 RFC 2544
|
||||
基准测试范围。
|
||||
基准范围。
|
||||
|
||||
<Warning>
|
||||
`channels.telegram.network.dangerouslyAllowPrivateNetwork` 会削弱 Telegram
|
||||
媒体 SSRF 防护。仅在受信任、由操作员控制的代理
|
||||
环境中使用,例如 Clash、Mihomo 或 Surge 的 fake-IP 路由,当它们
|
||||
在 RFC 2544 基准测试范围之外生成私有或特殊用途响应时。
|
||||
对于普通公共互联网 Telegram 访问,请保持关闭。
|
||||
媒体 SSRF 防护。仅应在受信任、由操作方控制的代理
|
||||
环境中使用,例如 Clash、Mihomo 或 Surge 的 fake-IP 路由,
|
||||
且这些环境会在 RFC 2544 基准范围之外合成私有或特殊用途应答。
|
||||
对于正常的公网 Telegram 访问,请保持关闭。
|
||||
</Warning>
|
||||
|
||||
- 环境变量覆盖(临时):
|
||||
- `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.<id>.groupPolicy`:按群组覆盖 `groupPolicy`(`open | allowlist | disabled`)。
|
||||
- `channels.telegram.groups.<id>.requireMention`:提及门控默认值。
|
||||
- `channels.telegram.groups.<id>.skills`:skill 过滤器(省略 = 所有 Skills,空值 = 无)。
|
||||
- `channels.telegram.groups.<id>.allowFrom`:按群组覆盖发送者 allowlist。
|
||||
- `channels.telegram.groups.<id>.systemPrompt`:该群组的额外系统提示词。
|
||||
- `channels.telegram.groups.<id>.enabled`:当为 `false` 时禁用该群组。
|
||||
- `channels.telegram.groups.<id>.topics.<threadId>.*`:按话题覆盖(群组字段 + 仅话题字段 `agentId`)。
|
||||
- `channels.telegram.groups.<id>.enabled`:当值为 `false` 时禁用该群组。
|
||||
- `channels.telegram.groups.<id>.topics.<threadId>.*`:按话题覆盖(群组字段 + 仅话题支持的 `agentId`)。
|
||||
- `channels.telegram.groups.<id>.topics.<threadId>.agentId`:将此话题路由到特定智能体(覆盖群组级和绑定路由)。
|
||||
- `channels.telegram.groups.<id>.topics.<threadId>.groupPolicy`:按话题覆盖 `groupPolicy`(`open | allowlist | disabled`)。
|
||||
- `channels.telegram.groups.<id>.topics.<threadId>.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.<id>.topics.<threadId>.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.<account>.execApprovals`:按账户覆盖 Telegram 执行审批路由和审批人授权。
|
||||
- `channels.telegram.execApprovals.sessionFilter`:用于转发审批提示的可选会话键过滤器(子串或正则表达式)。
|
||||
- `channels.telegram.accounts.<account>.execApprovals`:按账户覆盖 Telegram exec 审批路由和审批人授权。
|
||||
- `channels.telegram.capabilities.inlineButtons`:`off | dm | group | all | allowlist`(默认:allowlist)。
|
||||
- `channels.telegram.accounts.<account>.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`
|
||||
|
||||
## 相关内容
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="配对" icon="link" href="/zh-CN/channels/pairing">
|
||||
对未知发件人的默认私信策略是配对。
|
||||
未知发送者的默认私信策略是配对。
|
||||
</Card>
|
||||
<Card title="渠道故障排除" icon="wrench" href="/zh-CN/channels/troubleshooting">
|
||||
跨渠道诊断与修复操作手册。
|
||||
</Card>
|
||||
<Card title="Gateway 网关配置" icon="settings" href="/zh-CN/gateway/configuration">
|
||||
完整的渠道配置模式与示例。
|
||||
完整的渠道配置模式和示例。
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## 快速设置
|
||||
## 快速开始
|
||||
|
||||
<Steps>
|
||||
<Step title="配置 WhatsApp 访问策略">
|
||||
@ -63,13 +63,13 @@ openclaw plugins install @openclaw/whatsapp
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="关联 WhatsApp(QR 码)">
|
||||
<Step title="关联 WhatsApp(QR)">
|
||||
|
||||
```bash
|
||||
openclaw channels login --channel whatsapp
|
||||
```
|
||||
|
||||
对于特定账号:
|
||||
针对特定账户:
|
||||
|
||||
```bash
|
||||
openclaw channels login --channel whatsapp --account work
|
||||
@ -98,16 +98,16 @@ openclaw pairing approve whatsapp <CODE>
|
||||
</Steps>
|
||||
|
||||
<Note>
|
||||
OpenClaw 建议在可能的情况下为 WhatsApp 使用单独的号码。(渠道元数据和设置流程已针对该设置进行优化,但也支持个人号码设置。)
|
||||
OpenClaw 建议在可能的情况下为 WhatsApp 使用单独的号码。(渠道元数据和设置流程已针对这种方式优化,但也支持个人号码设置。)
|
||||
</Note>
|
||||
|
||||
## 部署模式
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="专用号码(推荐)">
|
||||
这是最简洁的运维模式:
|
||||
这是最清晰的运维模式:
|
||||
|
||||
- 为 OpenClaw 使用独立的 WhatsApp 身份
|
||||
- 为 OpenClaw 使用单独的 WhatsApp 身份
|
||||
- 更清晰的私信允许列表和路由边界
|
||||
- 更低的自聊混淆概率
|
||||
|
||||
@ -133,12 +133,12 @@ OpenClaw 建议在可能的情况下为 WhatsApp 使用单独的号码。(渠
|
||||
- `allowFrom` 包含你的个人号码
|
||||
- `selfChatMode: true`
|
||||
|
||||
在运行时,自聊保护基于已关联的自身号码和 `allowFrom` 生效。
|
||||
在运行时,自聊保护会依据已关联的自身号码和 `allowFrom` 生效。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="仅限 WhatsApp Web 的渠道范围">
|
||||
在当前 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:<agentId>:whatsapp:group:<jid>`)。
|
||||
- WhatsApp Web 传输遵循 Gateway 网关主机上的标准代理环境变量(`HTTPS_PROXY`、`HTTP_PROXY`、`NO_PROXY` 及其小写变体)。优先使用主机级代理配置,而不是渠道专用的 WhatsApp 代理设置。
|
||||
- WhatsApp Web 传输会遵循 Gateway 网关主机上的标准代理环境变量(`HTTPS_PROXY`、`HTTP_PROXY`、`NO_PROXY` 及其小写变体)。优先使用主机级代理配置,而不是渠道专用的 WhatsApp 代理设置。
|
||||
|
||||
## 访问控制和激活
|
||||
|
||||
<Tabs>
|
||||
<Tab title="私信策略">
|
||||
`channels.whatsapp.dmPolicy` 控制直接聊天访问:
|
||||
`channels.whatsapp.dmPolicy` 控制私聊访问:
|
||||
|
||||
- `pairing`(默认)
|
||||
- `allowlist`
|
||||
- `open`(要求 `allowFrom` 包含 `"*"`)
|
||||
- `disabled`
|
||||
|
||||
`allowFrom` 接受 E.164 风格号码(内部会进行标准化)。
|
||||
`allowFrom` 接受 E.164 风格号码(内部会规范化)。
|
||||
|
||||
多账号覆盖:`channels.whatsapp.accounts.<id>.dmPolicy`(以及 `allowFrom`)优先于该账号的渠道级默认值。
|
||||
多账户覆盖:该账户上的 `channels.whatsapp.accounts.<id>.dmPolicy`(以及 `allowFrom`)优先于渠道级默认值。
|
||||
|
||||
运行时行为细节:
|
||||
|
||||
- 配对会持久化到渠道允许存储,并与已配置的 `allowFrom` 合并
|
||||
- 配对会持久化到渠道 allow-store,并与配置的 `allowFrom` 合并
|
||||
- 如果未配置允许列表,则默认允许已关联的自身号码
|
||||
- 出站的 `fromMe` 私信绝不会自动配对
|
||||
- 出站 `fromMe` 私信永远不会自动配对
|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab title="群组策略 + 允许列表">
|
||||
群组访问有两层:
|
||||
群组访问有两层控制:
|
||||
|
||||
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` 也是如此。
|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab title="提及 + /activation">
|
||||
群组回复默认需要被提及。
|
||||
默认情况下,群组回复需要被提及。
|
||||
|
||||
提及检测包括:
|
||||
|
||||
- 对机器人身份的显式 WhatsApp 提及
|
||||
- 已配置的提及正则模式(`agents.list[].groupChat.mentionPatterns`,回退为 `messages.groupChat.mentionPatterns`)
|
||||
- 隐式回复机器人检测(回复发件人与机器人身份匹配)
|
||||
- 隐式回复给机器人的检测(回复发送者匹配机器人身份)
|
||||
|
||||
安全说明:
|
||||
|
||||
- 引用 / 回复只能满足提及门控;它**不会**授予发件人授权
|
||||
- 在 `groupPolicy: "allowlist"` 下,即使非允许列表发件人回复了允许列表用户的消息,仍会被阻止
|
||||
- 引用/回复只会满足提及门控;它**不会**授予发送者授权
|
||||
- 当 `groupPolicy: "allowlist"` 时,即使非允许列表发送者回复了允许列表用户的消息,也仍会被阻止
|
||||
|
||||
会话级激活命令:
|
||||
|
||||
- `/activation mention`
|
||||
- `/activation always`
|
||||
|
||||
`activation` 会更新会话状态(不是全局配置)。它受 owner 门控保护。
|
||||
`activation` 会更新会话状态(而非全局配置)。它受所有者权限控制。
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## 个人号码和自聊行为
|
||||
|
||||
当已关联的自身号码也出现在 `allowFrom` 中时,WhatsApp 自聊保护会激活:
|
||||
当已关联的自身号码也存在于 `allowFrom` 中时,WhatsApp 自聊保护会激活:
|
||||
|
||||
- 跳过自聊回合的已读回执
|
||||
- 忽略本会触发给自己发送提醒的 mention-JID 自动触发行为
|
||||
- 跳过自聊轮次的已读回执
|
||||
- 忽略原本会提醒你自己的 mention-JID 自动触发行为
|
||||
- 如果未设置 `messages.responsePrefix`,自聊回复默认使用 `[{identity.name}]` 或 `[openclaw]`
|
||||
|
||||
## 消息标准化和上下文
|
||||
## 消息规范化和上下文
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="入站信封 + 回复上下文">
|
||||
传入的 WhatsApp 消息会被包装到共享入站信封中。
|
||||
传入的 WhatsApp 消息会包装到共享的入站信封中。
|
||||
|
||||
如果存在引用回复,上下文会按以下形式附加:
|
||||
如果存在引用回复,上下文会以下列形式追加:
|
||||
|
||||
```text
|
||||
[Replying to <sender> id:<stanzaId>]
|
||||
@ -244,12 +244,12 @@ OpenClaw 建议在可能的情况下为 WhatsApp 使用单独的号码。(渠
|
||||
[/Replying]
|
||||
```
|
||||
|
||||
回复元数据字段也会在可用时填充(`ReplyToId`、`ReplyToBody`、`ReplyToSender`、发件人 JID/E.164)。
|
||||
在可用时,也会填充回复元数据字段(`ReplyToId`、`ReplyToBody`、`ReplyToSender`、发送者 JID/E.164)。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="媒体占位符和位置/联系人提取">
|
||||
仅包含媒体的入站消息会使用如下占位符进行标准化:
|
||||
<Accordion title="媒体占位符以及位置/联系人提取">
|
||||
仅含媒体的入站消息会使用如下占位符进行规范化:
|
||||
|
||||
- `<media:image>`
|
||||
- `<media:video>`
|
||||
@ -257,14 +257,14 @@ OpenClaw 建议在可能的情况下为 WhatsApp 使用单独的号码。(渠
|
||||
- `<media:document>`
|
||||
- `<media:sticker>`
|
||||
|
||||
位置和联系人负载会在路由前标准化为文本上下文。
|
||||
位置和联系人负载会在路由前规范化为文本上下文。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="待处理群组历史注入">
|
||||
对于群组,未处理消息可以被缓冲,并在机器人最终被触发时注入为上下文。
|
||||
对于群组,当机器人最终被触发时,未处理消息可以被缓冲并作为上下文注入。
|
||||
|
||||
- 默认限制:`50`
|
||||
- 默认上限:`50`
|
||||
- 配置:`channels.whatsapp.historyLimit`
|
||||
- 回退:`messages.groupChat.historyLimit`
|
||||
- `0` 表示禁用
|
||||
@ -277,7 +277,7 @@ OpenClaw 建议在可能的情况下为 WhatsApp 使用单独的号码。(渠
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="已读回执">
|
||||
对已接受的入站 WhatsApp 消息,默认启用已读回执。
|
||||
默认会为已接受的入站 WhatsApp 消息发送已读回执。
|
||||
|
||||
全局禁用:
|
||||
|
||||
@ -291,7 +291,7 @@ OpenClaw 建议在可能的情况下为 WhatsApp 使用单独的号码。(渠
|
||||
}
|
||||
```
|
||||
|
||||
按账号覆盖:
|
||||
按账户覆盖:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -307,7 +307,7 @@ OpenClaw 建议在可能的情况下为 WhatsApp 使用单独的号码。(渠
|
||||
}
|
||||
```
|
||||
|
||||
即使全局启用,自聊回合也会跳过已读回执。
|
||||
即使全局启用,自聊轮次也会跳过已读回执。
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
@ -318,40 +318,62 @@ OpenClaw 建议在可能的情况下为 WhatsApp 使用单独的号码。(渠
|
||||
<Accordion title="文本分块">
|
||||
- 默认分块限制:`channels.whatsapp.textChunkLimit = 4000`
|
||||
- `channels.whatsapp.chunkMode = "length" | "newline"`
|
||||
- `newline` 模式优先按段落边界(空行)分块,然后再回退到按长度安全分块
|
||||
- `newline` 模式优先按段落边界(空行)分块,然后回退到按长度安全分块
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="出站媒体行为">
|
||||
- 支持图片、视频、音频(PTT 语音便签)和文档负载
|
||||
- `audio/ogg` 会被重写为 `audio/ogg; codecs=opus` 以兼容语音便签
|
||||
- 通过在视频发送中设置 `gifPlayback: true` 支持动画 GIF 播放
|
||||
- 发送多媒体回复负载时,说明文字会应用到第一个媒体项
|
||||
- 支持图片、视频、音频(PTT 语音便笺)和文档负载
|
||||
- `audio/ogg` 会被改写为 `audio/ogg; codecs=opus` 以兼容语音便笺
|
||||
- 视频发送时可通过 `gifPlayback: true` 支持动画 GIF 播放
|
||||
- 发送多媒体回复负载时,说明文字会应用到第一项媒体
|
||||
- 媒体来源可以是 HTTP(S)、`file://` 或本地路径
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="媒体大小限制和回退行为">
|
||||
- 入站媒体保存上限:`channels.whatsapp.mediaMaxMb`(默认 `50`)
|
||||
- 出站媒体发送上限:`channels.whatsapp.mediaMaxMb`(默认 `50`)
|
||||
- 按账号覆盖使用 `channels.whatsapp.accounts.<accountId>.mediaMaxMb`
|
||||
- 图片会自动优化(调整大小 / 质量扫描)以符合限制
|
||||
- 媒体发送失败时,首项回退会发送文本警告,而不是静默丢弃响应
|
||||
- 按账户覆盖使用 `channels.whatsapp.accounts.<accountId>.mediaMaxMb`
|
||||
- 图片会自动优化(尺寸调整/质量扫描)以适配限制
|
||||
- 媒体发送失败时,首项回退会发送文本警告,而不是静默丢弃回复
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 反应级别
|
||||
## 回复引用
|
||||
|
||||
`channels.whatsapp.reactionLevel` 控制智能体在 WhatsApp 上使用 emoji 反应的广泛程度:
|
||||
WhatsApp 支持原生回复引用,出站回复会可见地引用入站消息。使用 `channels.whatsapp.replyToMode` 控制。
|
||||
|
||||
| 级别 | 确认反应 | 智能体主动发起的反应 | 描述 |
|
||||
| ------------- | -------- | -------------------- | ---- |
|
||||
| `"off"` | 否 | 否 | 完全不使用反应 |
|
||||
| `"ack"` | 是 | 否 | 仅确认反应(回复前回执) |
|
||||
| `"minimal"` | 是 | 是(保守) | 确认 + 智能体反应,采用保守指导 |
|
||||
| `"extensive"` | 是 | 是(鼓励) | 确认 + 智能体反应,采用鼓励性指导 |
|
||||
| 值 | 行为 |
|
||||
| -------- | ---------------------------------------------------------------------------- |
|
||||
| `"auto"` | 当提供商支持时引用入站消息;否则跳过引用 |
|
||||
| `"on"` | 始终引用入站消息;如果引用被拒绝,则回退为普通发送 |
|
||||
| `"off"` | 从不引用;以普通消息发送 |
|
||||
|
||||
默认值为 `"auto"`。按账户覆盖使用 `channels.whatsapp.accounts.<id>.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.<id>.reactionLevel`。
|
||||
按账户覆盖使用 `channels.whatsapp.accounts.<id>.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`)
|
||||
|
||||
## 多账号和凭证
|
||||
## 多账户和凭证
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="账号选择和默认值">
|
||||
- 账号 id 来自 `channels.whatsapp.accounts`
|
||||
- 默认账号选择:如果存在则为 `default`,否则为第一个已配置的账号 id(排序后)
|
||||
- 账号 id 会在内部标准化后用于查找
|
||||
<Accordion title="账户选择和默认值">
|
||||
- 账户 ID 来自 `channels.whatsapp.accounts`
|
||||
- 默认账户选择:如果存在则为 `default`,否则为第一个已配置的账户 ID(按排序)
|
||||
- 账户 ID 会在内部规范化以供查找
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="凭证路径和旧版兼容性">
|
||||
- 当前认证路径:`~/.openclaw/credentials/whatsapp/<accountId>/creds.json`
|
||||
- 备份文件:`creds.json.bak`
|
||||
- `~/.openclaw/credentials/` 中的旧版默认认证仍会被识别 / 迁移,用于默认账号流程
|
||||
- 位于 `~/.openclaw/credentials/` 中的旧版默认认证仍会在默认账户流程中被识别/迁移
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="登出行为">
|
||||
`openclaw channels logout --channel whatsapp [--account <id>]` 会清除该账号的 WhatsApp 认证状态。
|
||||
<Accordion title="退出登录行为">
|
||||
`openclaw channels logout --channel whatsapp [--account <id>]` 会清除该账户的 WhatsApp 认证状态。
|
||||
|
||||
在旧版认证目录中,会保留 `oauth.json`,同时删除 Baileys 认证文件。
|
||||
在旧版认证目录中,会保留 `oauth.json`,同时移除 Baileys 认证文件。
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 工具、操作和配置写入
|
||||
|
||||
- 智能体工具支持包括 WhatsApp 反应操作(`react`)。
|
||||
- 智能体工具支持包括 WhatsApp reaction 操作(`react`)。
|
||||
- 操作门控:
|
||||
- `channels.whatsapp.actions.reactions`
|
||||
- `channels.whatsapp.actions.polls`
|
||||
- 渠道发起的配置写入默认启用(可通过 `channels.whatsapp.configWrites=false` 禁用)。
|
||||
- 默认启用渠道发起的配置写入(可通过 `channels.whatsapp.configWrites=false` 禁用)。
|
||||
|
||||
## 故障排除
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="未关联(需要 QR 码)">
|
||||
症状:渠道状态显示未关联。
|
||||
<Accordion title="未关联(需要 QR)">
|
||||
症状:渠道状态报告为未关联。
|
||||
|
||||
修复方法:
|
||||
修复:
|
||||
|
||||
```bash
|
||||
openclaw channels login --channel whatsapp
|
||||
@ -436,9 +458,9 @@ WhatsApp 支持通过 `channels.whatsapp.ackReaction` 在接收入站消息时
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="已关联但已断开 / 重连循环">
|
||||
症状:已关联账号反复断开连接或重复尝试重连。
|
||||
症状:已关联账户反复断开或重复尝试重连。
|
||||
|
||||
修复方法:
|
||||
修复:
|
||||
|
||||
```bash
|
||||
openclaw doctor
|
||||
@ -450,14 +472,14 @@ WhatsApp 支持通过 `channels.whatsapp.ackReaction` 在接收入站消息时
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="发送时没有活动监听器">
|
||||
当目标账号不存在活动中的 Gateway 网关监听器时,出站发送会快速失败。
|
||||
当目标账户没有活动的 Gateway 网关监听器时,出站发送会快速失败。
|
||||
|
||||
请确认 Gateway 网关正在运行,且该账号已关联。
|
||||
请确保 Gateway 网关正在运行,且该账户已关联。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="群组消息被意外忽略">
|
||||
按以下顺序检查:
|
||||
请按以下顺序检查:
|
||||
|
||||
- `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["<groupId>"].systemPrompt`):如果特定群组条目定义了 `systemPrompt`,则使用它。
|
||||
2. **群组通配系统提示词**(`groups["*"].systemPrompt`):当特定群组条目不存在或未定义 `systemPrompt` 时使用。
|
||||
1. **群组专属系统提示词**(`groups["<groupId>"].systemPrompt`):如果特定群组条目定义了 `systemPrompt`,则使用它。
|
||||
2. **群组通配系统提示词**(`groups["*"].systemPrompt`):当特定群组条目不存在,或未定义 `systemPrompt` 时使用。
|
||||
|
||||
直接消息的解析层级:
|
||||
私聊消息的解析层级:
|
||||
|
||||
首先确定生效的 `direct` 映射:如果账号定义了自己的 `direct`,它会完全替换根级 `direct` 映射(不进行深度合并)。随后提示词查找会在结果中的单个映射上运行:
|
||||
首先确定生效的 `direct` 映射:如果账户定义了自己的 `direct`,它会完全替换根级 `direct` 映射(不进行深度合并)。然后在得到的这个单一映射上执行提示词查找:
|
||||
|
||||
1. **直接消息专用系统提示词**(`direct["<peerId>"].systemPrompt`):如果特定对端条目定义了 `systemPrompt`,则使用它。
|
||||
2. **直接消息通配系统提示词**(`direct["*"].systemPrompt`):当特定对端条目不存在或未定义 `systemPrompt` 时使用。
|
||||
1. **私聊专属系统提示词**(`direct["<peerId>"].systemPrompt`):如果特定对端条目定义了 `systemPrompt`,则使用它。
|
||||
2. **私聊通配系统提示词**(`direct["*"].systemPrompt`):当特定对端条目不存在,或未定义 `systemPrompt` 时使用。
|
||||
|
||||
注意:`dms` 仍然是轻量级的按私信历史记录覆盖桶(`dms.<id>.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.<id>.enabled`、`accounts.<id>.authDir`、账号级覆盖
|
||||
- 多账户:`accounts.<id>.enabled`、`accounts.<id>.authDir`、账户级覆盖
|
||||
- 运维:`configWrites`、`debounceMs`、`web.enabled`、`web.heartbeatSeconds`、`web.reconnect.*`
|
||||
- 会话行为:`session.dmScope`、`historyLimit`、`dmHistoryLimit`、`dms.<id>.historyLimit`
|
||||
- 提示词:`groups.<id>.systemPrompt`、`groups["*"].systemPrompt`、`direct.<id>.systemPrompt`、`direct["*"].systemPrompt`
|
||||
|
||||
@ -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.<timestamp>`,以安全回收空间。
|
||||
- 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.<provider>`。
|
||||
- 重复运行 `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.<timestamp>`,以安全回收空间。
|
||||
- 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.<provider>`。
|
||||
- 重复运行 `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` 环境变量覆盖
|
||||
|
||||
|
||||
@ -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 <port>`:WebSocket 端口(默认值来自配置 / 环境变量;通常为 `18789`)。
|
||||
- `--port <port>`:WebSocket 端口(默认来自配置/环境变量;通常为 `18789`)。
|
||||
- `--bind <loopback|lan|tailnet|auto|custom>`:监听器绑定模式。
|
||||
- `--auth <token|password>`:认证模式覆盖。
|
||||
- `--token <token>`:token 覆盖(也会为该进程设置 `OPENCLAW_GATEWAY_TOKEN`)。
|
||||
- `--password <password>`:密码覆盖。警告:内联密码可能会暴露在本地进程列表中。
|
||||
- `--auth <token|password>`:身份验证模式覆盖。
|
||||
- `--token <token>`:token 覆盖(同时会为该进程设置 `OPENCLAW_GATEWAY_TOKEN`)。
|
||||
- `--password <password>`:password 覆盖。警告:内联密码可能会暴露在本地进程列表中。
|
||||
- `--password-file <path>`:从文件读取 gateway 密码。
|
||||
- `--tailscale <off|serve|funnel>`:通过 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 <auto|full|compact>`:websocket 日志样式(默认 `auto`)。
|
||||
- `--compact`:`--ws-log compact` 的别名。
|
||||
- `--raw-stream`:将原始模型流事件记录到 jsonl。
|
||||
- `--raw-stream-path <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 <url>`:Gateway 网关 WebSocket URL。
|
||||
- `--token <token>`:Gateway 网关 token。
|
||||
- `--password <password>`:Gateway 网关密码。
|
||||
- `--timeout <ms>`:超时 / 预算(因命令而异)。
|
||||
- `--expect-final`:等待 “final” 响应(智能体调用)。
|
||||
- `--password <password>`:Gateway 网关 password。
|
||||
- `--timeout <ms>`:超时/预算(因命令而异)。
|
||||
- `--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 <limit>`:要包含的最近事件最大数量(默认 `25`,最大 `1000`)。
|
||||
- `--type <type>`:按诊断事件类型筛选,例如 `payload.large` 或 `diagnostic.memory.pressure`。
|
||||
- `--since-seq <seq>`:只包含指定诊断序列号之后的事件。
|
||||
- `--bundle [path]`:读取持久化的稳定性 bundle,而不是调用正在运行的 Gateway 网关。使用 `--bundle latest`(或仅 `--bundle`)可读取状态目录下最新的 bundle,也可直接传入 bundle JSON 路径。
|
||||
- `--limit <limit>`:要包含的最近事件的最大数量(默认 `25`,最大 `1000`)。
|
||||
- `--type <type>`:按诊断事件类型过滤,例如 `payload.large` 或 `diagnostic.memory.pressure`。
|
||||
- `--since-seq <seq>`:仅包含指定诊断序列号之后的事件。
|
||||
- `--bundle [path]`:读取持久化的 stability bundle,而不是调用正在运行的 Gateway 网关。使用 `--bundle latest`(或仅 `--bundle`)读取状态目录下最新的 bundle,或直接传入 bundle JSON 路径。
|
||||
- `--export`:写出一个可共享的支持诊断 zip,而不是打印稳定性详情。
|
||||
- `--output <path>`:`--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 <path>`:输出 zip 路径。默认为状态目录下的支持导出文件。
|
||||
- `--output <path>`:输出 zip 路径。默认写入状态目录下的支持导出文件。
|
||||
- `--log-lines <count>`:要包含的已脱敏日志行最大数量(默认 `5000`)。
|
||||
- `--log-bytes <bytes>`:要检查的最大日志字节数(默认 `1000000`)。
|
||||
- `--log-bytes <bytes>`:要检查的日志最大字节数(默认 `1000000`)。
|
||||
- `--url <url>`:用于健康快照的 Gateway 网关 WebSocket URL。
|
||||
- `--token <token>`:用于健康快照的 Gateway 网关 token。
|
||||
- `--password <password>`:用于健康快照的 Gateway 网关密码。
|
||||
- `--timeout <ms>`:状态 / 健康快照超时(默认 `3000`)。
|
||||
- `--no-stability-bundle`:跳过持久化稳定性 bundle 查找。
|
||||
- `--json`:以 JSON 输出写入路径、大小和清单。
|
||||
- `--password <password>`:用于健康快照的 Gateway 网关 password。
|
||||
- `--timeout <ms>`:状态/健康快照超时(默认 `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 <url>`:添加显式探测目标。仍会探测已配置的远程目标和 localhost。
|
||||
- `--token <token>`:用于探测的 token 认证。
|
||||
- `--password <password>`:用于探测的密码认证。
|
||||
- `--url <url>`:添加一个显式探测目标。仍会探测已配置的远端 + localhost。
|
||||
- `--token <token>`:用于探测的 token 身份验证。
|
||||
- `--password <password>`:用于探测的 password 身份验证。
|
||||
- `--timeout <ms>`:探测超时(默认 `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:<port>` 访问。
|
||||
macOS 应用中的“通过 SSH 连接远端”模式使用本地端口转发,因此远端 gateway(可能仅绑定到 loopback)会以 `ws://127.0.0.1:<port>` 的形式变得可达。
|
||||
|
||||
CLI 等效命令:
|
||||
等效 CLI:
|
||||
|
||||
```bash
|
||||
openclaw gateway probe --ssh user@gateway-host
|
||||
@ -274,8 +273,8 @@ openclaw gateway probe --ssh user@gateway-host
|
||||
|
||||
- `--ssh <target>`:`user@host` 或 `user@host:port`(端口默认为 `22`)。
|
||||
- `--ssh-identity <path>`:身份文件。
|
||||
- `--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 <ms>`:每条命令的超时时间(browse / resolve);默认 `2000`。
|
||||
- `--json`:机器可读输出(也会禁用样式 / spinner)。
|
||||
- `--timeout <ms>`:每个命令的超时时间(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`
|
||||
在那里也仍然是可选的。
|
||||
在那里同样仍是可选项。
|
||||
|
||||
@ -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 <url>`:Gateway 网关 WebSocket URL
|
||||
- `--token <token>`:Gateway 网关令牌
|
||||
- `--token-file <path>`:从文件读取令牌
|
||||
- `--token <token>`:Gateway 网关 token
|
||||
- `--token-file <path>`:从文件读取 token
|
||||
- `--password <password>`:Gateway 网关密码
|
||||
- `--password-file <path>`:从文件读取密码
|
||||
- `--claude-channel-mode <auto|on|off>`: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` 仅包含桥接器连接期间观察到的审批请求
|
||||
|
||||
@ -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 <id>`:限定到单个智能体。不传时,这些命令会对每个已配置的智能体运行;如果未配置智能体列表,则回退到默认智能体。
|
||||
- `--agent <id>`:限定为单个智能体。不使用该选项时,这些命令会对每个已配置的智能体运行;如果未配置智能体列表,则会回退到默认智能体。
|
||||
- `--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 <text>`。
|
||||
- 查询输入:可传入位置参数 `[query]` 或 `--query <text>`。
|
||||
- 如果两者都提供,则以 `--query` 为准。
|
||||
- 如果两者都未提供,命令会报错退出。
|
||||
- `--agent <id>`:限定到单个智能体(默认:默认智能体)。
|
||||
- `--agent <id>`:限定为单个智能体(默认:默认智能体)。
|
||||
- `--max-results <n>`:限制返回结果数量。
|
||||
- `--min-score <n>`:过滤低分匹配结果。
|
||||
- `--json`:输出 JSON 结果。
|
||||
@ -86,64 +88,65 @@ openclaw memory promote [--apply] [--limit <n>] [--include-promoted]
|
||||
```
|
||||
|
||||
- `--apply` -- 将提升内容写入 `MEMORY.md`(默认:仅预览)。
|
||||
- `--limit <n>` -- 限制显示的候选数量。
|
||||
- `--include-promoted` -- 包含之前周期中已提升的条目。
|
||||
- `--limit <n>` -- 限制显示的候选项数量。
|
||||
- `--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 <id>`:限定到单个智能体(默认:默认智能体)。
|
||||
- `--limit <n>`:返回/应用的最大候选数。
|
||||
- `--min-score <n>`:最小加权提升分数。
|
||||
- `--min-recall-count <n>`:候选项所需的最小回忆次数。
|
||||
- `--min-unique-queries <n>`:候选项所需的最小不同查询数。
|
||||
- `--apply`:将选中的候选追加到 `MEMORY.md`,并标记为已提升。
|
||||
- `--include-promoted`:在输出中包含已提升的候选。
|
||||
- `--agent <id>`:限定为单个智能体(默认:默认智能体)。
|
||||
- `--limit <n>`:返回/应用的最大候选项数量。
|
||||
- `--min-score <n>`:最低加权提升分数。
|
||||
- `--min-recall-count <n>`:候选项所需的最小 recall 次数。
|
||||
- `--min-unique-queries <n>`:候选项所需的最少不同查询数。
|
||||
- `--apply`:将选中的候选项追加到 `MEMORY.md`,并将其标记为已提升。
|
||||
- `--include-promoted`:在输出中包含已提升的候选项。
|
||||
- `--json`:输出 JSON。
|
||||
|
||||
`memory promote-explain`:
|
||||
|
||||
解释特定提升候选及其分数明细。
|
||||
解释某个特定提升候选项及其分数明细。
|
||||
|
||||
```bash
|
||||
openclaw memory promote-explain <selector> [--agent <id>] [--include-promoted] [--json]
|
||||
```
|
||||
|
||||
- `<selector>`:用于查找的候选键、路径片段或片段内容。
|
||||
- `--agent <id>`:限定到单个智能体(默认:默认智能体)。
|
||||
- `--include-promoted`:包含已提升的候选。
|
||||
- `<selector>`:用于查找的候选项键、路径片段或片段内容。
|
||||
- `--agent <id>`:限定为单个智能体(默认:默认智能体)。
|
||||
- `--include-promoted`:包含已提升的候选项。
|
||||
- `--json`:输出 JSON。
|
||||
|
||||
`memory rem-harness`:
|
||||
|
||||
预览 REM 反思、候选事实和 deep 提升输出,不会写入任何内容。
|
||||
预览 REM 反思、候选真相和 deep 提升输出,不会写入任何内容。
|
||||
|
||||
```bash
|
||||
openclaw memory rem-harness [--agent <id>] [--include-promoted] [--json]
|
||||
```
|
||||
|
||||
- `--agent <id>`:限定到单个智能体(默认:默认智能体)。
|
||||
- `--include-promoted`:包含已提升的 deep 候选。
|
||||
- `--agent <id>`:限定为单个智能体(默认:默认智能体)。
|
||||
- `--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/<phase>/YYYY-MM-DD.md`。
|
||||
- 排名使用加权信号:回忆频率、检索相关性、查询多样性、时间新近性、跨日整合程度以及派生概念丰富度。
|
||||
- 提升在写入 `MEMORY.md` 前会重新读取实时每日笔记,因此已编辑或删除的短期片段不会基于过期的 recall-store 快照被提升。
|
||||
- 计划任务和手动 `memory promote` 运行共享相同的 deep 阶段默认值,除非你传入 CLI 阈值覆盖。
|
||||
- 自动运行会在已配置的记忆工作区之间展开执行。
|
||||
- 面向人类可读的阶段输出和日志条目会写入 `DREAMS.md`(或已有的 `dreams.md`),并可选写入每阶段报告到 `memory/dreaming/<phase>/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 <file-or-dir> --grounded` 会从历史每日笔记中预览有依据的 `What Happened`、`Reflections` 和 `Possible Lasting Updates`,不会写入任何内容。
|
||||
- `memory rem-backfill --path <file-or-dir>` 会将可回滚的有依据日记条目写入 `DREAMS.md` 以供 UI 审查。
|
||||
- `memory rem-backfill --path <file-or-dir> --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 <file-or-dir> --grounded` 会基于历史每日笔记预览 grounded 的 `What Happened`、`Reflections` 和 `Possible Lasting Updates`,不会写入任何内容。
|
||||
- `memory rem-backfill --path <file-or-dir>` 会将可回滚的 grounded 日志条目写入 `DREAMS.md`,供 UI 审查。
|
||||
- `memory rem-backfill --path <file-or-dir> --stage-short-term` 还会将 grounded 的持久候选项播种到实时短期提升存储中,以便正常的 deep 阶段进行排序。
|
||||
- `memory rem-backfill --rollback` 会移除之前写入的 grounded 日志条目,而 `memory rem-backfill --rollback-short-term` 会移除之前暂存的 grounded 短期候选项。
|
||||
- 完整阶段说明和配置参考请参阅 [Dreaming](/zh-CN/concepts/dreaming)。
|
||||
|
||||
@ -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 <model-or-alias>
|
||||
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 <id>` 可检查某个已配置智能体的模型/凭证状态。省略时,
|
||||
命令会在设置了 `OPENCLAW_AGENT_DIR`/`PI_CODING_AGENT_DIR` 时使用它们,否则使用
|
||||
在 `--json` 输出中,`auth.providers` 是感知环境变量/配置/store 的提供商
|
||||
概览,而 `auth.oauth` 仅是 auth-store 配置文件健康状态。
|
||||
添加 `--probe` 可针对每个已配置的提供商配置文件运行实时认证探测。
|
||||
探测是真实请求(可能会消耗令牌并触发速率限制)。
|
||||
使用 `--agent <id>` 可检查已配置智能体的模型/认证状态。省略时,
|
||||
该命令会在设置了 `OPENCLAW_AGENT_DIR`/`PI_CODING_AGENT_DIR` 时使用它们,否则使用
|
||||
已配置的默认智能体。
|
||||
探测行可能来自凭证配置文件、环境变量凭证,或 `models.json`。
|
||||
探测行可能来自认证配置文件、环境变量凭证或 `models.json`。
|
||||
|
||||
说明:
|
||||
注意:
|
||||
|
||||
- `models set <model-or-alias>` 接受 `provider/model` 或别名。
|
||||
- `models list --all` 会包含由内置提供商拥有的静态目录行,即使
|
||||
你尚未通过该提供商完成认证也是如此。在配置匹配凭证之前,这些行仍会显示
|
||||
为不可用。
|
||||
- `models list --provider <id>` 会按提供商 id 过滤,例如 `moonshot` 或
|
||||
`openai-codex`。它不接受交互式提供商选择器中的显示标签,例如
|
||||
`Moonshot AI`。
|
||||
- 模型引用会通过在**第一个** `/` 处分割来解析。如果模型 ID 本身包含 `/`(OpenRouter 风格),请包含提供商前缀(示例:`openrouter/moonshotai/kimi-k2`)。
|
||||
- `models list --all` 包含由内置提供商拥有的静态目录行,即使你尚未为该提供商配置认证
|
||||
也是如此。这些行仍会显示为不可用,直到配置了匹配的认证。
|
||||
- `models list --provider <id>` 按提供商 ID 过滤,例如 `moonshot` 或
|
||||
`openai-codex`。它不接受交互式提供商选择器中的显示标签,例如 `Moonshot AI`。
|
||||
- 模型引用会通过按**第一个** `/` 分割来解析。如果模型 ID 包含 `/`(OpenRouter 风格),请包含提供商前缀(示例:`openrouter/moonshotai/kimi-k2`)。
|
||||
- 如果你省略提供商,OpenClaw 会先将输入解析为别名,然后
|
||||
解析为已配置提供商中与该精确模型 id 唯一匹配的项,最后才
|
||||
以弃用警告的方式回退到已配置的默认提供商。
|
||||
如果该提供商不再公开已配置的默认模型,OpenClaw 会
|
||||
回退到第一个已配置的提供商/模型,而不是暴露一个
|
||||
过时的、已移除提供商默认值。
|
||||
- `models status` 可能会在凭证输出中显示 `marker(<value>)`,用于表示非机密占位符(例如 `OPENAI_API_KEY`、`secretref-managed`、`minimax-oauth`、`oauth:chutes`、`ollama-local`),而不是将它们作为机密进行掩码处理。
|
||||
解析为已配置提供商中与该确切模型 ID 唯一匹配的项,最后才会回退到已配置的默认提供商,并给出弃用警告。
|
||||
如果该提供商不再暴露已配置的默认模型,OpenClaw
|
||||
会回退到第一个已配置的提供商/模型,而不是显示一个
|
||||
已失效、已移除提供商的默认值。
|
||||
- `models status` 可能会在认证输出中显示 `marker(<value>)`,用于表示非敏感占位符(例如 `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 <name>`(探测单个提供商)
|
||||
- `--probe-profile <id>`(可重复或使用逗号分隔的配置文件 id)
|
||||
- `--probe-profile <id>`(可重复或使用逗号分隔的配置文件 ID)
|
||||
- `--probe-timeout <ms>`
|
||||
- `--probe-concurrency <n>`
|
||||
- `--probe-max-tokens <n>`
|
||||
- `--agent <id>`(已配置的智能体 id;覆盖 `OPENCLAW_AGENT_DIR`/`PI_CODING_AGENT_DIR`)
|
||||
- `--agent <id>`(已配置智能体 ID;会覆盖 `OPENCLAW_AGENT_DIR`/`PI_CODING_AGENT_DIR`)
|
||||
|
||||
探测状态分组:
|
||||
|
||||
@ -93,12 +91,12 @@ Codex、MiniMax、Xiaomi 和 z.ai。用量凭证信息会在可用时来自提
|
||||
|
||||
可预期的探测详情/原因代码情况:
|
||||
|
||||
- `excluded_by_auth_order`:存在已存储的配置文件,但显式的
|
||||
`auth.order.<provider>` 省略了它,因此探测会报告该排除状态,而不是
|
||||
- `excluded_by_auth_order`:存在已存储的配置文件,但显式
|
||||
`auth.order.<provider>` 省略了它,因此探测会报告该排除,而不是
|
||||
尝试使用它。
|
||||
- `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 <id>
|
||||
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 `<provider>:manual`,除非你传入
|
||||
- `paste-token` 接受在其他地方或自动化流程中生成的令牌字符串。
|
||||
- `paste-token` 需要 `--provider`,会提示输入令牌值,并将其写入默认配置文件 ID `<provider>:manual`,除非你传入
|
||||
`--profile-id`。
|
||||
- `paste-token --expires-in <duration>` 会根据相对时长(例如 `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 <duration>` 会根据相对时长(如 `365d` 或 `12h`)
|
||||
存储一个绝对令牌过期时间。
|
||||
- Anthropic 说明:Anthropic 工作人员告诉我们,OpenClaw 风格的 Claude CLI 用法再次被允许,因此 OpenClaw 将 Claude CLI 复用和 `claude -p` 用法视为此集成的受支持方式,除非 Anthropic 发布新的策略。
|
||||
- Anthropic 的 `setup-token` / `paste-token` 仍然可作为受支持的 OpenClaw 令牌路径使用,但 OpenClaw 现在会在可用时优先使用 Claude CLI 复用和 `claude -p`。
|
||||
|
||||
@ -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 <marketplace>
|
||||
openclaw plugins marketplace list <marketplace> --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 <package> # 先 ClawHub,后 npm
|
||||
openclaw plugins install <package> # 优先 ClawHub,然后 npm
|
||||
openclaw plugins install clawhub:<package> # 仅 ClawHub
|
||||
openclaw plugins install <package> --force # 覆盖现有安装
|
||||
openclaw plugins install <package> --pin # 固定版本
|
||||
openclaw plugins install <package> --dangerously-force-unsafe-install
|
||||
openclaw plugins install <path> # 本地路径
|
||||
openclaw plugins install <plugin>@<marketplace> # marketplace
|
||||
openclaw plugins install <plugin> --marketplace <name> # marketplace(显式)
|
||||
openclaw plugins install <plugin> --marketplace <name> # marketplace(显式指定)
|
||||
openclaw plugins install <plugin> --marketplace https://github.com/<owner>/<repo>
|
||||
```
|
||||
|
||||
裸包名会先在 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 <id-or-npm-spec>`。
|
||||
如果配置无效,`plugins install` 通常会以失败关闭的方式终止,并提示你先
|
||||
运行 `openclaw doctor --fix`。唯一有文档说明的例外是一个针对内置插件的窄范围恢复路径,
|
||||
适用于显式启用了
|
||||
`openclaw.install.allowInvalidConfigRecovery` 的插件。
|
||||
|
||||
`--pin` 仅适用于 npm 安装。不支持与 `--marketplace` 一起使用,因为 marketplace 安装会保存 marketplace 源元数据,而不是 npm spec。
|
||||
`--force` 会复用现有安装目标,并原地覆盖一个已安装的
|
||||
插件或 hook 包。当你有意从新的本地路径、归档、ClawHub 包或 npm 制品
|
||||
重新安装相同 id 时可使用它。
|
||||
对于已跟踪 npm 插件的常规升级,优先使用
|
||||
`openclaw plugins update <id-or-npm-spec>`。
|
||||
|
||||
`--dangerously-force-unsafe-install` 是一个紧急兜底选项,用于处理内置危险代码扫描器的误报。即使内置扫描器报告 `critical` 级发现,它也允许继续安装,但它**不会**绕过插件 `before_install` hook 的策略阻止,也**不会**绕过扫描失败。
|
||||
如果你对一个已安装的插件 id 运行 `plugins install`,OpenClaw
|
||||
会停止并提示你:正常升级请使用 `plugins update <id-or-npm-spec>`,
|
||||
如果你确实想从不同来源覆盖
|
||||
当前安装,则使用 `plugins install <package> --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 <marketplace-name>
|
||||
openclaw plugins install <plugin-name>@<marketplace-name>
|
||||
```
|
||||
|
||||
如果你想显式传递 marketplace 源,请使用 `--marketplace`:
|
||||
当你想显式传递 marketplace 来源时,请使用 `--marketplace`:
|
||||
|
||||
```bash
|
||||
openclaw plugins install <plugin-name> --marketplace <marketplace-name>
|
||||
@ -121,24 +165,33 @@ openclaw plugins install <plugin-name> --marketplace https://github.com/<owner>/
|
||||
openclaw plugins install <plugin-name> --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 <id> --dry-run
|
||||
openclaw plugins uninstall <id> --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>` 时仍会继续使用。
|
||||
当你传入插件 id 时,OpenClaw 会复用该
|
||||
插件已记录的安装 spec。这意味着先前保存的 dist-tag(如 `@beta`)以及固定的精确版本
|
||||
会继续用于之后的 `update <id>` 运行。
|
||||
|
||||
对于 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 <id>
|
||||
openclaw plugins inspect <id> --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 <id> --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 <source>
|
||||
openclaw plugins marketplace list <source> --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 和
|
||||
插件条目。
|
||||
|
||||
@ -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:<id>:...`)。
|
||||
- 本地模式会直接使用内嵌智能体运行时。大多数本地工具都可用,但仅限 Gateway 网关 的功能不可用。
|
||||
- 本地模式会在终端 UI 命令界面中添加 `/auth [provider]`。
|
||||
- `tui` 会在可能的情况下,为 token/password 认证解析已配置的 Gateway 网关认证 `SecretRef`(`env`/`file`/`exec` 提供商)。
|
||||
- 当从已配置的智能体工作区目录内启动时,TUI 会自动为会话键默认值选择该智能体(除非 `--session` 明确为 `agent:<id>:...`)。
|
||||
- 本地模式直接使用嵌入式智能体运行时。大多数本地工具都可用,但仅限 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)。
|
||||
|
||||
@ -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 标签
|
||||
- 会移除 `<relevant-memories>` / `<relevant_memories>` 脚手架区块
|
||||
- 会移除纯文本工具调用 XML 负载区块,例如 `<tool_call>...</tool_call>`、`<function_call>...</function_call>`、`<tool_calls>...</tool_calls>` 和 `<function_calls>...</function_calls>`,也包括那些被截断且未正常闭合的负载
|
||||
- 会移除降级后的工具调用/结果脚手架,例如 `[Tool Call: ...]`、`[Tool Result ...]` 和 `[Historical context ...]`
|
||||
- 会移除泄露的模型控制 token,例如 `<|assistant|>`、其他 ASCII `<|...|>` token,以及全角 `<|...|>` 变体
|
||||
- 会移除格式错误的 MiniMax 工具调用 XML,例如 `<invoke ...>` / `</minimax:tool_call>`
|
||||
- 在返回前,类似凭证/token 的文本会被脱敏
|
||||
- 长文本区块会被截断
|
||||
- 对于非常大的历史记录,可能会丢弃较早的行,或将超大的单行替换为 `[sessions_history omitted: message too large]`
|
||||
- 该工具会报告摘要标记,例如 `truncated`、`droppedMessages`、`contentTruncated`、`contentRedacted` 和 `bytes`
|
||||
- 会移除 `<relevant-memories>` / `<relevant_memories>` 脚手架块
|
||||
- 会移除纯文本工具调用 XML 负载块,例如 `<tool_call>...</tool_call>`、
|
||||
`<function_call>...</function_call>`、`<tool_calls>...</tool_calls>` 和
|
||||
`<function_calls>...</function_calls>`,包括那些从未正常闭合的截断负载
|
||||
- 会移除降级后的工具调用/结果脚手架,例如 `[Tool Call: ...]`、
|
||||
`[Tool Result ...]` 和 `[Historical context ...]`
|
||||
- 会移除泄露的模型控制 token,例如 `<|assistant|>`、其他 ASCII
|
||||
`<|...|>` token,以及全角变体 `<|...|>`
|
||||
- 会移除格式错误的 MiniMax 工具调用 XML,例如 `<invoke ...>` /
|
||||
`</minimax:tool_call>`
|
||||
- 返回前会对类似凭证/令牌的文本进行脱敏
|
||||
- 过长文本块会被截断
|
||||
- 超大的历史记录可能会丢弃较早的行,或将超大行替换为
|
||||
`[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) -- 会话工具配置项
|
||||
|
||||
@ -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 会话。
|
||||
|
||||
<Note>
|
||||
内置的 Anthropic `claude-cli` 后端现已再次获得支持。Anthropic 工作人员
|
||||
告诉我们,再次允许 OpenClaw 风格的 Claude CLI 用法,因此除非 Anthropic 发布
|
||||
新的策略,否则 OpenClaw 会将用于此集成的 `claude -p` 用法视为已获认可。
|
||||
内置的 Anthropic `claude-cli` 后端现已重新支持。Anthropic 工作人员
|
||||
告诉我们,OpenClaw 风格的 Claude CLI 用法再次被允许,因此除非 Anthropic 发布
|
||||
新政策,否则 OpenClaw 会将用于此集成的 `claude -p` 用法视为已获许可。
|
||||
</Note>
|
||||
|
||||
内置的 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.<id>` 中的用户配置仍会覆盖插件默认值。
|
||||
- 后端特定的配置清理由插件通过可选的
|
||||
`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 支持文件路径)。
|
||||
|
||||
@ -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` 读取可选的 <Tooltip tip="JSON5 支持注释和尾随逗号">**JSON5**</Tooltip> 配置。
|
||||
当前使用的配置路径必须是常规文件。对于由 OpenClaw 管理的写入操作,不支持使用符号链接的 `openclaw.json`
|
||||
布局;原子写入可能会替换该路径,而不是保留符号链接。如果你将配置保存在默认状态目录之外,请将 `OPENCLAW_CONFIG_PATH` 直接指向真实文件。
|
||||
OpenClaw 会从 `~/.openclaw/openclaw.json` 读取一个可选的 <Tooltip tip="JSON5 supports comments and trailing commas">**JSON5**</Tooltip> 配置。
|
||||
当前活动的配置路径必须是一个常规文件。对于 OpenClaw 自有写入操作,不支持
|
||||
符号链接形式的 `openclaw.json` 布局;原子写入可能会替换该路径,
|
||||
而不是保留符号链接。如果你将配置保存在默认状态目录之外,请将
|
||||
`OPENCLAW_CONFIG_PATH` 直接指向真实文件。
|
||||
|
||||
如果该文件不存在,OpenClaw 会使用安全的默认设置。添加配置的常见原因包括:
|
||||
如果该文件不存在,OpenClaw 会使用安全默认值。添加配置的常见原因包括:
|
||||
|
||||
- 连接渠道并控制谁可以向机器人发送消息
|
||||
- 连接渠道并控制谁可以向 bot 发送消息
|
||||
- 设置模型、工具、沙箱隔离或自动化(cron、hooks)
|
||||
- 调整会话、媒体、网络或 UI
|
||||
|
||||
有关所有可用字段,请参阅[完整参考](/zh-CN/gateway/configuration-reference)。
|
||||
有关所有可用字段,请参见[完整参考](/zh-CN/gateway/configuration-reference)。
|
||||
|
||||
<Tip>
|
||||
**刚开始接触配置?** 可先运行 `openclaw onboard` 进行交互式设置,或查看[配置示例](/zh-CN/gateway/configuration-examples)指南,获取可直接复制粘贴的完整配置。
|
||||
**刚开始接触配置?** 从 `openclaw onboard` 开始进行交互式设置,或查看[配置示例](/zh-CN/gateway/configuration-examples)指南,获取完整的可复制粘贴配置。
|
||||
</Tip>
|
||||
|
||||
## 最小配置
|
||||
@ -47,7 +49,7 @@ OpenClaw 会从 `~/.openclaw/openclaw.json` 读取可选的 <Tooltip tip="JSON5
|
||||
<Tabs>
|
||||
<Tab title="交互式向导">
|
||||
```bash
|
||||
openclaw onboard # 完整的新手引导流程
|
||||
openclaw onboard # 完整新手引导流程
|
||||
openclaw configure # 配置向导
|
||||
```
|
||||
</Tab>
|
||||
@ -58,68 +60,75 @@ OpenClaw 会从 `~/.openclaw/openclaw.json` 读取可选的 <Tooltip tip="JSON5
|
||||
openclaw config unset plugins.entries.brave.config.webSearch.apiKey
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="控制 UI">
|
||||
打开 [http://127.0.0.1:18789](http://127.0.0.1:18789),然后使用 **配置** 标签页。
|
||||
<Tab title="Control UI">
|
||||
打开 [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 节点及其直接子节点摘要。
|
||||
</Tab>
|
||||
<Tab title="直接编辑">
|
||||
直接编辑 `~/.openclaw/openclaw.json`。Gateway 网关 会监视该文件并自动应用更改(参见[热重载](#config-hot-reload))。
|
||||
直接编辑 `~/.openclaw/openclaw.json`。Gateway 网关会监视该文件并自动应用更改(参见[热重载](#config-hot-reload))。
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## 严格校验
|
||||
|
||||
<Warning>
|
||||
OpenClaw 仅接受与 schema 完全匹配的配置。未知键名、类型格式错误或无效值都会导致 Gateway 网关 **拒绝启动**。根级别唯一的例外是 `$schema`(字符串),这样编辑器才能附加 JSON Schema 元数据。
|
||||
OpenClaw 只接受完全符合 schema 的配置。未知键、类型格式错误或无效值都会导致 Gateway 网关**拒绝启动**。唯一的根级例外是 `$schema`(字符串),这样编辑器就可以附加 JSON Schema 元数据。
|
||||
</Warning>
|
||||
|
||||
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 自有配置写入。
|
||||
当候选副本包含已脱敏的密钥占位符,
|
||||
如 `***` 或缩短后的令牌值时,将跳过提升。
|
||||
|
||||
## 常见任务
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="设置一个渠道(WhatsApp、Telegram、Discord 等)">
|
||||
每个渠道在 `channels.<provider>` 下都有自己的配置部分。设置步骤请参阅对应的专用渠道页面:
|
||||
每个渠道在 `channels.<provider>` 下都有自己的配置部分。设置步骤请参见对应渠道页面:
|
||||
|
||||
- [WhatsApp](/zh-CN/channels/whatsapp) — `channels.whatsapp`
|
||||
- [Telegram](/zh-CN/channels/telegram) — `channels.telegram`
|
||||
@ -150,7 +159,7 @@ JSON。
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="选择并配置模型">
|
||||
设置主模型和可选的回退模型:
|
||||
设置主模型和可选回退模型:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -169,31 +178,31 @@ JSON。
|
||||
}
|
||||
```
|
||||
|
||||
- `agents.defaults.models` 定义模型目录,并作为 `/model` 的 allowlist。
|
||||
- 使用 `openclaw config set agents.defaults.models '<json>' --strict-json --merge` 可在不移除现有模型的情况下添加 allowlist 条目。会移除条目的普通替换操作会被拒绝,除非你传入 `--replace`。
|
||||
- `agents.defaults.models` 定义模型目录,并充当 `/model` 的允许列表。
|
||||
- 使用 `openclaw config set agents.defaults.models '<json>' --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)。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="控制谁可以向机器人发送消息">
|
||||
私信访问权限通过每个渠道的 `dmPolicy` 控制:
|
||||
<Accordion title="控制谁可以向 bot 发送消息">
|
||||
私信访问按渠道通过 `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)。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="设置群聊提及门控">
|
||||
群组消息默认 **要求提及**。可按智能体配置模式:
|
||||
群组消息默认**要求提及**。按智能体配置模式:
|
||||
|
||||
```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)
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="按智能体限制 Skills">
|
||||
使用 `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)。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="调整 Gateway 网关 渠道健康监控">
|
||||
控制 Gateway 网关 对看起来已停滞的渠道执行重启的积极程度:
|
||||
<Accordion title="调整 gateway 渠道健康监控">
|
||||
控制 gateway 重启看起来已陈旧渠道的激进程度:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -273,13 +282,13 @@ JSON。
|
||||
|
||||
- 设置 `gateway.channelHealthCheckMinutes: 0` 可全局禁用健康监控重启。
|
||||
- `channelStaleEventThresholdMinutes` 应大于或等于检查间隔。
|
||||
- 使用 `channels.<provider>.healthMonitor.enabled` 或 `channels.<provider>.accounts.<id>.healthMonitor.enabled` 可为单个渠道或账户禁用自动重启,而无需关闭全局监控。
|
||||
- 运行排障请参阅[健康检查](/zh-CN/gateway/health),所有字段请参阅[完整参考](/zh-CN/gateway/configuration-reference#gateway)。
|
||||
- 使用 `channels.<provider>.healthMonitor.enabled` 或 `channels.<provider>.accounts.<id>.healthMonitor.enabled` 可在不禁用全局监控的情况下,为单个渠道或账户禁用自动重启。
|
||||
- 运维调试请参见[健康检查](/zh-CN/gateway/health),所有字段请参见[完整参考](/zh-CN/gateway/configuration-reference#gateway)。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="配置会话和重置">
|
||||
会话控制对话的连续性和隔离性:
|
||||
会话控制对话连续性和隔离:
|
||||
|
||||
```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)。
|
||||
|
||||
</Accordion>
|
||||
|
||||
@ -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)。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="为官方 iOS 构建启用基于 relay 的推送">
|
||||
基于 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)。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="设置 heartbeat(周期性报到)">
|
||||
<Accordion title="设置心跳(定期签到)">
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
@ -401,8 +410,8 @@ JSON。
|
||||
|
||||
- `every`:时长字符串(`30m`、`2h`)。设置为 `0m` 可禁用。
|
||||
- `target`:`last` | `none` | `<channel-id>`(例如 `discord`、`matrix`、`telegram` 或 `whatsapp`)
|
||||
- `directPolicy`:用于私信式 heartbeat 目标的 `allow`(默认)或 `block`
|
||||
- 完整指南请参阅[Heartbeat](/zh-CN/gateway/heartbeat)。
|
||||
- `directPolicy`:私信风格心跳目标使用 `allow`(默认)或 `block`
|
||||
- 完整指南请参见[心跳](/zh-CN/gateway/heartbeat)。
|
||||
|
||||
</Accordion>
|
||||
|
||||
@ -423,12 +432,12 @@ JSON。
|
||||
|
||||
- `sessionRetention`:从 `sessions.json` 中清理已完成的隔离运行会话(默认 `24h`;设置为 `false` 可禁用)。
|
||||
- `runLog`:按大小和保留行数清理 `cron/runs/<jobId>.jsonl`。
|
||||
- 功能概览和 CLI 示例请参阅[Cron 作业](/zh-CN/automation/cron-jobs)。
|
||||
- 功能概览和 CLI 示例请参见[Cron 作业](/zh-CN/automation/cron-jobs)。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="设置 webhook(hooks)">
|
||||
在 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)。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="配置多智能体路由">
|
||||
运行多个相互隔离的智能体,每个都有独立的工作区和会话:
|
||||
运行多个彼此隔离的智能体,并使用独立工作区和会话:
|
||||
|
||||
```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)。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="将配置拆分为多个文件($include)">
|
||||
使用 `$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 提供清晰错误
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 配置热重载
|
||||
|
||||
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` | **是** |
|
||||
|
||||
<Note>
|
||||
`gateway.reload` 和 `gateway.remote` 是例外——更改它们**不会**触发重启。
|
||||
</Note>
|
||||
|
||||
### 重载规划
|
||||
|
||||
当你编辑一个通过 `$include` 引用的源文件时,OpenClaw 会根据源作者编写的布局
|
||||
来规划重载,而不是根据拍平后的内存视图。
|
||||
即使某个顶层部分单独存在于其自己的 include 文件中,
|
||||
例如 `plugins: { $include: "./plugins.json5" }`,
|
||||
这种方式也能让热重载决策(热应用还是重启)保持可预测。
|
||||
|
||||
如果某次重载无法被安全规划——例如,因为源布局
|
||||
将根级 include 与同级覆盖组合在一起——OpenClaw 会以关闭方式失败、记录
|
||||
原因,并保留当前正在运行的配置不变,这样你就可以修复源布局
|
||||
而不是静默回退到拍平后的重载。
|
||||
|
||||
## 配置 RPC(程序化更新)
|
||||
|
||||
<Note>
|
||||
控制平面写入 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`。
|
||||
</Note>
|
||||
|
||||
安全 / 默认流程:
|
||||
安全/默认流程:
|
||||
|
||||
- `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`。
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="config.apply(完整替换)">
|
||||
在一步中校验并写入完整配置,同时重启 Gateway 网关。
|
||||
校验并写入完整配置,同时一步重启 Gateway 网关。
|
||||
|
||||
<Warning>
|
||||
`config.apply` 会替换**整个配置**。局部更新请使用 `config.patch`,单个键请使用 `openclaw config set`。
|
||||
`config.apply` 会替换**整个配置**。部分更新请使用 `config.patch`,单个键请使用 `openclaw config set`。
|
||||
</Warning>
|
||||
|
||||
参数:
|
||||
|
||||
- `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": "<hash>",
|
||||
@ -615,8 +636,8 @@ Gateway 网关 会监视 `~/.openclaw/openclaw.json` 并自动应用更改——
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="config.patch(局部更新)">
|
||||
将局部更新合并到现有配置中(JSON merge patch 语义):
|
||||
<Accordion title="config.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 会从父进程读取环境变量,此外还会读取:
|
||||
}
|
||||
```
|
||||
|
||||
<Accordion title="Shell 环境变量导入(可选)">
|
||||
如果启用,并且预期键名尚未设置,OpenClaw 会运行你的登录 shell,并且仅导入缺失的键:
|
||||
<Accordion title="导入 shell 环境变量(可选)">
|
||||
如果启用,并且预期键名未设置,OpenClaw 会运行你的登录 shell,并且只导入缺失的键:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -669,11 +690,11 @@ OpenClaw 会从父进程读取环境变量,此外还会读取:
|
||||
}
|
||||
```
|
||||
|
||||
环境变量对应项:`OPENCLAW_LOAD_SHELL_ENV=1`
|
||||
环境变量等价项:`OPENCLAW_LOAD_SHELL_ENV=1`
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="配置值中的环境变量替换">
|
||||
你可以在任意配置字符串值中使用 `${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"`
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="SecretRef(env、file、exec)">
|
||||
对于支持 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) 中。
|
||||
</Accordion>
|
||||
|
||||
完整优先级和来源请参阅[环境](/zh-CN/help/environment)。
|
||||
完整优先级和来源请参见[环境](/zh-CN/help/environment)。
|
||||
|
||||
## 完整参考
|
||||
|
||||
如需完整的逐字段参考,请参阅 **[配置参考](/zh-CN/gateway/configuration-reference)**。
|
||||
如需逐字段的完整参考,请参见 **[配置参考](/zh-CN/gateway/configuration-reference)**。
|
||||
|
||||
---
|
||||
|
||||
|
||||
@ -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 <name>` 获取该沙箱的 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 <name>` 以获取该沙箱的 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` 命令
|
||||
|
||||
@ -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 <id|name|ip> --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 <id|name|ip> --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+`)
|
||||
|
||||
<Warning>
|
||||
**破坏性变更:** 从 `2026.3.31` 开始,在节点配对获批之前,节点命令将被禁用。仅靠设备配对已不足以暴露已声明的节点命令。
|
||||
**破坏性变更:** 从 `2026.3.31` 开始,在节点配对获批之前,节点命令将被禁用。仅有设备配对已不足以暴露声明的节点命令。
|
||||
</Warning>
|
||||
|
||||
当节点首次连接时,会自动请求配对。在配对请求获批之前,来自该节点的所有待处理节点命令都会被过滤,不会执行。一旦通过配对批准建立信任,该节点声明的命令就会在正常命令策略约束下变得可用。
|
||||
当节点首次连接时,会自动请求配对。在该配对请求获批之前,该节点的所有待处理节点命令都会被过滤,不会执行。一旦通过配对批准建立信任,节点声明的命令就会在正常命令策略约束下可用。
|
||||
|
||||
这意味着:
|
||||
|
||||
- 之前仅依赖设备配对来暴露命令的节点,现在必须完成节点配对。
|
||||
- 在配对批准前排队的命令会被丢弃,而不是延后执行。
|
||||
- 以前仅依赖设备配对来暴露命令的节点,现在必须完成节点配对。
|
||||
- 在配对获批前排队的命令会被丢弃,而不是延后执行。
|
||||
|
||||
## 节点事件信任边界(`2026.3.31+`)
|
||||
|
||||
<Warning>
|
||||
**破坏性变更:** 节点来源的运行现在会保持在收缩后的受信任 surface 内。
|
||||
**破坏性变更:** 节点发起的运行现在会保留在收缩后的受信任面内。
|
||||
</Warning>
|
||||
|
||||
节点来源的摘要和相关会话事件会被限制在预期的受信任 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 <id|name|ip> --name "Living Room iPad"
|
||||
|
||||
安全说明:
|
||||
|
||||
- Token 属于密钥;请将 `paired.json` 视为敏感文件。
|
||||
- Token 是密钥;请将 `paired.json` 视为敏感文件。
|
||||
- 轮换 token 需要重新批准(或删除该节点条目)。
|
||||
|
||||
## 传输协议行为
|
||||
|
||||
- 传输协议是**无状态**的;它不存储成员资格。
|
||||
- 如果 Gateway 网关离线或禁用了配对,节点将无法配对。
|
||||
- 如果 Gateway 网关处于远程模式,配对仍然会针对远程 Gateway 网关的存储进行。
|
||||
- 如果 Gateway 网关离线或配对被禁用,节点将无法配对。
|
||||
- 如果 Gateway 网关处于远程模式,配对仍会针对远程 Gateway 网关的存储进行。
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -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 访问时更简单的替代方案
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -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 工具。
|
||||
|
||||
<Info>
|
||||
套件**不同于**原生 OpenClaw 插件。原生插件在进程内运行,并且可以注册任何能力。套件是内容包,只支持选择性的功能映射,并且信任边界更窄。
|
||||
套装**不**等同于原生 OpenClaw plugin。原生 plugin 在进程内运行,
|
||||
可以注册任意能力。套装是内容包,只支持选择性的功能映射,并且
|
||||
具有更窄的信任边界。
|
||||
</Info>
|
||||
|
||||
## 为什么需要套件
|
||||
## 为什么会有套装
|
||||
|
||||
许多实用插件以 Codex、Claude 或 Cursor 格式发布。OpenClaw 不要求作者将它们重写为原生 OpenClaw 插件,而是会检测这些格式,并将其中受支持的内容映射到原生功能集中。这意味着你可以安装一个 Claude 命令包或一个 Codex Skills 套件,并立即使用它。
|
||||
许多有用的 plugin 是以 Codex、Claude 或 Cursor 格式发布的。OpenClaw
|
||||
不会要求作者将它们重写为原生 OpenClaw plugin,而是会检测这些格式,
|
||||
并将其中受支持的内容映射到原生功能集中。这意味着你可以安装 Claude
|
||||
命令包或 Codex skill 套装,并立即使用它。
|
||||
|
||||
## 安装一个套件
|
||||
## 安装套装
|
||||
|
||||
<Steps>
|
||||
<Step title="从目录、归档文件或市场安装">
|
||||
<Step title="从目录、归档文件或 marketplace 安装">
|
||||
```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 <marketplace-name>
|
||||
openclaw plugins install <plugin-name>@<marketplace-name>
|
||||
```
|
||||
@ -50,7 +57,7 @@ OpenClaw 可以从三个外部生态系统安装插件:**Codex**、**Claude**
|
||||
openclaw plugins inspect <id>
|
||||
```
|
||||
|
||||
套件会显示为 `Format: bundle`,其子类型为 `codex`、`claude` 或 `cursor`。
|
||||
套装会显示为 `Format: bundle`,其子类型为 `codex`、`claude` 或 `cursor`。
|
||||
|
||||
</Step>
|
||||
|
||||
@ -59,50 +66,55 @@ OpenClaw 可以从三个外部生态系统安装插件:**Codex**、**Claude**
|
||||
openclaw gateway restart
|
||||
```
|
||||
|
||||
映射后的功能(Skills、hooks、MCP 工具、LSP 默认值)会在下一个会话中可用。
|
||||
已映射的功能(skills、hooks、MCP 工具、LSP 默认值)会在下一个会话中可用。
|
||||
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## 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 <id>` 中
|
||||
- 已启用的 Claude 套装可以提供 LSP 服务器配置
|
||||
- OpenClaw 会加载 `.lsp.json` 以及清单中声明的所有 `lspServers` 路径
|
||||
- 套装 LSP 配置会合并到生效的内置 Pi LSP 默认值中
|
||||
- 当前只有受支持的基于 stdio 的 LSP 服务器可以运行;不受支持的
|
||||
传输协议仍会显示在 `openclaw plugins inspect <id>` 中
|
||||
|
||||
### 已检测到但不会执行
|
||||
|
||||
这些内容会被识别并显示在诊断信息中,但 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 行内/应用元数据(能力报告之外的部分)
|
||||
|
||||
## 套件格式
|
||||
## 套装格式
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Codex 套件">
|
||||
<Accordion title="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 最契合。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Claude 套件">
|
||||
<Accordion title="Claude 套装">
|
||||
两种检测模式:
|
||||
|
||||
- **基于清单:** `.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` 会被检测到,但不会执行
|
||||
- 清单中的自定义组件路径是增量添加的(它们会扩展默认值,而不是替换默认值)
|
||||
- 清单中的自定义组件路径是增量式的(扩展默认值,而不是替换默认值)
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Cursor 套件">
|
||||
<Accordion title="Cursor 套装">
|
||||
标记:`.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` 仅检测,不执行
|
||||
|
||||
</Accordion>
|
||||
@ -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 服务器可能会作为子进程启动
|
||||
|
||||
这让套件在默认情况下更安全,但对于第三方套件,你仍应将其视为对其所暴露功能具有可信访问权限的内容。
|
||||
这使套装在默认情况下更安全,但对于它们所暴露功能所涉及的第三方
|
||||
套装内容,你仍应将其视为受信任内容。
|
||||
|
||||
## 故障排除
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="套件已检测到,但能力没有运行">
|
||||
运行 `openclaw plugins inspect <id>`。如果某项能力被列出,但标记为未接线启用,那是产品限制——并不是安装损坏。
|
||||
<Accordion title="已检测到套装,但能力没有运行">
|
||||
运行 `openclaw plugins inspect <id>`。如果某项能力已列出,但标记为
|
||||
未接线,那是产品限制——并非安装损坏。
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Claude 命令文件没有显示">
|
||||
请确认套件已启用,并且 Markdown 文件位于已检测到的 `commands/` 或 `skills/` 根目录中。
|
||||
<Accordion title="Claude 命令文件没有出现">
|
||||
请确认套装已启用,并且 Markdown 文件位于已检测到的
|
||||
`commands/` 或 `skills/` 根目录中。
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Claude 设置未生效">
|
||||
仅支持来自 `settings.json` 的内置 Pi 设置。OpenClaw 不会将套件设置视为原始配置补丁。
|
||||
<Accordion title="Claude 设置没有生效">
|
||||
当前仅支持来自 `settings.json` 的内置 Pi 设置。OpenClaw 不会
|
||||
将套装设置视为原始配置补丁。
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Claude hooks 没有执行">
|
||||
`hooks/hooks.json` 仅用于检测。如果你需要可运行的 hooks,请使用 OpenClaw hook 包布局,或者提供一个原生插件。
|
||||
`hooks/hooks.json` 仅检测,不执行。如果你需要可运行的 hooks,请使用
|
||||
OpenClaw hook-pack 布局,或提供原生 plugin。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 相关内容
|
||||
|
||||
- [安装和配置插件](/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
|
||||
|
||||
@ -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/<model>` 也会自动启用内置的 `codex` 插件。显式的插件条目在共享配置中仍然有用,因为它能明确表明部署意图。
|
||||
将 `agents.defaults.model` 或某个智能体模型设置为 `codex/<model>` 也会
|
||||
自动启用内置的 `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 <thread-id>` 将当前 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)
|
||||
|
||||
@ -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<package.json version>`;真实发布仍然需要真实的发布标签
|
||||
- 两个工作流都会将真实发布和提升路径保留在 GitHub 托管的 runner 上,而不修改状态的验证路径则可以使用更大的 Blacksmith Linux runner
|
||||
- 这种拆分是有意设计的:让真实 npm 发布路径保持简短、
|
||||
可预测,并聚焦于产物,而较慢的实时检查则留在它们
|
||||
自己的通道中,这样它们就不会拖慢或阻塞发布
|
||||
- 发布检查必须从 `main` 工作流引用或
|
||||
`release/YYYY.M.D` 工作流引用分发,以便工作流逻辑和 secret 始终
|
||||
受控
|
||||
- 该工作流接受现有发布标签,或当前完整的
|
||||
40 字符工作流分支提交 SHA
|
||||
- 在提交 SHA 模式下,它只接受当前工作流分支 HEAD;如果要验证更早的发布提交,请使用
|
||||
发布标签
|
||||
- `OpenClaw NPM Release` 的仅验证预检也接受当前
|
||||
完整的 40 字符工作流分支提交 SHA,而不要求先推送标签
|
||||
- 该 SHA 路径仅用于验证,不能被提升为真实发布
|
||||
- 在 SHA 模式下,工作流仅为包元数据检查合成
|
||||
`v<package.json version>`;真实发布仍然需要真实的发布标签
|
||||
- 两个工作流都将真实发布和提升路径保留在 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 提升路径都被
|
||||
文档化,并对操作人员可见。
|
||||
|
||||
## 公开参考
|
||||
|
||||
|
||||
@ -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 <provider/model>`
|
||||
- `/acp permissions <profile>`
|
||||
- `/acp timeout <seconds>`
|
||||
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:<agentId>:acp:<uuid>` | `agent:<agentId>:subagent:<uuid>` |
|
||||
| 主要命令 | `/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 <harness> --bind here`。
|
||||
当你希望当前会话变成一个持久 ACP 工作区,且不创建子线程时,请使用 `/acp spawn <harness> --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="<channelOrThreadId>"`
|
||||
- Telegram 论坛话题:`match.channel="telegram"` + `match.peer.id="<chatId>:topic:<topicId>"`
|
||||
- BlueBubbles 私信/群聊:`match.channel="bluebubbles"` + `match.peer.id="<handle|chat_id:*|chat_guid:*|chat_identifier:*>"`
|
||||
- BlueBubbles 私信/群聊:`match.channel="bluebubbles"` + `match.peer.id="<handle|chat_id:*|chat_guid:*|chat_identifier:*>"`
|
||||
对于稳定的群组绑定,优先使用 `chat_id:*` 或 `chat_identifier:*`。
|
||||
- iMessage 私信/群聊:`match.channel="imessage"` + `match.peer.id="<handle|chat_id:*|chat_guid:*|chat_identifier:*>"`
|
||||
- iMessage 私信/群聊:`match.channel="imessage"` + `match.peer.id="<handle|chat_id:*|chat_guid:*|chat_identifier:*>"`
|
||||
对于稳定的群组绑定,优先使用 `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 日志(`<sessionId>.acp-stream.jsonl`),你可以对其执行 tail 以查看完整的转发历史。
|
||||
- `cwd`(可选):请求的运行时工作目录(由后端/运行时策略验证)。如果省略,ACP 启动会在已配置时继承目标智能体工作区;继承路径缺失时会回退到后端默认值,而真实访问错误会直接返回。
|
||||
- `label`(可选):面向操作人员的标签,用于会话/横幅文本。
|
||||
- `resumeSessionId`(可选):恢复现有 ACP 会话,而不是创建新会话。智能体会通过 `session/load` 重放其会话历史。要求 `runtime: "acp"`。
|
||||
- `streamTo`(可选):`"parent"` 会将初始 ACP 运行的进度摘要作为系统事件流式回传给请求者会话。
|
||||
- 可用时,接受的响应还会包含 `streamLogPath`,指向一个按会话划分的 JSONL 日志(`<sessionId>.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=<yes/no>; childSessionKey=<value or none>; error=<exa
|
||||
|
||||
说明:
|
||||
|
||||
- 除非你是在有意测试绑定到线程的持久化 ACP 会话,否则请将此冒烟测试保持在 `mode: "run"`。
|
||||
- 对于基础检查,不要要求 `streamTo: "parent"`。该路径依赖于请求方/会话能力,是单独的集成检查项。
|
||||
- 将绑定到线程的 `mode: "session"` 测试视为第二阶段、更丰富的集成测试,应从真实的 Discord 线程或 Telegram 话题中进行。
|
||||
- 除非你是在有意测试线程绑定的持久 ACP 会话,否则请将此 smoke 测试保持在 `mode: "run"`。
|
||||
- 基础检查不应要求 `streamTo: "parent"`。该路径依赖请求者/会话能力,属于单独的集成检查。
|
||||
- 应将线程绑定的 `mode: "session"` 测试视为第二阶段、更丰富的集成验证,并从真实的 Discord 线程或 Telegram 话题中执行。
|
||||
|
||||
## 沙箱兼容性
|
||||
|
||||
ACP 会话当前运行在主机运行时上,而不是在 OpenClaw 沙箱内运行。
|
||||
ACP 会话当前运行在宿主运行时上,而不是 OpenClaw 沙箱内。
|
||||
|
||||
当前限制:
|
||||
|
||||
- 如果请求方会话是沙箱隔离的,则 ACP 启动会被阻止,包括 `sessions_spawn({ runtime: "acp" })` 和 `/acp spawn`。
|
||||
- 如果请求者会话处于沙箱中,则无论是 `sessions_spawn({ runtime: "acp" })` 还是 `/acp spawn`,ACP 启动都会被阻止。
|
||||
- 错误:`Sandboxed sessions cannot spawn ACP sessions because runtime="acp" runs on the host. Use runtime="subagent" from sandboxed sessions.`
|
||||
- 带有 `runtime: "acp"` 的 `sessions_spawn` 不支持 `sandbox: "require"`。
|
||||
- `runtime: "acp"` 的 `sessions_spawn` 不支持 `sandbox: "require"`。
|
||||
- 错误:`sessions_spawn sandbox="require" is unsupported for runtime="acp" because ACP sessions run outside the sandbox. Use runtime="subagent" or sandbox="inherit".`
|
||||
|
||||
当你需要由沙箱强制执行的运行时,请使用 `runtime: "subagent"`。
|
||||
当你需要由沙箱强制执行时,请使用 `runtime: "subagent"`。
|
||||
|
||||
### 从 `/acp` 命令启动
|
||||
### 从 `/acp` 命令
|
||||
|
||||
需要时,使用 `/acp spawn` 从聊天中进行显式的操作员控制。
|
||||
当需要从聊天中进行显式操作控制时,请使用 `/acp spawn`。
|
||||
|
||||
```text
|
||||
/acp spawn codex --mode persistent --thread auto
|
||||
@ -512,48 +508,48 @@ ACP 会话当前运行在主机运行时上,而不是在 OpenClaw 沙箱内运
|
||||
|
||||
1. 显式目标参数(或 `/acp steer` 的 `--session`)
|
||||
- 先尝试 key
|
||||
- 然后尝试 UUID 形状的 session id
|
||||
- 再尝试 UUID 形态的 session id
|
||||
- 再尝试 label
|
||||
2. 当前线程绑定(如果当前对话/线程已绑定到某个 ACP 会话)
|
||||
3. 当前请求方会话回退
|
||||
2. 当前线程绑定(如果该会话/线程已绑定到某个 ACP 会话)
|
||||
3. 当前请求者会话回退
|
||||
|
||||
当前对话绑定和线程绑定都会参与第 2 步。
|
||||
当前会话绑定和线程绑定都会参与第 2 步。
|
||||
|
||||
如果没有解析到目标,OpenClaw 会返回明确错误(`Unable to resolve session target: ...`)。
|
||||
如果无法解析出目标,OpenClaw 会返回清晰的错误(`Unable to resolve session target: ...`)。
|
||||
|
||||
## 启动绑定模式
|
||||
|
||||
`/acp spawn` 支持 `--bind here|off`。
|
||||
|
||||
| 模式 | 行为 |
|
||||
| ------ | ---------------------------------------------------------------------- |
|
||||
| `here` | 在原位置绑定当前活动对话;如果当前没有活动对话则失败。 |
|
||||
| `off` | 不创建当前对话绑定。 |
|
||||
| ---- | ---- |
|
||||
| `here` | 就地绑定当前活动会话;如果当前没有活动会话则失败。 |
|
||||
| `off` | 不创建当前会话绑定。 |
|
||||
|
||||
说明:
|
||||
|
||||
- `--bind here` 是“让这个渠道或聊天由 Codex 提供支持”的最简单操作路径。
|
||||
- `--bind here` 是“让这个渠道或聊天由 Codex 支持”的最简单操作路径。
|
||||
- `--bind here` 不会创建子线程。
|
||||
- `--bind here` 仅在暴露当前对话绑定能力的渠道上可用。
|
||||
- `--bind` 和 `--thread` 不能在同一次 `/acp spawn` 调用中组合使用。
|
||||
- `--bind here` 仅在暴露当前会话绑定支持的渠道上可用。
|
||||
- `--bind` 与 `--thread` 不能在同一次 `/acp spawn` 调用中组合使用。
|
||||
|
||||
## 启动线程模式
|
||||
|
||||
`/acp spawn` 支持 `--thread auto|here|off`。
|
||||
|
||||
| 模式 | 行为 |
|
||||
| ------ | --------------------------------------------------------------------------------------------------- |
|
||||
| `auto` | 在活动线程中:绑定该线程。在线程之外:在支持时创建并绑定一个子线程。 |
|
||||
| `here` | 要求当前存在活动线程;如果不在线程中则失败。 |
|
||||
| `off` | 不进行绑定。会话以未绑定状态启动。 |
|
||||
| ---- | ---- |
|
||||
| `auto` | 如果当前在线程中:绑定该线程。若不在线程中:在受支持时创建并绑定一个子线程。 |
|
||||
| `here` | 要求当前处于活动线程中;否则失败。 |
|
||||
| `off` | 不进行绑定。会话以未绑定状态启动。 |
|
||||
|
||||
说明:
|
||||
|
||||
- 在不支持线程绑定的界面上,默认行为实际上等同于 `off`。
|
||||
- 绑定到线程的启动需要渠道策略支持:
|
||||
- 线程绑定启动需要渠道策略支持:
|
||||
- Discord:`channels.discord.threadBindings.spawnAcpSessions=true`
|
||||
- Telegram:`channels.telegram.threadBindings.spawnAcpSessions=true`
|
||||
- 当你想固定当前对话而不创建子线程时,请使用 `--bind here`。
|
||||
- 当你希望固定当前会话而不创建子线程时,请使用 `--bind here`。
|
||||
|
||||
## ACP 控制
|
||||
|
||||
@ -575,45 +571,45 @@ ACP 会话当前运行在主机运行时上,而不是在 OpenClaw 沙箱内运
|
||||
- `/acp doctor`
|
||||
- `/acp install`
|
||||
|
||||
`/acp status` 会显示生效中的运行时选项,并且在可用时,同时显示运行时级别和后端级别的会话标识符。
|
||||
`/acp status` 会显示生效的运行时选项,并在可用时显示运行时级和后端级的会话标识符。
|
||||
|
||||
某些控制依赖于后端能力。如果某个后端不支持某项控制,OpenClaw 会返回明确的“不支持该控制”错误。
|
||||
某些控制依赖后端能力。如果某个后端不支持某项控制,OpenClaw 会返回清晰的“不支持该控制”错误。
|
||||
|
||||
## ACP 命令手册
|
||||
|
||||
| 命令 | 作用 | 示例 |
|
||||
| -------------------- | --------------------------------------------------------- | ------------------------------------------------------------- |
|
||||
| ---- | ---- | ---- |
|
||||
| `/acp spawn` | 创建 ACP 会话;可选当前绑定或线程绑定。 | `/acp spawn codex --bind here --cwd /repo` |
|
||||
| `/acp cancel` | 取消目标会话正在进行中的轮次。 | `/acp cancel agent:codex:acp:<uuid>` |
|
||||
| `/acp steer` | 向正在运行的会话发送引导指令。 | `/acp steer --session support inbox prioritize failing tests` |
|
||||
| `/acp cancel` | 取消目标会话中正在进行的轮次。 | `/acp cancel agent:codex:acp:<uuid>` |
|
||||
| `/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 <id>` 映射到运行时配置键 `model`。
|
||||
- `/acp permissions <profile>` 映射到运行时配置键 `approval_policy`。
|
||||
- `/acp timeout <seconds>` 映射到运行时配置键 `timeout`。
|
||||
- `/acp cwd <path>` 直接更新运行时 cwd 覆盖值。
|
||||
- `/acp cwd <path>` 会直接更新运行时 `cwd` 覆盖。
|
||||
- `/acp set <key> <value>` 是通用路径。
|
||||
- 特殊情况:`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 <command>` 指向任意适配器,但这个原始逃生口是 acpx CLI 功能(不是标准的 OpenClaw `agentId` 路径)。
|
||||
直接使用 acpx CLI 也可以通过 `--agent <command>` 定位任意适配器,但这类原始逃生口是 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@<pinned>` 并重新校验。
|
||||
`npm install --omit=dev --no-save acpx@<pinned>`,然后重新验证。
|
||||
|
||||
你可以在插件配置中覆盖命令/版本:
|
||||
|
||||
@ -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 "<id>" 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 <channel>.` | 适配器缺少当前对话 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 "<id>" 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 <channel>.` | 适配器缺少当前会话 ACP 绑定能力。 | 在受支持时使用 `/acp spawn ... --thread ...`,配置顶层 `bindings[]`,或切换到受支持的渠道。 |
|
||||
| `--thread here requires running /acp spawn inside an active ... thread` | 在线程上下文之外使用了 `--thread here`。 | 移动到目标线程,或使用 `--thread auto`/`off`。 |
|
||||
| `Only <user-id> can rebind this channel/conversation/thread.` | 另一个用户拥有当前活动绑定目标。 | 由拥有者重新绑定,或使用其他对话或线程。 |
|
||||
| `Only <user-id> can rebind this channel/conversation/thread.` | 另一个用户拥有当前活动绑定目标。 | 由所有者重新绑定,或使用其他会话或线程。 |
|
||||
| `Thread bindings are unavailable for <channel>.` | 适配器缺少线程绑定能力。 | 使用 `--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` 监控;手动杀掉陈旧进程。 |
|
||||
|
||||
@ -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 聊天命令使用 `! <cmd>`(`/bash <cmd>` 是其别名)。
|
||||
命令由 Gateway 网关处理。大多数命令必须作为**独立**消息发送,并且以 `/` 开头。
|
||||
仅主机可用的 bash 聊天命令使用 `! <cmd>`(`/bash <cmd>` 是其别名)。
|
||||
|
||||
这里有两个相关系统:
|
||||
|
||||
- **命令**:独立的 `/...` 消息。
|
||||
- **指令**:`/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`)启用 `! <cmd>` 来运行主机 shell 命令(`/bash <cmd>` 是别名;需要 `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`)启用 `! <cmd>` 以运行主机 shell 命令(`/bash <cmd>` 是别名;需要 `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.<channel>.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.<channel>.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 <duration|off>` 和 `/session max-age <duration|off>` 管理线程绑定过期。
|
||||
- `/think <level>` 设置 thinking 级别。可选值来自活动模型的提供商配置文件;常见级别有 `off`、`minimal`、`low`、`medium` 和 `high`,也有仅在支持时可用的自定义级别,如 `xhigh`、`adaptive`、`max` 或二元值 `on`。别名:`/thinking`、`/t`。
|
||||
- `/session idle <duration|off>` 和 `/session max-age <duration|off>` 管理线程绑定过期时间。
|
||||
- `/think <level>` 设置思考级别。可选项来自当前模型的提供商 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=<auto|sandbox|gateway|node> security=<deny|allowlist|full> ask=<off|on-miss|always> node=<id>` 显示或设置 exec 默认值。
|
||||
- `/model [name|#|status]` 显示或设置模型。
|
||||
- `/models [provider] [page] [limit=<n>|size=<n>|all]` 列出提供商或某个提供商下的模型。
|
||||
- `/models [provider] [page] [limit=<n>|size=<n>|all]` 列出提供商,或列出某提供商的模型。
|
||||
- `/queue <mode>` 管理队列行为(`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 <name> [input]` 按名称运行一个 skill。
|
||||
- `/allowlist [list|add|remove] ...` 管理 allowlist 条目。仅文本版。
|
||||
- `/allowlist [list|add|remove] ...` 管理 allowlist 条目。仅文本。
|
||||
- `/approve <id> <decision>` 处理 exec 审批提示。
|
||||
- `/btw <question>` 提出一个旁支问题,但不改变未来会话上下文。参见 [/tools/btw](/zh-CN/tools/btw)。
|
||||
- `/btw <question>` 提出一个旁路问题,而不会改变未来的会话上下文。参见 [/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 <target>` 将当前 Discord 线程或 Telegram 话题/会话绑定到一个会话目标。
|
||||
- `/focus <target>` 将当前 Discord 线程或 Telegram topic/conversation 绑定到一个会话目标。
|
||||
- `/unfocus` 移除当前绑定。
|
||||
- `/agents` 列出当前会话中线程绑定的智能体。
|
||||
- `/agents` 列出当前会话中与线程绑定的智能体。
|
||||
- `/kill <id|#|all>` 中止一个或所有正在运行的子智能体。
|
||||
- `/steer <id|#> <message>` 向正在运行的子智能体发送引导。别名:`/tell`。
|
||||
- `/steer <id|#> <message>` 向一个正在运行的子智能体发送引导。别名:`/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 <command>` 运行主机 shell 命令。仅文本版。别名:`! <command>`。需要 `commands.bash: true` 加 `tools.elevated` allowlist。
|
||||
- `/bash <command>` 运行主机 shell 命令。仅文本。别名:`! <command>`。需要 `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 <camera|screen|writes|all> [duration]|disarm` 临时启用高风险手机节点命令。
|
||||
- `/voice status|list [limit]|set <voiceId|name>` 管理 Talk 语音配置。在 Discord 上,原生命令名为 `/talkvoice`。
|
||||
- `/voice status|list [limit]|set <voiceId|name>` 管理 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 <name> [input]` 始终可作为通用入口点使用。
|
||||
- 当 skill/插件注册了直接命令时,它们也可能显示为像 `/prose` 这样的直接命令。
|
||||
- 当 skill/plugin 注册它们时,Skills 也可能显示为直接命令,例如 `/prose`。
|
||||
- 原生 skill 命令注册由 `commands.nativeSkills` 和 `channels.<provider>.commands.nativeSkills` 控制。
|
||||
|
||||
说明:
|
||||
|
||||
- 命令接受一个可选的 `:` 作为命令与参数之间的分隔(例如 `/think: high`、`/send: on`、`/help:`)。
|
||||
- `/new <model>` 接受模型别名、`provider/model` 或提供商名称(模糊匹配);如果未匹配到,则该文本会被视为消息正文。
|
||||
- 命令支持在命令和参数之间使用可选的 `:`(例如 `/think: high`、`/send: on`、`/help:`)。
|
||||
- `/new <model>` 接受模型别名、`provider/model` 或提供商名称(模糊匹配);如果没有匹配项,则该文本会被视为消息正文。
|
||||
- 如需完整的提供商使用量明细,请使用 `openclaw status --usage`。
|
||||
- `/allowlist add|remove` 需要 `commands.config=true`,并遵循渠道 `configWrites`。
|
||||
- `/allowlist add|remove` 需要 `commands.config=true`,并遵循渠道的 `configWrites`。
|
||||
- 在多账户渠道中,面向配置目标的 `/allowlist --account <id>` 和 `/config set channels.<provider>.accounts.<id>...` 也会遵循目标账户的 `configWrites`。
|
||||
- `/usage` 控制每条响应的使用量页脚;`/usage cost` 会根据 OpenClaw 会话日志打印本地成本摘要。
|
||||
- `/usage` 控制每条响应的 usage 页脚;`/usage cost` 会根据 OpenClaw 会话日志输出本地成本摘要。
|
||||
- `/restart` 默认启用;设置 `commands.restart: false` 可禁用。
|
||||
- `/plugins install <spec>` 接受与 `openclaw plugins install` 相同的插件规格:本地路径/归档、npm 包或 `clawhub:<pkg>`。
|
||||
- `/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 <spec>` 接受与 `openclaw plugins install` 相同的插件 spec:本地路径/归档、npm 包或 `clawhub:<pkg>`。
|
||||
- `/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 <name> [input]` 按名称运行一个 skill(当原生命令限制阻止为每个 skill 创建单独命令时,这很有用)。
|
||||
- **内联快捷方式(仅 allowlist 发送者):** 某些命令嵌入在普通消息中时也可生效,并会在模型看到其余文本前被剥离。
|
||||
- 示例:`hey /status` 会触发一条状态回复,而剩余文本会继续按正常流程处理。
|
||||
- 当前支持:`/help`、`/commands`、`/status`、`/whoami`(`/id`)。
|
||||
- 未授权的纯命令消息会被静默忽略,而内联 `/...` token 会被当作普通文本。
|
||||
- **Skill 命令:** `user-invocable` Skills 会作为斜杠命令暴露。名称会被清理为 `a-z0-9_`(最长 32 个字符);冲突名称会追加数字后缀(例如 `_2`)。
|
||||
- `/skill <name> [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:<agentId>:discord:slash:<userId>`
|
||||
- Slack:`agent:<agentId>:slack:slash:<userId>`(前缀可通过 `channels.slack.slashCommand.sessionPrefix` 配置)
|
||||
- Telegram:`telegram:slash:<userId>`(通过 `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)。
|
||||
|
||||
190
docs/zh-CN/tools/trajectory.md
Normal file
190
docs/zh-CN/tools/trajectory.md
Normal file
@ -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-<session>-<timestamp>/
|
||||
```
|
||||
|
||||
你可以选择一个相对输出目录名:
|
||||
|
||||
```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
|
||||
<session>.trajectory.jsonl
|
||||
```
|
||||
|
||||
OpenClaw 还会尽力在会话旁边写入一个指针文件:
|
||||
|
||||
```text
|
||||
<session>.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 超过了
|
||||
导出的安全限制。请开始一个新会话,或导出更小的复现。
|
||||
@ -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://<host>: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>
|
||||
```
|
||||
|
||||
如果浏览器在更改了身份验证详情(角色/作用域/公钥)后重试配对,之前的待处理请求会被替换,并生成新的 `requestId`。批准前请重新运行 `openclaw devices list`。
|
||||
如果浏览器在重试配对时更改了身份验证详情(role/scopes/public
|
||||
key),之前的待处理请求会被替代,并创建新的 `requestId`。
|
||||
批准前请重新运行 `openclaw devices list`。
|
||||
|
||||
如果浏览器已经配对,而你将其从只读访问更改为写入/管理员访问,这会被视为一次权限升级批准,而不是静默重连。OpenClaw 会保持旧批准有效,阻止权限更高的重连,并要求你显式批准新的作用域集合。
|
||||
如果浏览器已经配对,而你又将其从只读权限改为
|
||||
写入/管理员权限,这会被视为一次审批升级,而不是静默
|
||||
重连。OpenClaw 会保持旧审批仍然有效,阻止更高权限的重连,
|
||||
并要求你显式批准新的作用域集合。
|
||||
|
||||
一旦获批,该设备会被记住,除非你使用 `openclaw devices revoke --device <id> --role <role>` 撤销它,否则无需再次批准。有关 token 轮换和撤销,请参见 [Devices CLI](/zh-CN/cli/devices)。
|
||||
一旦获得批准,该设备就会被记住,除非你使用 `openclaw devices revoke --device <id> --role <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 负载(包括 `<tool_call>...</tool_call>`、`<function_call>...</function_call>`、`<tool_calls>...</tool_calls>`、`<function_calls>...</function_calls>` 以及被截断的工具调用块),并移除泄露出的 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 负载(包括 `<tool_call>...</tool_call>`、`<function_call>...</function_call>`、`<tool_calls>...</tool_calls>`、`<function_calls>...</function_calls>` 以及被截断的工具调用块),并移除泄露的 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://<magicdns>/`(或你配置的 `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://<lan-ip>` 或 `http://<tailscale-ip>`),
|
||||
浏览器会运行在**非安全上下文**中,并阻止 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://<magicdns>/`(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/<id>`)仍可正常渲染。
|
||||
- 内联 `data:image/...` URL 仍可正常渲染(对协议内负载很有用)。
|
||||
- 渠道元数据输出的远程头像 URL 会在 Control UI 的头像辅助函数中被剥离,并替换为内置 logo/badge,因此即使某个渠道被攻破或存在恶意行为,也无法强制操作员浏览器任意拉取远程图片。
|
||||
- 通过相对路径提供的头像和图片(例如 `/avatars/<id>`)仍然可以渲染。
|
||||
- 内联 `data:image/...` URL 仍然可以渲染(对协议内负载很有用)。
|
||||
- 由渠道元数据发出的远端头像 URL 会在控制 UI 的头像辅助函数中被剥离,并替换为内置 logo/badge,因此受损或恶意渠道无法强迫操作员浏览器发起任意远端图片请求。
|
||||
|
||||
你无需进行任何更改即可获得此行为——它始终开启,且不可配置。
|
||||
你无需做任何修改即可获得此行为——它始终开启,且不可配置。
|
||||
|
||||
## 头像路由身份验证
|
||||
|
||||
当配置了 Gateway 网关身份验证时,Control UI 的头像端点要求使用与其余 API 相同的 Gateway 网关 token:
|
||||
配置了 gateway 身份验证时,控制 UI 头像端点要求与其余 API 相同的 gateway token:
|
||||
|
||||
- `GET /avatar/<agentId>` 仅向已通过身份验证的调用者返回头像图片。`GET /avatar/<agentId>?meta=1` 也会在相同规则下返回头像元数据。
|
||||
- 对这两个路由的未认证请求都会被拒绝(与相邻的 assistant-media 路由保持一致)。这可以防止头像路由在其他部分已受保护的主机上泄露智能体身份。
|
||||
- Control UI 本身在获取头像时会将 Gateway 网关 token 作为 bearer 请求头转发,并使用已认证的 blob URL,因此图片仍能在仪表板中正常渲染。
|
||||
- `GET /avatar/<agentId>` 仅向已认证调用方返回头像图片。`GET /avatar/<agentId>?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://<gateway-host>:18789
|
||||
```
|
||||
|
||||
可选的一次性身份验证(如需要):
|
||||
可选的一次性身份验证(如有需要):
|
||||
|
||||
```text
|
||||
http://localhost:5173/?gatewayUrl=wss://<gateway-host>:18789#token=<gateway-token>
|
||||
@ -322,19 +369,20 @@ http://localhost:5173/?gatewayUrl=wss://<gateway-host>:18789#token=<gateway-toke
|
||||
|
||||
说明:
|
||||
|
||||
- `gatewayUrl` 会在加载后存入 localStorage,并从 URL 中移除。
|
||||
- `token` 应尽可能通过 URL 片段(`#token=...`)传递。片段不会发送到服务器,因此可避免请求日志和 Referer 泄露。旧版 `?token=` 查询参数为了兼容仍会导入一次,但仅作为回退使用,并会在 bootstrap 后立即剥离。
|
||||
- `gatewayUrl` 会在加载后存储到 localStorage 中,并从 URL 中移除。
|
||||
- 应尽可能通过 URL 片段(`#token=...`)传递 `token`。片段不会发送到服务器,这可避免请求日志和 Referer 泄露。旧版 `?token=` 查询参数仍会为兼容性导入一次,但仅作为回退,并会在引导后立即移除。
|
||||
- `password` 仅保存在内存中。
|
||||
- 当设置了 `gatewayUrl` 时,UI 不会回退到配置或环境凭证。
|
||||
请显式提供 `token`(或 `password`)。如果缺少显式凭证,会报错。
|
||||
- 当 Gateway 网关位于 TLS 后面时(Tailscale Serve、HTTPS 代理等),请使用 `wss://`。
|
||||
- `gatewayUrl` 仅在顶层窗口中接受(不能嵌入),以防止点击劫持。
|
||||
- 非 loopback 的 Control UI 部署必须显式设置 `gateway.controlUi.allowedOrigins`
|
||||
(完整 origin)。这也包括远程开发设置。
|
||||
- 除非是在严格受控的本地测试中,否则不要使用 `gateway.controlUi.allowedOrigins: ["*"]`。
|
||||
这表示允许任意浏览器 origin,而不是“匹配我正在使用的任意主机”。
|
||||
- 当设置了 `gatewayUrl` 时,UI 不会回退到配置或环境变量凭证。
|
||||
请显式提供 `token`(或 `password`)。缺少显式凭证会报错。
|
||||
- 当 Gateway 网关位于 TLS 之后时(Tailscale Serve、HTTPS 代理等),请使用 `wss://`。
|
||||
- `gatewayUrl` 只会在顶层窗口中被接受(不能嵌入),以防止点击劫持。
|
||||
- 非 loopback 的控制 UI 部署必须显式设置 `gateway.controlUi.allowedOrigins`
|
||||
(完整 origin)。这也包括远端开发设置。
|
||||
- 除非是严格受控的本地测试,否则不要使用 `gateway.controlUi.allowedOrigins: ["*"]`。
|
||||
它表示允许任何浏览器 origin,而不是“匹配我当前
|
||||
使用的任意主机”。
|
||||
- `gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true` 会启用
|
||||
Host 请求头 origin 回退模式,但这是危险的安全模式。
|
||||
Host 标头 origin 回退模式,但这是一种危险的安全模式。
|
||||
|
||||
示例:
|
||||
|
||||
@ -348,11 +396,11 @@ http://localhost:5173/?gatewayUrl=wss://<gateway-host>:18789#token=<gateway-toke
|
||||
}
|
||||
```
|
||||
|
||||
远程访问设置详情: [远程访问](/zh-CN/gateway/remote)。
|
||||
远端访问设置详情:[远端访问](/zh-CN/gateway/remote)。
|
||||
|
||||
## 相关内容
|
||||
|
||||
- [Dashboard](/zh-CN/web/dashboard) — Gateway 网关仪表板
|
||||
- [仪表板](/zh-CN/web/dashboard) — gateway 仪表板
|
||||
- [WebChat](/zh-CN/web/webchat) — 基于浏览器的聊天界面
|
||||
- [TUI](/zh-CN/web/tui) — 终端用户界面
|
||||
- [Health Checks](/zh-CN/gateway/health) — Gateway 网关健康监控
|
||||
- [健康检查](/zh-CN/gateway/health) — gateway 健康监控
|
||||
|
||||
Loading…
Reference in New Issue
Block a user