chore(i18n): refresh zh-CN translations
This commit is contained in:
parent
7a37fb3488
commit
b54f3efca2
@ -5,19 +5,19 @@ read_when:
|
||||
summary: Feishu 机器人概览、功能和配置
|
||||
title: Feishu
|
||||
x-i18n:
|
||||
generated_at: "2026-04-26T03:53:24Z"
|
||||
generated_at: "2026-04-26T07:48:29Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: b209a5e44d31fed562de624a39001f07e532dfeef9fefef4e0ce4a0bf18f21e2
|
||||
source_hash: 95a50a7cd7b290afe0a0db3a1b39c7305f6a0e7d0702597fb9a50b5a45afa855
|
||||
source_path: channels/feishu.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Feishu / Lark
|
||||
|
||||
Feishu/Lark 是一个一体化协作平台,团队可以在其中聊天、共享文档、管理日历,并协同完成工作。
|
||||
Feishu/Lark 是一个一体化协作平台,团队可以在其中聊天、共享文档、管理日历并协同完成工作。
|
||||
|
||||
**Status:** 机器人私信 + 群聊已可用于生产环境。WebSocket 是默认模式;webhook 模式为可选。
|
||||
**Status:** 已可用于机器人私信和群聊。WebSocket 是默认模式;webhook 模式为可选。
|
||||
|
||||
---
|
||||
|
||||
@ -48,7 +48,7 @@ Feishu/Lark 是一个一体化协作平台,团队可以在其中聊天、共
|
||||
|
||||
配置 `dmPolicy` 以控制谁可以向机器人发送私信:
|
||||
|
||||
- `"pairing"` — 未知用户会收到一个配对码;通过 CLI 批准
|
||||
- `"pairing"` — 未知用户会收到配对码;通过 CLI 批准
|
||||
- `"allowlist"` — 只有 `allowFrom` 中列出的用户可以聊天(默认:仅机器人所有者)
|
||||
- `"open"` — 允许所有用户
|
||||
- `"disabled"` — 禁用所有私信
|
||||
@ -62,21 +62,21 @@ openclaw pairing approve feishu <CODE>
|
||||
|
||||
### 群聊
|
||||
|
||||
**群策略** (`channels.feishu.groupPolicy`):
|
||||
**群策略**(`channels.feishu.groupPolicy`):
|
||||
|
||||
| 值 | 行为 |
|
||||
| ------------- | ------------------------------------------ |
|
||||
| `"open"` | 在群组中响应所有消息 |
|
||||
| `"allowlist"` | 仅响应 `groupAllowFrom` 中的群组 |
|
||||
| `"open"` | 在群组中回复所有消息 |
|
||||
| `"allowlist"` | 仅回复 `groupAllowFrom` 中的群组 |
|
||||
| `"disabled"` | 禁用所有群消息 |
|
||||
|
||||
默认值:`allowlist`
|
||||
|
||||
**提及要求** (`channels.feishu.requireMention`):
|
||||
**提及要求**(`channels.feishu.requireMention`):
|
||||
|
||||
- `true` — 需要 @提及(默认)
|
||||
- `false` — 无需 @提及即可响应
|
||||
- 每群覆盖:`channels.feishu.groups.<chat_id>.requireMention`
|
||||
- `false` — 无需 @提及也会回复
|
||||
- 按群覆盖:`channels.feishu.groups.<chat_id>.requireMention`
|
||||
|
||||
---
|
||||
|
||||
@ -94,7 +94,7 @@ openclaw pairing approve feishu <CODE>
|
||||
}
|
||||
```
|
||||
|
||||
### 允许所有群组,仍需 @提及
|
||||
### 允许所有群组,但仍需 @提及
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -146,15 +146,15 @@ openclaw pairing approve feishu <CODE>
|
||||
|
||||
## 获取群组/用户 ID
|
||||
|
||||
### 群组 ID (`chat_id`,格式:`oc_xxx`)
|
||||
### 群组 ID(`chat_id`,格式:`oc_xxx`)
|
||||
|
||||
在 Feishu/Lark 中打开群组,点击右上角的菜单图标,然后进入 **设置**。群组 ID (`chat_id`) 会显示在设置页面上。
|
||||
在 Feishu/Lark 中打开群组,点击右上角的菜单图标,然后进入**设置**。群组 ID(`chat_id`)会显示在设置页面中。
|
||||
|
||||

|
||||
|
||||
### 用户 ID (`open_id`,格式:`ou_xxx`)
|
||||
### 用户 ID(`open_id`,格式:`ou_xxx`)
|
||||
|
||||
启动 Gateway 网关,向机器人发送一条私信,然后查看日志:
|
||||
启动 Gateway 网关,向机器人发送一条私信,然后检查日志:
|
||||
|
||||
```bash
|
||||
openclaw logs --follow
|
||||
@ -176,24 +176,24 @@ openclaw pairing list feishu
|
||||
| `/reset` | 重置当前会话 |
|
||||
| `/model` | 显示或切换 AI 模型 |
|
||||
|
||||
> Feishu/Lark 不支持原生斜杠命令菜单,因此请将这些命令作为纯文本消息发送。
|
||||
> Feishu/Lark 不支持原生斜杠命令菜单,因此请将这些命令作为普通文本消息发送。
|
||||
|
||||
---
|
||||
|
||||
## 故障排除
|
||||
|
||||
### 机器人在群聊中没有响应
|
||||
### 机器人在群聊中没有回复
|
||||
|
||||
1. 确保机器人已被添加到群组中
|
||||
2. 确保你已 @提及机器人(默认需要)
|
||||
3. 验证 `groupPolicy` 不是 `"disabled"`
|
||||
1. 确保机器人已被添加到群组
|
||||
2. 确保你 @提及了机器人(默认要求)
|
||||
3. 确认 `groupPolicy` 不是 `"disabled"`
|
||||
4. 检查日志:`openclaw logs --follow`
|
||||
|
||||
### 机器人没有收到消息
|
||||
|
||||
1. 确保机器人已在 Feishu Open Platform / Lark Developer 中发布并获批
|
||||
2. 确保事件订阅包含 `im.message.receive_v1`
|
||||
3. 确保已选择 **持久连接**(WebSocket)
|
||||
3. 确保已选择**长连接**(WebSocket)
|
||||
4. 确保已授予所有必需的权限范围
|
||||
5. 确保 Gateway 网关正在运行:`openclaw gateway status`
|
||||
6. 检查日志:`openclaw logs --follow`
|
||||
@ -201,14 +201,14 @@ openclaw pairing list feishu
|
||||
### App Secret 泄露
|
||||
|
||||
1. 在 Feishu Open Platform / Lark Developer 中重置 App Secret
|
||||
2. 更新你的配置中的对应值
|
||||
2. 更新你配置中的对应值
|
||||
3. 重启 Gateway 网关:`openclaw gateway restart`
|
||||
|
||||
---
|
||||
|
||||
## 高级配置
|
||||
|
||||
### 多账户
|
||||
### 多账号
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -220,6 +220,11 @@ openclaw pairing list feishu
|
||||
appId: "cli_xxx",
|
||||
appSecret: "xxx",
|
||||
name: "Primary bot",
|
||||
tts: {
|
||||
providers: {
|
||||
openai: { voice: "shimmer" },
|
||||
},
|
||||
},
|
||||
},
|
||||
backup: {
|
||||
appId: "cli_yyy",
|
||||
@ -233,7 +238,8 @@ openclaw pairing list feishu
|
||||
}
|
||||
```
|
||||
|
||||
`defaultAccount` 控制当出站 API 未指定 `accountId` 时使用哪个账户。
|
||||
`defaultAccount` 用于控制在出站 API 未指定 `accountId` 时使用哪个账号。
|
||||
`accounts.<id>.tts` 使用与 `messages.tts` 相同的结构,并会在全局 TTS 配置之上进行深度合并,因此多机器人 Feishu 配置可以将共享的提供商凭证保留在全局,同时仅按账号覆盖语音、模型、persona 或自动模式。
|
||||
|
||||
### 消息限制
|
||||
|
||||
@ -242,27 +248,27 @@ openclaw pairing list feishu
|
||||
|
||||
### 流式传输
|
||||
|
||||
Feishu/Lark 通过交互式卡片支持流式回复。启用后,机器人会在生成文本时实时更新卡片。
|
||||
Feishu/Lark 支持通过交互式卡片进行流式回复。启用后,机器人会在生成文本时实时更新卡片。
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
feishu: {
|
||||
streaming: true, // 启用流式卡片输出(默认:true)
|
||||
blockStreaming: true, // 启用分块流式传输(默认:true)
|
||||
blockStreaming: true, // 启用块级流式传输(默认:true)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
设置 `streaming: false` 可将完整回复作为一条消息发送。
|
||||
设置 `streaming: false` 可在一条消息中发送完整回复。
|
||||
|
||||
### 配额优化
|
||||
|
||||
使用两个可选标志来减少 Feishu/Lark API 调用次数:
|
||||
使用两个可选标志减少 Feishu/Lark API 调用次数:
|
||||
|
||||
- `typingIndicator`(默认 `true`):设置为 `false` 可跳过“正在输入”反应调用
|
||||
- `resolveSenderNames`(默认 `true`):设置为 `false` 可跳过发送者资料查询
|
||||
- `typingIndicator`(默认 `true`):设为 `false` 以跳过“正在输入”反应调用
|
||||
- `resolveSenderNames`(默认 `true`):设为 `false` 以跳过发送者资料查找
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -331,7 +337,7 @@ Feishu/Lark 支持用于私信和群线程消息的 ACP。Feishu/Lark ACP 由文
|
||||
/acp spawn codex --thread here
|
||||
```
|
||||
|
||||
`--thread here` 适用于私信和 Feishu/Lark 线程消息。已绑定对话中的后续消息会直接路由到该 ACP 会话。
|
||||
`--thread here` 适用于私信和 Feishu/Lark 线程消息。绑定对话中的后续消息会直接路由到该 ACP 会话。
|
||||
|
||||
### 多智能体路由
|
||||
|
||||
@ -367,11 +373,11 @@ Feishu/Lark 支持用于私信和群线程消息的 ACP。Feishu/Lark ACP 由文
|
||||
|
||||
路由字段:
|
||||
|
||||
- `match.channel`: `"feishu"`
|
||||
- `match.peer.kind`: `"direct"`(私信)或 `"group"`(群聊)
|
||||
- `match.peer.id`: 用户 Open ID(`ou_xxx`)或群组 ID(`oc_xxx`)
|
||||
- `match.channel`:`"feishu"`
|
||||
- `match.peer.kind`:`"direct"`(私信)或 `"group"`(群聊)
|
||||
- `match.peer.id`:用户 Open ID(`ou_xxx`)或群组 ID(`oc_xxx`)
|
||||
|
||||
查找提示请参见 [获取群组/用户 ID](#get-groupuser-ids)。
|
||||
查找提示请参阅 [获取群组/用户 ID](#get-groupuser-ids)。
|
||||
|
||||
---
|
||||
|
||||
@ -382,23 +388,24 @@ Feishu/Lark 支持用于私信和群线程消息的 ACP。Feishu/Lark ACP 由文
|
||||
| 设置 | 说明 | 默认值 |
|
||||
| ------------------------------------------------- | ------------------------------------------ | ---------------- |
|
||||
| `channels.feishu.enabled` | 启用/禁用该渠道 | `true` |
|
||||
| `channels.feishu.domain` | API 域(`feishu` 或 `lark`) | `feishu` |
|
||||
| `channels.feishu.domain` | API 域名(`feishu` 或 `lark`) | `feishu` |
|
||||
| `channels.feishu.connectionMode` | 事件传输方式(`websocket` 或 `webhook`) | `websocket` |
|
||||
| `channels.feishu.defaultAccount` | 出站路由的默认账户 | `default` |
|
||||
| `channels.feishu.verificationToken` | webhook 模式必需 | — |
|
||||
| `channels.feishu.encryptKey` | webhook 模式必需 | — |
|
||||
| `channels.feishu.defaultAccount` | 出站路由的默认账号 | `default` |
|
||||
| `channels.feishu.verificationToken` | webhook 模式必填 | — |
|
||||
| `channels.feishu.encryptKey` | webhook 模式必填 | — |
|
||||
| `channels.feishu.webhookPath` | webhook 路由路径 | `/feishu/events` |
|
||||
| `channels.feishu.webhookHost` | webhook 绑定主机 | `127.0.0.1` |
|
||||
| `channels.feishu.webhookPort` | webhook 绑定端口 | `3000` |
|
||||
| `channels.feishu.accounts.<id>.appId` | App ID | — |
|
||||
| `channels.feishu.accounts.<id>.appSecret` | App Secret | — |
|
||||
| `channels.feishu.accounts.<id>.domain` | 每账户域覆盖 | `feishu` |
|
||||
| `channels.feishu.accounts.<id>.domain` | 按账号覆盖域名 | `feishu` |
|
||||
| `channels.feishu.accounts.<id>.tts` | 按账号覆盖 TTS | `messages.tts` |
|
||||
| `channels.feishu.dmPolicy` | 私信策略 | `allowlist` |
|
||||
| `channels.feishu.allowFrom` | 私信允许列表(`open_id` 列表) | [BotOwnerId] |
|
||||
| `channels.feishu.groupPolicy` | 群策略 | `allowlist` |
|
||||
| `channels.feishu.groupAllowFrom` | 群允许列表 | — |
|
||||
| `channels.feishu.requireMention` | 在群组中要求 @提及 | `true` |
|
||||
| `channels.feishu.groups.<chat_id>.requireMention` | 每群 @提及覆盖 | 继承 |
|
||||
| `channels.feishu.groups.<chat_id>.requireMention` | 按群覆盖 @提及要求 | inherited |
|
||||
| `channels.feishu.groups.<chat_id>.enabled` | 启用/禁用特定群组 | `true` |
|
||||
| `channels.feishu.textChunkLimit` | 消息分块大小 | `2000` |
|
||||
| `channels.feishu.mediaMaxMb` | 媒体大小限制 | `30` |
|
||||
@ -421,7 +428,7 @@ Feishu/Lark 支持用于私信和群线程消息的 ACP。Feishu/Lark ACP 由文
|
||||
- ✅ 视频/媒体
|
||||
- ✅ 贴纸
|
||||
|
||||
入站的 Feishu/Lark 音频消息会被标准化为媒体占位符,而不是原始 `file_key` JSON。当配置了 `tools.media.audio` 时,OpenClaw 会下载语音消息资源,并在智能体轮次之前运行共享音频转写,因此智能体接收到的是语音转写文本。如果 Feishu 在音频负载中直接包含转写文本,则会直接使用该文本,而不会再次调用 ASR。在没有音频转写提供商的情况下,智能体仍会接收到一个 `<media:audio>` 占位符以及已保存的附件,而不是原始的 Feishu 资源负载。
|
||||
入站的 Feishu/Lark 音频消息会被规范化为媒体占位符,而不是原始的 `file_key` JSON。配置了 `tools.media.audio` 时,OpenClaw 会下载语音消息资源,并在智能体轮次之前运行共享音频转写,因此智能体接收到的是语音转写文本。如果 Feishu 在音频负载中直接包含转写文本,则会直接使用该文本,而不会再次调用 ASR。若未配置音频转写提供商,智能体仍会收到一个 `<media:audio>` 占位符以及已保存的附件,而不是原始的 Feishu 资源负载。
|
||||
|
||||
### 发送
|
||||
|
||||
@ -431,23 +438,23 @@ Feishu/Lark 支持用于私信和群线程消息的 ACP。Feishu/Lark ACP 由文
|
||||
- ✅ 音频
|
||||
- ✅ 视频/媒体
|
||||
- ✅ 交互式卡片(包括流式更新)
|
||||
- ⚠️ 富文本(post 风格格式;不支持完整的 Feishu/Lark 编辑能力)
|
||||
- ⚠️ 富文本(post 风格格式;不支持完整的 Feishu/Lark 原生编辑能力)
|
||||
|
||||
原生 Feishu/Lark 音频气泡使用 Feishu `audio` 消息类型,并需要上传 Ogg/Opus 媒体(`file_type: "opus"`)。现有的 `.opus` 和 `.ogg` 媒体会直接作为原生音频发送。只有当回复请求以语音方式发送(`audioAsVoice` / 消息工具 `asVoice`,包括 TTS 语音便签回复)时,MP3/WAV/M4A 和其他可能的音频格式才会通过 `ffmpeg` 转码为 48 kHz Ogg/Opus。普通 MP3 附件会保持为常规文件。如果缺少 `ffmpeg` 或转换失败,OpenClaw 会回退为文件附件并记录原因。
|
||||
原生 Feishu/Lark 音频气泡使用 Feishu 的 `audio` 消息类型,并要求上传 Ogg/Opus 媒体(`file_type: "opus"`)。现有的 `.opus` 和 `.ogg` 媒体会直接作为原生音频发送。MP3/WAV/M4A 和其他可能的音频格式,仅在回复请求语音发送时才会使用 `ffmpeg` 转码为 48 kHz Ogg/Opus(`audioAsVoice` / 消息工具 `asVoice`,包括 TTS 语音便笺回复)。普通 MP3 附件会保持为常规文件。如果缺少 `ffmpeg` 或转换失败,OpenClaw 会回退为文件附件并记录原因。
|
||||
|
||||
### 线程和回复
|
||||
|
||||
- ✅ 内联回复
|
||||
- ✅ 行内回复
|
||||
- ✅ 线程回复
|
||||
- ✅ 回复线程消息时,媒体回复会保持线程感知
|
||||
|
||||
对于 `groupSessionScope: "group_topic"` 和 `"group_topic_sender"`,原生 Feishu/Lark 话题群组使用事件 `thread_id`(`omt_*`)作为规范的话题会话键。对于 OpenClaw 转换为线程的普通群回复,仍继续使用回复根消息 ID(`om_*`),这样首轮消息和后续轮次会保持在同一个会话中。
|
||||
对于 `groupSessionScope: "group_topic"` 和 `"group_topic_sender"`,原生 Feishu/Lark 话题群组使用事件中的 `thread_id`(`omt_*`)作为规范的话题会话键。对于 OpenClaw 转换为线程的普通群回复,则继续使用回复根消息 ID(`om_*`),这样首轮和后续轮次都会保留在同一会话中。
|
||||
|
||||
---
|
||||
|
||||
## 相关内容
|
||||
|
||||
- [渠道概览](/zh-CN/channels) — 所有支持的渠道
|
||||
- [渠道概览](/zh-CN/channels) — 所有受支持的渠道
|
||||
- [配对](/zh-CN/channels/pairing) — 私信身份验证和配对流程
|
||||
- [群组](/zh-CN/channels/groups) — 群聊行为和提及门控
|
||||
- [渠道路由](/zh-CN/channels/channel-routing) — 消息的会话路由
|
||||
|
||||
@ -1,158 +1,168 @@
|
||||
---
|
||||
read_when:
|
||||
- 更改群聊行为或提及门控
|
||||
summary: 跨不同界面上的群聊行为(Discord/iMessage/Matrix/Microsoft Teams/Signal/Slack/Telegram/WhatsApp/Zalo)
|
||||
sidebarTitle: Groups
|
||||
summary: 跨各渠道的群聊行为(Discord/iMessage/Matrix/Microsoft Teams/Signal/Slack/Telegram/WhatsApp/Zalo)
|
||||
title: 群组
|
||||
x-i18n:
|
||||
generated_at: "2026-04-26T05:36:54Z"
|
||||
generated_at: "2026-04-26T07:48:28Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: fa3448638de2f7babb432d0434dd4fb0f3d6ee53cad39627fef313b9023b138c
|
||||
source_hash: 837055b3cd044ebe3ef9aefe29e36f6471f48025d32169c43b9c5b04a8ac639c
|
||||
source_path: channels/groups.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
OpenClaw 会在不同界面上以一致方式处理群聊:Discord、iMessage、Matrix、Microsoft Teams、Signal、Slack、Telegram、WhatsApp、Zalo。
|
||||
OpenClaw 会在各个渠道上一致地处理群聊:Discord、iMessage、Matrix、Microsoft Teams、Signal、Slack、Telegram、WhatsApp、Zalo。
|
||||
|
||||
## 新手简介(2 分钟)
|
||||
## 新手介绍(2 分钟)
|
||||
|
||||
OpenClaw “运行”在你自己的消息账号上。没有单独的 WhatsApp 机器人用户。
|
||||
如果**你**在一个群组里,OpenClaw 就能看到该群组并在那里回复。
|
||||
OpenClaw “运行”在你自己的消息账号上。不存在单独的 WhatsApp 机器人用户。如果**你**在某个群里,OpenClaw 就可以看到那个群并在其中回复。
|
||||
|
||||
默认行为:
|
||||
|
||||
- 群组是受限的(`groupPolicy: "allowlist"`)。
|
||||
- 群组默认受限(`groupPolicy: "allowlist"`)。
|
||||
- 回复需要提及,除非你明确禁用提及门控。
|
||||
|
||||
也就是说:在允许列表中的发送者可以通过提及 OpenClaw 来触发它。
|
||||
|
||||
> TL;DR
|
||||
>
|
||||
> - **私信访问**由 `*.allowFrom` 控制。
|
||||
> - **群组访问**由 `*.groupPolicy` + 允许列表(`*.groups`、`*.groupAllowFrom`)控制。
|
||||
> - **回复触发**由提及门控(`requireMention`、`/activation`)控制。
|
||||
<Note>
|
||||
**TL;DR**
|
||||
|
||||
快速流程(群组消息会发生什么):
|
||||
- **私信访问**由 `*.allowFrom` 控制。
|
||||
- **群组访问**由 `*.groupPolicy` + 允许列表(`*.groups`、`*.groupAllowFrom`)控制。
|
||||
- **回复触发**由提及门控(`requireMention`、`/activation`)控制。
|
||||
</Note>
|
||||
|
||||
快速流程(群消息会发生什么):
|
||||
|
||||
```text
|
||||
groupPolicy? disabled -> 丢弃
|
||||
groupPolicy? allowlist -> 群组已允许?否 -> 丢弃
|
||||
requireMention? yes -> 已提及?否 -> 仅存储为上下文
|
||||
otherwise -> 回复
|
||||
groupPolicy? allowlist -> 群组被允许?否 -> 丢弃
|
||||
requireMention? 是 -> 被提及?否 -> 仅存储为上下文
|
||||
否则 -> 回复
|
||||
```
|
||||
|
||||
## 上下文可见性和允许列表
|
||||
## 上下文可见性与允许列表
|
||||
|
||||
群组安全涉及两种不同的控制:
|
||||
|
||||
- **触发授权**:谁可以触发智能体(`groupPolicy`、`groups`、`groupAllowFrom`、渠道特定的允许列表)。
|
||||
- **上下文可见性**:哪些补充上下文会被注入模型中(回复文本、引用、线程历史、转发元数据)。
|
||||
- **触发授权**:谁可以触发智能体(`groupPolicy`、`groups`、`groupAllowFrom`、特定渠道的允许列表)。
|
||||
- **上下文可见性**:哪些补充上下文会注入到模型中(回复文本、引用、线程历史、转发元数据)。
|
||||
|
||||
默认情况下,OpenClaw 优先保证正常聊天行为,并尽量保留接收到的上下文原样。这意味着允许列表主要决定谁可以触发操作,而不是对每一段引用或历史片段都构成通用的脱敏边界。
|
||||
默认情况下,OpenClaw 优先保留正常聊天行为,并尽量按接收到的原样保留上下文。这意味着允许列表主要决定谁可以触发动作,而不是对每一段引用或历史片段都建立通用的脱敏边界。
|
||||
|
||||
当前行为因渠道而异:
|
||||
<AccordionGroup>
|
||||
<Accordion title="当前行为因渠道而异">
|
||||
- 某些渠道已经在特定路径上对补充上下文应用了基于发送者的过滤(例如 Slack 线程种子、Matrix 回复/线程查找)。
|
||||
- 其他渠道仍会按接收到的原样传递引用/回复/转发上下文。
|
||||
</Accordion>
|
||||
<Accordion title="加固方向(计划中)">
|
||||
- `contextVisibility: "all"`(默认)保留当前按接收原样处理的行为。
|
||||
- `contextVisibility: "allowlist"` 将补充上下文过滤为仅允许列表中的发送者。
|
||||
- `contextVisibility: "allowlist_quote"` 是 `allowlist`,外加一个明确的引用/回复例外。
|
||||
|
||||
- 某些渠道已经在特定路径中对补充上下文应用基于发送者的过滤(例如 Slack 线程预填充、Matrix 回复/线程查询)。
|
||||
- 其他渠道仍然会按接收到的原样传递引用/回复/转发上下文。
|
||||
在这一加固模型尚未在各渠道中一致实现之前,你应预期不同渠道之间会有差异。
|
||||
|
||||
加固方向(计划中):
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
- `contextVisibility: "all"`(默认)保留当前按接收原样处理的行为。
|
||||
- `contextVisibility: "allowlist"` 将补充上下文过滤为仅允许列表中的发送者。
|
||||
- `contextVisibility: "allowlist_quote"` 表示 `allowlist`,并额外允许一个明确的引用/回复例外。
|
||||
|
||||
在这个加固模型尚未在各渠道中一致实现之前,不同界面之间会存在差异。
|
||||
|
||||

|
||||

|
||||
|
||||
如果你想要……
|
||||
|
||||
| 目标 | 要设置的内容 |
|
||||
| -------------------------------------------- | ---------------------------------------------------------- |
|
||||
| 允许所有群组,但只在 @提及时回复 | `groups: { "*": { requireMention: true } }` |
|
||||
| 允许所有群组,但仅在 @提及时回复 | `groups: { "*": { requireMention: true } }` |
|
||||
| 禁用所有群组回复 | `groupPolicy: "disabled"` |
|
||||
| 仅允许特定群组 | `groups: { "<group-id>": { ... } }`(不使用 `"*"` 键) |
|
||||
| 只有你能在群组中触发 | `groupPolicy: "allowlist"`,`groupAllowFrom: ["+1555..."]` |
|
||||
| 仅特定群组 | `groups: { "<group-id>": { ... } }`(不使用 `"*"` 键) |
|
||||
| 只有你可以在群组中触发 | `groupPolicy: "allowlist"`、`groupAllowFrom: ["+1555..."]` |
|
||||
|
||||
## 会话键
|
||||
|
||||
- 群组会话使用 `agent:<agentId>:<channel>:group:<id>` 作为会话键(房间/频道使用 `agent:<agentId>:<channel>:channel:<id>`)。
|
||||
- Telegram 论坛话题会将 `:topic:<threadId>` 添加到群组 id 中,因此每个话题都有自己的会话。
|
||||
- 私聊使用主会话(或按配置为每个发送者单独会话)。
|
||||
- 群组会话使用 `agent:<agentId>:<channel>:group:<id>` 会话键(房间/频道使用 `agent:<agentId>:<channel>:channel:<id>`)。
|
||||
- Telegram 论坛话题会在群组 id 后附加 `:topic:<threadId>`,因此每个话题都有自己的会话。
|
||||
- 私聊使用主会话(或在已配置时按发送者分会话)。
|
||||
- 心跳会跳过群组会话。
|
||||
|
||||
<a id="pattern-personal-dms-public-groups-single-agent"></a>
|
||||
|
||||
## 模式:个人私信 + 公共群组(单个智能体)
|
||||
## 模式:个人私信 + 公共群组(单智能体)
|
||||
|
||||
可以——如果你的“个人”流量是**私信**,而“公共”流量是**群组**,这种方式效果很好。
|
||||
|
||||
原因:在单智能体模式下,私信通常会进入**主**会话键(`agent:main:main`),而群组总是使用**非主**会话键(`agent:main:<channel>:group:<id>`)。如果你启用 `mode: "non-main"` 的沙箱隔离,这些群组会话就会在已配置的沙箱后端中运行,而你的主私信会话仍保留在宿主机上。如果你不选择具体后端,默认后端是 Docker。
|
||||
原因是:在单智能体模式下,私信通常会进入**主**会话键(`agent:main:main`),而群组始终使用**非主**会话键(`agent:main:<channel>:group:<id>`)。如果你启用沙箱隔离并设置 `mode: "non-main"`,这些群组会话就会在配置好的沙箱后端中运行,而你的主私信会话仍保留在主机上运行。如果你没有选择后端,默认后端是 Docker。
|
||||
|
||||
这样你就拥有一个智能体“中枢”(共享工作区 + memory),但有两种执行姿态:
|
||||
这会为你提供一个智能体“大脑”(共享工作区 + 记忆),但有两种不同的执行姿态:
|
||||
|
||||
- **私信**:完整工具(宿主机)
|
||||
- **私信**:完整工具(主机)
|
||||
- **群组**:沙箱 + 受限工具
|
||||
|
||||
> 如果你需要真正独立的工作区/人格(“个人”和“公共”绝不能混用),请使用第二个智能体 + 绑定。参见 [Multi-Agent Routing](/zh-CN/concepts/multi-agent)。
|
||||
<Note>
|
||||
如果你需要真正独立的工作区/人格(“个人”和“公开”绝不能混用),请使用第二个智能体 + 绑定。参见 [Multi-Agent Routing](/zh-CN/concepts/multi-agent)。
|
||||
</Note>
|
||||
|
||||
示例(私信在宿主机上,群组在沙箱中运行 + 仅允许消息类工具):
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
defaults: {
|
||||
sandbox: {
|
||||
mode: "non-main", // 群组/频道属于 non-main -> 沙箱隔离
|
||||
scope: "session", // 最强隔离(每个群组/频道一个容器)
|
||||
workspaceAccess: "none",
|
||||
},
|
||||
},
|
||||
},
|
||||
tools: {
|
||||
sandbox: {
|
||||
tools: {
|
||||
// 如果 allow 非空,其他所有内容都会被阻止(deny 仍然优先生效)。
|
||||
allow: ["group:messaging", "group:sessions"],
|
||||
deny: ["group:runtime", "group:fs", "group:ui", "nodes", "cron", "gateway"],
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
想要“群组只能看到文件夹 X”,而不是“完全不能访问宿主机”?保留 `workspaceAccess: "none"`,并只把允许列表中的路径挂载到沙箱中:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
defaults: {
|
||||
sandbox: {
|
||||
mode: "non-main",
|
||||
scope: "session",
|
||||
workspaceAccess: "none",
|
||||
docker: {
|
||||
binds: [
|
||||
// hostPath:containerPath:mode
|
||||
"/home/user/FriendsShared:/data:ro",
|
||||
],
|
||||
<Tabs>
|
||||
<Tab title="私信在主机上,群组使用沙箱隔离">
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
defaults: {
|
||||
sandbox: {
|
||||
mode: "non-main", // groups/channels are non-main -> sandboxed
|
||||
scope: "session", // strongest isolation (one container per group/channel)
|
||||
workspaceAccess: "none",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
tools: {
|
||||
sandbox: {
|
||||
tools: {
|
||||
// If allow is non-empty, everything else is blocked (deny still wins).
|
||||
allow: ["group:messaging", "group:sessions"],
|
||||
deny: ["group:runtime", "group:fs", "group:ui", "nodes", "cron", "gateway"],
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="群组只能看到允许列表中的文件夹">
|
||||
想要“群组只能看到文件夹 X”,而不是“完全无主机访问”?请保持 `workspaceAccess: "none"`,并且只将允许列表中的路径挂载到沙箱中:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
defaults: {
|
||||
sandbox: {
|
||||
mode: "non-main",
|
||||
scope: "session",
|
||||
workspaceAccess: "none",
|
||||
docker: {
|
||||
binds: [
|
||||
// hostPath:containerPath:mode
|
||||
"/home/user/FriendsShared:/data:ro",
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
相关内容:
|
||||
|
||||
- 配置键和默认值:[Gateway 网关配置](/zh-CN/gateway/config-agents#agentsdefaultssandbox)
|
||||
- 调试为什么某个工具被阻止:[Sandbox vs Tool Policy vs Elevated](/zh-CN/gateway/sandbox-vs-tool-policy-vs-elevated)
|
||||
- 调试为什么某个工具被阻止:[沙箱隔离 vs 工具策略 vs Elevated](/zh-CN/gateway/sandbox-vs-tool-policy-vs-elevated)
|
||||
- 绑定挂载详情:[沙箱隔离](/zh-CN/gateway/sandboxing#custom-bind-mounts)
|
||||
|
||||
## 显示标签
|
||||
|
||||
- UI 标签在可用时使用 `displayName`,格式为 `<channel>:<token>`。
|
||||
- `#room` 保留给房间/频道;群聊使用 `g-<slug>`(小写,空格转为 `-`,保留 `#@+._-`)。
|
||||
- UI 标签会在可用时使用 `displayName`,格式为 `<channel>:<token>`。
|
||||
- `#room` 保留给房间/频道;群聊使用 `g-<slug>`(小写,空格转换为 `-`,保留 `#@+._-`)。
|
||||
|
||||
## 群组策略
|
||||
|
||||
@ -167,7 +177,7 @@ otherwise -> 回复
|
||||
},
|
||||
telegram: {
|
||||
groupPolicy: "disabled",
|
||||
groupAllowFrom: ["123456789"], // Telegram 数字用户 id(向导可以解析 @username)
|
||||
groupAllowFrom: ["123456789"], // numeric Telegram user id (wizard can resolve @username)
|
||||
},
|
||||
signal: {
|
||||
groupPolicy: "disabled",
|
||||
@ -205,35 +215,44 @@ otherwise -> 回复
|
||||
|
||||
| 策略 | 行为 |
|
||||
| ------------- | ------------------------------------------------------------ |
|
||||
| `"open"` | 群组绕过允许列表;提及门控仍然适用。 |
|
||||
| `"open"` | 群组会绕过允许列表;提及门控仍然生效。 |
|
||||
| `"disabled"` | 完全阻止所有群组消息。 |
|
||||
| `"allowlist"` | 仅允许与已配置允许列表匹配的群组/房间。 |
|
||||
|
||||
注意:
|
||||
|
||||
- `groupPolicy` 与提及门控是分开的(提及门控要求 @提及)。
|
||||
- WhatsApp/Telegram/Signal/iMessage/Microsoft Teams/Zalo:使用 `groupAllowFrom`(回退为显式 `allowFrom`)。
|
||||
- 私信配对批准(`*-allowFrom` 存储条目)仅适用于私信访问;群组发送者授权仍然需要显式配置群组允许列表。
|
||||
- Discord:允许列表使用 `channels.discord.guilds.<id>.channels`。
|
||||
- Slack:允许列表使用 `channels.slack.channels`。
|
||||
- Matrix:允许列表使用 `channels.matrix.groups`。优先使用房间 id 或别名;已加入房间的名称查询属于尽力而为,无法解析的名称会在运行时被忽略。使用 `channels.matrix.groupAllowFrom` 来限制发送者;也支持按房间配置的 `users` 允许列表。
|
||||
- 群组私信单独控制(`channels.discord.dm.*`、`channels.slack.dm.*`)。
|
||||
- Telegram 允许列表可以匹配用户 id(`"123456789"`、`"telegram:123456789"`、`"tg:123456789"`)或用户名(`"@alice"` 或 `"alice"`);前缀大小写不敏感。
|
||||
- 默认值是 `groupPolicy: "allowlist"`;如果你的群组允许列表为空,群组消息会被阻止。
|
||||
- 运行时安全性:当某个提供商的配置块完全缺失(`channels.<provider>` 不存在)时,群组策略会回退到失败即关闭的模式(通常为 `allowlist`),而不是继承 `channels.defaults.groupPolicy`。
|
||||
<AccordionGroup>
|
||||
<Accordion title="各渠道说明">
|
||||
- `groupPolicy` 与提及门控是分开的(提及门控要求 @提及)。
|
||||
- WhatsApp/Telegram/Signal/iMessage/Microsoft Teams/Zalo:使用 `groupAllowFrom`(回退为显式 `allowFrom`)。
|
||||
- 私信配对批准(`*-allowFrom` 存储项)仅适用于私信访问;群组发送者授权仍需明确配置到群组允许列表中。
|
||||
- Discord:允许列表使用 `channels.discord.guilds.<id>.channels`。
|
||||
- Slack:允许列表使用 `channels.slack.channels`。
|
||||
- Matrix:允许列表使用 `channels.matrix.groups`。优先使用房间 ID 或别名;已加入房间的名称查找仅尽力而为,无法解析的名称会在运行时被忽略。使用 `channels.matrix.groupAllowFrom` 来限制发送者;也支持按房间的 `users` 允许列表。
|
||||
- 群组私信单独控制(`channels.discord.dm.*`、`channels.slack.dm.*`)。
|
||||
- Telegram 允许列表可以匹配用户 ID(`"123456789"`、`"telegram:123456789"`、`"tg:123456789"`)或用户名(`"@alice"` 或 `"alice"`);前缀不区分大小写。
|
||||
- 默认值是 `groupPolicy: "allowlist"`;如果你的群组允许列表为空,群组消息会被阻止。
|
||||
- 运行时安全:当某个提供商配置块完全缺失(`channels.<provider>` 不存在)时,群组策略会回退到故障关闭模式(通常是 `allowlist`),而不是继承 `channels.defaults.groupPolicy`。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
快速心智模型(群组消息的评估顺序):
|
||||
|
||||
1. `groupPolicy`(open/disabled/allowlist)
|
||||
2. 群组允许列表(`*.groups`、`*.groupAllowFrom`、渠道特定允许列表)
|
||||
3. 提及门控(`requireMention`、`/activation`)
|
||||
<Steps>
|
||||
<Step title="groupPolicy">
|
||||
`groupPolicy`(open/disabled/allowlist)。
|
||||
</Step>
|
||||
<Step title="群组允许列表">
|
||||
群组允许列表(`*.groups`、`*.groupAllowFrom`、特定渠道允许列表)。
|
||||
</Step>
|
||||
<Step title="提及门控">
|
||||
提及门控(`requireMention`、`/activation`)。
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## 提及门控(默认)
|
||||
|
||||
群组消息需要提及,除非你按群组覆盖该设置。默认值按各子系统存放在 `*.groups."*"` 下。
|
||||
群组消息默认需要提及,除非你在每个群组中单独覆盖。默认值位于每个子系统下的 `*.groups."*"`。
|
||||
|
||||
当渠道支持回复元数据时,回复机器人消息会被视为隐式提及。
|
||||
在暴露引用元数据的渠道上,引用机器人消息也可能被视为隐式提及。当前内置支持的情况包括 Telegram、WhatsApp、Slack、Discord、Microsoft Teams 和 ZaloUser。
|
||||
如果渠道支持回复元数据,回复机器人消息会被视为隐式提及。如果渠道暴露引用元数据,引用机器人消息也可以被视为隐式提及。当前内置支持的渠道包括 Telegram、WhatsApp、Slack、Discord、Microsoft Teams 和 ZaloUser。
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -271,32 +290,41 @@ otherwise -> 回复
|
||||
}
|
||||
```
|
||||
|
||||
注意:
|
||||
|
||||
- `mentionPatterns` 是大小写不敏感的安全正则表达式模式;无效模式和不安全的嵌套重复形式会被忽略。
|
||||
- 提供显式提及的界面仍然可以通过;这些模式只是回退机制。
|
||||
- 按智能体覆盖:`agents.list[].groupChat.mentionPatterns`(当多个智能体共享一个群组时很有用)。
|
||||
- 只有在能够检测提及的情况下才会强制执行提及门控(原生提及,或已配置 `mentionPatterns`)。
|
||||
- 在允许静默回复的群组中,纯空回复或仅包含推理的模型轮次会被视为静默,与 `NO_REPLY` 等效。私聊仍会把空回复视为一次失败的智能体轮次。
|
||||
- Discord 默认值位于 `channels.discord.guilds."*"`(可按 guild/频道覆盖)。
|
||||
- 群组历史上下文会在各渠道之间统一包装,并且仅包含**待处理消息**(即因提及门控而被跳过的消息);全局默认值使用 `messages.groupChat.historyLimit`,覆盖项使用 `channels.<channel>.historyLimit`(或 `channels.<channel>.accounts.*.historyLimit`)。设为 `0` 可禁用。
|
||||
<AccordionGroup>
|
||||
<Accordion title="提及门控说明">
|
||||
- `mentionPatterns` 是大小写不敏感的安全正则模式;无效模式和不安全的嵌套重复形式会被忽略。
|
||||
- 提供显式提及的渠道仍然会通过;这些模式只是回退方案。
|
||||
- 按智能体覆盖:`agents.list[].groupChat.mentionPatterns`(当多个智能体共享一个群组时很有用)。
|
||||
- 仅当可以进行提及检测时,提及门控才会生效(原生提及可用,或已配置 `mentionPatterns`)。
|
||||
- 在允许静默回复的群组中,纯空响应或仅推理的模型轮次会被视为静默,与 `NO_REPLY` 等价。私聊仍会将空回复视为一次失败的智能体轮次。
|
||||
- Discord 默认值位于 `channels.discord.guilds."*"`(可按 guild/channel 覆盖)。
|
||||
- 群组历史上下文会在各渠道间统一包装,并且仅限于**待处理消息**(即因提及门控而被跳过的消息);全局默认值使用 `messages.groupChat.historyLimit`,覆盖值使用 `channels.<channel>.historyLimit`(或 `channels.<channel>.accounts.*.historyLimit`)。设置为 `0` 可禁用。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 群组/频道工具限制(可选)
|
||||
|
||||
某些渠道配置支持限制**特定群组/房间/频道内**可用的工具。
|
||||
某些渠道配置支持限制**特定群组/房间/频道内部**可用的工具。
|
||||
|
||||
- `tools`:为整个群组允许/拒绝工具。
|
||||
- `toolsBySender`:群组内按发送者进行覆盖。
|
||||
使用明确的键前缀:
|
||||
`id:<senderId>`、`e164:<phone>`、`username:<handle>`、`name:<displayName>`,以及 `"*"` 通配符。
|
||||
旧版无前缀键仍然接受,但仅按 `id:` 匹配。
|
||||
- `toolsBySender`:群组内按发送者覆盖。使用显式键前缀:`id:<senderId>`、`e164:<phone>`、`username:<handle>`、`name:<displayName>`,以及 `"*"` 通配符。旧版无前缀键仍然被接受,但只会按 `id:` 进行匹配。
|
||||
|
||||
解析顺序(越具体越优先):
|
||||
|
||||
1. 群组/频道 `toolsBySender` 匹配
|
||||
2. 群组/频道 `tools`
|
||||
3. 默认(`"*"`)`toolsBySender` 匹配
|
||||
4. 默认(`"*"`)`tools`
|
||||
<Steps>
|
||||
<Step title="群组 toolsBySender">
|
||||
匹配群组/频道的 `toolsBySender`。
|
||||
</Step>
|
||||
<Step title="群组 tools">
|
||||
群组/频道的 `tools`。
|
||||
</Step>
|
||||
<Step title="默认 toolsBySender">
|
||||
默认(`"*"`)`toolsBySender` 匹配。
|
||||
</Step>
|
||||
<Step title="默认 tools">
|
||||
默认(`"*"`)`tools`。
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
示例(Telegram):
|
||||
|
||||
@ -318,68 +346,67 @@ otherwise -> 回复
|
||||
}
|
||||
```
|
||||
|
||||
注意:
|
||||
|
||||
- 群组/频道工具限制会在全局/智能体工具策略之外额外生效(`deny` 仍然优先生效)。
|
||||
- 某些渠道对房间/频道使用不同的嵌套方式(例如 Discord `guilds.*.channels.*`、Slack `channels.*`、Microsoft Teams `teams.*.channels.*`)。
|
||||
<Note>
|
||||
群组/频道工具限制会与全局/智能体工具策略一同应用(`deny` 仍然优先)。某些渠道对房间/频道使用不同的嵌套结构(例如 Discord `guilds.*.channels.*`、Slack `channels.*`、Microsoft Teams `teams.*.channels.*`)。
|
||||
</Note>
|
||||
|
||||
## 群组允许列表
|
||||
|
||||
当配置了 `channels.whatsapp.groups`、`channels.telegram.groups` 或 `channels.imessage.groups` 时,这些键会充当群组允许列表。使用 `"*"` 可以允许所有群组,同时仍然设置默认的提及行为。
|
||||
当配置了 `channels.whatsapp.groups`、`channels.telegram.groups` 或 `channels.imessage.groups` 时,这些键会充当群组允许列表。使用 `"*"` 可允许所有群组,同时仍设置默认提及行为。
|
||||
|
||||
常见混淆点:私信配对批准不等同于群组授权。
|
||||
对于支持私信配对的渠道,配对存储只会解锁私信。群组命令仍然需要通过配置允许列表进行显式的群组发送者授权,例如 `groupAllowFrom`,或该渠道文档中说明的配置回退方式。
|
||||
<Warning>
|
||||
常见混淆点:私信配对批准不等同于群组授权。对于支持私信配对的渠道,配对存储仅解锁私信。群组命令仍然需要配置允许列表中明确的群组发送者授权,例如 `groupAllowFrom`,或该渠道文档中说明的配置回退方式。
|
||||
</Warning>
|
||||
|
||||
常见意图(可直接复制粘贴):
|
||||
|
||||
1. 禁用所有群组回复
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: { whatsapp: { groupPolicy: "disabled" } },
|
||||
}
|
||||
```
|
||||
|
||||
2. 仅允许特定群组(WhatsApp)
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
whatsapp: {
|
||||
groups: {
|
||||
"123@g.us": { requireMention: true },
|
||||
"456@g.us": { requireMention: false },
|
||||
<Tabs>
|
||||
<Tab title="禁用所有群组回复">
|
||||
```json5
|
||||
{
|
||||
channels: { whatsapp: { groupPolicy: "disabled" } },
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="仅允许特定群组(WhatsApp)">
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
whatsapp: {
|
||||
groups: {
|
||||
"123@g.us": { requireMention: true },
|
||||
"456@g.us": { requireMention: false },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
3. 允许所有群组,但要求提及(显式设置)
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
whatsapp: {
|
||||
groups: { "*": { requireMention: true } },
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
4. 只有所有者可以在群组中触发(WhatsApp)
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
whatsapp: {
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["+15551234567"],
|
||||
groups: { "*": { requireMention: true } },
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="允许所有群组但要求提及">
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
whatsapp: {
|
||||
groups: { "*": { requireMention: true } },
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="仅所有者可触发(WhatsApp)">
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
whatsapp: {
|
||||
groupPolicy: "allowlist",
|
||||
groupAllowFrom: ["+15551234567"],
|
||||
groups: { "*": { requireMention: true } },
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## 激活(仅所有者)
|
||||
|
||||
@ -388,11 +415,11 @@ otherwise -> 回复
|
||||
- `/activation mention`
|
||||
- `/activation always`
|
||||
|
||||
所有者由 `channels.whatsapp.allowFrom` 决定(如果未设置,则使用机器人的自身 E.164)。请将该命令作为单独一条消息发送。其他界面当前会忽略 `/activation`。
|
||||
所有者由 `channels.whatsapp.allowFrom` 决定(如果未设置,则使用机器人的自身 E.164)。请将命令作为独立消息发送。其他渠道目前会忽略 `/activation`。
|
||||
|
||||
## 上下文字段
|
||||
|
||||
群组入站负载会设置:
|
||||
群组入站载荷会设置:
|
||||
|
||||
- `ChatType=group`
|
||||
- `GroupSubject`(如果已知)
|
||||
@ -400,29 +427,29 @@ otherwise -> 回复
|
||||
- `WasMentioned`(提及门控结果)
|
||||
- Telegram 论坛话题还会包含 `MessageThreadId` 和 `IsForum`。
|
||||
|
||||
渠道特定说明:
|
||||
特定渠道说明:
|
||||
|
||||
- BlueBubbles 可以在填充 `GroupMembers` 之前,选择性地从本地 Contacts 数据库中补全未命名的 macOS 群组参与者信息。此功能默认关闭,且仅会在常规群组门控通过后运行。
|
||||
- BlueBubbles 可以选择在填充 `GroupMembers` 之前,先从本地通讯录数据库中补充未命名的 macOS 群组参与者信息。此功能默认关闭,且仅在常规群组门控通过后才会运行。
|
||||
|
||||
智能体系统提示会在新群组会话的第一轮中包含一段群组简介。它会提醒模型像人类一样回复、避免使用 Markdown 表格、尽量减少空行并遵循正常聊天间距,同时避免输入字面量 `\n` 序列。来自渠道的群组名称和参与者标签会以带围栏的不受信任元数据形式呈现,而不是以内联系统指令的方式呈现。
|
||||
智能体系统提示会在新群组会话的第一轮包含一个群组介绍。它会提醒模型像真人一样回复、避免使用 Markdown 表格、尽量减少空行并遵循正常聊天间距,以及避免输入字面的 `\n` 序列。来自渠道的群组名称和参与者标签会被渲染为带围栏的不受信任元数据,而不是内联系统指令。
|
||||
|
||||
## iMessage 特定说明
|
||||
## iMessage 细节
|
||||
|
||||
- 在路由或加入允许列表时,优先使用 `chat_id:<id>`。
|
||||
- 在路由或允许列表中优先使用 `chat_id:<id>`。
|
||||
- 列出聊天:`imsg chats --limit 20`。
|
||||
- 群组回复始终会返回到相同的 `chat_id`。
|
||||
- 群组回复始终会发回同一个 `chat_id`。
|
||||
|
||||
## WhatsApp 系统提示
|
||||
|
||||
有关规范的 WhatsApp 系统提示规则,包括群组和私聊提示解析、通配符行为以及账号覆盖语义,请参见 [WhatsApp](/zh-CN/channels/whatsapp#system-prompts)。
|
||||
有关规范的 WhatsApp 系统提示规则,包括群组与私聊提示解析、通配符行为以及账号覆盖语义,请参见 [WhatsApp](/zh-CN/channels/whatsapp#system-prompts)。
|
||||
|
||||
## WhatsApp 特定说明
|
||||
## WhatsApp 细节
|
||||
|
||||
有关仅适用于 WhatsApp 的行为(历史注入、提及处理细节),请参见 [群组消息](/zh-CN/channels/group-messages)。
|
||||
有关仅适用于 WhatsApp 的行为(历史注入、提及处理细节),请参见 [群消息](/zh-CN/channels/group-messages)。
|
||||
|
||||
## 相关内容
|
||||
|
||||
- [群组消息](/zh-CN/channels/group-messages)
|
||||
- [广播群组](/zh-CN/channels/broadcast-groups)
|
||||
- [渠道路由](/zh-CN/channels/channel-routing)
|
||||
- [群消息](/zh-CN/channels/group-messages)
|
||||
- [配对](/zh-CN/channels/pairing)
|
||||
|
||||
@ -2,31 +2,31 @@
|
||||
read_when:
|
||||
- 你想将 OpenClaw 连接到 QQ
|
||||
- 你需要设置 QQ Bot 凭证
|
||||
- 你想要 QQ Bot 群聊或私信支持
|
||||
- 你想要 QQ Bot 群聊或私聊支持
|
||||
summary: QQ Bot 设置、配置和使用
|
||||
title: QQ Bot
|
||||
x-i18n:
|
||||
generated_at: "2026-04-26T03:53:16Z"
|
||||
generated_at: "2026-04-26T07:48:31Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: b2969d9cccd6561afeccf397841bbda7e86b7f21a0aafcf99ba78dbbb06eda39
|
||||
source_hash: bd899d9556ab418bbb3d7dc368e6f6e1eca96828cbcc87b4147ccad362f1918e
|
||||
source_path: channels/qqbot.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
QQ Bot 通过官方 QQ Bot API(WebSocket Gateway 网关)连接到 OpenClaw。该插件支持 C2C 私信、群组 @ 消息以及频道消息,并支持富媒体(图片、语音、视频、文件)。
|
||||
QQ Bot 通过官方 QQ Bot API(WebSocket Gateway 网关)连接到 OpenClaw。该插件支持 C2C 私聊、群 @消息,以及频道消息,并支持丰富媒体(图片、语音、视频、文件)。
|
||||
|
||||
Status:内置插件。支持私信、群聊、频道和媒体。不支持表情回应和话题串。
|
||||
Status:内置插件。支持私信、群聊、频道,以及媒体。不支持表情回应和主题帖。
|
||||
|
||||
## 内置插件
|
||||
|
||||
当前的 OpenClaw 发布版本已内置 QQ Bot,因此常规打包构建不需要单独执行 `openclaw plugins install` 步骤。
|
||||
当前的 OpenClaw 版本已内置 QQ Bot,因此普通打包构建不需要单独执行 `openclaw plugins install` 步骤。
|
||||
|
||||
## 设置
|
||||
|
||||
1. 前往 [QQ 开放平台](https://q.qq.com/),使用你手机上的 QQ 扫描二维码进行注册 / 登录。
|
||||
1. 前往 [QQ 开放平台](https://q.qq.com/),使用手机 QQ 扫描二维码进行注册 / 登录。
|
||||
2. 点击 **Create Bot** 创建一个新的 QQ 机器人。
|
||||
3. 在机器人的设置页面找到 **AppID** 和 **AppSecret** 并复制。
|
||||
3. 在机器人的设置页面找到 **AppID** 和 **AppSecret** 并复制它们。
|
||||
|
||||
> AppSecret 不会以明文存储——如果你离开页面前没有保存它,就必须重新生成一个新的。
|
||||
|
||||
@ -83,8 +83,8 @@ openclaw configure --section channels
|
||||
说明:
|
||||
|
||||
- 环境变量回退仅适用于默认 QQ Bot 账户。
|
||||
- `openclaw channels add --channel qqbot --token-file ...` 仅提供 AppSecret;AppID 必须已在配置中设置,或通过 `QQBOT_APP_ID` 提供。
|
||||
- `clientSecret` 也接受 SecretRef 输入,而不仅仅是明文字符串。
|
||||
- `openclaw channels add --channel qqbot --token-file ...` 只提供 AppSecret;AppID 必须已经在配置中设置,或通过 `QQBOT_APP_ID` 提供。
|
||||
- `clientSecret` 也接受 SecretRef 输入,不仅限于明文字符串。
|
||||
|
||||
### 多账户设置
|
||||
|
||||
@ -109,7 +109,7 @@ openclaw configure --section channels
|
||||
}
|
||||
```
|
||||
|
||||
每个账户都会启动各自的 WebSocket 连接,并维护独立的令牌缓存(按 `appId` 隔离)。
|
||||
每个账户都会启动各自独立的 WebSocket 连接,并维护独立的令牌缓存(按 `appId` 隔离)。
|
||||
|
||||
通过 CLI 添加第二个机器人:
|
||||
|
||||
@ -121,10 +121,10 @@ openclaw channels add --channel qqbot --account bot2 --token "222222222:secret-o
|
||||
|
||||
STT 和 TTS 支持两级配置,并带有优先级回退:
|
||||
|
||||
| 设置 | 插件专用 | 框架回退 |
|
||||
| ---- | -------------------- | ----------------------------- |
|
||||
| STT | `channels.qqbot.stt` | `tools.media.audio.models[0]` |
|
||||
| TTS | `channels.qqbot.tts` | `messages.tts` |
|
||||
| 设置 | 插件专用 | 框架回退 |
|
||||
| ------- | -------------------------------------------------------- | ----------------------------- |
|
||||
| STT | `channels.qqbot.stt` | `tools.media.audio.models[0]` |
|
||||
| TTS | `channels.qqbot.tts`, `channels.qqbot.accounts.<id>.tts` | `messages.tts` |
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -139,16 +139,26 @@ STT 和 TTS 支持两级配置,并带有优先级回退:
|
||||
model: "your-tts-model",
|
||||
voice: "your-voice",
|
||||
},
|
||||
accounts: {
|
||||
qq-main: {
|
||||
tts: {
|
||||
providers: {
|
||||
openai: { voice: "shimmer" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
将任一项设置为 `enabled: false` 可禁用对应功能。
|
||||
可在任一项上设置 `enabled: false` 以禁用。
|
||||
账户级 TTS 覆盖使用与 `messages.tts` 相同的结构,并会在渠道 / 全局 TTS 配置之上进行深度合并。
|
||||
|
||||
传入的 QQ 语音附件会以音频媒体元数据的形式暴露给智能体,同时将原始语音文件排除在通用 `MediaPaths` 之外。`[[audio_as_voice]]` 纯文本回复会合成 TTS,并在配置了 TTS 时发送原生 QQ 语音消息。
|
||||
传入的 QQ 语音附件会作为音频媒体元数据暴露给智能体,同时将原始语音文件排除在通用 `MediaPaths` 之外。`[[audio_as_voice]]` 纯文本回复会合成 TTS,并在配置了 TTS 时发送原生 QQ 语音消息。
|
||||
|
||||
出站音频的上传 / 转码行为也可通过 `channels.qqbot.audioFormatPolicy` 调整:
|
||||
出站音频的上传 / 转码行为也可以通过 `channels.qqbot.audioFormatPolicy` 调整:
|
||||
|
||||
- `sttDirectFormats`
|
||||
- `uploadDirectFormats`
|
||||
@ -156,56 +166,56 @@ STT 和 TTS 支持两级配置,并带有优先级回退:
|
||||
|
||||
## 目标格式
|
||||
|
||||
| 格式 | 描述 |
|
||||
| -------------------------- | ---------------- |
|
||||
| `qqbot:c2c:OPENID` | 私聊(C2C) |
|
||||
| `qqbot:group:GROUP_OPENID` | 群聊 |
|
||||
| `qqbot:channel:CHANNEL_ID` | 频道 |
|
||||
| 格式 | 描述 |
|
||||
| -------------------------- | ------------------ |
|
||||
| `qqbot:c2c:OPENID` | 私聊(C2C) |
|
||||
| `qqbot:group:GROUP_OPENID` | 群聊 |
|
||||
| `qqbot:channel:CHANNEL_ID` | 频道 |
|
||||
|
||||
> 每个机器人都有自己的一组用户 OpenID。由机器人 A 收到的 OpenID **不能** 用于通过机器人 B 发送消息。
|
||||
> 每个机器人都有自己的一组用户 OpenID。通过机器人 A 收到的 OpenID **不能** 用于通过机器人 B 发送消息。
|
||||
|
||||
## 斜杠命令
|
||||
|
||||
在 AI 队列之前拦截的内置命令:
|
||||
|
||||
| 命令 | 描述 |
|
||||
| -------------- | ------------------------------------------------------------------------------------------ |
|
||||
| `/bot-ping` | 延迟测试 |
|
||||
| `/bot-version` | 显示 OpenClaw 框架版本 |
|
||||
| `/bot-help` | 列出所有命令 |
|
||||
| `/bot-upgrade` | 显示 QQBot 升级指南链接 |
|
||||
| `/bot-logs` | 将最近的 Gateway 网关日志导出为文件 |
|
||||
| `/bot-approve` | 通过原生流程批准一个待处理的 QQ Bot 操作(例如确认一次 C2C 或群组上传)。 |
|
||||
| 命令 | 描述 |
|
||||
| -------------- | -------------------------------------------------------------------------------------------------------- |
|
||||
| `/bot-ping` | 延迟测试 |
|
||||
| `/bot-version` | 显示 OpenClaw 框架版本 |
|
||||
| `/bot-help` | 列出所有命令 |
|
||||
| `/bot-upgrade` | 显示 QQBot 升级指南链接 |
|
||||
| `/bot-logs` | 将最近的 Gateway 网关日志导出为文件 |
|
||||
| `/bot-approve` | 通过原生流程批准待处理的 QQ Bot 操作(例如确认 C2C 或群文件上传)。 |
|
||||
|
||||
在任意命令后追加 `?` 可查看用法帮助(例如 `/bot-upgrade ?`)。
|
||||
|
||||
## 引擎架构
|
||||
|
||||
QQ Bot 作为插件内的自包含引擎提供:
|
||||
QQ Bot 作为插件内部的自包含引擎提供:
|
||||
|
||||
- 每个账户都拥有独立的资源栈(WebSocket 连接、API 客户端、令牌缓存、媒体存储根目录),并以 `appId` 为键。账户之间绝不会共享入站 / 出站状态。
|
||||
- 多账户日志记录器会用所属账户标记日志行,因此当你在同一个 Gateway 网关下运行多个机器人时,诊断信息仍能清晰区分。
|
||||
- 入站、出站以及 Gateway 网关桥接路径共享 `~/.openclaw/media` 下的单一媒体负载根目录,因此上传、下载和转码缓存都会落在同一个受保护目录下,而不是分散到各子系统各自的目录树中。
|
||||
- 凭证可以作为标准 OpenClaw 凭证快照的一部分进行备份和恢复;恢复时,引擎会为每个账户重新附加其资源栈,而无需重新扫码配对。
|
||||
- 每个账户都拥有一个独立的资源栈(WebSocket 连接、API 客户端、令牌缓存、媒体存储根目录),并以 `appId` 为键。账户之间绝不会共享入站 / 出站状态。
|
||||
- 多账户日志记录器会为日志行标记所属账户,因此当你在一个 Gateway 网关下运行多个机器人时,诊断信息仍可区分。
|
||||
- 入站、出站和 Gateway 网关桥接路径共享 `~/.openclaw/media` 下的单一媒体负载根目录,因此上传、下载和转码缓存都会落在同一个受保护目录中,而不是按子系统分别存储。
|
||||
- 凭证可以作为标准 OpenClaw 凭证快照的一部分进行备份和恢复;引擎会在恢复时重新附加每个账户的资源栈,而无需重新进行二维码配对。
|
||||
|
||||
## 二维码新手引导
|
||||
|
||||
除了手动粘贴 `AppID:AppSecret` 之外,引擎还支持通过二维码新手引导流程将 QQ Bot 关联到 OpenClaw:
|
||||
除了手动粘贴 `AppID:AppSecret` 之外,该引擎还支持二维码新手引导流程,用于将 QQ Bot 关联到 OpenClaw:
|
||||
|
||||
1. 运行 QQ Bot 设置路径(例如 `openclaw channels add --channel qqbot`),并在提示时选择二维码流程。
|
||||
1. 运行 QQ Bot 设置流程(例如 `openclaw channels add --channel qqbot`),并在提示时选择二维码流程。
|
||||
2. 使用与目标 QQ Bot 绑定的手机应用扫描生成的二维码。
|
||||
3. 在手机上批准配对。OpenClaw 会将返回的凭证持久化到 `credentials/` 中对应的账户范围下。
|
||||
3. 在手机上批准配对。OpenClaw 会将返回的凭证持久化到 `credentials/` 中对应的账户作用域下。
|
||||
|
||||
由机器人自身生成的批准提示(例如 QQ Bot API 暴露的“允许此操作吗?”流程)会作为原生 OpenClaw 提示显示,你可以使用 `/bot-approve` 接受,而不必通过原始 QQ 客户端回复。
|
||||
由机器人本身生成的批准提示(例如 QQ Bot API 暴露的“允许此操作?”流程)会显示为原生 OpenClaw 提示,你可以使用 `/bot-approve` 接受,而不必通过原始 QQ 客户端回复。
|
||||
|
||||
## 故障排除
|
||||
|
||||
- **机器人回复“去了火星”:** 未配置凭证,或 Gateway 网关尚未启动。
|
||||
- **没有收到入站消息:** 验证 `appId` 和 `clientSecret` 是否正确,并确认机器人已在 QQ 开放平台启用。
|
||||
- **重复自我回复:** OpenClaw 会将 QQ 出站引用索引记录为机器人所发,并忽略当前 `msgIdx` 与同一机器人账户相匹配的入站事件。这样可以防止平台回显循环,同时仍允许用户引用或回复机器人之前的消息。
|
||||
- **使用 `--token-file` 设置后仍显示未配置:** `--token-file` 只会设置 AppSecret。你仍然需要在配置中设置 `appId`,或提供 `QQBOT_APP_ID`。
|
||||
- **主动消息未送达:** 如果用户最近没有交互,QQ 可能会拦截机器人主动发起的消息。
|
||||
- **语音未转写:** 确保已配置 STT,且提供商可访问。
|
||||
- **机器人回复“gone to Mars”:** 未配置凭证,或 Gateway 网关尚未启动。
|
||||
- **没有入站消息:** 验证 `appId` 和 `clientSecret` 是否正确,并确认机器人已在 QQ 开放平台启用。
|
||||
- **反复自我回复:** OpenClaw 会将 QQ 出站引用索引记录为机器人作者,并忽略当前 `msgIdx` 与该机器人账户相同的入站事件。这可防止平台回显循环,同时仍允许用户引用或回复机器人之前的消息。
|
||||
- **使用 `--token-file` 设置后仍显示未配置:** `--token-file` 只设置 AppSecret。你仍然需要在配置中设置 `appId`,或设置 `QQBOT_APP_ID`。
|
||||
- **主动消息未送达:** 如果用户最近没有互动,QQ 可能会拦截机器人主动发起的消息。
|
||||
- **语音未转写:** 请确认已配置 STT,且提供商可访问。
|
||||
|
||||
## 相关内容
|
||||
|
||||
|
||||
@ -1,36 +1,27 @@
|
||||
---
|
||||
read_when:
|
||||
- 你想以非交互方式读取或编辑配置。
|
||||
sidebarTitle: Config
|
||||
summary: '`openclaw config` 的 CLI 参考(get/set/unset/file/schema/validate)'
|
||||
title: 配置
|
||||
x-i18n:
|
||||
generated_at: "2026-04-25T05:53:10Z"
|
||||
generated_at: "2026-04-26T07:48:29Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 60567d39174d7214461f995d32f3064777d7437ff82226961eab404cd7fec5c4
|
||||
source_hash: 7871ee03a1da6ab5d0881ace7579ce101a89e9f9d05d1a720ff34fd31fa12a9d
|
||||
source_path: cli/config.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw config`
|
||||
用于在 `openclaw.json` 中进行非交互式编辑的配置辅助命令:按路径获取/设置/取消设置/file/schema/validate 值,并打印当前活动配置文件。不带子命令运行时,会打开配置向导(与 `openclaw configure` 相同)。
|
||||
|
||||
用于在 `openclaw.json` 中进行非交互式编辑的配置辅助命令:按路径获取/设置/取消设置/file/schema/validate 值,并打印当前生效的配置文件。不带子命令运行时,将打开配置向导(与 `openclaw configure` 相同)。
|
||||
## 根选项
|
||||
|
||||
根选项:
|
||||
<ParamField path="--section <section>" type="string">
|
||||
当你在不带子命令的情况下运行 `openclaw config` 时,可重复的引导式设置分区过滤器。
|
||||
</ParamField>
|
||||
|
||||
- `--section <section>`:当你在不带子命令的情况下运行 `openclaw config` 时,可重复使用的引导式设置分区过滤器
|
||||
|
||||
支持的引导式分区:
|
||||
|
||||
- `workspace`
|
||||
- `model`
|
||||
- `web`
|
||||
- `gateway`
|
||||
- `daemon`
|
||||
- `channels`
|
||||
- `plugins`
|
||||
- `skills`
|
||||
- `health`
|
||||
支持的引导分区:`workspace`、`model`、`web`、`gateway`、`daemon`、`channels`、`plugins`、`skills`、`health`。
|
||||
|
||||
## 示例
|
||||
|
||||
@ -55,26 +46,27 @@ openclaw config validate --json
|
||||
|
||||
### `config schema`
|
||||
|
||||
将 `openclaw.json` 的生成式 JSON schema 以 JSON 形式输出到 stdout。
|
||||
将 `openclaw.json` 的生成 JSON schema 以 JSON 形式输出到 stdout。
|
||||
|
||||
它包含的内容:
|
||||
|
||||
- 当前的根配置 schema,以及一个用于编辑器工具的根 `$schema` 字符串字段
|
||||
- Control UI 使用的字段 `title` 和 `description` 文档元数据
|
||||
- 当存在匹配的字段文档时,嵌套对象、通配符(`*`)和数组项(`[]`)节点会继承相同的 `title` / `description` 元数据
|
||||
- 当存在匹配的字段文档时,`anyOf` / `oneOf` / `allOf` 分支也会继承相同的文档元数据
|
||||
- 当能够加载运行时清单时,尽力提供实时的插件 + 渠道 schema 元数据
|
||||
- 即使当前配置无效,也会提供一个干净的回退 schema
|
||||
|
||||
相关的运行时 RPC:
|
||||
|
||||
- `config.schema.lookup` 返回一个标准化的配置路径,以及一个浅层 schema 节点(`title`、`description`、`type`、`enum`、`const`、常见边界)、匹配的 UI 提示元数据和直接子节点摘要。可将其用于 Control UI 或自定义客户端中的按路径逐层深入查看。
|
||||
<AccordionGroup>
|
||||
<Accordion title="包含内容">
|
||||
- 当前的根配置 schema,以及用于编辑器工具的根 `$schema` 字符串字段。
|
||||
- Control UI 使用的字段 `title` 和 `description` 文档元数据。
|
||||
- 当存在匹配字段文档时,嵌套对象、通配符(`*`)和数组项(`[]`)节点会继承相同的 `title` / `description` 元数据。
|
||||
- 当存在匹配字段文档时,`anyOf` / `oneOf` / `allOf` 分支也会继承相同的文档元数据。
|
||||
- 当能够加载运行时清单时,尽力提供实时的插件 + 渠道 schema 元数据。
|
||||
- 即使当前配置无效,也会提供一个干净的后备 schema。
|
||||
</Accordion>
|
||||
<Accordion title="相关运行时 RPC">
|
||||
`config.schema.lookup` 会返回一个规范化的配置路径、一个浅层 schema 节点(`title`、`description`、`type`、`enum`、`const`、常见边界)、匹配的 UI 提示元数据,以及直接子项摘要。可将它用于 Control UI 或自定义客户端中的按路径范围逐层深入查看。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
```bash
|
||||
openclaw config schema
|
||||
```
|
||||
|
||||
如果你想用其他工具检查或验证它,可以将其输出到文件:
|
||||
当你想用其他工具检查或验证它时,可以将其通过管道输出到文件中:
|
||||
|
||||
```bash
|
||||
openclaw config schema > openclaw.schema.json
|
||||
@ -82,7 +74,7 @@ openclaw config schema > openclaw.schema.json
|
||||
|
||||
### 路径
|
||||
|
||||
路径支持点表示法或方括号表示法:
|
||||
路径使用点号或方括号表示法:
|
||||
|
||||
```bash
|
||||
openclaw config get agents.defaults.workspace
|
||||
@ -98,7 +90,7 @@ openclaw config set agents.list[1].tools.exec.node "node-id-or-name"
|
||||
|
||||
## 值
|
||||
|
||||
值会尽可能按 JSON5 解析;否则会被视为字符串。使用 `--strict-json` 可强制要求 JSON5 解析。`--json` 仍作为旧版别名受支持。
|
||||
值会在可能的情况下按 JSON5 解析;否则会被视为字符串。使用 `--strict-json` 可强制要求进行 JSON5 解析。`--json` 仍然支持,作为旧版别名保留。
|
||||
|
||||
```bash
|
||||
openclaw config set agents.defaults.heartbeat.every "0m"
|
||||
@ -106,9 +98,11 @@ openclaw config set gateway.port 19001 --strict-json
|
||||
openclaw config set channels.whatsapp.groups '["*"]' --strict-json
|
||||
```
|
||||
|
||||
`config get <path> --json` 会将原始值作为 JSON 输出,而不是终端格式化文本。
|
||||
`config get <path> --json` 会将原始值按 JSON 输出,而不是输出终端格式化文本。
|
||||
|
||||
对象赋值默认会替换目标路径。对于通常保存用户新增条目的受保护映射/列表路径,例如 `agents.defaults.models`、`models.providers`、`models.providers.<id>.models`、`plugins.entries` 和 `auth.profiles`,如果替换会移除现有条目,则会拒绝,除非你传入 `--replace`。
|
||||
<Note>
|
||||
默认情况下,对象赋值会替换目标路径。对于常见的、通常保存用户新增条目的受保护映射/列表路径,例如 `agents.defaults.models`、`models.providers`、`models.providers.<id>.models`、`plugins.entries` 和 `auth.profiles`,如果替换会移除现有条目,则会被拒绝,除非你传入 `--replace`。
|
||||
</Note>
|
||||
|
||||
向这些映射中添加条目时,请使用 `--merge`:
|
||||
|
||||
@ -123,54 +117,61 @@ openclaw config set models.providers.ollama.models '[{"id":"llama3.2","name":"Ll
|
||||
|
||||
`openclaw config set` 支持四种赋值方式:
|
||||
|
||||
1. 值模式:`openclaw config set <path> <value>`
|
||||
2. SecretRef 构建器模式:
|
||||
<Tabs>
|
||||
<Tab title="值模式">
|
||||
```bash
|
||||
openclaw config set <path> <value>
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="SecretRef 构建器模式">
|
||||
```bash
|
||||
openclaw config set channels.discord.token \
|
||||
--ref-provider default \
|
||||
--ref-source env \
|
||||
--ref-id DISCORD_BOT_TOKEN
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="提供商构建器模式">
|
||||
提供商构建器模式仅以 `secrets.providers.<alias>` 路径为目标:
|
||||
|
||||
```bash
|
||||
openclaw config set channels.discord.token \
|
||||
--ref-provider default \
|
||||
--ref-source env \
|
||||
--ref-id DISCORD_BOT_TOKEN
|
||||
```
|
||||
```bash
|
||||
openclaw config set secrets.providers.vault \
|
||||
--provider-source exec \
|
||||
--provider-command /usr/local/bin/openclaw-vault \
|
||||
--provider-arg read \
|
||||
--provider-arg openai/api-key \
|
||||
--provider-timeout-ms 5000
|
||||
```
|
||||
|
||||
3. 提供商构建器模式(仅限 `secrets.providers.<alias>` 路径):
|
||||
</Tab>
|
||||
<Tab title="批量模式">
|
||||
```bash
|
||||
openclaw config set --batch-json '[
|
||||
{
|
||||
"path": "secrets.providers.default",
|
||||
"provider": { "source": "env" }
|
||||
},
|
||||
{
|
||||
"path": "channels.discord.token",
|
||||
"ref": { "source": "env", "provider": "default", "id": "DISCORD_BOT_TOKEN" }
|
||||
}
|
||||
]'
|
||||
```
|
||||
|
||||
```bash
|
||||
openclaw config set secrets.providers.vault \
|
||||
--provider-source exec \
|
||||
--provider-command /usr/local/bin/openclaw-vault \
|
||||
--provider-arg read \
|
||||
--provider-arg openai/api-key \
|
||||
--provider-timeout-ms 5000
|
||||
```
|
||||
```bash
|
||||
openclaw config set --batch-file ./config-set.batch.json --dry-run
|
||||
```
|
||||
|
||||
4. 批处理模式(`--batch-json` 或 `--batch-file`):
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
```bash
|
||||
openclaw config set --batch-json '[
|
||||
{
|
||||
"path": "secrets.providers.default",
|
||||
"provider": { "source": "env" }
|
||||
},
|
||||
{
|
||||
"path": "channels.discord.token",
|
||||
"ref": { "source": "env", "provider": "default", "id": "DISCORD_BOT_TOKEN" }
|
||||
}
|
||||
]'
|
||||
```
|
||||
<Warning>
|
||||
在不支持运行时可变更的表面上,SecretRef 赋值会被拒绝(例如 `hooks.token`、`commands.ownerDisplaySecret`、Discord 线程绑定 webhook token,以及 WhatsApp creds JSON)。参见 [SecretRef Credential Surface](/zh-CN/reference/secretref-credential-surface)。
|
||||
</Warning>
|
||||
|
||||
```bash
|
||||
openclaw config set --batch-file ./config-set.batch.json --dry-run
|
||||
```
|
||||
批量解析始终将批量载荷(`--batch-json`/`--batch-file`)作为事实来源。`--strict-json` / `--json` 不会改变批量解析行为。
|
||||
|
||||
策略说明:
|
||||
|
||||
- 对不支持运行时可变更的目标面进行 SecretRef 赋值会被拒绝(例如 `hooks.token`、`commands.ownerDisplaySecret`、Discord 线程绑定 webhook token,以及 WhatsApp 凭证 JSON)。参见 [SecretRef Credential Surface](/zh-CN/reference/secretref-credential-surface)。
|
||||
|
||||
批处理解析始终将批处理载荷(`--batch-json`/`--batch-file`)作为唯一真实来源。
|
||||
`--strict-json` / `--json` 不会改变批处理解析行为。
|
||||
|
||||
JSON 路径/值模式对 SecretRef 和提供商同样受支持:
|
||||
对 SecretRef 和提供商,也仍然支持 JSON 路径/值模式:
|
||||
|
||||
```bash
|
||||
openclaw config set channels.discord.token \
|
||||
@ -186,36 +187,35 @@ openclaw config set secrets.providers.vaultfile \
|
||||
|
||||
提供商构建器目标路径必须使用 `secrets.providers.<alias>`。
|
||||
|
||||
通用标志:
|
||||
<AccordionGroup>
|
||||
<Accordion title="通用标志">
|
||||
- `--provider-source <env|file|exec>`
|
||||
- `--provider-timeout-ms <ms>`(`file`、`exec`)
|
||||
</Accordion>
|
||||
<Accordion title="Env 提供商(--provider-source env)">
|
||||
- `--provider-allowlist <ENV_VAR>`(可重复)
|
||||
</Accordion>
|
||||
<Accordion title="文件提供商(--provider-source file)">
|
||||
- `--provider-path <path>`(必需)
|
||||
- `--provider-mode <singleValue|json>`
|
||||
- `--provider-max-bytes <bytes>`
|
||||
- `--provider-allow-insecure-path`
|
||||
</Accordion>
|
||||
<Accordion title="Exec 提供商(--provider-source exec)">
|
||||
- `--provider-command <path>`(必需)
|
||||
- `--provider-arg <arg>`(可重复)
|
||||
- `--provider-no-output-timeout-ms <ms>`
|
||||
- `--provider-max-output-bytes <bytes>`
|
||||
- `--provider-json-only`
|
||||
- `--provider-env <KEY=VALUE>`(可重复)
|
||||
- `--provider-pass-env <ENV_VAR>`(可重复)
|
||||
- `--provider-trusted-dir <path>`(可重复)
|
||||
- `--provider-allow-insecure-path`
|
||||
- `--provider-allow-symlink-command`
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
- `--provider-source <env|file|exec>`
|
||||
- `--provider-timeout-ms <ms>`(`file`、`exec`)
|
||||
|
||||
Env 提供商(`--provider-source env`):
|
||||
|
||||
- `--provider-allowlist <ENV_VAR>`(可重复)
|
||||
|
||||
文件提供商(`--provider-source file`):
|
||||
|
||||
- `--provider-path <path>`(必需)
|
||||
- `--provider-mode <singleValue|json>`
|
||||
- `--provider-max-bytes <bytes>`
|
||||
- `--provider-allow-insecure-path`
|
||||
|
||||
Exec 提供商(`--provider-source exec`):
|
||||
|
||||
- `--provider-command <path>`(必需)
|
||||
- `--provider-arg <arg>`(可重复)
|
||||
- `--provider-no-output-timeout-ms <ms>`
|
||||
- `--provider-max-output-bytes <bytes>`
|
||||
- `--provider-json-only`
|
||||
- `--provider-env <KEY=VALUE>`(可重复)
|
||||
- `--provider-pass-env <ENV_VAR>`(可重复)
|
||||
- `--provider-trusted-dir <path>`(可重复)
|
||||
- `--provider-allow-insecure-path`
|
||||
- `--provider-allow-symlink-command`
|
||||
|
||||
加固的 exec 提供商示例:
|
||||
加固后的 exec 提供商示例:
|
||||
|
||||
```bash
|
||||
openclaw config set secrets.providers.vault \
|
||||
@ -229,7 +229,7 @@ openclaw config set secrets.providers.vault \
|
||||
--provider-timeout-ms 5000
|
||||
```
|
||||
|
||||
## Dry run
|
||||
## 试运行
|
||||
|
||||
使用 `--dry-run` 可在不写入 `openclaw.json` 的情况下验证更改。
|
||||
|
||||
@ -255,25 +255,29 @@ openclaw config set channels.discord.token \
|
||||
--allow-exec
|
||||
```
|
||||
|
||||
dry-run 行为:
|
||||
<AccordionGroup>
|
||||
<Accordion title="试运行行为">
|
||||
- 构建器模式:对已更改的 ref/提供商运行 SecretRef 可解析性检查。
|
||||
- JSON 模式(`--strict-json`、`--json` 或批量模式):运行 schema 验证以及 SecretRef 可解析性检查。
|
||||
- 对已知不支持的 SecretRef 目标表面,也会运行策略验证。
|
||||
- 策略检查会评估更改后的完整配置,因此对父对象的写入(例如将 `hooks` 设置为对象)无法绕过不支持表面验证。
|
||||
- 为避免命令副作用,试运行期间默认跳过 Exec SecretRef 检查。
|
||||
- 将 `--allow-exec` 与 `--dry-run` 一起使用,可选择启用 exec SecretRef 检查(这可能会执行提供商命令)。
|
||||
- `--allow-exec` 仅适用于试运行;如果未配合 `--dry-run` 使用,则会报错。
|
||||
</Accordion>
|
||||
<Accordion title="--dry-run --json 字段">
|
||||
`--dry-run --json` 会输出机器可读报告:
|
||||
|
||||
- 构建器模式:对已更改的 ref/提供商运行 SecretRef 可解析性检查。
|
||||
- JSON 模式(`--strict-json`、`--json` 或批处理模式):运行 schema 验证以及 SecretRef 可解析性检查。
|
||||
- 也会对已知不受支持的 SecretRef 目标面运行策略验证。
|
||||
- 策略检查会基于变更后的完整配置进行评估,因此写入父对象(例如将 `hooks` 设置为对象)无法绕过对不受支持目标面的验证。
|
||||
- 默认情况下,dry-run 会跳过 exec SecretRef 检查,以避免命令副作用。
|
||||
- 如需启用 exec SecretRef 检查,请在 `--dry-run` 时配合使用 `--allow-exec`(这可能会执行提供商命令)。
|
||||
- `--allow-exec` 仅用于 dry-run;如果在未使用 `--dry-run` 时传入,则会报错。
|
||||
- `ok`:试运行是否通过
|
||||
- `operations`:已评估的赋值操作数量
|
||||
- `checks`:是否运行了 schema/可解析性检查
|
||||
- `checks.resolvabilityComplete`:可解析性检查是否已完整运行(当跳过 exec refs 时为 false)
|
||||
- `refsChecked`:试运行期间实际已解析的 ref 数量
|
||||
- `skippedExecRefs`:因未设置 `--allow-exec` 而跳过的 exec ref 数量
|
||||
- `errors`:当 `ok=false` 时的结构化 schema/可解析性失败信息
|
||||
|
||||
`--dry-run --json` 会输出机器可读报告:
|
||||
|
||||
- `ok`:dry-run 是否通过
|
||||
- `operations`:已评估的赋值操作数量
|
||||
- `checks`:是否运行了 schema/可解析性检查
|
||||
- `checks.resolvabilityComplete`:可解析性检查是否完整执行(当跳过 exec ref 时为 false)
|
||||
- `refsChecked`:dry-run 期间实际解析的 ref 数量
|
||||
- `skippedExecRefs`:由于未设置 `--allow-exec` 而跳过的 exec ref 数量
|
||||
- `errors`:当 `ok=false` 时,结构化的 schema/可解析性失败信息
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### JSON 输出结构
|
||||
|
||||
@ -294,70 +298,75 @@ dry-run 行为:
|
||||
{
|
||||
kind: "schema" | "resolvability",
|
||||
message: string,
|
||||
ref?: string, // 对于可解析性错误时会出现
|
||||
ref?: string, // 仅在可解析性错误中出现
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
成功示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"operations": 1,
|
||||
"configPath": "~/.openclaw/openclaw.json",
|
||||
"inputModes": ["builder"],
|
||||
"checks": {
|
||||
"schema": false,
|
||||
"resolvability": true,
|
||||
"resolvabilityComplete": true
|
||||
},
|
||||
"refsChecked": 1,
|
||||
"skippedExecRefs": 0
|
||||
}
|
||||
```
|
||||
|
||||
失败示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": false,
|
||||
"operations": 1,
|
||||
"configPath": "~/.openclaw/openclaw.json",
|
||||
"inputModes": ["builder"],
|
||||
"checks": {
|
||||
"schema": false,
|
||||
"resolvability": true,
|
||||
"resolvabilityComplete": true
|
||||
},
|
||||
"refsChecked": 1,
|
||||
"skippedExecRefs": 0,
|
||||
"errors": [
|
||||
<Tabs>
|
||||
<Tab title="成功示例">
|
||||
```json
|
||||
{
|
||||
"kind": "resolvability",
|
||||
"message": "Error: Environment variable \"MISSING_TEST_SECRET\" is not set.",
|
||||
"ref": "env:default:MISSING_TEST_SECRET"
|
||||
"ok": true,
|
||||
"operations": 1,
|
||||
"configPath": "~/.openclaw/openclaw.json",
|
||||
"inputModes": ["builder"],
|
||||
"checks": {
|
||||
"schema": false,
|
||||
"resolvability": true,
|
||||
"resolvabilityComplete": true
|
||||
},
|
||||
"refsChecked": 1,
|
||||
"skippedExecRefs": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="失败示例">
|
||||
```json
|
||||
{
|
||||
"ok": false,
|
||||
"operations": 1,
|
||||
"configPath": "~/.openclaw/openclaw.json",
|
||||
"inputModes": ["builder"],
|
||||
"checks": {
|
||||
"schema": false,
|
||||
"resolvability": true,
|
||||
"resolvabilityComplete": true
|
||||
},
|
||||
"refsChecked": 1,
|
||||
"skippedExecRefs": 0,
|
||||
"errors": [
|
||||
{
|
||||
"kind": "resolvability",
|
||||
"message": "Error: Environment variable \"MISSING_TEST_SECRET\" is not set.",
|
||||
"ref": "env:default:MISSING_TEST_SECRET"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
如果 dry-run 失败:
|
||||
|
||||
- `config schema validation failed`:你的变更后配置结构无效;请修正路径/值或提供商/ref 对象结构。
|
||||
- `Config policy validation failed: unsupported SecretRef usage`:请将该凭证移回明文/字符串输入,并仅在受支持的目标面上使用 SecretRef。
|
||||
- `SecretRef assignment(s) could not be resolved`:当前无法解析所引用的提供商/ref(缺少环境变量、文件指针无效、exec 提供商失败,或提供商/source 不匹配)。
|
||||
- `Dry run note: skipped <n> exec SecretRef resolvability check(s)`:dry-run 跳过了 exec ref;如果你需要验证 exec 可解析性,请使用 `--allow-exec` 重新运行。
|
||||
- 对于批处理模式,请修复失败的条目,然后在写入前重新运行 `--dry-run`。
|
||||
<AccordionGroup>
|
||||
<Accordion title="如果试运行失败">
|
||||
- `config schema validation failed`:你更改后的配置结构无效;请修正路径/值或 provider/ref 对象结构。
|
||||
- `Config policy validation failed: unsupported SecretRef usage`:请将该凭证移回明文/字符串输入,并仅在受支持的表面上使用 SecretRefs。
|
||||
- `SecretRef assignment(s) could not be resolved`:当前无法解析所引用的 provider/ref(缺少环境变量、文件指针无效、exec provider 失败,或 provider/source 不匹配)。
|
||||
- `Dry run note: skipped <n> exec SecretRef resolvability check(s)`:试运行跳过了 exec refs;如果你需要验证 exec 可解析性,请使用 `--allow-exec` 重新运行。
|
||||
- 对于批量模式,请修复失败的条目,并在写入前重新运行 `--dry-run`。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 写入安全
|
||||
|
||||
`openclaw config set` 和其他由 OpenClaw 管理的配置写入器,会在提交到磁盘前验证变更后的完整配置。如果新载荷未通过 schema 验证,或看起来像是破坏性的覆盖,当前生效配置将保持不变,且被拒绝的载荷会保存在其旁边,命名为 `openclaw.json.rejected.*`。
|
||||
当前生效的配置路径必须是常规文件。对于符号链接的 `openclaw.json`
|
||||
布局,不支持写入;请改用 `OPENCLAW_CONFIG_PATH` 直接指向真实文件。
|
||||
`openclaw config set` 和其他由 OpenClaw 管理的配置写入器,会在将完整的更改后配置提交到磁盘前进行验证。如果新载荷未通过 schema 验证,或看起来像是破坏性覆盖,则当前活动配置会保持不变,被拒绝的载荷会作为 `openclaw.json.rejected.*` 保存在其旁边。
|
||||
|
||||
对于小范围编辑,优先使用 CLI 写入:
|
||||
<Warning>
|
||||
活动配置路径必须是常规文件。不支持对符号链接形式的 `openclaw.json` 布局进行写入;请改用 `OPENCLAW_CONFIG_PATH` 直接指向真实文件。
|
||||
</Warning>
|
||||
|
||||
对于小幅修改,优先使用 CLI 写入:
|
||||
|
||||
```bash
|
||||
openclaw config set gateway.reload.mode hybrid --dry-run
|
||||
@ -365,7 +374,7 @@ openclaw config set gateway.reload.mode hybrid
|
||||
openclaw config validate
|
||||
```
|
||||
|
||||
如果写入被拒绝,请检查保存的载荷,并修正完整配置结构:
|
||||
如果写入被拒绝,请检查已保存的载荷并修复完整配置结构:
|
||||
|
||||
```bash
|
||||
CONFIG="$(openclaw config file)"
|
||||
@ -373,34 +382,36 @@ ls -lt "$CONFIG".rejected.* 2>/dev/null | head
|
||||
openclaw config validate
|
||||
```
|
||||
|
||||
仍然允许直接通过编辑器写入,但正在运行的 Gateway 网关 会在这些更改通过验证前将其视为不受信任。在启动或热重载期间,无效的直接编辑可能会从最后一次已知有效备份中恢复。参见 [Gateway 网关故障排除](/zh-CN/gateway/troubleshooting#gateway-restored-last-known-good-config)。
|
||||
仍然允许直接通过编辑器写入,但运行中的 Gateway 网关会在其通过验证之前将其视为不受信任。无效的直接编辑可能会在启动或热重载期间,从最后一次已知有效备份中恢复。参见 [Gateway 故障排除](/zh-CN/gateway/troubleshooting#gateway-restored-last-known-good-config)。
|
||||
|
||||
整文件恢复仅保留给全局损坏的配置,例如解析错误、根级 schema 失败、旧版迁移失败,或插件与根级配置混合失败。如果验证仅在 `plugins.entries.<id>...` 下失败,OpenClaw 会保持当前生效的 `openclaw.json` 不变,并报告插件本地问题,而不是恢复 `.last-good`。这可防止插件 schema 变更或 `minHostVersion` 不匹配导致回滚与你无关的用户设置,例如模型、提供商、auth 配置文件、渠道、Gateway 网关暴露设置、工具、内存、浏览器或 cron 配置。
|
||||
整文件恢复仅用于全局损坏的配置,例如解析错误、根级 schema 失败、旧版迁移失败,或插件与根配置混合失败。如果验证仅在 `plugins.entries.<id>...` 下失败,OpenClaw 会保留当前活动的 `openclaw.json`,并报告插件本地问题,而不是恢复 `.last-good`。这可防止插件 schema 变更或 `minHostVersion` 偏差回滚无关的用户设置,例如模型、提供商、认证配置文件、渠道、Gateway 网关暴露、工具、memory、浏览器或 cron 配置。
|
||||
|
||||
## 子命令
|
||||
|
||||
- `config file`:打印当前生效的配置文件路径(从 `OPENCLAW_CONFIG_PATH` 或默认位置解析)。该路径应指向常规文件,而不是符号链接。
|
||||
- `config file`:打印当前活动配置文件路径(从 `OPENCLAW_CONFIG_PATH` 或默认位置解析)。该路径应指向常规文件,而不是符号链接。
|
||||
|
||||
编辑后请重启网关。
|
||||
|
||||
## 验证
|
||||
|
||||
在不启动 Gateway 网关 的情况下,使用当前生效的 schema 验证当前配置。
|
||||
在不启动网关的情况下,根据当前活动 schema 验证当前配置。
|
||||
|
||||
```bash
|
||||
openclaw config validate
|
||||
openclaw config validate --json
|
||||
```
|
||||
|
||||
在 `openclaw config validate` 通过后,你可以使用本地 TUI,让内嵌智能体在你从同一个终端验证每项更改时,对照文档比较当前生效配置。
|
||||
当 `openclaw config validate` 通过后,你可以使用本地 TUI,让内嵌智能体在同一个终端中对照文档比较当前活动配置,并验证每一项更改:
|
||||
|
||||
如果验证已经失败,请先使用 `openclaw configure` 或 `openclaw doctor --fix`。`openclaw chat` 不会绕过无效配置保护。
|
||||
<Note>
|
||||
如果验证已经失败,请先从 `openclaw configure` 或 `openclaw doctor --fix` 开始。`openclaw chat` 不会绕过无效配置保护。
|
||||
</Note>
|
||||
|
||||
```bash
|
||||
openclaw chat
|
||||
```
|
||||
|
||||
然后在 TUI 中:
|
||||
然后在 TUI 内部:
|
||||
|
||||
```text
|
||||
!openclaw config file
|
||||
@ -409,12 +420,22 @@ openclaw chat
|
||||
!openclaw doctor
|
||||
```
|
||||
|
||||
典型修复循环:
|
||||
典型修复流程:
|
||||
|
||||
- 请智能体将你当前的配置与相关文档页面进行比较,并建议最小修复方案。
|
||||
- 使用 `openclaw config set` 或 `openclaw configure` 应用有针对性的编辑。
|
||||
- 每次更改后重新运行 `openclaw config validate`。
|
||||
- 如果验证通过但运行时仍不健康,请运行 `openclaw doctor` 或 `openclaw doctor --fix` 以获取迁移和修复帮助。
|
||||
<Steps>
|
||||
<Step title="与文档比对">
|
||||
让智能体将你当前的配置与相关文档页面进行比较,并建议最小修复方案。
|
||||
</Step>
|
||||
<Step title="应用定向编辑">
|
||||
使用 `openclaw config set` 或 `openclaw configure` 应用定向编辑。
|
||||
</Step>
|
||||
<Step title="重新验证">
|
||||
每次更改后重新运行 `openclaw config validate`。
|
||||
</Step>
|
||||
<Step title="使用 Doctor 处理运行时问题">
|
||||
如果验证通过但运行时仍不健康,请运行 `openclaw doctor` 或 `openclaw doctor --fix` 以获取迁移和修复帮助。
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## 相关内容
|
||||
|
||||
|
||||
@ -1,40 +1,42 @@
|
||||
---
|
||||
read_when:
|
||||
- 你在不带任何命令的情况下运行 `openclaw`,并且想了解 Crestodian
|
||||
- 你需要一种无需配置且安全的方式来检查或修复 OpenClaw
|
||||
- 你需要一种无配置且安全的方式来检查或修复 OpenClaw
|
||||
- 你正在设计或启用消息渠道救援模式
|
||||
summary: Crestodian 的 CLI 参考和安全模型,即无需配置且安全的设置与修复助手
|
||||
summary: Crestodian 的 CLI 参考和安全模型,这是一个无配置且安全的设置与修复辅助工具
|
||||
title: Crestodian
|
||||
x-i18n:
|
||||
generated_at: "2026-04-26T01:02:55Z"
|
||||
generated_at: "2026-04-26T07:48:33Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 28a613f828d5dfd5bd83c46f822639a06573aaabd23f3085603dca718cf8489c
|
||||
source_hash: aafa46de3c2df2ec4b0b16a0955bb9afc76df92d5ebb928077bb5007118e037c
|
||||
source_path: cli/crestodian.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw crestodian`
|
||||
|
||||
Crestodian 是 OpenClaw 的本地设置、修复和配置助手。它的设计目标是在正常的智能体路径出现故障时,仍然能够访问。
|
||||
Crestodian 是 OpenClaw 的本地设置、修复和配置辅助工具。它被设计为在正常智能体路径损坏时仍可访问。
|
||||
|
||||
在不带任何命令的情况下运行 `openclaw` 会以交互式终端启动 Crestodian。运行 `openclaw crestodian` 则会显式启动同一个助手。
|
||||
在不带任何命令的情况下运行 `openclaw` 会在交互式终端中启动 Crestodian。
|
||||
运行 `openclaw crestodian` 会显式启动同一个辅助工具。
|
||||
|
||||
## Crestodian 会显示什么
|
||||
|
||||
启动时,交互式 Crestodian 会打开与 `openclaw tui` 相同的 TUI shell,但使用 Crestodian 聊天后端。聊天日志会以简短的问候开头:
|
||||
启动时,交互式 Crestodian 会打开与 `openclaw tui` 相同的 TUI shell,但使用 Crestodian 聊天后端。聊天日志会以简短的问候开始:
|
||||
|
||||
- 何时应启动 Crestodian
|
||||
- Crestodian 实际正在使用的模型或确定性规划器路径
|
||||
- 何时启动 Crestodian
|
||||
- Crestodian 实际使用的模型或确定性规划器路径
|
||||
- 配置有效性和默认智能体
|
||||
- 首次启动探测得到的 Gateway 网关可达性
|
||||
- Crestodian 可以执行的下一步调试操作
|
||||
- 来自首次启动探测的 Gateway 网关 可达性
|
||||
- Crestodian 接下来可以执行的调试操作
|
||||
|
||||
它不会为了启动就转储密钥,也不会加载插件 CLI 命令。TUI 仍然提供常规的页眉、聊天日志、状态行、页脚、自动补全和编辑器控件。
|
||||
它不会为了启动而转储密钥,也不会加载插件 CLI 命令。TUI 仍然提供常规的页眉、聊天日志、状态行、页脚、自动补全和编辑器控件。
|
||||
|
||||
使用 `status` 可查看详细清单,其中包括配置路径、文档 / 源码路径、本地 CLI 探测、API 密钥是否存在、智能体、模型以及 Gateway 网关详情。
|
||||
使用 `status` 可查看详细清单,其中包括配置路径、文档/源码路径、本地 CLI 探测、API 密钥存在情况、智能体、模型以及 Gateway 网关 详情。
|
||||
|
||||
Crestodian 使用与常规智能体相同的 OpenClaw 参考发现机制。在 Git 检出中,它会将自己指向本地 `docs/` 和本地源码树。在 npm 包安装中,它会使用随包提供的文档,并链接到 [https://github.com/openclaw/openclaw](https://github.com/openclaw/openclaw),同时明确提示你在文档不足时查阅源码。
|
||||
Crestodian 使用与常规智能体相同的 OpenClaw 参考发现机制。在 Git 检出中,它会将自己指向本地 `docs/` 和本地源码树。在 npm 包安装中,它会使用打包附带的文档,并链接到
|
||||
[https://github.com/openclaw/openclaw](https://github.com/openclaw/openclaw),同时明确提示在文档不足时查看源码。
|
||||
|
||||
## 示例
|
||||
|
||||
@ -75,41 +77,42 @@ quit
|
||||
|
||||
## 安全启动
|
||||
|
||||
Crestodian 的启动路径被有意保持得很小。在以下情况下它仍可运行:
|
||||
Crestodian 的启动路径被刻意保持得很小。它可以在以下情况下运行:
|
||||
|
||||
- `openclaw.json` 缺失
|
||||
- 缺少 `openclaw.json`
|
||||
- `openclaw.json` 无效
|
||||
- Gateway 网关已停止
|
||||
- Gateway 网关 已关闭
|
||||
- 插件命令注册不可用
|
||||
- 还没有配置任何智能体
|
||||
- 尚未配置任何智能体
|
||||
|
||||
`openclaw --help` 和 `openclaw --version` 仍然走常规快速路径。非交互式的 `openclaw` 会输出一条简短消息后退出,而不是打印根帮助,因为无命令产品就是 Crestodian。
|
||||
`openclaw --help` 和 `openclaw --version` 仍然使用常规快速路径。
|
||||
非交互式 `openclaw` 会用一条简短消息退出,而不是打印根帮助,因为无命令产品就是 Crestodian。
|
||||
|
||||
## 操作与批准
|
||||
|
||||
Crestodian 使用类型化操作,而不是临时随意编辑配置。
|
||||
Crestodian 使用类型化操作,而不是临时编辑配置。
|
||||
|
||||
只读操作可以立即运行:
|
||||
|
||||
- 显示概览
|
||||
- 列出智能体
|
||||
- 显示模型 / 后端状态
|
||||
- 运行状态或健康检查
|
||||
- 检查 Gateway 网关可达性
|
||||
- 在不进行交互式修复的情况下运行 Doctor
|
||||
- 显示模型/后端状态
|
||||
- 运行 status 或健康检查
|
||||
- 检查 Gateway 网关 可达性
|
||||
- 在不进行交互式修复的情况下运行 doctor
|
||||
- 验证配置
|
||||
- 显示审计日志路径
|
||||
|
||||
持久化操作在交互模式下需要对话式批准,除非你为直接命令传入 `--yes`:
|
||||
持久化操作在交互模式下需要会话式批准,除非你为直接命令传递 `--yes`:
|
||||
|
||||
- 写入配置
|
||||
- 运行 `config set`
|
||||
- 通过 `config set-ref` 设置受支持的 SecretRef 值
|
||||
- 运行设置 / 新手引导引导流程
|
||||
- 通过 `config set-ref` 设置受支持的 `SecretRef` 值
|
||||
- 运行 setup/新手引导 bootstrap
|
||||
- 更改默认模型
|
||||
- 启动、停止或重启 Gateway 网关
|
||||
- 创建智能体
|
||||
- 运行会重写配置或状态的 Doctor 修复
|
||||
- 运行会重写配置或状态的 doctor 修复
|
||||
|
||||
已应用的写入会记录到:
|
||||
|
||||
@ -117,13 +120,14 @@ Crestodian 使用类型化操作,而不是临时随意编辑配置。
|
||||
~/.openclaw/audit/crestodian.jsonl
|
||||
```
|
||||
|
||||
发现过程不会被审计。只有已应用的操作和写入会被记录。
|
||||
设备发现不会被审计。只有已应用的操作和写入会被记录。
|
||||
|
||||
`openclaw onboard --modern` 会将 Crestodian 作为现代新手引导预览启动。普通的 `openclaw onboard` 仍会运行经典新手引导。
|
||||
`openclaw onboard --modern` 会将 Crestodian 作为现代新手引导预览启动。
|
||||
普通的 `openclaw onboard` 仍然运行经典新手引导。
|
||||
|
||||
## Setup Bootstrap
|
||||
|
||||
`setup` 是以聊天为优先的新手引导引导流程。它只会通过类型化配置操作进行写入,并且会先请求批准。
|
||||
`setup` 是一种以聊天优先的新手引导 bootstrap。它只通过类型化配置操作进行写入,并且会先请求批准。
|
||||
|
||||
```text
|
||||
setup
|
||||
@ -133,25 +137,26 @@ setup workspace ~/Projects/work model openai/gpt-5.5
|
||||
|
||||
当未配置模型时,setup 会按以下顺序选择第一个可用后端,并告诉你它选择了什么:
|
||||
|
||||
- 现有显式模型(如果已配置)
|
||||
- 已有显式模型(如果已配置)
|
||||
- `OPENAI_API_KEY` -> `openai/gpt-5.5`
|
||||
- `ANTHROPIC_API_KEY` -> `anthropic/claude-opus-4-7`
|
||||
- Claude Code CLI -> `claude-cli/claude-opus-4-7`
|
||||
- Codex CLI -> `codex-cli/gpt-5.5`
|
||||
|
||||
如果这些都不可用,setup 仍会写入默认工作区,但保持模型未设置。安装或登录 Codex / Claude Code,或者暴露 `OPENAI_API_KEY` / `ANTHROPIC_API_KEY`,然后再次运行 setup。
|
||||
如果这些都不可用,setup 仍会写入默认工作区,并将模型保持为未设置。安装或登录 Codex/Claude Code,或暴露
|
||||
`OPENAI_API_KEY`/`ANTHROPIC_API_KEY`,然后再次运行 setup。
|
||||
|
||||
## 模型辅助规划器
|
||||
|
||||
Crestodian 始终以确定性模式启动。对于确定性解析器无法理解的模糊命令,本地 Crestodian 可以通过 OpenClaw 的常规运行时路径执行一次受限的规划器轮次。它会先使用已配置的 OpenClaw 模型。如果尚无任何可用的已配置模型,它可以回退到机器上已经存在的本地运行时:
|
||||
Crestodian 始终以确定性模式启动。对于确定性解析器无法理解的模糊命令,本地 Crestodian 可以通过 OpenClaw 的常规运行时路径执行一次受限的规划器轮次。它会先使用已配置的 OpenClaw 模型。如果尚无可用的已配置模型,它可以回退到机器上已存在的本地运行时:
|
||||
|
||||
- Claude Code CLI:`claude-cli/claude-opus-4-7`
|
||||
- Codex app-server harness:`openai/gpt-5.5`,并设置 `embeddedHarness.runtime: "codex"`
|
||||
- Codex app-server harness:`openai/gpt-5.5`,带 `agentRuntime.id: "codex"`
|
||||
- Codex CLI:`codex-cli/gpt-5.5`
|
||||
|
||||
模型辅助规划器不能直接修改配置。它必须先将请求转换为 Crestodian 的某个类型化命令,然后再应用常规的批准和审计规则。Crestodian 会在执行任何操作之前打印它所使用的模型以及解释后的命令。无需配置的回退规划器轮次是临时的,在运行时支持时会禁用工具,并使用临时工作区 / 会话。
|
||||
模型辅助规划器不能直接更改配置。它必须将请求转换为 Crestodian 的某个类型化命令,然后再应用常规的批准和审计规则。Crestodian 会在执行任何操作之前打印它所使用的模型和解释后的命令。无配置的回退规划器轮次是临时的,在运行时支持的情况下会禁用工具,并使用临时工作区/会话。
|
||||
|
||||
消息渠道救援模式不会使用模型辅助规划器。远程救援保持确定性,以避免损坏或受入侵的常规智能体路径被用作配置编辑器。
|
||||
消息渠道救援模式不会使用模型辅助规划器。远程救援保持确定性,这样损坏或被攻陷的正常智能体路径就不能被用作配置编辑器。
|
||||
|
||||
## 切换到智能体
|
||||
|
||||
@ -165,18 +170,19 @@ switch to main agent
|
||||
|
||||
`openclaw tui`、`openclaw chat` 和 `openclaw terminal` 仍会直接打开常规智能体 TUI。它们不会启动 Crestodian。
|
||||
|
||||
切换进入常规 TUI 后,使用 `/crestodian` 返回 Crestodian。你也可以附带后续请求:
|
||||
切换到常规 TUI 后,使用 `/crestodian` 返回 Crestodian。
|
||||
你可以附带后续请求:
|
||||
|
||||
```text
|
||||
/crestodian
|
||||
/crestodian restart gateway
|
||||
```
|
||||
|
||||
TUI 内的智能体切换会留下提示,表明 `/crestodian` 可用。
|
||||
TUI 内的智能体切换会留下一个提示,说明 `/crestodian` 可用。
|
||||
|
||||
## 消息救援模式
|
||||
|
||||
消息救援模式是 Crestodian 的消息渠道入口点。它适用于你的常规智能体已失效,但像 WhatsApp 这样的受信任渠道仍能接收命令的情况。
|
||||
消息救援模式是 Crestodian 的消息渠道入口。它适用于你的正常智能体已失效,但像 WhatsApp 这样的受信任渠道仍然可以接收命令的情况。
|
||||
|
||||
支持的文本命令:
|
||||
|
||||
@ -193,28 +199,28 @@ You: /crestodian yes
|
||||
OpenClaw: Applied. Audit entry written.
|
||||
```
|
||||
|
||||
也可以从本地提示或救援模式中将智能体创建加入队列:
|
||||
也可以通过本地提示或救援模式排队创建智能体:
|
||||
|
||||
```text
|
||||
create agent work workspace ~/Projects/work model openai/gpt-5.5
|
||||
/crestodian create agent work workspace ~/Projects/work
|
||||
```
|
||||
|
||||
远程救援模式是一个管理表面。必须将其视为远程配置修复,而不是普通聊天。
|
||||
远程救援模式是一个管理员界面。必须将其视为远程配置修复,而不是普通聊天。
|
||||
|
||||
远程救援的安全契约:
|
||||
远程救援的安全约定:
|
||||
|
||||
- 当沙箱隔离处于活动状态时禁用。如果某个智能体 / 会话处于沙箱隔离状态,Crestodian 必须拒绝远程救援,并说明需要本地 CLI 修复。
|
||||
- 默认有效状态为 `auto`:仅在受信任的 YOLO 操作中允许远程救援,也就是运行时已经具有未沙箱隔离的本地权限时。
|
||||
- 需要显式的所有者身份。救援不得接受通配发送者规则、开放群组策略、未认证 webhook 或匿名渠道。
|
||||
- 默认仅允许所有者私信。群组 / 渠道救援需要显式选择启用。
|
||||
- 远程救援不能打开本地 TUI,也不能切换进入交互式智能体会话。智能体交接请使用本地 `openclaw`。
|
||||
- 当沙箱隔离处于激活状态时禁用。如果某个智能体/会话已被沙箱隔离,Crestodian 必须拒绝远程救援,并说明需要本地 CLI 修复。
|
||||
- 默认有效状态是 `auto`:仅在受信任的 YOLO 操作中允许远程救援,此时运行时已经具有未沙箱隔离的本地权限。
|
||||
- 要求明确的所有者身份。救援不得接受通配发送者规则、开放群组策略、未认证的 webhook 或匿名渠道。
|
||||
- 默认仅限所有者私信。群组/渠道救援需要显式选择启用。
|
||||
- 远程救援不能打开本地 TUI,也不能切换到交互式智能体会话。智能体交接请使用本地 `openclaw`。
|
||||
- 即使在救援模式下,持久化写入仍然需要批准。
|
||||
- 审计每一个已应用的救援操作。消息渠道救援会记录渠道、账号、发送者和源地址元数据。修改配置的操作还会记录变更前后的配置哈希。
|
||||
- 绝不回显密钥。SecretRef 检查应报告可用性,而不是值。
|
||||
- 如果 Gateway 网关存活,优先使用 Gateway 网关类型化操作。如果 Gateway 网关已停止,则只使用不依赖常规 Agent loop 的最小本地修复表面。
|
||||
- 审计每个已应用的救援操作。消息渠道救援会记录渠道、账号、发送者和源地址元数据。更改配置的操作还会记录变更前后的配置哈希。
|
||||
- 绝不回显密钥。`SecretRef` 检查应报告可用性,而不是值。
|
||||
- 如果 Gateway 网关 存活,优先使用 Gateway 网关 类型化操作。如果 Gateway 网关 已失效,只使用不依赖常规 Agent loop 的最小本地修复界面。
|
||||
|
||||
配置结构:
|
||||
配置形状:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
@ -229,13 +235,13 @@ create agent work workspace ~/Projects/work model openai/gpt-5.5
|
||||
|
||||
`enabled` 应接受:
|
||||
|
||||
- `"auto"`:默认值。仅当有效运行时为 YOLO 且沙箱隔离关闭时允许。
|
||||
- `"auto"`:默认值。仅当有效运行时是 YOLO 且沙箱隔离关闭时允许。
|
||||
- `false`:绝不允许消息渠道救援。
|
||||
- `true`:在所有者 / 渠道检查通过时显式允许救援。但这仍不得绕过沙箱隔离拒绝。
|
||||
- `true`:当所有者/渠道检查通过时显式允许救援。但这仍然不能绕过沙箱隔离拒绝。
|
||||
|
||||
默认的 `"auto"` YOLO 姿态为:
|
||||
默认的 `"auto"` YOLO 姿态是:
|
||||
|
||||
- sandbox 模式解析为 `off`
|
||||
- 沙箱模式解析为 `off`
|
||||
- `tools.exec.security` 解析为 `full`
|
||||
- `tools.exec.ask` 解析为 `off`
|
||||
|
||||
@ -245,25 +251,25 @@ create agent work workspace ~/Projects/work model openai/gpt-5.5
|
||||
pnpm test:docker:crestodian-rescue
|
||||
```
|
||||
|
||||
无需配置的本地规划器回退由以下内容覆盖:
|
||||
无配置的本地规划器回退由以下内容覆盖:
|
||||
|
||||
```bash
|
||||
pnpm test:docker:crestodian-planner
|
||||
```
|
||||
|
||||
一个选择启用的实时渠道命令表面冒烟测试会检查 `/crestodian status` 以及通过救援处理器完成的一次持久化批准往返:
|
||||
一个可选启用的实时渠道命令界面冒烟测试会检查 `/crestodian status`,以及通过救援处理器完成一次持久化批准往返:
|
||||
|
||||
```bash
|
||||
pnpm test:live:crestodian-rescue-channel
|
||||
```
|
||||
|
||||
通过 Crestodian 进行的全新无配置设置由以下内容覆盖:
|
||||
通过 Crestodian 进行的全新无配置 setup 由以下内容覆盖:
|
||||
|
||||
```bash
|
||||
pnpm test:docker:crestodian-first-run
|
||||
```
|
||||
|
||||
该 lane 从空状态目录开始,将裸 `openclaw` 路由到 Crestodian,设置默认模型,创建一个额外智能体,通过插件启用加 token SecretRef 配置 Discord,验证配置,并检查审计日志。QA Lab 也有一个以仓库为基础的场景,用于覆盖相同的 Ring 0 流程:
|
||||
该 lane 从一个空状态目录开始,将裸 `openclaw` 路由到 Crestodian,设置默认模型,创建一个额外智能体,通过插件启用加 token `SecretRef` 配置 Discord,验证配置,并检查审计日志。QA Lab 还为相同的 Ring 0 流程提供了一个基于仓库的场景:
|
||||
|
||||
```bash
|
||||
pnpm openclaw qa suite --scenario crestodian-ring-zero-setup
|
||||
@ -275,4 +281,4 @@ pnpm openclaw qa suite --scenario crestodian-ring-zero-setup
|
||||
- [Doctor](/zh-CN/cli/doctor)
|
||||
- [TUI](/zh-CN/cli/tui)
|
||||
- [沙箱](/zh-CN/cli/sandbox)
|
||||
- [安全](/zh-CN/cli/security)
|
||||
- [安全性](/zh-CN/cli/security)
|
||||
|
||||
@ -2,131 +2,151 @@
|
||||
read_when:
|
||||
- 你正在 PI、Codex、ACP 或其他原生智能体运行时之间进行选择
|
||||
- 你对 Status 或配置中的提供商 / 模型 / 运行时标签感到困惑
|
||||
- 你正在为原生 harness 记录支持一致性
|
||||
- 你正在为原生 harness 记录支持对等性
|
||||
summary: OpenClaw 如何区分模型提供商、模型、渠道和 Agent Runtimes
|
||||
title: Agent Runtimes
|
||||
x-i18n:
|
||||
generated_at: "2026-04-26T03:53:16Z"
|
||||
generated_at: "2026-04-26T07:48:29Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 729bfef9d30efe37ed8a3f697398be0d2faf72bdac46f219b983b7c8ca69de7d
|
||||
source_hash: f99e88a47a78c48b2f2408a3feedf15cde66a6bacc4e7bfadb9e47c74f7ce633
|
||||
source_path: concepts/agent-runtimes.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
**智能体运行时**是负责一个已准备好的模型循环的组件:它接收提示,驱动模型输出,处理原生工具调用,并将完成后的轮次返回给 OpenClaw。
|
||||
**智能体运行时** 是拥有单个已准备模型循环的组件:它接收提示词,驱动模型输出,处理原生工具调用,并将完成的轮次返回给 OpenClaw。
|
||||
|
||||
运行时很容易与提供商混淆,因为两者都会出现在模型配置附近。它们属于不同层级:
|
||||
运行时很容易与提供商混淆,因为两者都会出现在模型配置附近。它们是不同的层:
|
||||
|
||||
| 层级 | 示例 | 含义 |
|
||||
| ------------- | ------------------------------------- | ------------------------------------------------------------------- |
|
||||
| 提供商 | `openai`、`anthropic`、`openai-codex` | OpenClaw 如何进行身份验证、发现模型,以及命名模型引用。 |
|
||||
| 提供商 | `openai`、`anthropic`、`openai-codex` | OpenClaw 如何进行身份验证、发现模型以及命名模型引用。 |
|
||||
| 模型 | `gpt-5.5`、`claude-opus-4-6` | 为智能体轮次选择的模型。 |
|
||||
| Agent Runtimes | `pi`、`codex`、由 ACP 支持的运行时 | 执行已准备轮次的底层循环。 |
|
||||
| Agent Runtimes | `pi`、`codex`、`claude-cli` | 执行已准备轮次的底层循环或后端。 |
|
||||
| 渠道 | Telegram、Discord、Slack、WhatsApp | 消息进入和离开 OpenClaw 的位置。 |
|
||||
|
||||
你还会在代码和配置中看到 **harness** 这个词。harness 是提供某个智能体运行时的实现。例如,内置的 Codex harness 实现了 `codex` 运行时。出于兼容性考虑,配置键仍然命名为 `embeddedHarness`,但面向用户的文档和 Status 输出通常应使用“运行时”。
|
||||
你还会在代码中看到 **harness** 这个词。harness 是提供智能体运行时的实现。例如,内置的 Codex harness 实现了 `codex` 运行时。公开配置使用 `agentRuntime.id`;`openclaw doctor --fix` 会将旧的 runtime-policy 键改写为该结构。
|
||||
|
||||
## 三个都叫 Codex 的东西
|
||||
运行时分为两个家族:
|
||||
|
||||
大多数困惑来自三个不同的表面都共用了 Codex 这个名字:
|
||||
- **嵌入式 harness** 在 OpenClaw 已准备的智能体循环内部运行。目前这包括内置的 `pi` 运行时,以及已注册的插件 harness,例如 `codex`。
|
||||
- **CLI 后端** 运行本地 CLI 进程,同时保持模型引用为规范形式。例如,`anthropic/claude-opus-4-7` 配合 `agentRuntime.id: "claude-cli"` 表示“选择 Anthropic 模型,并通过 Claude CLI 执行”。`claude-cli` 不是嵌入式 harness id,不能传递给 AgentHarness 选择逻辑。
|
||||
|
||||
## 三个名为 Codex 的东西
|
||||
|
||||
大多数困惑都来自三个不同的表面共用了 Codex 这个名称:
|
||||
|
||||
| 表面 | OpenClaw 名称 / 配置 | 作用 |
|
||||
| ---------------------------------------------------- | ------------------------------------ | --------------------------------------------------------------------------------------------------- |
|
||||
| Codex OAuth provider 路由 | `openai-codex/*` 模型引用 | 通过常规 OpenClaw PI 运行器使用 ChatGPT / Codex 订阅 OAuth。 |
|
||||
| 原生 Codex app-server 运行时 | `embeddedHarness.runtime: "codex"` | 通过内置的 Codex app-server harness 运行嵌入式智能体轮次。 |
|
||||
| Codex OAuth 提供商路由 | `openai-codex/*` 模型引用 | 通过普通的 OpenClaw PI 运行器使用 ChatGPT / Codex 订阅 OAuth。 |
|
||||
| 原生 Codex app-server 运行时 | `agentRuntime.id: "codex"` | 通过内置的 Codex app-server harness 运行嵌入式智能体轮次。 |
|
||||
| Codex ACP 适配器 | `runtime: "acp"`、`agentId: "codex"` | 通过外部 ACP / acpx 控制平面运行 Codex。仅在明确要求 ACP / acpx 时使用。 |
|
||||
| 原生 Codex 聊天控制命令集 | `/codex ...` | 在聊天中绑定、恢复、引导、停止和检查 Codex app-server 线程。 |
|
||||
| 面向 GPT / Codex 风格模型的 OpenAI Platform API 路由 | `openai/*` 模型引用 | 使用 OpenAI API key 身份验证,除非某个运行时覆盖(例如 `runtime: "codex"`)来执行该轮次。 |
|
||||
| 原生 Codex chat-control 命令集 | `/codex ...` | 从聊天中绑定、恢复、引导、停止并检查 Codex app-server 线程。 |
|
||||
| 用于 GPT / Codex 风格模型的 OpenAI Platform API 路由 | `openai/*` 模型引用 | 使用 OpenAI API 密钥身份验证,除非有运行时覆盖(例如 `runtime: "codex"`)来执行该轮次。 |
|
||||
|
||||
这些表面是有意彼此独立的。启用 `codex` 插件会使原生 app-server 功能可用;它不会将 `openai-codex/*` 改写为 `openai/*`,不会更改现有会话,也不会让 ACP 成为 Codex 的默认方式。选择 `openai-codex/*` 的意思是“使用 Codex OAuth provider 路由”,除非你另外强制指定运行时。
|
||||
这些表面是有意彼此独立的。启用 `codex` 插件会使原生 app-server 功能可用;它不会将 `openai-codex/*` 改写为 `openai/*`,不会更改现有会话,也不会让 ACP 成为 Codex 的默认值。选择 `openai-codex/*` 表示“使用 Codex OAuth 提供商路由”,除非你另外强制指定运行时。
|
||||
|
||||
常见的 Codex 配置会将 `openai` 提供商与 `codex` 运行时搭配使用:
|
||||
常见的 Codex 设置是使用 `openai` 提供商和 `codex` 运行时:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
defaults: {
|
||||
model: "openai/gpt-5.5",
|
||||
embeddedHarness: {
|
||||
runtime: "codex",
|
||||
agentRuntime: {
|
||||
id: "codex",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
这表示 OpenClaw 先选择一个 OpenAI 模型引用,然后要求 Codex app-server 运行时来运行嵌入式智能体轮次。这并不意味着渠道、模型提供商目录或 OpenClaw 会话存储会变成 Codex。
|
||||
这意味着 OpenClaw 选择一个 OpenAI 模型引用,然后要求 Codex app-server 运行时运行嵌入式智能体轮次。这并不意味着渠道、模型提供商目录或 OpenClaw 会话存储会变成 Codex。
|
||||
|
||||
启用内置 `codex` 插件后,自然语言的 Codex 控制应使用原生 `/codex` 命令表面(`/codex bind`、`/codex threads`、`/codex resume`、`/codex steer`、`/codex stop`),而不是 ACP。只有当用户明确要求 ACP / acpx,或正在测试 ACP 适配器路径时,才对 Codex 使用 ACP。Claude Code、Gemini CLI、OpenCode、Cursor 以及类似的外部 harness 仍然使用 ACP。
|
||||
当内置的 `codex` 插件已启用时,自然语言 Codex 控制应使用原生 `/codex` 命令表面(`/codex bind`、`/codex threads`、`/codex resume`、`/codex steer`、`/codex stop`),而不是 ACP。仅当用户明确要求 ACP / acpx,或正在测试 ACP 适配器路径时,才对 Codex 使用 ACP。Claude Code、Gemini CLI、OpenCode、Cursor 以及类似的外部 harness 仍然使用 ACP。
|
||||
|
||||
这是面向智能体的决策树:
|
||||
|
||||
1. 如果用户要求 **Codex bind / control / thread / resume / steer / stop**,并且已启用内置 `codex` 插件,则使用原生 `/codex` 命令表面。
|
||||
2. 如果用户要求 **将 Codex 用作嵌入式运行时**,则使用 `openai/<model>` 并设置 `embeddedHarness.runtime: "codex"`。
|
||||
3. 如果用户要求 **在常规 OpenClaw 运行器上使用 Codex OAuth / 订阅身份验证**,则使用 `openai-codex/<model>`,并将运行时保持为 PI。
|
||||
4. 如果用户明确提到 **ACP**、**acpx** 或 **Codex ACP 适配器**,则使用 ACP,并设置 `runtime: "acp"` 和 `agentId: "codex"`。
|
||||
5. 如果请求涉及 **Claude Code、Gemini CLI、OpenCode、Cursor、Droid 或其他外部 harness**,则使用 ACP / acpx,而不是原生子智能体运行时。
|
||||
1. 如果用户要求 **Codex bind / control / thread / resume / steer / stop**,并且内置的 `codex` 插件已启用,则使用原生 `/codex` 命令表面。
|
||||
2. 如果用户要求 **Codex 作为嵌入式运行时**,则使用 `openai/<model>` 并设置 `agentRuntime.id: "codex"`。
|
||||
3. 如果用户要求 **在普通 OpenClaw 运行器上使用 Codex OAuth / 订阅认证**,则使用 `openai-codex/<model>`,并将运行时保留为 PI。
|
||||
4. 如果用户明确提到 **ACP**、**acpx** 或 **Codex ACP adapter**,则使用 ACP,并设置 `runtime: "acp"` 和 `agentId: "codex"`。
|
||||
5. 如果请求针对 **Claude Code、Gemini CLI、OpenCode、Cursor、Droid 或其他外部 harness**,则使用 ACP / acpx,而不是原生子智能体运行时。
|
||||
|
||||
| 你的意思是…… | 使用…… |
|
||||
| --------------------------------------- | -------------------------------------------- |
|
||||
| Codex app-server 聊天 / 线程控制 | 来自内置 `codex` 插件的 `/codex ...` |
|
||||
| Codex app-server 嵌入式智能体运行时 | `embeddedHarness.runtime: "codex"` |
|
||||
| 在 PI 运行器上使用 OpenAI Codex OAuth | `openai-codex/*` 模型引用 |
|
||||
| Codex app-server 嵌入式智能体运行时 | `agentRuntime.id: "codex"` |
|
||||
| 在 PI 运行器上的 OpenAI Codex OAuth | `openai-codex/*` 模型引用 |
|
||||
| Claude Code 或其他外部 harness | ACP / acpx |
|
||||
|
||||
关于 OpenAI 家族前缀拆分,参见 [OpenAI](/zh-CN/providers/openai) 和 [模型提供商](/zh-CN/concepts/model-providers)。关于 Codex 运行时支持契约,参见 [Codex harness](/zh-CN/plugins/codex-harness#v1-support-contract)。
|
||||
关于 OpenAI 系列前缀拆分,请参见 [OpenAI](/zh-CN/providers/openai) 和 [模型提供商](/zh-CN/concepts/model-providers)。关于 Codex 运行时支持契约,请参见 [Codex harness](/zh-CN/plugins/codex-harness#v1-support-contract)。
|
||||
|
||||
## 运行时归属
|
||||
|
||||
不同运行时拥有的循环部分不同。
|
||||
不同运行时拥有循环中的不同部分。
|
||||
|
||||
| 表面 | OpenClaw PI 嵌入式 | Codex app-server |
|
||||
| --------------------------- | --------------------------------------- | --------------------------------------------------------------------------- |
|
||||
| 模型循环所有者 | OpenClaw 通过 PI 嵌入式运行器 | Codex app-server |
|
||||
| 模型循环拥有者 | OpenClaw,通过 PI 嵌入式运行器 | Codex app-server |
|
||||
| 规范线程状态 | OpenClaw transcript | Codex 线程,以及 OpenClaw transcript 镜像 |
|
||||
| OpenClaw 动态工具 | 原生 OpenClaw 工具循环 | 通过 Codex 适配器桥接 |
|
||||
| 原生 shell 和文件工具 | PI / OpenClaw 路径 | Codex 原生工具,在支持时通过原生钩子桥接 |
|
||||
| 原生 shell 和文件工具 | PI / OpenClaw 路径 | Codex 原生工具,在支持的情况下通过原生钩子桥接 |
|
||||
| 上下文引擎 | 原生 OpenClaw 上下文组装 | OpenClaw 项目将组装后的上下文注入 Codex 轮次 |
|
||||
| 压缩 | OpenClaw 或选定的上下文引擎 | Codex 原生压缩,并带有 OpenClaw 通知和镜像维护 |
|
||||
| 压缩 | OpenClaw 或所选上下文引擎 | Codex 原生压缩,并带有 OpenClaw 通知和镜像维护 |
|
||||
| 渠道投递 | OpenClaw | OpenClaw |
|
||||
|
||||
这个归属划分是主要的设计规则:
|
||||
这种归属拆分是主要设计规则:
|
||||
|
||||
- 如果某个表面由 OpenClaw 拥有,OpenClaw 就可以提供常规插件钩子行为。
|
||||
- 如果某个表面由 OpenClaw 拥有,OpenClaw 就可以提供正常的插件钩子行为。
|
||||
- 如果某个表面由原生运行时拥有,OpenClaw 就需要运行时事件或原生钩子。
|
||||
- 如果原生运行时拥有规范线程状态,OpenClaw 应该镜像并投射上下文,而不是重写不受支持的内部实现。
|
||||
- 如果规范线程状态由原生运行时拥有,OpenClaw 应该镜像并投射上下文,而不是重写不受支持的内部结构。
|
||||
|
||||
## 运行时选择
|
||||
|
||||
OpenClaw 会在提供商和模型解析之后选择一个嵌入式运行时:
|
||||
OpenClaw 会在提供商和模型解析之后选择嵌入式运行时:
|
||||
|
||||
1. 会话中已记录的运行时优先。配置变更不会将现有 transcript 热切换到不同的原生线程系统。
|
||||
2. `OPENCLAW_AGENT_RUNTIME=<id>` 会为新会话或已重置的会话强制指定该运行时。
|
||||
3. `agents.defaults.embeddedHarness.runtime` 或 `agents.list[].embeddedHarness.runtime` 可以设置为 `auto`、`pi` 或某个已注册的运行时 ID,例如 `codex`。
|
||||
1. 会话中记录的运行时优先。配置更改不会将现有 transcript 热切换到不同的原生线程系统。
|
||||
2. `OPENCLAW_AGENT_RUNTIME=<id>` 会为新的或已重置的会话强制指定该运行时。
|
||||
3. `agents.defaults.agentRuntime.id` 或 `agents.list[].agentRuntime.id` 可以设置为 `auto`、`pi`、已注册的嵌入式 harness id(如 `codex`),或受支持的 CLI 后端别名(如 `claude-cli`)。
|
||||
4. 在 `auto` 模式下,已注册的插件运行时可以声明其支持的提供商 / 模型组合。
|
||||
5. 如果在 `auto` 模式下没有运行时声明某个轮次,且设置了 `fallback: "pi"`(默认值),OpenClaw 会使用 PI 作为兼容性回退。将 `fallback: "none"` 设为回退值,则会让未匹配的 `auto` 模式选择直接失败。
|
||||
5. 如果在 `auto` 模式下没有运行时声明某个轮次,并且设置了 `fallback: "pi"`(默认值),OpenClaw 会使用 PI 作为兼容性回退。将 `fallback: "none"` 设置为在 `auto` 模式匹配失败时直接报错,而不是回退。
|
||||
|
||||
显式插件运行时默认采用失败即关闭的方式。例如,`runtime: "codex"` 表示要么使用 Codex,要么返回明确的选择错误,除非你在同一覆盖范围中设置 `fallback: "pi"`。运行时覆盖不会继承更广范围的回退设置,因此即使默认值使用了 `fallback: "pi"`,智能体级别的 `runtime: "codex"` 也不会被静默路由回 PI。
|
||||
显式插件运行时默认是失败即关闭。例如,`runtime: "codex"` 表示要么使用 Codex,要么得到明确的选择错误,除非你在同一个覆盖作用域中设置 `fallback: "pi"`。运行时覆盖不会继承更宽作用域的回退设置,因此,智能体级别的 `runtime: "codex"` 不会仅因为默认值使用了 `fallback: "pi"` 就被悄悄路由回 PI。
|
||||
|
||||
`auto` 模式有意保持保守。插件运行时可以声明它们理解的提供商 / 模型组合,但 Codex 插件不会在 `auto` 模式下声明 `openai-codex` 提供商。这样可以让 `openai-codex/*` 继续作为显式的 PI Codex OAuth 路由,并避免将基于订阅身份验证的配置静默迁移到原生 app-server harness 上。
|
||||
CLI 后端别名与嵌入式 harness id 不同。推荐的 Claude CLI 形式是:
|
||||
|
||||
如果 `openclaw doctor` 警告说 `codex` 插件已启用,而 `openai-codex/*` 仍通过 PI 路由,请将其视为诊断,而不是迁移。当你想要的是 PI Codex OAuth 时,请保持配置不变。只有当你想要使用原生 Codex app-server 执行时,才切换到 `openai/<model>` 加上 `runtime: "codex"`。
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
defaults: {
|
||||
model: "anthropic/claude-opus-4-7",
|
||||
agentRuntime: { id: "claude-cli" },
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
像 `claude-cli/claude-opus-4-7` 这样的旧式引用仍然为了兼容性而受支持,但新配置应保持提供商 / 模型为规范形式,并将执行后端放在 `agentRuntime.id` 中。
|
||||
|
||||
`auto` 模式是有意保持保守的。插件运行时可以声明它们理解的提供商 / 模型组合,但 Codex 插件不会在 `auto` 模式下声明 `openai-codex` 提供商。这样可以将 `openai-codex/*` 保持为显式的 PI Codex OAuth 路由,并避免将基于订阅认证的配置悄悄迁移到原生 app-server harness 上。
|
||||
|
||||
如果 `openclaw doctor` 警告说 `codex` 插件已启用,而 `openai-codex/*` 仍然通过 PI 路由,请将其视为诊断,而不是迁移。如果你想要的是 PI Codex OAuth,就保持配置不变。只有当你希望使用原生 Codex app-server 执行时,才切换到 `openai/<model>` 加 `agentRuntime.id: "codex"`。
|
||||
|
||||
## 兼容性契约
|
||||
|
||||
当运行时不是 PI 时,它应记录自己支持哪些 OpenClaw 表面。运行时文档应使用如下结构:
|
||||
当某个运行时不是 PI 时,它应记录自己支持哪些 OpenClaw 表面。运行时文档应使用以下结构:
|
||||
|
||||
| 问题 | 为什么重要 |
|
||||
| -------------------------------------- | ------------------------------------------------------------------------------------------------- |
|
||||
| 谁拥有模型循环? | 决定重试、工具续接和最终答案决策发生在哪里。 |
|
||||
| 谁拥有规范线程历史? | 决定 OpenClaw 能否编辑历史,还是只能镜像它。 |
|
||||
| OpenClaw 动态工具是否可用? | 消息、会话、cron 和 OpenClaw 自有工具都依赖这一点。 |
|
||||
| 动态工具钩子是否可用? | 插件期望在 OpenClaw 自有工具周围存在 `before_tool_call`、`after_tool_call` 和中间件。 |
|
||||
| 原生工具钩子是否可用? | shell、patch 和运行时自有工具需要原生钩子来实现策略和观测。 |
|
||||
| 谁拥有模型循环? | 这决定了重试、工具续接和最终答案判定发生在哪里。 |
|
||||
| 谁拥有规范线程历史? | 这决定了 OpenClaw 是可以编辑历史,还是只能镜像历史。 |
|
||||
| OpenClaw 动态工具是否可用? | 消息传递、会话、cron 和 OpenClaw 自有工具都依赖这一点。 |
|
||||
| 动态工具钩子是否可用? | 插件期望围绕 OpenClaw 自有工具有 `before_tool_call`、`after_tool_call` 和中间件。 |
|
||||
| 原生工具钩子是否可用? | shell、patch 和运行时自有工具需要原生钩子来实现策略和观察。 |
|
||||
| 上下文引擎生命周期是否运行? | Memory 和上下文插件依赖 assemble、ingest、after-turn 和 compaction 生命周期。 |
|
||||
| 暴露了哪些压缩数据? | 有些插件只需要通知,而另一些则需要保留 / 丢弃元数据。 |
|
||||
| 哪些内容是有意不支持的? | 当原生运行时拥有更多状态时,用户不应假设它与 PI 等价。 |
|
||||
| 暴露了哪些压缩数据? | 有些插件只需要通知,而另一些需要保留 / 丢弃的元数据。 |
|
||||
| 哪些内容是有意不支持的? | 当原生运行时拥有更多状态时,用户不应假设它与 PI 完全等价。 |
|
||||
|
||||
Codex 运行时支持契约记录在 [Codex harness](/zh-CN/plugins/codex-harness#v1-support-contract) 中。
|
||||
|
||||
@ -134,11 +154,11 @@ Codex 运行时支持契约记录在 [Codex harness](/zh-CN/plugins/codex-harnes
|
||||
|
||||
Status 输出可能同时显示 `Execution` 和 `Runtime` 标签。应将它们理解为诊断信息,而不是提供商名称。
|
||||
|
||||
- 像 `openai/gpt-5.5` 这样的模型引用告诉你所选的提供商 / 模型。
|
||||
- 像 `codex` 这样的运行时 ID 告诉你是哪个循环在执行该轮次。
|
||||
- 像 Telegram 或 Discord 这样的渠道标签告诉你对话发生在哪里。
|
||||
- 像 `openai/gpt-5.5` 这样的模型引用会告诉你所选的提供商 / 模型。
|
||||
- 像 `codex` 这样的运行时 id 会告诉你是哪个循环在执行该轮次。
|
||||
- 像 Telegram 或 Discord 这样的渠道标签会告诉你对话发生在哪里。
|
||||
|
||||
如果在更改运行时配置后,会话仍然显示为 PI,请使用 `/new` 开启新会话,或使用 `/reset` 清除当前会话。现有会话会保留其已记录的运行时,以避免某个 transcript 被通过两个不兼容的原生会话系统重放。
|
||||
如果你在更改运行时配置后,会话仍然显示 PI,请使用 `/new` 启动新会话,或使用 `/reset` 清除当前会话。现有会话会保留其记录的运行时,这样 transcript 就不会通过两个不兼容的原生会话系统被重放。
|
||||
|
||||
## 相关内容
|
||||
|
||||
|
||||
@ -1,20 +1,20 @@
|
||||
---
|
||||
read_when:
|
||||
- 你需要一份按提供商逐项说明的模型设置参考。
|
||||
- 你想要获取模型提供商的示例配置或 CLI 新手引导命令。
|
||||
- 你需要一份按提供商分别说明的模型设置参考文档
|
||||
- 你想要模型提供商的示例配置或 CLI 新手引导命令
|
||||
sidebarTitle: Model providers
|
||||
summary: 模型提供商概览,包含示例配置 + CLI 流程
|
||||
title: 模型提供商
|
||||
x-i18n:
|
||||
generated_at: "2026-04-26T06:40:34Z"
|
||||
generated_at: "2026-04-26T07:48:30Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: fb5cdb72e0056e0c2ca0925d9c608d7268d28d2ce0880fe9c516661d16f60b89
|
||||
source_hash: 925641c70780a5bc87c4fc8236bad56ba9e157df26d8084143eba4bf54e63159
|
||||
source_path: concepts/model-providers.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
**LLM/模型提供商**参考(不是像 WhatsApp/Telegram 这样的聊天渠道)。关于模型选择规则,请参见 [Models](/zh-CN/concepts/models)。
|
||||
**LLM/模型提供商**参考(不是像 WhatsApp/Telegram 这样的聊天渠道)。有关模型选择规则,请参阅 [Models](/zh-CN/concepts/models)。
|
||||
|
||||
## 快速规则
|
||||
|
||||
@ -23,25 +23,25 @@ x-i18n:
|
||||
- 模型引用使用 `provider/model`(示例:`opencode/claude-opus-4-6`)。
|
||||
- 设置后,`agents.defaults.models` 会作为允许列表。
|
||||
- CLI 辅助命令:`openclaw onboard`、`openclaw models list`、`openclaw models set <provider/model>`。
|
||||
- `models.providers.*.models[].contextWindow` 是原生模型元数据;`contextTokens` 是运行时生效的上限。
|
||||
- 回退规则、冷却探测和会话覆盖持久化: [模型故障切换](/zh-CN/concepts/model-failover)。
|
||||
- `models.providers.*.models[].contextWindow` 是模型原生元数据;`contextTokens` 是运行时的实际限制上限。
|
||||
- 回退规则、冷却探测和会话覆盖持久化:参见 [模型故障切换](/zh-CN/concepts/model-failover)。
|
||||
</Accordion>
|
||||
<Accordion title="OpenAI provider/运行时拆分">
|
||||
OpenAI 系列路由按前缀区分:
|
||||
|
||||
- `openai/<model>` 在 PI 中使用直接 OpenAI API 密钥提供商。
|
||||
- `openai-codex/<model>` 在 PI 中使用 Codex OAuth。
|
||||
- `openai/<model>` 加上 `agents.defaults.embeddedHarness.runtime: "codex"` 会使用原生 Codex app-server harness。
|
||||
- `openai/<model>` 加上 `agents.defaults.agentRuntime.id: "codex"` 时,使用原生 Codex 应用服务器 Codex harness。
|
||||
|
||||
参见 [OpenAI](/zh-CN/providers/openai) 和 [Codex harness](/zh-CN/plugins/codex-harness)。如果你对 provider/运行时拆分感到困惑,请先阅读 [Agent Runtimes](/zh-CN/concepts/agent-runtimes)。
|
||||
参见 [OpenAI](/zh-CN/providers/openai) 和 [Codex harness](/zh-CN/plugins/codex-harness)。如果你对 provider/运行时的拆分感到困惑,请先阅读 [Agent Runtimes](/zh-CN/concepts/agent-runtimes)。
|
||||
|
||||
插件自动启用也遵循同一边界:`openai-codex/<model>` 属于 OpenAI 插件,而 Codex 插件由 `embeddedHarness.runtime: "codex"` 或旧版 `codex/<model>` 引用启用。
|
||||
插件自动启用遵循相同边界:`openai-codex/<model>` 属于 OpenAI 插件,而 Codex 插件由 `agentRuntime.id: "codex"` 或旧版 `codex/<model>` 引用启用。
|
||||
|
||||
GPT-5.5 可通过 `openai/gpt-5.5` 用于直接 API 密钥流量,通过 PI 中的 `openai-codex/gpt-5.5` 用于 Codex OAuth,并在设置 `embeddedHarness.runtime: "codex"` 时使用原生 Codex app-server harness。
|
||||
GPT-5.5 可通过 `openai/gpt-5.5` 用于直接 API 密钥流量,通过 `openai-codex/gpt-5.5` 在 PI 中用于 Codex OAuth,并在设置 `agentRuntime.id: "codex"` 时使用原生 Codex 应用服务器 Codex harness。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="CLI 运行时">
|
||||
CLI 运行时使用相同的拆分方式:选择规范模型引用,例如 `anthropic/claude-*`、`google/gemini-*` 或 `openai/gpt-*`,然后在你想使用本地 CLI 后端时,将 `agents.defaults.embeddedHarness.runtime` 设置为 `claude-cli`、`google-gemini-cli` 或 `codex-cli`。
|
||||
CLI 运行时也采用相同拆分:选择规范模型引用,例如 `anthropic/claude-*`、`google/gemini-*` 或 `openai/gpt-*`,然后在你想使用本地 CLI 后端时,将 `agents.defaults.agentRuntime.id` 设置为 `claude-cli`、`google-gemini-cli` 或 `codex-cli`。
|
||||
|
||||
旧版 `claude-cli/*`、`google-gemini-cli/*` 和 `codex-cli/*` 引用会迁移回规范提供商引用,并将运行时单独记录。
|
||||
|
||||
@ -50,56 +50,56 @@ x-i18n:
|
||||
|
||||
## 插件拥有的 provider 行为
|
||||
|
||||
大多数提供商特定逻辑都位于 provider 插件(`registerProvider(...)`)中,而 OpenClaw 保留通用推理循环。插件负责新手引导、模型目录、认证环境变量映射、传输/配置规范化、工具 schema 清理、故障切换分类、OAuth 刷新、使用情况报告、thinking/reasoning 配置文件等。
|
||||
大多数 provider 特定逻辑都位于 provider 插件(`registerProvider(...)`)中,而 OpenClaw 负责通用推理循环。插件负责新手引导、模型目录、认证环境变量映射、传输/配置规范化、工具 schema 清理、故障切换分类、OAuth 刷新、使用情况报告、thinking/reasoning 配置等。
|
||||
|
||||
provider SDK 钩子的完整列表和内置插件示例位于 [提供商插件](/zh-CN/plugins/sdk-provider-plugins)。如果某个 provider 需要完全自定义的请求执行器,那属于另一个更深层的扩展接口。
|
||||
完整的 provider SDK 钩子列表和内置插件示例位于 [提供商插件](/zh-CN/plugins/sdk-provider-plugins)。如果某个 provider 需要完全自定义的请求执行器,那会属于一个单独且更深层的扩展接口。
|
||||
|
||||
<Note>
|
||||
provider 运行时 `capabilities` 是共享运行器元数据(provider 家族、转录/工具链特殊行为、传输/缓存提示)。它不同于[公开能力模型](/zh-CN/plugins/architecture#public-capability-model),后者描述的是插件注册了什么(文本推理、语音等)。
|
||||
Provider 运行时 `capabilities` 是共享运行器元数据(provider 家族、转录/工具行为差异、传输/缓存提示)。它不同于[公开能力模型](/zh-CN/plugins/architecture#public-capability-model),后者描述的是一个插件注册了什么能力(文本推理、语音等)。
|
||||
</Note>
|
||||
|
||||
## API 密钥轮换
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="密钥来源和优先级">
|
||||
你可以通过以下方式配置多个密钥:
|
||||
通过以下方式配置多个密钥:
|
||||
|
||||
- `OPENCLAW_LIVE_<PROVIDER>_KEY`(单个实时覆盖项,最高优先级)
|
||||
- `<PROVIDER>_API_KEYS`(逗号或分号分隔的列表)
|
||||
- `OPENCLAW_LIVE_<PROVIDER>_KEY`(单个实时覆盖,最高优先级)
|
||||
- `<PROVIDER>_API_KEYS`(逗号或分号分隔列表)
|
||||
- `<PROVIDER>_API_KEY`(主密钥)
|
||||
- `<PROVIDER>_API_KEY_*`(编号列表,例如 `<PROVIDER>_API_KEY_1`)
|
||||
|
||||
对于 Google providers,`GOOGLE_API_KEY` 也会作为回退项包含在内。密钥选择顺序会保留优先级并去重值。
|
||||
对于 Google providers,还会将 `GOOGLE_API_KEY` 作为回退来源。密钥选择顺序会保留优先级并去重。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="何时触发轮换">
|
||||
- 只有在遇到限流响应时,请求才会使用下一个密钥重试(例如 `429`、`rate_limit`、`quota`、`resource exhausted`、`Too many concurrent requests`、`ThrottlingException`、`concurrency limit reached`、`workers_ai ... quota limit exceeded`,或周期性使用量限制消息)。
|
||||
- 仅当请求收到限流响应时,才会使用下一个密钥重试(例如 `429`、`rate_limit`、`quota`、`resource exhausted`、`Too many concurrent requests`、`ThrottlingException`、`concurrency limit reached`、`workers_ai ... quota limit exceeded`,或周期性使用量限制消息)。
|
||||
- 非限流失败会立即失败;不会尝试密钥轮换。
|
||||
- 当所有候选密钥都失败时,会返回最后一次尝试的最终错误。
|
||||
- 当所有候选密钥都失败时,将返回最后一次尝试的最终错误。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 内置提供商(pi-ai 目录)
|
||||
## 内置 providers(pi-ai 目录)
|
||||
|
||||
OpenClaw 附带 pi‑ai 目录。这些 provider **不需要** `models.providers` 配置;只需设置认证信息并选择模型。
|
||||
OpenClaw 内置了 pi‑ai 目录。这些 providers **不需要** `models.providers` 配置;只需设置认证并选择一个模型。
|
||||
|
||||
### OpenAI
|
||||
|
||||
- 提供商:`openai`
|
||||
- 认证:`OPENAI_API_KEY`
|
||||
- 可选轮换:`OPENAI_API_KEYS`、`OPENAI_API_KEY_1`、`OPENAI_API_KEY_2`,以及 `OPENCLAW_LIVE_OPENAI_KEY`(单个覆盖项)
|
||||
- 可选轮换:`OPENAI_API_KEYS`、`OPENAI_API_KEY_1`、`OPENAI_API_KEY_2`,以及 `OPENCLAW_LIVE_OPENAI_KEY`(单个覆盖)
|
||||
- 示例模型:`openai/gpt-5.5`、`openai/gpt-5.4-mini`
|
||||
- 如果特定安装或 API 密钥行为不同,请使用 `openclaw models list --provider openai` 验证账户/模型可用性。
|
||||
- 如果特定安装或 API 密钥行为不同,可使用 `openclaw models list --provider openai` 验证账户/模型可用性。
|
||||
- CLI:`openclaw onboard --auth-choice openai-api-key`
|
||||
- 默认传输为 `auto`(优先 WebSocket,回退到 SSE)
|
||||
- 可按模型通过 `agents.defaults.models["openai/<model>"].params.transport` 覆盖(`"sse"`、`"websocket"` 或 `"auto"`)
|
||||
- 默认传输为 `auto`(优先 WebSocket,回退 SSE)
|
||||
- 可通过 `agents.defaults.models["openai/<model>"].params.transport` 按模型覆盖(`"sse"`、`"websocket"` 或 `"auto"`)
|
||||
- OpenAI Responses WebSocket 预热默认通过 `params.openaiWsWarmup` 启用(`true`/`false`)
|
||||
- OpenAI 优先处理可通过 `agents.defaults.models["openai/<model>"].params.serviceTier` 启用
|
||||
- 可通过 `agents.defaults.models["openai/<model>"].params.serviceTier` 启用 OpenAI 优先处理
|
||||
- `/fast` 和 `params.fastMode` 会将直接 `openai/*` Responses 请求映射到 `api.openai.com` 上的 `service_tier=priority`
|
||||
- 如果你想使用显式层级而不是共享的 `/fast` 开关,请使用 `params.serviceTier`
|
||||
- 隐藏的 OpenClaw 归因请求头(`originator`、`version`、`User-Agent`)仅应用于发往 `api.openai.com` 的原生 OpenAI 流量,不适用于通用 OpenAI 兼容代理
|
||||
- 原生 OpenAI 路由还会保留 Responses `store`、提示缓存提示以及 OpenAI reasoning 兼容的负载整形;代理路由不会
|
||||
- `openai/gpt-5.3-codex-spark` 在 OpenClaw 中被有意屏蔽,因为实时 OpenAI API 请求会拒绝它,而当前 Codex 目录也未暴露它
|
||||
- 当你想显式指定层级而不是使用共享 `/fast` 开关时,请使用 `params.serviceTier`
|
||||
- 隐藏的 OpenClaw 归因请求头(`originator`、`version`、`User-Agent`)仅适用于发往 `api.openai.com` 的原生 OpenAI 流量,不适用于通用 OpenAI 兼容代理
|
||||
- 原生 OpenAI 路由还会保留 Responses `store`、提示缓存提示以及 OpenAI reasoning 兼容载荷整形;代理路由不会
|
||||
- `openai/gpt-5.3-codex-spark` 在 OpenClaw 中被有意屏蔽,因为实时 OpenAI API 请求会拒绝它,而当前 Codex 目录也未公开它
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -111,13 +111,17 @@ OpenClaw 附带 pi‑ai 目录。这些 provider **不需要** `models.providers
|
||||
|
||||
- 提供商:`anthropic`
|
||||
- 认证:`ANTHROPIC_API_KEY`
|
||||
- 可选轮换:`ANTHROPIC_API_KEYS`、`ANTHROPIC_API_KEY_1`、`ANTHROPIC_API_KEY_2`,以及 `OPENCLAW_LIVE_ANTHROPIC_KEY`(单个覆盖项)
|
||||
- 可选轮换:`ANTHROPIC_API_KEYS`、`ANTHROPIC_API_KEY_1`、`ANTHROPIC_API_KEY_2`,以及 `OPENCLAW_LIVE_ANTHROPIC_KEY`(单个覆盖)
|
||||
- 示例模型:`anthropic/claude-opus-4-6`
|
||||
- CLI:`openclaw onboard --auth-choice apiKey`
|
||||
- 直接公共 Anthropic 请求支持共享的 `/fast` 开关和 `params.fastMode`,包括发送到 `api.anthropic.com` 的 API 密钥和 OAuth 认证流量;OpenClaw 会将其映射到 Anthropic `service_tier`(`auto` 与 `standard_only`)
|
||||
- 直接公共 Anthropic 请求支持共享 `/fast` 开关和 `params.fastMode`,包括发送到 `api.anthropic.com` 的 API 密钥和 OAuth 认证流量;OpenClaw 会将其映射为 Anthropic `service_tier`(`auto` 与 `standard_only`)
|
||||
- 推荐的 Claude CLI 配置会保持模型引用为规范形式,并单独选择 CLI
|
||||
后端:`anthropic/claude-opus-4-7` 搭配
|
||||
`agents.defaults.agentRuntime.id: "claude-cli"`。旧版
|
||||
`claude-cli/claude-opus-4-7` 引用仍可用于兼容。
|
||||
|
||||
<Note>
|
||||
Anthropic 员工告诉我们,OpenClaw 风格的 Claude CLI 用法现已再次被允许,因此除非 Anthropic 发布新政策,否则 OpenClaw 将 Claude CLI 复用和 `claude -p` 用法视为此集成的许可方式。Anthropic setup-token 仍然作为受支持的 OpenClaw 令牌路径可用,但 OpenClaw 现在在可用时优先选择 Claude CLI 复用和 `claude -p`。
|
||||
Anthropic 员工告诉我们,OpenClaw 风格的 Claude CLI 用法再次被允许,因此除非 Anthropic 发布新的政策,否则 OpenClaw 将 Claude CLI 复用和 `claude -p` 用法视为此集成的获准方式。Anthropic setup-token 仍作为受支持的 OpenClaw 令牌路径保留,但 OpenClaw 现在在可用时更偏好 Claude CLI 复用和 `claude -p`。
|
||||
</Note>
|
||||
|
||||
```json5
|
||||
@ -131,19 +135,19 @@ Anthropic 员工告诉我们,OpenClaw 风格的 Claude CLI 用法现已再次
|
||||
- 提供商:`openai-codex`
|
||||
- 认证:OAuth(ChatGPT)
|
||||
- PI 模型引用:`openai-codex/gpt-5.5`
|
||||
- 原生 Codex app-server harness 引用:`openai/gpt-5.5`,并设置 `agents.defaults.embeddedHarness.runtime: "codex"`
|
||||
- 原生 Codex app-server harness 文档: [Codex harness](/zh-CN/plugins/codex-harness)
|
||||
- 原生 Codex 应用服务器 Codex harness 引用:`openai/gpt-5.5` 搭配 `agents.defaults.agentRuntime.id: "codex"`
|
||||
- 原生 Codex 应用服务器 Codex harness 文档:[Codex harness](/zh-CN/plugins/codex-harness)
|
||||
- 旧版模型引用:`codex/gpt-*`
|
||||
- 插件边界:`openai-codex/*` 会加载 OpenAI 插件;原生 Codex app-server 插件仅通过 Codex harness 运行时或旧版 `codex/*` 引用选择。
|
||||
- 插件边界:`openai-codex/*` 加载 OpenAI 插件;原生 Codex 应用服务器插件仅由 Codex harness 运行时或旧版 `codex/*` 引用选择。
|
||||
- CLI:`openclaw onboard --auth-choice openai-codex` 或 `openclaw models auth login --provider openai-codex`
|
||||
- 默认传输为 `auto`(优先 WebSocket,回退到 SSE)
|
||||
- 可按 PI 模型通过 `agents.defaults.models["openai-codex/<model>"].params.transport` 覆盖(`"sse"`、`"websocket"` 或 `"auto"`)
|
||||
- `params.serviceTier` 也会在原生 Codex Responses 请求(`chatgpt.com/backend-api`)中转发
|
||||
- 默认传输为 `auto`(优先 WebSocket,回退 SSE)
|
||||
- 可通过 `agents.defaults.models["openai-codex/<model>"].params.transport` 按 PI 模型覆盖(`"sse"`、`"websocket"` 或 `"auto"`)
|
||||
- `params.serviceTier` 也会转发到原生 Codex Responses 请求上(`chatgpt.com/backend-api`)
|
||||
- 隐藏的 OpenClaw 归因请求头(`originator`、`version`、`User-Agent`)仅附加到发往 `chatgpt.com/backend-api` 的原生 Codex 流量,不适用于通用 OpenAI 兼容代理
|
||||
- 与直接 `openai/*` 共享同一个 `/fast` 开关和 `params.fastMode` 配置;OpenClaw 会将其映射为 `service_tier=priority`
|
||||
- 与直接 `openai/*` 共用相同的 `/fast` 开关和 `params.fastMode` 配置;OpenClaw 会将其映射为 `service_tier=priority`
|
||||
- `openai-codex/gpt-5.5` 使用 Codex 目录原生 `contextWindow = 400000` 和默认运行时 `contextTokens = 272000`;可通过 `models.providers.openai-codex.models[].contextTokens` 覆盖运行时上限
|
||||
- 策略说明:OpenAI Codex OAuth 明确支持像 OpenClaw 这样的外部工具/工作流。
|
||||
- 当你想使用 Codex OAuth/订阅路线时,请使用 `openai-codex/gpt-5.5`;当你的 API 密钥配置和本地目录暴露了公共 API 路线时,请使用 `openai/gpt-5.5`。
|
||||
- 策略说明:OpenAI Codex OAuth 明确支持用于 OpenClaw 这类外部工具/工作流。
|
||||
- 当你想使用 Codex OAuth/订阅路径时,请使用 `openai-codex/gpt-5.5`;当你的 API 密钥设置和本地目录公开了公共 API 路径时,请使用 `openai/gpt-5.5`。
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -180,8 +184,8 @@ Anthropic 员工告诉我们,OpenClaw 风格的 Claude CLI 用法现已再次
|
||||
### OpenCode
|
||||
|
||||
- 认证:`OPENCODE_API_KEY`(或 `OPENCODE_ZEN_API_KEY`)
|
||||
- Zen 运行时提供商:`opencode`
|
||||
- Go 运行时提供商:`opencode-go`
|
||||
- Zen 运行时 provider:`opencode`
|
||||
- Go 运行时 provider:`opencode-go`
|
||||
- 示例模型:`opencode/claude-opus-4-6`、`opencode-go/kimi-k2.6`
|
||||
- CLI:`openclaw onboard --auth-choice opencode-zen` 或 `openclaw onboard --auth-choice opencode-go`
|
||||
|
||||
@ -195,12 +199,12 @@ Anthropic 员工告诉我们,OpenClaw 风格的 Claude CLI 用法现已再次
|
||||
|
||||
- 提供商:`google`
|
||||
- 认证:`GEMINI_API_KEY`
|
||||
- 可选轮换:`GEMINI_API_KEYS`、`GEMINI_API_KEY_1`、`GEMINI_API_KEY_2`、`GOOGLE_API_KEY` 回退项,以及 `OPENCLAW_LIVE_GEMINI_KEY`(单个覆盖项)
|
||||
- 可选轮换:`GEMINI_API_KEYS`、`GEMINI_API_KEY_1`、`GEMINI_API_KEY_2`、`GOOGLE_API_KEY` 回退,以及 `OPENCLAW_LIVE_GEMINI_KEY`(单个覆盖)
|
||||
- 示例模型:`google/gemini-3.1-pro-preview`、`google/gemini-3-flash-preview`
|
||||
- 兼容性:使用 `google/gemini-3.1-flash-preview` 的旧版 OpenClaw 配置会被规范化为 `google/gemini-3-flash-preview`
|
||||
- CLI:`openclaw onboard --auth-choice gemini-api-key`
|
||||
- Thinking:`/think adaptive` 使用 Google 动态 thinking。Gemini 3/3.1 不包含固定的 `thinkingLevel`;Gemini 2.5 会发送 `thinkingBudget: -1`。
|
||||
- 直接 Gemini 运行也接受 `agents.defaults.models["google/<model>"].params.cachedContent`(或旧版 `cached_content`),以转发 provider 原生 `cachedContents/...` 句柄;Gemini 缓存命中会显示为 OpenClaw `cacheRead`
|
||||
- Thinking:`/think adaptive` 使用 Google 动态 thinking。Gemini 3/3.1 不包含固定 `thinkingLevel`;Gemini 2.5 会发送 `thinkingBudget: -1`。
|
||||
- 直接 Gemini 运行也接受 `agents.defaults.models["google/<model>"].params.cachedContent`(或旧版 `cached_content`),用于转发 provider 原生 `cachedContents/...` 句柄;Gemini 缓存命中会显示为 OpenClaw `cacheRead`
|
||||
|
||||
### Google Vertex 和 Gemini CLI
|
||||
|
||||
@ -208,7 +212,7 @@ Anthropic 员工告诉我们,OpenClaw 风格的 Claude CLI 用法现已再次
|
||||
- 认证:Vertex 使用 gcloud ADC;Gemini CLI 使用其 OAuth 流程
|
||||
|
||||
<Warning>
|
||||
OpenClaw 中的 Gemini CLI OAuth 是非官方集成。一些用户报告在使用第三方客户端后遭遇 Google 账户限制。若你选择继续,请查看 Google 条款并使用非关键账户。
|
||||
OpenClaw 中的 Gemini CLI OAuth 是非官方集成。一些用户报告称,在使用第三方客户端后,其 Google 账户受到限制。请查看 Google 条款,并在你决定继续时使用非关键账户。
|
||||
</Warning>
|
||||
|
||||
Gemini CLI OAuth 作为内置 `google` 插件的一部分提供。
|
||||
@ -238,7 +242,7 @@ Gemini CLI OAuth 作为内置 `google` 插件的一部分提供。
|
||||
openclaw models auth login --provider google-gemini-cli --set-default
|
||||
```
|
||||
|
||||
默认模型:`google-gemini-cli/gemini-3-flash-preview`。你**不需要**将 client id 或 secret 粘贴到 `openclaw.json` 中。CLI 登录流程会将令牌存储在 Gateway 网关主机上的认证配置文件中。
|
||||
默认模型:`google-gemini-cli/gemini-3-flash-preview`。你**不要**把 client id 或 secret 粘贴到 `openclaw.json` 中。CLI 登录流程会将令牌存储在 Gateway 网关主机上的认证配置文件中。
|
||||
|
||||
</Step>
|
||||
<Step title="设置项目(如有需要)">
|
||||
@ -246,7 +250,7 @@ Gemini CLI OAuth 作为内置 `google` 插件的一部分提供。
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
Gemini CLI JSON 回复会从 `response` 解析;用量信息会回退到 `stats`,其中 `stats.cached` 会被规范化为 OpenClaw `cacheRead`。
|
||||
Gemini CLI JSON 回复会从 `response` 中解析;使用量统计会回退到 `stats`,其中 `stats.cached` 会被规范化为 OpenClaw `cacheRead`。
|
||||
|
||||
### Z.AI(GLM)
|
||||
|
||||
@ -264,25 +268,25 @@ Gemini CLI JSON 回复会从 `response` 解析;用量信息会回退到 `stats
|
||||
- 示例模型:`vercel-ai-gateway/anthropic/claude-opus-4.6`、`vercel-ai-gateway/moonshotai/kimi-k2.6`
|
||||
- CLI:`openclaw onboard --auth-choice ai-gateway-api-key`
|
||||
|
||||
### Kilo Gateway
|
||||
### Kilo Gateway 网关
|
||||
|
||||
- 提供商:`kilocode`
|
||||
- 认证:`KILOCODE_API_KEY`
|
||||
- 示例模型:`kilocode/kilo/auto`
|
||||
- CLI:`openclaw onboard --auth-choice kilocode-api-key`
|
||||
- 基础 URL:`https://api.kilo.ai/api/gateway/`
|
||||
- Base URL:`https://api.kilo.ai/api/gateway/`
|
||||
- 静态回退目录内置 `kilocode/kilo/auto`;实时 `https://api.kilo.ai/api/gateway/models` 发现还可以进一步扩展运行时目录。
|
||||
- `kilocode/kilo/auto` 背后的确切上游路由由 Kilo Gateway 拥有,不是在 OpenClaw 中硬编码的。
|
||||
- `kilocode/kilo/auto` 背后的确切上游路由由 Kilo Gateway 网关负责,而不是在 OpenClaw 中硬编码。
|
||||
|
||||
设置详情请参见 [/providers/kilocode](/zh-CN/providers/kilocode)。
|
||||
有关设置详情,请参阅 [/providers/kilocode](/zh-CN/providers/kilocode)。
|
||||
|
||||
### 其他内置 provider 插件
|
||||
|
||||
| 提供商 | Id | 认证环境变量 | 示例模型 |
|
||||
| ----------------------- | -------------------------------- | ------------------------------------------------------------ | ----------------------------------------------- |
|
||||
| BytePlus(国际版) | `byteplus` / `byteplus-plan` | `BYTEPLUS_API_KEY` | `byteplus-plan/ark-code-latest` |
|
||||
| BytePlus | `byteplus` / `byteplus-plan` | `BYTEPLUS_API_KEY` | `byteplus-plan/ark-code-latest` |
|
||||
| Cerebras | `cerebras` | `CEREBRAS_API_KEY` | `cerebras/zai-glm-4.7` |
|
||||
| Cloudflare AI Gateway | `cloudflare-ai-gateway` | `CLOUDFLARE_AI_GATEWAY_API_KEY` | — |
|
||||
| Cloudflare AI Gateway 网关 | `cloudflare-ai-gateway` | `CLOUDFLARE_AI_GATEWAY_API_KEY` | — |
|
||||
| DeepSeek | `deepseek` | `DEEPSEEK_API_KEY` | `deepseek/deepseek-v4-flash` |
|
||||
| GitHub Copilot | `github-copilot` | `COPILOT_GITHUB_TOKEN` / `GH_TOKEN` / `GITHUB_TOKEN` | — |
|
||||
| Groq | `groq` | `GROQ_API_KEY` | — |
|
||||
@ -299,7 +303,7 @@ Gemini CLI JSON 回复会从 `response` 解析;用量信息会回退到 `stats
|
||||
| StepFun | `stepfun` / `stepfun-plan` | `STEPFUN_API_KEY` | `stepfun/step-3.5-flash` |
|
||||
| Together | `together` | `TOGETHER_API_KEY` | `together/moonshotai/Kimi-K2.5` |
|
||||
| Venice | `venice` | `VENICE_API_KEY` | — |
|
||||
| Vercel AI Gateway | `vercel-ai-gateway` | `AI_GATEWAY_API_KEY` | `vercel-ai-gateway/anthropic/claude-opus-4.6` |
|
||||
| Vercel AI Gateway 网关 | `vercel-ai-gateway` | `AI_GATEWAY_API_KEY` | `vercel-ai-gateway/anthropic/claude-opus-4.6` |
|
||||
| Volcano Engine(Doubao) | `volcengine` / `volcengine-plan` | `VOLCANO_ENGINE_API_KEY` | `volcengine-plan/ark-code-latest` |
|
||||
| xAI | `xai` | `XAI_API_KEY` | `xai/grok-4` |
|
||||
| Xiaomi | `xiaomi` | `XIAOMI_API_KEY` | `xiaomi/mimo-v2-flash` |
|
||||
@ -308,31 +312,31 @@ Gemini CLI JSON 回复会从 `response` 解析;用量信息会回退到 `stats
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="OpenRouter">
|
||||
仅在已验证的 `openrouter.ai` 路由上应用其应用归因请求头和 Anthropic `cache_control` 标记。DeepSeek、Moonshot 和 ZAI 引用可用于 OpenRouter 管理的提示缓存 TTL,但不会接收 Anthropic 缓存标记。作为代理风格的 OpenAI 兼容路径,它会跳过仅原生 OpenAI 支持的整形处理(`serviceTier`、Responses `store`、提示缓存提示、OpenAI reasoning 兼容性)。以 Gemini 为后端的引用仅保留代理 Gemini thought-signature 清理。
|
||||
仅在已验证的 `openrouter.ai` 路由上应用其应用归因请求头和 Anthropic `cache_control` 标记。DeepSeek、Moonshot 和 ZAI 引用可使用由 OpenRouter 管理的提示缓存 TTL,但不会接收 Anthropic 缓存标记。作为代理风格的 OpenAI 兼容路径,它会跳过仅限原生 OpenAI 的载荷整形(`serviceTier`、Responses `store`、提示缓存提示、OpenAI reasoning 兼容)。基于 Gemini 的引用仅保留代理 Gemini thought-signature 清理。
|
||||
</Accordion>
|
||||
<Accordion title="Kilo Gateway">
|
||||
以 Gemini 为后端的引用遵循相同的代理 Gemini 清理路径;`kilocode/kilo/auto` 和其他不支持代理 reasoning 的引用会跳过代理 reasoning 注入。
|
||||
<Accordion title="Kilo Gateway 网关">
|
||||
基于 Gemini 的引用遵循相同的代理 Gemini 清理路径;`kilocode/kilo/auto` 和其他不支持代理 reasoning 的引用会跳过代理 reasoning 注入。
|
||||
</Accordion>
|
||||
<Accordion title="MiniMax">
|
||||
API 密钥新手引导会写入显式的纯文本 M2.7 聊天模型定义;图像理解仍由插件拥有的 `MiniMax-VL-01` 媒体 provider 处理。
|
||||
</Accordion>
|
||||
<Accordion title="xAI">
|
||||
使用 xAI Responses 路径。`/fast` 或 `params.fastMode: true` 会将 `grok-3`、`grok-3-mini`、`grok-4` 和 `grok-4-0709` 重写为对应的 `*-fast` 变体。`tool_stream` 默认开启;可通过 `agents.defaults.models["xai/<model>"].params.tool_stream=false` 关闭。
|
||||
使用 xAI Responses 路径。`/fast` 或 `params.fastMode: true` 会将 `grok-3`、`grok-3-mini`、`grok-4` 和 `grok-4-0709` 重写为各自的 `*-fast` 变体。`tool_stream` 默认开启;可通过 `agents.defaults.models["xai/<model>"].params.tool_stream=false` 禁用。
|
||||
</Accordion>
|
||||
<Accordion title="Cerebras">
|
||||
GLM 模型使用 `zai-glm-4.7` / `zai-glm-4.6`;OpenAI 兼容基础 URL 为 `https://api.cerebras.ai/v1`。
|
||||
GLM 模型使用 `zai-glm-4.7` / `zai-glm-4.6`;OpenAI 兼容 Base URL 为 `https://api.cerebras.ai/v1`。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 通过 `models.providers` 配置的提供商(自定义/基础 URL)
|
||||
## 通过 `models.providers` 配置的 providers(自定义/Base URL)
|
||||
|
||||
使用 `models.providers`(或 `models.json`)来添加**自定义**提供商或 OpenAI/Anthropic 兼容代理。
|
||||
使用 `models.providers`(或 `models.json`)添加**自定义** providers 或兼容 OpenAI/Anthropic 的代理。
|
||||
|
||||
下面许多内置 provider 插件已经发布了默认目录。只有当你想覆盖默认基础 URL、请求头或模型列表时,才使用显式的 `models.providers.<id>` 条目。
|
||||
下方许多内置 provider 插件已经发布了默认目录。只有当你想覆盖默认 Base URL、请求头或模型列表时,才需要显式添加 `models.providers.<id>` 条目。
|
||||
|
||||
### Moonshot AI(Kimi)
|
||||
|
||||
Moonshot 作为内置 provider 插件提供。默认使用内置 provider,只有在你需要覆盖基础 URL 或模型元数据时,才添加显式 `models.providers.moonshot` 条目:
|
||||
Moonshot 作为内置 provider 插件提供。默认请使用内置 provider,只有在你需要覆盖 Base URL 或模型元数据时,才添加显式的 `models.providers.moonshot` 条目:
|
||||
|
||||
- 提供商:`moonshot`
|
||||
- 认证:`MOONSHOT_API_KEY`
|
||||
@ -387,13 +391,13 @@ Kimi Coding 使用 Moonshot AI 的 Anthropic 兼容端点:
|
||||
}
|
||||
```
|
||||
|
||||
旧版 `kimi/k2p5` 仍然作为兼容模型 ID 被接受。
|
||||
旧版 `kimi/k2p5` 仍然作为兼容模型 id 被接受。
|
||||
|
||||
### Volcano Engine(Doubao)
|
||||
|
||||
Volcano Engine(火山引擎)为中国用户提供对 Doubao 和其他模型的访问。
|
||||
Volcano Engine(火山引擎)为中国用户提供对 Doubao 及其他模型的访问。
|
||||
|
||||
- 提供商:`volcengine`(编程版:`volcengine-plan`)
|
||||
- 提供商:`volcengine`(Coding:`volcengine-plan`)
|
||||
- 认证:`VOLCANO_ENGINE_API_KEY`
|
||||
- 示例模型:`volcengine-plan/ark-code-latest`
|
||||
- CLI:`openclaw onboard --auth-choice volcengine-api-key`
|
||||
@ -406,9 +410,9 @@ Volcano Engine(火山引擎)为中国用户提供对 Doubao 和其他模型
|
||||
}
|
||||
```
|
||||
|
||||
新手引导默认使用编程版接口,但同时也会注册通用 `volcengine/*` 目录。
|
||||
新手引导默认使用 Coding 接口,但通用 `volcengine/*` 目录也会同时注册。
|
||||
|
||||
在新手引导/配置模型选择器中,Volcengine 认证选项会优先显示 `volcengine/*` 和 `volcengine-plan/*` 两类条目。如果这些模型尚未加载,OpenClaw 会回退到未筛选目录,而不是显示一个按提供商范围筛选后的空选择器。
|
||||
在新手引导/配置模型选择器中,Volcengine 认证选项会优先显示 `volcengine/*` 和 `volcengine-plan/*` 两类条目。如果这些模型尚未加载,OpenClaw 会回退到未过滤的目录,而不是显示一个空的按提供商范围筛选的选择器。
|
||||
|
||||
<Tabs>
|
||||
<Tab title="标准模型">
|
||||
@ -418,7 +422,7 @@ Volcano Engine(火山引擎)为中国用户提供对 Doubao 和其他模型
|
||||
- `volcengine/glm-4-7-251222`(GLM 4.7)
|
||||
- `volcengine/deepseek-v3-2-251201`(DeepSeek V3.2 128K)
|
||||
</Tab>
|
||||
<Tab title="编程模型(volcengine-plan)">
|
||||
<Tab title="Coding 模型(volcengine-plan)">
|
||||
- `volcengine-plan/ark-code-latest`
|
||||
- `volcengine-plan/doubao-seed-code`
|
||||
- `volcengine-plan/kimi-k2.5`
|
||||
@ -431,7 +435,7 @@ Volcano Engine(火山引擎)为中国用户提供对 Doubao 和其他模型
|
||||
|
||||
BytePlus ARK 为国际用户提供与 Volcano Engine 相同模型的访问。
|
||||
|
||||
- 提供商:`byteplus`(编程版:`byteplus-plan`)
|
||||
- 提供商:`byteplus`(Coding:`byteplus-plan`)
|
||||
- 认证:`BYTEPLUS_API_KEY`
|
||||
- 示例模型:`byteplus-plan/ark-code-latest`
|
||||
- CLI:`openclaw onboard --auth-choice byteplus-api-key`
|
||||
@ -444,9 +448,9 @@ BytePlus ARK 为国际用户提供与 Volcano Engine 相同模型的访问。
|
||||
}
|
||||
```
|
||||
|
||||
新手引导默认使用编程版接口,但同时也会注册通用 `byteplus/*` 目录。
|
||||
新手引导默认使用 Coding 接口,但通用 `byteplus/*` 目录也会同时注册。
|
||||
|
||||
在新手引导/配置模型选择器中,BytePlus 认证选项会优先显示 `byteplus/*` 和 `byteplus-plan/*` 两类条目。如果这些模型尚未加载,OpenClaw 会回退到未筛选目录,而不是显示一个按提供商范围筛选后的空选择器。
|
||||
在新手引导/配置模型选择器中,BytePlus 认证选项会优先显示 `byteplus/*` 和 `byteplus-plan/*` 两类条目。如果这些模型尚未加载,OpenClaw 会回退到未过滤的目录,而不是显示一个空的按提供商范围筛选的选择器。
|
||||
|
||||
<Tabs>
|
||||
<Tab title="标准模型">
|
||||
@ -454,7 +458,7 @@ BytePlus ARK 为国际用户提供与 Volcano Engine 相同模型的访问。
|
||||
- `byteplus/kimi-k2-5-260127`(Kimi K2.5)
|
||||
- `byteplus/glm-4-7-251222`(GLM 4.7)
|
||||
</Tab>
|
||||
<Tab title="编程模型(byteplus-plan)">
|
||||
<Tab title="Coding 模型(byteplus-plan)">
|
||||
- `byteplus-plan/ark-code-latest`
|
||||
- `byteplus-plan/doubao-seed-code`
|
||||
- `byteplus-plan/kimi-k2.5`
|
||||
@ -465,7 +469,7 @@ BytePlus ARK 为国际用户提供与 Volcano Engine 相同模型的访问。
|
||||
|
||||
### Synthetic
|
||||
|
||||
Synthetic 通过 `synthetic` 提供商提供 Anthropic 兼容模型:
|
||||
Synthetic 通过 `synthetic` 提供商提供兼容 Anthropic 的模型:
|
||||
|
||||
- 提供商:`synthetic`
|
||||
- 认证:`SYNTHETIC_API_KEY`
|
||||
@ -495,16 +499,16 @@ Synthetic 通过 `synthetic` 提供商提供 Anthropic 兼容模型:
|
||||
|
||||
MiniMax 通过 `models.providers` 配置,因为它使用自定义端点:
|
||||
|
||||
- MiniMax OAuth(Global):`--auth-choice minimax-global-oauth`
|
||||
- MiniMax OAuth(CN):`--auth-choice minimax-cn-oauth`
|
||||
- MiniMax API 密钥(Global):`--auth-choice minimax-global-api`
|
||||
- MiniMax API 密钥(CN):`--auth-choice minimax-cn-api`
|
||||
- MiniMax OAuth(全球):`--auth-choice minimax-global-oauth`
|
||||
- MiniMax OAuth(中国):`--auth-choice minimax-cn-oauth`
|
||||
- MiniMax API 密钥(全球):`--auth-choice minimax-global-api`
|
||||
- MiniMax API 密钥(中国):`--auth-choice minimax-cn-api`
|
||||
- 认证:`minimax` 使用 `MINIMAX_API_KEY`;`minimax-portal` 使用 `MINIMAX_OAUTH_TOKEN` 或 `MINIMAX_API_KEY`
|
||||
|
||||
设置详情、模型选项和配置片段请参见 [/providers/minimax](/zh-CN/providers/minimax)。
|
||||
有关设置详情、模型选项和配置片段,请参阅 [/providers/minimax](/zh-CN/providers/minimax)。
|
||||
|
||||
<Note>
|
||||
在 MiniMax 的 Anthropic 兼容流式传输路径上,OpenClaw 默认禁用 thinking,除非你显式设置它;并且 `/fast on` 会将 `MiniMax-M2.7` 重写为 `MiniMax-M2.7-highspeed`。
|
||||
在 MiniMax 的 Anthropic 兼容流式传输路径上,除非你显式设置,否则 OpenClaw 默认禁用 thinking,并且 `/fast on` 会将 `MiniMax-M2.7` 重写为 `MiniMax-M2.7-highspeed`。
|
||||
</Note>
|
||||
|
||||
插件拥有的能力拆分:
|
||||
@ -512,7 +516,7 @@ MiniMax 通过 `models.providers` 配置,因为它使用自定义端点:
|
||||
- 文本/聊天默认使用 `minimax/MiniMax-M2.7`
|
||||
- 图像生成使用 `minimax/image-01` 或 `minimax-portal/image-01`
|
||||
- 图像理解在两种 MiniMax 认证路径上都使用由插件拥有的 `MiniMax-VL-01`
|
||||
- Web 搜索保持使用提供商 id `minimax`
|
||||
- Web 搜索保持使用 provider id `minimax`
|
||||
|
||||
### LM Studio
|
||||
|
||||
@ -520,9 +524,9 @@ LM Studio 作为内置 provider 插件提供,并使用原生 API:
|
||||
|
||||
- 提供商:`lmstudio`
|
||||
- 认证:`LM_API_TOKEN`
|
||||
- 默认推理基础 URL:`http://localhost:1234/v1`
|
||||
- 默认推理 Base URL:`http://localhost:1234/v1`
|
||||
|
||||
然后设置一个模型(替换为 `http://localhost:1234/api/v1/models` 返回的 ID 之一):
|
||||
然后设置一个模型(替换为 `http://localhost:1234/api/v1/models` 返回的某个 ID):
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -532,19 +536,19 @@ LM Studio 作为内置 provider 插件提供,并使用原生 API:
|
||||
}
|
||||
```
|
||||
|
||||
OpenClaw 使用 LM Studio 原生的 `/api/v1/models` 和 `/api/v1/models/load` 进行发现 + 自动加载,并默认使用 `/v1/chat/completions` 进行推理。设置和故障排除请参见 [/providers/lmstudio](/zh-CN/providers/lmstudio)。
|
||||
OpenClaw 使用 LM Studio 原生 `/api/v1/models` 和 `/api/v1/models/load` 进行发现 + 自动加载,并默认使用 `/v1/chat/completions` 进行推理。有关设置和故障排除,请参阅 [/providers/lmstudio](/zh-CN/providers/lmstudio)。
|
||||
|
||||
### Ollama
|
||||
|
||||
Ollama 作为内置 provider 插件提供,并使用 Ollama 的原生 API:
|
||||
Ollama 作为内置 provider 插件提供,并使用 Ollama 原生 API:
|
||||
|
||||
- 提供商:`ollama`
|
||||
- 认证:无需(本地服务器)
|
||||
- 示例模型:`ollama/llama3.3`
|
||||
- 安装: [https://ollama.com/download](https://ollama.com/download)
|
||||
- 安装:[https://ollama.com/download](https://ollama.com/download)
|
||||
|
||||
```bash
|
||||
# Install Ollama, then pull a model:
|
||||
# 安装 Ollama,然后拉取一个模型:
|
||||
ollama pull llama3.3
|
||||
```
|
||||
|
||||
@ -556,23 +560,23 @@ ollama pull llama3.3
|
||||
}
|
||||
```
|
||||
|
||||
当你通过 `OLLAMA_API_KEY` 选择启用时,系统会在本地 `http://127.0.0.1:11434` 检测 Ollama,而内置 provider 插件会将 Ollama 直接添加到 `openclaw onboard` 和模型选择器中。关于新手引导、云端/本地模式和自定义配置,请参见 [/providers/ollama](/zh-CN/providers/ollama)。
|
||||
当你通过 `OLLAMA_API_KEY` 选择启用时,系统会在本地 `http://127.0.0.1:11434` 检测 Ollama,并且内置 provider 插件会将 Ollama 直接添加到 `openclaw onboard` 和模型选择器中。有关新手引导、云端/本地模式和自定义配置,请参阅 [/providers/ollama](/zh-CN/providers/ollama)。
|
||||
|
||||
### vLLM
|
||||
|
||||
vLLM 作为内置 provider 插件提供,用于本地/自托管的 OpenAI 兼容服务器:
|
||||
vLLM 作为内置 provider 插件提供,用于本地/自托管 OpenAI 兼容服务器:
|
||||
|
||||
- 提供商:`vllm`
|
||||
- 认证:可选(取决于你的服务器)
|
||||
- 默认基础 URL:`http://127.0.0.1:8000/v1`
|
||||
- 默认 Base URL:`http://127.0.0.1:8000/v1`
|
||||
|
||||
要在本地选择启用自动发现(如果你的服务器不强制认证,任意值都可以):
|
||||
要在本地启用自动发现(如果你的服务器不强制认证,任意值都可以):
|
||||
|
||||
```bash
|
||||
export VLLM_API_KEY="vllm-local"
|
||||
```
|
||||
|
||||
然后设置一个模型(替换为 `/v1/models` 返回的 ID 之一):
|
||||
然后设置一个模型(替换为 `/v1/models` 返回的某个 ID):
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -582,7 +586,7 @@ export VLLM_API_KEY="vllm-local"
|
||||
}
|
||||
```
|
||||
|
||||
详情请参见 [/providers/vllm](/zh-CN/providers/vllm)。
|
||||
有关详情,请参阅 [/providers/vllm](/zh-CN/providers/vllm)。
|
||||
|
||||
### SGLang
|
||||
|
||||
@ -590,15 +594,15 @@ SGLang 作为内置 provider 插件提供,用于高性能自托管 OpenAI 兼
|
||||
|
||||
- 提供商:`sglang`
|
||||
- 认证:可选(取决于你的服务器)
|
||||
- 默认基础 URL:`http://127.0.0.1:30000/v1`
|
||||
- 默认 Base URL:`http://127.0.0.1:30000/v1`
|
||||
|
||||
要在本地选择启用自动发现(如果你的服务器不强制认证,任意值都可以):
|
||||
要在本地启用自动发现(如果你的服务器不强制认证,任意值都可以):
|
||||
|
||||
```bash
|
||||
export SGLANG_API_KEY="sglang-local"
|
||||
```
|
||||
|
||||
然后设置一个模型(替换为 `/v1/models` 返回的 ID 之一):
|
||||
然后设置一个模型(替换为 `/v1/models` 返回的某个 ID):
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -608,7 +612,7 @@ export SGLANG_API_KEY="sglang-local"
|
||||
}
|
||||
```
|
||||
|
||||
详情请参见 [/providers/sglang](/zh-CN/providers/sglang)。
|
||||
有关详情,请参阅 [/providers/sglang](/zh-CN/providers/sglang)。
|
||||
|
||||
### 本地代理(LM Studio、vLLM、LiteLLM 等)
|
||||
|
||||
@ -647,7 +651,7 @@ export SGLANG_API_KEY="sglang-local"
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="默认可选字段">
|
||||
对于自定义提供商,`reasoning`、`input`、`cost`、`contextWindow` 和 `maxTokens` 都是可选的。省略时,OpenClaw 默认值为:
|
||||
对于自定义 providers,`reasoning`、`input`、`cost`、`contextWindow` 和 `maxTokens` 都是可选的。省略时,OpenClaw 默认使用:
|
||||
|
||||
- `reasoning: false`
|
||||
- `input: ["text"]`
|
||||
@ -659,11 +663,11 @@ export SGLANG_API_KEY="sglang-local"
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="代理路由整形规则">
|
||||
- 对于非原生端点上的 `api: "openai-completions"`(任意非空 `baseUrl`,且其主机不是 `api.openai.com`),OpenClaw 会强制设置 `compat.supportsDeveloperRole: false`,以避免提供商因不支持 `developer` 角色而返回 400 错误。
|
||||
- 代理风格的 OpenAI 兼容路由也会跳过仅原生 OpenAI 支持的请求整形:没有 `service_tier`、没有 Responses `store`、没有 Completions `store`、没有提示缓存提示、没有 OpenAI reasoning 兼容负载整形,也没有隐藏的 OpenClaw 归因请求头。
|
||||
- 对于需要厂商特定字段的 OpenAI 兼容 Completions 代理,可设置 `agents.defaults.models["provider/model"].params.extra_body`(或 `extraBody`),将额外 JSON 合并到出站请求体中。
|
||||
- 对于 vLLM chat-template 控制,可设置 `agents.defaults.models["provider/model"].params.chat_template_kwargs`。当会话 thinking 级别关闭时,OpenClaw 会自动为 `vllm/nemotron-3-*` 发送 `enable_thinking: false` 和 `force_nonempty_content: true`。
|
||||
- 如果 `baseUrl` 为空/省略,OpenClaw 会保留默认 OpenAI 行为(解析为 `api.openai.com`)。
|
||||
- 对于非原生端点上的 `api: "openai-completions"`(任意非空 `baseUrl`,且其主机不是 `api.openai.com`),OpenClaw 会强制 `compat.supportsDeveloperRole: false`,以避免 provider 因不支持 `developer` 角色而返回 400 错误。
|
||||
- 代理风格的 OpenAI 兼容路由也会跳过仅限原生 OpenAI 的请求整形:没有 `service_tier`、没有 Responses `store`、没有 Completions `store`、没有提示缓存提示、没有 OpenAI reasoning 兼容载荷整形,也没有隐藏的 OpenClaw 归因请求头。
|
||||
- 对于需要厂商特定字段的 OpenAI 兼容 Completions 代理,请设置 `agents.defaults.models["provider/model"].params.extra_body`(或 `extraBody`),以将额外 JSON 合并到出站请求体中。
|
||||
- 对于 vLLM chat-template 控制,请设置 `agents.defaults.models["provider/model"].params.chat_template_kwargs`。当会话 thinking level 关闭时,OpenClaw 会自动为 `vllm/nemotron-3-*` 发送 `enable_thinking: false` 和 `force_nonempty_content: true`。
|
||||
- 如果 `baseUrl` 为空或省略,OpenClaw 会保留默认 OpenAI 行为(即解析到 `api.openai.com`)。
|
||||
- 出于安全考虑,即使显式设置了 `compat.supportsDeveloperRole: true`,在非原生 `openai-completions` 端点上仍会被覆盖。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
@ -676,11 +680,11 @@ openclaw models set opencode/claude-opus-4-6
|
||||
openclaw models list
|
||||
```
|
||||
|
||||
另请参见: [配置](/zh-CN/gateway/configuration),查看完整配置示例。
|
||||
另请参阅:[配置](/zh-CN/gateway/configuration) 了解完整配置示例。
|
||||
|
||||
## 相关内容
|
||||
|
||||
- [配置参考](/zh-CN/gateway/config-agents#agent-defaults) — 模型配置键
|
||||
- [模型故障切换](/zh-CN/concepts/model-failover) — 回退链和重试行为
|
||||
- [Models](/zh-CN/concepts/models) — 模型配置和别名
|
||||
- [提供商](/zh-CN/providers) — 按提供商分类的设置指南
|
||||
- [Providers](/zh-CN/providers) — 按 provider 分类的设置指南
|
||||
|
||||
@ -1,58 +1,58 @@
|
||||
---
|
||||
read_when:
|
||||
- 添加或修改 Models CLI(`models list`/`set`/`scan`/`aliases`/`fallbacks`)
|
||||
- 更改模型回退行为或选择用户体验
|
||||
- 更新模型扫描探针(工具 / 图像)
|
||||
summary: Models CLI:列出、设置、别名、回退、扫描、状态
|
||||
- 更改模型回退行为或选择 UX
|
||||
- 更新模型扫描探测(工具/图像)
|
||||
summary: Models CLI:列表、设置、别名、回退、扫描、状态
|
||||
title: Models CLI
|
||||
x-i18n:
|
||||
generated_at: "2026-04-25T09:52:03Z"
|
||||
generated_at: "2026-04-26T07:48:30Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 370453529596e87e724c4de7d2ae9d20334c29393116059bc01363b47c017d5d
|
||||
source_hash: 50cf422ac5d1a52596eb6c297a87e42b598d839c9e6a95b17d2f3aa0d24f2b6e
|
||||
source_path: concepts/models.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
有关凭证配置轮换、冷却时间以及它们如何与回退交互,请参阅 [/concepts/model-failover](/zh-CN/concepts/model-failover)。
|
||||
有关凭证配置轮换、冷却时间,以及它们如何与回退机制交互,请参阅 [/concepts/model-failover](/zh-CN/concepts/model-failover)。
|
||||
提供商快速概览与示例:[/concepts/model-providers](/zh-CN/concepts/model-providers)。
|
||||
模型引用会选择一个提供商和模型。它们通常不会选择底层的 Agent Runtimes。例如,`openai/gpt-5.5` 可以通过常规的 OpenAI provider 路径运行,也可以根据 `agents.defaults.embeddedHarness.runtime` 通过 Codex 应用服务器运行时运行。请参阅 [/concepts/agent-runtimes](/zh-CN/concepts/agent-runtimes)。
|
||||
模型引用会选择一个提供商和模型。它们通常不会选择底层的 Agent Runtimes。例如,`openai/gpt-5.5` 可以通过常规的 OpenAI provider 路径运行,也可以通过 Codex app-server 运行时运行,具体取决于 `agents.defaults.agentRuntime.id`。参见 [/concepts/agent-runtimes](/zh-CN/concepts/agent-runtimes)。
|
||||
|
||||
## 模型选择的工作方式
|
||||
|
||||
OpenClaw 按以下顺序选择模型:
|
||||
|
||||
1. **主** 模型(`agents.defaults.model.primary` 或 `agents.defaults.model`)。
|
||||
2. `agents.defaults.model.fallbacks` 中的 **回退**(按顺序)。
|
||||
1. **主模型**(`agents.defaults.model.primary` 或 `agents.defaults.model`)。
|
||||
2. `agents.defaults.model.fallbacks` 中的 **回退模型**(按顺序)。
|
||||
3. **提供商凭证故障切换** 会在提供商内部发生,然后才会切换到下一个模型。
|
||||
|
||||
相关内容:
|
||||
|
||||
- `agents.defaults.models` 是 OpenClaw 可用模型的允许列表 / 目录(也包括别名)。
|
||||
- `agents.defaults.imageModel` **仅在** 主模型无法接受图像时使用。
|
||||
- `agents.defaults.pdfModel` 由 `pdf` 工具使用。如果省略,该工具会回退到 `agents.defaults.imageModel`,然后回退到已解析的会话 / 默认模型。
|
||||
- `agents.defaults.imageGenerationModel` 用于共享的图像生成功能。如果省略,`image_generate` 仍然可以推断出一个有凭证支持的提供商默认值。它会先尝试当前默认提供商,然后按提供商 ID 顺序尝试其余已注册的图像生成提供商。如果你设置了特定的提供商 / 模型,也请配置该提供商的凭证 / API 密钥。
|
||||
- `agents.defaults.musicGenerationModel` 用于共享的音乐生成功能。如果省略,`music_generate` 仍然可以推断出一个有凭证支持的提供商默认值。它会先尝试当前默认提供商,然后按提供商 ID 顺序尝试其余已注册的音乐生成提供商。如果你设置了特定的提供商 / 模型,也请配置该提供商的凭证 / API 密钥。
|
||||
- `agents.defaults.videoGenerationModel` 用于共享的视频生成功能。如果省略,`video_generate` 仍然可以推断出一个有凭证支持的提供商默认值。它会先尝试当前默认提供商,然后按提供商 ID 顺序尝试其余已注册的视频生成提供商。如果你设置了特定的提供商 / 模型,也请配置该提供商的凭证 / API 密钥。
|
||||
- 每个智能体的默认值可以通过 `agents.list[].model` 加上绑定来覆盖 `agents.defaults.model`(参见 [/concepts/multi-agent](/zh-CN/concepts/multi-agent))。
|
||||
- `agents.defaults.models` 是 OpenClaw 可使用模型的允许列表/目录(以及别名)。
|
||||
- `agents.defaults.imageModel` **仅在** 主模型不能接受图像时使用。
|
||||
- `agents.defaults.pdfModel` 由 `pdf` 工具使用。如果省略,该工具会回退到 `agents.defaults.imageModel`,然后再回退到已解析的会话/默认模型。
|
||||
- `agents.defaults.imageGenerationModel` 由共享的图像生成功能使用。如果省略,`image_generate` 仍然可以推断出一个有凭证支持的提供商默认值。它会先尝试当前默认提供商,然后按提供商 id 顺序尝试其余已注册的图像生成提供商。如果你设置了特定的提供商/模型,也请配置该提供商的认证/API 密钥。
|
||||
- `agents.defaults.musicGenerationModel` 由共享的音乐生成功能使用。如果省略,`music_generate` 仍然可以推断出一个有凭证支持的提供商默认值。它会先尝试当前默认提供商,然后按提供商 id 顺序尝试其余已注册的音乐生成提供商。如果你设置了特定的提供商/模型,也请配置该提供商的认证/API 密钥。
|
||||
- `agents.defaults.videoGenerationModel` 由共享的视频生成功能使用。如果省略,`video_generate` 仍然可以推断出一个有凭证支持的提供商默认值。它会先尝试当前默认提供商,然后按提供商 id 顺序尝试其余已注册的视频生成提供商。如果你设置了特定的提供商/模型,也请配置该提供商的认证/API 密钥。
|
||||
- 每个智能体的默认设置可以通过 `agents.list[].model` 加上绑定来覆盖 `agents.defaults.model`(参见 [/concepts/multi-agent](/zh-CN/concepts/multi-agent))。
|
||||
|
||||
## 快速模型策略
|
||||
|
||||
- 将你的主模型设置为你可用的最强、最新一代模型。
|
||||
- 将回退用于对成本 / 延迟敏感的任务,以及风险较低的聊天。
|
||||
- 对于启用了工具的智能体或不受信任的输入,避免使用较旧 / 较弱的模型层级。
|
||||
- 将你的主模型设置为你可用的最新一代中能力最强的模型。
|
||||
- 对成本/延迟敏感的任务以及风险较低的聊天,使用回退模型。
|
||||
- 对于启用了工具的智能体或不受信任的输入,避免使用较旧/较弱档位的模型。
|
||||
|
||||
## 新手引导(推荐)
|
||||
|
||||
如果你不想手动编辑配置,请运行新手引导:
|
||||
如果你不想手动编辑配置,可以运行新手引导:
|
||||
|
||||
```bash
|
||||
openclaw onboard
|
||||
```
|
||||
|
||||
它可以为常见提供商设置模型 + 凭证,包括 **OpenAI Code(Codex)订阅**(OAuth)和 **Anthropic**(API 密钥或 Claude CLI)。
|
||||
它可以为常见提供商设置模型和认证,包括 **OpenAI Code(Codex)订阅**(OAuth)和 **Anthropic**(API 密钥或 Claude CLI)。
|
||||
|
||||
## 配置键名(概览)
|
||||
## 配置键(概览)
|
||||
|
||||
- `agents.defaults.model.primary` 和 `agents.defaults.model.fallbacks`
|
||||
- `agents.defaults.imageModel.primary` 和 `agents.defaults.imageModel.fallbacks`
|
||||
@ -62,35 +62,35 @@ openclaw onboard
|
||||
- `agents.defaults.models`(允许列表 + 别名 + 提供商参数)
|
||||
- `models.providers`(写入 `models.json` 的自定义提供商)
|
||||
|
||||
模型引用会被规范化为小写。像 `z.ai/*` 这样的提供商别名会规范化为 `zai/*`。
|
||||
模型引用会被标准化为小写。像 `z.ai/*` 这样的提供商别名会标准化为 `zai/*`。
|
||||
|
||||
提供商配置示例(包括 OpenCode)位于
|
||||
[/providers/opencode](/zh-CN/providers/opencode)。
|
||||
提供商配置示例(包括 OpenCode)位于 [/providers/opencode](/zh-CN/providers/opencode)。
|
||||
|
||||
### 安全地编辑允许列表
|
||||
|
||||
手动更新 `agents.defaults.models` 时,请使用增量写入:
|
||||
手动更新 `agents.defaults.models` 时,请使用追加式写入:
|
||||
|
||||
```bash
|
||||
openclaw config set agents.defaults.models '{"openai/gpt-5.4":{}}' --strict-json --merge
|
||||
```
|
||||
|
||||
`openclaw config set` 会保护模型 / 提供商映射,避免被意外覆盖。当对 `agents.defaults.models`、`models.providers` 或 `models.providers.<id>.models` 进行普通对象赋值且会移除现有条目时,该操作会被拒绝。对增量更改请使用 `--merge`;仅当提供的值应成为完整目标值时才使用 `--replace`。
|
||||
`openclaw config set` 会保护模型/提供商映射,防止被意外覆盖。对于 `agents.defaults.models`、`models.providers` 或 `models.providers.<id>.models` 的普通对象赋值,如果会移除现有条目,就会被拒绝。使用 `--merge` 进行追加式更改;仅当提供的值应成为完整目标值时,才使用 `--replace`。
|
||||
|
||||
交互式提供商设置和 `openclaw configure --section model` 也会将提供商范围内的选择合并到现有允许列表中,因此添加 Codex、Ollama 或其他提供商时,不会丢弃无关的模型条目。重新应用提供商凭证时,Configure 会保留现有的 `agents.defaults.model.primary`。像 `openclaw models auth login --provider <id> --set-default` 和 `openclaw models set <model>` 这样的显式默认值设置命令,仍然会替换 `agents.defaults.model.primary`。
|
||||
交互式提供商设置以及 `openclaw configure --section model` 也会把按提供商范围选择的内容合并到现有允许列表中,因此添加 Codex、Ollama 或其他提供商时,不会丢弃无关的模型条目。
|
||||
当重新应用提供商认证时,Configure 会保留现有的 `agents.defaults.model.primary`。而显式设置默认值的命令,例如 `openclaw models auth login --provider <id> --set-default` 和 `openclaw models set <model>`,仍然会替换 `agents.defaults.model.primary`。
|
||||
|
||||
## “Model is not allowed”(以及为什么回复会停止)
|
||||
|
||||
如果设置了 `agents.defaults.models`,它就会成为 `/model` 和会话覆盖的**允许列表**。当用户选择了不在该允许列表中的模型时,OpenClaw 会返回:
|
||||
如果设置了 `agents.defaults.models`,它就会成为 `/model` 和会话覆盖的 **允许列表**。当用户选择了不在该允许列表中的模型时,OpenClaw 会返回:
|
||||
|
||||
```
|
||||
Model "provider/model" is not allowed. Use /model to list available models.
|
||||
```
|
||||
|
||||
这会在生成正常回复**之前**发生,因此消息会让人感觉像是“没有响应”。解决办法是:
|
||||
这会发生在正常回复生成 **之前**,因此消息看起来可能像是“没有响应”。解决方法是:
|
||||
|
||||
- 将该模型添加到 `agents.defaults.models`,或者
|
||||
- 清空允许列表(移除 `agents.defaults.models`),或者
|
||||
- 将该模型添加到 `agents.defaults.models`,或
|
||||
- 清空允许列表(移除 `agents.defaults.models`),或
|
||||
- 从 `/model list` 中选择一个模型。
|
||||
|
||||
允许列表示例配置:
|
||||
@ -122,23 +122,23 @@ Model "provider/model" is not allowed. Use /model to list available models.
|
||||
说明:
|
||||
|
||||
- `/model`(以及 `/model list`)是一个紧凑的编号选择器(模型家族 + 可用提供商)。
|
||||
- 在 Discord 上,`/model` 和 `/models` 会打开一个交互式选择器,其中包含提供商和模型下拉菜单以及一个 Submit 步骤。
|
||||
- `/models add` 已弃用,现在会返回一条弃用消息,而不是从聊天中注册模型。
|
||||
- 在 Discord 上,`/model` 和 `/models` 会打开一个交互式选择器,其中包含提供商和模型下拉菜单,以及一个 Submit 步骤。
|
||||
- `/models add` 已弃用,现在会返回弃用提示消息,而不是通过聊天注册模型。
|
||||
- `/model <#>` 会从该选择器中进行选择。
|
||||
- `/model` 会立即持久化新的会话选择。
|
||||
- 如果智能体空闲,下一次运行会立即使用新模型。
|
||||
- 如果某次运行已经处于活动状态,OpenClaw 会将实时切换标记为待处理,并且只会在一个干净的重试点重启到新模型。
|
||||
- 如果工具活动或回复输出已经开始,待处理切换可能会一直排队,直到后续的重试机会或下一个用户回合。
|
||||
- `/model status` 是详细视图(凭证候选项,以及在已配置时显示提供商端点 `baseUrl` + `api` 模式)。
|
||||
- 模型引用会通过按**第一个** `/` 分割来解析。输入 `/model <ref>` 时,请使用 `provider/model`。
|
||||
- 如果模型 ID 本身包含 `/`(OpenRouter 风格),你必须包含提供商前缀(示例:`/model openrouter/moonshotai/kimi-k2`)。
|
||||
- 如果你省略提供商,OpenClaw 会按以下顺序解析输入:
|
||||
- 如果智能体处于空闲状态,下一次运行会立即使用新模型。
|
||||
- 如果某次运行已经在进行中,OpenClaw 会将实时切换标记为待处理,并只会在一个干净的重试点重启进入新模型。
|
||||
- 如果工具活动或回复输出已经开始,待处理切换可能会保持排队状态,直到后续的重试机会或下一轮用户输入。
|
||||
- `/model status` 是详细视图(认证候选项,以及在已配置时显示提供商端点 `baseUrl` 和 `api` 模式)。
|
||||
- 模型引用会通过按 **第一个** `/` 进行拆分解析。输入 `/model <ref>` 时请使用 `provider/model`。
|
||||
- 如果模型 id 本身包含 `/`(OpenRouter 风格),你必须包含提供商前缀(例如:`/model openrouter/moonshotai/kimi-k2`)。
|
||||
- 如果你省略了提供商,OpenClaw 会按以下顺序解析输入:
|
||||
1. 别名匹配
|
||||
2. 对该精确无前缀模型 ID 的唯一已配置提供商匹配
|
||||
3. 已弃用的回退:回退到已配置的默认提供商
|
||||
如果该提供商不再公开已配置的默认模型,OpenClaw 会改为回退到第一个已配置的提供商 / 模型,以避免暴露一个已过期、已移除提供商的默认值。
|
||||
2. 对该精确未加前缀模型 id 的唯一已配置提供商匹配
|
||||
3. 已弃用的回退:使用已配置的默认提供商
|
||||
如果该提供商不再暴露已配置的默认模型,OpenClaw 会改为回退到第一个已配置的提供商/模型,以避免暴露陈旧的、已移除提供商默认值。
|
||||
|
||||
完整命令行为 / 配置: [Slash commands](/zh-CN/tools/slash-commands)。
|
||||
完整的命令行为/配置: [Slash commands](/zh-CN/tools/slash-commands)。
|
||||
|
||||
## CLI 命令
|
||||
|
||||
@ -167,26 +167,26 @@ openclaw models image-fallbacks clear
|
||||
|
||||
### `models list`
|
||||
|
||||
默认显示已配置的模型。有用的标志:
|
||||
默认显示已配置的模型。常用标志:
|
||||
|
||||
- `--all`:完整目录
|
||||
- `--local`:仅本地提供商
|
||||
- `--provider <id>`:按提供商 ID 过滤,例如 `moonshot`;不接受交互式选择器中的显示标签
|
||||
- `--provider <id>`:按提供商 id 过滤,例如 `moonshot`;不接受交互式选择器中的显示标签
|
||||
- `--plain`:每行一个模型
|
||||
- `--json`:机器可读输出
|
||||
|
||||
`--all` 会在配置凭证之前包含内置的、由提供商拥有的静态目录行,因此仅发现视图也可以显示那些在你添加匹配提供商凭证之前不可用的模型。
|
||||
在配置认证之前,`--all` 会包含提供商自带的静态目录行,因此仅发现用途的视图可以显示那些在你添加匹配提供商凭证之前不可用的模型。
|
||||
|
||||
### `models status`
|
||||
|
||||
显示已解析的主模型、回退、图像模型以及已配置提供商的凭证概览。它还会显示在凭证存储中找到的配置文件的 OAuth 过期状态(默认在 24 小时内发出警告)。`--plain` 只打印已解析的主模型。
|
||||
显示已解析的主模型、回退模型、图像模型,以及已配置提供商的认证概览。它还会显示认证存储中找到的配置文件的 OAuth 过期状态(默认在 24 小时内发出警告)。`--plain` 只打印已解析的主模型。
|
||||
OAuth 状态始终会显示(并包含在 `--json` 输出中)。如果某个已配置提供商没有凭证,`models status` 会打印一个 **Missing auth** 部分。
|
||||
JSON 包含 `auth.oauth`(警告窗口 + 配置文件)和 `auth.providers`(每个提供商的有效凭证,包括基于环境变量的凭证)。`auth.oauth` 仅表示凭证存储配置文件的健康状态;仅使用环境变量的提供商不会出现在其中。
|
||||
自动化请使用 `--check`(缺失 / 已过期时退出码为 `1`,即将过期时为 `2`)。
|
||||
实时凭证检查请使用 `--probe`;探测行可以来自凭证配置文件、环境变量凭证或 `models.json`。
|
||||
如果显式的 `auth.order.<provider>` 省略了某个已存储配置文件,探测会报告 `excluded_by_auth_order`,而不是尝试它。如果存在凭证,但无法为该提供商解析出可探测的模型,探测会报告 `status: no_model`。
|
||||
JSON 包括 `auth.oauth`(警告窗口 + 配置文件)和 `auth.providers`(每个提供商的生效认证,包括由环境变量支持的凭证)。`auth.oauth` 仅表示认证存储中的配置文件健康状态;仅依赖环境变量的提供商不会出现在其中。
|
||||
对自动化用途可使用 `--check`(缺失/已过期时退出码为 `1`,即将过期时为 `2`)。
|
||||
使用 `--probe` 进行实时认证检查;探测行可能来自认证配置文件、环境变量凭证或 `models.json`。
|
||||
如果显式的 `auth.order.<provider>` 省略了某个已存储配置文件,探测会报告 `excluded_by_auth_order`,而不是尝试它。如果认证存在,但无法为该提供商解析出可探测的模型,探测会报告 `status: no_model`。
|
||||
|
||||
凭证选择取决于提供商 / 账户。对于始终在线的 Gateway 网关主机,API 密钥通常是最可预测的;也支持复用 Claude CLI 以及现有的 Anthropic OAuth / token 配置文件。
|
||||
认证选择取决于提供商/账户。对于始终在线的 Gateway 网关主机,API 密钥通常是最可预测的;也支持复用 Claude CLI 以及现有的 Anthropic OAuth/token 配置文件。
|
||||
|
||||
示例(Claude CLI):
|
||||
|
||||
@ -203,15 +203,15 @@ openclaw models status
|
||||
|
||||
- `--no-probe`:跳过实时探测(仅元数据)
|
||||
- `--min-params <b>`:最小参数规模(十亿)
|
||||
- `--max-age-days <days>`:跳过较旧的模型
|
||||
- `--provider <name>`:提供商前缀过滤器
|
||||
- `--max-age-days <days>`:跳过较旧模型
|
||||
- `--provider <name>`:提供商前缀过滤
|
||||
- `--max-candidates <n>`:回退列表大小
|
||||
- `--set-default`:将 `agents.defaults.model.primary` 设置为第一个选中的项
|
||||
- `--set-image`:将 `agents.defaults.imageModel.primary` 设置为第一个图像选项
|
||||
- `--set-default`:将 `agents.defaults.model.primary` 设为第一个选中的模型
|
||||
- `--set-image`:将 `agents.defaults.imageModel.primary` 设为第一个图像选中的模型
|
||||
|
||||
OpenRouter 的 `/models` 目录是公开的,因此仅元数据扫描在没有密钥时也可以列出免费候选项。探测和推理仍然需要一个 OpenRouter API 密钥(来自凭证配置文件或 `OPENROUTER_API_KEY`)。如果没有可用密钥,`openclaw models scan` 会回退为仅元数据输出,并且不会更改配置。使用 `--no-probe` 可显式请求仅元数据模式。
|
||||
OpenRouter 的 `/models` 目录是公开的,因此仅元数据扫描可以在没有密钥的情况下列出免费候选项。探测和推理仍然需要 OpenRouter API 密钥(来自认证配置文件或 `OPENROUTER_API_KEY`)。如果没有可用密钥,`openclaw models scan` 会回退到仅元数据输出,并保持配置不变。使用 `--no-probe` 可以显式请求仅元数据模式。
|
||||
|
||||
扫描结果按以下优先级排序:
|
||||
扫描结果按以下顺序排序:
|
||||
|
||||
1. 图像支持
|
||||
2. 工具延迟
|
||||
@ -221,34 +221,34 @@ OpenRouter 的 `/models` 目录是公开的,因此仅元数据扫描在没有
|
||||
输入
|
||||
|
||||
- OpenRouter `/models` 列表(过滤 `:free`)
|
||||
- 实时探测需要来自凭证配置文件或 `OPENROUTER_API_KEY` 的 OpenRouter API 密钥(参见 [/environment](/zh-CN/help/environment))
|
||||
- 实时探测需要来自认证配置文件或 `OPENROUTER_API_KEY` 的 OpenRouter API 密钥(参见 [/environment](/zh-CN/help/environment))
|
||||
- 可选过滤器:`--max-age-days`、`--min-params`、`--provider`、`--max-candidates`
|
||||
- 请求 / 探测控制:`--timeout`、`--concurrency`
|
||||
- 请求/探测控制:`--timeout`、`--concurrency`
|
||||
|
||||
当实时探测在 TTY 中运行时,你可以交互式地选择回退。在非交互模式下,传递 `--yes` 以接受默认值。仅元数据结果仅供参考;`--set-default` 和 `--set-image` 需要实时探测,这样 OpenClaw 才不会配置一个不可用、无密钥的 OpenRouter 模型。
|
||||
当实时探测在 TTY 中运行时,你可以交互式选择回退模型。在非交互模式下,传递 `--yes` 以接受默认值。仅元数据结果仅供参考;`--set-default` 和 `--set-image` 需要实时探测,这样 OpenClaw 才不会配置一个不可用的、无密钥的 OpenRouter 模型。
|
||||
|
||||
## 模型注册表(`models.json`)
|
||||
|
||||
`models.providers` 中的自定义提供商会写入智能体目录下的 `models.json`(默认路径为 `~/.openclaw/agents/<agentId>/agent/models.json`)。除非将 `models.mode` 设置为 `replace`,否则默认会合并此文件。
|
||||
`models.providers` 中的自定义提供商会写入智能体目录下的 `models.json`(默认是 `~/.openclaw/agents/<agentId>/agent/models.json`)。除非 `models.mode` 被设置为 `replace`,否则默认会合并此文件。
|
||||
|
||||
对于匹配的提供商 ID,合并模式的优先级如下:
|
||||
匹配提供商 ID 时的合并模式优先级:
|
||||
|
||||
- 智能体 `models.json` 中已存在的非空 `baseUrl` 优先生效。
|
||||
- 智能体 `models.json` 中的非空 `apiKey` 仅在该提供商在当前配置 / 凭证配置文件上下文中不是由 SecretRef 管理时优先生效。
|
||||
- 由 SecretRef 管理的提供商 `apiKey` 值会从源标记刷新(环境变量引用使用 `ENV_VAR_NAME`,文件 / exec 引用使用 `secretref-managed`),而不是持久化已解析的密钥。
|
||||
- 由 SecretRef 管理的提供商请求头值会从源标记刷新(环境变量引用使用 `secretref-env:ENV_VAR_NAME`,文件 / exec 引用使用 `secretref-managed`)。
|
||||
- 智能体中为空或缺失的 `apiKey` / `baseUrl` 会回退到配置中的 `models.providers`。
|
||||
- 其他提供商字段会从配置和规范化后的目录数据中刷新。
|
||||
- 智能体 `models.json` 中已存在的非空 `baseUrl` 优先。
|
||||
- 智能体 `models.json` 中的非空 `apiKey` 仅在该提供商在当前配置/认证配置文件上下文中不受 SecretRef 管理时优先。
|
||||
- 受 SecretRef 管理的提供商 `apiKey` 值会从源标记刷新(环境变量引用使用 `ENV_VAR_NAME`,文件/exec 引用使用 `secretref-managed`),而不是持久化已解析的密钥。
|
||||
- 受 SecretRef 管理的提供商请求头值会从源标记刷新(环境变量引用使用 `secretref-env:ENV_VAR_NAME`,文件/exec 引用使用 `secretref-managed`)。
|
||||
- 空的或缺失的智能体 `apiKey`/`baseUrl` 会回退到配置中的 `models.providers`。
|
||||
- 其他提供商字段会从配置和标准化后的目录数据中刷新。
|
||||
|
||||
标记持久化以源为准:OpenClaw 会从当前活动源配置快照(解析前)写入标记,而不是从已解析的运行时密钥值写入。
|
||||
只要 OpenClaw 重新生成 `models.json`,这一点就适用,包括像 `openclaw agent` 这样的命令驱动路径。
|
||||
标记持久化以源为准:OpenClaw 会从当前激活的源配置快照(解析前)写入标记,而不是从已解析的运行时密钥值写入。
|
||||
只要 OpenClaw 重新生成 `models.json`,这一规则就会生效,包括像 `openclaw agent` 这样的命令驱动路径。
|
||||
|
||||
## 相关内容
|
||||
|
||||
- [Model Providers](/zh-CN/concepts/model-providers) —— 提供商路由与凭证
|
||||
- [Agent Runtimes](/zh-CN/concepts/agent-runtimes) —— PI、Codex 和其他 Agent loop 运行时
|
||||
- [Model Failover](/zh-CN/concepts/model-failover) —— 回退链
|
||||
- [Image Generation](/zh-CN/tools/image-generation) —— 图像模型配置
|
||||
- [Music Generation](/zh-CN/tools/music-generation) —— 音乐模型配置
|
||||
- [Video Generation](/zh-CN/tools/video-generation) —— 视频模型配置
|
||||
- [Configuration Reference](/zh-CN/gateway/config-agents#agent-defaults) —— 模型配置键名
|
||||
- [Model Providers](/zh-CN/concepts/model-providers) — 提供商路由与认证
|
||||
- [Agent Runtimes](/zh-CN/concepts/agent-runtimes) — PI、Codex 和其他 Agent loop 运行时
|
||||
- [Model Failover](/zh-CN/concepts/model-failover) — 回退链
|
||||
- [Image Generation](/zh-CN/tools/image-generation) — 图像模型配置
|
||||
- [Music Generation](/zh-CN/tools/music-generation) — 音乐模型配置
|
||||
- [Video Generation](/zh-CN/tools/video-generation) — 视频模型配置
|
||||
- [Configuration Reference](/zh-CN/gateway/config-agents#agent-defaults) — 模型配置键
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -6,15 +6,15 @@ sidebarTitle: Doctor
|
||||
summary: Doctor 命令:健康检查、配置迁移和修复步骤
|
||||
title: Doctor
|
||||
x-i18n:
|
||||
generated_at: "2026-04-26T06:43:58Z"
|
||||
generated_at: "2026-04-26T07:49:08Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 4224459d9b052abc82ed32547e146686b777652fe304f850243cd3fcceae263b
|
||||
source_hash: 53248eb2777a16197480654302d6802b8b6d4f4b810b443d0aea44e5d40b1cd5
|
||||
source_path: gateway/doctor.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
`openclaw doctor` 是 OpenClaw 的修复 + 迁移工具。它会修复过时的配置/状态、检查健康状况,并提供可执行的修复步骤。
|
||||
`openclaw doctor` 是 OpenClaw 的修复 + 迁移工具。它会修复过时的配置/状态,检查健康状况,并提供可执行的修复步骤。
|
||||
|
||||
## 快速开始
|
||||
|
||||
@ -30,7 +30,7 @@ openclaw doctor
|
||||
openclaw doctor --yes
|
||||
```
|
||||
|
||||
接受默认选项而不提示(包括在适用时的重启/服务/沙箱修复步骤)。
|
||||
接受默认值而不提示(包括在适用时的重启/服务/沙箱修复步骤)。
|
||||
|
||||
</Tab>
|
||||
<Tab title="--repair">
|
||||
@ -38,7 +38,7 @@ openclaw doctor
|
||||
openclaw doctor --repair
|
||||
```
|
||||
|
||||
不经提示应用推荐的修复(在安全时执行修复 + 重启)。
|
||||
无需提示即可应用推荐修复(在安全情况下执行修复 + 重启)。
|
||||
|
||||
</Tab>
|
||||
<Tab title="--repair --force">
|
||||
@ -46,7 +46,7 @@ openclaw doctor
|
||||
openclaw doctor --repair --force
|
||||
```
|
||||
|
||||
也应用激进修复(会覆盖自定义 supervisor 配置)。
|
||||
还会应用激进修复(覆盖自定义 supervisor 配置)。
|
||||
|
||||
</Tab>
|
||||
<Tab title="--non-interactive">
|
||||
@ -54,7 +54,7 @@ openclaw doctor
|
||||
openclaw doctor --non-interactive
|
||||
```
|
||||
|
||||
在不提示的情况下运行,并且只应用安全迁移(配置规范化 + 磁盘状态移动)。会跳过需要人工确认的重启/服务/沙箱操作。检测到旧版状态时,旧版状态迁移会自动运行。
|
||||
在无提示的情况下运行,并且只应用安全迁移(配置规范化 + 磁盘状态移动)。会跳过需要人工确认的重启/服务/沙箱操作。检测到旧版状态迁移时会自动运行。
|
||||
|
||||
</Tab>
|
||||
<Tab title="--deep">
|
||||
@ -62,12 +62,12 @@ openclaw doctor
|
||||
openclaw doctor --deep
|
||||
```
|
||||
|
||||
扫描系统服务以查找额外的 Gateway 网关安装(`launchd`/`systemd`/`schtasks`)。
|
||||
扫描系统服务以查找额外的 Gateway 网关 安装(`launchd`/`systemd`/`schtasks`)。
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
如果你想在写入前先查看变更,请先打开配置文件:
|
||||
如果你想在写入前先查看更改,请先打开配置文件:
|
||||
|
||||
```bash
|
||||
cat ~/.openclaw/openclaw.json
|
||||
@ -76,104 +76,105 @@ cat ~/.openclaw/openclaw.json
|
||||
## 它会做什么(摘要)
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="健康、UI 和更新">
|
||||
- 针对 git 安装的可选预检更新(仅限交互模式)。
|
||||
- UI 协议新鲜度检查(当协议 schema 更新时重建 Control UI)。
|
||||
<Accordion title="健康状况、UI 和更新">
|
||||
- 可选的 Git 安装预检更新(仅限交互模式)。
|
||||
- UI 协议新鲜度检查(当协议 schema 较新时重建 Control UI)。
|
||||
- 健康检查 + 重启提示。
|
||||
- Skills 状态摘要(可用/缺失/被阻止)和插件状态。
|
||||
- Skills 状态摘要(可用/缺失/阻止)和插件状态。
|
||||
</Accordion>
|
||||
<Accordion title="配置和迁移">
|
||||
- 旧版值的配置规范化。
|
||||
- 将旧版扁平 `talk.*` 字段迁移为 `talk.provider` + `talk.providers.<provider>` 的 Talk 配置迁移。
|
||||
- 针对旧版 Chrome 扩展配置和 Chrome MCP 就绪状态的浏览器迁移检查。
|
||||
- OpenCode provider 覆盖警告(`models.providers.opencode` / `models.providers.opencode-go`)。
|
||||
- 将旧版扁平 `talk.*` 字段迁移到 `talk.provider` + `talk.providers.<provider>` 的 Talk 配置迁移。
|
||||
- 针对旧版 Chrome 扩展配置和 Chrome MCP 就绪情况的浏览器迁移检查。
|
||||
- OpenCode 提供商覆盖警告(`models.providers.opencode` / `models.providers.opencode-go`)。
|
||||
- Codex OAuth 遮蔽警告(`models.providers.openai-codex`)。
|
||||
- OpenAI Codex OAuth 配置文件的 OAuth TLS 前提条件检查。
|
||||
- OpenAI Codex OAuth profile 的 OAuth TLS 前置条件检查。
|
||||
- 旧版磁盘状态迁移(会话/智能体目录/WhatsApp 认证)。
|
||||
- 旧版插件清单契约键迁移(`speechProviders`、`realtimeTranscriptionProviders`、`realtimeVoiceProviders`、`mediaUnderstandingProviders`、`imageGenerationProviders`、`videoGenerationProviders`、`webFetchProviders`、`webSearchProviders` → `contracts`)。
|
||||
- 旧版插件 manifest 合约键迁移(`speechProviders`、`realtimeTranscriptionProviders`、`realtimeVoiceProviders`、`mediaUnderstandingProviders`、`imageGenerationProviders`、`videoGenerationProviders`、`webFetchProviders`、`webSearchProviders` → `contracts`)。
|
||||
- 旧版 cron 存储迁移(`jobId`、`schedule.cron`、顶层 delivery/payload 字段、payload `provider`、简单的 `notify: true` webhook 回退任务)。
|
||||
- 将旧版智能体运行时策略迁移到 `agents.defaults.agentRuntime` 和 `agents.list[].agentRuntime`。
|
||||
</Accordion>
|
||||
<Accordion title="状态和完整性">
|
||||
- 会话锁文件检查和过期锁清理。
|
||||
- 针对受影响的 2026.4.24 构建所创建的重复 prompt-rewrite 分支进行会话转录修复。
|
||||
- 会话锁文件检查和过时锁清理。
|
||||
- 修复受影响的 2026.4.24 构建所创建的重复 prompt-rewrite 分支造成的会话转录。
|
||||
- 状态完整性和权限检查(会话、转录、状态目录)。
|
||||
- 本地运行时的配置文件权限检查(`chmod 600`)。
|
||||
- 模型认证健康状态:检查 OAuth 过期情况、可以刷新即将过期的令牌,并报告 auth-profile 的冷却/禁用状态。
|
||||
- 模型认证健康检查:检查 OAuth 过期情况,可刷新即将过期的 token,并报告 auth-profile 冷却/禁用状态。
|
||||
- 额外工作区目录检测(`~/openclaw`)。
|
||||
</Accordion>
|
||||
<Accordion title="Gateway 网关、服务和 supervisor">
|
||||
- 在启用沙箱隔离时修复沙箱镜像。
|
||||
- 旧版服务迁移和额外 Gateway 网关检测。
|
||||
<Accordion title="Gateway、服务和 supervisor">
|
||||
- 启用沙箱隔离时的沙箱镜像修复。
|
||||
- 旧版服务迁移和额外 Gateway 网关 检测。
|
||||
- Matrix 渠道旧版状态迁移(在 `--fix` / `--repair` 模式下)。
|
||||
- Gateway 网关运行时检查(服务已安装但未运行;缓存的 `launchd` 标签)。
|
||||
- 渠道状态警告(从正在运行的 Gateway 网关探测)。
|
||||
- supervisor 配置审计(`launchd`/`systemd`/`schtasks`)及可选修复。
|
||||
- Gateway 网关运行时最佳实践检查(Node 与 Bun、版本管理器路径)。
|
||||
- Gateway 网关端口冲突诊断(默认 `18789`)。
|
||||
- Gateway 网关 运行时检查(服务已安装但未运行;缓存的 `launchd` 标签)。
|
||||
- 渠道状态警告(从正在运行的 Gateway 网关 探测)。
|
||||
- supervisor 配置审计(`launchd`/`systemd`/`schtasks`),可选修复。
|
||||
- Gateway 网关 运行时最佳实践检查(Node 与 Bun、版本管理器路径)。
|
||||
- Gateway 网关 端口冲突诊断(默认 `18789`)。
|
||||
</Accordion>
|
||||
<Accordion title="认证、安全和配对">
|
||||
<Accordion title="认证、安全性和配对">
|
||||
- 针对开放私信策略的安全警告。
|
||||
- 本地令牌模式下的 Gateway 网关认证检查(当不存在令牌来源时提供令牌生成功能;不会覆盖令牌 `SecretRef` 配置)。
|
||||
- 设备配对问题检测(待处理的首次配对请求、待处理的角色/作用域升级、本地设备令牌缓存漂移过期,以及已配对记录认证漂移)。
|
||||
- 本地 token 模式下的 Gateway 网关 认证检查(当不存在 token 源时提供 token 生成功能;不会覆盖 token SecretRef 配置)。
|
||||
- 设备配对故障检测(待处理的首次配对请求、待处理的角色/作用域升级、过时的本地设备 token 缓存漂移,以及已配对记录认证漂移)。
|
||||
</Accordion>
|
||||
<Accordion title="工作区和 shell">
|
||||
- Linux 上的 `systemd linger` 检查。
|
||||
- 工作区 bootstrap 文件大小检查(针对上下文文件的截断/接近上限警告)。
|
||||
- Shell 补全状态检查以及自动安装/升级。
|
||||
- Memory 搜索 embedding provider 就绪状态检查(本地模型、远程 API key 或 QMD 二进制文件)。
|
||||
- 源码安装检查(`pnpm` 工作区不匹配、缺失 UI 资源、缺失 `tsx` 二进制文件)。
|
||||
- shell 补全状态检查和自动安装/升级。
|
||||
- Memory 搜索嵌入提供商就绪检查(本地模型、远程 API 密钥或 QMD 二进制文件)。
|
||||
- 源码安装检查(`pnpm` 工作区不匹配、缺失的 UI 资源、缺失的 `tsx` 二进制文件)。
|
||||
- 写入更新后的配置 + 向导元数据。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Dreams UI 回填和重置
|
||||
|
||||
Control UI 的 Dreams 场景包含 **Backfill**、**Reset** 和 **Clear Grounded** 操作,用于 grounded dreaming 工作流。这些操作使用 Gateway 网关风格的 doctor RPC 方法,但它们**不是** `openclaw doctor` CLI 修复/迁移的一部分。
|
||||
Control UI Dreams 场景包含用于 grounded dreaming 工作流的 **Backfill**、**Reset** 和 **Clear Grounded** 操作。这些操作使用 Gateway 网关 doctor 风格的 RPC 方法,但它们**不是** `openclaw doctor` CLI 修复/迁移的一部分。
|
||||
|
||||
它们的作用:
|
||||
|
||||
- **Backfill** 会扫描活动工作区中的历史 `memory/YYYY-MM-DD.md` 文件,运行 grounded REM 日记处理流程,并将可逆的回填条目写入 `DREAMS.md`。
|
||||
- **Reset** 只会从 `DREAMS.md` 中移除那些已标记的回填日记条目。
|
||||
- **Clear Grounded** 只会移除那些来自历史回放、且尚未积累实时 recall 或每日支持的 staged grounded-only 短期条目。
|
||||
- **Backfill** 会扫描活动工作区中的历史 `memory/YYYY-MM-DD.md` 文件,运行 grounded REM 日记处理,并将可逆的回填条目写入 `DREAMS.md`。
|
||||
- **Reset** 仅从 `DREAMS.md` 中移除这些已标记的回填日记条目。
|
||||
- **Clear Grounded** 仅移除来自历史回放、且尚未积累实时 recall 或每日支持的 staged grounded-only 短期条目。
|
||||
|
||||
它们**本身不会**做的事情:
|
||||
它们本身**不会**做的事:
|
||||
|
||||
- 不会编辑 `MEMORY.md`
|
||||
- 不会运行完整的 doctor 迁移
|
||||
- 不会自动将 grounded 候选项加入实时短期提升存储,除非你先显式运行 staged CLI 路径
|
||||
- 除非你先显式运行 staged CLI 路径,否则不会自动将 grounded 候选项 staged 到实时短期提升存储中
|
||||
|
||||
如果你想让 grounded 历史回放影响正常的深度提升路径,请改用 CLI 流程:
|
||||
如果你希望 grounded 历史回放影响正常的深度提升通道,请改用 CLI 流程:
|
||||
|
||||
```bash
|
||||
openclaw memory rem-backfill --path ./memory --stage-short-term
|
||||
```
|
||||
|
||||
这样会在将 `DREAMS.md` 作为审查界面的同时,把 grounded durable 候选项加入短期 dreaming 存储。
|
||||
这样会将 grounded durable 候选项 staged 到短期 dreaming 存储中,同时保留 `DREAMS.md` 作为审查界面。
|
||||
|
||||
## 详细行为和原理说明
|
||||
## 详细行为和理由
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="0. 可选更新(git 安装)">
|
||||
如果这是一个 git checkout,且 doctor 以交互方式运行,它会在运行 doctor 之前提供更新选项(fetch/rebase/build)。
|
||||
<Accordion title="0. 可选更新(Git 安装)">
|
||||
如果这是一个 Git 检出,并且 doctor 正在交互式运行,它会在运行 doctor 之前提供更新(fetch/rebase/build)。
|
||||
</Accordion>
|
||||
<Accordion title="1. 配置规范化">
|
||||
如果配置包含旧版值结构(例如没有特定渠道覆盖的 `messages.ackReaction`),doctor 会将其规范化为当前 schema。
|
||||
如果配置包含旧版值形状(例如没有渠道特定覆盖的 `messages.ackReaction`),doctor 会将其规范化为当前 schema。
|
||||
|
||||
这也包括旧版 Talk 扁平字段。当前公开的 Talk 配置是 `talk.provider` + `talk.providers.<provider>`。Doctor 会将旧的 `talk.voiceId` / `talk.voiceAliases` / `talk.modelId` / `talk.outputFormat` / `talk.apiKey` 结构重写到 provider 映射中。
|
||||
这包括旧版 Talk 扁平字段。当前公开的 Talk 配置是 `talk.provider` + `talk.providers.<provider>`。Doctor 会将旧的 `talk.voiceId` / `talk.voiceAliases` / `talk.modelId` / `talk.outputFormat` / `talk.apiKey` 形状重写到提供商映射中。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="2. 旧版配置键迁移">
|
||||
当配置包含已弃用键时,其他命令会拒绝运行,并要求你运行 `openclaw doctor`。
|
||||
|
||||
Doctor 会:
|
||||
Doctor 将会:
|
||||
|
||||
- 说明发现了哪些旧版键。
|
||||
- 显示它所应用的迁移。
|
||||
- 解释找到了哪些旧版键。
|
||||
- 显示它应用的迁移。
|
||||
- 使用更新后的 schema 重写 `~/.openclaw/openclaw.json`。
|
||||
|
||||
当 Gateway 网关在启动时检测到旧版配置格式,也会自动运行 doctor 迁移,因此过时配置无需人工干预即可修复。Cron 任务存储迁移由 `openclaw doctor --fix` 处理。
|
||||
当 Gateway 网关 在启动时检测到旧版配置格式,也会自动运行 doctor 迁移,因此过时配置无需人工干预即可修复。Cron 任务存储迁移由 `openclaw doctor --fix` 处理。
|
||||
|
||||
当前迁移包括:
|
||||
当前迁移:
|
||||
|
||||
- `routing.allowFrom` → `channels.whatsapp.allowFrom`
|
||||
- `routing.groupChat.requireMention` → `channels.whatsapp/telegram/imessage.groups."*".requireMention`
|
||||
@ -196,64 +197,64 @@ openclaw memory rem-backfill --path ./memory --stage-short-term
|
||||
- `plugins.entries.voice-call.config.streaming.sttProvider` → `plugins.entries.voice-call.config.streaming.provider`
|
||||
- `plugins.entries.voice-call.config.streaming.openaiApiKey|sttModel|silenceDurationMs|vadThreshold` → `plugins.entries.voice-call.config.streaming.providers.openai.*`
|
||||
- `bindings[].match.accountID` → `bindings[].match.accountId`
|
||||
- 对于配置了具名 `accounts` 但仍残留单账户顶层渠道值的渠道,将这些账户作用域的值移动到为该渠道选定的提升账户中(大多数渠道使用 `accounts.default`;Matrix 可以保留现有匹配的具名/默认目标)
|
||||
- 对于已命名 `accounts` 但仍保留单账号顶层渠道值的渠道,将这些账号作用域值移入该渠道选定的提升账号中(大多数渠道使用 `accounts.default`;Matrix 可以保留现有匹配的已命名/默认目标)
|
||||
- `identity` → `agents.list[].identity`
|
||||
- `agent.*` → `agents.defaults` + `tools.*`(tools/elevated/exec/sandbox/subagents)
|
||||
- `agent.model`/`allowedModels`/`modelAliases`/`modelFallbacks`/`imageModelFallbacks` → `agents.defaults.models` + `agents.defaults.model.primary/fallbacks` + `agents.defaults.imageModel.primary/fallbacks`
|
||||
- `browser.ssrfPolicy.allowPrivateNetwork` → `browser.ssrfPolicy.dangerouslyAllowPrivateNetwork`
|
||||
- `browser.profiles.*.driver: "extension"` → `"existing-session"`
|
||||
- 移除 `browser.relayBindHost`(旧版扩展 relay 设置)
|
||||
- 删除 `browser.relayBindHost`(旧版扩展 relay 设置)
|
||||
|
||||
Doctor 警告还包括多账户渠道的默认账户指引:
|
||||
Doctor 警告还包括多账号渠道的默认账号指导:
|
||||
|
||||
- 如果配置了两个或更多 `channels.<channel>.accounts` 条目,但没有 `channels.<channel>.defaultAccount` 或 `accounts.default`,doctor 会警告回退路由可能选择意外的账户。
|
||||
- 如果 `channels.<channel>.defaultAccount` 设置为未知账户 ID,doctor 会发出警告并列出已配置的账户 ID。
|
||||
- 如果已配置两个或更多 `channels.<channel>.accounts` 条目,但未设置 `channels.<channel>.defaultAccount` 或 `accounts.default`,doctor 会警告回退路由可能选择意外账号。
|
||||
- 如果 `channels.<channel>.defaultAccount` 被设置为未知账号 ID,doctor 会发出警告并列出已配置的账号 ID。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="2b. OpenCode provider 覆盖">
|
||||
如果你手动添加了 `models.providers.opencode`、`opencode-zen` 或 `opencode-go`,它会覆盖来自 `@mariozechner/pi-ai` 的内置 OpenCode 目录。这可能会强行让模型走错误的 API,或者将费用归零。Doctor 会发出警告,以便你移除该覆盖并恢复按模型的 API 路由 + 费用。
|
||||
<Accordion title="2b. OpenCode 提供商覆盖">
|
||||
如果你手动添加了 `models.providers.opencode`、`opencode-zen` 或 `opencode-go`,它会覆盖来自 `@mariozechner/pi-ai` 的内置 OpenCode 目录。这可能会迫使模型走错 API,或将成本清零。Doctor 会发出警告,以便你移除该覆盖并恢复按模型的 API 路由 + 成本。
|
||||
</Accordion>
|
||||
<Accordion title="2c. 浏览器迁移和 Chrome MCP 就绪状态">
|
||||
如果你的浏览器配置仍然指向已移除的 Chrome 扩展路径,doctor 会将其规范化为当前基于主机本地 Chrome MCP attach 模式的配置:
|
||||
<Accordion title="2c. 浏览器迁移和 Chrome MCP 就绪情况">
|
||||
如果你的浏览器配置仍指向已移除的 Chrome 扩展路径,doctor 会将其规范化为当前的主机本地 Chrome MCP 附加模型:
|
||||
|
||||
- `browser.profiles.*.driver: "extension"` 会变为 `"existing-session"`
|
||||
- `browser.relayBindHost` 会被移除
|
||||
- `browser.relayBindHost` 会被删除
|
||||
|
||||
当你使用 `defaultProfile: "user"` 或配置了 `existing-session` 配置文件时,doctor 还会审计主机本地 Chrome MCP 路径:
|
||||
Doctor 还会在你使用 `defaultProfile: "user"` 或已配置的 `existing-session` profile 时,审计主机本地 Chrome MCP 路径:
|
||||
|
||||
- 检查默认自动连接配置文件所需的 Google Chrome 是否安装在同一主机上
|
||||
- 检查 Google Chrome 是否安装在同一主机上,以供默认自动连接 profile 使用
|
||||
- 检查检测到的 Chrome 版本,并在其低于 Chrome 144 时发出警告
|
||||
- 提醒你在浏览器的 inspect 页面中启用 remote debugging(例如 `chrome://inspect/#remote-debugging`、`brave://inspect/#remote-debugging` 或 `edge://inspect/#remote-debugging`)
|
||||
- 提醒你在浏览器 inspect 页面中启用远程调试(例如 `chrome://inspect/#remote-debugging`、`brave://inspect/#remote-debugging` 或 `edge://inspect/#remote-debugging`)
|
||||
|
||||
Doctor 无法替你启用 Chrome 端设置。主机本地 Chrome MCP 仍然要求:
|
||||
Doctor 不能替你启用 Chrome 侧设置。主机本地 Chrome MCP 仍然需要:
|
||||
|
||||
- Gateway 网关/节点主机上安装了 144+ 的 Chromium 内核浏览器
|
||||
- 浏览器正在本地运行
|
||||
- 该浏览器已启用 remote debugging
|
||||
- 在浏览器中批准首次 attach 同意提示
|
||||
- Gateway 网关/节点主机上安装 Chromium 内核浏览器 144+
|
||||
- 浏览器在本地运行
|
||||
- 在该浏览器中启用远程调试
|
||||
- 在浏览器中批准首次附加同意提示
|
||||
|
||||
这里的就绪状态仅针对本地 attach 的前提条件。`existing-session` 会保留当前 Chrome MCP 路由限制;像 `responsebody`、PDF 导出、下载拦截和批量操作这样的高级路由,仍然需要托管浏览器或原始 CDP 配置文件。
|
||||
这里的就绪情况仅指本地附加前置条件。Existing-session 会保留当前 Chrome MCP 路由限制;像 `responsebody`、PDF 导出、下载拦截和批量操作这样的高级路由仍然需要受管浏览器或原始 CDP profile。
|
||||
|
||||
此检查**不**适用于 Docker、沙箱、remote-browser 或其他无头流程。这些流程会继续使用原始 CDP。
|
||||
此检查**不**适用于 Docker、沙箱、remote-browser 或其他无头流程。那些流程将继续使用原始 CDP。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="2d. OAuth TLS 前提条件">
|
||||
配置 OpenAI Codex OAuth 配置文件后,doctor 会探测 OpenAI 授权端点,以验证本地 Node/OpenSSL TLS 栈能否校验证书链。如果探测因证书错误而失败(例如 `UNABLE_TO_GET_ISSUER_CERT_LOCALLY`、证书过期或自签名证书),doctor 会输出与平台对应的修复指引。在使用 Homebrew Node 的 macOS 上,修复方式通常是 `brew postinstall ca-certificates`。使用 `--deep` 时,即使 Gateway 网关健康,该探测也会运行。
|
||||
<Accordion title="2d. OAuth TLS 前置条件">
|
||||
配置了 OpenAI Codex OAuth profile 时,doctor 会探测 OpenAI 授权端点,以验证本地 Node/OpenSSL TLS 栈是否可以校验证书链。如果探测因证书错误而失败(例如 `UNABLE_TO_GET_ISSUER_CERT_LOCALLY`、证书过期或自签名证书),doctor 会打印特定于平台的修复指导。在 macOS 上使用 Homebrew Node 时,修复通常是 `brew postinstall ca-certificates`。使用 `--deep` 时,即使 Gateway 网关 健康,该探测也会运行。
|
||||
</Accordion>
|
||||
<Accordion title="2e. Codex OAuth provider 覆盖">
|
||||
如果你之前在 `models.providers.openai-codex` 下添加了旧版 OpenAI 传输设置,它们可能会遮蔽新版默认使用的内置 Codex OAuth provider 路径。当 doctor 看到这些旧传输设置与 Codex OAuth 同时存在时,会发出警告,这样你就可以移除或重写过时的传输覆盖,并恢复内置路由/回退行为。自定义代理和仅 header 的覆盖仍受支持,并且不会触发此警告。
|
||||
<Accordion title="2e. Codex OAuth 提供商覆盖">
|
||||
如果你之前在 `models.providers.openai-codex` 下添加了旧版 OpenAI 传输设置,它们可能会遮蔽较新版本自动使用的内置 Codex OAuth provider 路径。当 doctor 在 Codex OAuth 旁边看到这些旧传输设置时,会发出警告,以便你删除或重写过时的传输覆盖,并恢复内置路由/回退行为。自定义代理和仅 header 的覆盖仍然受支持,不会触发此警告。
|
||||
</Accordion>
|
||||
<Accordion title="2f. Codex 插件路由警告">
|
||||
启用内置 Codex 插件时,doctor 还会检查 `openai-codex/*` 主模型引用是否仍通过默认 PI 运行器解析。当你想通过 PI 使用 Codex OAuth/订阅认证时,这种组合是有效的,但它很容易与原生 Codex app-server harness 混淆。Doctor 会发出警告,并指向显式的 app-server 形式:`openai/*` 加上 `embeddedHarness.runtime: "codex"` 或 `OPENCLAW_AGENT_RUNTIME=codex`。
|
||||
启用内置 Codex 插件时,doctor 还会检查 `openai-codex/*` 主模型引用是否仍通过默认 PI runner 解析。当你想通过 PI 使用 Codex OAuth/订阅认证时,这种组合是有效的,但它很容易与原生 Codex app-server harness 混淆。Doctor 会发出警告,并指向显式的 app-server 形状:`openai/*` 加 `agentRuntime.id: "codex"` 或 `OPENCLAW_AGENT_RUNTIME=codex`。
|
||||
|
||||
Doctor 不会自动修复这一点,因为这两条路径都有效:
|
||||
Doctor 不会自动修复这一点,因为这两种路由都有效:
|
||||
|
||||
- `openai-codex/*` + PI 表示“通过普通 OpenClaw 运行器使用 Codex OAuth/订阅认证。”
|
||||
- `openai/*` + `runtime: "codex"` 表示“通过原生 Codex app-server 运行嵌入式 turn。”
|
||||
- `/codex ...` 表示“在聊天中控制或绑定一个原生 Codex 会话。”
|
||||
- `openai-codex/*` + PI 表示“通过常规 OpenClaw runner 使用 Codex OAuth/订阅认证。”
|
||||
- `openai/*` + `runtime: "codex"` 表示“通过原生 Codex app-server 运行嵌入式轮次。”
|
||||
- `/codex ...` 表示“从聊天中控制或绑定一个原生 Codex 会话。”
|
||||
- `/acp ...` 或 `runtime: "acp"` 表示“使用外部 ACP/acpx 适配器。”
|
||||
|
||||
如果出现此警告,请选择你想要的路径并手动编辑配置。如果你是有意使用 PI Codex OAuth,请保持该警告不变。
|
||||
如果出现该警告,请选择你原本打算使用的路由,并手动编辑配置。如果 PI Codex OAuth 是有意为之,请保持该警告原样。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="3. 旧版状态迁移(磁盘布局)">
|
||||
@ -264,17 +265,17 @@ openclaw memory rem-backfill --path ./memory --stage-short-term
|
||||
- 智能体目录:
|
||||
- 从 `~/.openclaw/agent/` 到 `~/.openclaw/agents/<agentId>/agent/`
|
||||
- WhatsApp 认证状态(Baileys):
|
||||
- 从旧版 `~/.openclaw/credentials/*.json`(`oauth.json` 除外)
|
||||
- 到 `~/.openclaw/credentials/whatsapp/<accountId>/...`(默认账户 ID:`default`)
|
||||
- 从旧版 `~/.openclaw/credentials/*.json`(不包括 `oauth.json`)
|
||||
- 到 `~/.openclaw/credentials/whatsapp/<accountId>/...`(默认账号 ID:`default`)
|
||||
|
||||
这些迁移会尽力执行且具备幂等性;如果 doctor 留下任何旧版文件夹作为备份,它会发出警告。Gateway 网关/CLI 在启动时也会自动迁移旧版会话 + 智能体目录,因此历史记录/认证/模型会进入每个智能体的专属路径,无需手动运行 doctor。WhatsApp 认证有意只通过 `openclaw doctor` 迁移。Talk provider/provider-map 规范化现在按结构相等进行比较,因此仅键顺序不同的差异不会再触发重复且无实际变更的 `doctor --fix`。
|
||||
这些迁移以尽力而为且幂等的方式执行;当 doctor 将任何旧版文件夹保留为备份时,会发出警告。Gateway 网关/CLI 也会在启动时自动迁移旧版会话 + 智能体目录,因此历史记录/认证/模型会落到每个智能体的路径下,而无需手动运行 doctor。WhatsApp 认证有意只通过 `openclaw doctor` 迁移。Talk provider/provider-map 规范化现在按结构相等性比较,因此仅键顺序不同的差异不再触发重复的无操作 `doctor --fix` 更改。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="3a. 旧版插件清单迁移">
|
||||
Doctor 会扫描所有已安装插件清单中的已弃用顶层能力键(`speechProviders`、`realtimeTranscriptionProviders`、`realtimeVoiceProviders`、`mediaUnderstandingProviders`、`imageGenerationProviders`、`videoGenerationProviders`、`webFetchProviders`、`webSearchProviders`)。找到后,它会提供将它们移动到 `contracts` 对象并原地重写清单文件的选项。此迁移具有幂等性;如果 `contracts` 键已经包含相同的值,则会移除旧版键而不会重复数据。
|
||||
<Accordion title="3a. 旧版插件 manifest 迁移">
|
||||
Doctor 会扫描所有已安装插件的 manifest,查找已弃用的顶层能力键(`speechProviders`、`realtimeTranscriptionProviders`、`realtimeVoiceProviders`、`mediaUnderstandingProviders`、`imageGenerationProviders`、`videoGenerationProviders`、`webFetchProviders`、`webSearchProviders`)。找到后,它会提议将它们移动到 `contracts` 对象中,并原地重写 manifest 文件。该迁移是幂等的;如果 `contracts` 键中已包含相同值,则会删除旧版键,而不会重复数据。
|
||||
</Accordion>
|
||||
<Accordion title="3b. 旧版 cron 存储迁移">
|
||||
Doctor 还会检查 cron 任务存储(默认是 `~/.openclaw/cron/jobs.json`,或在覆盖时使用 `cron.store`),查看调度器为兼容性仍然接受的旧任务结构。
|
||||
Doctor 还会检查 cron 任务存储(默认是 `~/.openclaw/cron/jobs.json`,或覆盖时使用 `cron.store`),查找调度器仍为兼容性而接受的旧任务形状。
|
||||
|
||||
当前 cron 清理包括:
|
||||
|
||||
@ -283,38 +284,38 @@ openclaw memory rem-backfill --path ./memory --stage-short-term
|
||||
- 顶层 payload 字段(`message`、`model`、`thinking`、...)→ `payload`
|
||||
- 顶层 delivery 字段(`deliver`、`channel`、`to`、`provider`、...)→ `delivery`
|
||||
- payload `provider` delivery 别名 → 显式 `delivery.channel`
|
||||
- 简单旧版 `notify: true` webhook 回退任务 → 显式 `delivery.mode="webhook"`,并设置 `delivery.to=cron.webhook`
|
||||
- 简单的旧版 `notify: true` webhook 回退任务 → 显式 `delivery.mode="webhook"` 且 `delivery.to=cron.webhook`
|
||||
|
||||
只有当 doctor 能在不改变行为的前提下迁移 `notify: true` 任务时,才会自动执行迁移。如果某个任务将旧版 notify 回退与现有的非 webhook delivery 模式结合使用,doctor 会发出警告,并将该任务保留供人工审查。
|
||||
Doctor 仅在能够不改变行为的情况下自动迁移 `notify: true` 任务。如果某个任务将旧版 notify 回退与现有的非 webhook delivery 模式组合在一起,doctor 会发出警告,并将该任务留待手动审查。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="3c. 会话锁清理">
|
||||
Doctor 会扫描每个智能体会话目录中的过期写锁文件——这些文件是在会话异常退出时遗留的。对于每个找到的锁文件,它会报告:路径、PID、该 PID 是否仍存活、锁龄,以及它是否被视为过期(PID 已失效或已超过 30 分钟)。在 `--fix` / `--repair` 模式下,它会自动移除过期锁文件;否则会输出说明,并提示你使用 `--fix` 重新运行。
|
||||
Doctor 会扫描每个智能体会话目录中的过时写锁文件 —— 这些文件是在会话异常退出时遗留下来的。对于找到的每个锁文件,它会报告:路径、PID、该 PID 是否仍然存活、锁年龄,以及它是否被视为过时(PID 已死亡或超过 30 分钟)。在 `--fix` / `--repair` 模式下,它会自动移除过时锁文件;否则会打印说明,并提示你使用 `--fix` 重新运行。
|
||||
</Accordion>
|
||||
<Accordion title="3d. 会话转录分支修复">
|
||||
Doctor 会扫描智能体会话 JSONL 文件,查找由 2026.4.24 prompt transcript 重写缺陷创建的重复分支结构:一个已放弃的用户 turn,带有 OpenClaw 内部运行时上下文;以及一个活动的同级分支,包含相同的可见用户提示。在 `--fix` / `--repair` 模式下,doctor 会在每个受影响文件的原文件旁创建备份,并将转录重写为活动分支,这样 Gateway 网关历史记录和 Memory 读取器就不会再看到重复 turn。
|
||||
Doctor 会扫描智能体会话 JSONL 文件,查找由 2026.4.24 prompt transcript 重写 bug 创建的重复分支形状:一个已放弃的用户轮次,包含 OpenClaw 内部运行时上下文,以及一个活动同级分支,包含相同的可见用户提示。在 `--fix` / `--repair` 模式下,doctor 会在原文件旁为每个受影响文件创建备份,并将转录重写为活动分支,从而让 Gateway 网关 历史和 Memory 读取器不再看到重复轮次。
|
||||
</Accordion>
|
||||
<Accordion title="4. 状态完整性检查(会话持久化、路由和安全)">
|
||||
状态目录是运行层面的中枢。如果它消失了,你会失去会话、凭证、日志和配置(除非你在其他地方有备份)。
|
||||
<Accordion title="4. 状态完整性检查(会话持久化、路由和安全性)">
|
||||
状态目录是运行层面的脑干。它一旦消失,你就会丢失会话、凭证、日志和配置(除非你在别处有备份)。
|
||||
|
||||
Doctor 会检查:
|
||||
|
||||
- **状态目录缺失**:警告灾难性状态丢失,提示重新创建目录,并提醒你它无法恢复丢失的数据。
|
||||
- **状态目录权限**:验证可写性;提供修复权限的选项(并在检测到所有者/组不匹配时给出 `chown` 提示)。
|
||||
- **macOS 云同步状态目录**:当状态路径位于 iCloud Drive(`~/Library/Mobile Documents/com~apple~CloudDocs/...`)或 `~/Library/CloudStorage/...` 下时发出警告,因为同步支持的路径可能导致更慢的 I/O 以及锁/同步竞争。
|
||||
- **Linux SD 或 eMMC 状态目录**:当状态路径解析到 `mmcblk*` 挂载源时发出警告,因为基于 SD 或 eMMC 的随机 I/O 在会话和凭证写入负载下可能更慢且磨损更快。
|
||||
- **会话目录缺失**:`sessions/` 和会话存储目录是持久化历史记录并避免 `ENOENT` 崩溃所必需的。
|
||||
- **转录不匹配**:当最近的会话条目缺少转录文件时发出警告。
|
||||
- **主会话“单行 JSONL”**:当主转录只有一行时发出标记(说明历史记录没有持续累积)。
|
||||
- **多个状态目录**:当多个主目录下存在多个 `~/.openclaw` 文件夹,或者 `OPENCLAW_STATE_DIR` 指向其他位置时发出警告(历史记录可能在多个安装之间分裂)。
|
||||
- **远程模式提醒**:如果 `gateway.mode=remote`,doctor 会提醒你在远程主机上运行它(状态保存在那里)。
|
||||
- **配置文件权限**:如果 `~/.openclaw/openclaw.json` 对组/全局可读,会发出警告,并提供将权限收紧为 `600` 的选项。
|
||||
- **状态目录缺失**:警告灾难性的状态丢失,提示重新创建目录,并提醒你它无法恢复缺失的数据。
|
||||
- **状态目录权限**:验证可写性;如果检测到所有者/组不匹配,则提供修复权限的选项(并给出 `chown` 提示)。
|
||||
- **macOS 云同步状态目录**:当状态解析到 iCloud Drive(`~/Library/Mobile Documents/com~apple~CloudDocs/...`)或 `~/Library/CloudStorage/...` 下时发出警告,因为基于同步的路径可能导致更慢的 I/O 以及锁/同步竞争。
|
||||
- **Linux SD 或 eMMC 状态目录**:当状态解析到 `mmcblk*` 挂载源时发出警告,因为基于 SD 或 eMMC 的随机 I/O 在会话和凭证写入下可能更慢且磨损更快。
|
||||
- **会话目录缺失**:`sessions/` 和会话存储目录是持久化历史并避免 `ENOENT` 崩溃所必需的。
|
||||
- **转录不匹配**:当最近的会话条目缺失转录文件时发出警告。
|
||||
- **主会话“1 行 JSONL”**:当主转录只有一行时标记(历史未在累积)。
|
||||
- **多个状态目录**:当不同主目录中存在多个 `~/.openclaw` 文件夹,或 `OPENCLAW_STATE_DIR` 指向其他位置时发出警告(历史可能在不同安装之间分裂)。
|
||||
- **远程模式提醒**:如果 `gateway.mode=remote`,doctor 会提醒你在远程主机上运行它(状态就存储在那里)。
|
||||
- **配置文件权限**:如果 `~/.openclaw/openclaw.json` 对组/所有人可读,则发出警告,并提供收紧为 `600` 的选项。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="5. 模型认证健康状态(OAuth 过期)">
|
||||
Doctor 会检查认证存储中的 OAuth 配置文件,在令牌即将过期/已过期时发出警告,并在安全时刷新它们。如果 Anthropic OAuth/令牌配置文件已过期,它会建议你使用 Anthropic API key 或 Anthropic setup-token 路径。刷新提示只会在交互模式(TTY)下出现;`--non-interactive` 会跳过刷新尝试。
|
||||
<Accordion title="5. 模型认证健康状况(OAuth 过期)">
|
||||
Doctor 会检查认证存储中的 OAuth profile,在 token 即将过期/已过期时发出警告,并可在安全情况下刷新它们。如果 Anthropic OAuth/token profile 已过时,它会建议使用 Anthropic API 密钥或 Anthropic setup-token 路径。刷新提示仅在交互式(TTY)运行时显示;`--non-interactive` 会跳过刷新尝试。
|
||||
|
||||
当 OAuth 刷新永久失败时(例如 `refresh_token_reused`、`invalid_grant`,或提供商提示你需要重新登录),doctor 会报告需要重新认证,并输出确切的 `openclaw models auth login --provider ...` 命令供你执行。
|
||||
当 OAuth 刷新永久失败时(例如 `refresh_token_reused`、`invalid_grant`,或提供商要求你重新登录),doctor 会报告需要重新认证,并打印要运行的精确 `openclaw models auth login --provider ...` 命令。
|
||||
|
||||
Doctor 还会报告因以下原因而暂时不可用的 auth-profile:
|
||||
|
||||
@ -322,146 +323,146 @@ openclaw memory rem-backfill --path ./memory --stage-short-term
|
||||
- 较长期禁用(计费/额度失败)
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="6. Hooks 模型校验">
|
||||
如果设置了 `hooks.gmail.model`,doctor 会根据目录和 allowlist 校验该模型引用,并在它无法解析或不被允许时发出警告。
|
||||
<Accordion title="6. 钩子模型验证">
|
||||
如果设置了 `hooks.gmail.model`,doctor 会根据目录和 allowlist 验证模型引用,并在其无法解析或不被允许时发出警告。
|
||||
</Accordion>
|
||||
<Accordion title="7. 沙箱镜像修复">
|
||||
启用沙箱隔离时,doctor 会检查 Docker 镜像,并在当前镜像缺失时提供构建或切换到旧版名称的选项。
|
||||
</Accordion>
|
||||
<Accordion title="7b. 内置插件运行时依赖">
|
||||
Doctor 只会为当前配置中激活或由其内置清单默认启用的内置插件验证运行时依赖,例如 `plugins.entries.discord.enabled: true`、旧版 `channels.discord.enabled: true`,或默认启用的内置 provider。如果有依赖缺失,doctor 会报告这些包,并在 `openclaw doctor --fix` / `openclaw doctor --repair` 模式下安装它们。外部插件仍使用 `openclaw plugins install` / `openclaw plugins update`;doctor 不会为任意插件路径安装依赖。
|
||||
Doctor 仅验证当前配置中处于激活状态,或由其内置 manifest 默认启用的内置插件的运行时依赖,例如 `plugins.entries.discord.enabled: true`、旧版 `channels.discord.enabled: true`,或默认启用的内置 provider。如果缺少任何依赖,doctor 会报告相应包,并在 `openclaw doctor --fix` / `openclaw doctor --repair` 模式下安装它们。外部插件仍然使用 `openclaw plugins install` / `openclaw plugins update`;doctor 不会为任意插件路径安装依赖。
|
||||
|
||||
Gateway 网关和本地 CLI 也可以在导入内置插件之前,按需修复处于激活状态的内置插件运行时依赖。这些安装会限定在插件运行时安装根目录内执行,运行时禁用脚本,不会写入 package lock,并且受安装根锁保护,因此并发的 CLI 或 Gateway 网关启动不会同时修改同一棵 `node_modules` 树。
|
||||
Gateway 网关 和本地 CLI 也可以在导入内置插件之前,按需修复处于激活状态的内置插件运行时依赖。这些安装被限定在插件运行时安装根目录中,安装时禁用脚本,不写入 package lock,并通过安装根锁进行保护,以免并发的 CLI 或 Gateway 网关 启动同时修改同一棵 `node_modules` 树。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="8. Gateway 网关服务迁移和清理提示">
|
||||
Doctor 会检测旧版 Gateway 网关服务(`launchd`/`systemd`/`schtasks`),并提供移除它们、使用当前 Gateway 网关端口安装 OpenClaw 服务的选项。它还可以扫描额外的类 Gateway 网关服务并输出清理提示。带有 profile 名称的 OpenClaw Gateway 网关服务被视为一等公民,不会被标记为“额外”服务。
|
||||
<Accordion title="8. Gateway 网关 服务迁移和清理提示">
|
||||
Doctor 会检测旧版 Gateway 网关 服务(`launchd`/`systemd`/`schtasks`),并提供移除它们以及使用当前 Gateway 网关 端口安装 OpenClaw 服务的选项。它还可以扫描额外的类似 Gateway 网关 的服务并打印清理提示。带 profile 名称的 OpenClaw Gateway 网关 服务被视为一等公民,不会被标记为“额外”。
|
||||
</Accordion>
|
||||
<Accordion title="8b. 启动时 Matrix 迁移">
|
||||
当 Matrix 渠道账户存在待处理或可执行的旧版状态迁移时,doctor(在 `--fix` / `--repair` 模式下)会先创建迁移前快照,然后运行尽力而为的迁移步骤:旧版 Matrix 状态迁移和旧版加密状态准备。这两个步骤都不是致命错误;错误会被记录,启动会继续。在只读模式下(不带 `--fix` 的 `openclaw doctor`),此检查会被完全跳过。
|
||||
当 Matrix 渠道账号存在待处理或可执行的旧版状态迁移时,doctor(在 `--fix` / `--repair` 模式下)会先创建迁移前快照,然后运行尽力而为的迁移步骤:旧版 Matrix 状态迁移和旧版加密状态准备。这两个步骤都不是致命的;错误会被记录,启动会继续进行。在只读模式下(不带 `--fix` 的 `openclaw doctor`),该检查会被完全跳过。
|
||||
</Accordion>
|
||||
<Accordion title="8c. 设备配对和认证漂移">
|
||||
Doctor 现在会将设备配对状态纳入常规健康检查的一部分。
|
||||
Doctor 现在会将设备配对状态作为正常健康检查的一部分进行检查。
|
||||
|
||||
它会报告的内容:
|
||||
|
||||
- 待处理的首次配对请求
|
||||
- 已配对设备待处理的角色升级
|
||||
- 已配对设备待处理的作用域升级
|
||||
- 公钥不匹配修复:设备 ID 仍匹配,但设备身份已不再匹配已批准记录
|
||||
- 已配对记录中缺少已批准角色的活动令牌
|
||||
- 已配对令牌的作用域漂移到批准配对基线之外
|
||||
- 当前机器的本地缓存设备令牌条目早于 Gateway 网关侧令牌轮换,或携带过期作用域元数据
|
||||
- 已配对设备的待处理角色升级
|
||||
- 已配对设备的待处理作用域升级
|
||||
- 公钥不匹配修复:设备 ID 仍然匹配,但设备身份已不再匹配已批准记录
|
||||
- 缺少已批准角色的活动 token 的已配对记录
|
||||
- 作用域漂移到已批准配对基线之外的已配对 token
|
||||
- 当前机器的本地缓存设备 token 条目,这些条目早于 Gateway 网关 侧 token 轮换,或携带过时的作用域元数据
|
||||
|
||||
Doctor 不会自动批准配对请求,也不会自动轮换设备令牌。它会直接输出精确的后续步骤:
|
||||
Doctor 不会自动批准配对请求,也不会自动轮换设备 token。它会改为打印精确的下一步操作:
|
||||
|
||||
- 使用 `openclaw devices list` 检查待处理请求
|
||||
- 使用 `openclaw devices approve <requestId>` 批准指定请求
|
||||
- 使用 `openclaw devices rotate --device <deviceId> --role <role>` 轮换新的令牌
|
||||
- 使用 `openclaw devices remove <deviceId>` 删除并重新批准过期记录
|
||||
- 使用 `openclaw devices approve <requestId>` 批准精确请求
|
||||
- 使用 `openclaw devices rotate --device <deviceId> --role <role>` 轮换新的 token
|
||||
- 使用 `openclaw devices remove <deviceId>` 删除并重新批准过时记录
|
||||
|
||||
这解决了常见的“已经配对但仍提示需要配对”的问题:doctor 现在可以区分首次配对、待处理的角色/作用域升级,以及过期令牌/设备身份漂移。
|
||||
这补上了常见的“已经配对但仍然提示需要配对”的漏洞:doctor 现在可以区分首次配对、待处理角色/作用域升级,以及过时 token/设备身份漂移。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="9. 安全警告">
|
||||
当某个提供商对私信开放但没有 allowlist,或策略配置存在危险方式时,doctor 会发出警告。
|
||||
当某个提供商在没有 allowlist 的情况下对私信开放,或策略配置方式具有危险性时,doctor 会发出警告。
|
||||
</Accordion>
|
||||
<Accordion title="10. systemd linger(Linux)">
|
||||
如果以 systemd 用户服务运行,doctor 会确保已启用 lingering,以便 Gateway 网关在注销后仍保持运行。
|
||||
<Accordion title="10. `systemd linger`(Linux)">
|
||||
如果作为 `systemd` 用户服务运行,doctor 会确保已启用 lingering,以便 Gateway 网关 在注销后保持运行。
|
||||
</Accordion>
|
||||
<Accordion title="11. 工作区状态(Skills、插件和旧版目录)">
|
||||
Doctor 会输出默认智能体的工作区状态摘要:
|
||||
Doctor 会打印默认智能体的工作区状态摘要:
|
||||
|
||||
- **Skills 状态**:统计可用、缺少要求和被 allowlist 阻止的 Skills 数量。
|
||||
- **旧版工作区目录**:当 `~/openclaw` 或其他旧版工作区目录与当前工作区同时存在时发出警告。
|
||||
- **插件状态**:统计已启用/已禁用/出错的插件数量;列出所有出错插件的插件 ID;报告内置插件能力。
|
||||
- **Skills 状态**:统计可用、缺少前置要求以及被 allowlist 阻止的 Skills。
|
||||
- **旧版工作区目录**:当 `~/openclaw` 或其他旧版工作区目录与当前工作区并存时发出警告。
|
||||
- **插件状态**:统计已启用/已禁用/出错的插件;列出所有出错插件的插件 ID;报告内置插件能力。
|
||||
- **插件兼容性警告**:标记与当前运行时存在兼容性问题的插件。
|
||||
- **插件诊断**:显示插件注册表在加载时发出的任何警告或错误。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="11b. Bootstrap 文件大小">
|
||||
Doctor 会检查工作区 bootstrap 文件(例如 `AGENTS.md`、`CLAUDE.md` 或其他注入的上下文文件)是否接近或超过已配置的字符预算。它会报告每个文件的原始字符数与注入字符数、截断百分比、截断原因(`max/file` 或 `max/total`),以及总注入字符数占总预算的比例。当文件被截断或接近限制时,doctor 会输出调整 `agents.defaults.bootstrapMaxChars` 和 `agents.defaults.bootstrapTotalMaxChars` 的建议。
|
||||
Doctor 会检查工作区 bootstrap 文件(例如 `AGENTS.md`、`CLAUDE.md` 或其他注入的上下文文件)是否接近或超过已配置的字符预算。它会报告每个文件的原始字符数与注入字符数、截断百分比、截断原因(`max/file` 或 `max/total`),以及总注入字符数占总预算的比例。当文件被截断或接近限制时,doctor 会打印用于调节 `agents.defaults.bootstrapMaxChars` 和 `agents.defaults.bootstrapTotalMaxChars` 的提示。
|
||||
</Accordion>
|
||||
<Accordion title="11c. Shell 补全">
|
||||
Doctor 会检查当前 shell(zsh、bash、fish 或 PowerShell)是否已安装 tab 补全:
|
||||
|
||||
- 如果 shell 配置文件使用的是较慢的动态补全模式(`source <(openclaw completion ...)`),doctor 会将其升级为更快的缓存文件变体。
|
||||
- 如果配置文件中已配置补全,但缓存文件缺失,doctor 会自动重新生成缓存。
|
||||
- 如果根本没有配置补全,doctor 会提示安装(仅限交互模式;使用 `--non-interactive` 时跳过)。
|
||||
- 如果 shell profile 使用较慢的动态补全模式(`source <(openclaw completion ...)`),doctor 会将其升级为更快的缓存文件变体。
|
||||
- 如果 profile 中已配置补全,但缓存文件缺失,doctor 会自动重新生成缓存。
|
||||
- 如果完全未配置补全,doctor 会提示安装(仅限交互模式;`--non-interactive` 下会跳过)。
|
||||
|
||||
运行 `openclaw completion --write-state` 可手动重新生成缓存。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="12. Gateway 网关认证检查(本地令牌)">
|
||||
Doctor 会检查本地 Gateway 网关令牌认证就绪状态。
|
||||
<Accordion title="12. Gateway 网关 认证检查(本地 token)">
|
||||
Doctor 会检查本地 Gateway 网关 token 认证的就绪情况。
|
||||
|
||||
- 如果令牌模式需要令牌且不存在令牌来源,doctor 会提供生成令牌的选项。
|
||||
- 如果 `gateway.auth.token` 由 `SecretRef` 管理但当前不可用,doctor 会发出警告,并且不会用明文覆盖它。
|
||||
- 只有在未配置任何令牌 `SecretRef` 时,`openclaw doctor --generate-gateway-token` 才会强制生成令牌。
|
||||
- 如果 token 模式需要 token 且不存在 token 源,doctor 会提供生成 token 的选项。
|
||||
- 如果 `gateway.auth.token` 由 SecretRef 管理但不可用,doctor 会发出警告,并且不会用明文覆盖它。
|
||||
- 仅当未配置 token SecretRef 时,`openclaw doctor --generate-gateway-token` 才会强制生成。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="12b. 识别 SecretRef 的只读修复">
|
||||
某些修复流程需要检查已配置的凭证,同时又不能削弱运行时的快速失败行为。
|
||||
<Accordion title="12b. 只读且支持 SecretRef 的修复">
|
||||
某些修复流程需要检查已配置凭证,而不削弱运行时快速失败行为。
|
||||
|
||||
- `openclaw doctor --fix` 现在会像 Status 系列命令一样,使用相同的只读 `SecretRef` 摘要模型来执行针对性的配置修复。
|
||||
- 例如:Telegram `allowFrom` / `groupAllowFrom` `@username` 修复会在可用时尝试使用已配置的 bot 凭证。
|
||||
- 如果 Telegram bot token 是通过 `SecretRef` 配置的,但在当前命令路径中不可用,doctor 会报告该凭证为“已配置但不可用”,并跳过自动解析,而不是崩溃或错误地将该 token 报告为缺失。
|
||||
- `openclaw doctor --fix` 现在使用与 status 系列命令相同的只读 SecretRef 摘要模型来执行有针对性的配置修复。
|
||||
- 例如:Telegram `allowFrom` / `groupAllowFrom` 的 `@username` 修复会在可用时尝试使用已配置的 bot 凭证。
|
||||
- 如果 Telegram bot token 通过 SecretRef 配置,但在当前命令路径中不可用,doctor 会报告该凭证是“已配置但不可用”,并跳过自动解析,而不是崩溃或错误地将 token 报告为缺失。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="13. Gateway 网关健康检查 + 重启">
|
||||
Doctor 会运行健康检查,并在 Gateway 网关看起来不健康时提供重启选项。
|
||||
<Accordion title="13. Gateway 网关 健康检查 + 重启">
|
||||
Doctor 会运行健康检查,并在 Gateway 网关 看起来不健康时提供重启选项。
|
||||
</Accordion>
|
||||
<Accordion title="13b. Memory 搜索就绪状态">
|
||||
Doctor 会检查为默认智能体配置的 Memory 搜索 embedding provider 是否已就绪。其行为取决于已配置的后端和 provider:
|
||||
<Accordion title="13b. Memory 搜索就绪情况">
|
||||
Doctor 会检查为默认智能体配置的 Memory 搜索嵌入提供商是否已就绪。行为取决于已配置的后端和提供商:
|
||||
|
||||
- **QMD 后端**:探测 `qmd` 二进制文件是否可用并可启动。如果不可用,会输出修复指引,包括 npm 包以及手动二进制路径选项。
|
||||
- **显式本地 provider**:检查本地模型文件或已识别的远程/可下载模型 URL 是否存在。如果不存在,会建议切换到远程 provider。
|
||||
- **显式远程 provider**(`openai`、`voyage` 等):验证环境或认证存储中是否存在 API key。若缺失,会输出可执行的修复提示。
|
||||
- **自动 provider**:先检查本地模型可用性,然后按照自动选择顺序依次尝试每个远程 provider。
|
||||
- **QMD 后端**:探测 `qmd` 二进制文件是否可用且可启动。如果不可用,则打印修复指导,包括 npm 包和手动二进制路径选项。
|
||||
- **显式本地提供商**:检查本地模型文件或已识别的远程/可下载模型 URL。如果缺失,则建议切换到远程提供商。
|
||||
- **显式远程提供商**(`openai`、`voyage` 等):验证环境变量或认证存储中是否存在 API 密钥。如果缺失,则打印可执行的修复提示。
|
||||
- **自动提供商**:先检查本地模型可用性,然后按自动选择顺序依次尝试每个远程提供商。
|
||||
|
||||
当存在 Gateway 网关探测结果时(检查时 Gateway 网关是健康的),doctor 会将其结果与 CLI 可见配置进行交叉核对,并指出任何差异。
|
||||
当 Gateway 网关 探测结果可用时(检查时 Gateway 网关 处于健康状态),doctor 会将其结果与 CLI 可见配置进行交叉比对,并注明任何差异。
|
||||
|
||||
使用 `openclaw memory status --deep` 可在运行时验证 embedding 就绪状态。
|
||||
使用 `openclaw memory status --deep` 可在运行时验证嵌入就绪情况。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="14. 渠道状态警告">
|
||||
如果 Gateway 网关健康,doctor 会运行渠道状态探测,并报告带有建议修复方案的警告。
|
||||
如果 Gateway 网关 健康,doctor 会运行渠道状态探测,并报告带有建议修复措施的警告。
|
||||
</Accordion>
|
||||
<Accordion title="15. supervisor 配置审计 + 修复">
|
||||
Doctor 会检查已安装的 supervisor 配置(`launchd`/`systemd`/`schtasks`)是否缺少默认项或默认项已过期(例如 systemd 的 `network-online` 依赖和重启延迟)。当发现不匹配时,它会建议更新,并可将服务文件/任务重写为当前默认值。
|
||||
<Accordion title="15. Supervisor 配置审计 + 修复">
|
||||
Doctor 会检查已安装的 supervisor 配置(`launchd`/`systemd`/`schtasks`)中是否缺少或过时的默认值(例如 `systemd` 的 `network-online` 依赖项和重启延迟)。发现不匹配时,它会建议更新,并可将服务文件/任务重写为当前默认值。
|
||||
|
||||
说明:
|
||||
|
||||
- `openclaw doctor` 会在重写 supervisor 配置前提示确认。
|
||||
- `openclaw doctor --yes` 会接受默认修复提示。
|
||||
- `openclaw doctor --repair` 会在不提示的情况下应用推荐修复。
|
||||
- `openclaw doctor --repair` 会在无提示的情况下应用推荐修复。
|
||||
- `openclaw doctor --repair --force` 会覆盖自定义 supervisor 配置。
|
||||
- 如果令牌认证需要令牌且 `gateway.auth.token` 由 `SecretRef` 管理,doctor 的服务安装/修复会校验该 `SecretRef`,但不会将解析得到的明文令牌值持久化到 supervisor 服务环境元数据中。
|
||||
- 如果令牌认证需要令牌且配置的令牌 `SecretRef` 无法解析,doctor 会阻止安装/修复路径,并给出可执行的指引。
|
||||
- 如果同时配置了 `gateway.auth.token` 和 `gateway.auth.password`,但 `gateway.auth.mode` 未设置,doctor 会阻止安装/修复,直到显式设置 mode。
|
||||
- 对于 Linux user-systemd 单元,doctor 的令牌漂移检查现在在比较服务认证元数据时会同时包含 `Environment=` 和 `EnvironmentFile=` 来源。
|
||||
- 当配置最后一次由较新版本写入时,doctor 服务修复会拒绝重写、停止或重启来自较旧 OpenClaw 二进制文件的 Gateway 网关服务。参见 [Gateway 网关故障排除](/zh-CN/gateway/troubleshooting#split-brain-installs-and-newer-config-guard)。
|
||||
- 你始终可以通过 `openclaw gateway install --force` 强制执行完整重写。
|
||||
- 如果 token 认证需要 token 且 `gateway.auth.token` 由 SecretRef 管理,doctor 的服务安装/修复会验证该 SecretRef,但不会将解析出的明文 token 值持久化到 supervisor 服务环境元数据中。
|
||||
- 如果 token 认证需要 token 且已配置的 token SecretRef 尚未解析,doctor 会阻止安装/修复路径,并提供可执行指导。
|
||||
- 如果同时配置了 `gateway.auth.token` 和 `gateway.auth.password`,但未设置 `gateway.auth.mode`,doctor 会阻止安装/修复,直到显式设置模式。
|
||||
- 对于 Linux user-systemd 单元,doctor 的 token 漂移检查现在同时包括 `Environment=` 和 `EnvironmentFile=` 源,以比较服务认证元数据。
|
||||
- 当配置最后一次是由较新版本写入时,doctor 服务修复会拒绝重写、停止或重启来自较旧 OpenClaw 二进制文件的 Gateway 网关 服务。参见 [Gateway 网关 故障排除](/zh-CN/gateway/troubleshooting#split-brain-installs-and-newer-config-guard)。
|
||||
- 你始终可以通过 `openclaw gateway install --force` 强制进行完整重写。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="16. Gateway 网关运行时 + 端口诊断">
|
||||
Doctor 会检查服务运行时(PID、上次退出状态),并在服务已安装但实际上未运行时发出警告。它还会检查 Gateway 网关端口(默认 `18789`)是否冲突,并报告可能原因(Gateway 网关已在运行、SSH 隧道)。
|
||||
<Accordion title="16. Gateway 网关 运行时 + 端口诊断">
|
||||
Doctor 会检查服务运行时(PID、最后退出状态),并在服务已安装但实际上未运行时发出警告。它还会检查 Gateway 网关 端口(默认 `18789`)上的端口冲突,并报告可能原因(Gateway 网关 已在运行、SSH 隧道)。
|
||||
</Accordion>
|
||||
<Accordion title="17. Gateway 网关运行时最佳实践">
|
||||
当 Gateway 网关服务运行在 Bun 或版本管理的 Node 路径(`nvm`、`fnm`、`volta`、`asdf` 等)上时,doctor 会发出警告。WhatsApp + Telegram 渠道要求使用 Node,而版本管理器路径在升级后可能失效,因为服务不会加载你的 shell 初始化。若系统 Node 安装可用(Homebrew/apt/choco),doctor 会提供迁移到系统 Node 安装的选项。
|
||||
<Accordion title="17. Gateway 网关 运行时最佳实践">
|
||||
当 Gateway 网关 服务运行在 Bun 或受版本管理的 Node 路径(`nvm`、`fnm`、`volta`、`asdf` 等)上时,doctor 会发出警告。WhatsApp + Telegram 渠道需要 Node,而版本管理器路径可能会在升级后失效,因为服务不会加载你的 shell 初始化。Doctor 会在系统 Node 安装可用时提供迁移到系统 Node 安装的选项(Homebrew/apt/choco)。
|
||||
</Accordion>
|
||||
<Accordion title="18. 配置写入 + 向导元数据">
|
||||
Doctor 会持久化所有配置变更,并写入向导元数据以记录此次 doctor 运行。
|
||||
Doctor 会持久化任何配置更改,并写入向导元数据以记录本次 doctor 运行。
|
||||
</Accordion>
|
||||
<Accordion title="19. 工作区提示(备份 + Memory 系统)">
|
||||
如果缺少工作区 Memory 系统,doctor 会给出建议;如果工作区尚未纳入 git 管理,它还会输出备份提示。
|
||||
当工作区缺少 Memory 系统时,doctor 会给出建议;如果工作区尚未纳入 Git 管理,它还会打印备份提示。
|
||||
|
||||
有关工作区结构和 git 备份(推荐使用私有 GitHub 或 GitLab)的完整指南,请参见 [/concepts/agent-workspace](/zh-CN/concepts/agent-workspace)。
|
||||
有关工作区结构和 Git 备份(推荐使用私有 GitHub 或 GitLab)的完整指南,请参见 [/concepts/agent-workspace](/zh-CN/concepts/agent-workspace)。
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 相关内容
|
||||
|
||||
- [Gateway 网关运行手册](/zh-CN/gateway)
|
||||
- [Gateway 网关故障排除](/zh-CN/gateway/troubleshooting)
|
||||
- [Gateway 网关 运行手册](/zh-CN/gateway)
|
||||
- [Gateway 网关 故障排除](/zh-CN/gateway/troubleshooting)
|
||||
|
||||
@ -1,38 +1,50 @@
|
||||
---
|
||||
read_when:
|
||||
- 调整心跳频率或消息内容
|
||||
- 为计划任务决定使用心跳还是 cron
|
||||
- 调整心跳频率或消息传递方式
|
||||
- 在计划任务中决定使用心跳还是 cron
|
||||
sidebarTitle: Heartbeat
|
||||
summary: 心跳轮询消息和通知规则
|
||||
title: 心跳
|
||||
x-i18n:
|
||||
generated_at: "2026-04-26T01:45:58Z"
|
||||
generated_at: "2026-04-26T07:49:07Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 440afefdbefba8317eeb7f3a1ecb6dddb2d88600e78b46a31f2f432bfa5eeb33
|
||||
source_hash: fe0d3e9c531062d90e8e24cb7795fed20bc0985c3eadc8ed367295fc2544d14e
|
||||
source_path: gateway/heartbeat.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
> **心跳还是 Cron?** 关于何时使用两者的指导,请参阅 [自动化与任务](/zh-CN/automation)。
|
||||
<Note>
|
||||
**心跳还是 cron?** 关于何时使用两者中的哪一个,请参见 [自动化与任务](/zh-CN/automation)。
|
||||
</Note>
|
||||
|
||||
心跳会在主会话中运行**周期性的智能体轮次**,这样模型就能主动提示任何需要关注的事项,而不会对你造成刷屏。
|
||||
心跳会在主会话中运行**周期性的智能体轮次**,这样模型就可以提示任何需要注意的事项,而不会对你造成刷屏。
|
||||
|
||||
心跳是一次按计划执行的主会话轮次——它**不会**创建[后台任务](/zh-CN/automation/tasks)记录。
|
||||
任务记录用于脱离主会话的工作(ACP 运行、子智能体、独立的 cron 作业)。
|
||||
心跳是一个已调度的主会话轮次——它**不会**创建[后台任务](/zh-CN/automation/tasks)记录。任务记录用于分离式工作(ACP 运行、子智能体、隔离的 cron 作业)。
|
||||
|
||||
故障排除:[计划任务](/zh-CN/automation/cron-jobs#troubleshooting)
|
||||
故障排除: [计划任务](/zh-CN/automation/cron-jobs#troubleshooting)
|
||||
|
||||
## 快速开始(适合初学者)
|
||||
## 快速开始(初学者)
|
||||
|
||||
1. 保持心跳启用状态(默认是 `30m`,对于 Anthropic OAuth/令牌认证,包括 Claude CLI 复用时为 `1h`),或者设置你自己的频率。
|
||||
2. 在智能体工作区中创建一个简短的 `HEARTBEAT.md` 检查清单或 `tasks:` 块(可选,但推荐)。
|
||||
3. 决定心跳消息应该发送到哪里(默认是 `target: "none"`;设置 `target: "last"` 可将其路由到上一次联系的对象)。
|
||||
4. 可选:启用心跳推理内容投递,以提高透明度。
|
||||
5. 可选:如果心跳运行只需要 `HEARTBEAT.md`,可使用轻量级引导上下文。
|
||||
6. 可选:启用隔离会话,避免每次心跳都发送完整的对话历史。
|
||||
7. 可选:将心跳限制在活跃时段内(本地时间)。
|
||||
<Steps>
|
||||
<Step title="选择频率">
|
||||
保持启用心跳(默认是 `30m`,对于 Anthropic OAuth / token auth,包括 Claude CLI 复用,则为 `1h`),或者设置你自己的频率。
|
||||
</Step>
|
||||
<Step title="添加 HEARTBEAT.md(可选)">
|
||||
在智能体工作区中创建一个简短的 `HEARTBEAT.md` 检查清单或 `tasks:` 块。
|
||||
</Step>
|
||||
<Step title="决定心跳消息应发送到哪里">
|
||||
`target: "none"` 是默认值;设置 `target: "last"` 可将其路由到上一个联系人。
|
||||
</Step>
|
||||
<Step title="可选调优">
|
||||
- 启用心跳推理内容传递以提高透明度。
|
||||
- 如果心跳运行只需要 `HEARTBEAT.md`,可使用轻量级 bootstrap 上下文。
|
||||
- 启用隔离会话,避免每次心跳都发送完整的对话历史。
|
||||
- 将心跳限制在活跃时段内(本地时间)。
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
配置示例:
|
||||
示例配置:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -40,10 +52,10 @@ x-i18n:
|
||||
defaults: {
|
||||
heartbeat: {
|
||||
every: "30m",
|
||||
target: "last", // 显式投递到上一次联系的对象(默认是 "none")
|
||||
directPolicy: "allow", // 默认:允许直接/私信目标;设置为 "block" 可禁止
|
||||
lightContext: true, // 可选:仅从引导文件中注入 HEARTBEAT.md
|
||||
isolatedSession: true, // 可选:每次运行使用新会话(无对话历史)
|
||||
target: "last", // 明确投递到上一个联系人(默认是 "none")
|
||||
directPolicy: "allow", // 默认:允许 direct / 私信 目标;设置为 "block" 以禁止
|
||||
lightContext: true, // 可选:仅从 bootstrap 文件注入 HEARTBEAT.md
|
||||
isolatedSession: true, // 可选:每次运行都使用全新会话(无对话历史)
|
||||
// activeHours: { start: "08:00", end: "24:00" },
|
||||
// includeReasoning: true, // 可选:额外发送单独的 `Reasoning:` 消息
|
||||
},
|
||||
@ -54,32 +66,31 @@ x-i18n:
|
||||
|
||||
## 默认值
|
||||
|
||||
- 间隔:`30m`(当检测到的认证模式为 Anthropic OAuth/令牌认证时为 `1h`,包括 Claude CLI 复用)。设置 `agents.defaults.heartbeat.every` 或按智能体设置 `agents.list[].heartbeat.every`;使用 `0m` 可禁用。
|
||||
- 提示正文(可通过 `agents.defaults.heartbeat.prompt` 配置):
|
||||
`Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK.`
|
||||
- 心跳提示会**原样**作为用户消息发送。系统提示中只有在默认智能体启用了心跳且该次运行已在内部标记时,才会包含一个“Heartbeat”部分。
|
||||
- 当使用 `0m` 禁用心跳时,普通运行也会从引导上下文中省略 `HEARTBEAT.md`,因此模型不会看到仅用于心跳的说明。
|
||||
- 活跃时段(`heartbeat.activeHours`)会按配置的时区检查。在该时间窗口之外,心跳会被跳过,直到窗口内的下一次轮询。
|
||||
- 间隔:`30m`(或在检测到 Anthropic OAuth / token auth 为认证模式时为 `1h`,包括 Claude CLI 复用)。设置 `agents.defaults.heartbeat.every` 或按智能体设置 `agents.list[].heartbeat.every`;使用 `0m` 可禁用。
|
||||
- 提示词正文(可通过 `agents.defaults.heartbeat.prompt` 配置):`Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK.`
|
||||
- 心跳提示词会**原样**作为用户消息发送。系统提示词仅在默认智能体启用了心跳且运行在内部被标记时,才包含 “Heartbeat” 部分。
|
||||
- 当使用 `0m` 禁用心跳时,普通运行也会从 bootstrap 上下文中省略 `HEARTBEAT.md`,这样模型就不会看到仅用于心跳的指令。
|
||||
- 活跃时段(`heartbeat.activeHours`)会在配置的时区中进行检查。在时间窗口之外,心跳会被跳过,直到窗口内的下一次 tick。
|
||||
|
||||
## 心跳提示的用途
|
||||
## 心跳提示词的用途
|
||||
|
||||
默认提示特意保持宽泛:
|
||||
默认提示词有意保持宽泛:
|
||||
|
||||
- **后台任务**:“Consider outstanding tasks” 会促使智能体检查待跟进事项(收件箱、日历、提醒、排队中的工作),并提示任何紧急内容。
|
||||
- **人工问候**:“Checkup sometimes on your human during day time” 会促使其偶尔发送轻量级的“你需要什么帮助吗?”之类消息,但会通过你配置的本地时区避免夜间打扰(参见 [/concepts/timezone](/zh-CN/concepts/timezone))。
|
||||
- **后台任务**:“Consider outstanding tasks” 会推动智能体检查后续事项(收件箱、日历、提醒、排队工作),并提示任何紧急事项。
|
||||
- **人工检查**:“Checkup sometimes on your human during day time” 会推动偶尔发送轻量级的“你需要什么吗?”消息,但会使用你配置的本地时区来避免夜间刷屏(参见 [时区](/zh-CN/concepts/timezone))。
|
||||
|
||||
心跳可以对已完成的[后台任务](/zh-CN/automation/tasks)作出反应,但心跳运行本身不会创建任务记录。
|
||||
|
||||
如果你希望心跳执行非常具体的操作(例如“检查 Gmail PubSub 统计信息”或“验证网关健康状态”),可以将 `agents.defaults.heartbeat.prompt`(或 `agents.list[].heartbeat.prompt`)设置为自定义正文(会原样发送)。
|
||||
如果你希望心跳执行非常具体的操作(例如“检查 Gmail PubSub 统计信息”或“验证 Gateway 网关健康状态”),请将 `agents.defaults.heartbeat.prompt`(或 `agents.list[].heartbeat.prompt`)设置为自定义正文(会原样发送)。
|
||||
|
||||
## 响应约定
|
||||
|
||||
- 如果没有任何需要关注的事项,请回复 **`HEARTBEAT_OK`**。
|
||||
- 在心跳运行期间,如果回复的**开头或结尾**出现 `HEARTBEAT_OK`,OpenClaw 会将其视为确认。该标记会被移除;如果剩余内容**≤ `ackMaxChars`**(默认:300),则整条回复会被丢弃。
|
||||
- 如果没有任何事项需要关注,请回复 **`HEARTBEAT_OK`**。
|
||||
- 在心跳运行期间,当 `HEARTBEAT_OK` 出现在回复的**开头或结尾**时,OpenClaw 会将其视为确认信号。如果剩余内容 **≤ `ackMaxChars`**(默认:300),则该标记会被移除,回复也会被丢弃。
|
||||
- 如果 `HEARTBEAT_OK` 出现在回复的**中间**,则不会被特殊处理。
|
||||
- 对于告警,**不要**包含 `HEARTBEAT_OK`;只返回告警文本。
|
||||
- 对于警报,**不要**包含 `HEARTBEAT_OK`;只返回警报文本。
|
||||
|
||||
在非心跳场景下,如果消息开头或结尾意外出现 `HEARTBEAT_OK`,也会被移除并记录日志;如果一条消息只有 `HEARTBEAT_OK`,则会被丢弃。
|
||||
在心跳之外,如果消息开头 / 结尾意外出现 `HEARTBEAT_OK`,它会被移除并记录日志;如果消息内容只有 `HEARTBEAT_OK`,则会被丢弃。
|
||||
|
||||
## 配置
|
||||
|
||||
@ -88,16 +99,16 @@ x-i18n:
|
||||
agents: {
|
||||
defaults: {
|
||||
heartbeat: {
|
||||
every: "30m", // 默认:30m(0m 表示禁用)
|
||||
every: "30m", // 默认:30m(0m 禁用)
|
||||
model: "anthropic/claude-opus-4-6",
|
||||
includeReasoning: false, // 默认:false(可用时投递单独的 Reasoning: 消息)
|
||||
lightContext: false, // 默认:false;true 时仅保留工作区引导文件中的 HEARTBEAT.md
|
||||
isolatedSession: false, // 默认:false;true 时每次心跳在新会话中运行(无对话历史)
|
||||
target: "last", // 默认:none | 可选:last | none | <channel id>(核心或插件,例如 "bluebubbles")
|
||||
to: "+15551234567", // 可选的渠道专用覆盖值
|
||||
includeReasoning: false, // 默认:false(在可用时投递单独的 Reasoning: 消息)
|
||||
lightContext: false, // 默认:false;true 时仅保留工作区 bootstrap 文件中的 HEARTBEAT.md
|
||||
isolatedSession: false, // 默认:false;true 时每次心跳都在全新会话中运行(无对话历史)
|
||||
target: "last", // 默认:none | 可选值:last | none | <channel id>(核心或插件,例如 "bluebubbles")
|
||||
to: "+15551234567", // 可选的渠道专用覆盖
|
||||
accountId: "ops-bot", // 可选的多账号渠道 id
|
||||
prompt: "Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK.",
|
||||
ackMaxChars: 300, // HEARTBEAT_OK 后允许的最大字符数
|
||||
ackMaxChars: 300, // HEARTBEAT_OK 之后允许的最大字符数
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -107,15 +118,14 @@ x-i18n:
|
||||
### 作用域和优先级
|
||||
|
||||
- `agents.defaults.heartbeat` 设置全局心跳行为。
|
||||
- `agents.list[].heartbeat` 会在其基础上合并;如果任何智能体带有 `heartbeat` 块,**则只有这些智能体**会运行心跳。
|
||||
- `agents.list[].heartbeat` 会在其之上合并;如果任一智能体有 `heartbeat` 块,**则只有这些智能体**会运行心跳。
|
||||
- `channels.defaults.heartbeat` 为所有渠道设置可见性默认值。
|
||||
- `channels.<channel>.heartbeat` 会覆盖渠道默认值。
|
||||
- `channels.<channel>.accounts.<id>.heartbeat`(多账号渠道)会按渠道进一步覆盖。
|
||||
|
||||
### 按智能体配置心跳
|
||||
### 按智能体设置心跳
|
||||
|
||||
如果任何 `agents.list[]` 条目包含 `heartbeat` 块,**则只有这些智能体**会运行心跳。
|
||||
按智能体的块会在 `agents.defaults.heartbeat` 之上合并(因此你可以先设置共享默认值,再为每个智能体覆盖)。
|
||||
如果任一 `agents.list[]` 条目包含 `heartbeat` 块,**则只有这些智能体**会运行心跳。按智能体设置的块会在 `agents.defaults.heartbeat` 之上合并(这样你可以先设置共享默认值,再按智能体覆盖)。
|
||||
|
||||
示例:两个智能体,只有第二个智能体运行心跳。
|
||||
|
||||
@ -125,7 +135,7 @@ x-i18n:
|
||||
defaults: {
|
||||
heartbeat: {
|
||||
every: "30m",
|
||||
target: "last", // 显式投递到上一次联系的对象(默认是 "none")
|
||||
target: "last", // 明确投递到上一个联系人(默认是 "none")
|
||||
},
|
||||
},
|
||||
list: [
|
||||
@ -155,7 +165,7 @@ x-i18n:
|
||||
defaults: {
|
||||
heartbeat: {
|
||||
every: "30m",
|
||||
target: "last", // 显式投递到上一次联系的对象(默认是 "none")
|
||||
target: "last", // 明确投递到上一个联系人(默认是 "none")
|
||||
activeHours: {
|
||||
start: "09:00",
|
||||
end: "22:00",
|
||||
@ -167,17 +177,18 @@ x-i18n:
|
||||
}
|
||||
```
|
||||
|
||||
在该时间窗口之外(美东时间上午 9 点前或晚上 10 点后),心跳会被跳过。窗口内的下一次计划轮询将正常运行。
|
||||
在这个时间窗口之外(东部时间上午 9 点前或晚上 10 点后),心跳会被跳过。窗口内的下一次计划 tick 会正常运行。
|
||||
|
||||
### 24/7 配置
|
||||
|
||||
如果你希望心跳全天运行,可以使用以下任一方式:
|
||||
如果你希望心跳全天运行,可以使用以下任一模式:
|
||||
|
||||
- 完全省略 `activeHours`(不限制时间窗口;这是默认行为)。
|
||||
- 设置全天窗口:`activeHours: { start: "00:00", end: "24:00" }`。
|
||||
|
||||
不要将 `start` 和 `end` 设为相同时间(例如 `08:00` 到 `08:00`)。
|
||||
这会被视为零宽度窗口,因此心跳始终会被跳过。
|
||||
<Warning>
|
||||
不要将 `start` 和 `end` 设置为相同的时间(例如 `08:00` 到 `08:00`)。这会被视为零宽度窗口,因此心跳将始终被跳过。
|
||||
</Warning>
|
||||
|
||||
### 多账号示例
|
||||
|
||||
@ -192,7 +203,7 @@ x-i18n:
|
||||
heartbeat: {
|
||||
every: "1h",
|
||||
target: "telegram",
|
||||
to: "12345678:topic:42", // 可选:路由到特定 topic/thread
|
||||
to: "12345678:topic:42", // 可选:路由到特定主题 / 线程
|
||||
accountId: "ops-bot",
|
||||
},
|
||||
},
|
||||
@ -210,60 +221,95 @@ x-i18n:
|
||||
|
||||
### 字段说明
|
||||
|
||||
- `every`:心跳间隔(时长字符串;默认单位 = 分钟)。
|
||||
- `model`:心跳运行时的可选模型覆盖值(`provider/model`)。
|
||||
- `includeReasoning`:启用后,如果可用,还会投递单独的 `Reasoning:` 消息(形态与 `/reasoning on` 相同)。
|
||||
- `lightContext`:为 true 时,心跳运行会使用轻量级引导上下文,并且仅保留工作区引导文件中的 `HEARTBEAT.md`。
|
||||
- `isolatedSession`:为 true 时,每次心跳都会在全新会话中运行,不带先前对话历史。其隔离模式与 cron 的 `sessionTarget: "isolated"` 相同。可显著降低每次心跳的 token 成本。与 `lightContext: true` 结合可获得最大节省。投递路由仍使用主会话上下文。
|
||||
- `session`:心跳运行的可选会话键。
|
||||
- `main`(默认):智能体主会话。
|
||||
- 显式会话键(可从 `openclaw sessions --json` 或 [sessions CLI](/zh-CN/cli/sessions) 获取)。
|
||||
- 会话键格式:参见[会话](/zh-CN/concepts/session)和[群组](/zh-CN/channels/groups)。
|
||||
- `target`:
|
||||
- `last`:投递到上一次使用的外部渠道。
|
||||
- 显式渠道:任何已配置的渠道或插件 id,例如 `discord`、`matrix`、`telegram` 或 `whatsapp`。
|
||||
- `none`(默认):运行心跳,但**不进行**外部投递。
|
||||
- `directPolicy`:控制直接/私信投递行为:
|
||||
- `allow`(默认):允许直接/私信心跳投递。
|
||||
- `block`:禁止直接/私信投递(`reason=dm-blocked`)。
|
||||
- `to`:可选的收件人覆盖值(渠道专用 id,例如 WhatsApp 的 E.164 或 Telegram chat id)。对于 Telegram topics/threads,使用 `<chatId>:topic:<messageThreadId>`。
|
||||
- `accountId`:多账号渠道的可选账号 id。当 `target: "last"` 时,如果解析出的上一个渠道支持账号,则会应用该账号 id;否则会被忽略。如果该账号 id 与解析出的渠道中已配置账号不匹配,则会跳过投递。
|
||||
- `prompt`:覆盖默认提示正文(不合并)。
|
||||
- `ackMaxChars`:`HEARTBEAT_OK` 之后允许的最大字符数。
|
||||
- `suppressToolErrorWarnings`:为 true 时,会在心跳运行期间抑制工具错误警告负载。
|
||||
- `activeHours`:将心跳运行限制在一个时间窗口内。对象包含 `start`(HH:MM,含边界;使用 `00:00` 表示一天开始)、`end`(HH:MM,不含边界;一天结束可用 `24:00`)以及可选的 `timezone`。
|
||||
- 省略或设为 `"user"`:如果设置了你的 `agents.defaults.userTimezone` 则使用它,否则回退到主机系统时区。
|
||||
- `"local"`:始终使用主机系统时区。
|
||||
- 任意 IANA 标识符(例如 `America/New_York`):直接使用;如果无效,则回退到上述 `"user"` 行为。
|
||||
- 对于活动窗口,`start` 和 `end` 不能相等;相等会被视为零宽度(始终在窗口外)。
|
||||
- 在活跃窗口之外,心跳会被跳过,直到窗口内的下一次轮询。
|
||||
<ParamField path="every" type="string">
|
||||
心跳间隔(时长字符串;默认单位 = 分钟)。
|
||||
</ParamField>
|
||||
<ParamField path="model" type="string">
|
||||
心跳运行的可选模型覆盖(`provider/model`)。
|
||||
</ParamField>
|
||||
<ParamField path="includeReasoning" type="boolean" default="false">
|
||||
启用后,在可用时也会投递单独的 `Reasoning:` 消息(与 `/reasoning on` 形式相同)。
|
||||
</ParamField>
|
||||
<ParamField path="lightContext" type="boolean" default="false">
|
||||
为 true 时,心跳运行使用轻量级 bootstrap 上下文,并且只保留工作区 bootstrap 文件中的 `HEARTBEAT.md`。
|
||||
</ParamField>
|
||||
<ParamField path="isolatedSession" type="boolean" default="false">
|
||||
为 true 时,每次心跳都会在全新会话中运行,不带任何先前的对话历史。使用与 cron `sessionTarget: "isolated"` 相同的隔离模式。可显著降低每次心跳的 token 成本。与 `lightContext: true` 组合可获得最大节省。投递路由仍使用主会话上下文。
|
||||
</ParamField>
|
||||
<ParamField path="session" type="string">
|
||||
心跳运行的可选会话键。
|
||||
|
||||
- `main`(默认):智能体主会话。
|
||||
- 显式会话键(可从 `openclaw sessions --json` 或 [sessions CLI](/zh-CN/cli/sessions) 复制)。
|
||||
- 会话键格式:参见 [会话](/zh-CN/concepts/session) 和 [群组](/zh-CN/channels/groups)。
|
||||
</ParamField>
|
||||
<ParamField path="target" type="string">
|
||||
- `last`:投递到最近使用的外部渠道。
|
||||
- 显式渠道:任意已配置渠道或插件 id,例如 `discord`、`matrix`、`telegram` 或 `whatsapp`。
|
||||
- `none`(默认):运行心跳,但**不向外部投递**。
|
||||
</ParamField>
|
||||
<ParamField path="directPolicy" type='"allow" | "block"' default="allow">
|
||||
控制 direct / 私信 投递行为。`allow`:允许 direct / 私信 心跳投递。`block`:禁止 direct / 私信 投递(`reason=dm-blocked`)。
|
||||
</ParamField>
|
||||
<ParamField path="to" type="string">
|
||||
可选的收件人覆盖(渠道专用 id,例如 WhatsApp 的 E.164 或 Telegram chat id)。对于 Telegram 主题 / 线程,请使用 `<chatId>:topic:<messageThreadId>`。
|
||||
</ParamField>
|
||||
<ParamField path="accountId" type="string">
|
||||
多账号渠道的可选账号 id。当 `target: "last"` 时,如果解析出的最近渠道支持账号,则会应用该账号 id;否则会忽略。如果该账号 id 与解析出的渠道中已配置的账号不匹配,则会跳过投递。
|
||||
</ParamField>
|
||||
<ParamField path="prompt" type="string">
|
||||
覆盖默认提示词正文(不会合并)。
|
||||
</ParamField>
|
||||
<ParamField path="ackMaxChars" type="number" default="300">
|
||||
`HEARTBEAT_OK` 之后允许的最大字符数,超过则仍会投递。
|
||||
</ParamField>
|
||||
<ParamField path="suppressToolErrorWarnings" type="boolean">
|
||||
为 true 时,会在心跳运行期间抑制工具错误警告负载。
|
||||
</ParamField>
|
||||
<ParamField path="activeHours" type="object">
|
||||
将心跳运行限制在某个时间窗口内。对象包含 `start`(HH:MM,包含;一天开始请使用 `00:00`)、`end`(HH:MM,不包含;一天结束可使用 `24:00`)以及可选的 `timezone`。
|
||||
|
||||
- 省略或设为 `"user"`:如果设置了 `agents.defaults.userTimezone`,则使用你的时区;否则回退到主机系统时区。
|
||||
- `"local"`:始终使用主机系统时区。
|
||||
- 任意 IANA 标识符(例如 `America/New_York`):直接使用;如果无效,则回退到上面的 `"user"` 行为。
|
||||
- 对于活跃窗口,`start` 和 `end` 不能相等;相等会被视为零宽度(始终在窗口外)。
|
||||
- 在活跃窗口之外,心跳会被跳过,直到窗口内的下一次 tick。
|
||||
</ParamField>
|
||||
|
||||
## 投递行为
|
||||
|
||||
- 心跳默认在智能体的主会话中运行(`agent:<id>:<mainKey>`),当 `session.scope = "global"` 时则为 `global`。设置 `session` 可覆盖到特定渠道会话(Discord/WhatsApp 等)。
|
||||
- `session` 只影响运行上下文;投递由 `target` 和 `to` 控制。
|
||||
- 若要投递到特定渠道/收件人,请设置 `target` + `to`。当使用 `target: "last"` 时,投递会使用该会话最近一次使用的外部渠道。
|
||||
- 默认情况下,心跳投递允许直接/私信目标。设置 `directPolicy: "block"` 可在仍然运行心跳轮次的同时,禁止向直接目标发送消息。
|
||||
- 如果主队列繁忙,心跳会被跳过并稍后重试。
|
||||
- 如果 `target` 解析后没有外部目标,运行仍会发生,但不会发送出站消息。
|
||||
- 如果 `showOk`、`showAlerts` 和 `useIndicator` 全部被禁用,则会在开始前跳过该运行,并标记为 `reason=alerts-disabled`。
|
||||
- 如果仅禁用了告警投递,OpenClaw 仍可运行心跳、更新到期任务时间戳、恢复会话空闲时间戳,并抑制对外告警负载。
|
||||
- 如果解析出的心跳目标支持“正在输入”状态,OpenClaw 会在心跳运行期间显示输入状态。它使用的目标与心跳发送聊天输出时相同,并且可通过 `typingMode: "never"` 禁用。
|
||||
- 仅由心跳产生的回复**不会**保持会话存活。心跳元数据可能会更新会话行,但空闲过期使用的是最近一次真实用户/渠道消息的 `lastInteractionAt`,而每日过期使用的是 `sessionStartedAt`。
|
||||
- Control UI 和 WebChat 历史记录会隐藏心跳提示以及仅 OK 的确认消息。底层会话转录仍可能包含这些轮次,以便审计/回放。
|
||||
- 脱离主会话的[后台任务](/zh-CN/automation/tasks)可以排入一个系统事件并唤醒心跳,以便让主会话尽快注意到某些事项。但这种唤醒不会让心跳运行变成后台任务。
|
||||
<AccordionGroup>
|
||||
<Accordion title="会话和目标路由">
|
||||
- 心跳默认在智能体主会话中运行(`agent:<id>:<mainKey>`),或者当 `session.scope = "global"` 时运行在 `global` 中。设置 `session` 可覆盖为特定渠道会话(Discord / WhatsApp / 等)。
|
||||
- `session` 只影响运行上下文;投递由 `target` 和 `to` 控制。
|
||||
- 要投递到特定渠道 / 收件人,请设置 `target` + `to`。使用 `target: "last"` 时,投递会使用该会话最近的外部渠道。
|
||||
- 心跳投递默认允许 direct / 私信 目标。设置 `directPolicy: "block"` 可在仍然运行心跳轮次的同时,禁止发送到 direct 目标。
|
||||
- 如果主队列繁忙,心跳会被跳过并在稍后重试。
|
||||
- 如果 `target` 未解析到任何外部目标,运行仍会发生,但不会发送出站消息。
|
||||
</Accordion>
|
||||
<Accordion title="可见性和跳过行为">
|
||||
- 如果 `showOk`、`showAlerts` 和 `useIndicator` 全部禁用,则运行会在一开始就被跳过,标记为 `reason=alerts-disabled`。
|
||||
- 如果只是禁用了警报投递,OpenClaw 仍然可以运行心跳、更新到期任务时间戳、恢复会话空闲时间戳,并抑制对外的警报负载。
|
||||
- 如果解析出的心跳目标支持输入中状态,OpenClaw 会在心跳运行期间显示输入中状态。这使用与心跳发送聊天输出相同的目标,并且可通过 `typingMode: "never"` 禁用。
|
||||
</Accordion>
|
||||
<Accordion title="会话生命周期和审计">
|
||||
- 仅包含心跳的回复**不会**让会话保持活跃。心跳元数据可能会更新会话行,但空闲过期使用的是上一条真实用户 / 渠道消息的 `lastInteractionAt`,而每日过期使用的是 `sessionStartedAt`。
|
||||
- Control UI 和 WebChat 历史会隐藏心跳提示词以及仅 OK 的确认。底层会话 transcript 仍然可能包含这些轮次,用于审计 / 重放。
|
||||
- 分离的[后台任务](/zh-CN/automation/tasks)可以将系统事件加入队列,并在主会话需要快速注意某事时唤醒心跳。这种唤醒不会让心跳运行变成后台任务。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 可见性控制
|
||||
|
||||
默认情况下,`HEARTBEAT_OK` 确认消息会被抑制,而告警内容会被投递。你可以按渠道或按账号进行调整:
|
||||
默认情况下,`HEARTBEAT_OK` 确认会被抑制,而警报内容会被投递。你可以按渠道或按账号进行调整:
|
||||
|
||||
```yaml
|
||||
channels:
|
||||
defaults:
|
||||
heartbeat:
|
||||
showOk: false # 隐藏 HEARTBEAT_OK(默认)
|
||||
showAlerts: true # 显示告警消息(默认)
|
||||
useIndicator: true # 发送指示器事件(默认)
|
||||
showAlerts: true # 显示警报消息(默认)
|
||||
useIndicator: true # 发出指示器事件(默认)
|
||||
telegram:
|
||||
heartbeat:
|
||||
showOk: true # 在 Telegram 上显示 OK 确认
|
||||
@ -271,18 +317,18 @@ channels:
|
||||
accounts:
|
||||
work:
|
||||
heartbeat:
|
||||
showAlerts: false # 对此账号抑制告警投递
|
||||
showAlerts: false # 对此账号禁止警报投递
|
||||
```
|
||||
|
||||
优先级:按账号 → 按渠道 → 渠道默认值 → 内置默认值。
|
||||
|
||||
### 每个标志的作用
|
||||
|
||||
- `showOk`:当模型返回仅包含 OK 的回复时,发送一条 `HEARTBEAT_OK` 确认消息。
|
||||
- `showAlerts`:当模型返回非 OK 回复时,发送告警内容。
|
||||
- `useIndicator`:为 UI 状态界面发送指示器事件。
|
||||
- `showOk`:当模型返回仅 OK 的回复时,发送 `HEARTBEAT_OK` 确认。
|
||||
- `showAlerts`:当模型返回非 OK 回复时,发送警报内容。
|
||||
- `useIndicator`:为 UI 状态表面发出指示器事件。
|
||||
|
||||
如果**这三个标志全部**为 false,OpenClaw 会完全跳过心跳运行(不会调用模型)。
|
||||
如果**这三个值全为 false**,OpenClaw 会完全跳过心跳运行(不调用模型)。
|
||||
|
||||
### 按渠道与按账号示例
|
||||
|
||||
@ -299,7 +345,7 @@ channels:
|
||||
accounts:
|
||||
ops:
|
||||
heartbeat:
|
||||
showAlerts: false # 仅对 ops 账号抑制告警
|
||||
showAlerts: false # 仅对 ops 账号禁止警报
|
||||
telegram:
|
||||
heartbeat:
|
||||
showOk: true
|
||||
@ -308,32 +354,30 @@ channels:
|
||||
### 常见模式
|
||||
|
||||
| 目标 | 配置 |
|
||||
| --- | --- |
|
||||
| 默认行为(静默 OK,开启告警) | _(无需配置)_ |
|
||||
| ---------------------------------------- | ---------------------------------------------------------------------------------------- |
|
||||
| 默认行为(静默 OK,开启警报) | _(无需配置)_ |
|
||||
| 完全静默(无消息、无指示器) | `channels.defaults.heartbeat: { showOk: false, showAlerts: false, useIndicator: false }` |
|
||||
| 仅指示器(无消息) | `channels.defaults.heartbeat: { showOk: false, showAlerts: false, useIndicator: true }` |
|
||||
| 仅在一个渠道中显示 OK | `channels.telegram.heartbeat: { showOk: true }` |
|
||||
|
||||
## HEARTBEAT.md(可选)
|
||||
|
||||
如果工作区中存在 `HEARTBEAT.md` 文件,默认提示会告诉智能体去读取它。你可以把它看作你的“心跳检查清单”:简短、稳定,并且适合每 30 分钟都包含一次。
|
||||
如果工作区中存在 `HEARTBEAT.md` 文件,默认提示词会告诉智能体去读取它。你可以把它看作你的“心跳检查清单”:内容小、稳定,并且可以安全地每 30 分钟包含一次。
|
||||
|
||||
在普通运行中,仅当默认智能体启用了心跳指引时,才会注入 `HEARTBEAT.md`。将心跳频率设为 `0m` 禁用,或设置 `includeSystemPromptSection: false`,都会使它不再出现在普通引导上下文中。
|
||||
在普通运行中,只有当默认智能体启用了心跳指导时,才会注入 `HEARTBEAT.md`。将心跳频率用 `0m` 禁用,或设置 `includeSystemPromptSection: false`,都会使其不再出现在普通 bootstrap 上下文中。
|
||||
|
||||
如果 `HEARTBEAT.md` 存在但实际上为空(只有空行和 Markdown 标题,如 `# Heading`),OpenClaw 会跳过该次心跳运行以节省 API 调用。
|
||||
该跳过会记录为 `reason=empty-heartbeat-file`。
|
||||
如果文件不存在,心跳仍会运行,由模型决定该怎么做。
|
||||
如果 `HEARTBEAT.md` 存在,但实际上为空(只有空行和 Markdown 标题,如 `# Heading`),OpenClaw 会跳过心跳运行以节省 API 调用。该跳过会报告为 `reason=empty-heartbeat-file`。如果文件不存在,心跳仍会运行,由模型决定要做什么。
|
||||
|
||||
请保持它足够小巧(简短检查清单或提醒),以避免提示膨胀。
|
||||
请保持它足够小(简短清单或提醒),以避免提示词膨胀。
|
||||
|
||||
示例 `HEARTBEAT.md`:
|
||||
|
||||
```md
|
||||
# Heartbeat checklist
|
||||
# 心跳检查清单
|
||||
|
||||
- Quick scan: anything urgent in inboxes?
|
||||
- If it’s daytime, do a lightweight check-in if nothing else is pending.
|
||||
- If a task is blocked, write down _what is missing_ and ask Peter next time.
|
||||
- 快速扫描:收件箱中是否有任何紧急事项?
|
||||
- 如果是白天,且没有其他待处理事项,进行一次轻量级询问。
|
||||
- 如果某个任务被阻塞,写下_缺少什么_,并在下次询问 Peter。
|
||||
```
|
||||
|
||||
### `tasks:` 块
|
||||
@ -347,77 +391,80 @@ tasks:
|
||||
|
||||
- name: inbox-triage
|
||||
interval: 30m
|
||||
prompt: "Check for urgent unread emails and flag anything time sensitive."
|
||||
prompt: "检查是否有紧急未读邮件,并标记任何时间敏感事项。"
|
||||
- name: calendar-scan
|
||||
interval: 2h
|
||||
prompt: "Check for upcoming meetings that need prep or follow-up."
|
||||
prompt: "检查即将到来的会议,看看是否需要准备或后续跟进。"
|
||||
|
||||
# Additional instructions
|
||||
# 其他说明
|
||||
|
||||
- Keep alerts short.
|
||||
- If nothing needs attention after all due tasks, reply HEARTBEAT_OK.
|
||||
- 保持警报简短。
|
||||
- 如果所有到期任务处理后都没有需要关注的事项,请回复 HEARTBEAT_OK。
|
||||
```
|
||||
|
||||
行为如下:
|
||||
<AccordionGroup>
|
||||
<Accordion title="行为">
|
||||
- OpenClaw 会解析 `tasks:` 块,并根据每个任务自己的 `interval` 进行检查。
|
||||
- 对于该次 tick,只会将**到期**任务包含进心跳提示词中。
|
||||
- 如果没有任务到期,心跳将被完全跳过(`reason=no-tasks-due`),以避免浪费模型调用。
|
||||
- `HEARTBEAT.md` 中的非任务内容会被保留,并在到期任务列表后附加为额外上下文。
|
||||
- 任务的上次运行时间戳会存储在会话状态中(`heartbeatTaskState`),因此在正常重启后间隔仍然有效。
|
||||
- 只有在心跳运行完成其正常回复路径之后,任务时间戳才会推进。被跳过的 `empty-heartbeat-file` / `no-tasks-due` 运行不会将任务标记为已完成。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
- OpenClaw 会解析 `tasks:` 块,并根据各自的 `interval` 检查每个任务。
|
||||
- 只有**已到期**的任务才会被包含进该次轮询的心跳提示中。
|
||||
- 如果没有任务到期,心跳会被完全跳过(`reason=no-tasks-due`),以避免浪费一次模型调用。
|
||||
- `HEARTBEAT.md` 中的非任务内容会被保留,并在到期任务列表之后作为附加上下文追加。
|
||||
- 任务上次运行时间戳会存储在会话状态(`heartbeatTaskState`)中,因此这些间隔在普通重启后仍可保留。
|
||||
- 只有在心跳运行完成其正常回复路径后,任务时间戳才会推进。被跳过的 `empty-heartbeat-file` / `no-tasks-due` 运行不会将任务标记为已完成。
|
||||
|
||||
当你希望一个心跳文件容纳多个周期检查,而又不想在每次轮询时都为所有检查付费时,任务模式会很有用。
|
||||
任务模式适合这样的场景:你希望一个心跳文件中保存多个周期性检查,但又不想在每次 tick 时都为所有检查付费。
|
||||
|
||||
### 智能体可以更新 HEARTBEAT.md 吗?
|
||||
|
||||
可以——如果你要求它这样做。
|
||||
|
||||
`HEARTBEAT.md` 只是智能体工作区中的一个普通文件,因此你可以在普通聊天中这样告诉智能体:
|
||||
`HEARTBEAT.md` 只是智能体工作区中的普通文件,因此你可以在普通聊天中告诉智能体类似这样的话:
|
||||
|
||||
- “更新 `HEARTBEAT.md`,加入一个每日历检查。”
|
||||
- “更新 `HEARTBEAT.md`,添加一个每日日历检查。”
|
||||
- “重写 `HEARTBEAT.md`,让它更短,并专注于收件箱跟进。”
|
||||
|
||||
如果你希望这能主动发生,也可以在心跳提示中加入一行明确说明,例如:“如果检查清单已经过时,就更新 HEARTBEAT.md,换成一个更好的版本。”
|
||||
如果你希望它主动这样做,也可以在心跳提示词中加入一行明确说明,例如:“如果检查清单已经过时,就用更好的版本更新 HEARTBEAT.md。”
|
||||
|
||||
安全说明:不要把密钥(API keys、电话号码、私密令牌)放进 `HEARTBEAT.md`——它会成为提示上下文的一部分。
|
||||
<Warning>
|
||||
不要把密钥(API keys、电话号码、私密 token)放入 `HEARTBEAT.md`——它会成为提示词上下文的一部分。
|
||||
</Warning>
|
||||
|
||||
## 手动唤醒(按需)
|
||||
|
||||
你可以通过以下命令排入一个系统事件并立即触发一次心跳:
|
||||
你可以通过以下命令将系统事件加入队列,并立即触发一次心跳:
|
||||
|
||||
```bash
|
||||
openclaw system event --text "Check for urgent follow-ups" --mode now
|
||||
openclaw system event --text "检查是否有紧急跟进事项" --mode now
|
||||
```
|
||||
|
||||
如果多个智能体都配置了 `heartbeat`,手动唤醒会立即运行这些智能体各自的心跳。
|
||||
如果多个智能体配置了 `heartbeat`,手动唤醒会立即运行这些智能体各自的心跳。
|
||||
|
||||
使用 `--mode next-heartbeat` 可等待下一次计划轮询。
|
||||
使用 `--mode next-heartbeat` 可等待下一次计划 tick。
|
||||
|
||||
## 推理内容投递(可选)
|
||||
|
||||
默认情况下,心跳只投递最终的“answer”负载。
|
||||
默认情况下,心跳只投递最终的“答案”负载。
|
||||
|
||||
如果你希望提高透明度,请启用:
|
||||
|
||||
- `agents.defaults.heartbeat.includeReasoning: true`
|
||||
|
||||
启用后,心跳还会额外投递一条以
|
||||
`Reasoning:` 为前缀的单独消息(形态与 `/reasoning on` 相同)。当智能体管理多个会话/codexes,且你希望了解它为何决定来提醒你时,这会很有用——但它也可能泄露比你希望看到的更多内部细节。在群聊中通常建议保持关闭。
|
||||
启用后,心跳还会额外投递一条以 `Reasoning:` 为前缀的消息(形式与 `/reasoning on` 相同)。当智能体正在管理多个会话 / codex 时,这有助于你理解它为什么决定提醒你——但它也可能泄露比你希望更多的内部细节。在群聊中通常更适合保持关闭。
|
||||
|
||||
## 成本意识
|
||||
|
||||
心跳会运行完整的智能体轮次。更短的间隔会消耗更多 token。要降低成本:
|
||||
|
||||
- 使用 `isolatedSession: true`,避免发送完整对话历史(每次运行大约可从 ~100K tokens 降到 ~2-5K)。
|
||||
- 使用 `lightContext: true`,将引导文件限制为仅 `HEARTBEAT.md`。
|
||||
- 设置一个更便宜的 `model`(例如 `ollama/llama3.2:1b`)。
|
||||
- 保持 `HEARTBEAT.md` 简短。
|
||||
- 如果你只想要内部状态更新,可使用 `target: "none"`。
|
||||
- 使用 `isolatedSession: true`,避免发送完整的对话历史(每次运行大约从 ~100K token 降到 ~2-5K)。
|
||||
- 使用 `lightContext: true`,将 bootstrap 文件限制为仅 `HEARTBEAT.md`。
|
||||
- 设置更便宜的 `model`(例如 `ollama/llama3.2:1b`)。
|
||||
- 保持 `HEARTBEAT.md` 内容简短。
|
||||
- 如果你只想更新内部状态,使用 `target: "none"`。
|
||||
|
||||
## 相关内容
|
||||
|
||||
- [自动化与任务](/zh-CN/automation) —— 所有自动化机制总览
|
||||
- [后台任务](/zh-CN/automation/tasks) —— 脱离主会话的工作如何被跟踪
|
||||
- [自动化与任务](/zh-CN/automation) —— 所有自动化机制一览
|
||||
- [后台任务](/zh-CN/automation/tasks) —— 分离式工作如何被跟踪
|
||||
- [时区](/zh-CN/concepts/timezone) —— 时区如何影响心跳调度
|
||||
- [故障排除](/zh-CN/automation/cron-jobs#troubleshooting) —— 自动化问题调试方法
|
||||
- [故障排除](/zh-CN/automation/cron-jobs#troubleshooting) —— 自动化问题调试
|
||||
|
||||
@ -1,26 +1,27 @@
|
||||
---
|
||||
read_when:
|
||||
- 你想将 OpenClaw 的模型使用情况、消息流或会话指标发送到 OpenTelemetry 收集器
|
||||
- 你正在将追踪、指标或日志接入 Grafana、Datadog、Honeycomb、New Relic、Tempo 或其他 OTLP 后端
|
||||
- 你需要确切的指标名称、span 名称或属性结构来构建仪表板或告警
|
||||
summary: 通过 diagnostics-otel 插件(OTLP/HTTP),将 OpenClaw 诊断数据导出到任何 OpenTelemetry 收集器
|
||||
- 你想将 OpenClaw 模型使用情况、消息流或会话指标发送到 OpenTelemetry 收集器。
|
||||
- 你正在将追踪、指标或日志接入 Grafana、Datadog、Honeycomb、New Relic、Tempo 或其他 OTLP 后端。
|
||||
- 你需要精确的指标名称、span 名称或属性结构来构建仪表板或告警。
|
||||
summary: 通过 diagnostics-otel 插件(OTLP/HTTP),将 OpenClaw 诊断数据导出到任意 OpenTelemetry 收集器。
|
||||
title: OpenTelemetry 导出
|
||||
x-i18n:
|
||||
generated_at: "2026-04-26T06:59:36Z"
|
||||
generated_at: "2026-04-26T07:49:20Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 6b0a8e2e9e808597c6a139306d4b1264e198edb95579a5f7ba36db049ec96afe
|
||||
source_hash: 63fe66de2d046255a0e5b0eee8bbead2c9d278b8911bdc09bfee1e9c59294418
|
||||
source_path: gateway/opentelemetry.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
OpenClaw 通过内置的 `diagnostics-otel` 插件,使用 **OTLP/HTTP(protobuf)** 导出诊断数据。任何接受 OTLP/HTTP 的收集器或后端都无需代码改动即可使用。关于本地文件日志以及如何读取它们,请参阅 [Logging](/zh-CN/logging)。
|
||||
OpenClaw 通过内置的 `diagnostics-otel` 插件,使用 **OTLP/HTTP(protobuf)** 导出诊断数据。任何接受 OTLP/HTTP 的收集器或后端都无需修改代码即可工作。有关本地文件日志及其读取方式,请参见 [日志](/zh-CN/logging)。
|
||||
|
||||
## 它是如何协同工作的
|
||||
## 工作方式
|
||||
|
||||
- **诊断事件** 是由 Gateway 网关和内置插件为模型运行、消息流、会话、队列和 exec 发出的结构化进程内记录。
|
||||
- **`diagnostics-otel` 插件** 订阅这些事件,并通过 OTLP/HTTP 将其导出为 OpenTelemetry **指标**、**追踪** 和 **日志**。
|
||||
- 只有在诊断功能和插件都启用时,导出器才会附加,因此默认情况下进程内开销几乎为零。
|
||||
- **诊断事件** 是由 Gateway 网关和内置插件发出的结构化进程内记录,用于模型运行、消息流、会话、队列和 exec。
|
||||
- **`diagnostics-otel` 插件** 会订阅这些事件,并通过 OTLP/HTTP 将它们导出为 OpenTelemetry **指标**、**追踪** 和 **日志**。
|
||||
- 当提供商传输接受自定义头时,**提供商调用** 会从 OpenClaw 受信任的模型调用 span 上下文接收一个 W3C `traceparent` 标头。插件发出的追踪上下文不会被传播。
|
||||
- 只有当诊断表面和该插件都已启用时,导出器才会附加,因此默认情况下进程内开销几乎为零。
|
||||
|
||||
## 快速开始
|
||||
|
||||
@ -56,18 +57,18 @@ openclaw plugins enable diagnostics-otel
|
||||
```
|
||||
|
||||
<Note>
|
||||
`protocol` 当前仅支持 `http/protobuf`。`grpc` 会被忽略。
|
||||
`protocol` 目前仅支持 `http/protobuf`。`grpc` 会被忽略。
|
||||
</Note>
|
||||
|
||||
## 导出的信号
|
||||
|
||||
| 信号 | 包含内容 |
|
||||
| 信号 | 内容 |
|
||||
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| **指标** | 用于 token 使用量、成本、运行时长、消息流、队列通道、会话状态、exec 和内存压力的计数器与直方图。 |
|
||||
| **追踪** | 用于模型使用、模型调用、harness 生命周期、工具执行、exec、webhook/消息处理、上下文组装和工具循环的 span。 |
|
||||
| **日志** | 当启用 `diagnostics.otel.logs` 时,通过 OTLP 导出的结构化 `logging.file` 记录。 |
|
||||
| **追踪** | 用于模型使用、模型调用、harness 生命周期、工具执行、exec、webhook/消息处理、上下文组装和工具循环的 spans。 |
|
||||
| **日志** | 当 `diagnostics.otel.logs` 启用时,通过 OTLP 导出的结构化 `logging.file` 记录。 |
|
||||
|
||||
可以独立切换 `traces`、`metrics` 和 `logs`。当 `diagnostics.otel.enabled` 为 true 时,这三项默认都开启。
|
||||
你可以独立切换 `traces`、`metrics` 和 `logs`。当 `diagnostics.otel.enabled` 为 true 时,三者默认都启用。
|
||||
|
||||
## 配置参考
|
||||
|
||||
@ -106,32 +107,34 @@ openclaw plugins enable diagnostics-otel
|
||||
|
||||
| 变量 | 用途 |
|
||||
| ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `OTEL_EXPORTER_OTLP_ENDPOINT` | 覆盖 `diagnostics.otel.endpoint`。如果该值已经包含 `/v1/traces`、`/v1/metrics` 或 `/v1/logs`,则按原样使用。 |
|
||||
| `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` / `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` / `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` | 当匹配的 `diagnostics.otel.*Endpoint` 配置键未设置时,使用对应信号的 endpoint 覆盖。优先级为:信号专用配置 > 信号专用环境变量 > 共享 endpoint。 |
|
||||
| `OTEL_EXPORTER_OTLP_ENDPOINT` | 覆盖 `diagnostics.otel.endpoint`。如果该值已包含 `/v1/traces`、`/v1/metrics` 或 `/v1/logs`,则按原样使用。 |
|
||||
| `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` / `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` / `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` | 当对应的 `diagnostics.otel.*Endpoint` 配置键未设置时,作为信号级端点覆盖。信号级配置优先于信号级环境变量,后者优先于共享端点。 |
|
||||
| `OTEL_SERVICE_NAME` | 覆盖 `diagnostics.otel.serviceName`。 |
|
||||
| `OTEL_EXPORTER_OTLP_PROTOCOL` | 覆盖线协议(当前只有 `http/protobuf` 会生效)。 |
|
||||
| `OTEL_SEMCONV_STABILITY_OPT_IN` | 设置为 `gen_ai_latest_experimental`,以发出最新的实验性 GenAI span 属性(`gen_ai.provider.name`),而不是旧版的 `gen_ai.system`。无论如何,GenAI 指标始终使用有界、低基数的语义属性。 |
|
||||
| `OPENCLAW_OTEL_PRELOADED` | 当另一个 preload 或宿主进程已经注册了全局 OpenTelemetry SDK 时,设置为 `1`。此时插件会跳过自身的 NodeSDK 生命周期,但仍会连接诊断监听器,并遵守 `traces` / `metrics` / `logs`。 |
|
||||
| `OTEL_EXPORTER_OTLP_PROTOCOL` | 覆盖传输协议(目前仅 `http/protobuf` 生效)。 |
|
||||
| `OTEL_SEMCONV_STABILITY_OPT_IN` | 设置为 `gen_ai_latest_experimental` 时,将发出最新的实验性 GenAI span 属性(`gen_ai.provider.name`),而不是旧版 `gen_ai.system`。无论如何,GenAI 指标始终使用有界、低基数的语义属性。 |
|
||||
| `OPENCLAW_OTEL_PRELOADED` | 当另一个预加载项或宿主进程已经注册了全局 OpenTelemetry SDK 时,将其设为 `1`。这样插件会跳过自己的 NodeSDK 生命周期,但仍会接入诊断监听器,并遵循 `traces`/`metrics`/`logs`。 |
|
||||
|
||||
## 隐私与内容捕获
|
||||
## 隐私和内容采集
|
||||
|
||||
默认**不会**导出原始模型/工具内容。span 携带的是有界标识符(渠道、提供商、模型、错误类别、仅哈希的请求 ID),绝不会包含提示词文本、响应文本、工具输入、工具输出或会话键。
|
||||
默认**不会**导出原始模型/工具内容。spans 携带的是有界标识符(渠道、提供商、模型、错误类别、仅哈希的请求 ID),绝不包含提示词文本、响应文本、工具输入、工具输出或会话键。
|
||||
|
||||
仅当你的收集器和保留策略已获批准可存储提示词、响应、工具或系统提示文本时,才将 `diagnostics.otel.captureContent.*` 设为 `true`。每个子键都需要独立选择启用:
|
||||
出站模型请求可能包含一个 W3C `traceparent` 标头。该标头仅根据 OpenClaw 拥有的、当前模型调用的诊断追踪上下文生成。现有的调用方提供的 `traceparent` 标头会被替换,因此插件或自定义提供商选项不能伪造跨服务追踪祖先关系。
|
||||
|
||||
- `inputMessages` —— 用户提示内容。
|
||||
- `outputMessages` —— 模型响应内容。
|
||||
- `toolInputs` —— 工具参数负载。
|
||||
- `toolOutputs` —— 工具结果负载。
|
||||
- `systemPrompt` —— 组装后的 system/developer 提示词。
|
||||
仅当你的收集器和保留策略已获准处理提示词、响应、工具或系统提示文本时,才将 `diagnostics.otel.captureContent.*` 设为 `true`。每个子键都需要独立选择启用:
|
||||
|
||||
当启用任一子键时,模型和工具 span 仅会为该类内容添加有界、已脱敏的 `openclaw.content.*` 属性。
|
||||
- `inputMessages` — 用户提示内容。
|
||||
- `outputMessages` — 模型响应内容。
|
||||
- `toolInputs` — 工具参数载荷。
|
||||
- `toolOutputs` — 工具结果载荷。
|
||||
- `systemPrompt` — 组装后的系统/开发者提示。
|
||||
|
||||
当启用任一子键时,模型和工具 spans 会仅为该类内容附加有界、已脱敏的 `openclaw.content.*` 属性。
|
||||
|
||||
## 采样与刷新
|
||||
|
||||
- **追踪:** `diagnostics.otel.sampleRate`(仅根 span,`0.0` 表示全部丢弃,`1.0` 表示全部保留)。
|
||||
- **指标:** `diagnostics.otel.flushIntervalMs`(最小值为 `1000`)。
|
||||
- **日志:** OTLP 日志遵循 `logging.level`(文件日志级别)。控制台脱敏**不会**应用到 OTLP 日志。高流量部署应优先使用 OTLP 收集器采样/过滤,而不是本地采样。
|
||||
- **日志:** OTLP 日志遵循 `logging.level`(文件日志级别)。控制台脱敏**不会**应用于 OTLP 日志。高流量部署应优先使用 OTLP 收集器采样/过滤,而不是本地采样。
|
||||
|
||||
## 导出的指标
|
||||
|
||||
@ -141,8 +144,8 @@ openclaw plugins enable diagnostics-otel
|
||||
- `openclaw.cost.usd`(计数器,属性:`openclaw.channel`、`openclaw.provider`、`openclaw.model`)
|
||||
- `openclaw.run.duration_ms`(直方图,属性:`openclaw.channel`、`openclaw.provider`、`openclaw.model`)
|
||||
- `openclaw.context.tokens`(直方图,属性:`openclaw.context`、`openclaw.channel`、`openclaw.provider`、`openclaw.model`)
|
||||
- `gen_ai.client.token.usage`(直方图,GenAI 语义约定指标,属性:`gen_ai.token.type` = `input`/`output`、`gen_ai.provider.name`、`gen_ai.operation.name`、`gen_ai.request.model`)
|
||||
- `gen_ai.client.operation.duration`(直方图,单位为秒,GenAI 语义约定指标,属性:`gen_ai.provider.name`、`gen_ai.operation.name`、`gen_ai.request.model`,可选 `error.type`)
|
||||
- `gen_ai.client.token.usage`(直方图,GenAI semantic-conventions 指标,属性:`gen_ai.token.type` = `input`/`output`、`gen_ai.provider.name`、`gen_ai.operation.name`、`gen_ai.request.model`)
|
||||
- `gen_ai.client.operation.duration`(直方图,单位为秒,GenAI semantic-conventions 指标,属性:`gen_ai.provider.name`、`gen_ai.operation.name`、`gen_ai.request.model`、可选 `error.type`)
|
||||
|
||||
### 消息流
|
||||
|
||||
@ -168,7 +171,7 @@ openclaw plugins enable diagnostics-otel
|
||||
|
||||
### Harness 生命周期
|
||||
|
||||
- `openclaw.harness.duration_ms`(直方图,属性:`openclaw.harness.id`、`openclaw.harness.plugin`、`openclaw.outcome`,错误时还包括 `openclaw.harness.phase`)
|
||||
- `openclaw.harness.duration_ms`(直方图,属性:`openclaw.harness.id`、`openclaw.harness.plugin`、`openclaw.outcome`、出错时为 `openclaw.harness.phase`)
|
||||
|
||||
### Exec
|
||||
|
||||
@ -182,17 +185,17 @@ openclaw plugins enable diagnostics-otel
|
||||
- `openclaw.tool.loop.iterations`(计数器,属性:`openclaw.toolName`、`openclaw.outcome`)
|
||||
- `openclaw.tool.loop.duration_ms`(直方图,属性:`openclaw.toolName`、`openclaw.outcome`)
|
||||
|
||||
## 导出的 span
|
||||
## 导出的 spans
|
||||
|
||||
- `openclaw.model.usage`
|
||||
- `openclaw.channel`、`openclaw.provider`、`openclaw.model`
|
||||
- `openclaw.tokens.*`(input/output/cache_read/cache_write/total)
|
||||
- 默认使用 `gen_ai.system`,或者在启用最新 GenAI 语义约定时使用 `gen_ai.provider.name`
|
||||
- 默认使用 `gen_ai.system`,或者在启用最新 GenAI semantic conventions 时使用 `gen_ai.provider.name`
|
||||
- `gen_ai.request.model`、`gen_ai.operation.name`、`gen_ai.usage.*`
|
||||
- `openclaw.run`
|
||||
- `openclaw.outcome`、`openclaw.channel`、`openclaw.provider`、`openclaw.model`、`openclaw.errorCategory`
|
||||
- `openclaw.model.call`
|
||||
- 默认使用 `gen_ai.system`,或者在启用最新 GenAI 语义约定时使用 `gen_ai.provider.name`
|
||||
- 默认使用 `gen_ai.system`,或者在启用最新 GenAI semantic conventions 时使用 `gen_ai.provider.name`
|
||||
- `gen_ai.request.model`、`gen_ai.operation.name`、`openclaw.provider`、`openclaw.model`、`openclaw.api`、`openclaw.transport`
|
||||
- `openclaw.provider.request_id_hash`(上游提供商请求 ID 的有界 SHA 哈希;不会导出原始 ID)
|
||||
- `openclaw.harness.run`
|
||||
@ -214,21 +217,21 @@ openclaw plugins enable diagnostics-otel
|
||||
- `openclaw.session.stuck`
|
||||
- `openclaw.state`、`openclaw.ageMs`、`openclaw.queueDepth`
|
||||
- `openclaw.context.assembled`
|
||||
- `openclaw.prompt.size`、`openclaw.history.size`、`openclaw.context.tokens`、`openclaw.errorCategory`(不包含 prompt、history、response 或 session-key 内容)
|
||||
- `openclaw.prompt.size`、`openclaw.history.size`、`openclaw.context.tokens`、`openclaw.errorCategory`(不包含提示词、历史、响应或会话键内容)
|
||||
- `openclaw.tool.loop`
|
||||
- `openclaw.toolName`、`openclaw.outcome`、`openclaw.iterations`、`openclaw.errorCategory`(不包含循环消息、参数或工具输出)
|
||||
- `openclaw.memory.pressure`
|
||||
- `openclaw.memory.level`、`openclaw.memory.heap_used_bytes`、`openclaw.memory.rss_bytes`
|
||||
|
||||
当显式启用内容捕获时,模型和工具 span 还可以包含有界、已脱敏的 `openclaw.content.*` 属性,用于你选择启用的特定内容类别。
|
||||
当明确启用内容采集时,模型和工具 spans 还可以包含针对你选择启用的特定内容类别的有界、已脱敏 `openclaw.content.*` 属性。
|
||||
|
||||
## 诊断事件目录
|
||||
|
||||
以下事件为上面的指标和 span 提供支持。插件也可以直接订阅它们,而无需 OTLP 导出。
|
||||
下面这些事件支撑了上述指标和 spans。插件也可以在不通过 OTLP 导出的情况下直接订阅它们。
|
||||
|
||||
**模型使用情况**
|
||||
|
||||
- `model.usage` — token、成本、时长、上下文、提供商/模型/渠道、会话 ID。`usage` 是提供商/轮次级别的成本和遥测统计;`context.used` 是当前的 prompt/上下文快照,在涉及缓存输入或工具循环调用时,可能低于提供商的 `usage.total`。
|
||||
- `model.usage` — token、成本、时长、上下文、provider/模型/渠道、会话 ID。`usage` 是用于成本与遥测的 provider/轮次统计;`context.used` 是当前提示/上下文快照,当涉及缓存输入或工具循环调用时,它可能低于 provider 的 `usage.total`。
|
||||
|
||||
**消息流**
|
||||
|
||||
@ -241,11 +244,11 @@ openclaw plugins enable diagnostics-otel
|
||||
- `queue.lane.enqueue` / `queue.lane.dequeue`
|
||||
- `session.state` / `session.stuck`
|
||||
- `run.attempt`
|
||||
- `diagnostic.heartbeat`(聚合计数器:webhooks/queue/session)
|
||||
- `diagnostic.heartbeat`(聚合计数器:webhooks/队列/会话)
|
||||
|
||||
**Harness 生命周期**
|
||||
|
||||
- `harness.run.started` / `harness.run.completed` / `harness.run.error` — 智能体 harness 的单次运行生命周期。包括 `harnessId`、可选的 `pluginId`、provider/model/channel,以及运行 ID。完成事件还会增加 `durationMs`、`outcome`、可选的 `resultClassification`、`yieldDetected` 和 `itemLifecycle` 计数。错误事件还会增加 `phase`(`prepare`/`start`/`send`/`resolve`/`cleanup`)、`errorCategory` 和可选的 `cleanupFailed`。
|
||||
- `harness.run.started` / `harness.run.completed` / `harness.run.error` — 智能体 harness 的逐次运行生命周期。包含 `harnessId`、可选 `pluginId`、provider/模型/渠道以及运行 ID。完成时会增加 `durationMs`、`outcome`、可选的 `resultClassification`、`yieldDetected` 和 `itemLifecycle` 计数。错误时会增加 `phase`(`prepare`/`start`/`send`/`resolve`/`cleanup`)、`errorCategory` 和可选的 `cleanupFailed`。
|
||||
|
||||
**Exec**
|
||||
|
||||
@ -253,7 +256,7 @@ openclaw plugins enable diagnostics-otel
|
||||
|
||||
## 不使用导出器
|
||||
|
||||
你可以在不运行 `diagnostics-otel` 的情况下,仍然让诊断事件可供插件或自定义 sink 使用:
|
||||
你可以在不运行 `diagnostics-otel` 的情况下,继续让插件或自定义 sink 使用诊断事件:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -261,7 +264,7 @@ openclaw plugins enable diagnostics-otel
|
||||
}
|
||||
```
|
||||
|
||||
如需在不提高 `logging.level` 的情况下获取定向调试输出,请使用诊断标志。标志不区分大小写,并支持通配符(例如 `telegram.*` 或 `*`):
|
||||
若要在不提高 `logging.level` 的情况下获得定向调试输出,请使用诊断标志。标志不区分大小写,并支持通配符(例如 `telegram.*` 或 `*`):
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -275,8 +278,7 @@ openclaw plugins enable diagnostics-otel
|
||||
OPENCLAW_DIAGNOSTICS=telegram.http,telegram.payload openclaw gateway
|
||||
```
|
||||
|
||||
标志输出会写入标准日志文件(`logging.file`),并且仍会由 `logging.redactSensitive` 进行脱敏。完整指南请参阅:
|
||||
[Diagnostics flags](/zh-CN/diagnostics/flags)。
|
||||
标志输出会写入标准日志文件(`logging.file`),并且仍会由 `logging.redactSensitive` 进行脱敏。完整指南请参见:[诊断标志](/zh-CN/diagnostics/flags)。
|
||||
|
||||
## 禁用
|
||||
|
||||
@ -286,13 +288,12 @@ OPENCLAW_DIAGNOSTICS=telegram.http,telegram.payload openclaw gateway
|
||||
}
|
||||
```
|
||||
|
||||
你也可以不将 `diagnostics-otel` 加入 `plugins.allow`,或运行
|
||||
`openclaw plugins disable diagnostics-otel`。
|
||||
你也可以不把 `diagnostics-otel` 放入 `plugins.allow`,或者运行 `openclaw plugins disable diagnostics-otel`。
|
||||
|
||||
## 相关内容
|
||||
|
||||
- [Logging](/zh-CN/logging) — 文件日志、控制台输出、CLI tail,以及 Control UI 的 Logs 标签页
|
||||
- [Gateway logging internals](/zh-CN/gateway/logging) — WS 日志样式、子系统前缀和控制台捕获
|
||||
- [Diagnostics flags](/zh-CN/diagnostics/flags) — 定向调试日志标志
|
||||
- [Diagnostics export](/zh-CN/gateway/diagnostics) — 面向运维人员的支持包导出工具(与 OTEL 导出分开)
|
||||
- [Configuration reference](/zh-CN/gateway/configuration-reference#diagnostics) — 完整的 `diagnostics.*` 字段参考
|
||||
- [日志](/zh-CN/logging) — 文件日志、控制台输出、CLI 尾部跟随以及 Control UI 的日志标签页
|
||||
- [Gateway 网关日志内部机制](/zh-CN/gateway/logging) — WS 日志样式、子系统前缀和控制台捕获
|
||||
- [诊断标志](/zh-CN/diagnostics/flags) — 定向调试日志标志
|
||||
- [诊断导出](/zh-CN/gateway/diagnostics) — 面向运维的支持包工具(与 OTEL 导出分开)
|
||||
- [配置参考](/zh-CN/gateway/configuration-reference#diagnostics) — 完整的 `diagnostics.*` 字段参考
|
||||
|
||||
@ -1,104 +1,114 @@
|
||||
---
|
||||
read_when: You want a dedicated explanation of sandboxing or need to tune agents.defaults.sandbox.
|
||||
sidebarTitle: Sandboxing
|
||||
status: active
|
||||
summary: OpenClaw 沙箱隔离如何工作:模式、作用域、工作区访问和镜像
|
||||
summary: OpenClaw 沙箱隔离的工作方式:模式、作用范围、工作区访问和图像
|
||||
title: 沙箱隔离
|
||||
x-i18n:
|
||||
generated_at: "2026-04-25T09:15:35Z"
|
||||
generated_at: "2026-04-26T07:49:15Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 4f22778690a4d41033c7abf9e97d54e53163418f8d45f1a816ce2be9d124fedf
|
||||
source_hash: 83930d5533832f2ece5fd069c15670f8a73c5801c829ca85c249a4582d36ff29
|
||||
source_path: gateway/sandboxing.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
OpenClaw 可以在**沙箱后端内运行工具**,以降低影响范围。
|
||||
OpenClaw 可以在**沙箱后端内运行工具**,以减少影响范围。这是**可选的**,并通过配置(`agents.defaults.sandbox` 或 `agents.list[].sandbox`)控制。如果关闭沙箱隔离,工具会在主机上运行。Gateway 网关保持在主机上;启用后,工具执行会在隔离的沙箱中运行。
|
||||
|
||||
这是**可选的**,并由配置控制(`agents.defaults.sandbox` 或
|
||||
`agents.list[].sandbox`)。如果关闭沙箱隔离,工具会在宿主机上运行。
|
||||
Gateway 网关会继续运行在宿主机上;启用后,工具执行会在隔离的沙箱中进行。
|
||||
<Note>
|
||||
这不是一个完美的安全边界,但当模型做出愚蠢操作时,它能显著限制文件系统和进程访问。
|
||||
</Note>
|
||||
|
||||
这并不是一个完美的安全边界,但当模型做出愚蠢操作时,它能显著限制文件系统
|
||||
和进程访问。
|
||||
|
||||
## 什么会被沙箱隔离
|
||||
## 哪些内容会被沙箱隔离
|
||||
|
||||
- 工具执行(`exec`、`read`、`write`、`edit`、`apply_patch`、`process` 等)。
|
||||
- 可选的沙箱隔离浏览器(`agents.defaults.sandbox.browser`)。
|
||||
- 默认情况下,当浏览器工具需要它时,沙箱浏览器会自动启动(确保 CDP 可达)。
|
||||
通过 `agents.defaults.sandbox.browser.autoStart` 和 `agents.defaults.sandbox.browser.autoStartTimeoutMs` 配置。
|
||||
- 默认情况下,沙箱浏览器容器使用专用的 Docker 网络(`openclaw-sandbox-browser`),而不是全局的 `bridge` 网络。
|
||||
使用 `agents.defaults.sandbox.browser.network` 配置。
|
||||
- 可选的 `agents.defaults.sandbox.browser.cdpSourceRange` 可通过 CIDR 允许列表限制容器边界的 CDP 入站连接(例如 `172.21.0.1/32`)。
|
||||
- noVNC 观察者访问默认受密码保护;OpenClaw 会生成一个短期有效的令牌 URL,用于提供本地引导页面,并在 URL 片段中(而非查询参数 / 请求头日志中)携带密码打开 noVNC。
|
||||
- `agents.defaults.sandbox.browser.allowHostControl` 允许沙箱隔离会话显式将目标指向宿主机浏览器。
|
||||
- 可选允许列表可限制 `target: "custom"`:`allowedControlUrls`、`allowedControlHosts`、`allowedControlPorts`。
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="沙箱隔离浏览器详情">
|
||||
- 默认情况下,当浏览器工具需要时,沙箱浏览器会自动启动(确保 CDP 可访问)。可通过 `agents.defaults.sandbox.browser.autoStart` 和 `agents.defaults.sandbox.browser.autoStartTimeoutMs` 进行配置。
|
||||
- 默认情况下,沙箱浏览器容器使用专用的 Docker 网络(`openclaw-sandbox-browser`),而不是全局 `bridge` 网络。可通过 `agents.defaults.sandbox.browser.network` 配置。
|
||||
- 可选的 `agents.defaults.sandbox.browser.cdpSourceRange` 会使用 CIDR 允许列表限制容器边缘的 CDP 入站连接(例如 `172.21.0.1/32`)。
|
||||
- noVNC 观察者访问默认受密码保护;OpenClaw 会输出一个短期有效的令牌 URL,它会提供一个本地引导页面,并在 URL 片段中(而不是查询参数/请求头日志中)携带密码来打开 noVNC。
|
||||
- `agents.defaults.sandbox.browser.allowHostControl` 允许沙箱隔离会话显式以主机浏览器为目标。
|
||||
- 可选的允许列表可限制 `target: "custom"`:`allowedControlUrls`、`allowedControlHosts`、`allowedControlPorts`。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
不会被沙箱隔离的内容:
|
||||
|
||||
- Gateway 网关进程本身。
|
||||
- 任何被明确允许在沙箱外运行的工具(例如 `tools.elevated`)。
|
||||
- **提权 exec 会绕过沙箱隔离,并使用已配置的逃逸路径(默认是 `gateway`,或者当 exec 目标为 `node` 时使用 `node`)。**
|
||||
- 如果沙箱隔离已关闭,`tools.elevated` 不会改变执行行为(本来就在宿主机上运行)。参见 [Elevated Mode](/zh-CN/tools/elevated)。
|
||||
- **提升权限的 `exec` 会绕过沙箱隔离,并使用已配置的逃逸路径(默认是 `gateway`,或者当 `exec` 目标为 `node` 时使用 `node`)。**
|
||||
- 如果关闭了沙箱隔离,`tools.elevated` 不会改变执行方式(本来就在主机上)。参见 [Elevated Mode](/zh-CN/tools/elevated)。
|
||||
|
||||
## 模式
|
||||
|
||||
`agents.defaults.sandbox.mode` 控制**何时**使用沙箱隔离:
|
||||
|
||||
- `"off"`:不使用沙箱隔离。
|
||||
- `"non-main"`:仅对**非主**会话启用沙箱隔离(如果你希望普通聊天运行在宿主机上,这是默认选择)。
|
||||
- `"all"`:所有会话都在沙箱中运行。
|
||||
注意:`"non-main"` 是基于 `session.mainKey`(默认值为 `"main"`),而不是基于智能体 id。
|
||||
群组 / 渠道会话使用它们自己的键,因此会被视为非主会话,并会被沙箱隔离。
|
||||
<Tabs>
|
||||
<Tab title="off">
|
||||
不使用沙箱隔离。
|
||||
</Tab>
|
||||
<Tab title="non-main">
|
||||
仅对**非主**会话使用沙箱(如果你希望普通聊天在主机上运行,这是默认推荐值)。
|
||||
|
||||
## 作用域
|
||||
`"non-main"` 基于 `session.mainKey`(默认 `"main"`),而不是智能体 id。群组/渠道会话使用它们自己的键,因此它们会被视为非主会话并进入沙箱。
|
||||
|
||||
</Tab>
|
||||
<Tab title="all">
|
||||
每个会话都在沙箱中运行。
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## 作用范围
|
||||
|
||||
`agents.defaults.sandbox.scope` 控制**会创建多少个容器**:
|
||||
|
||||
- `"agent"`(默认):每个智能体一个容器。
|
||||
- `"session"`:每个会话一个容器。
|
||||
- `"shared"`:所有已启用沙箱隔离的会话共享一个容器。
|
||||
- `"shared"`:所有沙箱隔离会话共享一个容器。
|
||||
|
||||
## 后端
|
||||
|
||||
`agents.defaults.sandbox.backend` 控制**由哪个运行时**提供沙箱:
|
||||
|
||||
- `"docker"`(启用沙箱隔离时的默认值):基于本地 Docker 的沙箱运行时。
|
||||
- `"ssh"`:通用的基于 SSH 的远程沙箱运行时。
|
||||
- `"openshell"`:基于 OpenShell 的沙箱运行时。
|
||||
- `"docker"`(启用沙箱隔离时的默认值):本地 Docker 支持的沙箱运行时。
|
||||
- `"ssh"`:通用 SSH 支持的远程沙箱运行时。
|
||||
- `"openshell"`:OpenShell 支持的沙箱运行时。
|
||||
|
||||
SSH 专属配置位于 `agents.defaults.sandbox.ssh` 下。
|
||||
OpenShell 专属配置位于 `plugins.entries.openshell.config` 下。
|
||||
SSH 专用配置位于 `agents.defaults.sandbox.ssh`。OpenShell 专用配置位于 `plugins.entries.openshell.config`。
|
||||
|
||||
### 选择后端
|
||||
|
||||
| | Docker | SSH | OpenShell |
|
||||
| ------------------- | --------------------------- | ------------------------ | -------------------------------------- |
|
||||
| **运行位置** | 本地容器 | 任意可通过 SSH 访问的主机 | OpenShell 管理的沙箱 |
|
||||
| **设置** | `scripts/sandbox-setup.sh` | SSH 密钥 + 目标主机 | 启用 OpenShell 插件 |
|
||||
| **工作区模型** | 绑定挂载或复制 | 远程为准(一次性初始化) | `mirror` 或 `remote` |
|
||||
| **网络控制** | `docker.network`(默认:无) | 取决于远程主机 | 取决于 OpenShell |
|
||||
| **浏览器沙箱** | 支持 | 不支持 | 尚不支持 |
|
||||
| **绑定挂载** | `docker.binds` | 不适用 | 不适用 |
|
||||
| **最适合** | 本地开发、完整隔离 | 卸载到远程机器执行 | 受管远程沙箱,并可选择双向同步 |
|
||||
| | Docker | SSH | OpenShell |
|
||||
| ------------------- | ------------------------- | -------------------- | --------------------------------- |
|
||||
| **运行位置** | 本地容器 | 任何可通过 SSH 访问的主机 | OpenShell 管理的沙箱 |
|
||||
| **设置** | `scripts/sandbox-setup.sh` | SSH 密钥 + 目标主机 | 启用 OpenShell 插件 |
|
||||
| **工作区模型** | 绑定挂载或复制 | 远程规范(一次初始化) | `mirror` 或 `remote` |
|
||||
| **网络控制** | `docker.network`(默认:无) | 取决于远程主机 | 取决于 OpenShell |
|
||||
| **浏览器沙箱** | 支持 | 不支持 | 尚不支持 |
|
||||
| **绑定挂载** | `docker.binds` | 不适用 | 不适用 |
|
||||
| **最适合** | 本地开发、完整隔离 | 卸载到远程机器运行 | 带可选双向同步的托管远程沙箱 |
|
||||
|
||||
### Docker 后端
|
||||
|
||||
默认情况下,沙箱隔离是关闭的。如果你启用了沙箱隔离但没有选择
|
||||
后端,OpenClaw 会使用 Docker 后端。它通过 Docker 守护进程套接字(`/var/run/docker.sock`)在本地执行工具和沙箱浏览器。沙箱容器的
|
||||
隔离由 Docker 命名空间决定。
|
||||
沙箱隔离默认关闭。如果你启用了沙箱隔离但没有选择后端,OpenClaw 会使用 Docker 后端。它通过 Docker 守护进程套接字(`/var/run/docker.sock`)在本地执行工具和沙箱浏览器。沙箱容器的隔离性由 Docker 命名空间决定。
|
||||
|
||||
**Docker-out-of-Docker(DooD)约束**:
|
||||
如果你将 OpenClaw Gateway 网关本身部署为 Docker 容器,它会通过宿主机的 Docker 套接字(DooD)编排同级沙箱容器。这会引入一个特定的路径映射约束:
|
||||
<Warning>
|
||||
**Docker-out-of-Docker(DooD)约束**
|
||||
|
||||
- **配置必须使用宿主机路径**:`openclaw.json` 中的 `workspace` 配置必须包含**宿主机的绝对路径**(例如 `/home/user/.openclaw/workspaces`),而不是 Gateway 网关容器内部路径。当 OpenClaw 请求 Docker 守护进程生成沙箱时,守护进程会相对于宿主机 OS 命名空间解析路径,而不是 Gateway 网关命名空间。
|
||||
- **文件系统桥接一致性(完全相同的卷映射)**:OpenClaw Gateway 网关原生进程也会将心跳和桥接文件写入 `workspace` 目录。由于 Gateway 网关会在它自己的容器化环境中,以完全相同的字符串(宿主机路径)进行解析,因此 Gateway 网关部署必须包含完全相同的卷映射,以便原生链接到宿主机命名空间(`-v /home/user/.openclaw:/home/user/.openclaw`)。
|
||||
如果你将 OpenClaw Gateway 网关本身部署为 Docker 容器,它会使用主机的 Docker 套接字(DooD)来编排同级沙箱容器。这会引入一个特定的路径映射约束:
|
||||
|
||||
如果你仅在容器内部映射路径,而没有与宿主机绝对路径保持一致,OpenClaw 在容器环境中尝试写入心跳文件时会原生抛出 `EACCES` 权限错误,因为这个完整限定路径字符串在原生环境中并不存在。
|
||||
- **配置必须使用主机路径**:`openclaw.json` 中的 `workspace` 配置必须包含**主机的绝对路径**(例如 `/home/user/.openclaw/workspaces`),而不是 Gateway 网关容器内部路径。当 OpenClaw 请求 Docker 守护进程启动一个沙箱时,守护进程会相对于主机操作系统命名空间解析路径,而不是 Gateway 网关命名空间。
|
||||
- **文件系统桥接一致性(相同的卷映射)**:OpenClaw Gateway 网关原生进程也会将心跳和桥接文件写入 `workspace` 目录。由于 Gateway 网关在它自己的容器化环境内会解析完全相同的字符串(主机路径),因此 Gateway 网关部署必须包含一个相同的卷映射,以便原生链接到主机命名空间(`-v /home/user/.openclaw:/home/user/.openclaw`)。
|
||||
|
||||
如果你在内部映射路径时没有保持绝对主机路径一致性,OpenClaw 会原生抛出一个 `EACCES` 权限错误,因为该完全限定路径字符串在容器环境中原生不存在,导致它在容器内尝试写入心跳时失败。
|
||||
</Warning>
|
||||
|
||||
### SSH 后端
|
||||
|
||||
当你希望 OpenClaw 在任意可通过 SSH 访问的机器上对 `exec`、文件工具和媒体读取进行沙箱隔离时,使用 `backend: "ssh"`。
|
||||
当你希望 OpenClaw 在任意可通过 SSH 访问的机器上对 `exec`、文件工具和媒体读取进行沙箱隔离时,请使用 `backend: "ssh"`。
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -117,7 +127,7 @@ OpenShell 专属配置位于 `plugins.entries.openshell.config` 下。
|
||||
identityFile: "~/.ssh/id_ed25519",
|
||||
certificateFile: "~/.ssh/id_ed25519-cert.pub",
|
||||
knownHostsFile: "~/.ssh/known_hosts",
|
||||
// Or use SecretRefs / inline contents instead of local files:
|
||||
// 或者使用 SecretRef / 内联内容而不是本地文件:
|
||||
// identityData: { source: "env", provider: "default", id: "SSH_IDENTITY" },
|
||||
// certificateData: { source: "env", provider: "default", id: "SSH_CERTIFICATE" },
|
||||
// knownHostsData: { source: "env", provider: "default", id: "SSH_KNOWN_HOSTS" },
|
||||
@ -128,37 +138,34 @@ OpenShell 专属配置位于 `plugins.entries.openshell.config` 下。
|
||||
}
|
||||
```
|
||||
|
||||
其工作方式如下:
|
||||
<AccordionGroup>
|
||||
<Accordion title="工作原理">
|
||||
- OpenClaw 会在 `sandbox.ssh.workspaceRoot` 下按作用范围创建远程根目录。
|
||||
- 在创建或重建之后的首次使用时,OpenClaw 会将本地工作区一次性初始化到该远程工作区。
|
||||
- 之后,`exec`、`read`、`write`、`edit`、`apply_patch`、提示媒体读取以及入站媒体暂存都会通过 SSH 直接针对远程工作区运行。
|
||||
- OpenClaw 不会自动将远程更改同步回本地工作区。
|
||||
</Accordion>
|
||||
<Accordion title="认证材料">
|
||||
- `identityFile`、`certificateFile`、`knownHostsFile`:使用现有本地文件,并通过 OpenSSH 配置传递。
|
||||
- `identityData`、`certificateData`、`knownHostsData`:使用内联字符串或 SecretRef。OpenClaw 会通过正常的 secrets 运行时快照解析它们,将其写入权限为 `0600` 的临时文件,并在 SSH 会话结束时删除它们。
|
||||
- 如果为同一项同时设置了 `*File` 和 `*Data`,则该 SSH 会话中 `*Data` 优先。
|
||||
</Accordion>
|
||||
<Accordion title="远程规范模型的影响">
|
||||
这是一个**远程规范**模型。初始初始化之后,远程 SSH 工作区就成为真实的沙箱状态。
|
||||
|
||||
- OpenClaw 会在 `sandbox.ssh.workspaceRoot` 下为每个作用域创建一个远程根目录。
|
||||
- 在创建或重建后的首次使用时,OpenClaw 会将本地工作区初始化到该远程工作区一次。
|
||||
- 之后,`exec`、`read`、`write`、`edit`、`apply_patch`、提示词媒体读取以及入站媒体暂存,都会直接通过 SSH 针对远程工作区执行。
|
||||
- OpenClaw 不会自动将远程变更同步回本地工作区。
|
||||
- 在初始化步骤之后,如果在 OpenClaw 外部对主机本地进行了编辑,这些更改在你重建沙箱之前不会在远程端可见。
|
||||
- `openclaw sandbox recreate` 会删除按作用范围划分的远程根目录,并在下次使用时再次从本地初始化。
|
||||
- SSH 后端不支持浏览器沙箱隔离。
|
||||
- `sandbox.docker.*` 设置不适用于 SSH 后端。
|
||||
|
||||
认证材料:
|
||||
|
||||
- `identityFile`、`certificateFile`、`knownHostsFile`:使用现有本地文件,并通过 OpenSSH 配置传递。
|
||||
- `identityData`、`certificateData`、`knownHostsData`:使用内联字符串或 SecretRefs。OpenClaw 会通过常规 secrets 运行时快照解析它们,将其以 `0600` 权限写入临时文件,并在 SSH 会话结束时删除。
|
||||
- 如果同一项同时设置了 `*File` 和 `*Data`,则该 SSH 会话优先使用 `*Data`。
|
||||
|
||||
这是一个**远程为准**模型。初始初始化完成后,远程 SSH 工作区就成为真实的沙箱状态。
|
||||
|
||||
重要影响:
|
||||
|
||||
- 在初始化步骤之后,如果你在 OpenClaw 外部对宿主机本地文件进行了编辑,远程端不会看到这些更改,除非你重建沙箱。
|
||||
- `openclaw sandbox recreate` 会删除每个作用域的远程根目录,并在下次使用时重新从本地初始化。
|
||||
- SSH 后端不支持浏览器沙箱隔离。
|
||||
- `sandbox.docker.*` 设置不适用于 SSH 后端。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### OpenShell 后端
|
||||
|
||||
当你希望 OpenClaw 在 OpenShell 管理的远程环境中对工具进行沙箱隔离时,使用 `backend: "openshell"`。有关完整设置指南、配置
|
||||
参考以及工作区模式对比,请参见专门的
|
||||
[OpenShell 页面](/zh-CN/gateway/openshell)。
|
||||
当你希望 OpenClaw 在由 OpenShell 管理的远程环境中对工具进行沙箱隔离时,请使用 `backend: "openshell"`。有关完整设置指南、配置参考以及工作区模式对比,请参见专门的 [OpenShell 页面](/zh-CN/gateway/openshell)。
|
||||
|
||||
OpenShell 复用了与通用 SSH 后端相同的核心 SSH 传输和远程文件系统桥接,并增加了 OpenShell 专属生命周期
|
||||
(`sandbox create/get/delete`、`sandbox ssh-config`),以及可选的 `mirror`
|
||||
工作区模式。
|
||||
OpenShell 复用了与通用 SSH 后端相同的核心 SSH 传输和远程文件系统桥接,并增加了 OpenShell 专用生命周期(`sandbox create/get/delete`、`sandbox ssh-config`)以及可选的 `mirror` 工作区模式。
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -190,119 +197,126 @@ OpenShell 复用了与通用 SSH 后端相同的核心 SSH 传输和远程文件
|
||||
|
||||
OpenShell 模式:
|
||||
|
||||
- `mirror`(默认):本地工作区保持为准。OpenClaw 会在 exec 之前将本地文件同步到 OpenShell,并在 exec 之后将远程工作区同步回本地。
|
||||
- `remote`:沙箱创建后,OpenShell 工作区成为准本。OpenClaw 会从本地工作区向远程工作区初始化一次,之后文件工具和 exec 会直接针对远程沙箱运行,而不会将更改同步回本地。
|
||||
- `mirror`(默认):本地工作区保持为规范源。OpenClaw 会在 `exec` 之前将本地文件同步到 OpenShell,并在 `exec` 之后将远程工作区同步回来。
|
||||
- `remote`:创建沙箱后,OpenShell 工作区成为规范源。OpenClaw 会先将本地工作区一次性初始化到远程工作区,然后文件工具和 `exec` 会直接针对远程沙箱运行,不会把更改同步回本地。
|
||||
|
||||
远程传输细节:
|
||||
|
||||
- OpenClaw 会通过 `openshell sandbox ssh-config <name>` 向 OpenShell 请求沙箱专属 SSH 配置。
|
||||
- 核心会将该 SSH 配置写入临时文件,打开 SSH 会话,并复用 `backend: "ssh"` 使用的同一个远程文件系统桥接。
|
||||
- 仅在 `mirror` 模式下生命周期不同:在 exec 之前将本地同步到远程,然后在 exec 之后同步回来。
|
||||
|
||||
当前 OpenShell 的限制:
|
||||
|
||||
- 尚不支持 sandbox 浏览器
|
||||
- OpenShell 后端不支持 `sandbox.docker.binds`
|
||||
- `sandbox.docker.*` 下的 Docker 专属运行时参数仍然仅适用于 Docker 后端
|
||||
<AccordionGroup>
|
||||
<Accordion title="远程传输细节">
|
||||
- OpenClaw 会通过 `openshell sandbox ssh-config <name>` 向 OpenShell 请求沙箱专用 SSH 配置。
|
||||
- 核心会将该 SSH 配置写入临时文件,打开 SSH 会话,并复用 `backend: "ssh"` 使用的同一远程文件系统桥接。
|
||||
- 只有在 `mirror` 模式下,生命周期才不同:在 `exec` 前将本地同步到远程,然后在 `exec` 后同步回来。
|
||||
</Accordion>
|
||||
<Accordion title="当前 OpenShell 限制">
|
||||
- 尚不支持 sandbox browser
|
||||
- OpenShell 后端不支持 `sandbox.docker.binds`
|
||||
- `sandbox.docker.*` 下的 Docker 专用运行时调节项仍然只适用于 Docker 后端
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
#### 工作区模式
|
||||
|
||||
OpenShell 有两种工作区模型。实际上,这部分最为重要。
|
||||
OpenShell 有两种工作区模型。这是实际使用中最重要的部分。
|
||||
|
||||
##### `mirror`
|
||||
<Tabs>
|
||||
<Tab title="mirror (local canonical)">
|
||||
当你希望**本地工作区保持为规范源**时,请使用 `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` 前后会产生额外的同步开销。
|
||||
|
||||
代价:
|
||||
</Tab>
|
||||
<Tab title="remote (OpenShell canonical)">
|
||||
当你希望 **OpenShell 工作区成为规范源** 时,请使用 `plugins.entries.openshell.config.mode: "remote"`。
|
||||
|
||||
- exec 前后会产生额外的同步开销
|
||||
行为:
|
||||
|
||||
##### `remote`
|
||||
- 首次创建沙箱时,OpenClaw 会将本地工作区一次性初始化到远程工作区。
|
||||
- 之后,`exec`、`read`、`write`、`edit` 和 `apply_patch` 会直接针对远程 OpenShell 工作区运行。
|
||||
- OpenClaw **不会** 在 `exec` 之后将远程更改同步回本地工作区。
|
||||
- 提示阶段的媒体读取仍然可用,因为文件和媒体工具会通过沙箱桥接读取,而不是假定存在本地主机路径。
|
||||
- 传输方式是通过 SSH 连接到 `openshell sandbox ssh-config` 返回的 OpenShell 沙箱。
|
||||
|
||||
当你希望**OpenShell 工作区成为准本**时,使用 `plugins.entries.openshell.config.mode: "remote"`。
|
||||
重要影响:
|
||||
|
||||
行为:
|
||||
- 如果你在初始化步骤之后于 OpenClaw 外部在主机上编辑文件,远程沙箱**不会**自动看到这些更改。
|
||||
- 如果沙箱被重建,远程工作区会再次从本地工作区初始化。
|
||||
- 当使用 `scope: "agent"` 或 `scope: "shared"` 时,该远程工作区会在同一作用范围内共享。
|
||||
|
||||
- 当沙箱首次创建时,OpenClaw 会先将本地工作区初始化到远程工作区一次。
|
||||
- 之后,`exec`、`read`、`write`、`edit` 和 `apply_patch` 会直接针对远程 OpenShell 工作区运行。
|
||||
- OpenClaw 在 exec 后**不会**将远程变更同步回本地工作区。
|
||||
- 提示阶段的媒体读取仍然可用,因为文件和媒体工具是通过沙箱桥接读取,而不是假定存在本地宿主机路径。
|
||||
- 传输方式是通过 SSH 连接到 `openshell sandbox ssh-config` 返回的 OpenShell 沙箱。
|
||||
适用场景:
|
||||
|
||||
重要影响:
|
||||
- 沙箱应主要驻留在远程 OpenShell 侧
|
||||
- 你希望每轮的同步开销更低
|
||||
- 你不希望主机本地编辑静默覆盖远程沙箱状态
|
||||
|
||||
- 如果你在初始化步骤后于 OpenClaw 外部在宿主机上编辑文件,远程沙箱**不会**自动看到这些更改。
|
||||
- 如果沙箱被重建,远程工作区会再次从本地工作区初始化。
|
||||
- 当使用 `scope: "agent"` 或 `scope: "shared"` 时,该远程工作区也会在相同作用域内共享。
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
适用场景:
|
||||
|
||||
- 沙箱应主要存在于远程 OpenShell 一侧
|
||||
- 你希望降低每轮的同步开销
|
||||
- 你不希望宿主机本地编辑悄悄覆盖远程沙箱状态
|
||||
|
||||
如果你将沙箱视为临时执行环境,请选择 `mirror`。
|
||||
如果你将沙箱视为真实工作区,请选择 `remote`。
|
||||
如果你把沙箱视为临时执行环境,请选择 `mirror`。如果你把沙箱视为真实工作区,请选择 `remote`。
|
||||
|
||||
#### OpenShell 生命周期
|
||||
|
||||
OpenShell 沙箱仍通过常规沙箱生命周期进行管理:
|
||||
OpenShell 沙箱仍然通过常规沙箱生命周期进行管理:
|
||||
|
||||
- `openclaw sandbox list` 会显示 OpenShell 运行时以及 Docker 运行时
|
||||
- `openclaw sandbox recreate` 会删除当前运行时,并让 OpenClaw 在下次使用时重新创建它
|
||||
- 清理逻辑同样会识别后端类型
|
||||
- 清理逻辑也能识别不同后端
|
||||
|
||||
对于 `remote` 模式,recreate 特别重要:
|
||||
对于 `remote` 模式,重建尤其重要:
|
||||
|
||||
- recreate 会删除该作用域的规范远程工作区
|
||||
- 下次使用时会从本地工作区初始化一个新的远程工作区
|
||||
- 重建会删除该作用范围的规范远程工作区
|
||||
- 下一次使用时会从本地工作区初始化一个全新的远程工作区
|
||||
|
||||
对于 `mirror` 模式,recreate 主要是重置远程执行环境,
|
||||
因为无论如何本地工作区仍然是准本。
|
||||
对于 `mirror` 模式,重建主要是重置远程执行环境,因为本地工作区无论如何仍然是规范源。
|
||||
|
||||
## 工作区访问
|
||||
|
||||
`agents.defaults.sandbox.workspaceAccess` 控制**沙箱可以看到什么**:
|
||||
|
||||
- `"none"`(默认):工具只能看到 `~/.openclaw/sandboxes` 下的沙箱工作区。
|
||||
- `"ro"`:将智能体工作区以只读方式挂载到 `/agent`(会禁用 `write` / `edit` / `apply_patch`)。
|
||||
- `"rw"`:将智能体工作区以读写方式挂载到 `/workspace`。
|
||||
<Tabs>
|
||||
<Tab title="none (default)">
|
||||
工具会看到位于 `~/.openclaw/sandboxes` 下的沙箱工作区。
|
||||
</Tab>
|
||||
<Tab title="ro">
|
||||
以只读方式将智能体工作区挂载到 `/agent`(禁用 `write`/`edit`/`apply_patch`)。
|
||||
</Tab>
|
||||
<Tab title="rw">
|
||||
以读写方式将智能体工作区挂载到 `/workspace`。
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
使用 OpenShell 后端时:
|
||||
|
||||
- `mirror` 模式仍然在各个 exec 轮次之间使用本地工作区作为准本来源
|
||||
- `remote` 模式在初次初始化后使用远程 OpenShell 工作区作为准本来源
|
||||
- `workspaceAccess: "ro"` 和 `"none"` 仍会以相同方式限制写入行为
|
||||
- `mirror` 模式仍然在每次 `exec` 轮次之间将本地工作区作为规范源
|
||||
- `remote` 模式在初始初始化后将远程 OpenShell 工作区作为规范源
|
||||
- `workspaceAccess: "ro"` 和 `"none"` 仍然会以相同方式限制写入行为
|
||||
|
||||
入站媒体会被复制到当前沙箱工作区(`media/inbound/*`)。
|
||||
Skills 注意:`read` 工具以沙箱根目录为根。使用 `workspaceAccess: "none"` 时,
|
||||
OpenClaw 会将符合条件的 Skills 镜像到沙箱工作区(`.../skills`)中,
|
||||
以便能够读取它们。使用 `"rw"` 时,可从
|
||||
`/workspace/skills` 读取工作区 Skills。
|
||||
入站媒体会被复制到当前活动的沙箱工作区中(`media/inbound/*`)。
|
||||
|
||||
<Note>
|
||||
**Skills 注意事项:** `read` 工具以沙箱根目录为基础。使用 `workspaceAccess: "none"` 时,OpenClaw 会将符合条件的 Skills 镜像到沙箱工作区(`.../skills`),以便读取。使用 `"rw"` 时,工作区 Skills 可从 `/workspace/skills` 读取。
|
||||
</Note>
|
||||
|
||||
## 自定义绑定挂载
|
||||
|
||||
`agents.defaults.sandbox.docker.binds` 会将额外的宿主机目录挂载到容器中。
|
||||
格式:`host:container:mode`(例如 `"/home/user/source:/source:rw"`)。
|
||||
`agents.defaults.sandbox.docker.binds` 会将额外的主机目录挂载到容器中。格式:`host:container:mode`(例如 `"/home/user/source:/source:rw"`)。
|
||||
|
||||
全局和每个智能体的 binds 会**合并**,而不是替换。在 `scope: "shared"` 下,会忽略每个智能体的 binds。
|
||||
全局绑定和每个智能体的绑定会**合并**(而不是替换)。在 `scope: "shared"` 下,每个智能体的绑定会被忽略。
|
||||
|
||||
`agents.defaults.sandbox.browser.binds` 仅会将额外的宿主机目录挂载到**沙箱浏览器**容器中。
|
||||
`agents.defaults.sandbox.browser.binds` 仅将额外的主机目录挂载到**沙箱浏览器**容器中。
|
||||
|
||||
- 设置后(包括 `[]`),它会替代浏览器容器中的 `agents.defaults.sandbox.docker.binds`。
|
||||
- 未设置时,浏览器容器会回退使用 `agents.defaults.sandbox.docker.binds`(向后兼容)。
|
||||
- 设置后(包括 `[]`),它会在浏览器容器中替换 `agents.defaults.sandbox.docker.binds`。
|
||||
- 如果省略,浏览器容器会回退到 `agents.defaults.sandbox.docker.binds`(向后兼容)。
|
||||
|
||||
示例(只读源码 + 一个额外数据目录):
|
||||
|
||||
@ -330,137 +344,127 @@ OpenClaw 会将符合条件的 Skills 镜像到沙箱工作区(`.../skills`)
|
||||
}
|
||||
```
|
||||
|
||||
安全注意事项:
|
||||
<Warning>
|
||||
**绑定安全性**
|
||||
|
||||
- 绑定挂载会绕过沙箱文件系统:它们会以你设置的模式(`:ro` 或 `:rw`)暴露宿主机路径。
|
||||
- OpenClaw 会阻止危险的绑定来源(例如:`docker.sock`、`/etc`、`/proc`、`/sys`、`/dev`,以及会暴露它们的父级挂载)。
|
||||
- OpenClaw 还会阻止常见的家目录凭证根路径,例如 `~/.aws`、`~/.cargo`、`~/.config`、`~/.docker`、`~/.gnupg`、`~/.netrc`、`~/.npm` 和 `~/.ssh`。
|
||||
- 绑定校验不只是字符串匹配。OpenClaw 会先规范化源路径,然后通过最深层已存在祖先路径再次解析,之后再重新检查被阻止路径和允许根路径。
|
||||
- 这意味着即使最终叶子节点尚不存在,父级符号链接逃逸也仍会以关闭方式失败。示例:如果 `run-link` 指向那里,`/workspace/run-link/new-file` 仍会解析为 `/var/run/...`。
|
||||
- 允许的源根路径也会以相同方式规范化,因此某个路径即使在符号链接解析前看起来位于允许列表内,仍可能因 `outside allowed roots` 而被拒绝。
|
||||
- 敏感挂载(secrets、SSH 密钥、服务凭证)除非绝对必要,否则应使用 `:ro`。
|
||||
- 如果你只需要对工作区的读取权限,可结合 `workspaceAccess: "ro"` 使用;绑定模式仍然彼此独立。
|
||||
- 有关 binds 如何与工具策略和提权 exec 交互,请参见 [Sandbox vs Tool Policy vs Elevated](/zh-CN/gateway/sandbox-vs-tool-policy-vs-elevated)。
|
||||
- 绑定会绕过沙箱文件系统:它们会以你设置的模式(`:ro` 或 `:rw`)暴露主机路径。
|
||||
- OpenClaw 会阻止危险的绑定源(例如:`docker.sock`、`/etc`、`/proc`、`/sys`、`/dev`,以及会暴露它们的父级挂载)。
|
||||
- OpenClaw 还会阻止常见的主目录凭证根目录,例如 `~/.aws`、`~/.cargo`、`~/.config`、`~/.docker`、`~/.gnupg`、`~/.netrc`、`~/.npm` 和 `~/.ssh`。
|
||||
- 绑定校验不只是字符串匹配。OpenClaw 会先标准化源路径,然后通过最深的现有祖先路径再次解析它,再重新检查被阻止的路径和允许的根目录。
|
||||
- 这意味着即使最终叶子节点尚不存在,父级符号链接逃逸仍然会被安全地拒绝。例如,如果 `run-link` 指向那里,那么 `/workspace/run-link/new-file` 仍会被解析为 `/var/run/...`。
|
||||
- 允许的源根目录也会以相同方式标准化,因此某个路径即使在符号链接解析之前看起来位于允许列表内,仍然会因 `outside allowed roots` 而被拒绝。
|
||||
- 敏感挂载(密钥、SSH 密钥、服务凭证)除非绝对必要,否则应使用 `:ro`。
|
||||
- 如果你只需要对工作区进行只读访问,请结合 `workspaceAccess: "ro"` 使用;绑定模式仍然彼此独立。
|
||||
- 关于绑定如何与工具策略和提升权限 `exec` 交互,请参见 [Sandbox vs Tool Policy vs Elevated](/zh-CN/gateway/sandbox-vs-tool-policy-vs-elevated)。
|
||||
</Warning>
|
||||
|
||||
## 镜像 + 设置
|
||||
## 镜像和设置
|
||||
|
||||
默认 Docker 镜像:`openclaw-sandbox:bookworm-slim`
|
||||
|
||||
构建一次即可:
|
||||
<Steps>
|
||||
<Step title="构建默认镜像">
|
||||
```bash
|
||||
scripts/sandbox-setup.sh
|
||||
```
|
||||
|
||||
```bash
|
||||
scripts/sandbox-setup.sh
|
||||
```
|
||||
默认镜像**不**包含 Node。如果某个 Skill 需要 Node(或其他运行时),请自行构建自定义镜像,或通过 `sandbox.docker.setupCommand` 安装(需要网络出口 + 可写根文件系统 + root 用户)。
|
||||
|
||||
注意:默认镜像**不**包含 Node。如果某个 Skill 需要 Node(或
|
||||
其他运行时),你可以构建自定义镜像,或者通过
|
||||
`sandbox.docker.setupCommand` 安装(需要网络出口 + 可写根文件系统 +
|
||||
root 用户)。
|
||||
</Step>
|
||||
<Step title="可选:构建通用镜像">
|
||||
如需更实用的沙箱镜像并包含常用工具(例如 `curl`、`jq`、`nodejs`、`python3`、`git`):
|
||||
|
||||
如果你想要一个功能更完整、包含常用工具(例如
|
||||
`curl`、`jq`、`nodejs`、`python3`、`git`)的沙箱镜像,请构建:
|
||||
```bash
|
||||
scripts/sandbox-common-setup.sh
|
||||
```
|
||||
|
||||
```bash
|
||||
scripts/sandbox-common-setup.sh
|
||||
```
|
||||
然后将 `agents.defaults.sandbox.docker.image` 设置为 `openclaw-sandbox-common:bookworm-slim`。
|
||||
|
||||
然后将 `agents.defaults.sandbox.docker.image` 设置为
|
||||
`openclaw-sandbox-common:bookworm-slim`。
|
||||
</Step>
|
||||
<Step title="可选:构建沙箱浏览器镜像">
|
||||
```bash
|
||||
scripts/sandbox-browser-setup.sh
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
沙箱浏览器镜像:
|
||||
默认情况下,Docker 沙箱容器**没有网络**。可通过 `agents.defaults.sandbox.docker.network` 覆盖。
|
||||
|
||||
```bash
|
||||
scripts/sandbox-browser-setup.sh
|
||||
```
|
||||
<AccordionGroup>
|
||||
<Accordion title="沙箱浏览器 Chromium 默认值">
|
||||
随附的沙箱浏览器镜像还会对容器化工作负载应用较为保守的 Chromium 启动默认值。当前容器默认值包括:
|
||||
|
||||
默认情况下,Docker 沙箱容器**没有网络**。
|
||||
可通过 `agents.defaults.sandbox.docker.network` 覆盖。
|
||||
- `--remote-debugging-address=127.0.0.1`
|
||||
- `--remote-debugging-port=<derived from OPENCLAW_BROWSER_CDP_PORT>`
|
||||
- `--user-data-dir=${HOME}/.chrome`
|
||||
- `--no-first-run`
|
||||
- `--no-default-browser-check`
|
||||
- `--disable-3d-apis`
|
||||
- `--disable-gpu`
|
||||
- `--disable-dev-shm-usage`
|
||||
- `--disable-background-networking`
|
||||
- `--disable-extensions`
|
||||
- `--disable-features=TranslateUI`
|
||||
- `--disable-breakpad`
|
||||
- `--disable-crash-reporter`
|
||||
- `--disable-software-rasterizer`
|
||||
- `--no-zygote`
|
||||
- `--metrics-recording-only`
|
||||
- `--renderer-process-limit=2`
|
||||
- 启用 `noSandbox` 时使用 `--no-sandbox`。
|
||||
- 三个图形加固标志(`--disable-3d-apis`、`--disable-software-rasterizer`、`--disable-gpu`)是可选的,当容器缺少 GPU 支持时很有用。如果你的工作负载需要 WebGL 或其他 3D/浏览器特性,请设置 `OPENCLAW_BROWSER_DISABLE_GRAPHICS_FLAGS=0`。
|
||||
- `--disable-extensions` 默认启用;对于依赖扩展的流程,可通过 `OPENCLAW_BROWSER_DISABLE_EXTENSIONS=0` 禁用。
|
||||
- `--renderer-process-limit=2` 由 `OPENCLAW_BROWSER_RENDERER_PROCESS_LIMIT=<N>` 控制,其中 `0` 会保留 Chromium 的默认值。
|
||||
|
||||
内置的沙箱浏览器镜像还会为容器化工作负载应用保守的 Chromium 启动默认值。
|
||||
当前容器默认值包括:
|
||||
如果你需要不同的运行时配置文件,请使用自定义浏览器镜像并提供你自己的入口点。对于本地(非容器)Chromium 配置文件,请使用 `browser.extraArgs` 追加额外的启动标志。
|
||||
|
||||
- `--remote-debugging-address=127.0.0.1`
|
||||
- `--remote-debugging-port=<derived from OPENCLAW_BROWSER_CDP_PORT>`
|
||||
- `--user-data-dir=${HOME}/.chrome`
|
||||
- `--no-first-run`
|
||||
- `--no-default-browser-check`
|
||||
- `--disable-3d-apis`
|
||||
- `--disable-gpu`
|
||||
- `--disable-dev-shm-usage`
|
||||
- `--disable-background-networking`
|
||||
- `--disable-extensions`
|
||||
- `--disable-features=TranslateUI`
|
||||
- `--disable-breakpad`
|
||||
- `--disable-crash-reporter`
|
||||
- `--disable-software-rasterizer`
|
||||
- `--no-zygote`
|
||||
- `--metrics-recording-only`
|
||||
- `--renderer-process-limit=2`
|
||||
- 启用 `noSandbox` 时使用 `--no-sandbox`。
|
||||
- 三个图形强化标志(`--disable-3d-apis`、
|
||||
`--disable-software-rasterizer`、`--disable-gpu`)是可选的;当容器缺少 GPU 支持时会很有用。如果你的工作负载需要 WebGL 或其他 3D / 浏览器功能,请设置 `OPENCLAW_BROWSER_DISABLE_GRAPHICS_FLAGS=0`。
|
||||
- `--disable-extensions` 默认启用,可通过
|
||||
`OPENCLAW_BROWSER_DISABLE_EXTENSIONS=0` 关闭,以支持依赖扩展的流程。
|
||||
- `--renderer-process-limit=2` 由
|
||||
`OPENCLAW_BROWSER_RENDERER_PROCESS_LIMIT=<N>` 控制,其中 `0` 会保留 Chromium 的默认值。
|
||||
</Accordion>
|
||||
<Accordion title="网络安全默认值">
|
||||
- `network: "host"` 会被阻止。
|
||||
- `network: "container:<id>"` 默认会被阻止(存在绕过命名空间加入的风险)。
|
||||
- 应急覆盖:`agents.defaults.sandbox.docker.dangerouslyAllowContainerNamespaceJoin: true`。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
如果你需要不同的运行时配置,请使用自定义浏览器镜像并提供
|
||||
你自己的入口点。对于本地(非容器)Chromium 配置,使用
|
||||
`browser.extraArgs` 追加额外启动标志。
|
||||
Docker 安装和容器化 Gateway 网关部署请参见这里:[Docker](/zh-CN/install/docker)
|
||||
|
||||
安全默认值:
|
||||
对于 Docker Gateway 网关部署,`scripts/docker/setup.sh` 可以引导沙箱配置。设置 `OPENCLAW_SANDBOX=1`(或 `true`/`yes`/`on`)以启用该路径。你可以通过 `OPENCLAW_DOCKER_SOCKET` 覆盖套接字位置。完整设置和环境变量参考: [Docker](/zh-CN/install/docker#agent-sandbox)。
|
||||
|
||||
- `network: "host"` 会被阻止。
|
||||
- `network: "container:<id>"` 默认会被阻止(存在命名空间加入绕过风险)。
|
||||
- 破窗覆盖:`agents.defaults.sandbox.docker.dangerouslyAllowContainerNamespaceJoin: true`。
|
||||
## `setupCommand`(一次性容器设置)
|
||||
|
||||
Docker 安装和容器化 Gateway 网关部署说明见:
|
||||
[Docker](/zh-CN/install/docker)
|
||||
|
||||
对于 Docker Gateway 网关部署,`scripts/docker/setup.sh` 可以引导生成沙箱配置。
|
||||
设置 `OPENCLAW_SANDBOX=1`(或 `true` / `yes` / `on`)可启用该路径。你还可以
|
||||
使用 `OPENCLAW_DOCKER_SOCKET` 覆盖套接字位置。完整设置和环境变量
|
||||
参考: [Docker](/zh-CN/install/docker#agent-sandbox)。
|
||||
|
||||
## setupCommand(一次性容器设置)
|
||||
|
||||
`setupCommand` 会在沙箱容器创建后**运行一次**(而不是每次运行都执行)。
|
||||
它会通过 `sh -lc` 在容器内执行。
|
||||
`setupCommand` 会在沙箱容器创建后**运行一次**(不是每次运行都执行)。它会通过 `sh -lc` 在容器内执行。
|
||||
|
||||
路径:
|
||||
|
||||
- 全局:`agents.defaults.sandbox.docker.setupCommand`
|
||||
- 每个智能体:`agents.list[].sandbox.docker.setupCommand`
|
||||
|
||||
常见陷阱:
|
||||
<AccordionGroup>
|
||||
<Accordion title="常见陷阱">
|
||||
- 默认 `docker.network` 为 `"none"`(无出口网络),因此安装软件包会失败。
|
||||
- `docker.network: "container:<id>"` 需要 `dangerouslyAllowContainerNamespaceJoin: true`,仅应用于应急情况。
|
||||
- `readOnlyRoot: true` 会阻止写入;请设置 `readOnlyRoot: false` 或构建自定义镜像。
|
||||
- 安装软件包时,`user` 必须为 root(省略 `user` 或设置 `user: "0:0"`)。
|
||||
- 沙箱 `exec` **不会**继承主机 `process.env`。对于 Skill API 密钥,请使用 `agents.defaults.sandbox.docker.env`(或自定义镜像)。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
- 默认 `docker.network` 为 `"none"`(无出口),因此安装软件包会失败。
|
||||
- `docker.network: "container:<id>"` 需要 `dangerouslyAllowContainerNamespaceJoin: true`,并且仅适用于破窗场景。
|
||||
- `readOnlyRoot: true` 会阻止写入;请设置 `readOnlyRoot: false` 或构建自定义镜像。
|
||||
- 安装软件包时,`user` 必须是 root(省略 `user` 或设置 `user: "0:0"`)。
|
||||
- 沙箱 exec **不会**继承宿主机 `process.env`。请使用
|
||||
`agents.defaults.sandbox.docker.env`(或自定义镜像)为 Skill API 密钥提供环境变量。
|
||||
## 工具策略和逃逸通道
|
||||
|
||||
## 工具策略 + 逃逸口
|
||||
工具允许/拒绝策略仍会在沙箱规则之前生效。如果某个工具在全局或某个智能体上被拒绝,沙箱隔离不会把它重新启用。
|
||||
|
||||
在应用沙箱规则之前,工具允许 / 拒绝策略仍然会先执行。如果某个工具在全局
|
||||
或针对某个智能体被拒绝,沙箱隔离也不会把它重新启用。
|
||||
|
||||
`tools.elevated` 是一个显式逃逸口,它会让 `exec` 在沙箱外运行(默认使用 `gateway`,当 exec 目标为 `node` 时使用 `node`)。
|
||||
`/exec` 指令仅适用于已授权发送者,并且会按会话持久化;如果要彻底禁用
|
||||
`exec`,请使用工具策略 deny(参见 [Sandbox vs Tool Policy vs Elevated](/zh-CN/gateway/sandbox-vs-tool-policy-vs-elevated))。
|
||||
`tools.elevated` 是一个显式逃逸通道,它会在沙箱外运行 `exec`(默认使用 `gateway`,或者当 `exec` 目标为 `node` 时使用 `node`)。`/exec` 指令仅对已授权发送者生效,并按会话持久化;如果要彻底禁用 `exec`,请使用工具策略拒绝(参见 [Sandbox vs Tool Policy vs Elevated](/zh-CN/gateway/sandbox-vs-tool-policy-vs-elevated))。
|
||||
|
||||
调试:
|
||||
|
||||
- 使用 `openclaw sandbox explain` 检查实际生效的沙箱模式、工具策略以及 fix-it 配置键。
|
||||
- 关于“为什么这被阻止了?”的思考模型,请参见 [Sandbox vs Tool Policy vs Elevated](/zh-CN/gateway/sandbox-vs-tool-policy-vs-elevated)。
|
||||
保持严格锁定。
|
||||
- 使用 `openclaw sandbox explain` 检查生效中的沙箱模式、工具策略和修复建议配置键。
|
||||
- 关于“为什么这被阻止了?”的理解模型,请参见 [Sandbox vs Tool Policy vs Elevated](/zh-CN/gateway/sandbox-vs-tool-policy-vs-elevated)。
|
||||
|
||||
请保持严格锁定。
|
||||
|
||||
## 多智能体覆盖
|
||||
|
||||
每个智能体都可以覆盖 sandbox + tools:
|
||||
`agents.list[].sandbox` 和 `agents.list[].tools`(以及用于沙箱工具策略的 `agents.list[].tools.sandbox.tools`)。
|
||||
优先级请参见 [Multi-Agent Sandbox & Tools](/zh-CN/tools/multi-agent-sandbox-tools)。
|
||||
每个智能体都可以覆盖沙箱和工具:`agents.list[].sandbox` 和 `agents.list[].tools`(以及用于沙箱工具策略的 `agents.list[].tools.sandbox.tools`)。优先级请参见 [Multi-Agent Sandbox & Tools](/zh-CN/tools/multi-agent-sandbox-tools)。
|
||||
|
||||
## 最小启用示例
|
||||
|
||||
@ -478,10 +482,10 @@ Docker 安装和容器化 Gateway 网关部署说明见:
|
||||
}
|
||||
```
|
||||
|
||||
## 相关文档
|
||||
## 相关内容
|
||||
|
||||
- [OpenShell](/zh-CN/gateway/openshell) -- 受管沙箱后端设置、工作区模式和配置参考
|
||||
- [Sandbox Configuration](/zh-CN/gateway/config-agents#agentsdefaultssandbox)
|
||||
- [Sandbox vs Tool Policy vs Elevated](/zh-CN/gateway/sandbox-vs-tool-policy-vs-elevated) -- 调试“为什么这被阻止了?”
|
||||
- [Multi-Agent Sandbox & Tools](/zh-CN/tools/multi-agent-sandbox-tools) -- 每个智能体的覆盖和优先级
|
||||
- [Multi-Agent Sandbox & Tools](/zh-CN/tools/multi-agent-sandbox-tools) — 每个智能体的覆盖和优先级
|
||||
- [OpenShell](/zh-CN/gateway/openshell) — 托管沙箱后端设置、工作区模式和配置参考
|
||||
- [Sandbox configuration](/zh-CN/gateway/config-agents#agentsdefaultssandbox)
|
||||
- [Sandbox vs Tool Policy vs Elevated](/zh-CN/gateway/sandbox-vs-tool-policy-vs-elevated) — 调试“为什么这被阻止了?”
|
||||
- [Security](/zh-CN/gateway/security)
|
||||
|
||||
@ -1,128 +1,130 @@
|
||||
---
|
||||
read_when:
|
||||
- 为提供商凭证和 `auth-profiles.json` refs 配置 SecretRefs
|
||||
- 在生产环境中安全地执行秘密重载、审计、配置和应用 开元棋牌 to=final code omitted
|
||||
- 理解启动快速失败、非活动表面过滤和上一次已知良好配置行为
|
||||
summary: 秘密管理:SecretRef 契约、运行时快照行为与安全的单向清除
|
||||
title: 秘密管理
|
||||
- 为提供商凭证和 `auth-profiles.json` 引用配置 SecretRef
|
||||
- 在生产环境中安全地执行密钥重载、审计、配置和应用
|
||||
- 理解启动时快速失败、非活动表面过滤以及最后已知良好行为
|
||||
sidebarTitle: Secrets management
|
||||
summary: 密钥管理:SecretRef 契约、运行时快照行为,以及安全的单向清除
|
||||
title: 密钥管理
|
||||
x-i18n:
|
||||
generated_at: "2026-04-23T20:50:09Z"
|
||||
generated_at: "2026-04-26T07:49:20Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 18e21f63bbf1815b7166dfe123900575754270de94113b446311d73dfd4f2343
|
||||
source_hash: a8697a8eb15cf6ef9b105e3f12cfdad6205284d4c45f1314cd7aec2e2c81fed1
|
||||
source_path: gateway/secrets.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
OpenClaw 支持增量式 SecretRef,因此在受支持的情况下,凭证无需以明文形式存储在配置中。
|
||||
OpenClaw 支持增量式 SecretRef,因此受支持的凭证无需以明文形式存储在配置中。
|
||||
|
||||
明文仍然可用。SecretRef 是按凭证逐项选择启用的可选功能。
|
||||
<Note>
|
||||
明文仍然可用。SecretRef 对每个凭证都是可选启用的。
|
||||
</Note>
|
||||
|
||||
## 目标与运行时模型
|
||||
## 目标和运行时模型
|
||||
|
||||
秘密会被解析到内存中的运行时快照里。
|
||||
密钥会被解析到内存中的运行时快照里。
|
||||
|
||||
- 解析发生在激活期间,并且是急切解析,而不是在请求路径上惰性解析。
|
||||
- 当某个实际处于活动状态的 SecretRef 无法解析时,启动会快速失败。
|
||||
- 重载使用原子交换:要么完全成功,要么保留上一次已知良好的快照。
|
||||
- SecretRef 策略违规(例如 OAuth 模式的认证配置文件与 SecretRef 输入组合使用)会在运行时快照交换之前导致激活失败。
|
||||
- 运行时请求只会从当前活动的内存快照中读取。
|
||||
- 在首次成功完成配置激活/加载后,运行时代码路径会持续读取该活动内存快照,直到成功重载并完成交换。
|
||||
- 出站传递路径也从该活动快照中读取(例如 Discord 回复/线程传递和 Telegram 操作发送);它们不会在每次发送时重新解析 SecretRefs。
|
||||
- 解析会在激活期间急切执行,而不是在请求路径上延迟执行。
|
||||
- 当实际上处于活动状态的 SecretRef 无法解析时,启动会快速失败。
|
||||
- 重载使用原子交换:要么全部成功,要么保留最后已知良好的快照。
|
||||
- SecretRef 策略违规(例如 OAuth 模式认证配置文件与 SecretRef 输入组合使用)会在运行时交换之前导致激活失败。
|
||||
- 运行时请求仅从活动的内存快照中读取。
|
||||
- 在第一次成功的配置激活/加载之后,运行时代码路径会持续读取该活动的内存快照,直到某次成功的重载完成交换。
|
||||
- 出站投递路径也会从该活动快照中读取(例如 Discord 回复/线程投递和 Telegram 动作发送);它们不会在每次发送时重新解析 SecretRef。
|
||||
|
||||
这样可以避免在高频请求路径上受到秘密提供商故障的影响。
|
||||
这样可以避免把密钥提供商故障带到高频请求路径上。
|
||||
|
||||
## 活动表面过滤
|
||||
|
||||
SecretRef 只会在实际上处于活动状态的表面上进行验证。
|
||||
SecretRef 仅会在实际上处于活动状态的表面上进行验证。
|
||||
|
||||
- 已启用的表面:未解析的 refs 会阻止启动/重载。
|
||||
- 非活动表面:未解析的 refs 不会阻止启动/重载。
|
||||
- 非活动 refs 会发出非致命诊断,代码为 `SECRETS_REF_IGNORED_INACTIVE_SURFACE`。
|
||||
- 已启用表面:未解析的引用会阻止启动/重载。
|
||||
- 非活动表面:未解析的引用不会阻止启动/重载。
|
||||
- 非活动引用会发出非致命诊断,代码为 `SECRETS_REF_IGNORED_INACTIVE_SURFACE`。
|
||||
|
||||
非活动表面的示例:
|
||||
|
||||
- 已禁用的渠道/账户条目。
|
||||
- 启用账户没有继承的顶级渠道凭证。
|
||||
- 已禁用的工具/功能表面。
|
||||
- 未被 `tools.web.search.provider` 选中的 Web 搜索提供商专用密钥。
|
||||
在自动模式下(未设置 provider),系统会按优先级依次尝试各密钥进行提供商自动检测,直到某个密钥成功解析。
|
||||
选定之后,未选中的提供商密钥会被视为非活动,直到被选中。
|
||||
- 沙箱 SSH 认证材料(`agents.defaults.sandbox.ssh.identityData`、
|
||||
`certificateData`、`knownHostsData`,以及每个智能体的覆盖项)仅在默认智能体或已启用智能体的生效沙箱后端为 `ssh` 时处于活动状态。
|
||||
- `gateway.remote.token` / `gateway.remote.password` SecretRefs 在以下任一情况成立时处于活动状态:
|
||||
- `gateway.mode=remote`
|
||||
- 已配置 `gateway.remote.url`
|
||||
- `gateway.tailscale.mode` 为 `serve` 或 `funnel`
|
||||
- 在本地模式下且不存在上述远程表面时:
|
||||
- 当令牌认证可能胜出且未配置 env/auth 令牌时,`gateway.remote.token` 处于活动状态。
|
||||
- 当密码认证可能胜出且未配置 env/auth 密码时,`gateway.remote.password` 才处于活动状态。
|
||||
- 当设置了 `OPENCLAW_GATEWAY_TOKEN` 时,`gateway.auth.token` SecretRef 对启动认证解析来说处于非活动状态,因为该运行时会优先采用环境变量令牌输入。
|
||||
<AccordionGroup>
|
||||
<Accordion title="非活动表面的示例">
|
||||
- 已禁用的渠道/账号条目。
|
||||
- 没有任何启用账号继承的顶层渠道凭证。
|
||||
- 已禁用的工具/功能表面。
|
||||
- 未被 `tools.web.search.provider` 选中的 Web 搜索提供商专用键。在自动模式下(未设置提供商),系统会按优先级查询这些键以进行提供商自动检测,直到某个键成功解析。选定后,未选中的提供商键会被视为非活动,直到被选中为止。
|
||||
- 沙箱 SSH 认证材料(`agents.defaults.sandbox.ssh.identityData`、`certificateData`、`knownHostsData`,以及每个智能体的覆盖项)仅在默认智能体或某个已启用智能体的有效沙箱后端为 `ssh` 时处于活动状态。
|
||||
- `gateway.remote.token` / `gateway.remote.password` SecretRef 在以下任一条件满足时处于活动状态:
|
||||
- `gateway.mode=remote`
|
||||
- 已配置 `gateway.remote.url`
|
||||
- `gateway.tailscale.mode` 为 `serve` 或 `funnel`
|
||||
- 在本地模式下且不存在这些远程表面时:
|
||||
- 当 token 认证可能获胜且未配置 env/auth token 时,`gateway.remote.token` 处于活动状态。
|
||||
- 仅当 password 认证可能获胜且未配置 env/auth password 时,`gateway.remote.password` 才处于活动状态。
|
||||
- 当设置了 `OPENCLAW_GATEWAY_TOKEN` 时,`gateway.auth.token` SecretRef 对启动认证解析而言是非活动的,因为该运行时会优先使用 env token 输入。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Gateway 网关认证表面诊断
|
||||
|
||||
当在 `gateway.auth.token`、`gateway.auth.password`、
|
||||
`gateway.remote.token` 或 `gateway.remote.password` 上配置 SecretRef 时,Gateway 网关启动/重载会显式记录
|
||||
该表面的状态:
|
||||
当在 `gateway.auth.token`、`gateway.auth.password`、`gateway.remote.token` 或 `gateway.remote.password` 上配置 SecretRef 时,Gateway 网关启动/重载会显式记录表面状态:
|
||||
|
||||
- `active`:该 SecretRef 属于生效认证表面,必须可解析。
|
||||
- `inactive`:该 SecretRef 会在此运行时中被忽略,因为有其他认证表面胜出,或
|
||||
因为远程认证未启用/未激活。
|
||||
- `active`:该 SecretRef 是有效认证表面的一部分,必须能够解析。
|
||||
- `inactive`:该 SecretRef 在当前运行时会被忽略,因为有其他认证表面优先,或因为远程认证已禁用/未激活。
|
||||
|
||||
这些条目会以 `SECRETS_GATEWAY_AUTH_SURFACE` 记录,并包含活动表面策略所使用的原因,因此你可以看到某个凭证为何被视为活动或非活动。
|
||||
这些条目会以 `SECRETS_GATEWAY_AUTH_SURFACE` 记录,并包含活动表面策略使用的原因,因此你可以看到某个凭证为何被视为活动或非活动。
|
||||
|
||||
## 新手引导引用预检查
|
||||
## 新手引导引用预检
|
||||
|
||||
当新手引导在交互模式下运行,并且你选择使用 SecretRef 存储时,OpenClaw 会在保存前运行预检查验证:
|
||||
当新手引导在交互模式下运行且你选择使用 SecretRef 存储时,OpenClaw 会在保存前执行预检验证:
|
||||
|
||||
- Env refs:验证环境变量名,并确认在设置期间可见非空值。
|
||||
- Provider refs(`file` 或 `exec`):验证提供商选择、解析 `id`,并检查解析值类型。
|
||||
- 快速开始复用路径:当 `gateway.auth.token` 已经是 SecretRef 时,新手引导会在探测/仪表盘引导之前先解析它(适用于 `env`、`file` 和 `exec` refs),并使用相同的快速失败门控。
|
||||
- Env 引用:验证环境变量名称,并确认在设置期间可见非空值。
|
||||
- 提供商引用(`file` 或 `exec`):验证提供商选择,解析 `id`,并检查解析后的值类型。
|
||||
- 快速开始复用路径:当 `gateway.auth.token` 已经是 SecretRef 时,新手引导会在探测/仪表板引导之前解析它(适用于 `env`、`file` 和 `exec` 引用),并使用相同的快速失败门控。
|
||||
|
||||
如果验证失败,新手引导会显示错误并允许你重试。
|
||||
|
||||
## SecretRef 契约
|
||||
|
||||
在所有地方都使用同一种对象形状:
|
||||
在所有地方都使用同一种对象结构:
|
||||
|
||||
```json5
|
||||
{ source: "env" | "file" | "exec", provider: "default", id: "..." }
|
||||
```
|
||||
|
||||
### `source: "env"`
|
||||
<Tabs>
|
||||
<Tab title="env">
|
||||
```json5
|
||||
{ source: "env", provider: "default", id: "OPENAI_API_KEY" }
|
||||
```
|
||||
|
||||
```json5
|
||||
{ source: "env", provider: "default", id: "OPENAI_API_KEY" }
|
||||
```
|
||||
验证:
|
||||
|
||||
验证规则:
|
||||
- `provider` 必须匹配 `^[a-z][a-z0-9_-]{0,63}$`
|
||||
- `id` 必须匹配 `^[A-Z][A-Z0-9_]{0,127}$`
|
||||
|
||||
- `provider` 必须匹配 `^[a-z][a-z0-9_-]{0,63}$`
|
||||
- `id` 必须匹配 `^[A-Z][A-Z0-9_]{0,127}$`
|
||||
</Tab>
|
||||
<Tab title="file">
|
||||
```json5
|
||||
{ source: "file", provider: "filemain", id: "/providers/openai/apiKey" }
|
||||
```
|
||||
|
||||
### `source: "file"`
|
||||
验证:
|
||||
|
||||
```json5
|
||||
{ source: "file", provider: "filemain", id: "/providers/openai/apiKey" }
|
||||
```
|
||||
- `provider` 必须匹配 `^[a-z][a-z0-9_-]{0,63}$`
|
||||
- `id` 必须是绝对 JSON pointer(`/...`)
|
||||
- 分段中的 RFC6901 转义:`~` => `~0`,`/` => `~1`
|
||||
|
||||
验证规则:
|
||||
</Tab>
|
||||
<Tab title="exec">
|
||||
```json5
|
||||
{ source: "exec", provider: "vault", id: "providers/openai/apiKey" }
|
||||
```
|
||||
|
||||
- `provider` 必须匹配 `^[a-z][a-z0-9_-]{0,63}$`
|
||||
- `id` 必须是绝对 JSON pointer(`/...`)
|
||||
- 段中的 RFC6901 转义规则:`~` => `~0`,`/` => `~1`
|
||||
验证:
|
||||
|
||||
### `source: "exec"`
|
||||
- `provider` 必须匹配 `^[a-z][a-z0-9_-]{0,63}$`
|
||||
- `id` 必须匹配 `^[A-Za-z0-9][A-Za-z0-9._:/-]{0,255}$`
|
||||
- `id` 不能包含以斜杠分隔的 `.` 或 `..` 路径段(例如 `a/../b` 会被拒绝)
|
||||
|
||||
```json5
|
||||
{ source: "exec", provider: "vault", id: "providers/openai/apiKey" }
|
||||
```
|
||||
|
||||
验证规则:
|
||||
|
||||
- `provider` 必须匹配 `^[a-z][a-z0-9_-]{0,63}$`
|
||||
- `id` 必须匹配 `^[A-Za-z0-9][A-Za-z0-9._:/-]{0,255}$`
|
||||
- `id` 不得包含以 `/` 分隔的 `.` 或 `..` 路径段(例如 `a/../b` 会被拒绝)
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## 提供商配置
|
||||
|
||||
@ -160,142 +162,143 @@ SecretRef 只会在实际上处于活动状态的表面上进行验证。
|
||||
}
|
||||
```
|
||||
|
||||
### Env 提供商
|
||||
<AccordionGroup>
|
||||
<Accordion title="Env 提供商">
|
||||
- 可通过 `allowlist` 设置可选允许列表。
|
||||
- 缺失/为空的 env 值会导致解析失败。
|
||||
</Accordion>
|
||||
<Accordion title="File 提供商">
|
||||
- 从 `path` 读取本地文件。
|
||||
- `mode: "json"` 期望 JSON 对象负载,并将 `id` 作为 pointer 解析。
|
||||
- `mode: "singleValue"` 期望引用 id 为 `"value"`,并返回文件内容。
|
||||
- 路径必须通过所有权/权限检查。
|
||||
- Windows 失败即关闭说明:如果某个路径无法进行 ACL 验证,则解析失败。仅对受信任路径,可在该提供商上设置 `allowInsecurePath: true` 以绕过路径安全检查。
|
||||
</Accordion>
|
||||
<Accordion title="Exec 提供商">
|
||||
- 运行已配置的绝对二进制路径,不经过 shell。
|
||||
- 默认情况下,`command` 必须指向常规文件(而非符号链接)。
|
||||
- 设置 `allowSymlinkCommand: true` 可允许符号链接命令路径(例如 Homebrew shim)。OpenClaw 会验证解析后的目标路径。
|
||||
- 将 `allowSymlinkCommand` 与 `trustedDirs` 搭配使用,以支持包管理器路径(例如 `["/opt/homebrew"]`)。
|
||||
- 支持超时、无输出超时、输出字节限制、环境变量允许列表和受信任目录。
|
||||
- Windows 失败即关闭说明:如果命令路径无法进行 ACL 验证,则解析失败。仅对受信任路径,可在该提供商上设置 `allowInsecurePath: true` 以绕过路径安全检查。
|
||||
|
||||
- 可通过 `allowlist` 设置可选允许列表。
|
||||
- 环境变量值缺失或为空都会导致解析失败。
|
||||
请求负载(stdin):
|
||||
|
||||
### File 提供商
|
||||
```json
|
||||
{ "protocolVersion": 1, "provider": "vault", "ids": ["providers/openai/apiKey"] }
|
||||
```
|
||||
|
||||
- 从 `path` 读取本地文件。
|
||||
- `mode: "json"` 期待 JSON 对象载荷,并将 `id` 解析为 pointer。
|
||||
- `mode: "singleValue"` 期待 ref id 为 `"value"`,并返回文件内容。
|
||||
- 路径必须通过所有权/权限检查。
|
||||
- Windows 失败即关闭说明:如果无法对某个路径进行 ACL 验证,则解析失败。仅对受信任路径,可在该提供商上设置 `allowInsecurePath: true`,以绕过路径安全检查。
|
||||
响应负载(stdout):
|
||||
|
||||
### Exec 提供商
|
||||
```jsonc
|
||||
{ "protocolVersion": 1, "values": { "providers/openai/apiKey": "<openai-api-key>" } } // pragma: allowlist secret
|
||||
```
|
||||
|
||||
- 运行已配置的绝对二进制路径,不经过 shell。
|
||||
- 默认情况下,`command` 必须指向常规文件(不能是符号链接)。
|
||||
- 设置 `allowSymlinkCommand: true` 可允许符号链接命令路径(例如 Homebrew shim)。OpenClaw 会验证解析后的目标路径。
|
||||
- 对于包管理器路径(例如 `["/opt/homebrew"]`),应将 `allowSymlinkCommand` 与 `trustedDirs` 搭配使用。
|
||||
- 支持超时、无输出超时、输出字节限制、环境变量允许列表以及受信任目录。
|
||||
- Windows 失败即关闭说明:如果无法对命令路径进行 ACL 验证,则解析失败。仅对受信任路径,可在该提供商上设置 `allowInsecurePath: true`,以绕过路径安全检查。
|
||||
可选的逐 id 错误:
|
||||
|
||||
请求载荷(stdin):
|
||||
```json
|
||||
{
|
||||
"protocolVersion": 1,
|
||||
"values": {},
|
||||
"errors": { "providers/openai/apiKey": { "message": "not found" } }
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{ "protocolVersion": 1, "provider": "vault", "ids": ["providers/openai/apiKey"] }
|
||||
```
|
||||
|
||||
响应载荷(stdout):
|
||||
|
||||
```jsonc
|
||||
{ "protocolVersion": 1, "values": { "providers/openai/apiKey": "<openai-api-key>" } } // pragma: allowlist secret
|
||||
```
|
||||
|
||||
可选的按 ID 错误:
|
||||
|
||||
```json
|
||||
{
|
||||
"protocolVersion": 1,
|
||||
"values": {},
|
||||
"errors": { "providers/openai/apiKey": { "message": "not found" } }
|
||||
}
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Exec 集成示例
|
||||
|
||||
### 1Password CLI
|
||||
|
||||
```json5
|
||||
{
|
||||
secrets: {
|
||||
providers: {
|
||||
onepassword_openai: {
|
||||
source: "exec",
|
||||
command: "/opt/homebrew/bin/op",
|
||||
allowSymlinkCommand: true, // Homebrew 符号链接二进制所必需
|
||||
trustedDirs: ["/opt/homebrew"],
|
||||
args: ["read", "op://Personal/OpenClaw QA API Key/password"],
|
||||
passEnv: ["HOME"],
|
||||
jsonOnly: false,
|
||||
<AccordionGroup>
|
||||
<Accordion title="1Password CLI">
|
||||
```json5
|
||||
{
|
||||
secrets: {
|
||||
providers: {
|
||||
onepassword_openai: {
|
||||
source: "exec",
|
||||
command: "/opt/homebrew/bin/op",
|
||||
allowSymlinkCommand: true, // Homebrew 符号链接二进制文件所必需
|
||||
trustedDirs: ["/opt/homebrew"],
|
||||
args: ["read", "op://Personal/OpenClaw QA API Key/password"],
|
||||
passEnv: ["HOME"],
|
||||
jsonOnly: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
models: {
|
||||
providers: {
|
||||
openai: {
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
models: [{ id: "gpt-5", name: "gpt-5" }],
|
||||
apiKey: { source: "exec", provider: "onepassword_openai", id: "value" },
|
||||
models: {
|
||||
providers: {
|
||||
openai: {
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
models: [{ id: "gpt-5", name: "gpt-5" }],
|
||||
apiKey: { source: "exec", provider: "onepassword_openai", id: "value" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### HashiCorp Vault CLI
|
||||
|
||||
```json5
|
||||
{
|
||||
secrets: {
|
||||
providers: {
|
||||
vault_openai: {
|
||||
source: "exec",
|
||||
command: "/opt/homebrew/bin/vault",
|
||||
allowSymlinkCommand: true, // Homebrew 符号链接二进制所必需
|
||||
trustedDirs: ["/opt/homebrew"],
|
||||
args: ["kv", "get", "-field=OPENAI_API_KEY", "secret/openclaw"],
|
||||
passEnv: ["VAULT_ADDR", "VAULT_TOKEN"],
|
||||
jsonOnly: false,
|
||||
}
|
||||
```
|
||||
</Accordion>
|
||||
<Accordion title="HashiCorp Vault CLI">
|
||||
```json5
|
||||
{
|
||||
secrets: {
|
||||
providers: {
|
||||
vault_openai: {
|
||||
source: "exec",
|
||||
command: "/opt/homebrew/bin/vault",
|
||||
allowSymlinkCommand: true, // Homebrew 符号链接二进制文件所必需
|
||||
trustedDirs: ["/opt/homebrew"],
|
||||
args: ["kv", "get", "-field=OPENAI_API_KEY", "secret/openclaw"],
|
||||
passEnv: ["VAULT_ADDR", "VAULT_TOKEN"],
|
||||
jsonOnly: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
models: {
|
||||
providers: {
|
||||
openai: {
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
models: [{ id: "gpt-5", name: "gpt-5" }],
|
||||
apiKey: { source: "exec", provider: "vault_openai", id: "value" },
|
||||
models: {
|
||||
providers: {
|
||||
openai: {
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
models: [{ id: "gpt-5", name: "gpt-5" }],
|
||||
apiKey: { source: "exec", provider: "vault_openai", id: "value" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### `sops`
|
||||
|
||||
```json5
|
||||
{
|
||||
secrets: {
|
||||
providers: {
|
||||
sops_openai: {
|
||||
source: "exec",
|
||||
command: "/opt/homebrew/bin/sops",
|
||||
allowSymlinkCommand: true, // Homebrew 符号链接二进制所必需
|
||||
trustedDirs: ["/opt/homebrew"],
|
||||
args: ["-d", "--extract", '["providers"]["openai"]["apiKey"]', "/path/to/secrets.enc.json"],
|
||||
passEnv: ["SOPS_AGE_KEY_FILE"],
|
||||
jsonOnly: false,
|
||||
}
|
||||
```
|
||||
</Accordion>
|
||||
<Accordion title="sops">
|
||||
```json5
|
||||
{
|
||||
secrets: {
|
||||
providers: {
|
||||
sops_openai: {
|
||||
source: "exec",
|
||||
command: "/opt/homebrew/bin/sops",
|
||||
allowSymlinkCommand: true, // Homebrew 符号链接二进制文件所必需
|
||||
trustedDirs: ["/opt/homebrew"],
|
||||
args: ["-d", "--extract", '["providers"]["openai"]["apiKey"]', "/path/to/secrets.enc.json"],
|
||||
passEnv: ["SOPS_AGE_KEY_FILE"],
|
||||
jsonOnly: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
models: {
|
||||
providers: {
|
||||
openai: {
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
models: [{ id: "gpt-5", name: "gpt-5" }],
|
||||
apiKey: { source: "exec", provider: "sops_openai", id: "value" },
|
||||
models: {
|
||||
providers: {
|
||||
openai: {
|
||||
baseUrl: "https://api.openai.com/v1",
|
||||
models: [{ id: "gpt-5", name: "gpt-5" }],
|
||||
apiKey: { source: "exec", provider: "sops_openai", id: "value" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
}
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## MCP 服务器环境变量
|
||||
|
||||
通过 `plugins.entries.acpx.config.mcpServers` 配置的 MCP 服务器环境变量支持 SecretInput。这样可以避免将 API 密钥和令牌放在明文配置中:
|
||||
通过 `plugins.entries.acpx.config.mcpServers` 配置的 MCP 服务器环境变量支持 SecretInput。这样可以让 API key 和 token 不出现在明文配置中:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -324,11 +327,11 @@ SecretRef 只会在实际上处于活动状态的表面上进行验证。
|
||||
}
|
||||
```
|
||||
|
||||
明文字符串值仍然可用。像 `${MCP_SERVER_API_KEY}` 这样的 env-template refs 和 SecretRef 对象会在 Gateway 网关激活期间、MCP 服务器进程启动之前完成解析。与其他 SecretRef 表面一样,只有当 `acpx` 插件实际上处于活动状态时,未解析的 refs 才会阻止激活。
|
||||
明文字符串值仍然可用。诸如 `${MCP_SERVER_API_KEY}` 这样的 env 模板引用以及 SecretRef 对象,都会在生成 MCP 服务器进程之前于 Gateway 网关激活期间被解析。与其他 SecretRef 表面一样,只有当 `acpx` 插件实际上处于活动状态时,未解析的引用才会阻止激活。
|
||||
|
||||
## 沙箱 SSH 认证材料
|
||||
|
||||
核心 `ssh` 沙箱后端也支持将 SecretRef 用于 SSH 认证材料:
|
||||
核心 `ssh` 沙箱后端同样支持用于 SSH 认证材料的 SecretRef:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -351,56 +354,58 @@ SecretRef 只会在实际上处于活动状态的表面上进行验证。
|
||||
|
||||
运行时行为:
|
||||
|
||||
- OpenClaw 会在沙箱激活期间解析这些 refs,而不是在每次 SSH 调用时惰性解析。
|
||||
- 解析后的值会写入具有限制性权限的临时文件,并用于生成的 SSH 配置。
|
||||
- 如果生效的沙箱后端不是 `ssh`,这些 refs 将保持非活动状态,不会阻止启动。
|
||||
- OpenClaw 会在沙箱激活期间解析这些引用,而不是在每次 SSH 调用时延迟解析。
|
||||
- 解析后的值会以严格权限写入临时文件,并用于生成的 SSH 配置。
|
||||
- 如果有效沙箱后端不是 `ssh`,这些引用会保持非活动状态,不会阻止启动。
|
||||
|
||||
## 支持的凭证表面
|
||||
|
||||
受支持与不受支持凭证的规范列表见:
|
||||
规范的受支持和不受支持凭证列表见:
|
||||
|
||||
- [SecretRef 凭证表面](/zh-CN/reference/secretref-credential-surface)
|
||||
- [SecretRef Credential Surface](/zh-CN/reference/secretref-credential-surface)
|
||||
|
||||
运行时签发或会轮换的凭证,以及 OAuth 刷新材料,都被有意排除在只读 SecretRef 解析之外。
|
||||
<Note>
|
||||
运行时铸造或轮换的凭证,以及 OAuth 刷新材料,会被有意排除在只读 SecretRef 解析之外。
|
||||
</Note>
|
||||
|
||||
## 必需行为与优先级
|
||||
## 必需行为和优先级
|
||||
|
||||
- 字段没有 ref:行为不变。
|
||||
- 字段有 ref:在活动表面上,激活期间必须可解析。
|
||||
- 如果同时存在明文和 ref,在受支持的优先级路径上,ref 优先。
|
||||
- 脱敏哨兵值 `__OPENCLAW_REDACTED__` 保留供内部配置脱敏/恢复使用,作为字面量提交的配置数据时会被拒绝。
|
||||
- 不带引用的字段:保持不变。
|
||||
- 带有引用的字段:在活动表面上激活时为必需。
|
||||
- 如果明文和引用同时存在,在受支持的优先级路径上,引用优先。
|
||||
- 脱敏哨兵值 `__OPENCLAW_REDACTED__` 保留用于内部配置脱敏/恢复,作为字面提交的配置数据时会被拒绝。
|
||||
|
||||
警告与审计信号:
|
||||
警告和审计信号:
|
||||
|
||||
- `SECRETS_REF_OVERRIDES_PLAINTEXT`(运行时警告)
|
||||
- `REF_SHADOWED`(当 `auth-profiles.json` 中的凭证优先于 `openclaw.json` refs 时的审计发现)
|
||||
- `REF_SHADOWED`(当 `auth-profiles.json` 中的凭证优先于 `openclaw.json` 中的引用时的审计发现)
|
||||
|
||||
Google Chat 兼容性行为:
|
||||
Google Chat 兼容行为:
|
||||
|
||||
- `serviceAccountRef` 优先于明文 `serviceAccount`。
|
||||
- 当设置了同级 ref 时,明文值会被忽略。
|
||||
- 当设置了同级引用时,明文值会被忽略。
|
||||
|
||||
## 激活触发器
|
||||
## 激活触发点
|
||||
|
||||
秘密激活会在以下场景运行:
|
||||
密钥激活会在以下情况下运行:
|
||||
|
||||
- 启动时(预检查 + 最终激活)
|
||||
- 配置重载的热应用路径
|
||||
- 配置重载的重启检查路径
|
||||
- 启动时(预检加最终激活)
|
||||
- 配置重载热应用路径
|
||||
- 配置重载重启检查路径
|
||||
- 通过 `secrets.reload` 手动重载
|
||||
- Gateway 网关配置写入 RPC 预检查(`config.set` / `config.apply` / `config.patch`),用于在持久化编辑之前,针对提交配置载荷中活动表面的 SecretRef 可解析性进行检查
|
||||
- Gateway 网关配置写入 RPC 预检(`config.set` / `config.apply` / `config.patch`),会在持久化编辑前,对所提交配置负载中活动表面的 SecretRef 可解析性进行检查
|
||||
|
||||
激活契约:
|
||||
|
||||
- 成功时会原子交换快照。
|
||||
- 成功时会原子性交换快照。
|
||||
- 启动失败会中止 Gateway 网关启动。
|
||||
- 运行时重载失败会保留上一次已知良好的快照。
|
||||
- 写入 RPC 预检查失败会拒绝提交的配置,并保持磁盘配置和活动运行时快照都不变。
|
||||
- 为出站辅助工具/工具调用提供显式的单次渠道令牌不会触发 SecretRef 激活;激活点仍然只有启动、重载和显式 `secrets.reload`。
|
||||
- 运行时重载失败时会保留最后已知良好的快照。
|
||||
- 写入 RPC 预检失败会拒绝提交的配置,并保持磁盘配置和活动运行时快照均不变。
|
||||
- 为出站辅助函数/工具调用提供显式的逐调用渠道 token,不会触发 SecretRef 激活;激活点仍然仅限于启动、重载和显式 `secrets.reload`。
|
||||
|
||||
## 降级与恢复信号
|
||||
## 降级和恢复信号
|
||||
|
||||
当健康状态下的重载时激活失败后,OpenClaw 会进入秘密降级状态。
|
||||
当健康状态下的重载时激活失败后,OpenClaw 会进入密钥降级状态。
|
||||
|
||||
一次性系统事件和日志代码:
|
||||
|
||||
@ -409,136 +414,158 @@ Google Chat 兼容性行为:
|
||||
|
||||
行为:
|
||||
|
||||
- 降级:运行时会保留上一次已知良好的快照。
|
||||
- 恢复:在下一次成功激活后只发出一次。
|
||||
- 如果已经处于降级状态时再次失败,会记录警告,但不会重复刷屏事件。
|
||||
- 启动快速失败不会发出降级事件,因为运行时从未真正进入活动状态。
|
||||
- 降级:运行时保留最后已知良好的快照。
|
||||
- 恢复:在下一次成功激活后仅发出一次。
|
||||
- 在已处于降级状态时重复失败会记录警告,但不会刷屏事件。
|
||||
- 启动快速失败不会发出降级事件,因为运行时从未进入活动状态。
|
||||
|
||||
## 命令路径解析
|
||||
|
||||
命令路径可以通过 Gateway 网关快照 RPC 选择加入受支持的 SecretRef 解析。
|
||||
命令路径可通过 Gateway 网关快照 RPC 选择启用受支持的 SecretRef 解析。
|
||||
|
||||
大致有两类行为:
|
||||
主要有两类行为:
|
||||
|
||||
- 严格命令路径(例如 `openclaw memory` 的远程 memory 路径,以及当 `openclaw qr --remote` 需要远程共享密钥 refs 时)会从活动快照中读取,并在必需 SecretRef 不可用时快速失败。
|
||||
- 只读命令路径(例如 `openclaw status`、`openclaw status --all`、`openclaw channels status`、`openclaw channels resolve`、`openclaw security audit`,以及只读的 doctor/config 修复流程)同样优先使用活动快照,但当目标 SecretRef 在该命令路径中不可用时,会降级而不是中止。
|
||||
<Tabs>
|
||||
<Tab title="严格命令路径">
|
||||
例如 `openclaw memory` 远程内存路径,以及在需要远程共享密钥引用时的 `openclaw qr --remote`。它们会从活动快照中读取,并在所需 SecretRef 不可用时快速失败。
|
||||
</Tab>
|
||||
<Tab title="只读命令路径">
|
||||
例如 `openclaw status`、`openclaw status --all`、`openclaw channels status`、`openclaw channels resolve`、`openclaw security audit`,以及只读的 Doctor/配置修复流程。它们同样优先使用活动快照,但当目标 SecretRef 在该命令路径中不可用时,会降级而不是中止。
|
||||
|
||||
只读行为:
|
||||
只读行为:
|
||||
|
||||
- 当 Gateway 网关正在运行时,这些命令会优先从活动快照读取。
|
||||
- 如果 Gateway 网关解析不完整,或 Gateway 网关不可用,它们会尝试针对特定命令表面的本地定向回退。
|
||||
- 如果目标 SecretRef 仍然不可用,命令会继续执行,但输出为降级的只读结果,并带有明确诊断,例如“已配置,但在此命令路径中不可用”。
|
||||
- 这种降级行为仅限于命令本地,不会削弱运行时启动、重载或发送/认证路径。
|
||||
- 当 Gateway 网关正在运行时,这些命令会优先从活动快照中读取。
|
||||
- 如果 Gateway 网关解析不完整或 Gateway 网关不可用,它们会尝试针对该特定命令表面的本地回退。
|
||||
- 如果目标 SecretRef 仍然不可用,命令会继续输出降级的只读结果,并带有明确诊断,例如“已配置但在此命令路径中不可用”。
|
||||
- 这种降级行为仅限命令本地。它不会削弱运行时启动、重载或发送/认证路径。
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
其他说明:
|
||||
|
||||
- 在后端秘密轮换后刷新快照,需要使用 `openclaw secrets reload`。
|
||||
- 这些命令路径使用的 Gateway 网关 RPC 方法是:`secrets.resolve`。
|
||||
- 后端密钥轮换后的快照刷新由 `openclaw secrets reload` 处理。
|
||||
- 这些命令路径使用的 Gateway 网关 RPC 方法:`secrets.resolve`。
|
||||
|
||||
## 审计与配置工作流
|
||||
## 审计和配置工作流
|
||||
|
||||
默认运维流程:
|
||||
默认操作员流程:
|
||||
|
||||
```bash
|
||||
openclaw secrets audit --check
|
||||
openclaw secrets configure
|
||||
openclaw secrets audit --check
|
||||
```
|
||||
<Steps>
|
||||
<Step title="审计当前状态">
|
||||
```bash
|
||||
openclaw secrets audit --check
|
||||
```
|
||||
</Step>
|
||||
<Step title="配置 SecretRef">
|
||||
```bash
|
||||
openclaw secrets configure
|
||||
```
|
||||
</Step>
|
||||
<Step title="重新审计">
|
||||
```bash
|
||||
openclaw secrets audit --check
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
### `secrets audit`
|
||||
<AccordionGroup>
|
||||
<Accordion title="secrets audit">
|
||||
审计发现包括:
|
||||
|
||||
发现项包括:
|
||||
- 静态存储中的明文值(`openclaw.json`、`auth-profiles.json`、`.env` 和生成的 `agents/*/agent/models.json`)
|
||||
- 生成的 `models.json` 条目中明文敏感提供商头残留
|
||||
- 未解析的引用
|
||||
- 优先级遮蔽(`auth-profiles.json` 优先于 `openclaw.json` 引用)
|
||||
- 遗留残留(`auth.json`、OAuth 提醒)
|
||||
|
||||
- 静态明文值(位于 `openclaw.json`、`auth-profiles.json`、`.env` 以及生成的 `agents/*/agent/models.json` 中)
|
||||
- 生成的 `models.json` 条目中明文敏感提供商 header 残留
|
||||
- 未解析的 refs
|
||||
- 优先级遮蔽(`auth-profiles.json` 优先于 `openclaw.json` refs)
|
||||
- 旧版残留(`auth.json`、OAuth 提醒)
|
||||
Exec 说明:
|
||||
|
||||
Exec 说明:
|
||||
- 默认情况下,审计会跳过 exec SecretRef 可解析性检查,以避免命令副作用。
|
||||
- 使用 `openclaw secrets audit --allow-exec` 可在审计期间执行 exec 提供商。
|
||||
|
||||
- 默认情况下,审计会跳过 exec SecretRef 可解析性检查,以避免命令副作用。
|
||||
- 使用 `openclaw secrets audit --allow-exec` 可在审计期间执行 exec 提供商。
|
||||
头残留说明:
|
||||
|
||||
Header 残留说明:
|
||||
- 敏感提供商头检测基于名称启发式规则(常见认证/凭证头名称及片段,例如 `authorization`、`x-api-key`、`token`、`secret`、`password` 和 `credential`)。
|
||||
|
||||
- 敏感提供商 header 检测基于名称启发式规则(常见认证/凭证 header 名称及片段,例如 `authorization`、`x-api-key`、`token`、`secret`、`password` 和 `credential`)。
|
||||
</Accordion>
|
||||
<Accordion title="secrets configure">
|
||||
一个交互式辅助工具,用于:
|
||||
|
||||
### `secrets configure`
|
||||
- 先配置 `secrets.providers`(`env`/`file`/`exec`,添加/编辑/删除)
|
||||
- 让你在 `openclaw.json` 中选择受支持的携带密钥字段,以及某个智能体范围内的 `auth-profiles.json`
|
||||
- 可以直接在目标选择器中创建新的 `auth-profiles.json` 映射
|
||||
- 收集 SecretRef 详情(`source`、`provider`、`id`)
|
||||
- 执行预检解析
|
||||
- 可立即应用
|
||||
|
||||
交互式辅助工具,可执行以下操作:
|
||||
Exec 说明:
|
||||
|
||||
- 先配置 `secrets.providers`(`env`/`file`/`exec`,添加/编辑/删除)
|
||||
- 让你在一个智能体作用域中,选择 `openclaw.json` 和 `auth-profiles.json` 里受支持的含密字段
|
||||
- 可直接在目标选择器中创建新的 `auth-profiles.json` 映射
|
||||
- 捕获 SecretRef 详情(`source`、`provider`、`id`)
|
||||
- 运行预检查解析
|
||||
- 可立即应用
|
||||
- 除非设置了 `--allow-exec`,否则预检会跳过 exec SecretRef 检查。
|
||||
- 如果你直接通过 `configure --apply` 应用,并且计划中包含 exec 引用/提供商,则在应用步骤中也要保留 `--allow-exec`。
|
||||
|
||||
Exec 说明:
|
||||
实用模式:
|
||||
|
||||
- 除非设置了 `--allow-exec`,否则预检查会跳过 exec SecretRef 检查。
|
||||
- 如果你直接从 `configure --apply` 应用,并且计划中包含 exec refs/providers,则请在应用步骤中也保持设置 `--allow-exec`。
|
||||
- `openclaw secrets configure --providers-only`
|
||||
- `openclaw secrets configure --skip-provider-setup`
|
||||
- `openclaw secrets configure --agent <id>`
|
||||
|
||||
有用模式:
|
||||
`configure` 应用默认行为:
|
||||
|
||||
- `openclaw secrets configure --providers-only`
|
||||
- `openclaw secrets configure --skip-provider-setup`
|
||||
- `openclaw secrets configure --agent <id>`
|
||||
- 清除 `auth-profiles.json` 中目标提供商对应的匹配静态凭证
|
||||
- 清除 `auth.json` 中遗留的静态 `api_key` 条目
|
||||
- 清除 `<config-dir>/.env` 中匹配的已知密钥行
|
||||
|
||||
`configure` 的默认应用行为:
|
||||
</Accordion>
|
||||
<Accordion title="secrets apply">
|
||||
应用已保存的计划:
|
||||
|
||||
- 清除 `auth-profiles.json` 中目标提供商匹配的静态凭证
|
||||
- 清除 `auth.json` 中旧版静态 `api_key` 条目
|
||||
- 清除 `<config-dir>/.env` 中匹配的已知秘密行
|
||||
```bash
|
||||
openclaw secrets apply --from /tmp/openclaw-secrets-plan.json
|
||||
openclaw secrets apply --from /tmp/openclaw-secrets-plan.json --allow-exec
|
||||
openclaw secrets apply --from /tmp/openclaw-secrets-plan.json --dry-run
|
||||
openclaw secrets apply --from /tmp/openclaw-secrets-plan.json --dry-run --allow-exec
|
||||
```
|
||||
|
||||
### `secrets apply`
|
||||
Exec 说明:
|
||||
|
||||
应用已保存的计划:
|
||||
- 除非设置了 `--allow-exec`,否则 dry-run 会跳过 exec 检查。
|
||||
- 写入模式会拒绝包含 exec SecretRef/提供商的计划,除非设置了 `--allow-exec`。
|
||||
|
||||
```bash
|
||||
openclaw secrets apply --from /tmp/openclaw-secrets-plan.json
|
||||
openclaw secrets apply --from /tmp/openclaw-secrets-plan.json --allow-exec
|
||||
openclaw secrets apply --from /tmp/openclaw-secrets-plan.json --dry-run
|
||||
openclaw secrets apply --from /tmp/openclaw-secrets-plan.json --dry-run --allow-exec
|
||||
```
|
||||
有关严格目标/路径契约细节和精确拒绝规则,请参阅 [Secrets Apply Plan Contract](/zh-CN/gateway/secrets-plan-contract)。
|
||||
|
||||
Exec 说明:
|
||||
|
||||
- dry run 会跳过 exec 检查,除非设置了 `--allow-exec`。
|
||||
- 写入模式会拒绝包含 exec SecretRefs/providers 的计划,除非设置了 `--allow-exec`。
|
||||
|
||||
关于严格的目标/路径契约细节和精确的拒绝规则,请参见:
|
||||
|
||||
- [Secrets Apply Plan Contract](/zh-CN/gateway/secrets-plan-contract)
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 单向安全策略
|
||||
|
||||
OpenClaw 有意不会写入包含历史明文秘密值的回滚备份。
|
||||
<Warning>
|
||||
OpenClaw 故意不会写入包含历史明文密钥值的回滚备份。
|
||||
</Warning>
|
||||
|
||||
安全模型:
|
||||
|
||||
- 写入模式前必须通过预检查
|
||||
- 写入模式前必须先通过预检
|
||||
- 提交前会验证运行时激活
|
||||
- apply 会使用原子文件替换更新文件,并在失败时尽力恢复
|
||||
- apply 会使用原子文件替换更新文件,并在失败时尽最大努力恢复
|
||||
|
||||
## 旧版认证兼容性说明
|
||||
## 遗留认证兼容性说明
|
||||
|
||||
对于静态凭证,运行时不再依赖明文旧版认证存储。
|
||||
对于静态凭证,运行时不再依赖明文遗留认证存储。
|
||||
|
||||
- 运行时凭证来源是解析后的内存快照。
|
||||
- 发现旧版静态 `api_key` 条目时会进行清除。
|
||||
- 与 OAuth 相关的兼容性行为仍然单独处理。
|
||||
- 运行时凭证来源是已解析的内存快照。
|
||||
- 发现后会清除遗留静态 `api_key` 条目。
|
||||
- 与 OAuth 相关的兼容行为仍然单独处理。
|
||||
|
||||
## Web UI 说明
|
||||
|
||||
某些 SecretInput 联合类型在原始编辑器模式下比在表单模式下更容易配置。
|
||||
某些 SecretInput 联合类型在原始编辑器模式下比表单模式更容易配置。
|
||||
|
||||
## 相关文档
|
||||
## 相关内容
|
||||
|
||||
- CLI 命令:[secrets](/zh-CN/cli/secrets)
|
||||
- 计划契约细节:[Secrets Apply Plan Contract](/zh-CN/gateway/secrets-plan-contract)
|
||||
- 凭证表面:[SecretRef Credential Surface](/zh-CN/reference/secretref-credential-surface)
|
||||
- 认证设置:[Authentication](/zh-CN/gateway/authentication)
|
||||
- 安全态势:[Security](/zh-CN/gateway/security)
|
||||
- 环境变量优先级:[环境变量](/zh-CN/help/environment)
|
||||
- [Authentication](/zh-CN/gateway/authentication) — 认证设置
|
||||
- [CLI: secrets](/zh-CN/cli/secrets) — CLI 命令
|
||||
- [环境变量](/zh-CN/help/environment) — 环境变量优先级
|
||||
- [SecretRef Credential Surface](/zh-CN/reference/secretref-credential-surface) — 凭证表面
|
||||
- [Secrets Apply Plan Contract](/zh-CN/gateway/secrets-plan-contract) — 计划契约详情
|
||||
- [安全](/zh-CN/gateway/security) — 安全态势
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -6,24 +6,24 @@ read_when:
|
||||
- 实现提供商运行时钩子或渠道插件
|
||||
sidebarTitle: Internals
|
||||
summary: 插件内部机制:能力模型、归属、契约、加载管线和运行时辅助工具
|
||||
title: 插件内部机制
|
||||
title: 插件架构内部机制
|
||||
x-i18n:
|
||||
generated_at: "2026-04-25T02:35:33Z"
|
||||
generated_at: "2026-04-26T07:50:09Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: d1fd7d9192c8c06aceeb6e8054a740bba27c94770e17eabf064627adda884e77
|
||||
source_hash: 16664d284a8bfbfcb9914bb012d1f36dfdd60406636d6bf4b011f76e886cb518
|
||||
source_path: plugins/architecture.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
这是 OpenClaw 插件系统的**深度架构参考**。如需实用指南,请先从下面这些聚焦页面之一开始。
|
||||
这是 OpenClaw 插件系统的**深度架构参考**。如果你想看实用指南,请先从下面这些聚焦页面之一开始。
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="安装和使用插件" icon="plug" href="/zh-CN/tools/plugin">
|
||||
面向终端用户的指南,介绍如何添加、启用和故障排除插件。
|
||||
面向最终用户的指南,介绍如何添加、启用以及排查插件问题。
|
||||
</Card>
|
||||
<Card title="构建插件" icon="rocket" href="/zh-CN/plugins/building-plugins">
|
||||
首个插件教程,使用最小可工作的清单文件。
|
||||
第一个插件教程,包含最小可工作的 manifest。
|
||||
</Card>
|
||||
<Card title="渠道插件" icon="comments" href="/zh-CN/plugins/sdk-channel-plugins">
|
||||
构建一个消息渠道插件。
|
||||
@ -31,67 +31,79 @@ x-i18n:
|
||||
<Card title="提供商插件" icon="microchip" href="/zh-CN/plugins/sdk-provider-plugins">
|
||||
构建一个模型提供商插件。
|
||||
</Card>
|
||||
<Card title="SDK 概览" icon="book" href="/zh-CN/plugins/sdk-overview">
|
||||
<Card title="插件 SDK 概览" icon="book" href="/zh-CN/plugins/sdk-overview">
|
||||
导入映射和注册 API 参考。
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## 公开能力模型
|
||||
## 公共能力模型
|
||||
|
||||
能力是 OpenClaw 内部公开的**原生插件**模型。每个原生 OpenClaw 插件都会针对一种或多种能力类型进行注册:
|
||||
能力是 OpenClaw 内部公共的**原生插件**模型。每个原生 OpenClaw 插件都会针对一种或多种能力类型进行注册:
|
||||
|
||||
| 能力 | 注册方法 | 示例插件 |
|
||||
| ---------------------- | ------------------------------------------------ | ------------------------------------ |
|
||||
| 文本推理 | `api.registerProvider(...)` | `openai`, `anthropic` |
|
||||
| CLI 推理后端 | `api.registerCliBackend(...)` | `openai`, `anthropic` |
|
||||
| 语音 | `api.registerSpeechProvider(...)` | `elevenlabs`, `microsoft` |
|
||||
| 实时转录 | `api.registerRealtimeTranscriptionProvider(...)` | `openai` |
|
||||
| 文本推理 | `api.registerProvider(...)` | `openai`、`anthropic` |
|
||||
| CLI 推理后端 | `api.registerCliBackend(...)` | `openai`、`anthropic` |
|
||||
| 语音 | `api.registerSpeechProvider(...)` | `elevenlabs`、`microsoft` |
|
||||
| 实时转写 | `api.registerRealtimeTranscriptionProvider(...)` | `openai` |
|
||||
| 实时语音 | `api.registerRealtimeVoiceProvider(...)` | `openai` |
|
||||
| 媒体理解 | `api.registerMediaUnderstandingProvider(...)` | `openai`, `google` |
|
||||
| 图像生成 | `api.registerImageGenerationProvider(...)` | `openai`, `google`, `fal`, `minimax` |
|
||||
| 音乐生成 | `api.registerMusicGenerationProvider(...)` | `google`, `minimax` |
|
||||
| 媒体理解 | `api.registerMediaUnderstandingProvider(...)` | `openai`、`google` |
|
||||
| 图像生成 | `api.registerImageGenerationProvider(...)` | `openai`、`google`、`fal`、`minimax` |
|
||||
| 音乐生成 | `api.registerMusicGenerationProvider(...)` | `google`、`minimax` |
|
||||
| 视频生成 | `api.registerVideoGenerationProvider(...)` | `qwen` |
|
||||
| Web 抓取 | `api.registerWebFetchProvider(...)` | `firecrawl` |
|
||||
| Web 搜索 | `api.registerWebSearchProvider(...)` | `google` |
|
||||
| 渠道 / 消息 | `api.registerChannel(...)` | `msteams`, `matrix` |
|
||||
| 渠道 / 消息传递 | `api.registerChannel(...)` | `msteams`、`matrix` |
|
||||
| Gateway 网关发现 | `api.registerGatewayDiscoveryService(...)` | `bonjour` |
|
||||
|
||||
如果某个插件注册了零个能力,但提供了钩子、工具、发现服务或后台服务,则它属于**仅 legacy hook** 插件。该模式目前仍被完全支持。
|
||||
<Note>
|
||||
一个注册了零能力、但提供钩子、工具、发现服务或后台服务的插件,属于**旧式纯钩子**插件。该模式目前仍然被完全支持。
|
||||
</Note>
|
||||
|
||||
### 外部兼容性立场
|
||||
|
||||
能力模型已经在核心中落地,并且当前已被内置 / 原生插件使用,但外部插件兼容性仍需要比“它已导出,因此它已冻结”更严格的标准。
|
||||
能力模型已经落地到核心中,并已被今天的内置 / 原生插件使用,但外部插件兼容性仍然需要比“它已导出,因此它已冻结”更严格的标准。
|
||||
|
||||
| 插件情况 | 指引 |
|
||||
| 插件情况 | 指导原则 |
|
||||
| ------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
|
||||
| 现有外部插件 | 保持基于钩子的集成继续可用;这是兼容性的基线。 |
|
||||
| 新的内置 / 原生插件 | 优先选择显式能力注册,而不是面向特定厂商的深入访问或新的纯钩子设计。 |
|
||||
| 采用能力注册的外部插件 | 允许,但除非文档明确标记为稳定,否则应将特定于能力的辅助接口视为仍在演进中。 |
|
||||
| 现有外部插件 | 保持基于钩子的集成可用;这是兼容性的基线。 |
|
||||
| 新的内置 / 原生插件 | 优先使用显式能力注册,而不是针对特定厂商的深入调用或新的纯钩子设计。 |
|
||||
| 采用能力注册的外部插件 | 允许,但除非文档将其标记为稳定,否则应将特定能力的辅助表面视为仍在演进中。 |
|
||||
|
||||
能力注册是预期的发展方向。在过渡期间,对于外部插件来说,legacy hook 仍然是最安全、最不易破坏的路径。已导出的辅助子路径并不完全等同 —— 应优先选择范围明确、已文档化的契约,而不是偶然暴露出来的辅助导出。
|
||||
能力注册是预期的发展方向。在过渡期间,旧式钩子仍然是对外部插件最安全、最不易破坏的路径。已导出的辅助子路径并不都同样稳定——应优先使用范围收窄、且有文档说明的契约,而不是偶然暴露出来的辅助导出。
|
||||
|
||||
### 插件形态
|
||||
|
||||
OpenClaw 会根据每个已加载插件的实际注册行为(而不只是静态元数据)将其分类为一种形态:
|
||||
OpenClaw 会根据每个已加载插件的实际注册行为(而不只是静态元数据)将其归类为某种形态:
|
||||
|
||||
- **plain-capability**:恰好注册一种能力类型(例如仅提供商插件 `mistral`)。
|
||||
- **hybrid-capability**:注册多种能力类型(例如 `openai` 同时拥有文本推理、语音、媒体理解和图像生成)。
|
||||
- **hook-only**:只注册钩子(类型化或自定义),不注册能力、工具、命令或服务。
|
||||
- **non-capability**:注册工具、命令、服务或路由,但不注册能力。
|
||||
<AccordionGroup>
|
||||
<Accordion title="plain-capability">
|
||||
只注册一种能力类型(例如像 `mistral` 这样的仅提供商插件)。
|
||||
</Accordion>
|
||||
<Accordion title="hybrid-capability">
|
||||
注册多种能力类型(例如 `openai` 同时拥有文本推理、语音、媒体理解和图像生成)。
|
||||
</Accordion>
|
||||
<Accordion title="hook-only">
|
||||
只注册钩子(类型化或自定义),不注册任何能力、工具、命令或服务。
|
||||
</Accordion>
|
||||
<Accordion title="non-capability">
|
||||
注册工具、命令、服务或路由,但不注册能力。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
使用 `openclaw plugins inspect <id>` 可查看插件的形态和能力拆分。详情请参见 [CLI 参考](/zh-CN/cli/plugins#inspect)。
|
||||
使用 `openclaw plugins inspect <id>` 可以查看插件的形态和能力拆分。详情请参见 [CLI 参考](/zh-CN/cli/plugins#inspect)。
|
||||
|
||||
### Legacy hooks
|
||||
### 旧式钩子
|
||||
|
||||
`before_agent_start` 钩子仍然作为仅 hook 插件的兼容路径而受到支持。现实中的 legacy 插件仍然依赖它。
|
||||
`before_agent_start` 钩子仍然作为纯钩子插件的兼容路径被支持。现实中的旧插件仍然依赖它。
|
||||
|
||||
方向如下:
|
||||
|
||||
- 保持其可用
|
||||
- 将其文档标注为 legacy
|
||||
- 对于模型 / 提供商覆盖工作,优先使用 `before_model_resolve`
|
||||
- 对于提示词变更工作,优先使用 `before_prompt_build`
|
||||
- 仅在真实使用量下降且夹具覆盖证明迁移安全后再移除
|
||||
- 在文档中标记为旧式
|
||||
- 涉及模型 / 提供商覆盖工作时,优先使用 `before_model_resolve`
|
||||
- 涉及提示词变更工作时,优先使用 `before_prompt_build`
|
||||
- 仅在真实使用下降,且 fixture 覆盖证明迁移安全之后,才移除
|
||||
|
||||
### 兼容性信号
|
||||
|
||||
@ -99,71 +111,78 @@ OpenClaw 会根据每个已加载插件的实际注册行为(而不只是静
|
||||
|
||||
| 信号 | 含义 |
|
||||
| -------------------------- | ------------------------------------------------------------ |
|
||||
| **config valid** | 配置解析正常,且插件可被解析 |
|
||||
| **compatibility advisory** | 插件使用受支持但较旧的模式(例如 `hook-only`) |
|
||||
| **legacy warning** | 插件使用 `before_agent_start`,该接口已弃用 |
|
||||
| **hard error** | 配置无效或插件加载失败 |
|
||||
| **config valid** | 配置解析正常,插件可解析 |
|
||||
| **compatibility advisory** | 插件使用了受支持但较旧的模式(例如 `hook-only`) |
|
||||
| **legacy warning** | 插件使用了 `before_agent_start`,该功能已弃用 |
|
||||
| **hard error** | 配置无效,或插件加载失败 |
|
||||
|
||||
当前,`hook-only` 和 `before_agent_start` 都不会让你的插件损坏:`hook-only` 只是提示性信息,而 `before_agent_start` 只会触发警告。这些信号也会出现在 `openclaw status --all` 和 `openclaw plugins doctor` 中。
|
||||
如今,`hook-only` 和 `before_agent_start` 都不会破坏你的插件:`hook-only` 只是提示信息,而 `before_agent_start` 只会触发警告。这些信号也会出现在 `openclaw status --all` 和 `openclaw plugins doctor` 中。
|
||||
|
||||
## 架构概览
|
||||
|
||||
OpenClaw 的插件系统有四层:
|
||||
|
||||
1. **清单文件 + 设备发现**
|
||||
OpenClaw 会从已配置路径、工作区根目录、全局插件根目录和内置插件中查找候选插件。设备发现会先读取原生 `openclaw.plugin.json` 清单文件以及受支持的 bundle 清单文件。
|
||||
2. **启用 + 验证**
|
||||
核心决定某个已发现的插件是启用、禁用、阻止,还是被选入诸如 memory 之类的独占插槽。
|
||||
3. **运行时加载**
|
||||
原生 OpenClaw 插件通过 jiti 在进程内加载,并将能力注册到中央注册表中。兼容的 bundle 会在不导入运行时代码的情况下被规范化为注册表记录。
|
||||
4. **表面消费**
|
||||
OpenClaw 的其余部分会读取注册表,以公开工具、渠道、提供商设置、钩子、HTTP 路由、CLI 命令和服务。
|
||||
<Steps>
|
||||
<Step title="Manifest + 设备发现">
|
||||
OpenClaw 会从已配置路径、工作区根目录、全局插件根目录以及内置插件中查找候选插件。设备发现会优先读取原生 `openclaw.plugin.json` manifest 以及受支持的 bundle manifest。
|
||||
</Step>
|
||||
<Step title="启用 + 验证">
|
||||
核心决定某个已发现插件是启用、禁用、阻止,还是被选中用于某个独占插槽,例如 memory。
|
||||
</Step>
|
||||
<Step title="运行时加载">
|
||||
原生 OpenClaw 插件会通过 jiti 在进程内加载,并将能力注册到中央注册表中。兼容的 bundle 会被标准化为注册表记录,而无需导入运行时代码。
|
||||
</Step>
|
||||
<Step title="表面消费">
|
||||
OpenClaw 的其余部分会读取注册表,以暴露工具、渠道、提供商设置、钩子、HTTP 路由、CLI 命令和服务。
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
对于插件 CLI 而言,根命令发现会拆分为两个阶段:
|
||||
就插件 CLI 而言,根命令发现分为两个阶段:
|
||||
|
||||
- 解析时元数据来自 `registerCli(..., { descriptors: [...] })`
|
||||
- 真正的插件 CLI 模块可以保持惰性,并在首次调用时再注册
|
||||
- 真正的插件 CLI 模块可以保持懒加载,并在第一次调用时注册
|
||||
|
||||
这样既能让插件自有的 CLI 代码保留在插件内部,又能让 OpenClaw 在解析前预留根命令名称。
|
||||
|
||||
重要的设计边界是:
|
||||
|
||||
- 清单文件 / 配置验证应当基于**清单文件 / schema 元数据**完成,而无需执行插件代码
|
||||
- 原生能力发现可以加载受信任的插件入口代码,以构建一个非激活的注册表快照
|
||||
- 原生运行时行为来自插件模块的 `register(api)` 路径,其中 `api.registrationMode === "full"`
|
||||
- manifest / 配置验证应仅根据 **manifest / schema 元数据** 即可完成,而无需执行插件代码
|
||||
- 原生能力发现可以加载受信任的插件入口代码,以构建一个不激活的注册表快照
|
||||
- 原生运行时行为来自插件模块的 `register(api)` 路径,并带有 `api.registrationMode === "full"`
|
||||
|
||||
这种拆分使 OpenClaw 能够在完整运行时激活之前,先验证配置、解释缺失 / 被禁用的插件,并构建 UI / schema 提示。
|
||||
这种拆分让 OpenClaw 能够在完整运行时尚未激活前,验证配置、解释缺失 / 禁用的插件,并构建 UI / schema 提示。
|
||||
|
||||
### 激活规划
|
||||
|
||||
激活规划是控制平面的一部分。调用方可以在加载更广泛的运行时注册表之前,先询问哪些插件与某个具体命令、提供商、渠道、路由、Agent harness 或能力相关。
|
||||
激活规划是控制平面的一部分。调用方可以在加载更广泛的运行时注册表之前,先询问哪些插件与某个具体命令、提供商、渠道、路由、智能体 harness 或能力相关。
|
||||
|
||||
规划器会保持当前清单文件行为的兼容性:
|
||||
规划器会保持当前 manifest 行为兼容:
|
||||
|
||||
- `activation.*` 字段是显式的规划器提示
|
||||
- `providers`、`channels`、`commandAliases`、`setup.providers`、`contracts.tools` 和 hooks 仍然是清单文件归属的回退来源
|
||||
- 仅 id 的规划器 API 仍然对现有调用方可用
|
||||
- 规划 API 会报告原因标签,以便诊断区分显式提示与归属回退
|
||||
- `providers`、`channels`、`commandAliases`、`setup.providers`、`contracts.tools` 和钩子仍然保留为 manifest 归属回退
|
||||
- 仅返回 id 的规划器 API 仍然可供现有调用方使用
|
||||
- plan API 会报告原因标签,以便诊断信息区分显式提示与归属回退
|
||||
|
||||
不要把 `activation` 视为生命周期钩子,也不要把它当作 `register(...)` 的替代品。它是用于缩小加载范围的元数据。当归属字段已经能描述关系时,应优先使用归属字段;只有在需要额外规划提示时才使用 `activation`。
|
||||
<Warning>
|
||||
不要把 `activation` 当作生命周期钩子,或当作 `register(...)` 的替代品。它只是用于缩小加载范围的元数据。当归属字段已经能够描述该关系时,应优先使用归属字段;只有在需要额外规划器提示时才使用 `activation`。
|
||||
</Warning>
|
||||
|
||||
### 渠道插件与共享 message 工具
|
||||
### 渠道插件和共享 message 工具
|
||||
|
||||
对于常规聊天操作,渠道插件不需要单独注册发送 / 编辑 / 响应工具。OpenClaw 在核心中保留了一个共享的 `message` 工具,而渠道插件负责其背后的渠道特定发现与执行。
|
||||
对于普通聊天动作,渠道插件不需要单独注册发送 / 编辑 / 反应工具。OpenClaw 在核心中保留了一个共享的 `message` 工具,而渠道插件负责其背后的渠道特定发现与执行。
|
||||
|
||||
当前边界如下:
|
||||
|
||||
- 核心拥有共享 `message` 工具宿主、提示词接线、会话 / 线程记账以及执行分发
|
||||
- 渠道插件拥有作用域化的动作发现、能力发现以及任何渠道特定的 schema 片段
|
||||
- 核心拥有共享 `message` 工具宿主、提示词接线、会话 / 线程簿记以及执行分发
|
||||
- 渠道插件拥有带作用域的动作发现、能力发现以及任何渠道特定的 schema 片段
|
||||
- 渠道插件拥有提供商特定的会话对话语法,例如对话 id 如何编码线程 id,或如何从父对话继承
|
||||
- 渠道插件通过其动作适配器执行最终动作
|
||||
|
||||
对于渠道插件,SDK 接口是 `ChannelMessageActionAdapter.describeMessageTool(...)`。这个统一的发现调用允许插件将可见动作、能力以及 schema 贡献一起返回,从而避免这些部分彼此漂移。
|
||||
对于渠道插件,SDK 表面是 `ChannelMessageActionAdapter.describeMessageTool(...)`。这种统一的发现调用让插件可以把可见动作、能力和 schema 贡献一起返回,从而避免这些部分彼此漂移。
|
||||
|
||||
当某个渠道特定的消息工具参数携带媒体源(例如本地路径或远程媒体 URL)时,插件还应从 `describeMessageTool(...)` 返回 `mediaSourceParams`。核心会使用这份显式列表来应用沙箱路径规范化和出站媒体访问提示,而无需硬编码插件自有参数名。
|
||||
这里应优先使用按动作划分的映射,而不是整个渠道共用的扁平列表,这样仅配置文件相关的媒体参数就不会在 `send` 等无关动作上被规范化。
|
||||
当某个渠道特定的 message-tool 参数携带媒体源(例如本地路径或远程媒体 URL)时,插件还应从 `describeMessageTool(...)` 返回 `mediaSourceParams`。核心会使用这个显式列表来应用沙箱路径规范化以及出站媒体访问提示,而不是对插件自有参数名进行硬编码。这里应优先使用按动作划分的映射,而不是整个渠道范围的扁平列表,这样某个仅用于 profile 的媒体参数就不会在 `send` 这类无关动作上被规范化。
|
||||
|
||||
核心会将运行时作用域传入这一步发现过程。重要字段包括:
|
||||
核心会将运行时作用域传入该发现步骤。重要字段包括:
|
||||
|
||||
- `accountId`
|
||||
- `currentChannelId`
|
||||
@ -174,80 +193,104 @@ OpenClaw 的插件系统有四层:
|
||||
- `agentId`
|
||||
- 受信任的入站 `requesterSenderId`
|
||||
|
||||
这对于上下文敏感的插件很重要。渠道可以根据当前账户、当前房间 / 线程 / 消息,或受信任的请求者身份,隐藏或暴露消息动作,而无需在核心 `message` 工具中硬编码渠道特定分支。
|
||||
这对于依赖上下文的插件很重要。渠道可以根据当前活跃账号、当前房间 / 线程 / 消息,或受信任的请求者身份,隐藏或暴露消息动作,而无需在核心 `message` 工具中硬编码渠道特定分支。
|
||||
|
||||
这也是为什么嵌入式 runner 路由变更仍然属于插件工作:runner 负责将当前聊天 / 会话身份转发到插件发现边界中,从而让共享 `message` 工具在当前轮次中暴露正确的、由渠道拥有的表面。
|
||||
这也是为什么嵌入式运行器路由变更仍然属于插件工作:运行器负责将当前聊天 / 会话身份转发到插件发现边界,从而让共享 `message` 工具为当前轮次暴露正确的渠道自有表面。
|
||||
|
||||
对于渠道自有的执行辅助工具,内置插件应将执行运行时保留在其各自的扩展模块内部。核心不再拥有位于 `src/agents/tools` 下的 Discord、Slack、Telegram 或 WhatsApp 消息动作运行时。我们不会发布独立的 `plugin-sdk/*-action-runtime` 子路径,内置插件应直接从其扩展自有模块导入本地运行时代码。
|
||||
对于渠道自有的执行辅助工具,内置插件应将执行运行时保留在各自的扩展模块内部。核心不再拥有位于 `src/agents/tools` 下的 Discord、Slack、Telegram 或 WhatsApp 消息动作运行时。我们不会发布单独的 `plugin-sdk/*-action-runtime` 子路径,内置插件应直接从各自扩展自有模块导入本地运行时代码。
|
||||
|
||||
同样的边界也适用于一般意义上按提供商命名的 SDK 接缝:核心不应导入面向 Slack、Discord、Signal、WhatsApp 或类似扩展的渠道特定便捷 barrel。如果核心需要某种行为,要么消费内置插件自己的 `api.ts` / `runtime-api.ts` barrel,要么将这项需求提升为共享 SDK 中范围明确的通用能力。
|
||||
同样的边界原则也适用于一般性的、以提供商命名的 SDK 接缝:核心不应导入 Slack、Discord、Signal、WhatsApp 或类似扩展的渠道专用便捷 barrel。如果核心需要某种行为,要么使用内置插件自己的 `api.ts` / `runtime-api.ts` barrel,要么将该需求提升为共享 SDK 中一个范围收窄的通用能力。
|
||||
|
||||
对于投票,具体有两条执行路径:
|
||||
|
||||
- `outbound.sendPoll` 是适用于符合通用投票模型的渠道的共享基线
|
||||
- `actions.handleAction("poll")` 是处理渠道特定投票语义或额外投票参数的首选路径
|
||||
|
||||
现在,核心会在插件投票分发拒绝该动作之后,才延迟执行共享投票解析,因此由插件拥有的投票处理器可以接受渠道特定的投票字段,而不会先被通用投票解析器拦住。
|
||||
现在,核心会在插件投票分发拒绝该动作之后,才延后执行共享投票解析,因此插件自有的投票处理器可以接受渠道特定的投票字段,而不会先被通用投票解析器拦住。
|
||||
|
||||
完整启动顺序请参见 [插件架构内部机制](/zh-CN/plugins/architecture-internals)。
|
||||
|
||||
## 能力归属模型
|
||||
|
||||
OpenClaw 将原生插件视为某个**公司**或某个**功能**的归属边界,而不是一堆互不相关集成的杂物袋。
|
||||
OpenClaw 将一个原生插件视为某个**公司**或某项**功能**的归属边界,而不是一堆彼此无关集成的杂物袋。
|
||||
|
||||
这意味着:
|
||||
|
||||
- 公司插件通常应拥有该公司面向 OpenClaw 的所有表面
|
||||
- 功能插件通常应拥有它所引入的完整功能表面
|
||||
- 渠道应消费共享的核心能力,而不是临时重新实现提供商行为
|
||||
- 一个公司插件通常应拥有该公司的所有 OpenClaw 对外表面
|
||||
- 一个功能插件通常应拥有它所引入的完整功能表面
|
||||
- 渠道应消费共享的核心能力,而不是临时性地重复实现提供商行为
|
||||
|
||||
<Accordion title="内置插件中的归属模式示例">
|
||||
- **厂商多能力**:`openai` 拥有文本推理、语音、实时语音、媒体理解和图像生成。`google` 拥有文本推理,以及媒体理解、图像生成和 Web 搜索。`qwen` 拥有文本推理,以及媒体理解和视频生成。
|
||||
- **厂商单能力**:`elevenlabs` 和 `microsoft` 拥有语音;`firecrawl` 拥有 Web 抓取;`minimax` / `mistral` / `moonshot` / `zai` 拥有媒体理解后端。
|
||||
- **功能插件**:`voice-call` 拥有通话传输、工具、CLI、路由和 Twilio 媒体流桥接,但它消费共享的语音、实时转录和实时语音能力,而不是直接导入厂商插件。
|
||||
</Accordion>
|
||||
<AccordionGroup>
|
||||
<Accordion title="Vendor multi-capability">
|
||||
`openai` 拥有文本推理、语音、实时语音、媒体理解和图像生成。`google` 拥有文本推理,以及媒体理解、图像生成和 Web 搜索。`qwen` 拥有文本推理,以及媒体理解和视频生成。
|
||||
</Accordion>
|
||||
<Accordion title="Vendor single-capability">
|
||||
`elevenlabs` 和 `microsoft` 拥有语音;`firecrawl` 拥有 Web 抓取;`minimax` / `mistral` / `moonshot` / `zai` 拥有媒体理解后端。
|
||||
</Accordion>
|
||||
<Accordion title="Feature plugin">
|
||||
`voice-call` 拥有呼叫传输、工具、CLI、路由和 Twilio 媒体流桥接,但它会消费共享的语音、实时转写和实时语音能力,而不是直接导入厂商插件。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
预期的最终状态是:
|
||||
|
||||
- OpenAI 位于一个插件中,即使它横跨文本模型、语音、图像以及未来的视频
|
||||
- 其他厂商也可以对自己的表面区域采用同样方式
|
||||
- 渠道不关心哪个厂商插件拥有提供商;它们消费的是由核心暴露的共享能力契约
|
||||
- OpenAI 即使横跨文本模型、语音、图像以及未来的视频,也仍然驻留在一个插件中
|
||||
- 其他厂商也可以对自己的表面区域采取同样做法
|
||||
- 渠道并不关心是哪一个厂商插件拥有该提供商;它们消费的是核心暴露出的共享能力契约
|
||||
|
||||
这是关键区别:
|
||||
这里的关键区别是:
|
||||
|
||||
- **plugin** = 归属边界
|
||||
- **capability** = 多个插件都可实现或消费的核心契约
|
||||
- **capability** = 可由多个插件实现或消费的核心契约
|
||||
|
||||
因此,如果 OpenClaw 新增一个诸如视频这样的领域,第一个问题不应是“哪个提供商应该硬编码视频处理?”第一个问题应是“核心的视频能力契约是什么?”一旦这个契约存在,厂商插件就可以针对它进行注册,而渠道 / 功能插件也可以消费它。
|
||||
因此,如果 OpenClaw 新增了一个像视频这样的领域,第一个问题不应该是“哪个提供商应该硬编码视频处理?”第一个问题应该是“核心的视频能力契约是什么?”一旦这个契约存在,厂商插件就可以针对它注册,而渠道 / 功能插件也可以消费它。
|
||||
|
||||
如果该能力尚不存在,通常正确的做法是:
|
||||
|
||||
1. 在核心中定义缺失的能力
|
||||
2. 通过插件 API / 运行时以类型化方式将其暴露出来
|
||||
3. 让渠道 / 功能围绕该能力进行接线
|
||||
4. 让厂商插件注册实现
|
||||
<Steps>
|
||||
<Step title="定义能力">
|
||||
在核心中定义缺失的能力。
|
||||
</Step>
|
||||
<Step title="通过 SDK 暴露">
|
||||
以类型化方式通过插件 API / 运行时将其暴露出来。
|
||||
</Step>
|
||||
<Step title="接线消费者">
|
||||
将渠道 / 功能接入该能力。
|
||||
</Step>
|
||||
<Step title="厂商实现">
|
||||
让厂商插件注册其实现。
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
这样既能保持归属明确,也能避免核心行为依赖某个单一厂商或某条一次性的插件特定代码路径。
|
||||
这样既能保持归属清晰,又能避免核心行为依赖于单一厂商或某条一次性的插件专用代码路径。
|
||||
|
||||
### 能力分层
|
||||
|
||||
在判断代码应放在哪里时,请使用以下心智模型:
|
||||
当你决定代码应该放在哪里时,请使用这个思维模型:
|
||||
|
||||
- **核心能力层**:共享编排、策略、回退、配置合并规则、交付语义和类型化契约
|
||||
- **厂商插件层**:厂商特定 API、认证、模型目录、语音合成、图像生成、未来的视频后端、用量端点
|
||||
- **渠道 / 功能插件层**:Slack / Discord / voice-call / 等集成,它们消费核心能力并将其呈现在某个表面上
|
||||
<Tabs>
|
||||
<Tab title="核心能力层">
|
||||
共享的编排、策略、回退、配置合并规则、投递语义和类型化契约。
|
||||
</Tab>
|
||||
<Tab title="厂商插件层">
|
||||
厂商特定 API、认证、模型目录、语音合成、图像生成、未来的视频后端、用量端点。
|
||||
</Tab>
|
||||
<Tab title="渠道/功能插件层">
|
||||
Slack / Discord / voice-call / 等集成,它们消费核心能力并在某个表面上呈现出来。
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
例如,TTS 遵循这种形态:
|
||||
例如,TTS 遵循这种结构:
|
||||
|
||||
- 核心拥有回复时 TTS 策略、回退顺序、偏好和渠道交付
|
||||
- `openai`、`elevenlabs` 和 `microsoft` 拥有合成实现
|
||||
- 核心拥有回复时 TTS 策略、回退顺序、偏好设置和渠道投递
|
||||
- `openai`、`elevenlabs` 和 `microsoft` 拥有语音合成实现
|
||||
- `voice-call` 消费电话 TTS 运行时辅助工具
|
||||
|
||||
对于未来的能力,也应优先采用相同模式。
|
||||
对于未来能力,也应优先采用同样的模式。
|
||||
|
||||
### 多能力公司插件示例
|
||||
|
||||
一个公司插件从外部看应该是连贯的。如果 OpenClaw 对模型、语音、实时转录、实时语音、媒体理解、图像生成、视频生成、Web 抓取和 Web 搜索都有共享契约,那么某个厂商可以在一个地方拥有其所有表面:
|
||||
从外部看,一个公司插件应当具有一致性。如果 OpenClaw 拥有针对模型、语音、实时转写、实时语音、媒体理解、图像生成、视频生成、Web 抓取和 Web 搜索的共享契约,那么一个厂商就可以在一个地方拥有其所有表面:
|
||||
|
||||
```ts
|
||||
import type { OpenClawPluginDefinition } from "openclaw/plugin-sdk/plugin-entry";
|
||||
@ -301,7 +344,7 @@ const plugin: OpenClawPluginDefinition = {
|
||||
export default plugin;
|
||||
```
|
||||
|
||||
重要的不是确切的辅助工具名称,而是这种形态:
|
||||
重要的不是确切的辅助函数名,而是这种结构:
|
||||
|
||||
- 一个插件拥有厂商表面
|
||||
- 核心仍然拥有能力契约
|
||||
@ -310,100 +353,117 @@ export default plugin;
|
||||
|
||||
### 能力示例:视频理解
|
||||
|
||||
OpenClaw 已经将图像 / 音频 / 视频理解视为一种共享能力。同样的归属模型也适用于这里:
|
||||
OpenClaw 已经将图像 / 音频 / 视频理解视为一个共享能力。这里同样适用相同的归属模型:
|
||||
|
||||
1. 核心定义媒体理解契约
|
||||
2. 厂商插件按需注册 `describeImage`、`transcribeAudio` 和 `describeVideo`
|
||||
3. 渠道和功能插件消费共享的核心行为,而不是直接接到厂商代码上
|
||||
<Steps>
|
||||
<Step title="核心定义契约">
|
||||
核心定义媒体理解契约。
|
||||
</Step>
|
||||
<Step title="厂商插件注册">
|
||||
厂商插件按需注册 `describeImage`、`transcribeAudio` 和 `describeVideo`。
|
||||
</Step>
|
||||
<Step title="消费者使用共享行为">
|
||||
渠道和功能插件消费共享的核心行为,而不是直接接线到厂商代码。
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
这样可以避免把某个提供商对视频的假设烘焙进核心。插件拥有厂商表面;核心拥有能力契约和回退行为。
|
||||
这避免了把某个提供商对视频的假设烘焙进核心。插件拥有厂商表面;核心拥有能力契约和回退行为。
|
||||
|
||||
视频生成已经采用了同样的顺序:核心拥有类型化的能力契约和运行时辅助工具,而厂商插件则针对它注册 `api.registerVideoGenerationProvider(...)` 实现。
|
||||
视频生成已经采用了同样的顺序:核心拥有类型化能力契约和运行时辅助工具,而厂商插件则针对其注册 `api.registerVideoGenerationProvider(...)` 实现。
|
||||
|
||||
需要具体的上线检查清单?请参见 [能力扩展手册](/zh-CN/plugins/architecture)。
|
||||
需要一个具体的发布清单吗?请参见 [能力扩展手册](/zh-CN/plugins/architecture)。
|
||||
|
||||
## 契约与强制执行
|
||||
## 契约与约束执行
|
||||
|
||||
插件 API 表面有意通过 `OpenClawPluginApi` 进行类型化并集中管理。该契约定义了受支持的注册点,以及插件可以依赖的运行时辅助工具。
|
||||
插件 API 表面有意在 `OpenClawPluginApi` 中集中并做了类型化。该契约定义了受支持的注册点,以及插件可以依赖的运行时辅助工具。
|
||||
|
||||
这很重要,因为:
|
||||
|
||||
- 插件作者可以获得一个稳定的内部标准
|
||||
- 核心可以拒绝重复归属,例如两个插件注册同一个 provider id
|
||||
- 启动阶段可以为格式错误的注册提供可执行的诊断信息
|
||||
- 契约测试可以强制约束内置插件的归属并防止静默漂移
|
||||
- 插件作者可以得到一套稳定的内部标准
|
||||
- 核心可以拒绝重复归属,例如两个插件注册相同的提供商 id
|
||||
- 启动过程可以为格式错误的注册暴露可执行的诊断信息
|
||||
- 契约测试可以强制执行内置插件的归属,并防止静默漂移
|
||||
|
||||
这里有两层强制执行:
|
||||
这里有两层约束执行:
|
||||
|
||||
1. **运行时注册强制执行**
|
||||
插件注册表会在插件加载时验证注册内容。例如:重复的 provider id、重复的语音提供商 id,以及格式错误的注册,都会产生插件诊断,而不是导致未定义行为。
|
||||
2. **契约测试**
|
||||
在测试运行期间,内置插件会被捕获到契约注册表中,以便 OpenClaw 可以显式断言归属。目前这用于模型提供商、语音提供商、Web 搜索提供商以及内置注册归属。
|
||||
<AccordionGroup>
|
||||
<Accordion title="运行时注册约束执行">
|
||||
插件注册表会在插件加载时验证注册。例如:重复的提供商 id、重复的语音提供商 id,以及格式错误的注册,都会产生插件诊断信息,而不是导致未定义行为。
|
||||
</Accordion>
|
||||
<Accordion title="契约测试">
|
||||
在测试运行期间,内置插件会被捕获到契约注册表中,这样 OpenClaw 就可以显式断言归属。当前这用于模型提供商、语音提供商、Web 搜索提供商和内置注册归属。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
实际效果是,OpenClaw 可以预先知道哪个插件拥有哪个表面。这让核心和渠道能够无缝组合,因为归属是被声明、被类型化并且可测试的,而不是隐式的。
|
||||
实际效果是,OpenClaw 可以预先知道哪个插件拥有哪个表面。这使得核心和渠道能够无缝组合,因为归属是被声明、被类型化且可测试的,而不是隐式的。
|
||||
|
||||
### 什么应该属于契约
|
||||
|
||||
良好的插件契约应当是:
|
||||
<Tabs>
|
||||
<Tab title="好契约">
|
||||
- 类型化
|
||||
- 小而精
|
||||
- 能力特定
|
||||
- 由核心拥有
|
||||
- 可被多个插件复用
|
||||
- 可在不了解厂商细节的情况下被渠道 / 功能消费
|
||||
</Tab>
|
||||
<Tab title="坏契约">
|
||||
- 隐藏在核心中的厂商特定策略
|
||||
- 绕过注册表的一次性插件逃生口
|
||||
- 直接深入调用厂商实现的渠道代码
|
||||
- 不属于 `OpenClawPluginApi` 或 `api.runtime` 的临时运行时对象
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
- 类型化的
|
||||
- 小而精的
|
||||
- 特定于能力的
|
||||
- 由核心拥有
|
||||
- 可被多个插件复用
|
||||
- 可被渠道 / 功能消费,而无需厂商知识
|
||||
|
||||
不良的插件契约则是:
|
||||
|
||||
- 隐藏在核心中的厂商特定策略
|
||||
- 绕过注册表的一次性插件逃生口
|
||||
- 直接深入某个厂商实现的渠道代码
|
||||
- 不属于 `OpenClawPluginApi` 或 `api.runtime` 的临时运行时对象
|
||||
|
||||
如果拿不准,请提升抽象层级:先定义能力,再让插件接入它。
|
||||
拿不准时,就提升抽象层级:先定义能力,再让插件接入它。
|
||||
|
||||
## 执行模型
|
||||
|
||||
原生 OpenClaw 插件与 Gateway 网关**在同一进程内**运行。它们没有经过沙箱隔离。一个已加载的原生插件与核心代码处于同样的进程级信任边界内。
|
||||
原生 OpenClaw 插件与 Gateway 网关**在同一进程中**运行。它们没有沙箱隔离。一个已加载的原生插件与核心代码具有相同的进程级信任边界。
|
||||
|
||||
其含义是:
|
||||
<Warning>
|
||||
影响包括:
|
||||
|
||||
- 原生插件可以注册工具、网络处理器、钩子和服务
|
||||
- 原生插件中的 bug 可能导致 gateway 崩溃或不稳定
|
||||
- 恶意原生插件等同于在 OpenClaw 进程内执行任意代码
|
||||
- 原生插件的 bug 可能导致 Gateway 网关崩溃或不稳定
|
||||
- 恶意原生插件等同于在 OpenClaw 进程内部执行任意代码
|
||||
</Warning>
|
||||
|
||||
兼容 bundle 默认更安全,因为 OpenClaw 当前将它们视为元数据 / 内容包。在当前版本中,这主要意味着内置 Skills。
|
||||
兼容的 bundle 默认情况下更安全,因为 OpenClaw 当前将其视为元数据 / 内容包。在当前版本中,这主要指内置 Skills。
|
||||
|
||||
对于非内置插件,请使用 allowlist 和显式的安装 / 加载路径。应将工作区插件视为开发期代码,而不是生产默认值。
|
||||
对于非内置插件,请使用允许列表和显式安装 / 加载路径。应将工作区插件视为开发时代码,而不是生产默认值。
|
||||
|
||||
对于内置工作区包名,请让插件 id 锚定在 npm 名称中:默认使用 `@openclaw/<id>`,或者在包有意暴露更窄的插件角色时,使用经批准的类型化后缀,例如 `-provider`、`-plugin`、`-speech`、`-sandbox` 或 `-media-understanding`。
|
||||
对于内置工作区 package 名称,请让插件 id 锚定在 npm 名称中:默认使用 `@openclaw/<id>`,或者在该 package 有意暴露更窄的插件角色时,使用经批准的类型化后缀,例如 `-provider`、`-plugin`、`-speech`、`-sandbox` 或 `-media-understanding`。
|
||||
|
||||
重要信任说明:
|
||||
<Note>
|
||||
**信任说明:**
|
||||
|
||||
- `plugins.allow` 信任的是**插件 id**,而不是来源出处。
|
||||
- 与内置插件具有相同 id 的工作区插件,在该工作区插件被启用 / 加入 allowlist 时,会有意遮蔽内置副本。
|
||||
- 这很正常,也很有用,适用于本地开发、补丁测试和热修复。
|
||||
- 内置插件信任是根据源码快照解析的 —— 即加载时磁盘上的清单文件和代码 —— 而不是基于安装元数据。损坏或被替换的安装记录不能在实际源码声明之外,悄悄扩大某个内置插件的信任表面。
|
||||
- 当启用 / 加入允许列表的工作区插件与某个内置插件具有相同 id 时,它会有意遮蔽该内置副本。
|
||||
- 这在本地开发、补丁测试和热修复中是正常且有用的。
|
||||
- 内置插件信任是根据源快照解析的——也就是加载时磁盘上的 manifest 和代码——而不是根据安装元数据。一个被破坏或被替换的安装记录,不能在实际源代码未声明的情况下,静默扩大某个内置插件的信任表面。
|
||||
</Note>
|
||||
|
||||
## 导出边界
|
||||
|
||||
OpenClaw 导出的是能力,而不是实现层面的便捷工具。
|
||||
|
||||
请保持能力注册为公开接口,并收缩那些不属于契约的辅助导出:
|
||||
保持能力注册为公共接口。收紧非契约辅助导出:
|
||||
|
||||
- 内置插件特定的辅助子路径
|
||||
- 不打算作为公开 API 的运行时接线子路径
|
||||
- 内置插件专用的辅助子路径
|
||||
- 不打算作为公共 API 的运行时管线子路径
|
||||
- 厂商特定的便捷辅助工具
|
||||
- 属于实现细节的 setup / onboarding 辅助工具
|
||||
- 属于实现细节的设置 / 新手引导辅助工具
|
||||
|
||||
某些内置插件辅助子路径仍然保留在生成的 SDK 导出映射中,以兼容现有用法并便于维护内置插件。当前示例包括 `plugin-sdk/feishu`、`plugin-sdk/feishu-setup`、`plugin-sdk/zalo`、`plugin-sdk/zalo-setup` 以及若干 `plugin-sdk/matrix*` 接缝。应将这些视为保留的实现细节导出,而不是新第三方插件推荐采用的 SDK 模式。
|
||||
为了兼容性和内置插件维护,一些内置插件辅助子路径仍然保留在生成的 SDK 导出映射中。当前示例包括 `plugin-sdk/feishu`、`plugin-sdk/feishu-setup`、`plugin-sdk/zalo`、`plugin-sdk/zalo-setup` 以及若干 `plugin-sdk/matrix*` 接缝。应将这些视为保留的实现细节导出,而不是为新的第三方插件推荐的 SDK 模式。
|
||||
|
||||
## 内部机制与参考
|
||||
|
||||
有关加载管线、注册表模型、提供商运行时钩子、Gateway 网关 HTTP 路由、message 工具 schema、渠道目标解析、提供商目录、上下文引擎插件,以及新增能力的指南,请参见 [插件架构内部机制](/zh-CN/plugins/architecture-internals)。
|
||||
关于加载管线、注册表模型、提供商运行时钩子、Gateway 网关 HTTP 路由、消息工具 schema、渠道目标解析、提供商目录、上下文引擎插件以及添加新能力的指南,请参见 [插件架构内部机制](/zh-CN/plugins/architecture-internals)。
|
||||
|
||||
## 相关内容
|
||||
|
||||
- [构建插件](/zh-CN/plugins/building-plugins)
|
||||
- [插件 manifest](/zh-CN/plugins/manifest)
|
||||
- [插件 SDK 设置](/zh-CN/plugins/sdk-setup)
|
||||
- [插件清单文件](/zh-CN/plugins/manifest)
|
||||
|
||||
@ -1,144 +1,135 @@
|
||||
---
|
||||
read_when:
|
||||
- 你想使用内置的 Codex app-server harness。
|
||||
- 你需要 Codex harness 配置示例。
|
||||
- 你希望仅使用 Codex 的部署在失败时直接报错,而不是回退到 PI。
|
||||
summary: 通过内置的 Codex app-server harness 运行 OpenClaw 嵌入式智能体回合
|
||||
- 你想使用内置的 Codex 应用服务器 Codex harness
|
||||
- 你需要 Codex harness 配置示例
|
||||
- 你希望仅 Codex 部署在失败时直接报错,而不是回退到 PI
|
||||
summary: 通过内置的 Codex 应用服务器 Codex harness 运行 OpenClaw 嵌入式智能体回合
|
||||
title: Codex harness
|
||||
x-i18n:
|
||||
generated_at: "2026-04-26T03:53:44Z"
|
||||
generated_at: "2026-04-26T07:50:09Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: e43e9683ee0deaa9b97345a51f4a6b5848f0f3738f1ddb9519a01954c247fea5
|
||||
source_hash: bf54ee2eab64e611e50605e8fef24cc840b3246d0bddc18ae03730a05848e271
|
||||
source_path: plugins/codex-harness.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
内置的 `codex` 插件允许 OpenClaw 通过 Codex app-server 来运行嵌入式智能体回合,
|
||||
而不是使用内置的 PI harness。
|
||||
内置的 `codex` 插件让 OpenClaw 可以通过 Codex 应用服务器运行嵌入式智能体回合,而不是使用内置的 PI harness。
|
||||
|
||||
当你希望由 Codex 接管底层智能体会话时,请使用此方式:模型
|
||||
发现、原生线程恢复、原生压缩以及 app-server 执行。
|
||||
OpenClaw 仍然负责聊天渠道、会话文件、模型选择、工具、
|
||||
审批、媒体传递以及可见的转录镜像。
|
||||
当你希望由 Codex 接管底层智能体会话时,请使用它:模型发现、原生线程恢复、原生压缩以及应用服务器执行。OpenClaw 仍然负责聊天渠道、会话文件、模型选择、工具、审批、媒体传递,以及可见的转录镜像。
|
||||
|
||||
如果你正在熟悉这一部分,请先阅读
|
||||
[Agent Runtimes](/zh-CN/concepts/agent-runtimes)。简短版本如下:
|
||||
如果你正在尝试建立整体认知,请先阅读
|
||||
[Agent Runtimes](/zh-CN/concepts/agent-runtimes)。简要来说:
|
||||
`openai/gpt-5.5` 是模型引用,`codex` 是运行时,而 Telegram、
|
||||
Discord、Slack 或其他渠道仍然是通信界面。
|
||||
|
||||
## 这个插件会改变什么
|
||||
|
||||
内置的 `codex` 插件提供了几项彼此独立的能力:
|
||||
内置的 `codex` 插件提供几个彼此独立的能力:
|
||||
|
||||
| 能力 | 你的使用方式 | 它的作用 |
|
||||
| --------------------------------- | ------------------------------------------------- | --------------------------------------------------------------------------- |
|
||||
| 原生嵌入式运行时 | `embeddedHarness.runtime: "codex"` | 通过 Codex app-server 运行 OpenClaw 嵌入式智能体回合。 |
|
||||
| 原生聊天控制命令 | `/codex bind`、`/codex resume`、`/codex steer`... | 从消息对话中绑定并控制 Codex app-server 线程。 |
|
||||
| Codex app-server 提供商/目录 | `codex` 内部实现,通过 harness 暴露 | 让运行时能够发现并验证 app-server 模型。 |
|
||||
| Codex 媒体理解路径 | `codex/*` 图像模型兼容路径 | 为受支持的图像理解模型运行受限的 Codex app-server 回合。 |
|
||||
| 原生钩子转发 | 围绕 Codex 原生事件的插件钩子 | 让 OpenClaw 能够观察/阻止受支持的 Codex 原生工具/终结事件。 |
|
||||
| 能力 | 使用方式 | 作用 |
|
||||
| --------------------------------- | --------------------------------------------------- | ----------------------------------------------------------------------------- |
|
||||
| 原生嵌入式运行时 | `agentRuntime.id: "codex"` | 通过 Codex 应用服务器运行 OpenClaw 嵌入式智能体回合。 |
|
||||
| 原生聊天控制命令 | `/codex bind`、`/codex resume`、`/codex steer`、... | 从消息对话中绑定和控制 Codex 应用服务器线程。 |
|
||||
| Codex 应用服务器 provider/目录 | `codex` 内部机制,通过 harness 暴露 | 让运行时能够发现并验证应用服务器模型。 |
|
||||
| Codex 媒体理解路径 | `codex/*` 图像模型兼容路径 | 对受支持的图像理解模型运行受限的 Codex 应用服务器回合。 |
|
||||
| 原生钩子中继 | 围绕 Codex 原生事件的插件钩子 | 让 OpenClaw 可以观察/阻止受支持的 Codex 原生工具/终结事件。 |
|
||||
|
||||
启用该插件会使这些能力可用。它**不会**:
|
||||
|
||||
- 为每个 OpenAI 模型都开始使用 Codex
|
||||
- 开始对每个 OpenAI 模型都使用 Codex
|
||||
- 将 `openai-codex/*` 模型引用转换为原生运行时
|
||||
- 让 ACP/acpx 成为默认的 Codex 路径
|
||||
- 热切换已经记录了 PI 运行时的现有会话
|
||||
- 替换 OpenClaw 的渠道传递、会话文件、凭证配置文件存储或
|
||||
- 使 ACP/acpx 成为默认 Codex 路径
|
||||
- 对已经记录了 PI 运行时的现有会话进行热切换
|
||||
- 替换 OpenClaw 渠道传递、会话文件、认证配置文件存储或
|
||||
消息路由
|
||||
|
||||
同一个插件还负责原生 `/codex` 聊天控制命令界面。如果
|
||||
该插件已启用,并且用户要求从聊天中绑定、恢复、引导、停止或检查
|
||||
Codex 线程,智能体应优先使用 `/codex ...` 而不是 ACP。
|
||||
当用户明确要求 ACP/acpx 或正在测试 ACP
|
||||
Codex 适配器时,ACP 仍然是明确的回退路径。
|
||||
同一个插件还拥有原生 `/codex` 聊天控制命令界面。如果
|
||||
插件已启用,且用户要求从聊天中绑定、恢复、引导、停止或检查
|
||||
Codex 线程,智能体应优先使用 `/codex ...` 而不是 ACP。当用户明确要求 ACP/acpx 或正在测试 ACP
|
||||
Codex 适配器时,ACP 仍然是显式回退方案。
|
||||
|
||||
原生 Codex 回合会将 OpenClaw 插件钩子保留为公共兼容层。
|
||||
这些是进程内的 OpenClaw 钩子,不是 Codex `hooks.json` 命令钩子:
|
||||
原生 Codex 回合保留 OpenClaw 插件钩子作为公共兼容层。
|
||||
这些是在进程内的 OpenClaw 钩子,不是 Codex `hooks.json` 命令钩子:
|
||||
|
||||
- `before_prompt_build`
|
||||
- `before_compaction`、`after_compaction`
|
||||
- `llm_input`、`llm_output`
|
||||
- `before_tool_call`、`after_tool_call`
|
||||
- 用于镜像转录记录的 `before_message_write`
|
||||
- 通过 Codex `Stop` 转发触发的 `before_agent_finalize`
|
||||
- 通过 Codex `Stop` 中继的 `before_agent_finalize`
|
||||
- `agent_end`
|
||||
|
||||
插件还可以注册与运行时无关的工具结果中间件,以便在 OpenClaw 执行工具之后、
|
||||
并在结果返回给 Codex 之前,重写 OpenClaw 动态工具结果。这与公共
|
||||
`tool_result_persist` 插件钩子不同,后者会转换 OpenClaw 自有的转录
|
||||
插件还可以注册与运行时无关的工具结果中间件,以便在 OpenClaw 执行工具之后、将结果返回给 Codex 之前,重写 OpenClaw 动态工具结果。这与公共
|
||||
`tool_result_persist` 插件钩子是分开的,后者用于转换由 OpenClaw 拥有的转录
|
||||
工具结果写入。
|
||||
|
||||
关于插件钩子语义本身,请参阅 [Plugin hooks](/zh-CN/plugins/hooks)
|
||||
和 [Plugin guard behavior](/zh-CN/tools/plugin)。
|
||||
有关插件钩子语义本身,请参阅 [插件钩子](/zh-CN/plugins/hooks)
|
||||
和 [插件守卫行为](/zh-CN/tools/plugin)。
|
||||
|
||||
该 harness 默认关闭。新配置应保持 OpenAI 模型引用
|
||||
使用规范形式 `openai/gpt-*`,并在需要原生 app-server 执行时
|
||||
显式强制设置
|
||||
`embeddedHarness.runtime: "codex"` 或 `OPENCLAW_AGENT_RUNTIME=codex`。
|
||||
旧版 `codex/*` 模型引用仍会自动选择该 harness 以保持兼容,
|
||||
但由运行时支持的旧版提供商前缀不会作为普通模型/提供商选择项显示。
|
||||
该 harness 默认关闭。新配置应保持 OpenAI 模型引用的规范形式为 `openai/gpt-*`,并在
|
||||
需要原生应用服务器执行时,显式强制使用
|
||||
`agentRuntime.id: "codex"` 或 `OPENCLAW_AGENT_RUNTIME=codex`。
|
||||
旧版 `codex/*` 模型引用仍会自动选择
|
||||
该 harness 以保持兼容,但由运行时支持的旧版 provider 前缀不会显示为普通模型/提供商选项。
|
||||
|
||||
如果启用了 `codex` 插件,但主模型仍然是
|
||||
`openai-codex/*`,`openclaw doctor` 会发出警告,而不是更改路由。这是
|
||||
有意为之:`openai-codex/*` 仍然是 PI Codex OAuth/订阅路径,而
|
||||
原生 app-server 执行始终是一个显式运行时选择。
|
||||
有意设计的:`openai-codex/*` 仍然是 PI Codex OAuth/订阅路径,而
|
||||
原生应用服务器执行仍然是一个显式运行时选择。
|
||||
|
||||
## 路由映射
|
||||
|
||||
在更改配置前,请先使用此表:
|
||||
在修改配置前,请先使用此表:
|
||||
|
||||
| 期望行为 | 模型引用 | 运行时配置 | 插件要求 | 预期状态标签 |
|
||||
| ------------------------------------------- | -------------------------- | -------------------------------------- | --------------------------- | ---------------------------- |
|
||||
| 通过普通 OpenClaw 运行器使用 OpenAI API | `openai/gpt-*` | 省略或 `runtime: "pi"` | OpenAI provider | `Runtime: OpenClaw Pi Default` |
|
||||
| 通过 PI 使用 Codex OAuth/订阅 | `openai-codex/gpt-*` | 省略或 `runtime: "pi"` | OpenAI Codex OAuth provider | `Runtime: OpenClaw Pi Default` |
|
||||
| 原生 Codex app-server 嵌入式回合 | `openai/gpt-*` | `embeddedHarness.runtime: "codex"` | `codex` 插件 | `Runtime: OpenAI Codex` |
|
||||
| 使用保守自动模式的混合提供商 | 提供商特定引用 | `runtime: "auto", fallback: "pi"` | 可选插件运行时 | 取决于所选运行时 |
|
||||
| 显式 Codex ACP 适配器会话 | 取决于 ACP prompt/model | `sessions_spawn` with `runtime: "acp"` | 健康的 `acpx` 后端 | ACP task/session status |
|
||||
| 期望行为 | 模型引用 | 运行时配置 | 插件要求 | 预期状态标签 |
|
||||
| ------------------------------------------- | -------------------------- | -------------------------------------- | --------------------------- | ------------------------------ |
|
||||
| 通过普通 OpenClaw 运行器访问 OpenAI API | `openai/gpt-*` | 省略或 `runtime: "pi"` | OpenAI provider | `Runtime: OpenClaw Pi Default` |
|
||||
| 通过 PI 使用 Codex OAuth/订阅 | `openai-codex/gpt-*` | 省略或 `runtime: "pi"` | OpenAI Codex OAuth provider | `Runtime: OpenClaw Pi Default` |
|
||||
| 原生 Codex 应用服务器嵌入式回合 | `openai/gpt-*` | `agentRuntime.id: "codex"` | `codex` 插件 | `Runtime: OpenAI Codex` |
|
||||
| 混合提供商的保守自动模式 | provider 特定引用 | `agentRuntime.id: "auto"` | 可选插件运行时 | 取决于所选运行时 |
|
||||
| 显式 Codex ACP 适配器会话 | 取决于 ACP prompt/模型 | `sessions_spawn` 搭配 `runtime: "acp"` | 正常工作的 `acpx` 后端 | ACP task/session 状态 |
|
||||
|
||||
关键区别在于提供商与运行时:
|
||||
关键区别在于 provider 与运行时:
|
||||
|
||||
- `openai-codex/*` 回答的是“PI 应该使用哪条提供商/凭证路径?”
|
||||
- `embeddedHarness.runtime: "codex"` 回答的是“哪个循环应执行这个
|
||||
- `openai-codex/*` 回答的是“PI 应该使用哪条 provider/认证路径?”
|
||||
- `agentRuntime.id: "codex"` 回答的是“应由哪个循环执行这个
|
||||
嵌入式回合?”
|
||||
- `/codex ...` 回答的是“这个聊天应绑定或控制哪个原生 Codex 对话?”
|
||||
- `/codex ...` 回答的是“这个聊天应绑定
|
||||
或控制哪个原生 Codex 对话?”
|
||||
- ACP 回答的是“acpx 应启动哪个外部 harness 进程?”
|
||||
|
||||
## 选择正确的模型前缀
|
||||
|
||||
OpenAI 系列路由对前缀很敏感。当你想通过 PI 使用
|
||||
Codex OAuth 时,请使用 `openai-codex/*`;当你想直接使用 OpenAI API,或者
|
||||
要强制使用原生 Codex app-server harness 时,请使用 `openai/*`:
|
||||
OpenAI 系列路由按前缀区分。当你想通过 PI 使用
|
||||
Codex OAuth 时,请使用 `openai-codex/*`;当你想使用直接 OpenAI API 访问,或
|
||||
当你要强制使用原生 Codex 应用服务器 harness 时,请使用 `openai/*`:
|
||||
|
||||
| 模型引用 | 运行时路径 | 使用场景 |
|
||||
| ---------------------------------------------------- | -------------------------------------------- | ------------------------------------------------------------------------- |
|
||||
| `openai/gpt-5.4` | 通过 OpenClaw/PI 管道的 OpenAI provider | 你希望通过 `OPENAI_API_KEY` 使用当前直接 OpenAI Platform API 访问。 |
|
||||
| `openai-codex/gpt-5.5` | 通过 OpenClaw/PI 的 OpenAI Codex OAuth | 你希望使用默认 PI 运行器通过 ChatGPT/Codex 订阅凭证。 |
|
||||
| `openai/gpt-5.5` + `embeddedHarness.runtime: "codex"` | Codex app-server harness | 你希望在嵌入式智能体回合中使用原生 Codex app-server 执行。 |
|
||||
| 模型引用 | 运行时路径 | 使用场景 |
|
||||
| --------------------------------------------- | -------------------------------------------- | ------------------------------------------------------------------------- |
|
||||
| `openai/gpt-5.4` | 通过 OpenClaw/PI 管线的 OpenAI provider | 你想使用当前通过 `OPENAI_API_KEY` 提供的直接 OpenAI Platform API 访问。 |
|
||||
| `openai-codex/gpt-5.5` | 通过 OpenClaw/PI 的 OpenAI Codex OAuth | 你想通过默认 PI 运行器使用 ChatGPT/Codex 订阅认证。 |
|
||||
| `openai/gpt-5.5` + `agentRuntime.id: "codex"` | Codex 应用服务器 harness | 你希望嵌入式智能体回合使用原生 Codex 应用服务器执行。 |
|
||||
|
||||
GPT-5.5 目前在 OpenClaw 中仅支持订阅/OAuth 方式。请使用
|
||||
GPT-5.5 当前在 OpenClaw 中仅支持订阅/OAuth。请使用
|
||||
`openai-codex/gpt-5.5` 进行 PI OAuth,或使用 `openai/gpt-5.5` 搭配 Codex
|
||||
app-server harness。一旦 OpenAI 在公共 API 上启用 GPT-5.5,
|
||||
就会支持 `openai/gpt-5.5` 的直接 API 密钥访问。
|
||||
应用服务器 harness。一旦 OpenAI 在公共 API 上启用 GPT-5.5,
|
||||
`openai/gpt-5.5` 的直接 API 密钥访问也会得到支持。
|
||||
|
||||
旧版 `codex/gpt-*` 引用仍然接受,作为兼容别名。Doctor
|
||||
兼容性迁移会将旧版主运行时引用重写为规范模型
|
||||
引用,并将运行时策略单独记录;而仅用于回退的旧版引用会保持不变,
|
||||
因为运行时是为整个智能体容器配置的。
|
||||
旧版 `codex/gpt-*` 引用仍被接受为兼容别名。Doctor
|
||||
兼容迁移会将旧版主运行时引用重写为规范模型
|
||||
引用,并单独记录运行时策略,而仅用于回退的旧版引用则保持不变,因为运行时是为整个智能体容器配置的。
|
||||
新的 PI Codex OAuth 配置应使用 `openai-codex/gpt-*`;新的原生
|
||||
app-server harness 配置应使用 `openai/gpt-*`,再加上
|
||||
`embeddedHarness.runtime: "codex"`。
|
||||
应用服务器 harness 配置应使用 `openai/gpt-*` 加上
|
||||
`agentRuntime.id: "codex"`。
|
||||
|
||||
`agents.defaults.imageModel` 也遵循相同的前缀划分。当图像理解应通过 OpenAI
|
||||
Codex OAuth 提供商路径运行时,请使用
|
||||
`openai-codex/gpt-*`。当图像理解应通过受限的 Codex app-server 回合运行时,请使用
|
||||
`codex/gpt-*`。Codex app-server 模型必须
|
||||
声明支持图像输入;纯文本 Codex 模型会在媒体回合
|
||||
开始前失败。
|
||||
`agents.defaults.imageModel` 也遵循相同的前缀拆分。使用
|
||||
`openai-codex/gpt-*`,当图像理解应通过 OpenAI
|
||||
Codex OAuth provider 路径运行时。使用 `codex/gpt-*`,当图像理解应通过
|
||||
受限的 Codex 应用服务器回合运行时。Codex 应用服务器模型必须
|
||||
声明支持图像输入;纯文本 Codex 模型会在媒体回合开始前失败。
|
||||
|
||||
使用 `/status` 来确认当前会话的实际 harness。如果选择结果出乎意料,
|
||||
请为 `agents/harness` 子系统启用调试日志,
|
||||
使用 `/status` 确认当前会话的实际 harness。如果选择结果出乎意料,请为 `agents/harness` 子系统启用调试日志,
|
||||
并检查 Gateway 网关的结构化 `agent harness selected` 记录。它
|
||||
包含所选 harness id、选择原因、运行时/回退策略,以及在
|
||||
`auto` 模式下每个插件候选项的支持结果。
|
||||
@ -151,46 +142,43 @@ Codex OAuth 提供商路径运行时,请使用
|
||||
- 某个智能体的主模型是 `openai-codex/*`
|
||||
- 该智能体的实际运行时不是 `codex`
|
||||
|
||||
之所以有这个警告,是因为用户常常会以为“启用了 Codex 插件”就意味着
|
||||
“使用原生 Codex app-server 运行时”。OpenClaw 不会自动这样做。该警告表示:
|
||||
之所以存在这个警告,是因为用户经常会以为“启用了 Codex 插件”就意味着
|
||||
“使用原生 Codex 应用服务器运行时”。OpenClaw 不会自动做出这种推断。这个警告意味着:
|
||||
|
||||
- 如果你的目标是通过 PI 使用 ChatGPT/Codex OAuth,**则无需更改**。
|
||||
- 如果你的目标是原生 app-server
|
||||
执行,请将模型更改为 `openai/<model>`,并设置
|
||||
`embeddedHarness.runtime: "codex"`。
|
||||
- 现有会话在运行时更改后仍然需要 `/new` 或 `/reset`,
|
||||
- 如果你的本意是通过 PI 使用 ChatGPT/Codex OAuth,**则无需更改**。
|
||||
- 如果你的本意是使用原生应用服务器
|
||||
执行,请将模型改为 `openai/<model>`,并设置
|
||||
`agentRuntime.id: "codex"`。
|
||||
- 现有会话在运行时变更后仍然需要 `/new` 或 `/reset`,
|
||||
因为会话运行时固定是粘性的。
|
||||
|
||||
Harness 选择不是实时会话控制。当嵌入式回合运行时,
|
||||
OpenClaw 会在该会话上记录所选 harness id,并在相同会话 id 的后续回合中
|
||||
继续使用它。当你希望未来的会话使用另一个 harness 时,
|
||||
请更改 `embeddedHarness` 配置或
|
||||
`OPENCLAW_AGENT_RUNTIME`;在将现有对话从 PI 切换到 Codex 或反向切换之前,
|
||||
请使用 `/new` 或 `/reset` 开启一个新会话。
|
||||
这样可以避免将同一份转录内容通过两个不兼容的原生会话系统进行回放。
|
||||
OpenClaw 会在该会话上记录所选 harness id,并在
|
||||
同一会话 id 的后续回合中继续使用它。当你希望未来的会话使用其他 harness 时,请更改 `agentRuntime` 配置或
|
||||
`OPENCLAW_AGENT_RUNTIME`;
|
||||
在将现有对话从 PI 切换到 Codex 之前,请使用 `/new` 或 `/reset` 启动一个全新会话。
|
||||
这样可以避免将同一份转录通过两个不兼容的原生会话系统重复回放。
|
||||
|
||||
在引入 harness 固定机制之前创建的旧会话,一旦拥有转录历史,
|
||||
就会被视为固定到 PI。更改配置后,如需让该对话改用 Codex,
|
||||
请使用 `/new` 或 `/reset`。
|
||||
在引入 harness 固定机制之前创建的旧版会话,一旦拥有转录历史,就会被视为固定到 PI。更改配置后,请使用 `/new` 或 `/reset` 将该对话切换到
|
||||
Codex。
|
||||
|
||||
`/status` 会显示实际模型运行时。默认的 PI harness 会显示为
|
||||
`Runtime: OpenClaw Pi Default`,而 Codex app-server harness 会显示为
|
||||
`/status` 会显示实际模型运行时。默认 PI harness 显示为
|
||||
`Runtime: OpenClaw Pi Default`,Codex 应用服务器 harness 显示为
|
||||
`Runtime: OpenAI Codex`。
|
||||
|
||||
## 要求
|
||||
|
||||
- OpenClaw,并且可用内置的 `codex` 插件。
|
||||
- Codex app-server `0.125.0` 或更高版本。内置插件默认会管理一个兼容的
|
||||
Codex app-server 二进制文件,因此 `PATH` 中本地 `codex` 命令
|
||||
- 已提供内置 `codex` 插件的 OpenClaw。
|
||||
- Codex 应用服务器 `0.125.0` 或更高版本。内置插件默认会管理兼容的
|
||||
Codex 应用服务器二进制文件,因此 `PATH` 中本地的 `codex` 命令
|
||||
不会影响正常的 harness 启动。
|
||||
- app-server 进程可用的 Codex 凭证。
|
||||
- 应用服务器进程可用的 Codex 认证。
|
||||
|
||||
该插件会阻止较旧或未带版本信息的 app-server 握手。
|
||||
这样可确保 OpenClaw 仅运行在它已经测试过的协议表面之上。
|
||||
该插件会阻止较旧或未带版本信息的应用服务器握手。这样可以确保
|
||||
OpenClaw 始终使用它已经验证过的协议接口。
|
||||
|
||||
对于实时和 Docker 烟雾测试,凭证通常来自 `OPENAI_API_KEY`,并可附带
|
||||
可选的 Codex CLI 文件,例如 `~/.codex/auth.json` 和
|
||||
`~/.codex/config.toml`。请使用与你本地 Codex app-server 相同的凭证材料。
|
||||
对于实时和 Docker smoke 测试,认证通常来自 `OPENAI_API_KEY`,再加上可选的 Codex CLI 文件,例如 `~/.codex/auth.json` 和
|
||||
`~/.codex/config.toml`。请使用与你本地 Codex 应用服务器相同的认证材料。
|
||||
|
||||
## 最小配置
|
||||
|
||||
@ -208,15 +196,15 @@ OpenClaw 会在该会话上记录所选 harness id,并在相同会话 id 的
|
||||
agents: {
|
||||
defaults: {
|
||||
model: "openai/gpt-5.5",
|
||||
embeddedHarness: {
|
||||
runtime: "codex",
|
||||
agentRuntime: {
|
||||
id: "codex",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
如果你的配置使用 `plugins.allow`,也请将 `codex` 包含进去:
|
||||
如果你的配置使用 `plugins.allow`,也请将 `codex` 包含在其中:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -231,28 +219,25 @@ OpenClaw 会在该会话上记录所选 harness id,并在相同会话 id 的
|
||||
}
|
||||
```
|
||||
|
||||
仍将 `agents.defaults.model` 或某个智能体模型设置为
|
||||
`codex/<model>` 的旧配置,仍会自动启用内置的 `codex` 插件。新配置应
|
||||
优先使用 `openai/<model>`,再配合上面的显式
|
||||
`embeddedHarness` 条目。
|
||||
旧版配置如果将 `agents.defaults.model` 或某个智能体模型设置为
|
||||
`codex/<model>`,仍会自动启用内置 `codex` 插件。新配置应优先
|
||||
使用 `openai/<model>` 加上上面的显式 `agentRuntime` 条目。
|
||||
|
||||
## 将 Codex 与其他模型一起添加
|
||||
## 将 Codex 与其他模型一起使用
|
||||
|
||||
如果同一个智能体需要在 Codex 和非 Codex 提供商模型之间自由切换,
|
||||
请不要全局设置 `runtime: "codex"`。强制运行时会应用到该智能体或会话的每一次
|
||||
嵌入式回合。如果你在强制该运行时时选择了 Anthropic 模型,
|
||||
OpenClaw 仍会尝试使用 Codex harness,并以关闭失败的方式报错,而不是悄悄地将该回合路由到 PI。
|
||||
如果同一个智能体需要在 Codex 和非 Codex provider 模型之间自由切换,请不要全局设置 `agentRuntime.id: "codex"`。强制运行时会应用到该智能体或会话的每一个
|
||||
嵌入式回合。如果你在该运行时被强制时选择了 Anthropic 模型,OpenClaw 仍会尝试使用 Codex harness,并以失败关闭,而不是静默地通过 PI 路由该回合。
|
||||
|
||||
请改用以下其中一种形式:
|
||||
请改用以下其中一种结构:
|
||||
|
||||
- 为 Codex 单独设置一个智能体,并使用 `embeddedHarness.runtime: "codex"`。
|
||||
- 将默认智能体保持为 `runtime: "auto"`,并在正常混合
|
||||
提供商用法下使用 PI 回退。
|
||||
- 仅将旧版 `codex/*` 引用用于兼容性。新配置应优先使用
|
||||
`openai/*`,并搭配显式的 Codex 运行时策略。
|
||||
- 将 Codex 放到一个专用智能体上,并设置 `agentRuntime.id: "codex"`。
|
||||
- 将默认智能体保持为 `agentRuntime.id: "auto"`,并为常规混合
|
||||
provider 使用保留 PI 回退。
|
||||
- 仅将旧版 `codex/*` 引用用于兼容性。新配置应优先
|
||||
使用 `openai/*` 加上显式 Codex 运行时策略。
|
||||
|
||||
例如,下面的配置会让默认智能体保持正常的自动选择,同时
|
||||
新增一个独立的 Codex 智能体:
|
||||
例如,下面的配置会让默认智能体保持正常的自动选择,并
|
||||
添加一个单独的 Codex 智能体:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -265,8 +250,8 @@ OpenClaw 仍会尝试使用 Codex harness,并以关闭失败的方式报错,
|
||||
},
|
||||
agents: {
|
||||
defaults: {
|
||||
embeddedHarness: {
|
||||
runtime: "auto",
|
||||
agentRuntime: {
|
||||
id: "auto",
|
||||
fallback: "pi",
|
||||
},
|
||||
},
|
||||
@ -280,8 +265,8 @@ OpenClaw 仍会尝试使用 Codex harness,并以关闭失败的方式报错,
|
||||
id: "codex",
|
||||
name: "Codex",
|
||||
model: "openai/gpt-5.5",
|
||||
embeddedHarness: {
|
||||
runtime: "codex",
|
||||
agentRuntime: {
|
||||
id: "codex",
|
||||
},
|
||||
},
|
||||
],
|
||||
@ -289,36 +274,36 @@ OpenClaw 仍会尝试使用 Codex harness,并以关闭失败的方式报错,
|
||||
}
|
||||
```
|
||||
|
||||
在这种形式下:
|
||||
在这种结构下:
|
||||
|
||||
- 默认的 `main` 智能体使用正常的提供商路径和 PI 兼容回退。
|
||||
- `codex` 智能体使用 Codex app-server harness。
|
||||
- 如果 `codex` 智能体缺少 Codex 或 Codex 不受支持,该回合会
|
||||
直接失败,而不是悄悄使用 PI。
|
||||
- 默认的 `main` 智能体使用正常 provider 路径和 PI 兼容回退。
|
||||
- `codex` 智能体使用 Codex 应用服务器 harness。
|
||||
- 如果 `codex` 智能体缺少 Codex 或不受支持,该回合会失败,
|
||||
而不是悄悄改用 PI。
|
||||
|
||||
## 智能体命令路由
|
||||
|
||||
智能体应按用户意图路由请求,而不是仅仅根据 “Codex” 这个词:
|
||||
智能体应根据用户意图而不是仅凭“Codex”这个词来路由请求:
|
||||
|
||||
| 用户请求的是…… | 智能体应使用…… |
|
||||
| ------------------------------------------------------ | ---------------------------------------------- |
|
||||
| “将这个聊天绑定到 Codex” | `/codex bind` |
|
||||
| “在这里恢复 Codex 线程 `<id>`” | `/codex resume <id>` |
|
||||
| “显示 Codex 线程” | `/codex threads` |
|
||||
| “将 Codex 用作这个智能体的运行时” | 将配置更改为 `embeddedHarness.runtime` |
|
||||
| “用我的 ChatGPT/Codex 订阅配合普通 OpenClaw” | `openai-codex/*` 模型引用 |
|
||||
| “通过 ACP/acpx 运行 Codex” | ACP `sessions_spawn({ runtime: "acp", ... })` |
|
||||
| “在线程中启动 Claude Code/Gemini/OpenCode/Cursor” | ACP/acpx,而不是 `/codex`,也不是原生子智能体 |
|
||||
| 用户请求的是... | 智能体应使用... |
|
||||
| -------------------------------------------------------- | ------------------------------------------------ |
|
||||
| “将这个聊天绑定到 Codex” | `/codex bind` |
|
||||
| “在这里恢复 Codex 线程 `<id>`” | `/codex resume <id>` |
|
||||
| “显示 Codex 线程” | `/codex threads` |
|
||||
| “将 Codex 用作这个智能体的运行时” | 将 `agentRuntime.id` 改为相应配置 |
|
||||
| “用我的 ChatGPT/Codex 订阅配合普通 OpenClaw 使用” | `openai-codex/*` 模型引用 |
|
||||
| “通过 ACP/acpx 运行 Codex” | ACP `sessions_spawn({ runtime: "acp", ... })` |
|
||||
| “在线程中启动 Claude Code/Gemini/OpenCode/Cursor” | ACP/acpx,而不是 `/codex`,也不是原生子智能体 |
|
||||
|
||||
只有在 ACP 已启用、可分发,并且由已加载的运行时后端支持时,
|
||||
OpenClaw 才会向智能体展示 ACP 启动指导。如果 ACP 不可用,
|
||||
系统提示词和插件 Skills 不应向智能体传授 ACP
|
||||
仅当 ACP 已启用、可调度并且有已加载的运行时后端支持时,
|
||||
OpenClaw 才会向智能体公开 ACP 启动指引。如果 ACP 不可用,
|
||||
系统提示和插件 Skills 不应向智能体传授 ACP
|
||||
路由方式。
|
||||
|
||||
## 仅 Codex 部署
|
||||
|
||||
当你需要证明每一个嵌入式智能体回合
|
||||
都使用 Codex 时,请强制使用 Codex harness。显式插件运行时默认不使用 PI 回退,因此
|
||||
当你需要证明每一个嵌入式智能体回合都
|
||||
使用 Codex 时,请强制使用 Codex harness。显式插件运行时默认不使用 PI 回退,因此
|
||||
`fallback: "none"` 是可选的,但通常对文档说明很有帮助:
|
||||
|
||||
```json5
|
||||
@ -326,8 +311,8 @@ OpenClaw 才会向智能体展示 ACP 启动指导。如果 ACP 不可用,
|
||||
agents: {
|
||||
defaults: {
|
||||
model: "openai/gpt-5.5",
|
||||
embeddedHarness: {
|
||||
runtime: "codex",
|
||||
agentRuntime: {
|
||||
id: "codex",
|
||||
fallback: "none",
|
||||
},
|
||||
},
|
||||
@ -341,22 +326,21 @@ OpenClaw 才会向智能体展示 ACP 启动指导。如果 ACP 不可用,
|
||||
OPENCLAW_AGENT_RUNTIME=codex openclaw gateway run
|
||||
```
|
||||
|
||||
在强制使用 Codex 的情况下,如果 Codex 插件被禁用、app-server
|
||||
版本过旧,或 app-server 无法启动,OpenClaw 会尽早失败。只有当你明确希望
|
||||
PI 处理缺失的 harness 选择时,才设置
|
||||
在强制使用 Codex 的情况下,如果 Codex 插件被禁用、
|
||||
应用服务器版本过旧,或应用服务器无法启动,OpenClaw 会尽早失败。只有当你明确希望在缺少 harness 选择时由 PI 处理时,才设置
|
||||
`OPENCLAW_AGENT_HARNESS_FALLBACK=pi`。
|
||||
|
||||
## 按智能体使用 Codex
|
||||
|
||||
你可以让某一个智能体仅使用 Codex,同时让默认智能体保持正常的
|
||||
你可以让某个智能体仅使用 Codex,而默认智能体仍保持正常
|
||||
自动选择:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
defaults: {
|
||||
embeddedHarness: {
|
||||
runtime: "auto",
|
||||
agentRuntime: {
|
||||
id: "auto",
|
||||
fallback: "pi",
|
||||
},
|
||||
},
|
||||
@ -370,8 +354,8 @@ PI 处理缺失的 harness 选择时,才设置
|
||||
id: "codex",
|
||||
name: "Codex",
|
||||
model: "openai/gpt-5.5",
|
||||
embeddedHarness: {
|
||||
runtime: "codex",
|
||||
agentRuntime: {
|
||||
id: "codex",
|
||||
fallback: "none",
|
||||
},
|
||||
},
|
||||
@ -380,15 +364,15 @@ PI 处理缺失的 harness 选择时,才设置
|
||||
}
|
||||
```
|
||||
|
||||
使用常规会话命令来切换智能体和模型。`/new` 会创建一个新的
|
||||
OpenClaw 会话,而 Codex harness 会按需创建或恢复它的 sidecar app-server
|
||||
使用普通会话命令切换智能体和模型。`/new` 会创建一个新的
|
||||
OpenClaw 会话,而 Codex harness 会按需创建或恢复其侧车应用服务器
|
||||
线程。`/reset` 会清除该线程的 OpenClaw 会话绑定,
|
||||
并让下一次回合再次根据当前配置解析 harness。
|
||||
并让下一回合根据当前配置再次解析 harness。
|
||||
|
||||
## 模型发现
|
||||
|
||||
默认情况下,Codex 插件会向 app-server 请求可用模型。如果
|
||||
发现失败或超时,它会使用内置的回退目录来支持以下模型:
|
||||
默认情况下,Codex 插件会向应用服务器请求可用模型。如果
|
||||
发现失败或超时,它会使用一个内置回退目录,包含:
|
||||
|
||||
- GPT-5.5
|
||||
- GPT-5.4 mini
|
||||
@ -434,26 +418,24 @@ OpenClaw 会话,而 Codex harness 会按需创建或恢复它的 sidecar app-s
|
||||
}
|
||||
```
|
||||
|
||||
## App-server 连接与策略
|
||||
## 应用服务器连接和策略
|
||||
|
||||
默认情况下,插件会在本地使用以下命令启动由 OpenClaw 管理的 Codex 二进制文件:
|
||||
默认情况下,插件会在本地使用以下命令启动 OpenClaw 管理的 Codex 二进制文件:
|
||||
|
||||
```bash
|
||||
codex app-server --listen stdio://
|
||||
```
|
||||
|
||||
该受管二进制文件被声明为内置插件运行时依赖,并与其余 `codex` 插件依赖一起
|
||||
进行准备。这使 app-server 版本绑定到内置插件,而不是绑定到本地
|
||||
恰好安装的独立 Codex CLI。只有在你明确希望运行其他可执行文件时,
|
||||
才设置 `appServer.command`。
|
||||
该受管二进制文件被声明为内置插件运行时依赖,并与其余 `codex` 插件依赖一起暂存。
|
||||
这样可以让应用服务器版本绑定到内置插件,而不是绑定到本地恰好安装的某个独立 Codex CLI。
|
||||
只有在你明确想运行不同可执行文件时,才设置 `appServer.command`。
|
||||
|
||||
默认情况下,OpenClaw 会以 YOLO 模式启动本地 Codex harness 会话:
|
||||
`approvalPolicy: "never"`、`approvalsReviewer: "user"`,以及
|
||||
`sandbox: "danger-full-access"`。这是用于自治 heartbeat 的受信任本地操作员姿态:
|
||||
Codex 可以使用 shell 和网络工具,而不会停在
|
||||
无人应答的原生审批提示上。
|
||||
`sandbox: "danger-full-access"`。这是用于自治心跳的受信任本地操作员姿态:
|
||||
Codex 可以使用 shell 和网络工具,而不会停在无人可响应的原生审批提示上。
|
||||
|
||||
若要启用由 Codex guardian 审核的审批,请设置 `appServer.mode:
|
||||
如果你想启用由 Codex guardian 审核的审批,请设置 `appServer.mode:
|
||||
"guardian"`:
|
||||
|
||||
```json5
|
||||
@ -474,20 +456,21 @@ Codex 可以使用 shell 和网络工具,而不会停在
|
||||
}
|
||||
```
|
||||
|
||||
Guardian 模式使用 Codex 的原生自动审核审批路径。当 Codex 请求
|
||||
离开沙箱、在工作区外写入,或添加诸如网络访问之类的权限时,
|
||||
Codex 会将该审批请求路由给原生审核器,而不是发出人工提示。
|
||||
审核器会应用 Codex 的风险框架,并批准或拒绝该具体请求。
|
||||
当你希望比 YOLO 模式有更多护栏,但仍需要无人值守智能体持续推进时,请使用 Guardian。
|
||||
Guardian 模式使用 Codex 原生自动审查审批路径。当 Codex 请求
|
||||
离开沙箱、写入工作区之外,或添加诸如网络访问之类的权限时,
|
||||
Codex 会将该审批请求路由给原生审查器,而不是人工提示。
|
||||
该审查器会应用 Codex 的风险框架,并批准或拒绝具体请求。
|
||||
当你想要比 YOLO 模式更多的防护措施,
|
||||
但仍需要无人值守智能体持续推进工作时,请使用 Guardian。
|
||||
|
||||
`guardian` 预设会展开为 `approvalPolicy: "on-request"`、
|
||||
`approvalsReviewer: "auto_review"` 和 `sandbox: "workspace-write"`。
|
||||
`approvalsReviewer: "auto_review"`,以及 `sandbox: "workspace-write"`。
|
||||
单独的策略字段仍会覆盖 `mode`,因此高级部署可以将
|
||||
该预设与显式选择混合使用。旧的 `guardian_subagent` 审核器值
|
||||
仍可作为兼容别名使用,但新配置应使用
|
||||
该预设与显式选择混合使用。较旧的 `guardian_subagent` 审查器值
|
||||
仍被接受为兼容别名,但新配置应使用
|
||||
`auto_review`。
|
||||
|
||||
对于已经在运行的 app-server,请使用 WebSocket 传输:
|
||||
对于已经运行的应用服务器,请使用 WebSocket 传输:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -511,20 +494,20 @@ 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 headers。 |
|
||||
| `requestTimeoutMs` | `60000` | app-server 控制平面调用的超时时间。 |
|
||||
| `mode` | `"yolo"` | 用于 YOLO 或 guardian 审核执行的预设。 |
|
||||
| `approvalPolicy` | `"never"` | 发送到线程启动/恢复/回合的原生 Codex 审批策略。 |
|
||||
| `sandbox` | `"danger-full-access"` | 发送到线程启动/恢复的原生 Codex 沙箱模式。 |
|
||||
| `approvalsReviewer` | `"user"` | 使用 `"auto_review"` 可让 Codex 审核原生审批提示。`guardian_subagent` 仍是旧版别名。 |
|
||||
| `serviceTier` | 未设置 | 可选的 Codex app-server 服务层级:`"fast"`、`"flex"` 或 `null`。无效的旧版值会被忽略。 |
|
||||
| 字段 | 默认值 | 含义 |
|
||||
| ------------------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
|
||||
| `transport` | `"stdio"` | `"stdio"` 会启动 Codex;`"websocket"` 会连接到 `url`。 |
|
||||
| `command` | 受管 Codex 二进制文件 | 用于 stdio 传输的可执行文件。留空则使用受管二进制文件;只有在明确覆盖时才设置它。 |
|
||||
| `args` | `["app-server", "--listen", "stdio://"]` | 用于 stdio 传输的参数。 |
|
||||
| `url` | 未设置 | WebSocket 应用服务器 URL。 |
|
||||
| `authToken` | 未设置 | 用于 WebSocket 传输的 Bearer token。 |
|
||||
| `headers` | `{}` | 额外的 WebSocket 请求头。 |
|
||||
| `requestTimeoutMs` | `60000` | 应用服务器控制平面调用的超时时间。 |
|
||||
| `mode` | `"yolo"` | YOLO 或 guardian 审核执行的预设。 |
|
||||
| `approvalPolicy` | `"never"` | 发送到线程启动/恢复/回合的原生 Codex 审批策略。 |
|
||||
| `sandbox` | `"danger-full-access"` | 发送到线程启动/恢复的原生 Codex 沙箱模式。 |
|
||||
| `approvalsReviewer` | `"user"` | 使用 `"auto_review"` 让 Codex 审核原生审批提示。`guardian_subagent` 仍是旧版别名。 |
|
||||
| `serviceTier` | 未设置 | 可选的 Codex 应用服务器服务层级:`"fast"`、`"flex"` 或 `null`。无效的旧值会被忽略。 |
|
||||
|
||||
环境变量覆盖仍可用于本地测试:
|
||||
|
||||
@ -534,14 +517,13 @@ Codex 会将该审批请求路由给原生审核器,而不是发出人工提
|
||||
- `OPENCLAW_CODEX_APP_SERVER_APPROVAL_POLICY`
|
||||
- `OPENCLAW_CODEX_APP_SERVER_SANDBOX`
|
||||
|
||||
当 `appServer.command` 未设置时,
|
||||
`OPENCLAW_CODEX_APP_SERVER_BIN` 会绕过受管二进制文件。
|
||||
当
|
||||
`appServer.command` 未设置时,`OPENCLAW_CODEX_APP_SERVER_BIN` 会绕过受管二进制文件。
|
||||
|
||||
`OPENCLAW_CODEX_APP_SERVER_GUARDIAN=1` 已被移除。请改用
|
||||
`plugins.entries.codex.config.appServer.mode: "guardian"`,或
|
||||
在一次性本地测试中使用 `OPENCLAW_CODEX_APP_SERVER_MODE=guardian`。对于
|
||||
可重复部署,优先使用配置,因为这样可以将插件行为与 Codex harness 其余设置
|
||||
放在同一个经过审查的文件中。
|
||||
`plugins.entries.codex.config.appServer.mode: "guardian"`,或者
|
||||
在一次性本地测试中使用 `OPENCLAW_CODEX_APP_SERVER_MODE=guardian`。对于可重复部署,优先使用配置,
|
||||
因为它可以将插件行为与 Codex harness 其余设置一起保存在同一个经过审查的文件中。
|
||||
|
||||
## 常见配方
|
||||
|
||||
@ -566,8 +548,8 @@ Codex 会将该审批请求路由给原生审核器,而不是发出人工提
|
||||
agents: {
|
||||
defaults: {
|
||||
model: "openai/gpt-5.5",
|
||||
embeddedHarness: {
|
||||
runtime: "codex",
|
||||
agentRuntime: {
|
||||
id: "codex",
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -603,7 +585,7 @@ Codex 会将该审批请求路由给原生审核器,而不是发出人工提
|
||||
}
|
||||
```
|
||||
|
||||
带显式 headers 的远程 app-server:
|
||||
带显式请求头的远程应用服务器:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -626,180 +608,161 @@ Codex 会将该审批请求路由给原生审核器,而不是发出人工提
|
||||
}
|
||||
```
|
||||
|
||||
模型切换仍由 OpenClaw 控制。当一个 OpenClaw 会话附加到现有的
|
||||
Codex 线程时,下一次回合会再次将当前所选的
|
||||
OpenAI 模型、提供商、审批策略、沙箱和服务层级发送到
|
||||
app-server。从 `openai/gpt-5.5` 切换到 `openai/gpt-5.2` 会保留
|
||||
模型切换仍由 OpenClaw 控制。当一个 OpenClaw 会话附加到现有
|
||||
Codex 线程时,下一回合会再次向
|
||||
app-server 发送当前选定的
|
||||
OpenAI 模型、provider、审批策略、沙箱和服务层级。从 `openai/gpt-5.5` 切换到 `openai/gpt-5.2` 会保留
|
||||
线程绑定,但会要求 Codex 使用新选定的模型继续执行。
|
||||
|
||||
## Codex 命令
|
||||
|
||||
内置插件将 `/codex` 注册为一个已授权的斜杠命令。它是通用的,
|
||||
适用于任何支持 OpenClaw 文本命令的渠道。
|
||||
内置插件将 `/codex` 注册为一个已授权斜杠命令。它是
|
||||
通用的,可在任何支持 OpenClaw 文本命令的渠道上使用。
|
||||
|
||||
常见形式:
|
||||
|
||||
- `/codex status` 显示实时 app-server 连接状态、模型、账户、速率限制、MCP 服务器和 skills。
|
||||
- `/codex status` 显示实时 app-server 连接性、模型、账户、速率限制、MCP 服务器和 Skills。
|
||||
- `/codex models` 列出实时 Codex app-server 模型。
|
||||
- `/codex threads [filter]` 列出最近的 Codex 线程。
|
||||
- `/codex resume <thread-id>` 将当前 OpenClaw 会话附加到一个现有的 Codex 线程。
|
||||
- `/codex resume <thread-id>` 将当前 OpenClaw 会话附加到现有 Codex 线程。
|
||||
- `/codex compact` 请求 Codex app-server 压缩已附加的线程。
|
||||
- `/codex review` 为已附加的线程启动 Codex 原生审核。
|
||||
- `/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` 会写入与 harness 在
|
||||
常规回合中使用的同一个 sidecar 绑定文件。在下一条消息中,OpenClaw 会恢复该 Codex 线程,
|
||||
将当前选定的 OpenClaw 模型传入 app-server,并保持扩展历史记录
|
||||
处于启用状态。
|
||||
正常回合中使用的同一个侧车绑定文件。在下一条消息时,OpenClaw 会恢复该 Codex 线程,将
|
||||
当前选定的 OpenClaw 模型传入 app-server,并保持启用扩展历史记录。
|
||||
|
||||
该命令界面要求 Codex app-server `0.125.0` 或更高版本。如果未来或自定义的
|
||||
app-server 未暴露相应 JSON-RPC 方法,各个单独的
|
||||
控制方法会显示为 `unsupported by this Codex app-server`。
|
||||
该命令界面要求 Codex app-server `0.125.0` 或更高版本。如果
|
||||
未来版本或自定义 app-server 未公开某个 JSON-RPC 方法,
|
||||
对应控制方法会显示为 `unsupported by this Codex app-server`。
|
||||
|
||||
## 钩子边界
|
||||
|
||||
Codex harness 具有三层钩子:
|
||||
Codex harness 有三层钩子:
|
||||
|
||||
| 层级 | 所有者 | 目的 |
|
||||
| 层级 | 所有者 | 用途 |
|
||||
| ------------------------------------- | ------------------------ | ------------------------------------------------------------------- |
|
||||
| OpenClaw 插件钩子 | OpenClaw | 在 PI 和 Codex harness 之间提供产品/插件兼容性。 |
|
||||
| Codex app-server 扩展中间件 | OpenClaw 内置插件 | 围绕 OpenClaw 动态工具的逐回合适配器行为。 |
|
||||
| Codex 原生钩子 | Codex | 来自 Codex 配置的底层 Codex 生命周期和原生工具策略。 |
|
||||
| OpenClaw 插件钩子 | OpenClaw | 在 PI 和 Codex harness 之间保持产品/插件兼容性。 |
|
||||
| Codex app-server 扩展中间件 | OpenClaw 内置插件 | 围绕 OpenClaw 动态工具的逐回合适配器行为。 |
|
||||
| Codex 原生钩子 | Codex | 来自 Codex 配置的底层 Codex 生命周期和原生工具策略。 |
|
||||
|
||||
OpenClaw 不会使用项目级或全局的 Codex `hooks.json` 文件来路由
|
||||
OpenClaw 不使用项目级或全局 Codex `hooks.json` 文件来路由
|
||||
OpenClaw 插件行为。对于受支持的原生工具和权限桥接,
|
||||
OpenClaw 会为每个线程注入 Codex 配置,用于 `PreToolUse`、`PostToolUse`、
|
||||
`PermissionRequest` 和 `Stop`。其他 Codex 钩子,例如 `SessionStart` 和
|
||||
`UserPromptSubmit`,仍然属于 Codex 级控制;它们不会作为
|
||||
v1 合同中的 OpenClaw 插件钩子暴露。
|
||||
`UserPromptSubmit`,仍然属于 Codex 级控制;在 v1 合约中,它们不会作为
|
||||
OpenClaw 插件钩子公开。
|
||||
|
||||
对于 OpenClaw 动态工具,Codex 发出调用请求之后由 OpenClaw 执行该工具,
|
||||
因此 OpenClaw 会在
|
||||
harness 适配器中触发它所拥有的插件和中间件行为。对于 Codex 原生工具,
|
||||
Codex 拥有规范工具记录。OpenClaw 可以镜像选定事件,
|
||||
但无法重写原生 Codex 线程,
|
||||
除非 Codex 通过 app-server 或原生钩子
|
||||
回调暴露该操作。
|
||||
对于 OpenClaw 动态工具,Codex 请求调用后由 OpenClaw 执行该工具,因此 OpenClaw 会在
|
||||
harness 适配器中触发它所拥有的插件和中间件行为。对于 Codex 原生工具,Codex 拥有规范工具记录。
|
||||
OpenClaw 可以镜像选定事件,但无法重写原生 Codex
|
||||
线程,除非 Codex 通过 app-server 或原生钩子
|
||||
回调公开该操作。
|
||||
|
||||
压缩和 LLM 生命周期投影来自 Codex app-server
|
||||
通知和 OpenClaw 适配器状态,而不是原生 Codex 钩子命令。
|
||||
OpenClaw 的 `before_compaction`、`after_compaction`、`llm_input` 和
|
||||
`llm_output` 事件是适配器级观察结果,而不是
|
||||
对 Codex 内部请求或压缩载荷的逐字节捕获。
|
||||
`llm_output` 事件是适配器级观察结果,而不是对
|
||||
Codex 内部请求或压缩载荷的逐字节捕获。
|
||||
|
||||
Codex 原生 `hook/started` 和 `hook/completed` app-server 通知
|
||||
会被投影为 `codex_app_server.hook` 智能体事件,用于轨迹记录和调试。
|
||||
会被投影为用于轨迹和调试的 `codex_app_server.hook` 智能体事件。
|
||||
它们不会调用 OpenClaw 插件钩子。
|
||||
|
||||
## V1 支持合同
|
||||
## V1 支持合约
|
||||
|
||||
Codex 模式并不是在底层换了一个模型调用的 PI。Codex 接管了更多
|
||||
原生模型循环,而 OpenClaw 会围绕这一边界适配它的插件和会话界面。
|
||||
Codex 模式并不是“底层换了个模型调用的 PI”。Codex 接管了更多
|
||||
原生模型循环,而 OpenClaw 会围绕这个边界适配它的插件和会话界面。
|
||||
|
||||
Codex 运行时 v1 中支持的内容:
|
||||
Codex 运行时 v1 中受支持的内容:
|
||||
|
||||
| 界面 | 支持情况 | 原因 |
|
||||
| --------------------------------------------- | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| 通过 Codex 运行 OpenAI 模型循环 | 支持 | Codex app-server 负责 OpenAI 回合、原生线程恢复和原生工具续接。 |
|
||||
| OpenClaw 渠道路由与传递 | 支持 | Telegram、Discord、Slack、WhatsApp、iMessage 和其他渠道保持在模型运行时之外。 |
|
||||
| OpenClaw 动态工具 | 支持 | Codex 会请求 OpenClaw 执行这些工具,因此 OpenClaw 仍在执行路径中。 |
|
||||
| 提示词和上下文插件 | 支持 | OpenClaw 会在启动或恢复线程之前构建提示词叠加层,并将上下文投影到 Codex 回合中。 |
|
||||
| 上下文引擎生命周期 | 支持 | 组装、摄取或回合后维护,以及上下文引擎压缩协调,都会在 Codex 回合中运行。 |
|
||||
| 动态工具钩子 | 支持 | `before_tool_call`、`after_tool_call` 和工具结果中间件会围绕 OpenClaw 自有动态工具运行。 |
|
||||
| 生命周期钩子 | 作为适配器观察结果提供支持 | `llm_input`、`llm_output`、`agent_end`、`before_compaction` 和 `after_compaction` 会使用符合实际的 Codex 模式载荷触发。 |
|
||||
| 最终答案修订门 | 通过原生钩子转发提供支持 | Codex `Stop` 会转发给 `before_agent_finalize`;`revise` 会要求 Codex 在最终化之前再进行一次模型调用。 |
|
||||
| 原生 shell、patch 和 MCP 的阻止或观察 | 通过原生钩子转发提供支持 | Codex `PreToolUse` 和 `PostToolUse` 会针对已承诺的原生工具界面进行转发,包括 Codex app-server `0.125.0` 或更高版本上的 MCP 载荷。支持阻止;不支持参数重写。 |
|
||||
| 原生权限策略 | 通过原生钩子转发提供支持 | 当运行时暴露该能力时,Codex `PermissionRequest` 可以通过 OpenClaw 策略进行路由。如果 OpenClaw 不返回决策,Codex 会继续其正常的 guardian 或用户审批路径。 |
|
||||
| app-server 轨迹捕获 | 支持 | OpenClaw 会记录它发送给 app-server 的请求,以及它接收到的 app-server 通知。 |
|
||||
| 界面 | 支持情况 | 原因 |
|
||||
| --------------------------------------------- | --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| 通过 Codex 运行 OpenAI 模型循环 | 支持 | Codex app-server 负责 OpenAI 回合、原生线程恢复和原生工具继续执行。 |
|
||||
| OpenClaw 渠道路由和传递 | 支持 | Telegram、Discord、Slack、WhatsApp、iMessage 和其他渠道保持在模型运行时之外。 |
|
||||
| OpenClaw 动态工具 | 支持 | Codex 会请求 OpenClaw 执行这些工具,因此 OpenClaw 仍处于执行路径中。 |
|
||||
| 提示和上下文插件 | 支持 | OpenClaw 会在启动或恢复线程之前构建提示覆盖层,并将上下文投影到 Codex 回合中。 |
|
||||
| 上下文引擎生命周期 | 支持 | Assemble、摄取或回合后维护,以及上下文引擎压缩协调都会为 Codex 回合运行。 |
|
||||
| 动态工具钩子 | 支持 | `before_tool_call`、`after_tool_call` 和工具结果中间件会围绕 OpenClaw 拥有的动态工具运行。 |
|
||||
| 生命周期钩子 | 作为适配器观察结果受支持 | `llm_input`、`llm_output`、`agent_end`、`before_compaction` 和 `after_compaction` 会触发,并携带真实的 Codex 模式载荷。 |
|
||||
| 最终答案修订门控 | 通过原生钩子中继支持 | Codex `Stop` 会中继到 `before_agent_finalize`;`revise` 会在最终完成前请求 Codex 再执行一次模型推理。 |
|
||||
| 阻止或观察原生 shell、patch 和 MCP | 通过原生钩子中继支持 | 对于已提交的原生工具界面,包括 Codex app-server `0.125.0` 或更高版本中的 MCP 载荷,Codex `PreToolUse` 和 `PostToolUse` 会被中继。支持阻止;不支持参数重写。 |
|
||||
| 原生权限策略 | 通过原生钩子中继支持 | 当运行时公开该能力时,Codex `PermissionRequest` 可以通过 OpenClaw 策略路由。如果 OpenClaw 未返回决定,Codex 会继续走它自己的 guardian 或用户审批路径。 |
|
||||
| App-server 轨迹捕获 | 支持 | OpenClaw 会记录它发送给 app-server 的请求以及它接收到的 app-server 通知。 |
|
||||
|
||||
Codex 运行时 v1 中不支持的内容:
|
||||
|
||||
| 界面 | V1 边界 | 未来路径 |
|
||||
| --------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
|
||||
| 原生工具参数变更 | Codex 原生 pre-tool 钩子可以阻止,但 OpenClaw 不会重写 Codex 原生工具参数。 | 需要 Codex 钩子/模式支持替换后的工具输入。 |
|
||||
| 可编辑的 Codex 原生转录历史 | Codex 拥有规范的原生线程历史。OpenClaw 拥有镜像,并可以投影未来上下文,但不应变更不受支持的内部结构。 | 如果需要对原生线程进行手术式修改,则需添加显式 Codex app-server API。 |
|
||||
| 用于 Codex 原生工具记录的 `tool_result_persist` | 该钩子转换的是 OpenClaw 自有的转录写入,而不是 Codex 原生工具记录。 | 可以镜像转换后的记录,但规范性重写需要 Codex 支持。 |
|
||||
| 丰富的原生压缩元数据 | OpenClaw 能观察到压缩开始和完成,但不会收到稳定的保留/丢弃列表、token 增量或摘要载荷。 | 需要更丰富的 Codex 压缩事件。 |
|
||||
| 压缩干预 | 当前 OpenClaw 的压缩钩子在 Codex 模式下仅限通知级别。 | 如果插件需要否决或重写原生压缩,则需添加 Codex 的 pre/post 压缩钩子。 |
|
||||
| 逐字节模型 API 请求捕获 | OpenClaw 可以捕获 app-server 请求和通知,但最终 OpenAI API 请求由 Codex 核心在内部构建。 | 需要 Codex 模型请求追踪事件或调试 API。 |
|
||||
| 界面 | V1 边界 | 未来路径 |
|
||||
| --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
|
||||
| 原生工具参数变更 | Codex 原生预工具钩子可以阻止调用,但 OpenClaw 不会重写 Codex 原生工具参数。 | 需要 Codex 钩子/schema 支持替换工具输入。 |
|
||||
| 可编辑的 Codex 原生转录历史 | Codex 拥有规范的原生线程历史。OpenClaw 拥有镜像并可以投影未来上下文,但不应修改不受支持的内部结构。 | 如果需要原生线程外科式修改,则需增加显式 Codex app-server API。 |
|
||||
| 用于 Codex 原生工具记录的 `tool_result_persist` | 该钩子转换的是 OpenClaw 拥有的转录写入,而不是 Codex 原生工具记录。 | 可以镜像转换后的记录,但规范重写需要 Codex 支持。 |
|
||||
| 丰富的原生压缩元数据 | OpenClaw 能观察到压缩开始和完成,但不会接收到稳定的保留/丢弃列表、token 增量或摘要载荷。 | 需要更丰富的 Codex 压缩事件。 |
|
||||
| 压缩干预 | 当前 OpenClaw 压缩钩子在 Codex 模式下仅处于通知级别。 | 如果插件需要否决或重写原生压缩,则需增加 Codex 压缩前/后钩子。 |
|
||||
| 逐字节模型 API 请求捕获 | OpenClaw 可以捕获 app-server 请求和通知,但最终的 OpenAI API 请求由 Codex core 在内部构建。 | 需要 Codex 模型请求追踪事件或调试 API。 |
|
||||
|
||||
## 工具、媒体与压缩
|
||||
## 工具、媒体和压缩
|
||||
|
||||
Codex harness 只改变底层嵌入式智能体执行器。
|
||||
|
||||
OpenClaw 仍然构建工具列表,并从
|
||||
harness 接收动态工具结果。文本、图像、视频、音乐、TTS、审批以及消息工具输出
|
||||
仍然通过常规 OpenClaw 传递路径处理。
|
||||
harness 接收动态工具结果。文本、图像、视频、音乐、TTS、审批和消息工具输出
|
||||
仍然通过正常的 OpenClaw 传递路径进行处理。
|
||||
|
||||
原生钩子转发刻意保持通用,但 v1 支持合同
|
||||
仅限于 OpenClaw 测试过的 Codex 原生工具和权限路径。在
|
||||
原生钩子中继被有意设计为通用机制,但 v1 支持合约
|
||||
仅限于 OpenClaw 已测试的 Codex 原生工具和权限路径。在
|
||||
Codex 运行时中,这包括 shell、patch 和 MCP 的 `PreToolUse`、
|
||||
`PostToolUse` 以及 `PermissionRequest` 载荷。不要假定未来的每个
|
||||
Codex 钩子事件都会成为 OpenClaw 插件界面,除非运行时合同
|
||||
明确命名它。
|
||||
`PostToolUse` 以及 `PermissionRequest` 载荷。不要假设未来所有
|
||||
Codex 钩子事件都会成为 OpenClaw 插件界面,除非运行时合约明确
|
||||
命名了它。
|
||||
|
||||
对于 `PermissionRequest`,只有在策略作出决定时,OpenClaw 才会返回明确的允许或拒绝
|
||||
决策。无决策结果并不等于允许。Codex 会将其视为没有
|
||||
钩子决策,并继续走它自己的 guardian 或用户审批路径。
|
||||
对于 `PermissionRequest`,仅当策略做出决定时,OpenClaw 才会返回显式允许或拒绝
|
||||
决定。无决定结果并不等于允许。Codex 会将其视为没有
|
||||
钩子决定,并继续走它自己的 guardian 或用户审批路径。
|
||||
|
||||
当 Codex 将 `_meta.codex_approval_kind` 标记为
|
||||
`"mcp_tool_call"` 时,Codex MCP 工具审批征询会通过 OpenClaw 的插件
|
||||
审批流进行路由。Codex 的 `request_user_input` 提示会被发送回
|
||||
发起的聊天中,而下一个排队的后续消息会回答该原生
|
||||
服务器请求,而不是被作为额外上下文引导。其他 MCP 征询
|
||||
请求仍会以关闭失败方式处理。
|
||||
审批流程进行路由。Codex `request_user_input` 提示会被发送回
|
||||
发起聊天,而下一个排队的后续消息会回答该原生
|
||||
服务器请求,而不是作为额外上下文被引导处理。其他 MCP 征询
|
||||
请求仍然会以失败关闭。
|
||||
|
||||
当所选模型使用 Codex harness 时,原生线程压缩会委托给
|
||||
Codex app-server。OpenClaw 会保留一个转录镜像,用于渠道历史记录、
|
||||
搜索、`/new`、`/reset`,以及未来的模型或 harness 切换。该
|
||||
镜像包括用户提示词、最终助手文本,以及在 app-server 发出时的轻量级 Codex
|
||||
推理或计划记录。目前,OpenClaw 只记录原生压缩的开始和完成信号。
|
||||
它尚未暴露人类可读的压缩摘要,也尚未提供一份可审计的条目列表,
|
||||
说明 Codex 在压缩后保留了哪些内容。
|
||||
当所选模型使用 Codex harness 时,原生线程压缩会委托给 Codex app-server。OpenClaw 会保留一个转录镜像,用于渠道历史、搜索、`/new`、`/reset`,以及未来的模型或 harness 切换。该镜像包含用户提示、最终助手文本,以及当 app-server 发出时的轻量级 Codex reasoning 或计划记录。目前,OpenClaw 仅记录原生压缩开始和完成信号。它尚未公开人类可读的压缩摘要,也尚未提供 Codex 在压缩后保留了哪些条目的可审计列表。
|
||||
|
||||
由于 Codex 拥有规范的原生线程,`tool_result_persist` 目前不会
|
||||
重写 Codex 原生工具结果记录。它仅在
|
||||
OpenClaw 正在写入 OpenClaw 自有会话转录工具结果时才会生效。
|
||||
由于 Codex 拥有规范的原生线程,`tool_result_persist` 当前不会重写 Codex 原生工具结果记录。它仅在 OpenClaw 正在写入由 OpenClaw 拥有的会话转录工具结果时生效。
|
||||
|
||||
媒体生成不需要 PI。图像、视频、音乐、PDF、TTS 以及媒体理解
|
||||
仍会继续使用匹配的提供商/模型设置,例如
|
||||
`agents.defaults.imageGenerationModel`、`videoGenerationModel`、`pdfModel` 和
|
||||
`messages.tts`。
|
||||
媒体生成不需要 PI。图像、视频、音乐、PDF、TTS 和媒体理解仍会继续使用匹配的 provider/模型设置,例如 `agents.defaults.imageGenerationModel`、`videoGenerationModel`、`pdfModel` 和 `messages.tts`。
|
||||
|
||||
## 故障排除
|
||||
|
||||
**Codex 没有显示为普通的 `/model` 提供商:** 这对
|
||||
新配置来说是预期行为。请选择一个 `openai/gpt-*` 模型,并设置
|
||||
`embeddedHarness.runtime: "codex"`(或使用旧版 `codex/*` 引用),启用
|
||||
**Codex 没有作为普通 `/model` provider 出现:** 对于新配置,这是预期行为。请选择一个 `openai/gpt-*` 模型,并设置
|
||||
`agentRuntime.id: "codex"`(或使用旧版 `codex/*` 引用),启用
|
||||
`plugins.entries.codex.enabled`,并检查 `plugins.allow` 是否排除了
|
||||
`codex`。
|
||||
|
||||
**OpenClaw 使用了 PI 而不是 Codex:** `runtime: "auto"` 在没有
|
||||
Codex harness 认领该运行时,仍然会使用 PI 作为兼容后端。测试时请设置
|
||||
`embeddedHarness.runtime: "codex"` 来强制选择 Codex。
|
||||
强制 Codex 运行时现在会直接失败,而不是回退到 PI,除非你
|
||||
显式设置了 `embeddedHarness.fallback: "pi"`。一旦选中了 Codex app-server,
|
||||
其失败会直接暴露出来,不需要额外回退配置。
|
||||
**OpenClaw 使用了 PI 而不是 Codex:** `agentRuntime.id: "auto"` 在没有 Codex harness 声明接管运行时,仍可能使用 PI 作为兼容后端。测试时请设置
|
||||
`agentRuntime.id: "codex"` 以强制选择 Codex。现在,强制的 Codex 运行时在失败时会直接报错,而不是回退到 PI,除非你显式设置
|
||||
`agentRuntime.fallback: "pi"`。一旦选中了 Codex app-server,
|
||||
它的失败会直接暴露出来,不需要额外的回退配置。
|
||||
|
||||
**app-server 被拒绝:** 请升级 Codex,使 app-server 握手
|
||||
报告的版本为 `0.125.0` 或更高。相同版本号的预发布版本或带构建后缀的
|
||||
版本,例如 `0.125.0-alpha.2` 或 `0.125.0+custom`,也会被拒绝,因为
|
||||
OpenClaw 测试所依据的协议最低版本是稳定版 `0.125.0`。
|
||||
报告版本 `0.125.0` 或更高。相同版本号的预发布版或带构建后缀的
|
||||
版本,例如 `0.125.0-alpha.2` 或 `0.125.0+custom`,都会被拒绝,因为 OpenClaw 测试的是稳定版 `0.125.0` 这一协议下限。
|
||||
|
||||
**模型发现很慢:** 降低 `plugins.entries.codex.config.discovery.timeoutMs`
|
||||
或禁用发现。
|
||||
|
||||
**WebSocket 传输立即失败:** 请检查 `appServer.url`、`authToken`,
|
||||
并确认远程 app-server 使用的是相同版本的 Codex app-server 协议。
|
||||
以及远程 app-server 是否使用相同版本的 Codex app-server 协议。
|
||||
|
||||
**非 Codex 模型使用了 PI:** 除非你为该智能体强制设置了
|
||||
`embeddedHarness.runtime: "codex"`,或选择了旧版
|
||||
`codex/*` 引用,否则这是预期行为。普通的 `openai/gpt-*` 和其他提供商引用
|
||||
在 `auto` 模式下会继续使用各自的常规提供商路径。如果你强制设置了
|
||||
`runtime: "codex"`,则该智能体的每一个嵌入式回合
|
||||
都必须是受 Codex 支持的 OpenAI 模型。
|
||||
**非 Codex 模型使用了 PI:** 这是预期行为,除非你为该智能体强制设置了
|
||||
`agentRuntime.id: "codex"`,或选择了旧版
|
||||
`codex/*` 引用。在 `auto` 模式下,普通 `openai/gpt-*` 和其他 provider 引用会保留在各自正常的
|
||||
provider 路径上。如果你强制设置 `agentRuntime.id: "codex"`,该智能体的每一个嵌入式
|
||||
回合都必须是 Codex 支持的 OpenAI 模型。
|
||||
|
||||
## 相关内容
|
||||
|
||||
@ -808,6 +771,6 @@ OpenClaw 测试所依据的协议最低版本是稳定版 `0.125.0`。
|
||||
- [模型提供商](/zh-CN/concepts/model-providers)
|
||||
- [OpenAI provider](/zh-CN/providers/openai)
|
||||
- [Status](/zh-CN/cli/status)
|
||||
- [Plugin hooks](/zh-CN/plugins/hooks)
|
||||
- [插件钩子](/zh-CN/plugins/hooks)
|
||||
- [配置参考](/zh-CN/gateway/configuration-reference)
|
||||
- [测试](/zh-CN/help/testing-live#live-codex-app-server-harness-smoke)
|
||||
|
||||
@ -1,39 +1,39 @@
|
||||
---
|
||||
read_when:
|
||||
- 你维护一个 OpenClaw 插件
|
||||
- 你看到一条插件兼容性警告
|
||||
- 你正在规划插件 SDK 或清单迁移
|
||||
- 你在维护一个 OpenClaw 插件。
|
||||
- 你看到了插件兼容性警告。
|
||||
- 你正在规划插件 SDK 或清单迁移。
|
||||
summary: 插件兼容性契约、弃用元数据和迁移预期
|
||||
title: 插件兼容性
|
||||
x-i18n:
|
||||
generated_at: "2026-04-25T17:39:04Z"
|
||||
generated_at: "2026-04-26T07:50:08Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 511bd12cff1e72a93091cbb1ac7d75377b0b9d2f016b55f4cdc77293f6172a00
|
||||
source_hash: 5b015e39981aab5e055529b72eb07e303116d6a6b5e583d2cd6a0273335669b1
|
||||
source_path: plugins/compatibility.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
OpenClaw 会在移除旧版插件契约之前,通过具名兼容适配器继续接线支持这些旧契约。这可以在 SDK、清单、设置、配置和智能体运行时契约演进期间,保护现有的内置插件和外部插件。
|
||||
OpenClaw 会在移除旧插件契约之前,先通过具名兼容性适配器继续接入这些旧契约。这样在 SDK、清单、设置、配置和 Agent Runtimes 契约演进期间,可以保护现有的内置插件和外部插件。
|
||||
|
||||
## 兼容性注册表
|
||||
|
||||
插件兼容性契约会在核心注册表 `src/plugins/compat/registry.ts` 中进行跟踪。
|
||||
|
||||
每条记录包含:
|
||||
每条记录都包含:
|
||||
|
||||
- 稳定的兼容性代码
|
||||
- 一个稳定的兼容性代码
|
||||
- 状态:`active`、`deprecated`、`removal-pending` 或 `removed`
|
||||
- 所有者:SDK、配置、设置、渠道、提供商、插件执行、智能体运行时或核心
|
||||
- 归属方:SDK、配置、设置、渠道、提供商、插件执行、Agent Runtimes 或 core
|
||||
- 适用时的引入日期和弃用日期
|
||||
- 替代方案指引
|
||||
- 覆盖旧行为和新行为的文档、诊断信息和测试
|
||||
|
||||
该注册表是维护者规划和未来插件检查器检查的来源。如果面向插件的行为发生变化,请在添加适配器的同一项变更中新增或更新兼容性记录。
|
||||
该注册表是维护者规划和未来插件检查器检查的依据。如果插件面向的行为发生变化,请在添加适配器的同一变更中添加或更新兼容性记录。
|
||||
|
||||
## 插件检查器包
|
||||
|
||||
插件检查器应位于核心 OpenClaw 仓库之外,作为一个独立的软件包/仓库,并基于带版本的兼容性契约和清单契约构建。
|
||||
插件检查器应位于 OpenClaw core 仓库之外,作为一个单独的包/代码仓库,并以带版本的兼容性契约和清单契约为基础。
|
||||
|
||||
首日 CLI 应为:
|
||||
|
||||
@ -43,45 +43,45 @@ openclaw-plugin-inspector ./my-plugin
|
||||
|
||||
它应输出:
|
||||
|
||||
- 清单/模式验证
|
||||
- 清单/schema 验证
|
||||
- 正在检查的契约兼容性版本
|
||||
- 安装/来源元数据检查
|
||||
- 冷路径导入检查
|
||||
- 弃用和兼容性警告
|
||||
|
||||
在 CI 注释中使用 `--json` 获取稳定的机器可读输出。OpenClaw 核心应暴露检查器可使用的契约和夹具,但不应从主 `openclaw` 包发布该检查器二进制文件。
|
||||
在 CI 注释中使用稳定的机器可读输出时,请使用 `--json`。OpenClaw core 应公开检查器可使用的契约和夹具,但不应从主 `openclaw` 包中发布该检查器二进制文件。
|
||||
|
||||
## 弃用策略
|
||||
|
||||
OpenClaw 不应在引入某个已记录插件契约替代方案的同一版本中移除该契约。
|
||||
OpenClaw 不应在引入替代方案的同一版本中移除已文档化的插件契约。
|
||||
|
||||
迁移顺序如下:
|
||||
|
||||
1. 添加新契约。
|
||||
2. 通过具名兼容适配器继续接线保留旧行为。
|
||||
3. 当插件作者可以采取行动时,发出诊断信息或警告。
|
||||
2. 通过具名兼容性适配器保留旧行为接入。
|
||||
3. 在插件作者可以采取行动时发出诊断信息或警告。
|
||||
4. 记录替代方案和时间线。
|
||||
5. 测试旧路径和新路径。
|
||||
6. 等待已公布的迁移窗口结束。
|
||||
7. 仅在获得明确的破坏性发布批准后移除。
|
||||
5. 对旧路径和新路径都进行测试。
|
||||
6. 等待已公告的迁移窗口期结束。
|
||||
7. 仅在获得明确的破坏性发布批准后再移除。
|
||||
|
||||
已弃用记录必须包含警告开始日期、替代方案、文档链接,以及在已知时的目标移除日期。
|
||||
已弃用记录必须包含警告开始日期、替代方案、文档链接,以及已知时的目标移除日期。
|
||||
|
||||
## 当前兼容性领域
|
||||
|
||||
当前兼容性记录包括:
|
||||
|
||||
- 旧版宽泛 SDK 导入,例如 `openclaw/plugin-sdk/compat`
|
||||
- 旧版仅钩子插件形态和 `before_agent_start`
|
||||
- 旧版仅 hook 的插件形态和 `before_agent_start`
|
||||
- 内置插件允许列表和启用行为
|
||||
- 旧版 provider/渠道环境变量清单元数据
|
||||
- 正在由清单贡献所有权替代的激活提示
|
||||
- `embeddedHarness` 和 `agent-harness` 命名别名,在公共命名向 `agentRuntime` 迁移期间继续保留
|
||||
- 在以注册表优先的 `channelConfigs` 元数据落地期间,生成的内置渠道配置元数据回退
|
||||
- 持久化的插件注册表禁用环境变量,同时修复流程会将运维人员迁移到 `openclaw plugins registry --refresh` 和 `openclaw doctor --fix`
|
||||
- 旧版 provider/channel 环境变量清单元数据
|
||||
- 正在由清单贡献归属替代的激活提示
|
||||
- 在 Doctor 将运维人员迁移到 `agentRuntime` 期间保留的旧版运行时策略配置键
|
||||
- 在 registry-first 的 `channelConfigs` 元数据落地期间,生成的内置渠道配置元数据后备逻辑
|
||||
- 在修复流程将运维人员迁移到 `openclaw plugins registry --refresh` 和 `openclaw doctor --fix` 期间,持久化的插件注册表禁用环境变量
|
||||
|
||||
新插件代码应优先使用注册表和特定迁移指南中列出的替代方案。现有插件可以继续使用兼容路径,直到文档、诊断信息和发布说明公布移除窗口。
|
||||
新插件代码应优先使用注册表和特定迁移指南中列出的替代方案。现有插件可以继续使用兼容路径,直到文档、诊断信息和发布说明公告移除窗口期。
|
||||
|
||||
## 发布说明
|
||||
|
||||
发布说明应包含即将到来的插件弃用事项,并附上目标日期和迁移文档链接。这类警告必须在某个兼容路径转为 `removal-pending` 或 `removed` 之前发出。
|
||||
发布说明应包含即将到来的插件弃用项,并附上目标日期和迁移文档链接。这个警告必须在兼容路径进入 `removal-pending` 或 `removed` 之前发出。
|
||||
|
||||
@ -1,61 +1,59 @@
|
||||
---
|
||||
read_when:
|
||||
- 你正在更改嵌入式智能体运行时或 harness 注册表
|
||||
- 你正在从内置或受信任的插件注册一个智能体 harness
|
||||
- 你需要了解 Codex 插件与模型提供商之间的关系
|
||||
- 你正在更改内嵌智能体运行时或 harness 注册表。
|
||||
- 你正在从内置插件或受信任插件注册一个智能体 harness。
|
||||
- 你需要了解 Codex 插件与模型提供商之间的关系。
|
||||
sidebarTitle: Agent Harness
|
||||
summary: 用于替换底层嵌入式智能体执行器的插件实验性 SDK 接口
|
||||
summary: 用于替换底层内嵌智能体执行器的插件实验性 SDK 表面
|
||||
title: Agent harness plugins
|
||||
x-i18n:
|
||||
generated_at: "2026-04-25T23:10:32Z"
|
||||
generated_at: "2026-04-26T07:50:26Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 623d4d9b6bfe6f0746e2f72e8c221148f0aacc10f1d9de68e3ab9028d750ba34
|
||||
source_hash: 340fc6207dabc6ffe7ffb9c07ca9e80e76f1034d4978c41279dc826468302181
|
||||
source_path: plugins/sdk-agent-harness.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
**智能体 harness** 是为单次已准备好的 OpenClaw 智能体轮次提供底层执行的组件。它不是模型提供商,不是渠道,也不是工具注册表。
|
||||
关于面向用户的心智模型,请参见 [Agent Runtimes](/zh-CN/concepts/agent-runtimes)。
|
||||
**智能体 harness** 是用于执行一次已准备好的 OpenClaw 智能体轮次的底层执行器。它不是模型提供商,不是渠道,也不是工具注册表。关于面向用户的心智模型,请参见 [Agent Runtimes](/zh-CN/concepts/agent-runtimes)。
|
||||
|
||||
仅对内置或受信任的原生插件使用此接口。该契约仍处于实验阶段,因为参数类型有意映射当前的嵌入式运行器。
|
||||
仅应将此表面用于内置插件或受信任的原生插件。该契约目前仍属实验性,因为其参数类型有意镜像当前的内嵌运行器。
|
||||
|
||||
## 何时使用 harness
|
||||
|
||||
当某个模型家族拥有自己的原生会话运行时,而常规 OpenClaw 提供商传输抽象并不适合时,请注册一个智能体 harness。
|
||||
当某个模型家族拥有自己的原生会话运行时,而普通 OpenClaw 提供商传输抽象并不适合时,请注册一个智能体 harness。
|
||||
|
||||
示例:
|
||||
|
||||
- 拥有线程和压缩管理能力的原生编码智能体服务器
|
||||
- 必须流式传输原生计划 / 推理 / 工具事件的本地 CLI 或守护进程
|
||||
- 除了 OpenClaw 会话转录记录之外,还需要自己的恢复 id 的模型运行时
|
||||
- 拥有线程和压缩逻辑的原生 coding-agent 服务器
|
||||
- 必须流式传输原生计划/推理/工具事件的本地 CLI 或守护进程
|
||||
- 除 OpenClaw 会话转录之外,还需要自己的恢复 ID 的模型运行时
|
||||
|
||||
不要仅为了添加一个新的 LLM API 而注册 harness。对于常规的 HTTP 或 WebSocket 模型 API,请构建一个 [提供商插件](/zh-CN/plugins/sdk-provider-plugins)。
|
||||
**不要**仅为了接入新的 LLM API 而注册 harness。对于普通的 HTTP 或 WebSocket 模型 API,请构建一个[提供商插件](/zh-CN/plugins/sdk-provider-plugins)。
|
||||
|
||||
## 核心仍负责的内容
|
||||
## core 仍然负责的内容
|
||||
|
||||
在选择 harness 之前,OpenClaw 已经解析完成:
|
||||
在选择 harness 之前,OpenClaw 已经解析好以下内容:
|
||||
|
||||
- provider 和 model
|
||||
- 提供商和模型
|
||||
- 运行时认证状态
|
||||
- 思考级别和上下文预算
|
||||
- OpenClaw 转录记录 / 会话文件
|
||||
- OpenClaw 转录/会话文件
|
||||
- 工作区、沙箱和工具策略
|
||||
- 渠道回复回调和流式传输回调
|
||||
- 模型回退和实时模型切换策略
|
||||
|
||||
这种划分是有意设计的。harness 执行的是一次已准备好的尝试;它不会选择提供商、替换渠道投递,或静默切换模型。
|
||||
这种划分是有意为之。harness 执行的是一次已准备好的尝试;它不负责选择提供商、不替代渠道投递,也不会静默切换模型。
|
||||
|
||||
该已准备好的尝试还包括 `params.runtimePlan`,这是由 OpenClaw 持有的一组运行时决策策略包,这些策略必须在 PI 和原生 harness 之间保持共享:
|
||||
该已准备好的尝试还包含 `params.runtimePlan`,这是一个由 OpenClaw 持有的运行时策略包,用于那些必须在 PI 和原生 harness 之间共享的运行时决策:
|
||||
|
||||
- `runtimePlan.tools.normalize(...)` 和
|
||||
`runtimePlan.tools.logDiagnostics(...)`,用于提供商感知的工具 schema 策略
|
||||
- `runtimePlan.transcript.resolvePolicy(...)`,用于转录记录清理和工具调用修复策略
|
||||
- `runtimePlan.tools.normalize(...)` 和 `runtimePlan.tools.logDiagnostics(...)`,用于 provider 感知的工具 schema 策略
|
||||
- `runtimePlan.transcript.resolvePolicy(...)`,用于转录净化和工具调用修复策略
|
||||
- `runtimePlan.delivery.isSilentPayload(...)`,用于共享的 `NO_REPLY` 和媒体投递抑制
|
||||
- `runtimePlan.outcome.classifyRunResult(...)`,用于模型回退分类
|
||||
- `runtimePlan.observability`,用于已解析的 provider / model / harness 元数据
|
||||
- `runtimePlan.observability`,用于已解析的 provider/模型/harness 元数据
|
||||
|
||||
harness 可以使用该计划来做出需要与 PI 行为一致的决策,但仍应将其视为由宿主持有的尝试状态。不要修改它,也不要用它在单次轮次中切换 provider / model。
|
||||
harness 可以在需要与 PI 行为保持一致的决策中使用该 plan,但仍应将其视为由宿主持有的尝试状态。不要修改它,也不要用它在单个轮次内切换提供商/模型。
|
||||
|
||||
## 注册 harness
|
||||
|
||||
@ -67,7 +65,7 @@ import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
||||
|
||||
const myHarness: AgentHarness = {
|
||||
id: "my-harness",
|
||||
label: "My native agent harness",
|
||||
label: "我的原生智能体 harness",
|
||||
|
||||
supports(ctx) {
|
||||
return ctx.provider === "my-provider"
|
||||
@ -76,9 +74,9 @@ const myHarness: AgentHarness = {
|
||||
},
|
||||
|
||||
async runAttempt(params) {
|
||||
// Start or resume your native thread.
|
||||
// Use params.prompt, params.tools, params.images, params.onPartialReply,
|
||||
// params.onAgentEvent, and the other prepared attempt fields.
|
||||
// 启动或恢复你的原生线程。
|
||||
// 使用 params.prompt、params.tools、params.images、params.onPartialReply、
|
||||
// params.onAgentEvent,以及其他已准备好的尝试字段。
|
||||
return await runMyNativeTurn(params);
|
||||
},
|
||||
};
|
||||
@ -86,7 +84,7 @@ const myHarness: AgentHarness = {
|
||||
export default definePluginEntry({
|
||||
id: "my-native-agent",
|
||||
name: "My Native Agent",
|
||||
description: "Runs selected models through a native agent daemon.",
|
||||
description: "通过原生智能体守护进程运行选定模型。",
|
||||
register(api) {
|
||||
api.registerAgentHarness(myHarness);
|
||||
},
|
||||
@ -95,91 +93,83 @@ export default definePluginEntry({
|
||||
|
||||
## 选择策略
|
||||
|
||||
OpenClaw 会在 provider / model 解析完成后选择一个 harness:
|
||||
OpenClaw 会在提供商/模型解析完成后选择 harness:
|
||||
|
||||
1. 现有会话中已记录的 harness id 优先生效,因此配置 / 环境变量变更不会将该转录记录热切换到另一个运行时。
|
||||
2. `OPENCLAW_AGENT_RUNTIME=<id>` 会为尚未固定的会话强制指定该 id 对应的已注册 harness。
|
||||
1. 现有会话中记录的 harness ID 优先,因此配置/环境变量变更不会将该转录热切换到另一个运行时。
|
||||
2. `OPENCLAW_AGENT_RUNTIME=<id>` 会为尚未固定的会话强制使用具有该 ID 的已注册 harness。
|
||||
3. `OPENCLAW_AGENT_RUNTIME=pi` 会强制使用内置的 PI harness。
|
||||
4. `OPENCLAW_AGENT_RUNTIME=auto` 会让已注册 harness 判断自己是否支持已解析的 provider / model。
|
||||
5. 如果没有匹配的已注册 harness,除非禁用了 PI 回退,否则 OpenClaw 会使用 PI。
|
||||
4. `OPENCLAW_AGENT_RUNTIME=auto` 会让已注册的 harness 询问自己是否支持已解析的提供商/模型。
|
||||
5. 如果没有匹配的已注册 harness,OpenClaw 会使用 PI,除非 PI 回退已禁用。
|
||||
|
||||
插件 harness 失败会表现为运行失败。在 `auto` 模式下,仅当没有任何已注册插件 harness 支持已解析的 provider / model 时,才会使用 PI 回退。一旦某个插件 harness 已认领该次运行,OpenClaw 就不会再通过 PI 重放同一轮次,因为这可能改变认证 / 运行时语义,或导致副作用重复发生。
|
||||
插件 harness 失败会表现为运行失败。在 `auto` 模式下,仅当没有任何已注册插件 harness 支持已解析的提供商/模型时,才会使用 PI 回退。一旦某个插件 harness 已经接管一次运行,OpenClaw 不会再通过 PI 重放同一轮次,因为那可能改变认证/运行时语义,或造成副作用重复执行。
|
||||
|
||||
所选的 harness id 会在一次嵌入式运行后与会话 id 一起持久化。对于在 harness 固定机制引入之前创建的旧会话,只要它们已有转录历史,就会被视为固定到 PI。若要在 PI 与原生插件 harness 之间切换,请使用新的 / 已重置的会话。`/status` 会在 `Fast` 旁边显示非默认 harness id,例如 `codex`;PI 因为是默认兼容路径而保持隐藏。如果所选 harness 出乎你的预期,请启用 `agents/harness` 调试日志,并检查 Gateway 网关中的结构化 `agent harness selected` 记录。该记录包含所选 harness id、选择原因、运行时 / 回退策略,以及在 `auto` 模式下每个插件候选项的支持结果。
|
||||
选中的 harness ID 会在一次内嵌运行后与会话 ID 一起持久化。对于在 harness 固定机制引入前创建的旧会话,只要它们已有转录历史,就会被视为已固定到 PI。要在 PI 与原生插件 harness 之间切换,请使用新的/已重置的会话。`/status` 会在 `Fast` 旁边显示非默认 harness ID,例如 `codex`;PI 因为是默认兼容路径,所以会隐藏。如果选中的 harness 出乎你的意料,请启用 `agents/harness` 调试日志,并检查 Gateway 网关中的结构化 `agent harness selected` 记录。它包含所选 harness ID、选择原因、运行时/回退策略,以及在 `auto` 模式下每个插件候选项的支持结果。
|
||||
|
||||
内置 Codex 插件将 `codex` 注册为其 harness id。核心将其视为普通的插件 harness id;Codex 专属别名应由插件或运维配置处理,而不应放入共享运行时选择器中。
|
||||
内置 Codex 插件将 `codex` 注册为其 harness ID。core 将其视为普通的插件 harness ID;Codex 特定别名应放在插件或运维配置中,而不应放在共享运行时选择器中。
|
||||
|
||||
## provider 与 harness 配对
|
||||
## 提供商与 harness 配对
|
||||
|
||||
大多数 harness 也应同时注册一个 provider。provider 让模型引用、认证状态、模型元数据和 `/model` 选择对 OpenClaw 的其余部分可见。然后,harness 在 `supports(...)` 中认领该 provider。
|
||||
大多数 harness 也应注册一个 provider。provider 会让模型引用、认证状态、模型元数据和 `/model` 选择对 OpenClaw 其余部分可见。然后 harness 再在 `supports(...)` 中声明自己接管该 provider。
|
||||
|
||||
内置 Codex 插件遵循这种模式:
|
||||
内置 Codex 插件遵循这一模式:
|
||||
|
||||
- 首选的用户模型引用:`openai/gpt-5.5` 加上
|
||||
`embeddedHarness.runtime: "codex"`
|
||||
- 兼容性引用:旧版 `codex/gpt-*` 引用仍然可接受,但新配置不应将它们作为常规 provider / model 引用使用
|
||||
- harness id:`codex`
|
||||
- 认证:使用合成 provider 可用性,因为 Codex harness 持有原生 Codex 登录 / 会话
|
||||
- app-server 请求:OpenClaw 将裸模型 id 发送给 Codex,并由 harness 与原生 app-server 协议通信
|
||||
- 首选用户模型引用:`openai/gpt-5.5` 加上 `agentRuntime.id: "codex"`
|
||||
- 兼容性引用:旧版 `codex/gpt-*` 引用仍然可用,但新配置不应将其用作普通 provider/模型引用
|
||||
- harness ID:`codex`
|
||||
- 认证:合成 provider 可用性,因为 Codex harness 拥有原生 Codex 登录/会话
|
||||
- app-server 请求:OpenClaw 向 Codex 发送裸模型 ID,并由 harness 与原生 app-server 协议通信
|
||||
|
||||
Codex 插件是增量式的。普通 `openai/gpt-*` 引用会继续使用常规 OpenClaw provider 路径,除非你通过 `embeddedHarness.runtime: "codex"` 强制使用 Codex harness。较旧的 `codex/gpt-*` 引用仍会出于兼容性原因选择 Codex provider 和 harness。
|
||||
Codex 插件是增量式的。普通 `openai/gpt-*` 引用仍继续使用普通 OpenClaw provider 路径,除非你通过 `agentRuntime.id: "codex"` 强制使用 Codex harness。旧版 `codex/gpt-*` 引用仍会为兼容性目的选择 Codex provider 和 harness。
|
||||
|
||||
有关运维设置、模型前缀示例和仅适用于 Codex 的配置,请参见
|
||||
[Codex harness](/zh-CN/plugins/codex-harness)。
|
||||
有关运维设置、模型前缀示例和仅 Codex 配置,请参见 [Codex harness](/zh-CN/plugins/codex-harness)。
|
||||
|
||||
OpenClaw 要求 Codex app-server 版本为 `0.125.0` 或更高。Codex 插件会检查 app-server 初始化握手,并阻止较旧或未提供版本信息的服务器,以确保 OpenClaw 仅在其已测试过的协议接口上运行。`0.125.0` 的最低要求包含了在 Codex `0.124.0` 中引入的原生 MCP hook 负载支持,同时将 OpenClaw 固定在更新且已验证稳定的版本线上。
|
||||
OpenClaw 要求 Codex app-server 为 `0.125.0` 或更高版本。Codex 插件会检查 app-server 初始化握手,并阻止较旧或未带版本号的服务器,以确保 OpenClaw 仅在其已测试过的协议表面上运行。`0.125.0` 这一最低版本包含了在 Codex `0.124.0` 中引入的原生 MCP hook 载荷支持,同时也将 OpenClaw 固定在更新且已验证的稳定版本线上。
|
||||
|
||||
### 工具结果中间件
|
||||
|
||||
当内置插件在其 manifest 的 `contracts.agentToolResultMiddleware` 中声明目标运行时 id 时,可以通过
|
||||
`api.registerAgentToolResultMiddleware(...)` 挂接与运行时无关的工具结果中间件。这个受信任接口用于异步工具结果转换,这些转换必须在 PI 或 Codex 将工具输出回送给模型之前运行。
|
||||
当内置插件在其清单中的 `contracts.agentToolResultMiddleware` 声明了目标运行时 ID 时,它们可以通过 `api.registerAgentToolResultMiddleware(...)` 附加运行时中立的工具结果中间件。这个受信任接缝适用于那些必须在 PI 或 Codex 将工具输出回传给模型之前运行的异步工具结果转换。
|
||||
|
||||
旧版内置插件仍可使用
|
||||
`api.registerCodexAppServerExtensionFactory(...)` 来实现仅适用于 Codex app-server 的中间件,但新的结果转换应使用与运行时无关的 API。
|
||||
仅适用于 Pi 的 `api.registerEmbeddedExtensionFactory(...)` hook 已被移除;Pi 的工具结果转换必须使用与运行时无关的中间件。
|
||||
旧版内置插件仍可使用 `api.registerCodexAppServerExtensionFactory(...)` 处理仅适用于 Codex app-server 的中间件,但新的结果转换应使用运行时中立 API。仅适用于 Pi 的 `api.registerEmbeddedExtensionFactory(...)` hook 已被移除;Pi 工具结果转换必须使用运行时中立中间件。
|
||||
|
||||
### 终态结果分类
|
||||
|
||||
拥有自己协议投影的原生 harness 可以在已完成轮次未产生可见助手文本时,使用来自
|
||||
`openclaw/plugin-sdk/agent-harness-runtime` 的
|
||||
`classifyAgentHarnessTerminalOutcome(...)`。该辅助函数会返回 `empty`、`reasoning-only` 或 `planning-only`,以便 OpenClaw 的回退策略决定是否在其他模型上重试。它有意不对提示错误、进行中的轮次,以及像 `NO_REPLY` 这样有意静默的回复进行分类。
|
||||
拥有自身协议投影的原生 harness,可在一次已完成轮次未产生可见 assistant 文本时,使用 `openclaw/plugin-sdk/agent-harness-runtime` 中的 `classifyAgentHarnessTerminalOutcome(...)`。该辅助函数会返回 `empty`、`reasoning-only` 或 `planning-only`,以便 OpenClaw 的回退策略判断是否应在不同模型上重试。它有意不对提示错误、进行中的轮次,以及诸如 `NO_REPLY` 之类的有意静默回复进行分类。
|
||||
|
||||
### 原生 Codex harness 模式
|
||||
|
||||
内置的 `codex` harness 是嵌入式 OpenClaw 智能体轮次的原生 Codex 模式。请先启用内置 `codex` 插件;如果你的配置使用了限制性 allowlist,请在 `plugins.allow` 中包含 `codex`。原生 app-server 配置应使用 `openai/gpt-*` 并搭配 `embeddedHarness.runtime: "codex"`。如果要通过 PI 使用 Codex OAuth,请改用 `openai-codex/*`。旧版 `codex/*` 模型引用仍保留为原生 harness 的兼容性别名。
|
||||
内置的 `codex` harness 是内嵌 OpenClaw 智能体轮次的原生 Codex 模式。请先启用内置 `codex` 插件;如果你的配置使用了限制性允许列表,还需要将 `codex` 加入 `plugins.allow`。原生 app-server 配置应使用 `openai/gpt-*` 搭配 `agentRuntime.id: "codex"`。如果要通过 PI 使用 Codex OAuth,请改用 `openai-codex/*`。旧版 `codex/*` 模型引用仍作为原生 harness 的兼容别名保留。
|
||||
|
||||
当此模式运行时,Codex 持有原生线程 id、恢复行为、压缩和 app-server 执行。OpenClaw 仍持有聊天渠道、可见转录镜像、工具策略、审批、媒体投递和会话选择。当你需要证明只有 Codex app-server 路径可以认领该次运行时,请使用不带 `fallback` 覆盖项的 `embeddedHarness.runtime: "codex"`。显式插件运行时默认已经是失败即关闭。只有在你有意希望 PI 处理缺失的 harness 选择时,才设置 `fallback: "pi"`。Codex app-server 故障本身已经会直接失败,而不是通过 PI 重试。
|
||||
在此模式下运行时,Codex 负责原生线程 ID、恢复行为、压缩和 app-server 执行。OpenClaw 仍负责聊天渠道、可见转录镜像、工具策略、审批、媒体投递和会话选择。当你需要证明只有 Codex app-server 路径才能接管该次运行时,请使用不带 `fallback` 覆盖的 `agentRuntime.id: "codex"`。显式插件运行时默认已经是失败即关闭。只有在你明确希望由 PI 处理缺失的 harness 选择时,才设置 `fallback: "pi"`。Codex app-server 失败本来就会直接失败,而不会通过 PI 重试。
|
||||
|
||||
## 禁用 PI 回退
|
||||
|
||||
默认情况下,OpenClaw 通过将 `agents.defaults.embeddedHarness`
|
||||
设置为 `{ runtime: "auto", fallback: "pi" }` 来运行嵌入式智能体。在 `auto` 模式下,已注册的插件 harness 可以认领 provider / model 配对。如果没有任何匹配项,OpenClaw 会回退到 PI。
|
||||
默认情况下,OpenClaw 会以 `agents.defaults.agentRuntime` 设置为 `{ id: "auto", fallback: "pi" }` 来运行内嵌智能体。在 `auto` 模式下,已注册的插件 harness 可以接管某个 provider/模型组合。如果没有匹配项,OpenClaw 会回退到 PI。
|
||||
|
||||
在 `auto` 模式下,当你需要在缺少插件 harness 选择时直接失败而不是使用 PI 时,请设置 `fallback: "none"`。像 `runtime: "codex"` 这样的显式插件运行时,默认已经是失败即关闭,除非在同一配置或环境覆盖范围中设置了 `fallback: "pi"`。已选中的插件 harness 一旦失败,总是会直接失败。这不会阻止显式的 `runtime: "pi"` 或 `OPENCLAW_AGENT_RUNTIME=pi`。
|
||||
在 `auto` 模式下,如果你需要在没有插件 harness 选中时直接失败,而不是使用 PI,请设置 `fallback: "none"`。显式插件运行时(如 `runtime: "codex"`)默认已经是失败即关闭,除非在同一配置或环境变量覆盖作用域中设置了 `fallback: "pi"`。已选中的插件 harness 失败总是会硬失败。这不会阻止显式 `runtime: "pi"` 或 `OPENCLAW_AGENT_RUNTIME=pi`。
|
||||
|
||||
对于仅使用 Codex 的嵌入式运行:
|
||||
对于仅使用 Codex 的内嵌运行:
|
||||
|
||||
```json
|
||||
{
|
||||
"agents": {
|
||||
"defaults": {
|
||||
"model": "openai/gpt-5.5",
|
||||
"embeddedHarness": {
|
||||
"runtime": "codex"
|
||||
"agentRuntime": {
|
||||
"id": "codex"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
如果你希望任意已注册的插件 harness 认领匹配的模型,但又不希望 OpenClaw 静默回退到 PI,请保持 `runtime: "auto"` 并禁用回退:
|
||||
如果你希望任何已注册插件 harness 都能接管匹配的模型,但又绝不希望 OpenClaw 静默回退到 PI,请保持 `runtime: "auto"` 并禁用回退:
|
||||
|
||||
```json
|
||||
{
|
||||
"agents": {
|
||||
"defaults": {
|
||||
"embeddedHarness": {
|
||||
"runtime": "auto",
|
||||
"agentRuntime": {
|
||||
"id": "auto",
|
||||
"fallback": "none"
|
||||
}
|
||||
}
|
||||
@ -187,14 +177,14 @@ OpenClaw 要求 Codex app-server 版本为 `0.125.0` 或更高。Codex 插件会
|
||||
}
|
||||
```
|
||||
|
||||
每个智能体的覆盖项使用相同结构:
|
||||
针对单个智能体的覆盖使用相同结构:
|
||||
|
||||
```json
|
||||
{
|
||||
"agents": {
|
||||
"defaults": {
|
||||
"embeddedHarness": {
|
||||
"runtime": "auto",
|
||||
"agentRuntime": {
|
||||
"id": "auto",
|
||||
"fallback": "pi"
|
||||
}
|
||||
},
|
||||
@ -202,8 +192,8 @@ OpenClaw 要求 Codex app-server 版本为 `0.125.0` 或更高。Codex 插件会
|
||||
{
|
||||
"id": "codex-only",
|
||||
"model": "openai/gpt-5.5",
|
||||
"embeddedHarness": {
|
||||
"runtime": "codex",
|
||||
"agentRuntime": {
|
||||
"id": "codex",
|
||||
"fallback": "none"
|
||||
}
|
||||
}
|
||||
@ -212,8 +202,7 @@ OpenClaw 要求 Codex app-server 版本为 `0.125.0` 或更高。Codex 插件会
|
||||
}
|
||||
```
|
||||
|
||||
`OPENCLAW_AGENT_RUNTIME` 仍会覆盖已配置的运行时。使用
|
||||
`OPENCLAW_AGENT_HARNESS_FALLBACK=none` 可通过环境变量禁用 PI 回退。
|
||||
`OPENCLAW_AGENT_RUNTIME` 仍会覆盖已配置运行时。使用 `OPENCLAW_AGENT_HARNESS_FALLBACK=none` 可通过环境变量禁用 PI 回退。
|
||||
|
||||
```bash
|
||||
OPENCLAW_AGENT_RUNTIME=codex \
|
||||
@ -221,35 +210,34 @@ OPENCLAW_AGENT_HARNESS_FALLBACK=none \
|
||||
openclaw gateway run
|
||||
```
|
||||
|
||||
在禁用回退后,如果所请求的 harness 未注册、不支持已解析的 provider / model,或在产生轮次副作用之前即失败,会话会提前失败。这对于仅使用 Codex 的部署,以及必须证明 Codex app-server 路径确实正在使用的实时测试来说,是有意设计的行为。
|
||||
在禁用回退后,如果请求的 harness 未注册、不支持已解析的 provider/模型,或在产生轮次副作用之前就失败了,会话就会提前失败。对于仅 Codex 部署,以及那些必须证明确实在使用 Codex app-server 路径的在线测试来说,这正是预期行为。
|
||||
|
||||
此设置仅控制嵌入式智能体 harness。它不会禁用图像、视频、音乐、TTS、PDF 或其他提供商特定模型路由。
|
||||
此设置仅控制内嵌智能体 harness。它不会禁用图像、视频、音乐、TTS、PDF 或其他特定 provider 的模型路由。
|
||||
|
||||
## 原生会话与转录镜像
|
||||
|
||||
harness 可以保留原生会话 id、线程 id 或守护进程端恢复令牌。请将这种绑定显式关联到 OpenClaw 会话,并继续将面向用户可见的助手 / 工具输出镜像到 OpenClaw 转录记录中。
|
||||
harness 可以保留一个原生会话 ID、线程 ID 或守护进程端恢复 token。请将这种绑定明确关联到 OpenClaw 会话,并持续将用户可见的 assistant/工具输出镜像到 OpenClaw 转录中。
|
||||
|
||||
OpenClaw 转录记录仍然是以下能力的兼容层:
|
||||
OpenClaw 转录仍然是以下场景的兼容层:
|
||||
|
||||
- 渠道可见的会话历史
|
||||
- 转录记录搜索与索引
|
||||
- 转录搜索和索引
|
||||
- 在后续轮次切回内置 PI harness
|
||||
- 通用的 `/new`、`/reset` 和会话删除行为
|
||||
- 通用 `/new`、`/reset` 和会话删除行为
|
||||
|
||||
如果你的 harness 存储了 sidecar 绑定,请实现 `reset(...)`,以便 OpenClaw 在所属 OpenClaw 会话被重置时清除它。
|
||||
如果你的 harness 存储了侧车绑定,请实现 `reset(...)`,以便 OpenClaw 在所属 OpenClaw 会话被重置时清除它。
|
||||
|
||||
## 工具和媒体结果
|
||||
|
||||
核心会构建 OpenClaw 工具列表,并将其传入已准备好的尝试。
|
||||
当 harness 执行动态工具调用时,请通过 harness 结果结构返回工具结果,而不是自行发送渠道媒体。
|
||||
core 会构建 OpenClaw 工具列表,并将其传入已准备好的尝试。当 harness 执行动态工具调用时,请通过 harness 结果结构返回工具结果,而不是自行发送渠道媒体。
|
||||
|
||||
这样可以让文本、图像、视频、音乐、TTS、审批以及消息工具输出与基于 PI 的运行保持在同一投递路径上。
|
||||
这样可以让文本、图像、视频、音乐、TTS、审批和消息工具输出,与基于 PI 的运行保持在同一投递路径上。
|
||||
|
||||
## 当前限制
|
||||
|
||||
- 公共导入路径是通用的,但某些 attempt / result 类型别名仍带有 `Pi` 名称,以保持兼容性。
|
||||
- 第三方 harness 安装仍处于实验阶段。在你确实需要原生会话运行时之前,请优先使用提供商插件。
|
||||
- 支持跨轮次切换 harness。不要在单次轮次进行到一半时切换 harness,尤其是在原生工具、审批、助手文本或消息发送已经开始之后。
|
||||
- 公共导入路径是通用的,但出于兼容性考虑,某些 attempt/result 类型别名仍然带有 `Pi` 名称。
|
||||
- 第三方 harness 安装仍属实验性。在你确实需要原生会话运行时之前,请优先使用提供商插件。
|
||||
- 支持跨轮次切换 harness。不要在单个轮次中途切换 harness,尤其是在原生工具、审批、assistant 文本或消息发送已经开始之后。
|
||||
|
||||
## 相关内容
|
||||
|
||||
|
||||
@ -1,25 +1,30 @@
|
||||
---
|
||||
read_when:
|
||||
- 你需要从插件调用核心辅助工具(TTS、STT、图像生成、Web 搜索、子智能体、节点)
|
||||
- 你想了解 `api.runtime` 暴露了哪些内容
|
||||
- 你正在从插件代码访问配置、智能体或媒体辅助工具
|
||||
sidebarTitle: Runtime Helpers
|
||||
summary: api.runtime —— 提供给插件的注入式运行时辅助工具
|
||||
title: 插件运行时辅助工具
|
||||
- 你需要从插件调用核心辅助函数(TTS、STT、图像生成、网络搜索、子智能体、节点)
|
||||
- 你想了解 `api.runtime` 暴露了什么
|
||||
- 你正在从插件代码访问配置、智能体或媒体辅助函数
|
||||
sidebarTitle: Runtime helpers
|
||||
summary: api.runtime —— 可供插件使用的注入式运行时辅助函数
|
||||
title: 插件运行时辅助函数
|
||||
x-i18n:
|
||||
generated_at: "2026-04-25T05:55:40Z"
|
||||
generated_at: "2026-04-26T07:50:36Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: e9f1a56faf33ac18ea7e4b14f70d6f3a73c8b88481aeb0ee77035a17a03f15ce
|
||||
source_hash: db9e57f3129b33bd05a58949a4090a97014472d9c984af82c6aa3b4e16faa1b3
|
||||
source_path: plugins/sdk-runtime.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
提供给每个插件在注册期间注入的 `api.runtime` 对象参考。请使用这些辅助工具,而不是直接导入宿主内部实现。
|
||||
每个插件在注册期间都会注入 `api.runtime` 对象,本页是它的参考文档。使用这些辅助函数,而不是直接导入宿主内部实现。
|
||||
|
||||
<Tip>
|
||||
**想看操作演示?** 请参见 [渠道插件](/zh-CN/plugins/sdk-channel-plugins) 或 [提供商插件](/zh-CN/plugins/sdk-provider-plugins) 的分步指南,这些指南会在上下文中展示这些辅助工具的使用方式。
|
||||
</Tip>
|
||||
<CardGroup cols={2}>
|
||||
<Card title="渠道插件" href="/zh-CN/plugins/sdk-channel-plugins">
|
||||
分步指南,在渠道插件的上下文中使用这些辅助函数。
|
||||
</Card>
|
||||
<Card title="提供商插件" href="/zh-CN/plugins/sdk-provider-plugins">
|
||||
分步指南,在提供商插件的上下文中使用这些辅助函数。
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
```typescript
|
||||
register(api) {
|
||||
@ -29,423 +34,449 @@ register(api) {
|
||||
|
||||
## 运行时命名空间
|
||||
|
||||
### `api.runtime.agent`
|
||||
|
||||
智能体身份、目录和会话管理。
|
||||
|
||||
```typescript
|
||||
// Resolve the agent's working directory
|
||||
const agentDir = api.runtime.agent.resolveAgentDir(cfg);
|
||||
|
||||
// Resolve agent workspace
|
||||
const workspaceDir = api.runtime.agent.resolveAgentWorkspaceDir(cfg);
|
||||
|
||||
// Get agent identity
|
||||
const identity = api.runtime.agent.resolveAgentIdentity(cfg);
|
||||
|
||||
// Get default thinking level
|
||||
const thinking = api.runtime.agent.resolveThinkingDefault(cfg, provider, model);
|
||||
|
||||
// Get agent timeout
|
||||
const timeoutMs = api.runtime.agent.resolveAgentTimeoutMs(cfg);
|
||||
|
||||
// Ensure workspace exists
|
||||
await api.runtime.agent.ensureAgentWorkspace(cfg);
|
||||
|
||||
// Run an embedded agent turn
|
||||
const agentDir = api.runtime.agent.resolveAgentDir(cfg);
|
||||
const result = await api.runtime.agent.runEmbeddedAgent({
|
||||
sessionId: "my-plugin:task-1",
|
||||
runId: crypto.randomUUID(),
|
||||
sessionFile: path.join(agentDir, "sessions", "my-plugin-task-1.jsonl"),
|
||||
workspaceDir: api.runtime.agent.resolveAgentWorkspaceDir(cfg),
|
||||
prompt: "Summarize the latest changes",
|
||||
timeoutMs: api.runtime.agent.resolveAgentTimeoutMs(cfg),
|
||||
});
|
||||
```
|
||||
|
||||
`runEmbeddedAgent(...)` 是从插件代码启动普通 OpenClaw 智能体轮次的中立辅助工具。它使用与渠道触发回复相同的 provider/模型解析和 agent-harness 选择。
|
||||
|
||||
`runEmbeddedPiAgent(...)` 仍保留为兼容性别名。
|
||||
|
||||
**会话存储辅助工具**位于 `api.runtime.agent.session` 下:
|
||||
|
||||
```typescript
|
||||
const storePath = api.runtime.agent.session.resolveStorePath(cfg);
|
||||
const store = api.runtime.agent.session.loadSessionStore(cfg);
|
||||
await api.runtime.agent.session.saveSessionStore(cfg, store);
|
||||
const filePath = api.runtime.agent.session.resolveSessionFilePath(cfg, sessionId);
|
||||
```
|
||||
|
||||
### `api.runtime.agent.defaults`
|
||||
|
||||
默认模型和 provider 常量:
|
||||
|
||||
```typescript
|
||||
const model = api.runtime.agent.defaults.model; // e.g. "anthropic/claude-sonnet-4-6"
|
||||
const provider = api.runtime.agent.defaults.provider; // e.g. "anthropic"
|
||||
```
|
||||
|
||||
### `api.runtime.subagent`
|
||||
|
||||
启动并管理后台子智能体运行。
|
||||
|
||||
```typescript
|
||||
// Start a subagent run
|
||||
const { runId } = await api.runtime.subagent.run({
|
||||
sessionKey: "agent:main:subagent:search-helper",
|
||||
message: "Expand this query into focused follow-up searches.",
|
||||
provider: "openai", // optional override
|
||||
model: "gpt-4.1-mini", // optional override
|
||||
deliver: false,
|
||||
});
|
||||
|
||||
// Wait for completion
|
||||
const result = await api.runtime.subagent.waitForRun({ runId, timeoutMs: 30000 });
|
||||
|
||||
// Read session messages
|
||||
const { messages } = await api.runtime.subagent.getSessionMessages({
|
||||
sessionKey: "agent:main:subagent:search-helper",
|
||||
limit: 10,
|
||||
});
|
||||
|
||||
// Delete a session
|
||||
await api.runtime.subagent.deleteSession({
|
||||
sessionKey: "agent:main:subagent:search-helper",
|
||||
});
|
||||
```
|
||||
|
||||
<Warning>
|
||||
模型覆盖(`provider`/`model`)需要操作员在配置中通过 `plugins.entries.<id>.subagent.allowModelOverride: true` 显式启用。
|
||||
不受信任的插件仍然可以运行子智能体,但覆盖请求会被拒绝。
|
||||
</Warning>
|
||||
|
||||
### `api.runtime.nodes`
|
||||
|
||||
列出已连接节点,并从 Gateway 网关加载的插件代码或插件 CLI 命令中调用节点主机命令。当插件在已配对设备上拥有本地工作时,请使用此功能,例如在另一台 Mac 上的浏览器或音频桥接。
|
||||
|
||||
```typescript
|
||||
const { nodes } = await api.runtime.nodes.list({ connected: true });
|
||||
|
||||
const result = await api.runtime.nodes.invoke({
|
||||
nodeId: "mac-studio",
|
||||
command: "my-plugin.command",
|
||||
params: { action: "start" },
|
||||
timeoutMs: 30000,
|
||||
});
|
||||
```
|
||||
|
||||
在 Gateway 网关内部,此运行时是进程内的。在插件 CLI 命令中,它会通过 RPC 调用已配置的 Gateway 网关,因此像 `openclaw googlemeet recover-tab` 这样的命令可以从终端检查已配对节点。节点命令仍然会经过正常的 Gateway 网关节点配对、命令允许列表和节点本地命令处理。
|
||||
|
||||
### `api.runtime.taskFlow`
|
||||
|
||||
将 Task Flow 运行时绑定到现有 OpenClaw 会话键或受信任工具上下文,然后在无需每次调用都传入所有者的情况下创建和管理 Task Flows。
|
||||
|
||||
```typescript
|
||||
const taskFlow = api.runtime.taskFlow.fromToolContext(ctx);
|
||||
|
||||
const created = taskFlow.createManaged({
|
||||
controllerId: "my-plugin/review-batch",
|
||||
goal: "Review new pull requests",
|
||||
});
|
||||
|
||||
const child = taskFlow.runTask({
|
||||
flowId: created.flowId,
|
||||
runtime: "acp",
|
||||
childSessionKey: "agent:main:subagent:reviewer",
|
||||
task: "Review PR #123",
|
||||
status: "running",
|
||||
startedAt: Date.now(),
|
||||
});
|
||||
|
||||
const waiting = taskFlow.setWaiting({
|
||||
flowId: created.flowId,
|
||||
expectedRevision: created.revision,
|
||||
currentStep: "await-human-reply",
|
||||
waitJson: { kind: "reply", channel: "telegram" },
|
||||
});
|
||||
```
|
||||
|
||||
当你已经从自己的绑定层获得受信任的 OpenClaw 会话键时,请使用 `bindSession({ sessionKey, requesterOrigin })`。不要从原始用户输入进行绑定。
|
||||
|
||||
### `api.runtime.tts`
|
||||
|
||||
文本转语音合成。
|
||||
|
||||
```typescript
|
||||
// Standard TTS
|
||||
const clip = await api.runtime.tts.textToSpeech({
|
||||
text: "Hello from OpenClaw",
|
||||
cfg: api.config,
|
||||
});
|
||||
|
||||
// Telephony-optimized TTS
|
||||
const telephonyClip = await api.runtime.tts.textToSpeechTelephony({
|
||||
text: "Hello from OpenClaw",
|
||||
cfg: api.config,
|
||||
});
|
||||
|
||||
// List available voices
|
||||
const voices = await api.runtime.tts.listVoices({
|
||||
provider: "elevenlabs",
|
||||
cfg: api.config,
|
||||
});
|
||||
```
|
||||
|
||||
使用核心 `messages.tts` 配置和 provider 选择。返回 PCM 音频缓冲区 + 采样率。
|
||||
|
||||
### `api.runtime.mediaUnderstanding`
|
||||
|
||||
图像、音频和视频分析。
|
||||
|
||||
```typescript
|
||||
// Describe an image
|
||||
const image = await api.runtime.mediaUnderstanding.describeImageFile({
|
||||
filePath: "/tmp/inbound-photo.jpg",
|
||||
cfg: api.config,
|
||||
agentDir: "/tmp/agent",
|
||||
});
|
||||
|
||||
// Transcribe audio
|
||||
const { text } = await api.runtime.mediaUnderstanding.transcribeAudioFile({
|
||||
filePath: "/tmp/inbound-audio.ogg",
|
||||
cfg: api.config,
|
||||
mime: "audio/ogg", // optional, for when MIME cannot be inferred
|
||||
});
|
||||
|
||||
// Describe a video
|
||||
const video = await api.runtime.mediaUnderstanding.describeVideoFile({
|
||||
filePath: "/tmp/inbound-video.mp4",
|
||||
cfg: api.config,
|
||||
});
|
||||
|
||||
// Generic file analysis
|
||||
const result = await api.runtime.mediaUnderstanding.runFile({
|
||||
filePath: "/tmp/inbound-file.pdf",
|
||||
cfg: api.config,
|
||||
});
|
||||
```
|
||||
|
||||
当没有生成输出时(例如跳过输入),返回 `{ text: undefined }`。
|
||||
|
||||
<Info>
|
||||
`api.runtime.stt.transcribeAudioFile(...)` 仍保留为 `api.runtime.mediaUnderstanding.transcribeAudioFile(...)` 的兼容性别名。
|
||||
</Info>
|
||||
|
||||
### `api.runtime.imageGeneration`
|
||||
|
||||
图像生成。
|
||||
|
||||
```typescript
|
||||
const result = await api.runtime.imageGeneration.generate({
|
||||
prompt: "A robot painting a sunset",
|
||||
cfg: api.config,
|
||||
});
|
||||
|
||||
const providers = api.runtime.imageGeneration.listProviders({ cfg: api.config });
|
||||
```
|
||||
|
||||
### `api.runtime.webSearch`
|
||||
|
||||
Web 搜索。
|
||||
|
||||
```typescript
|
||||
const providers = api.runtime.webSearch.listProviders({ config: api.config });
|
||||
|
||||
const result = await api.runtime.webSearch.search({
|
||||
config: api.config,
|
||||
args: { query: "OpenClaw plugin SDK", count: 5 },
|
||||
});
|
||||
```
|
||||
|
||||
### `api.runtime.media`
|
||||
|
||||
底层媒体辅助工具。
|
||||
|
||||
```typescript
|
||||
const webMedia = await api.runtime.media.loadWebMedia(url);
|
||||
const mime = await api.runtime.media.detectMime(buffer);
|
||||
const kind = api.runtime.media.mediaKindFromMime("image/jpeg"); // "image"
|
||||
const isVoice = api.runtime.media.isVoiceCompatibleAudio(filePath);
|
||||
const metadata = await api.runtime.media.getImageMetadata(filePath);
|
||||
const resized = await api.runtime.media.resizeToJpeg(buffer, { maxWidth: 800 });
|
||||
const terminalQr = await api.runtime.media.renderQrTerminal("https://openclaw.ai");
|
||||
const pngQr = await api.runtime.media.renderQrPngBase64("https://openclaw.ai", {
|
||||
scale: 6, // 1-12
|
||||
marginModules: 4, // 0-16
|
||||
});
|
||||
const pngQrDataUrl = await api.runtime.media.renderQrPngDataUrl("https://openclaw.ai");
|
||||
const tmpRoot = resolvePreferredOpenClawTmpDir();
|
||||
const pngQrFile = await api.runtime.media.writeQrPngTempFile("https://openclaw.ai", {
|
||||
tmpRoot,
|
||||
dirPrefix: "my-plugin-qr-",
|
||||
fileName: "qr.png",
|
||||
});
|
||||
```
|
||||
|
||||
### `api.runtime.config`
|
||||
|
||||
配置加载和写入。
|
||||
|
||||
```typescript
|
||||
const cfg = await api.runtime.config.loadConfig();
|
||||
await api.runtime.config.writeConfigFile(cfg);
|
||||
```
|
||||
|
||||
### `api.runtime.system`
|
||||
|
||||
系统级辅助工具。
|
||||
|
||||
```typescript
|
||||
await api.runtime.system.enqueueSystemEvent(event);
|
||||
api.runtime.system.requestHeartbeatNow();
|
||||
const output = await api.runtime.system.runCommandWithTimeout(cmd, args, opts);
|
||||
const hint = api.runtime.system.formatNativeDependencyHint(pkg);
|
||||
```
|
||||
|
||||
### `api.runtime.events`
|
||||
|
||||
事件订阅。
|
||||
|
||||
```typescript
|
||||
api.runtime.events.onAgentEvent((event) => {
|
||||
/* ... */
|
||||
});
|
||||
api.runtime.events.onSessionTranscriptUpdate((update) => {
|
||||
/* ... */
|
||||
});
|
||||
```
|
||||
|
||||
### `api.runtime.logging`
|
||||
|
||||
日志记录。
|
||||
|
||||
```typescript
|
||||
const verbose = api.runtime.logging.shouldLogVerbose();
|
||||
const childLogger = api.runtime.logging.getChildLogger({ plugin: "my-plugin" }, { level: "debug" });
|
||||
```
|
||||
|
||||
### `api.runtime.modelAuth`
|
||||
|
||||
模型和 provider 认证解析。
|
||||
|
||||
```typescript
|
||||
const auth = await api.runtime.modelAuth.getApiKeyForModel({ model, cfg });
|
||||
const providerAuth = await api.runtime.modelAuth.resolveApiKeyForProvider({
|
||||
provider: "openai",
|
||||
cfg,
|
||||
});
|
||||
```
|
||||
|
||||
### `api.runtime.state`
|
||||
|
||||
状态目录解析。
|
||||
|
||||
```typescript
|
||||
const stateDir = api.runtime.state.resolveStateDir();
|
||||
```
|
||||
|
||||
### `api.runtime.tools`
|
||||
|
||||
Memory 工具工厂和 CLI。
|
||||
|
||||
```typescript
|
||||
const getTool = api.runtime.tools.createMemoryGetTool(/* ... */);
|
||||
const searchTool = api.runtime.tools.createMemorySearchTool(/* ... */);
|
||||
api.runtime.tools.registerMemoryCli(/* ... */);
|
||||
```
|
||||
|
||||
### `api.runtime.channel`
|
||||
|
||||
渠道特定运行时辅助工具(在加载渠道插件时可用)。
|
||||
|
||||
`api.runtime.channel.mentions` 是供使用运行时注入的内置渠道插件共享的入站 mention 策略能力面:
|
||||
|
||||
```typescript
|
||||
const mentionMatch = api.runtime.channel.mentions.matchesMentionWithExplicit(text, {
|
||||
mentionRegexes,
|
||||
mentionPatterns,
|
||||
});
|
||||
|
||||
const decision = api.runtime.channel.mentions.resolveInboundMentionDecision({
|
||||
facts: {
|
||||
canDetectMention: true,
|
||||
wasMentioned: mentionMatch.matched,
|
||||
implicitMentionKinds: api.runtime.channel.mentions.implicitMentionKindWhen(
|
||||
"reply_to_bot",
|
||||
isReplyToBot,
|
||||
),
|
||||
},
|
||||
policy: {
|
||||
isGroup,
|
||||
requireMention,
|
||||
allowTextCommands,
|
||||
hasControlCommand,
|
||||
commandAuthorized,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
可用的 mention 辅助工具:
|
||||
|
||||
- `buildMentionRegexes`
|
||||
- `matchesMentionPatterns`
|
||||
- `matchesMentionWithExplicit`
|
||||
- `implicitMentionKindWhen`
|
||||
- `resolveInboundMentionDecision`
|
||||
|
||||
`api.runtime.channel.mentions` 有意不暴露旧版的 `resolveMentionGating*` 兼容辅助工具。请优先使用规范化的 `{ facts, policy }` 路径。
|
||||
<AccordionGroup>
|
||||
<Accordion title="api.runtime.agent">
|
||||
智能体身份、目录和会话管理。
|
||||
|
||||
```typescript
|
||||
// 解析智能体工作目录
|
||||
const agentDir = api.runtime.agent.resolveAgentDir(cfg);
|
||||
|
||||
// 解析智能体工作区
|
||||
const workspaceDir = api.runtime.agent.resolveAgentWorkspaceDir(cfg);
|
||||
|
||||
// 获取智能体身份
|
||||
const identity = api.runtime.agent.resolveAgentIdentity(cfg);
|
||||
|
||||
// 获取默认思考等级
|
||||
const thinking = api.runtime.agent.resolveThinkingDefault(cfg, provider, model);
|
||||
|
||||
// 获取智能体超时时间
|
||||
const timeoutMs = api.runtime.agent.resolveAgentTimeoutMs(cfg);
|
||||
|
||||
// 确保工作区存在
|
||||
await api.runtime.agent.ensureAgentWorkspace(cfg);
|
||||
|
||||
// 运行一次嵌入式智能体轮次
|
||||
const agentDir = api.runtime.agent.resolveAgentDir(cfg);
|
||||
const result = await api.runtime.agent.runEmbeddedAgent({
|
||||
sessionId: "my-plugin:task-1",
|
||||
runId: crypto.randomUUID(),
|
||||
sessionFile: path.join(agentDir, "sessions", "my-plugin-task-1.jsonl"),
|
||||
workspaceDir: api.runtime.agent.resolveAgentWorkspaceDir(cfg),
|
||||
prompt: "总结最新的更改",
|
||||
timeoutMs: api.runtime.agent.resolveAgentTimeoutMs(cfg),
|
||||
});
|
||||
```
|
||||
|
||||
`runEmbeddedAgent(...)` 是用于从插件代码启动普通 OpenClaw 智能体轮次的中立辅助函数。它使用与渠道触发回复相同的提供商/模型解析和智能体 harness 选择逻辑。
|
||||
|
||||
`runEmbeddedPiAgent(...)` 仍然保留为兼容性别名。
|
||||
|
||||
**会话存储辅助函数** 位于 `api.runtime.agent.session` 下:
|
||||
|
||||
```typescript
|
||||
const storePath = api.runtime.agent.session.resolveStorePath(cfg);
|
||||
const store = api.runtime.agent.session.loadSessionStore(cfg);
|
||||
await api.runtime.agent.session.saveSessionStore(cfg, store);
|
||||
const filePath = api.runtime.agent.session.resolveSessionFilePath(cfg, sessionId);
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="api.runtime.agent.defaults">
|
||||
默认模型和提供商常量:
|
||||
|
||||
```typescript
|
||||
const model = api.runtime.agent.defaults.model; // 例如 "anthropic/claude-sonnet-4-6"
|
||||
const provider = api.runtime.agent.defaults.provider; // 例如 "anthropic"
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="api.runtime.subagent">
|
||||
启动并管理后台子智能体运行。
|
||||
|
||||
```typescript
|
||||
// 启动一个子智能体运行
|
||||
const { runId } = await api.runtime.subagent.run({
|
||||
sessionKey: "agent:main:subagent:search-helper",
|
||||
message: "将这个查询扩展为更聚焦的后续搜索。",
|
||||
provider: "openai", // 可选覆盖
|
||||
model: "gpt-4.1-mini", // 可选覆盖
|
||||
deliver: false,
|
||||
});
|
||||
|
||||
// 等待完成
|
||||
const result = await api.runtime.subagent.waitForRun({ runId, timeoutMs: 30000 });
|
||||
|
||||
// 读取会话消息
|
||||
const { messages } = await api.runtime.subagent.getSessionMessages({
|
||||
sessionKey: "agent:main:subagent:search-helper",
|
||||
limit: 10,
|
||||
});
|
||||
|
||||
// 删除一个会话
|
||||
await api.runtime.subagent.deleteSession({
|
||||
sessionKey: "agent:main:subagent:search-helper",
|
||||
});
|
||||
```
|
||||
|
||||
<Warning>
|
||||
模型覆盖(`provider`/`model`)需要操作员在配置中通过 `plugins.entries.<id>.subagent.allowModelOverride: true` 显式启用。不受信任的插件仍然可以运行子智能体,但覆盖请求会被拒绝。
|
||||
</Warning>
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="api.runtime.nodes">
|
||||
列出已连接节点,并从 Gateway 网关加载的插件代码或插件 CLI 命令中调用节点宿主命令。当某个插件拥有配对设备上的本地工作时使用它,例如另一台 Mac 上的浏览器或音频桥接。
|
||||
|
||||
```typescript
|
||||
const { nodes } = await api.runtime.nodes.list({ connected: true });
|
||||
|
||||
const result = await api.runtime.nodes.invoke({
|
||||
nodeId: "mac-studio",
|
||||
command: "my-plugin.command",
|
||||
params: { action: "start" },
|
||||
timeoutMs: 30000,
|
||||
});
|
||||
```
|
||||
|
||||
在 Gateway 网关内部,这个运行时是进程内的。在插件 CLI 命令中,它会通过 RPC 调用已配置的 Gateway 网关,因此像 `openclaw googlemeet recover-tab` 这样的命令可以从终端检查已配对节点。节点命令仍然会经过常规的 Gateway 网关节点配对、命令允许列表和节点本地命令处理。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="api.runtime.taskFlow">
|
||||
将 Task Flow 运行时绑定到现有的 OpenClaw 会话键或受信任工具上下文,然后在每次调用时无需传递 owner 即可创建和管理 Task Flows。
|
||||
|
||||
```typescript
|
||||
const taskFlow = api.runtime.taskFlow.fromToolContext(ctx);
|
||||
|
||||
const created = taskFlow.createManaged({
|
||||
controllerId: "my-plugin/review-batch",
|
||||
goal: "审查新的拉取请求",
|
||||
});
|
||||
|
||||
const child = taskFlow.runTask({
|
||||
flowId: created.flowId,
|
||||
runtime: "acp",
|
||||
childSessionKey: "agent:main:subagent:reviewer",
|
||||
task: "审查 PR #123",
|
||||
status: "running",
|
||||
startedAt: Date.now(),
|
||||
});
|
||||
|
||||
const waiting = taskFlow.setWaiting({
|
||||
flowId: created.flowId,
|
||||
expectedRevision: created.revision,
|
||||
currentStep: "await-human-reply",
|
||||
waitJson: { kind: "reply", channel: "telegram" },
|
||||
});
|
||||
```
|
||||
|
||||
当你已经从自己的绑定层拿到一个受信任的 OpenClaw 会话键时,请使用 `bindSession({ sessionKey, requesterOrigin })`。不要直接根据原始用户输入进行绑定。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="api.runtime.tts">
|
||||
文本转语音合成。
|
||||
|
||||
```typescript
|
||||
// 标准 TTS
|
||||
const clip = await api.runtime.tts.textToSpeech({
|
||||
text: "Hello from OpenClaw",
|
||||
cfg: api.config,
|
||||
});
|
||||
|
||||
// 面向电话场景优化的 TTS
|
||||
const telephonyClip = await api.runtime.tts.textToSpeechTelephony({
|
||||
text: "Hello from OpenClaw",
|
||||
cfg: api.config,
|
||||
});
|
||||
|
||||
// 列出可用声音
|
||||
const voices = await api.runtime.tts.listVoices({
|
||||
provider: "elevenlabs",
|
||||
cfg: api.config,
|
||||
});
|
||||
```
|
||||
|
||||
使用核心 `messages.tts` 配置和提供商选择。返回 PCM 音频缓冲区 + 采样率。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="api.runtime.mediaUnderstanding">
|
||||
图像、音频和视频分析。
|
||||
|
||||
```typescript
|
||||
// 描述图像
|
||||
const image = await api.runtime.mediaUnderstanding.describeImageFile({
|
||||
filePath: "/tmp/inbound-photo.jpg",
|
||||
cfg: api.config,
|
||||
agentDir: "/tmp/agent",
|
||||
});
|
||||
|
||||
// 转录音频
|
||||
const { text } = await api.runtime.mediaUnderstanding.transcribeAudioFile({
|
||||
filePath: "/tmp/inbound-audio.ogg",
|
||||
cfg: api.config,
|
||||
mime: "audio/ogg", // 可选,用于无法推断 MIME 时
|
||||
});
|
||||
|
||||
// 描述视频
|
||||
const video = await api.runtime.mediaUnderstanding.describeVideoFile({
|
||||
filePath: "/tmp/inbound-video.mp4",
|
||||
cfg: api.config,
|
||||
});
|
||||
|
||||
// 通用文件分析
|
||||
const result = await api.runtime.mediaUnderstanding.runFile({
|
||||
filePath: "/tmp/inbound-file.pdf",
|
||||
cfg: api.config,
|
||||
});
|
||||
```
|
||||
|
||||
当没有产生输出时返回 `{ text: undefined }`(例如输入被跳过时)。
|
||||
|
||||
<Info>
|
||||
`api.runtime.stt.transcribeAudioFile(...)` 仍然保留为 `api.runtime.mediaUnderstanding.transcribeAudioFile(...)` 的兼容性别名。
|
||||
</Info>
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="api.runtime.imageGeneration">
|
||||
图像生成。
|
||||
|
||||
```typescript
|
||||
const result = await api.runtime.imageGeneration.generate({
|
||||
prompt: "一个正在为夕阳作画的机器人",
|
||||
cfg: api.config,
|
||||
});
|
||||
|
||||
const providers = api.runtime.imageGeneration.listProviders({ cfg: api.config });
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="api.runtime.webSearch">
|
||||
网络搜索。
|
||||
|
||||
```typescript
|
||||
const providers = api.runtime.webSearch.listProviders({ config: api.config });
|
||||
|
||||
const result = await api.runtime.webSearch.search({
|
||||
config: api.config,
|
||||
args: { query: "OpenClaw plugin SDK", count: 5 },
|
||||
});
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="api.runtime.media">
|
||||
底层媒体工具函数。
|
||||
|
||||
```typescript
|
||||
const webMedia = await api.runtime.media.loadWebMedia(url);
|
||||
const mime = await api.runtime.media.detectMime(buffer);
|
||||
const kind = api.runtime.media.mediaKindFromMime("image/jpeg"); // "image"
|
||||
const isVoice = api.runtime.media.isVoiceCompatibleAudio(filePath);
|
||||
const metadata = await api.runtime.media.getImageMetadata(filePath);
|
||||
const resized = await api.runtime.media.resizeToJpeg(buffer, { maxWidth: 800 });
|
||||
const terminalQr = await api.runtime.media.renderQrTerminal("https://openclaw.ai");
|
||||
const pngQr = await api.runtime.media.renderQrPngBase64("https://openclaw.ai", {
|
||||
scale: 6, // 1-12
|
||||
marginModules: 4, // 0-16
|
||||
});
|
||||
const pngQrDataUrl = await api.runtime.media.renderQrPngDataUrl("https://openclaw.ai");
|
||||
const tmpRoot = resolvePreferredOpenClawTmpDir();
|
||||
const pngQrFile = await api.runtime.media.writeQrPngTempFile("https://openclaw.ai", {
|
||||
tmpRoot,
|
||||
dirPrefix: "my-plugin-qr-",
|
||||
fileName: "qr.png",
|
||||
});
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="api.runtime.config">
|
||||
加载和写入配置。
|
||||
|
||||
```typescript
|
||||
const cfg = await api.runtime.config.loadConfig();
|
||||
await api.runtime.config.writeConfigFile(cfg);
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="api.runtime.system">
|
||||
系统级工具函数。
|
||||
|
||||
```typescript
|
||||
await api.runtime.system.enqueueSystemEvent(event);
|
||||
api.runtime.system.requestHeartbeatNow();
|
||||
const output = await api.runtime.system.runCommandWithTimeout(cmd, args, opts);
|
||||
const hint = api.runtime.system.formatNativeDependencyHint(pkg);
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="api.runtime.events">
|
||||
事件订阅。
|
||||
|
||||
```typescript
|
||||
api.runtime.events.onAgentEvent((event) => {
|
||||
/* ... */
|
||||
});
|
||||
api.runtime.events.onSessionTranscriptUpdate((update) => {
|
||||
/* ... */
|
||||
});
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="api.runtime.logging">
|
||||
日志记录。
|
||||
|
||||
```typescript
|
||||
const verbose = api.runtime.logging.shouldLogVerbose();
|
||||
const childLogger = api.runtime.logging.getChildLogger({ plugin: "my-plugin" }, { level: "debug" });
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="api.runtime.modelAuth">
|
||||
模型和提供商认证解析。
|
||||
|
||||
```typescript
|
||||
const auth = await api.runtime.modelAuth.getApiKeyForModel({ model, cfg });
|
||||
const providerAuth = await api.runtime.modelAuth.resolveApiKeyForProvider({
|
||||
provider: "openai",
|
||||
cfg,
|
||||
});
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="api.runtime.state">
|
||||
状态目录解析。
|
||||
|
||||
```typescript
|
||||
const stateDir = api.runtime.state.resolveStateDir();
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="api.runtime.tools">
|
||||
Memory 工具工厂和 CLI。
|
||||
|
||||
```typescript
|
||||
const getTool = api.runtime.tools.createMemoryGetTool(/* ... */);
|
||||
const searchTool = api.runtime.tools.createMemorySearchTool(/* ... */);
|
||||
api.runtime.tools.registerMemoryCli(/* ... */);
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="api.runtime.channel">
|
||||
渠道专用运行时辅助函数(在加载渠道插件时可用)。
|
||||
|
||||
`api.runtime.channel.mentions` 是供使用运行时注入的内置渠道插件共享的入站提及策略接口:
|
||||
|
||||
```typescript
|
||||
const mentionMatch = api.runtime.channel.mentions.matchesMentionWithExplicit(text, {
|
||||
mentionRegexes,
|
||||
mentionPatterns,
|
||||
});
|
||||
|
||||
const decision = api.runtime.channel.mentions.resolveInboundMentionDecision({
|
||||
facts: {
|
||||
canDetectMention: true,
|
||||
wasMentioned: mentionMatch.matched,
|
||||
implicitMentionKinds: api.runtime.channel.mentions.implicitMentionKindWhen(
|
||||
"reply_to_bot",
|
||||
isReplyToBot,
|
||||
),
|
||||
},
|
||||
policy: {
|
||||
isGroup,
|
||||
requireMention,
|
||||
allowTextCommands,
|
||||
hasControlCommand,
|
||||
commandAuthorized,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
可用的提及辅助函数:
|
||||
|
||||
- `buildMentionRegexes`
|
||||
- `matchesMentionPatterns`
|
||||
- `matchesMentionWithExplicit`
|
||||
- `implicitMentionKindWhen`
|
||||
- `resolveInboundMentionDecision`
|
||||
|
||||
`api.runtime.channel.mentions` 有意不暴露较旧的 `resolveMentionGating*` 兼容性辅助函数。请优先使用标准化的 `{ facts, policy }` 路径。
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 存储运行时引用
|
||||
|
||||
使用 `createPluginRuntimeStore` 来存储运行时引用,以便在 `register` 回调之外使用:
|
||||
|
||||
```typescript
|
||||
import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store";
|
||||
import type { PluginRuntime } from "openclaw/plugin-sdk/runtime-store";
|
||||
<Steps>
|
||||
<Step title="创建存储">
|
||||
```typescript
|
||||
import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store";
|
||||
import type { PluginRuntime } from "openclaw/plugin-sdk/runtime-store";
|
||||
|
||||
const store = createPluginRuntimeStore<PluginRuntime>({
|
||||
pluginId: "my-plugin",
|
||||
errorMessage: "my-plugin runtime not initialized",
|
||||
});
|
||||
const store = createPluginRuntimeStore<PluginRuntime>({
|
||||
pluginId: "my-plugin",
|
||||
errorMessage: "my-plugin runtime not initialized",
|
||||
});
|
||||
```
|
||||
|
||||
// In your entry point
|
||||
export default defineChannelPluginEntry({
|
||||
id: "my-plugin",
|
||||
name: "My Plugin",
|
||||
description: "Example",
|
||||
plugin: myPlugin,
|
||||
setRuntime: store.setRuntime,
|
||||
});
|
||||
</Step>
|
||||
<Step title="接入入口点">
|
||||
```typescript
|
||||
export default defineChannelPluginEntry({
|
||||
id: "my-plugin",
|
||||
name: "My Plugin",
|
||||
description: "Example",
|
||||
plugin: myPlugin,
|
||||
setRuntime: store.setRuntime,
|
||||
});
|
||||
```
|
||||
</Step>
|
||||
<Step title="从其他文件访问">
|
||||
```typescript
|
||||
export function getRuntime() {
|
||||
return store.getRuntime(); // throws if not initialized
|
||||
}
|
||||
|
||||
// In other files
|
||||
export function getRuntime() {
|
||||
return store.getRuntime(); // throws if not initialized
|
||||
}
|
||||
export function tryGetRuntime() {
|
||||
return store.tryGetRuntime(); // returns null if not initialized
|
||||
}
|
||||
```
|
||||
|
||||
export function tryGetRuntime() {
|
||||
return store.tryGetRuntime(); // returns null if not initialized
|
||||
}
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
优先使用 `pluginId` 作为 runtime-store 标识。更底层的 `key` 形式适用于少见情况,即某个插件有意需要多个运行时槽位。
|
||||
<Note>
|
||||
对于 runtime-store 标识,优先使用 `pluginId`。更底层的 `key` 形式仅适用于少见场景:某个插件有意需要多个运行时槽位。
|
||||
</Note>
|
||||
|
||||
## 其他顶层 `api` 字段
|
||||
|
||||
除了 `api.runtime` 之外,API 对象还提供:
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
| ------------------------ | ------------------------- | ------------------------------------------------------------------------------------------- |
|
||||
| `api.id` | `string` | 插件 id |
|
||||
| `api.name` | `string` | 插件显示名称 |
|
||||
| `api.config` | `OpenClawConfig` | 当前配置快照(可用时为活动中的内存运行时快照) |
|
||||
| `api.pluginConfig` | `Record<string, unknown>` | 来自 `plugins.entries.<id>.config` 的插件专用配置 |
|
||||
| `api.logger` | `PluginLogger` | 作用域日志记录器(`debug`、`info`、`warn`、`error`) |
|
||||
| `api.registrationMode` | `PluginRegistrationMode` | 当前加载模式;`"setup-runtime"` 是完整入口启动/设置前的轻量预启动/设置窗口 |
|
||||
| `api.resolvePath(input)` | `(string) => string` | 解析相对于插件根目录的路径 |
|
||||
<ParamField path="api.id" type="string">
|
||||
插件 id。
|
||||
</ParamField>
|
||||
<ParamField path="api.name" type="string">
|
||||
插件显示名称。
|
||||
</ParamField>
|
||||
<ParamField path="api.config" type="OpenClawConfig">
|
||||
当前配置快照(可用时为活动的内存中运行时快照)。
|
||||
</ParamField>
|
||||
<ParamField path="api.pluginConfig" type="Record<string, unknown>">
|
||||
来自 `plugins.entries.<id>.config` 的插件专用配置。
|
||||
</ParamField>
|
||||
<ParamField path="api.logger" type="PluginLogger">
|
||||
作用域日志记录器(`debug`、`info`、`warn`、`error`)。
|
||||
</ParamField>
|
||||
<ParamField path="api.registrationMode" type="PluginRegistrationMode">
|
||||
当前加载模式;`"setup-runtime"` 是完整入口启动/设置之前的轻量级预启动/设置窗口。
|
||||
</ParamField>
|
||||
<ParamField path="api.resolvePath(input)" type="(string) => string">
|
||||
解析相对于插件根目录的路径。
|
||||
</ParamField>
|
||||
|
||||
## 相关内容
|
||||
|
||||
- [SDK 概览](/zh-CN/plugins/sdk-overview) — 子路径参考
|
||||
- [插件架构内部机制](/zh-CN/plugins/architecture) — 能力模型与注册表
|
||||
- [插件入口点](/zh-CN/plugins/sdk-entrypoints) — `definePluginEntry` 选项
|
||||
- [插件架构内部机制](/zh-CN/plugins/architecture) — 能力模型和注册表
|
||||
- [插件 SDK 概览](/zh-CN/plugins/sdk-overview) — 子路径参考
|
||||
|
||||
@ -1,45 +1,45 @@
|
||||
---
|
||||
read_when:
|
||||
- 你想在 OpenClaw 中使用 Anthropic 模型
|
||||
summary: 在 OpenClaw 中通过 API 密钥或 Claude CLI 使用 Anthropic(API + Claude CLI)
|
||||
summary: 在 OpenClaw 中通过 API key 或 Claude CLI 使用 Anthropic Claude
|
||||
title: Anthropic
|
||||
x-i18n:
|
||||
generated_at: "2026-04-26T03:26:30Z"
|
||||
generated_at: "2026-04-26T07:50:35Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: cf1ecd7846b8dd86cd7a722654042cd78e6c28fc2ae5aca43d967d19df337744
|
||||
source_hash: f26f117cb4f98790c323e056d39267c18f1278b0a7a8d3d43a7cbaddbb4523c1
|
||||
source_path: providers/anthropic.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
Anthropic 构建了 **Claude** 模型系列。OpenClaw 支持两种认证方式:
|
||||
Anthropic 构建了 **Claude** 模型家族。OpenClaw 支持两种认证方式:
|
||||
|
||||
- **API 密钥** — 直接访问 Anthropic API,并按用量计费(`anthropic/*` 模型)
|
||||
- **API key** — 通过 Anthropic API 直接访问,并按使用量计费(`anthropic/*` 模型)
|
||||
- **Claude CLI** — 在同一主机上复用现有的 Claude CLI 登录
|
||||
|
||||
<Warning>
|
||||
Anthropic 员工告诉我们,OpenClaw 风格的 Claude CLI 用法再次被允许,因此除非 Anthropic 发布新的政策,否则 OpenClaw 会将 Claude CLI 复用和 `claude -p` 用法视为已获认可。
|
||||
Anthropic 员工告诉我们,OpenClaw 风格的 Claude CLI 使用方式已再次被允许,因此除非 Anthropic 发布新的政策,否则 OpenClaw 会将 Claude CLI 复用和 `claude -p` 用法视为已获认可。
|
||||
|
||||
对于长期运行的 Gateway 网关主机,Anthropic API 密钥仍然是最清晰、最可预测的生产路径。
|
||||
对于长期运行的 Gateway 网关主机,Anthropic API key 仍然是最清晰、最可预测的生产路径。
|
||||
|
||||
Anthropic 当前的公开文档:
|
||||
|
||||
- [Claude Code CLI 参考](https://code.claude.com/docs/en/cli-reference)
|
||||
- [Claude Agent SDK 概览](https://platform.claude.com/docs/en/agent-sdk/overview)
|
||||
- [在你的 Pro 或 Max 计划中使用 Claude Code](https://support.claude.com/en/articles/11145838-using-claude-code-with-your-pro-or-max-plan)
|
||||
- [在你的 Team 或 Enterprise 计划中使用 Claude Code](https://support.anthropic.com/en/articles/11845131-using-claude-code-with-your-team-or-enterprise-plan/)
|
||||
- [将 Claude Code 与你的 Pro 或 Max 方案一起使用](https://support.claude.com/en/articles/11145838-using-claude-code-with-your-pro-or-max-plan)
|
||||
- [将 Claude Code 与你的 Team 或 Enterprise 方案一起使用](https://support.anthropic.com/en/articles/11845131-using-claude-code-with-your-team-or-enterprise-plan/)
|
||||
|
||||
</Warning>
|
||||
|
||||
## 入门指南
|
||||
|
||||
<Tabs>
|
||||
<Tab title="API 密钥">
|
||||
**最适合:** 标准 API 访问和按用量计费。
|
||||
<Tab title="API key">
|
||||
**最适合:** 标准 API 访问和按使用量计费。
|
||||
|
||||
<Steps>
|
||||
<Step title="获取你的 API 密钥">
|
||||
在 [Anthropic Console](https://console.anthropic.com/) 中创建一个 API 密钥。
|
||||
<Step title="获取你的 API key">
|
||||
在 [Anthropic Console](https://console.anthropic.com/) 中创建 API key。
|
||||
</Step>
|
||||
<Step title="运行新手引导">
|
||||
```bash
|
||||
@ -47,7 +47,7 @@ Anthropic 当前的公开文档:
|
||||
# 选择:Anthropic API key
|
||||
```
|
||||
|
||||
或直接传入密钥:
|
||||
或直接传入 key:
|
||||
|
||||
```bash
|
||||
openclaw onboard --anthropic-api-key "$ANTHROPIC_API_KEY"
|
||||
@ -72,10 +72,10 @@ Anthropic 当前的公开文档:
|
||||
</Tab>
|
||||
|
||||
<Tab title="Claude CLI">
|
||||
**最适合:** 复用现有的 Claude CLI 登录,而无需单独的 API 密钥。
|
||||
**最适合:** 复用现有的 Claude CLI 登录,而无需单独的 API key。
|
||||
|
||||
<Steps>
|
||||
<Step title="确保已安装 Claude CLI 并完成登录">
|
||||
<Step title="确保 Claude CLI 已安装并已登录">
|
||||
使用以下命令验证:
|
||||
|
||||
```bash
|
||||
@ -101,16 +101,33 @@ Anthropic 当前的公开文档:
|
||||
Claude CLI 后端的设置和运行时细节见 [CLI 后端](/zh-CN/gateway/cli-backends)。
|
||||
</Note>
|
||||
|
||||
### 配置示例
|
||||
|
||||
推荐使用规范的 Anthropic 模型引用,并通过 CLI 运行时覆盖:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
defaults: {
|
||||
model: { primary: "anthropic/claude-opus-4-7" },
|
||||
agentRuntime: { id: "claude-cli" },
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
遗留的 `claude-cli/claude-opus-4-7` 模型引用仍可用于兼容性,但新配置应将 provider/模型选择保持为 `anthropic/*`,并将执行后端放在 `agentRuntime.id` 中。
|
||||
|
||||
<Tip>
|
||||
如果你希望获得最清晰的计费路径,请改用 Anthropic API 密钥。OpenClaw 还支持来自 [OpenAI Codex](/zh-CN/providers/openai)、[Qwen Cloud](/zh-CN/providers/qwen)、[MiniMax](/zh-CN/providers/minimax) 和 [Z.AI / GLM](/zh-CN/providers/glm) 的订阅式选项。
|
||||
如果你希望获得最清晰的计费路径,请改用 Anthropic API key。OpenClaw 还支持来自 [OpenAI Codex](/zh-CN/providers/openai)、[Qwen Cloud](/zh-CN/providers/qwen)、[MiniMax](/zh-CN/providers/minimax) 和 [Z.AI / GLM](/zh-CN/providers/glm) 的订阅式选项。
|
||||
</Tip>
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Thinking 默认值(Claude 4.6)
|
||||
## 思考默认值(Claude 4.6)
|
||||
|
||||
当未设置显式 thinking 级别时,Claude 4.6 模型在 OpenClaw 中默认使用 `adaptive` thinking。
|
||||
当未设置显式思考级别时,Claude 4.6 模型在 OpenClaw 中默认使用 `adaptive` 思考。
|
||||
|
||||
可通过 `/think:<level>` 按消息覆盖,或在模型参数中设置:
|
||||
|
||||
@ -130,17 +147,17 @@ Anthropic 当前的公开文档:
|
||||
|
||||
<Note>
|
||||
相关 Anthropic 文档:
|
||||
- [Adaptive thinking](https://platform.claude.com/docs/en/build-with-claude/adaptive-thinking)
|
||||
- [Extended thinking](https://platform.claude.com/docs/en/build-with-claude/extended-thinking)
|
||||
- [自适应思考](https://platform.claude.com/docs/en/build-with-claude/adaptive-thinking)
|
||||
- [扩展思考](https://platform.claude.com/docs/en/build-with-claude/extended-thinking)
|
||||
</Note>
|
||||
|
||||
## 提示缓存
|
||||
|
||||
OpenClaw 支持 Anthropic 的提示缓存功能,适用于 API 密钥认证。
|
||||
OpenClaw 支持 Anthropic 针对 API key 认证提供的提示缓存功能。
|
||||
|
||||
| 值 | 缓存时长 | 描述 |
|
||||
| 值 | 缓存时长 | 说明 |
|
||||
| ------------------- | -------------- | -------------------------------------- |
|
||||
| `"short"`(默认) | 5 分钟 | 对 API 密钥认证自动应用 |
|
||||
| `"short"`(默认) | 5 分钟 | 会自动应用于 API key 认证 |
|
||||
| `"long"` | 1 小时 | 扩展缓存 |
|
||||
| `"none"` | 不缓存 | 禁用提示缓存 |
|
||||
|
||||
@ -160,7 +177,7 @@ OpenClaw 支持 Anthropic 的提示缓存功能,适用于 API 密钥认证。
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="按智能体覆盖缓存">
|
||||
使用模型级 `params` 作为基线,然后通过 `agents.list[].params` 覆盖特定智能体:
|
||||
使用模型级参数作为基线,然后通过 `agents.list[].params` 覆盖特定智能体:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -186,14 +203,14 @@ OpenClaw 支持 Anthropic 的提示缓存功能,适用于 API 密钥认证。
|
||||
1. `agents.defaults.models["provider/model"].params`
|
||||
2. `agents.list[].params`(匹配 `id`,按键覆盖)
|
||||
|
||||
这样,你可以让一个智能体保留长期缓存,同时让同一模型上的另一个智能体为突发性或低复用流量禁用缓存。
|
||||
这样可以让一个智能体保留长时缓存,而另一个使用相同模型的智能体则为突发型/低复用流量禁用缓存。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Bedrock Claude 说明">
|
||||
- Bedrock 上的 Anthropic Claude 模型(`amazon-bedrock/*anthropic.claude*`)在配置后接受 `cacheRetention` 透传。
|
||||
- Bedrock 上的 Anthropic Claude 模型(`amazon-bedrock/*anthropic.claude*`)在配置时接受 `cacheRetention` 透传。
|
||||
- 非 Anthropic 的 Bedrock 模型会在运行时被强制设为 `cacheRetention: "none"`。
|
||||
- 当未设置显式值时,API 密钥的智能默认值也会为 Bedrock 上的 Claude 引用预设 `cacheRetention: "short"`。
|
||||
- 当未设置显式值时,API key 智能默认值也会为 Claude-on-Bedrock 引用填入 `cacheRetention: "short"`。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
@ -201,7 +218,7 @@ OpenClaw 支持 Anthropic 的提示缓存功能,适用于 API 密钥认证。
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="快速模式">
|
||||
OpenClaw 的共享 `/fast` 开关支持直连 Anthropic 流量(API 密钥和面向 `api.anthropic.com` 的 OAuth)。
|
||||
OpenClaw 的共享 `/fast` 开关支持直连 Anthropic 流量(API key 和指向 `api.anthropic.com` 的 OAuth)。
|
||||
|
||||
| 命令 | 映射到 |
|
||||
|---------|---------|
|
||||
@ -223,30 +240,27 @@ OpenClaw 支持 Anthropic 的提示缓存功能,适用于 API 密钥认证。
|
||||
```
|
||||
|
||||
<Note>
|
||||
- 仅对直连 `api.anthropic.com` 的请求注入。代理路由会保持 `service_tier` 不变。
|
||||
- 仅注入到直连 `api.anthropic.com` 的请求中。代理路由会保持 `service_tier` 不变。
|
||||
- 当同时设置时,显式的 `serviceTier` 或 `service_tier` 参数会覆盖 `/fast`。
|
||||
- 在没有 Priority Tier 容量的账户上,`service_tier: "auto"` 可能会解析为 `standard`。
|
||||
- 对于没有 Priority Tier 容量的账户,`service_tier: "auto"` 可能会解析为 `standard`。
|
||||
</Note>
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="媒体理解(图像和 PDF)">
|
||||
内置的 Anthropic 插件注册了图像和 PDF 理解能力。OpenClaw
|
||||
会根据已配置的 Anthropic 认证自动解析媒体能力——无需
|
||||
额外配置。
|
||||
<Accordion title="媒体理解(图片和 PDF)">
|
||||
内置的 Anthropic 插件注册了图片和 PDF 理解能力。OpenClaw 会从已配置的 Anthropic 认证中自动解析媒体能力——无需额外配置。
|
||||
|
||||
| 属性 | 值 |
|
||||
| -------------- | -------------------- |
|
||||
| 默认模型 | `claude-opus-4-6` |
|
||||
| 支持的输入 | 图像、PDF 文档 |
|
||||
| 支持的输入 | 图片、PDF 文档 |
|
||||
|
||||
当图像或 PDF 附加到对话中时,OpenClaw 会自动
|
||||
通过 Anthropic 媒体理解提供商进行处理。
|
||||
当图片或 PDF 附加到对话中时,OpenClaw 会自动通过 Anthropic 媒体理解提供商进行路由。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="1M 上下文窗口(测试版)">
|
||||
Anthropic 的 1M 上下文窗口受测试版门控限制。请按模型启用:
|
||||
<Accordion title="1M 上下文窗口(beta)">
|
||||
Anthropic 的 1M 上下文窗口受 beta 门控控制。请按模型启用:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -262,41 +276,38 @@ OpenClaw 支持 Anthropic 的提示缓存功能,适用于 API 密钥认证。
|
||||
}
|
||||
```
|
||||
|
||||
OpenClaw 会将其映射为请求中的 `anthropic-beta: context-1m-2025-08-07`。
|
||||
OpenClaw 会在请求中将其映射为 `anthropic-beta: context-1m-2025-08-07`。
|
||||
|
||||
`params.context1m: true` 也适用于 Claude CLI 后端
|
||||
(`claude-cli/*`)中符合条件的 Opus 和 Sonnet 模型,从而扩展这些 CLI 会话的运行时
|
||||
上下文窗口,使其与直连 API 的行为保持一致。
|
||||
`params.context1m: true` 也适用于 Claude CLI 后端(`claude-cli/*`)中符合条件的 Opus 和 Sonnet 模型,从而扩展这些 CLI 会话的运行时上下文窗口,使其与直连 API 行为一致。
|
||||
|
||||
<Warning>
|
||||
需要你的 Anthropic 凭证具备长上下文访问权限。旧版令牌认证(`sk-ant-oat-*`)会被 1M 上下文请求拒绝——OpenClaw 会记录警告,并回退到标准上下文窗口。
|
||||
需要你的 Anthropic 凭证具备长上下文访问权限。遗留 token 认证(`sk-ant-oat-*`)会被拒绝用于 1M 上下文请求——OpenClaw 会记录警告并回退到标准上下文窗口。
|
||||
</Warning>
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Claude Opus 4.7 1M 上下文">
|
||||
`anthropic/claude-opus-4.7` 及其 `claude-cli` 变体默认具有 1M 上下文
|
||||
窗口——无需设置 `params.context1m: true`。
|
||||
`anthropic/claude-opus-4.7` 及其 `claude-cli` 变体默认具有 1M 上下文窗口——无需设置 `params.context1m: true`。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 故障排除
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="401 错误 / 令牌突然失效">
|
||||
Anthropic 令牌认证会过期,也可能被撤销。对于新的配置,建议改用 Anthropic API 密钥。
|
||||
<Accordion title="401 错误 / token 突然失效">
|
||||
Anthropic token 认证会过期,也可能被撤销。对于新配置,建议改用 Anthropic API key。
|
||||
</Accordion>
|
||||
|
||||
<Accordion title='未找到提供商 "anthropic" 的 API 密钥'>
|
||||
Anthropic 认证是**按智能体**配置的——新智能体不会继承主智能体的密钥。请为该智能体重新运行新手引导(或在 Gateway 网关主机上配置 API 密钥),然后使用 `openclaw models status` 验证。
|
||||
<Accordion title='未找到 provider "anthropic" 的 API key'>
|
||||
Anthropic 认证是**按智能体划分**的——新智能体不会继承主智能体的 key。请为该智能体重新运行新手引导(或在 Gateway 网关主机上配置 API key),然后通过 `openclaw models status` 验证。
|
||||
</Accordion>
|
||||
|
||||
<Accordion title='未找到配置文件 "anthropic:default" 的凭证'>
|
||||
运行 `openclaw models status` 以查看当前启用的是哪个认证配置文件。重新运行新手引导,或为该配置文件路径配置 API 密钥。
|
||||
<Accordion title='未找到 profile "anthropic:default" 的凭证'>
|
||||
运行 `openclaw models status` 查看当前激活的是哪个认证配置文件。重新运行新手引导,或为该 profile 路径配置 API key。
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="没有可用的认证配置文件(全部处于冷却中)">
|
||||
检查 `openclaw models status --json` 中的 `auth.unusableProfiles`。Anthropic 的速率限制冷却可能按模型范围生效,因此同级的其他 Anthropic 模型可能仍可使用。添加另一个 Anthropic 配置文件,或等待冷却结束。
|
||||
检查 `openclaw models status --json` 中的 `auth.unusableProfiles`。Anthropic 的限流冷却可能是按模型范围生效的,因此同级的其他 Anthropic 模型仍可能可用。添加另一个 Anthropic 配置文件,或等待冷却结束。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
@ -314,7 +325,7 @@ OpenClaw 支持 Anthropic 的提示缓存功能,适用于 API 密钥认证。
|
||||
Claude CLI 后端设置和运行时细节。
|
||||
</Card>
|
||||
<Card title="提示缓存" href="/zh-CN/reference/prompt-caching" icon="database">
|
||||
提示缓存如何在不同提供商之间工作。
|
||||
提示缓存在各提供商中的工作方式。
|
||||
</Card>
|
||||
<Card title="OAuth 和认证" href="/zh-CN/gateway/authentication" icon="key">
|
||||
认证细节和凭证复用规则。
|
||||
|
||||
@ -2,32 +2,33 @@
|
||||
read_when:
|
||||
- 你想在 OpenClaw 中使用 Google Gemini 模型
|
||||
- 你需要 API 密钥或 OAuth 认证流程
|
||||
summary: Google Gemini 设置(API 密钥 + OAuth、图像生成、媒体理解、TTS、网页搜索)
|
||||
summary: Google Gemini 设置(API 密钥 + OAuth、图像生成、媒体理解、TTS、web 搜索)
|
||||
title: Google(Gemini)
|
||||
x-i18n:
|
||||
generated_at: "2026-04-25T20:42:01Z"
|
||||
generated_at: "2026-04-26T07:50:46Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 990a2567790673261f7b018816ee3fb81fe03e662a78769248ee91311ff5d2fc
|
||||
source_hash: 312c7a5bc433831d98d1d47c42c5cac6a4cd8d4948ddbf16f1ae11aaec7a0339
|
||||
source_path: providers/google.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
Google 插件通过 Google AI Studio 提供对 Gemini 模型的访问,还支持通过 Gemini Grounding 进行图像生成、媒体理解(图像/音频/视频)、文本转语音以及网页搜索。
|
||||
Google 插件通过 Google AI Studio 提供对 Gemini 模型的访问,还提供通过
|
||||
Gemini Grounding 实现的图像生成、媒体理解(图像/音频/视频)、文本转语音和 web 搜索。
|
||||
|
||||
- 提供商:`google`
|
||||
- 认证:`GEMINI_API_KEY` 或 `GOOGLE_API_KEY`
|
||||
- API:Google Gemini API
|
||||
- 运行时选项:`agents.defaults.embeddedHarness.runtime: "google-gemini-cli"`
|
||||
会复用 Gemini CLI OAuth,同时将模型引用保持为规范形式 `google/*`。
|
||||
- 运行时选项:`agents.defaults.agentRuntime.id: "google-gemini-cli"`
|
||||
会复用 Gemini CLI OAuth,同时保持模型引用规范为 `google/*`。
|
||||
|
||||
## 入门指南
|
||||
|
||||
选择你偏好的认证方式,并按照设置步骤操作。
|
||||
|
||||
<Tabs>
|
||||
<Tab title="API 密钥">
|
||||
**最适合:** 通过 Google AI Studio 进行标准的 Gemini API 访问。
|
||||
<Tab title="API key">
|
||||
**最适合:** 通过 Google AI Studio 进行标准 Gemini API 访问。
|
||||
|
||||
<Steps>
|
||||
<Step title="运行新手引导">
|
||||
@ -63,28 +64,28 @@ Google 插件通过 Google AI Studio 提供对 Gemini 模型的访问,还支
|
||||
</Steps>
|
||||
|
||||
<Tip>
|
||||
环境变量 `GEMINI_API_KEY` 和 `GOOGLE_API_KEY` 都可接受。使用你已经配置好的那个即可。
|
||||
环境变量 `GEMINI_API_KEY` 和 `GOOGLE_API_KEY` 都受支持。使用你已经配置好的那个即可。
|
||||
</Tip>
|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab title="Gemini CLI(OAuth)">
|
||||
**最适合:** 复用已有的 Gemini CLI 登录(通过 PKCE OAuth),而不是单独使用 API 密钥。
|
||||
<Tab title="Gemini CLI (OAuth)">
|
||||
**最适合:** 复用现有 Gemini CLI 登录的 PKCE OAuth,而不是单独使用 API 密钥。
|
||||
|
||||
<Warning>
|
||||
`google-gemini-cli` 提供商是非官方集成。一些用户
|
||||
报告在以这种方式使用 OAuth 时会遇到账户限制。请自行承担风险。
|
||||
`google-gemini-cli` provider 是非官方集成。一些用户
|
||||
报告使用这种 OAuth 方式时会遇到账户限制。请自行承担风险。
|
||||
</Warning>
|
||||
|
||||
<Steps>
|
||||
<Step title="安装 Gemini CLI">
|
||||
本地 `gemini` 命令必须可在 `PATH` 中使用。
|
||||
本地 `gemini` 命令必须可在 `PATH` 中找到。
|
||||
|
||||
```bash
|
||||
# Homebrew
|
||||
brew install gemini-cli
|
||||
|
||||
# 或 npm
|
||||
# or npm
|
||||
npm install -g @google/gemini-cli
|
||||
```
|
||||
|
||||
@ -112,20 +113,20 @@ Google 插件通过 Google AI Studio 提供对 Gemini 模型的访问,还支
|
||||
- `OPENCLAW_GEMINI_OAUTH_CLIENT_ID`
|
||||
- `OPENCLAW_GEMINI_OAUTH_CLIENT_SECRET`
|
||||
|
||||
(或者使用 `GEMINI_CLI_*` 变体。)
|
||||
(或使用 `GEMINI_CLI_*` 变体。)
|
||||
|
||||
<Note>
|
||||
如果 Gemini CLI OAuth 在登录后请求失败,请在 Gateway 网关主机上设置 `GOOGLE_CLOUD_PROJECT` 或
|
||||
如果 Gemini CLI OAuth 请求在登录后失败,请在 Gateway 网关 主机上设置 `GOOGLE_CLOUD_PROJECT` 或
|
||||
`GOOGLE_CLOUD_PROJECT_ID`,然后重试。
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
如果在浏览器流程开始前登录就失败,请确保本地 `gemini`
|
||||
命令已安装并且位于 `PATH` 中。
|
||||
如果在浏览器流程开始之前登录失败,请确保本地 `gemini`
|
||||
命令已安装并位于 `PATH` 中。
|
||||
</Note>
|
||||
|
||||
`google-gemini-cli/*` 模型引用是旧版兼容别名。新的
|
||||
配置应使用 `google/*` 模型引用,并在需要本地 Gemini CLI 执行时
|
||||
`google-gemini-cli/*` 模型引用是旧版兼容别名。新配置
|
||||
应使用 `google/*` 模型引用,并在需要本地 Gemini CLI 执行时
|
||||
搭配 `google-gemini-cli` 运行时。
|
||||
|
||||
</Tab>
|
||||
@ -133,7 +134,7 @@ Google 插件通过 Google AI Studio 提供对 Gemini 模型的访问,还支
|
||||
|
||||
## 功能
|
||||
|
||||
| 功能 | 支持情况 |
|
||||
| 能力 | 支持情况 |
|
||||
| ---------------------- | ----------------------------- |
|
||||
| 聊天补全 | 是 |
|
||||
| 图像生成 | 是 |
|
||||
@ -141,37 +142,37 @@ Google 插件通过 Google AI Studio 提供对 Gemini 模型的访问,还支
|
||||
| 文本转语音 | 是 |
|
||||
| 实时语音 | 是(Google Live API) |
|
||||
| 图像理解 | 是 |
|
||||
| 音频转写 | 是 |
|
||||
| 音频转录 | 是 |
|
||||
| 视频理解 | 是 |
|
||||
| 网页搜索(Grounding) | 是 |
|
||||
| 思考/推理 | 是(Gemini 2.5+ / Gemini 3+) |
|
||||
| web 搜索(Grounding) | 是 |
|
||||
| thinking/reasoning | 是(Gemini 2.5+ / Gemini 3+) |
|
||||
| Gemma 4 模型 | 是 |
|
||||
|
||||
<Tip>
|
||||
Gemini 3 模型使用 `thinkingLevel`,而不是 `thinkingBudget`。OpenClaw 会将
|
||||
Gemini 3、Gemini 3.1 和 `gemini-*-latest` 别名的推理控制映射到
|
||||
`thinkingLevel`,这样默认/低延迟运行就不会发送被禁用的
|
||||
`thinkingLevel`,这样默认/低延迟运行就不会发送已禁用的
|
||||
`thinkingBudget` 值。
|
||||
|
||||
`/think adaptive` 会保留 Google 的动态思考语义,而不是选择
|
||||
一个固定的 OpenClaw 级别。Gemini 3 和 Gemini 3.1 不会发送固定的 `thinkingLevel`,因此
|
||||
Google 可以自行选择级别;Gemini 2.5 会发送 Google 的动态哨兵值
|
||||
`/think adaptive` 会保留 Google 的动态 thinking 语义,而不是选择
|
||||
固定的 OpenClaw 级别。Gemini 3 和 Gemini 3.1 会省略固定的 `thinkingLevel`,以便
|
||||
让 Google 自行选择级别;Gemini 2.5 会发送 Google 的动态哨兵值
|
||||
`thinkingBudget: -1`。
|
||||
|
||||
Gemma 4 模型(例如 `gemma-4-26b-a4b-it`)支持思考模式。OpenClaw
|
||||
会将 `thinkingBudget` 重写为 Google 支持的 `thinkingLevel`,用于 Gemma 4。
|
||||
将 thinking 设置为 `off` 会保持禁用思考,而不是映射为
|
||||
Gemma 4 模型(例如 `gemma-4-26b-a4b-it`)支持 thinking 模式。OpenClaw
|
||||
会将 `thinkingBudget` 重写为 Google 支持的 `thinkingLevel`,以用于 Gemma 4。
|
||||
将 thinking 设置为 `off` 时,会保留 thinking 已禁用状态,而不会映射到
|
||||
`MINIMAL`。
|
||||
</Tip>
|
||||
|
||||
## 图像生成
|
||||
|
||||
内置的 `google` 图像生成提供商默认使用
|
||||
内置的 `google` 图像生成 provider 默认使用
|
||||
`google/gemini-3.1-flash-image-preview`。
|
||||
|
||||
- 也支持 `google/gemini-3-pro-image-preview`
|
||||
- 生成:每次请求最多 4 张图像
|
||||
- 编辑模式:已启用,最多支持 5 张输入图像
|
||||
- 生成:每个请求最多 4 张图像
|
||||
- 编辑模式:已启用,最多 5 张输入图像
|
||||
- 几何控制:`size`、`aspectRatio` 和 `resolution`
|
||||
|
||||
要将 Google 用作默认图像提供商:
|
||||
@ -189,16 +190,16 @@ Gemma 4 模型(例如 `gemma-4-26b-a4b-it`)支持思考模式。OpenClaw
|
||||
```
|
||||
|
||||
<Note>
|
||||
共享工具参数、提供商选择和故障转移行为,请参见 [图像生成](/zh-CN/tools/image-generation)。
|
||||
有关共享工具参数、提供商选择和故障转移行为,请参见 [图像生成](/zh-CN/tools/image-generation)。
|
||||
</Note>
|
||||
|
||||
## 视频生成
|
||||
|
||||
内置的 `google` 插件还会通过共享的
|
||||
`video_generate` 工具注册视频生成能力。
|
||||
内置的 `google` 插件也通过共享的
|
||||
`video_generate` 工具注册视频生成。
|
||||
|
||||
- 默认视频模型:`google/veo-3.1-fast-generate-preview`
|
||||
- 模式:文生视频、图生视频,以及单视频参考流程
|
||||
- 模式:文生视频、图生视频和单视频参考流程
|
||||
- 支持 `aspectRatio`、`resolution` 和 `audio`
|
||||
- 当前时长限制:**4 到 8 秒**
|
||||
|
||||
@ -217,20 +218,20 @@ Gemma 4 模型(例如 `gemma-4-26b-a4b-it`)支持思考模式。OpenClaw
|
||||
```
|
||||
|
||||
<Note>
|
||||
共享工具参数、提供商选择和故障转移行为,请参见 [视频生成](/zh-CN/tools/video-generation)。
|
||||
有关共享工具参数、提供商选择和故障转移行为,请参见 [视频生成](/zh-CN/tools/video-generation)。
|
||||
</Note>
|
||||
|
||||
## 音乐生成
|
||||
|
||||
内置的 `google` 插件还会通过共享的
|
||||
`music_generate` 工具注册音乐生成功能。
|
||||
内置的 `google` 插件也通过共享的
|
||||
`music_generate` 工具注册音乐生成。
|
||||
|
||||
- 默认音乐模型:`google/lyria-3-clip-preview`
|
||||
- 也支持 `google/lyria-3-pro-preview`
|
||||
- 提示控制:`lyrics` 和 `instrumental`
|
||||
- 输出格式:默认 `mp3`,在 `google/lyria-3-pro-preview` 上还支持 `wav`
|
||||
- 输出格式:默认 `mp3`,并且 `google/lyria-3-pro-preview` 支持 `wav`
|
||||
- 参考输入:最多 10 张图像
|
||||
- 基于会话的运行会通过共享的任务/Status 流程分离执行,包括 `action: "status"`
|
||||
- 基于会话的运行会通过共享的任务/状态流程分离执行,包括 `action: "status"`
|
||||
|
||||
要将 Google 用作默认音乐提供商:
|
||||
|
||||
@ -247,20 +248,20 @@ Gemma 4 模型(例如 `gemma-4-26b-a4b-it`)支持思考模式。OpenClaw
|
||||
```
|
||||
|
||||
<Note>
|
||||
共享工具参数、提供商选择和故障转移行为,请参见 [音乐生成](/zh-CN/tools/music-generation)。
|
||||
有关共享工具参数、提供商选择和故障转移行为,请参见 [音乐生成](/zh-CN/tools/music-generation)。
|
||||
</Note>
|
||||
|
||||
## 文本转语音
|
||||
|
||||
内置的 `google` 语音提供商通过
|
||||
内置的 `google` 语音 provider 通过
|
||||
`gemini-3.1-flash-tts-preview` 使用 Gemini API TTS 路径。
|
||||
|
||||
- 默认声音:`Kore`
|
||||
- 默认语音:`Kore`
|
||||
- 认证:`messages.tts.providers.google.apiKey`、`models.providers.google.apiKey`、`GEMINI_API_KEY` 或 `GOOGLE_API_KEY`
|
||||
- 输出:常规 TTS 附件使用 WAV,语音便笺目标使用 Opus,Talk/电话场景使用 PCM
|
||||
- 语音便笺输出:Google PCM 会先封装为 WAV,再通过 `ffmpeg` 转码为 48 kHz Opus
|
||||
- 语音便笺输出:Google PCM 会被封装为 WAV,并通过 `ffmpeg` 转码为 48 kHz Opus
|
||||
|
||||
要将 Google 用作默认 TTS 提供商:
|
||||
要将 Google 用作默认 TTS provider:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -280,14 +281,13 @@ Gemma 4 模型(例如 `gemma-4-26b-a4b-it`)支持思考模式。OpenClaw
|
||||
}
|
||||
```
|
||||
|
||||
Gemini API TTS 使用自然语言提示来控制风格。设置
|
||||
`audioProfile` 可在朗读文本前添加一个可复用的风格提示。若你的提示文本中提到了具名说话者,请设置
|
||||
Gemini API TTS 使用自然语言提示进行风格控制。设置
|
||||
`audioProfile` 以在朗读文本前附加可复用的风格提示。若你的提示文本引用了具名说话者,请设置
|
||||
`speakerName`。
|
||||
|
||||
Gemini API TTS 还支持在文本中使用富表现力的方括号音频标签,
|
||||
例如 `[whispers]` 或 `[laughs]`。要在将标签发送给 TTS 的同时
|
||||
避免它们出现在可见聊天回复中,请将它们放入 `[[tts:text]]...[[/tts:text]]`
|
||||
块中:
|
||||
Gemini API TTS 也接受文本中的方括号音频标签,
|
||||
例如 `[whispers]` 或 `[laughs]`。为了在将这些标签发送给 TTS 的同时,不让它们出现在可见聊天回复中,请将其放入 `[[tts:text]]...[[/tts:text]]`
|
||||
块内:
|
||||
|
||||
```text
|
||||
Here is the clean reply text.
|
||||
@ -296,26 +296,26 @@ Here is the clean reply text.
|
||||
```
|
||||
|
||||
<Note>
|
||||
一个限制为 Gemini API 的 Google Cloud Console API 密钥对该
|
||||
提供商有效。这不是单独的 Cloud Text-to-Speech API 路径。
|
||||
限制为 Gemini API 的 Google Cloud Console API 密钥对该
|
||||
provider 有效。这不是单独的 Cloud Text-to-Speech API 路径。
|
||||
</Note>
|
||||
|
||||
## 实时语音
|
||||
|
||||
内置的 `google` 插件注册了一个由
|
||||
Gemini Live API 支持的实时语音提供商,用于 Voice Call 和 Google Meet 等后端音频桥接场景。
|
||||
Gemini Live API 支持的实时语音 provider,适用于 Voice Call 和 Google Meet 等后端音频桥接。
|
||||
|
||||
| 设置 | 配置路径 | 默认值 |
|
||||
| --------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
|
||||
| 模型 | `plugins.entries.voice-call.config.realtime.providers.google.model` | `gemini-2.5-flash-native-audio-preview-12-2025` |
|
||||
| 声音 | `...google.voice` | `Kore` |
|
||||
| 语音 | `...google.voice` | `Kore` |
|
||||
| Temperature | `...google.temperature` | (未设置) |
|
||||
| VAD 起始灵敏度 | `...google.startSensitivity` | (未设置) |
|
||||
| VAD 开始灵敏度 | `...google.startSensitivity` | (未设置) |
|
||||
| VAD 结束灵敏度 | `...google.endSensitivity` | (未设置) |
|
||||
| 静音时长 | `...google.silenceDurationMs` | (未设置) |
|
||||
| API 密钥 | `...google.apiKey` | 回退到 `models.providers.google.apiKey`、`GEMINI_API_KEY` 或 `GOOGLE_API_KEY` |
|
||||
|
||||
示例 Voice Call 实时配置:
|
||||
Voice Call 实时配置示例:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -343,32 +343,30 @@ Gemini Live API 支持的实时语音提供商,用于 Voice Call 和 Google Me
|
||||
|
||||
<Note>
|
||||
Google Live API 通过 WebSocket 使用双向音频和函数调用。
|
||||
OpenClaw 会将电话/Meet 桥接音频适配到 Gemini 的 PCM Live API 流,并
|
||||
让工具调用保持在共享的实时语音契约上。除非你需要调整采样行为,否则请保持 `temperature`
|
||||
未设置;OpenClaw 会省略非正值,
|
||||
因为当 `temperature: 0` 时,Google Live 可能返回只有转录而没有音频的结果。
|
||||
Gemini API 转写会在不设置 `languageCodes` 的情况下启用;当前 Google
|
||||
SDK 在这条 API 路径上会拒绝语言代码提示。
|
||||
OpenClaw 会将电话/Meet 桥接音频适配到 Gemini 的 PCM Live API 流中,并
|
||||
在共享实时语音约定上保留工具调用。除非你需要调整采样,否则请保持 `temperature`
|
||||
未设置;OpenClaw 会省略非正值,因为 Google Live 在 `temperature: 0` 时
|
||||
可能返回只有转录而没有音频的结果。
|
||||
Gemini API 转录在不设置 `languageCodes` 的情况下启用;当前 Google
|
||||
SDK 会在此 API 路径上拒绝语言代码提示。
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
Control UI Talk 浏览器会话仍然需要带有
|
||||
浏览器 WebRTC 会话实现的实时语音提供商。目前这条路径是 OpenAI Realtime;Google
|
||||
提供商用于后端实时桥接。
|
||||
Control UI Talk 浏览器会话仍然需要带有浏览器 WebRTC 会话实现的实时语音 provider。当前该路径是 OpenAI Realtime;Google provider 用于后端实时桥接。
|
||||
</Note>
|
||||
|
||||
## 高级配置
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="直接复用 Gemini 缓存">
|
||||
对于直接的 Gemini API 运行(`api: "google-generative-ai"`),OpenClaw
|
||||
对于直接 Gemini API 运行(`api: "google-generative-ai"`),OpenClaw
|
||||
会将已配置的 `cachedContent` 句柄透传给 Gemini 请求。
|
||||
|
||||
- 使用以下任一项按模型或全局配置参数:
|
||||
- 使用以下任一字段按模型或全局配置参数:
|
||||
`cachedContent` 或旧版 `cached_content`
|
||||
- 如果两者都存在,则 `cachedContent` 优先
|
||||
- 如果两者都存在,`cachedContent` 优先
|
||||
- 示例值:`cachedContents/prebuilt-context`
|
||||
- Gemini 缓存命中用量会从上游 `cachedContentTokenCount` 规范化到 OpenClaw `cacheRead`
|
||||
- Gemini 缓存命中用量会从上游 `cachedContentTokenCount` 规范化为 OpenClaw `cacheRead`
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -389,20 +387,20 @@ Control UI Talk 浏览器会话仍然需要带有
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Gemini CLI JSON 使用说明">
|
||||
使用 `google-gemini-cli` OAuth 提供商时,OpenClaw 会按如下方式规范化
|
||||
使用 `google-gemini-cli` OAuth provider 时,OpenClaw 会按如下方式规范化
|
||||
CLI JSON 输出:
|
||||
|
||||
- 回复文本来自 CLI JSON 的 `response` 字段。
|
||||
- 当 CLI 将 `usage` 留空时,用量会回退到 `stats`。
|
||||
- `stats.cached` 会规范化到 OpenClaw `cacheRead`。
|
||||
- `stats.cached` 会被规范化为 OpenClaw `cacheRead`。
|
||||
- 如果缺少 `stats.input`,OpenClaw 会根据
|
||||
`stats.input_tokens - stats.cached` 推导输入 token 数。
|
||||
`stats.input_tokens - stats.cached` 推导输入 token。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="环境和守护进程设置">
|
||||
如果 Gateway 网关以守护进程方式运行(launchd/systemd),请确保 `GEMINI_API_KEY`
|
||||
对该进程可用(例如在 `~/.openclaw/.env` 中,或通过
|
||||
如果 Gateway 网关 作为守护进程运行(`launchd`/`systemd`),请确保 `GEMINI_API_KEY`
|
||||
对该进程可用(例如,在 `~/.openclaw/.env` 中或通过
|
||||
`env.shellEnv`)。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
@ -1,121 +1,121 @@
|
||||
---
|
||||
read_when:
|
||||
- 你想在 OpenClaw 中使用 OpenAI 模型
|
||||
- 你想使用 Codex 订阅认证,而不是 API 密钥
|
||||
- 你需要更严格的 GPT-5 智能体执行行为
|
||||
summary: 在 OpenClaw 中通过 API 密钥或 Codex 订阅使用 OpenAI
|
||||
- 你想在 OpenClaw 中使用 OpenAI 模型。
|
||||
- 你想使用 Codex 订阅认证,而不是 API keys。
|
||||
- 你需要更严格的 GPT-5 智能体执行行为。
|
||||
summary: 在 OpenClaw 中通过 API keys 或 Codex 订阅使用 OpenAI
|
||||
title: OpenAI
|
||||
x-i18n:
|
||||
generated_at: "2026-04-26T03:53:47Z"
|
||||
generated_at: "2026-04-26T07:51:11Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: ac4a3c2c915c4e35b76b37ddccc49a6e37bcd55c8c41eb487ed788cac7d77156
|
||||
source_hash: e4c3e734217ca82e1a5965c41686341a8bd87b4d2194c6d9e286e1087fa53320
|
||||
source_path: providers/openai.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
OpenAI 为 GPT 模型提供开发者 API,而 Codex 也可作为通过 OpenAI Codex 客户端使用的 ChatGPT 计划编程智能体。OpenClaw 将这些能力面分开处理,以便让配置保持可预测。
|
||||
OpenAI 为 GPT 模型提供开发者 API,而 Codex 也可作为 ChatGPT 套餐中的 coding agent,通过 OpenAI 的 Codex 客户端使用。OpenClaw 将这些表面分开处理,以保持配置行为可预测。
|
||||
|
||||
OpenClaw 支持三种 OpenAI 系列路径。模型前缀用于选择提供商 / 认证路径;另一个独立的运行时设置则用于选择由谁执行嵌入式 Agent loop:
|
||||
OpenClaw 支持三种 OpenAI 系列路径。模型前缀用于选择 provider/认证路径;单独的运行时设置用于选择由谁执行内嵌智能体循环:
|
||||
|
||||
- **API 密钥** — 通过按量计费直接访问 OpenAI 平台(`openai/*` 模型)
|
||||
- **通过 PI 使用 Codex 订阅** — 使用 ChatGPT/Codex 登录并通过订阅访问(`openai-codex/*` 模型)
|
||||
- **Codex app-server harness** — 原生 Codex app-server 执行(`openai/*` 模型,加上 `agents.defaults.embeddedHarness.runtime: "codex"`)
|
||||
- **API key** — 通过 OpenAI Platform 直接访问,按使用量计费(`openai/*` 模型)
|
||||
- **通过 PI 使用 Codex 订阅** — 使用 ChatGPT/Codex 登录和订阅访问(`openai-codex/*` 模型)
|
||||
- **Codex app-server harness** — 原生 Codex app-server 执行(`openai/*` 模型加上 `agents.defaults.agentRuntime.id: "codex"`)
|
||||
|
||||
OpenAI 明确支持在 OpenClaw 这样的外部工具和工作流中使用基于订阅的 OAuth。
|
||||
OpenAI 明确支持在 OpenClaw 这类外部工具和工作流中使用订阅 OAuth。
|
||||
|
||||
提供商、模型、运行时和渠道是彼此独立的层。如果这些标签让你混淆了,请先阅读 [Agent Runtimes](/zh-CN/concepts/agent-runtimes),再修改配置。
|
||||
provider、模型、运行时和渠道是彼此独立的层。如果你把这些标签混在一起了,请在修改配置前先阅读 [Agent Runtimes](/zh-CN/concepts/agent-runtimes)。
|
||||
|
||||
## 快速选择
|
||||
|
||||
| 目标 | 使用方式 | 说明 |
|
||||
| --------------------------------------------- | -------------------------------------------------------- | ---------------------------------------------------------------------------- |
|
||||
| 直接使用 API 密钥计费 | `openai/gpt-5.5` | 设置 `OPENAI_API_KEY` 或运行 OpenAI API 密钥新手引导。 |
|
||||
| 使用 ChatGPT/Codex 订阅认证的 GPT-5.5 | `openai-codex/gpt-5.5` | Codex OAuth 的默认 PI 路径。对于订阅场景,这是最佳首选。 |
|
||||
| 使用原生 Codex app-server 行为的 GPT-5.5 | `openai/gpt-5.5` 加 `embeddedHarness.runtime: "codex"` | 为该模型引用强制使用 Codex app-server harness。 |
|
||||
| --------------------------------------------- | ------------------------------------------------ | ---------------------------------------------------------------------------- |
|
||||
| 直接使用 API key 计费 | `openai/gpt-5.5` | 设置 `OPENAI_API_KEY`,或运行 OpenAI API key 新手引导。 |
|
||||
| 使用 ChatGPT/Codex 订阅认证的 GPT-5.5 | `openai-codex/gpt-5.5` | 这是 Codex OAuth 的默认 PI 路径。是订阅配置的首选方案。 |
|
||||
| 使用原生 Codex app-server 行为的 GPT-5.5 | `openai/gpt-5.5` 加 `agentRuntime.id: "codex"` | 为该模型引用强制使用 Codex app-server harness。 |
|
||||
| 图像生成或编辑 | `openai/gpt-image-2` | 可配合 `OPENAI_API_KEY` 或 OpenAI Codex OAuth 使用。 |
|
||||
| 透明背景图像 | `openai/gpt-image-1.5` | 使用 `outputFormat=png` 或 `webp`,并设置 `openai.background=transparent`。 |
|
||||
|
||||
## 命名对照表
|
||||
## 命名对照
|
||||
|
||||
这些名称看起来相似,但不能互换:
|
||||
|
||||
| 你看到的名称 | 层级 | 含义 |
|
||||
| 你看到的名称 | 所属层级 | 含义 |
|
||||
| ---------------------------------- | ----------------- | ------------------------------------------------------------------------------------------------- |
|
||||
| `openai` | 提供商前缀 | 直接使用 OpenAI 平台 API 的路径。 |
|
||||
| `openai-codex` | 提供商前缀 | 通过常规 OpenClaw Pi 运行器使用 OpenAI Codex OAuth / 订阅路径。 |
|
||||
| `openai` | 提供商前缀 | 直接 OpenAI Platform API 路径。 |
|
||||
| `openai-codex` | 提供商前缀 | 通过普通 OpenClaw Pi 运行器走 OpenAI Codex OAuth/订阅路径。 |
|
||||
| `codex` plugin | 插件 | OpenClaw 内置插件,提供原生 Codex app-server 运行时和 `/codex` 聊天控制。 |
|
||||
| `embeddedHarness.runtime: codex` | 智能体运行时 | 为嵌入式回合强制使用原生 Codex app-server harness。 |
|
||||
| `/codex ...` | 聊天命令集 | 在会话中绑定 / 控制 Codex app-server 线程。 |
|
||||
| `runtime: "acp", agentId: "codex"` | ACP 会话路径 | 通过 ACP/acpx 运行 Codex 的显式回退路径。 |
|
||||
| `agentRuntime.id: codex` | Agent Runtimes | 为内嵌轮次强制使用原生 Codex app-server harness。 |
|
||||
| `/codex ...` | 聊天命令集 | 在对话中绑定/控制 Codex app-server 线程。 |
|
||||
| `runtime: "acp", agentId: "codex"` | ACP 会话路径 | 通过 ACP/acpx 运行 Codex 的显式后备路径。 |
|
||||
|
||||
这意味着,一个配置中可以有意同时包含 `openai-codex/*` 和 `codex` plugin。当你既想通过 PI 使用 Codex OAuth,又想启用原生 `/codex` 聊天控制时,这是有效的。`openclaw doctor` 会对这种组合发出警告,以便你确认这是有意为之;它不会重写该配置。
|
||||
这意味着一个配置中可以有意同时包含 `openai-codex/*` 和 `codex` 插件。当你希望通过 PI 使用 Codex OAuth,同时又希望原生 `/codex` 聊天控制可用时,这是有效的。`openclaw doctor` 会对这种组合发出警告,以便你确认这是有意为之;它不会重写该配置。
|
||||
|
||||
<Note>
|
||||
GPT-5.5 同时支持直接通过 OpenAI 平台 API 密钥访问,以及订阅 / OAuth 路径。对于直接 `OPENAI_API_KEY` 流量,请使用 `openai/gpt-5.5`;对于通过 PI 的 Codex OAuth,请使用 `openai-codex/gpt-5.5`;对于原生 Codex app-server harness,请使用 `openai/gpt-5.5` 并设置 `embeddedHarness.runtime: "codex"`。
|
||||
GPT-5.5 同时可通过直接 OpenAI Platform API key 访问,以及订阅/OAuth 路径访问。对直接 `OPENAI_API_KEY` 流量,请使用 `openai/gpt-5.5`;对通过 PI 的 Codex OAuth,请使用 `openai-codex/gpt-5.5`;对原生 Codex app-server harness,请使用带 `agentRuntime.id: "codex"` 的 `openai/gpt-5.5`。
|
||||
</Note>
|
||||
|
||||
<Note>
|
||||
启用 OpenAI plugin,或选择 `openai-codex/*` 模型,并不会启用内置的 Codex app-server plugin。只有当你显式选择原生 Codex harness(通过 `embeddedHarness.runtime: "codex"`),或使用旧版 `codex/*` 模型引用时,OpenClaw 才会启用该插件。
|
||||
如果内置的 `codex` plugin 已启用,但 `openai-codex/*` 仍然通过 PI 解析,`openclaw doctor` 会发出警告并保持该路径不变。
|
||||
启用 OpenAI 插件或选择 `openai-codex/*` 模型,并不会启用内置 Codex app-server 插件。只有当你显式选择原生 Codex harness(`agentRuntime.id: "codex"`)或使用旧版 `codex/*` 模型引用时,OpenClaw 才会启用该插件。
|
||||
如果内置 `codex` 插件已启用,但 `openai-codex/*` 仍通过 PI 解析,`openclaw doctor` 会发出警告,但会保持该路径不变。
|
||||
</Note>
|
||||
|
||||
## OpenClaw 功能覆盖范围
|
||||
|
||||
| OpenAI 能力 | OpenClaw 能力面 | Status |
|
||||
| OpenAI 能力 | OpenClaw 表面 | 状态 |
|
||||
| ------------------------- | ---------------------------------------------------------- | ------------------------------------------------------ |
|
||||
| 聊天 / Responses | `openai/<model>` 模型提供商 | 是 |
|
||||
| Codex 订阅模型 | 带有 `openai-codex` OAuth 的 `openai-codex/<model>` | 是 |
|
||||
| Codex app-server harness | 带有 `embeddedHarness.runtime: codex` 的 `openai/<model>` | 是 |
|
||||
| 服务端 Web 搜索 | 原生 OpenAI Responses 工具 | 是,当启用 Web 搜索且未固定提供商时 |
|
||||
| Codex 订阅模型 | 使用 `openai-codex` OAuth 的 `openai-codex/<model>` | 是 |
|
||||
| Codex app-server harness | 带 `agentRuntime.id: codex` 的 `openai/<model>` | 是 |
|
||||
| 服务端 Web 搜索 | 原生 OpenAI Responses 工具 | 是,当启用 Web 搜索且未固定 provider 时 |
|
||||
| 图像 | `image_generate` | 是 |
|
||||
| 视频 | `video_generate` | 是 |
|
||||
| 文本转语音 | `messages.tts.provider: "openai"` / `tts` | 是 |
|
||||
| 批量语音转文本 | `tools.media.audio` / 媒体理解 | 是 |
|
||||
| 流式语音转文本 | Voice Call `streaming.provider: "openai"` | 是 |
|
||||
| 实时语音 | Voice Call `realtime.provider: "openai"` / Control UI Talk | 是 |
|
||||
| Embeddings | 记忆嵌入提供商 | 是 |
|
||||
| Embeddings | memory embedding provider | 是 |
|
||||
|
||||
## 入门指南
|
||||
|
||||
选择你偏好的认证方式,并按照设置步骤进行。
|
||||
选择你偏好的认证方式,并按照设置步骤进行操作。
|
||||
|
||||
<Tabs>
|
||||
<Tab title="API 密钥(OpenAI 平台)">
|
||||
**最适合:** 直接 API 访问和按量计费。
|
||||
<Tab title="API key(OpenAI Platform)">
|
||||
**最适合:** 直接 API 访问和按使用量计费。
|
||||
|
||||
<Steps>
|
||||
<Step title="获取你的 API 密钥">
|
||||
在 [OpenAI 平台控制台](https://platform.openai.com/api-keys) 创建或复制一个 API 密钥。
|
||||
<Step title="获取你的 API key">
|
||||
在 [OpenAI Platform dashboard](https://platform.openai.com/api-keys) 创建或复制一个 API key。
|
||||
</Step>
|
||||
<Step title="运行新手引导">
|
||||
```bash
|
||||
openclaw onboard --auth-choice openai-api-key
|
||||
```
|
||||
|
||||
或直接传入密钥:
|
||||
或直接传入 key:
|
||||
|
||||
```bash
|
||||
openclaw onboard --openai-api-key "$OPENAI_API_KEY"
|
||||
```
|
||||
</Step>
|
||||
<Step title="验证模型可用">
|
||||
<Step title="验证模型是否可用">
|
||||
```bash
|
||||
openclaw models list --provider openai
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
### 路径摘要
|
||||
### 路径概览
|
||||
|
||||
| 模型引用 | 运行时配置 | 路径 | 认证 |
|
||||
| ---------------------- | -------------------------- | --------------------------- | ---------------- |
|
||||
| `openai/gpt-5.5` | 省略 / `runtime: "pi"` | 直接 OpenAI 平台 API | `OPENAI_API_KEY` |
|
||||
| `openai/gpt-5.4-mini` | 省略 / `runtime: "pi"` | 直接 OpenAI 平台 API | `OPENAI_API_KEY` |
|
||||
| `openai/gpt-5.5` | `runtime: "codex"` | Codex app-server harness | Codex app-server |
|
||||
| `openai/gpt-5.5` | 省略 / `agentRuntime.id: "pi"` | 直接 OpenAI Platform API | `OPENAI_API_KEY` |
|
||||
| `openai/gpt-5.4-mini` | 省略 / `agentRuntime.id: "pi"` | 直接 OpenAI Platform API | `OPENAI_API_KEY` |
|
||||
| `openai/gpt-5.5` | `agentRuntime.id: "codex"` | Codex app-server harness | Codex app-server |
|
||||
|
||||
<Note>
|
||||
`openai/*` 默认是直接 OpenAI API 密钥路径,除非你显式强制使用 Codex app-server harness。通过默认 Pi 运行器使用 Codex OAuth 时,请使用 `openai-codex/*`;若要原生 Codex app-server 执行,请使用 `openai/gpt-5.5` 并设置 `embeddedHarness.runtime: "codex"`。
|
||||
`openai/*` 是直接 OpenAI API key 路径,除非你显式强制使用 Codex app-server harness。对通过默认 Pi 运行器的 Codex OAuth,请使用 `openai-codex/*`;对原生 Codex app-server 执行,请使用带 `agentRuntime.id: "codex"` 的 `openai/gpt-5.5`。
|
||||
</Note>
|
||||
|
||||
### 配置示例
|
||||
@ -128,13 +128,13 @@ x-i18n:
|
||||
```
|
||||
|
||||
<Warning>
|
||||
OpenClaw **不** 暴露 `openai/gpt-5.3-codex-spark`。实时 OpenAI API 请求会拒绝该模型,当前 Codex 目录也未暴露它。
|
||||
OpenClaw **不会**暴露 `openai/gpt-5.3-codex-spark`。实时 OpenAI API 请求会拒绝该模型,当前 Codex 目录也未公开它。
|
||||
</Warning>
|
||||
|
||||
</Tab>
|
||||
|
||||
<Tab title="Codex 订阅">
|
||||
**最适合:** 使用你的 ChatGPT/Codex 订阅,而不是单独的 API 密钥。Codex cloud 需要 ChatGPT 登录。
|
||||
**最适合:** 使用你的 ChatGPT/Codex 订阅,而不是单独的 API key。Codex cloud 需要 ChatGPT 登录。
|
||||
|
||||
<Steps>
|
||||
<Step title="运行 Codex OAuth">
|
||||
@ -148,7 +148,7 @@ x-i18n:
|
||||
openclaw models auth login --provider openai-codex
|
||||
```
|
||||
|
||||
对于无头环境或不适合回调的场景,可添加 `--device-code`,通过 ChatGPT 设备码流程登录,而不是使用 localhost 浏览器回调:
|
||||
对于无头环境或不适合回调的设置,可添加 `--device-code`,通过 ChatGPT device-code 流程登录,而不是使用 localhost 浏览器回调:
|
||||
|
||||
```bash
|
||||
openclaw models auth login --provider openai-codex --device-code
|
||||
@ -159,25 +159,24 @@ x-i18n:
|
||||
openclaw config set agents.defaults.model.primary openai-codex/gpt-5.5
|
||||
```
|
||||
</Step>
|
||||
<Step title="验证模型可用">
|
||||
<Step title="验证模型是否可用">
|
||||
```bash
|
||||
openclaw models list --provider openai-codex
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
### 路径摘要
|
||||
### 路径概览
|
||||
|
||||
| 模型引用 | 运行时配置 | 路径 | 认证 |
|
||||
|-----------|----------------|-------|------|
|
||||
| `openai-codex/gpt-5.5` | 省略 / `runtime: "pi"` | 通过 PI 使用 ChatGPT/Codex OAuth | Codex 登录 |
|
||||
| `openai-codex/gpt-5.5` | `runtime: "auto"` | 除非某个插件显式声明 `openai-codex`,否则仍为 PI | Codex 登录 |
|
||||
| `openai/gpt-5.5` | `embeddedHarness.runtime: "codex"` | Codex app-server harness | Codex app-server 认证 |
|
||||
| `openai-codex/gpt-5.5` | 省略 / `runtime: "pi"` | 通过 Pi 的 ChatGPT/Codex OAuth | Codex 登录 |
|
||||
| `openai-codex/gpt-5.5` | `runtime: "auto"` | 仍然是 Pi,除非有插件显式接管 `openai-codex` | Codex 登录 |
|
||||
| `openai/gpt-5.5` | `agentRuntime.id: "codex"` | Codex app-server harness | Codex app-server 认证 |
|
||||
|
||||
<Note>
|
||||
认证 / 配置文件命令请继续使用 `openai-codex` 提供商 id。
|
||||
`openai-codex/*` 模型前缀也是通过 PI 使用 Codex OAuth 的显式路径。
|
||||
它不会选择或自动启用内置的 Codex app-server harness。
|
||||
对认证/配置文件命令,继续使用 `openai-codex` provider ID。`openai-codex/*` 模型前缀也是通过 Codex OAuth 走 Pi 的显式路径。
|
||||
它不会选择或自动启用内置 Codex app-server harness。
|
||||
</Note>
|
||||
|
||||
### 配置示例
|
||||
@ -189,31 +188,30 @@ x-i18n:
|
||||
```
|
||||
|
||||
<Note>
|
||||
新手引导不再从 `~/.codex` 导入 OAuth 材料。请使用浏览器 OAuth(默认)或上述设备码流程登录——OpenClaw 会在自己的智能体认证存储中管理生成的凭证。
|
||||
新手引导不再从 `~/.codex` 导入 OAuth 材料。请使用浏览器 OAuth(默认)或上面的 device-code 流程登录——OpenClaw 会在自己的智能体认证存储中管理生成的凭证。
|
||||
</Note>
|
||||
|
||||
### Status 指示器
|
||||
### 状态指示器
|
||||
|
||||
聊天中的 `/status` 会显示当前会话正在使用的模型运行时。
|
||||
聊天 `/status` 会显示当前会话正在使用的模型运行时。
|
||||
默认的 Pi harness 会显示为 `Runtime: OpenClaw Pi Default`。当选择内置 Codex app-server harness 时,`/status` 会显示
|
||||
`Runtime: OpenAI Codex`。现有会话会保留其已记录的 harness id,因此如果你修改了 `embeddedHarness` 后希望 `/status` 反映新的 PI / Codex 选择,请使用 `/new` 或 `/reset`。
|
||||
`Runtime: OpenAI Codex`。现有会话会保留其已记录的 harness ID,因此如果你在更改 `agentRuntime` 后希望 `/status` 反映新的 Pi/Codex 选择,请使用 `/new` 或 `/reset`。
|
||||
|
||||
### Doctor 警告
|
||||
|
||||
如果选择了本标签页中的 `openai-codex/*` 路径,同时又启用了内置的 `codex` plugin,`openclaw doctor` 会警告该模型仍然通过 PI 解析。
|
||||
如果这正是你想要的订阅认证路径,请保持配置不变。只有当你想使用原生 Codex app-server 执行时,才切换到 `openai/<model>` 加
|
||||
`embeddedHarness.runtime: "codex"`。
|
||||
如果启用了内置 `codex` 插件,而本标签页中的
|
||||
`openai-codex/*` 路径已被选中,`openclaw doctor` 会警告该模型仍通过 Pi 解析。当这正是你希望使用的订阅认证路径时,请保持配置不变。只有在你想使用原生 Codex app-server 执行时,才切换到 `openai/<model>` 加 `agentRuntime.id: "codex"`。
|
||||
|
||||
### 上下文窗口上限
|
||||
|
||||
OpenClaw 将模型元数据和运行时上下文上限视为两个独立的值。
|
||||
OpenClaw 将模型元数据和运行时上下文上限视为两个独立值。
|
||||
|
||||
对于通过 Codex OAuth 使用的 `openai-codex/gpt-5.5`:
|
||||
|
||||
- 原生 `contextWindow`:`1000000`
|
||||
- 默认运行时 `contextTokens` 上限:`272000`
|
||||
|
||||
较小的默认上限在实践中通常具有更好的延迟和质量特性。你可以通过 `contextTokens` 覆盖它:
|
||||
较小的默认上限在实践中具有更好的延迟和质量特性。你可以使用 `contextTokens` 覆盖它:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -233,26 +231,25 @@ x-i18n:
|
||||
|
||||
### 目录恢复
|
||||
|
||||
当上游 Codex 目录中存在 `gpt-5.5` 的元数据时,OpenClaw 会使用它。
|
||||
如果实时 Codex 发现遗漏了 `openai-codex/gpt-5.5` 这一行,而账户又已经完成认证,OpenClaw 会合成这一 OAuth 模型行,以避免 cron、子智能体和已配置的默认模型运行因 `Unknown model` 而失败。
|
||||
当上游 Codex 目录中存在 `gpt-5.5` 元数据时,OpenClaw 会使用它。如果实时 Codex 发现结果在账户已认证的情况下遗漏了 `openai-codex/gpt-5.5` 这一行,OpenClaw 会合成该 OAuth 模型行,以避免 cron、子智能体和已配置默认模型运行因 `Unknown model` 而失败。
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## 图像生成
|
||||
|
||||
内置的 `openai` plugin 通过 `image_generate` 工具注册图像生成功能。
|
||||
它通过同一个 `openai/gpt-image-2` 模型引用,同时支持 OpenAI API 密钥图像生成和 Codex OAuth 图像生成。
|
||||
内置 `openai` 插件通过 `image_generate` 工具注册图像生成功能。
|
||||
它支持使用相同的 `openai/gpt-image-2` 模型引用,通过 OpenAI API key 图像生成和 Codex OAuth 图像生成。
|
||||
|
||||
| 能力 | OpenAI API 密钥 | Codex OAuth |
|
||||
| 能力 | OpenAI API key | Codex OAuth |
|
||||
| ------------------------- | ---------------------------------- | ------------------------------------ |
|
||||
| 模型引用 | `openai/gpt-image-2` | `openai/gpt-image-2` |
|
||||
| 认证 | `OPENAI_API_KEY` | OpenAI Codex OAuth 登录 |
|
||||
| 传输 | OpenAI Images API | Codex Responses 后端 |
|
||||
| 每次请求的最大图像数 | 4 | 4 |
|
||||
| 编辑模式 | 已启用(最多 5 张参考图) | 已启用(最多 5 张参考图) |
|
||||
| 编辑模式 | 已启用(最多 5 张参考图像) | 已启用(最多 5 张参考图像) |
|
||||
| 尺寸覆盖 | 支持,包括 2K/4K 尺寸 | 支持,包括 2K/4K 尺寸 |
|
||||
| 宽高比 / 分辨率 | 不会转发到 OpenAI Images API | 在安全情况下映射到受支持的尺寸 |
|
||||
| 宽高比 / 分辨率 | 不会转发到 OpenAI Images API | 在安全时映射到受支持的尺寸 |
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -265,19 +262,17 @@ x-i18n:
|
||||
```
|
||||
|
||||
<Note>
|
||||
有关共享工具参数、提供商选择和故障切换行为,请参阅 [Image Generation](/zh-CN/tools/image-generation)。
|
||||
有关共享工具参数、提供商选择和故障切换行为,请参见 [图像生成](/zh-CN/tools/image-generation)。
|
||||
</Note>
|
||||
|
||||
`gpt-image-2` 是 OpenAI 文生图生成和图像编辑的默认模型。
|
||||
`gpt-image-1.5`、`gpt-image-1` 和 `gpt-image-1-mini` 仍可作为显式模型覆盖使用。对于透明背景 PNG/WebP 输出,请使用 `openai/gpt-image-1.5`;当前的 `gpt-image-2` API 会拒绝
|
||||
`gpt-image-2` 是 OpenAI 文生图和图像编辑的默认模型。`gpt-image-1.5`、`gpt-image-1` 和 `gpt-image-1-mini` 仍可作为显式模型覆盖使用。对于透明背景 PNG/WebP 输出,请使用 `openai/gpt-image-1.5`;当前的 `gpt-image-2` API 会拒绝
|
||||
`background: "transparent"`。
|
||||
|
||||
对于透明背景请求,智能体应调用 `image_generate`,并设置
|
||||
对于透明背景请求,智能体应调用 `image_generate`,并使用
|
||||
`model: "openai/gpt-image-1.5"`、`outputFormat: "png"` 或 `"webp"`,以及
|
||||
`background: "transparent"`;旧的 `openai.background` 提供商选项仍然受支持。OpenClaw 还会通过将默认的 `openai/gpt-image-2` 透明请求重写为 `gpt-image-1.5`,来保护公共 OpenAI 和
|
||||
OpenAI Codex OAuth 路径;Azure 和自定义 OpenAI 兼容端点则保留其已配置的部署 / 模型名称。
|
||||
`background: "transparent"`;较旧的 `openai.background` provider 选项仍然受支持。OpenClaw 还会通过将默认的 `openai/gpt-image-2` 透明请求重写为 `gpt-image-1.5`,来保护公共 OpenAI 和 OpenAI Codex OAuth 路径;Azure 和自定义 OpenAI 兼容端点则会保留其已配置的 deployment/模型名称。
|
||||
|
||||
同样的设置也暴露给无头 CLI 运行:
|
||||
同样的设置也适用于无头 CLI 运行:
|
||||
|
||||
```bash
|
||||
openclaw infer image generate \
|
||||
@ -288,14 +283,11 @@ openclaw infer image generate \
|
||||
--json
|
||||
```
|
||||
|
||||
从输入文件开始时,对 `openclaw infer image edit` 使用相同的 `--output-format` 和 `--background` 标志。
|
||||
`--openai-background` 仍可用作 OpenAI 专用别名。
|
||||
当从输入文件开始时,对 `openclaw infer image edit` 使用相同的 `--output-format` 和 `--background` 标志。
|
||||
`--openai-background` 仍可作为 OpenAI 专用别名使用。
|
||||
|
||||
对于 Codex OAuth 安装,继续使用相同的 `openai/gpt-image-2` 引用。当配置了
|
||||
`openai-codex` OAuth 配置文件时,OpenClaw 会解析该已存储的 OAuth 访问令牌,并通过 Codex Responses 后端发送图像请求。它不会先尝试 `OPENAI_API_KEY`,也不会在该请求上静默回退到 API 密钥。
|
||||
当你想改为直接使用 OpenAI Images API 路径时,请显式配置 `models.providers.openai`,并提供 API 密钥、自定义基础 URL 或 Azure 端点。
|
||||
如果该自定义图像端点位于受信任的局域网 / 私有地址上,还需设置
|
||||
`browser.ssrfPolicy.dangerouslyAllowPrivateNetwork: true`;若没有这一显式启用项,OpenClaw 会继续阻止私有 / 内部的 OpenAI 兼容图像端点。
|
||||
对于 Codex OAuth 安装,继续使用相同的 `openai/gpt-image-2` 引用。当配置了 `openai-codex` OAuth 配置文件时,OpenClaw 会解析该已存储的 OAuth 访问令牌,并通过 Codex Responses 后端发送图像请求。它不会先尝试 `OPENAI_API_KEY`,也不会在该请求中静默回退到 API key。如果你想改为使用直接 OpenAI Images API 路径,请显式配置 `models.providers.openai`,并设置 API key、自定义 base URL 或 Azure 端点。
|
||||
如果该自定义图像端点位于受信任 LAN/私有地址上,还需设置 `browser.ssrfPolicy.dangerouslyAllowPrivateNetwork: true`;如果没有这一显式启用项,OpenClaw 会继续阻止私有/内部 OpenAI 兼容图像端点。
|
||||
|
||||
生成:
|
||||
|
||||
@ -317,15 +309,15 @@ openclaw infer image generate \
|
||||
|
||||
## 视频生成
|
||||
|
||||
内置的 `openai` plugin 通过 `video_generate` 工具注册视频生成功能。
|
||||
内置 `openai` 插件通过 `video_generate` 工具注册视频生成功能。
|
||||
|
||||
| 能力 | 值 |
|
||||
| ---------------- | --------------------------------------------------------------------------------- |
|
||||
| 默认模型 | `openai/sora-2` |
|
||||
| 模式 | 文生视频、图生视频、单视频编辑 |
|
||||
| 参考输入 | 1 张图片或 1 个视频 |
|
||||
| 参考输入 | 1 张图像或 1 个视频 |
|
||||
| 尺寸覆盖 | 支持 |
|
||||
| 其他覆盖 | `aspectRatio`、`resolution`、`audio`、`watermark` 会被忽略,并给出工具警告 |
|
||||
| 其他覆盖 | `aspectRatio`、`resolution`、`audio`、`watermark` 会被忽略,并产生工具警告 |
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -338,16 +330,16 @@ openclaw infer image generate \
|
||||
```
|
||||
|
||||
<Note>
|
||||
有关共享工具参数、提供商选择和故障切换行为,请参阅 [Video Generation](/zh-CN/tools/video-generation)。
|
||||
有关共享工具参数、提供商选择和故障切换行为,请参见 [视频生成](/zh-CN/tools/video-generation)。
|
||||
</Note>
|
||||
|
||||
## GPT-5 提示词贡献
|
||||
## GPT-5 提示词叠加
|
||||
|
||||
OpenClaw 会为跨提供商的 GPT-5 系列运行添加一个共享的 GPT-5 提示词贡献。它按模型 id 生效,因此 `openai-codex/gpt-5.5`、`openai/gpt-5.5`、`openrouter/openai/gpt-5.5`、`opencode/gpt-5.5` 以及其他兼容的 GPT-5 引用都会收到同样的叠加层。较旧的 GPT-4.x 模型则不会。
|
||||
OpenClaw 会为跨提供商的 GPT-5 系列运行添加共享的 GPT-5 提示词叠加。它按模型 ID 生效,因此 `openai-codex/gpt-5.5`、`openai/gpt-5.5`、`openrouter/openai/gpt-5.5`、`opencode/gpt-5.5` 以及其他兼容的 GPT-5 引用都会收到相同的叠加。较旧的 GPT-4.x 模型则不会。
|
||||
|
||||
内置的原生 Codex harness 通过 Codex app-server 开发者指令使用相同的 GPT-5 行为和心跳叠加层,因此,即使 `openai/gpt-5.x` 会话通过 `embeddedHarness.runtime: "codex"` 被强制走 Codex,仍会保持相同的后续执行和主动心跳指导,尽管 harness 提示词的其余部分由 Codex 接管。
|
||||
内置原生 Codex harness 会通过 Codex app-server 开发者指令使用相同的 GPT-5 行为和 heartbeat 叠加,因此即使 Codex 拥有其余 harness 提示词,使用 `agentRuntime.id: "codex"` 强制执行的 `openai/gpt-5.x` 会话仍会保持相同的后续执行和主动 heartbeat 指导。
|
||||
|
||||
GPT-5 贡献为人格持续性、执行安全、工具纪律、输出形态、完成检查和验证添加了一个带标签的行为契约。渠道特定的回复和静默消息行为则保留在共享的 OpenClaw 系统提示词和出站投递策略中。GPT-5 指导始终会对匹配模型启用。友好交互风格层是独立的,并且可配置。
|
||||
GPT-5 叠加会添加一个带标签的行为契约,用于人格持续性、执行安全、工具纪律、输出结构、完成检查和验证。渠道特定的回复和静默消息行为则保留在共享的 OpenClaw 系统提示词和出站投递策略中。GPT-5 指导会始终对匹配的模型启用。友好交互风格层是独立且可配置的。
|
||||
|
||||
| 值 | 效果 |
|
||||
| ---------------------- | ------------------------------------------- |
|
||||
@ -377,30 +369,30 @@ GPT-5 贡献为人格持续性、执行安全、工具纪律、输出形态、
|
||||
</Tabs>
|
||||
|
||||
<Tip>
|
||||
运行时值不区分大小写,因此 `"Off"` 和 `"off"` 都会禁用友好风格层。
|
||||
运行时对值不区分大小写,因此 `"Off"` 和 `"off"` 都会禁用友好风格层。
|
||||
</Tip>
|
||||
|
||||
<Note>
|
||||
当未设置共享的 `agents.defaults.promptOverlays.gpt5.personality` 时,旧版 `plugins.entries.openai.config.personality` 仍会作为兼容性回退被读取。
|
||||
当共享设置 `agents.defaults.promptOverlays.gpt5.personality` 未设置时,仍会读取旧版 `plugins.entries.openai.config.personality` 作为兼容性后备。
|
||||
</Note>
|
||||
|
||||
## 语音和语音识别
|
||||
## 语音与语音识别
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="语音合成(TTS)">
|
||||
内置的 `openai` plugin 为 `messages.tts` 能力面注册了语音合成功能。
|
||||
内置 `openai` 插件为 `messages.tts` 表面注册了语音合成功能。
|
||||
|
||||
| 设置 | 配置路径 | 默认值 |
|
||||
|---------|------------|---------|
|
||||
| 模型 | `messages.tts.providers.openai.model` | `gpt-4o-mini-tts` |
|
||||
| 声音 | `messages.tts.providers.openai.voice` | `coral` |
|
||||
| 语音 | `messages.tts.providers.openai.voice` | `coral` |
|
||||
| 速度 | `messages.tts.providers.openai.speed` | (未设置) |
|
||||
| 指令 | `messages.tts.providers.openai.instructions` | (未设置,仅 `gpt-4o-mini-tts`) |
|
||||
| 格式 | `messages.tts.providers.openai.responseFormat` | 语音便笺为 `opus`,文件为 `mp3` |
|
||||
| API 密钥 | `messages.tts.providers.openai.apiKey` | 回退到 `OPENAI_API_KEY` |
|
||||
| 基础 URL | `messages.tts.providers.openai.baseUrl` | `https://api.openai.com/v1` |
|
||||
| 格式 | `messages.tts.providers.openai.responseFormat` | 语音笔记为 `opus`,文件为 `mp3` |
|
||||
| API key | `messages.tts.providers.openai.apiKey` | 回退到 `OPENAI_API_KEY` |
|
||||
| Base URL | `messages.tts.providers.openai.baseUrl` | `https://api.openai.com/v1` |
|
||||
|
||||
可用模型:`gpt-4o-mini-tts`、`tts-1`、`tts-1-hd`。可用声音:`alloy`、`ash`、`ballad`、`cedar`、`coral`、`echo`、`fable`、`juniper`、`marin`、`onyx`、`nova`、`sage`、`shimmer`、`verse`。
|
||||
可用模型:`gpt-4o-mini-tts`、`tts-1`、`tts-1-hd`。可用语音:`alloy`、`ash`、`ballad`、`cedar`、`coral`、`echo`、`fable`、`juniper`、`marin`、`onyx`、`nova`、`sage`、`shimmer`、`verse`。
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -415,22 +407,22 @@ GPT-5 贡献为人格持续性、执行安全、工具纪律、输出形态、
|
||||
```
|
||||
|
||||
<Note>
|
||||
设置 `OPENAI_TTS_BASE_URL` 可覆盖 TTS 基础 URL,而不会影响聊天 API 端点。
|
||||
设置 `OPENAI_TTS_BASE_URL` 可覆盖 TTS base URL,而不影响聊天 API 端点。
|
||||
</Note>
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="语音转文本">
|
||||
内置的 `openai` plugin 通过
|
||||
OpenClaw 的媒体理解转写能力面注册了批量语音转文本功能。
|
||||
内置 `openai` 插件通过
|
||||
OpenClaw 的媒体理解转录表面注册了批量语音转文本功能。
|
||||
|
||||
- 默认模型:`gpt-4o-transcribe`
|
||||
- 端点:OpenAI REST `/v1/audio/transcriptions`
|
||||
- 输入路径:multipart 音频文件上传
|
||||
- 在 OpenClaw 中,凡是入站音频转写使用
|
||||
- 在 OpenClaw 中,凡是入站音频转录使用
|
||||
`tools.media.audio` 的地方都支持,包括 Discord 语音频道片段和渠道音频附件
|
||||
|
||||
要强制对入站音频转写使用 OpenAI:
|
||||
若要强制对入站音频转录使用 OpenAI:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -450,12 +442,12 @@ GPT-5 贡献为人格持续性、执行安全、工具纪律、输出形态、
|
||||
}
|
||||
```
|
||||
|
||||
当共享音频媒体配置或按次调用的转写请求提供了语言和提示信息时,这些信息会被转发给 OpenAI。
|
||||
当由共享音频媒体配置或每次调用的转录请求提供语言和提示线索时,它们会被转发给 OpenAI。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="实时转写">
|
||||
内置的 `openai` plugin 为 Voice Call 插件注册了实时转写功能。
|
||||
<Accordion title="实时转录">
|
||||
内置 `openai` 插件为 Voice Call 插件注册了实时转录功能。
|
||||
|
||||
| 设置 | 配置路径 | 默认值 |
|
||||
|---------|------------|---------|
|
||||
@ -464,25 +456,25 @@ GPT-5 贡献为人格持续性、执行安全、工具纪律、输出形态、
|
||||
| 提示词 | `...openai.prompt` | (未设置) |
|
||||
| 静音时长 | `...openai.silenceDurationMs` | `800` |
|
||||
| VAD 阈值 | `...openai.vadThreshold` | `0.5` |
|
||||
| API 密钥 | `...openai.apiKey` | 回退到 `OPENAI_API_KEY` |
|
||||
| API key | `...openai.apiKey` | 回退到 `OPENAI_API_KEY` |
|
||||
|
||||
<Note>
|
||||
使用连接到 `wss://api.openai.com/v1/realtime` 的 WebSocket,以及 G.711 u-law(`g711_ulaw` / `audio/pcmu`)音频。这个流式提供商用于 Voice Call 的实时转写路径;Discord 语音当前仍会录制短片段,并改用批量 `tools.media.audio` 转写路径。
|
||||
使用 WebSocket 连接到 `wss://api.openai.com/v1/realtime`,并使用 G.711 u-law(`g711_ulaw` / `audio/pcmu`)音频。此流式提供商用于 Voice Call 的实时转录路径;Discord 语音当前仍会录制短片段,并改用批量 `tools.media.audio` 转录路径。
|
||||
</Note>
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="实时语音">
|
||||
内置的 `openai` plugin 为 Voice Call 插件注册了实时语音功能。
|
||||
内置 `openai` 插件为 Voice Call 插件注册了实时语音功能。
|
||||
|
||||
| 设置 | 配置路径 | 默认值 |
|
||||
|---------|------------|---------|
|
||||
| 模型 | `plugins.entries.voice-call.config.realtime.providers.openai.model` | `gpt-realtime-1.5` |
|
||||
| 声音 | `...openai.voice` | `alloy` |
|
||||
| 温度 | `...openai.temperature` | `0.8` |
|
||||
| 语音 | `...openai.voice` | `alloy` |
|
||||
| Temperature | `...openai.temperature` | `0.8` |
|
||||
| VAD 阈值 | `...openai.vadThreshold` | `0.5` |
|
||||
| 静音时长 | `...openai.silenceDurationMs` | `500` |
|
||||
| API 密钥 | `...openai.apiKey` | 回退到 `OPENAI_API_KEY` |
|
||||
| API key | `...openai.apiKey` | 回退到 `OPENAI_API_KEY` |
|
||||
|
||||
<Note>
|
||||
支持通过 `azureEndpoint` 和 `azureDeployment` 配置键使用 Azure OpenAI。支持双向工具调用。使用 G.711 u-law 音频格式。
|
||||
@ -493,11 +485,11 @@ GPT-5 贡献为人格持续性、执行安全、工具纪律、输出形态、
|
||||
|
||||
## Azure OpenAI 端点
|
||||
|
||||
内置的 `openai` 提供商可以通过覆盖基础 URL,将目标指向 Azure OpenAI 资源以进行图像生成。在图像生成路径上,OpenClaw 会检测 `models.providers.openai.baseUrl` 上的 Azure 主机名,并自动切换到 Azure 的请求格式。
|
||||
内置 `openai` provider 可以通过覆盖 base URL,将图像生成请求发送到 Azure OpenAI 资源。在图像生成路径上,OpenClaw 会检测 `models.providers.openai.baseUrl` 中的 Azure 主机名,并自动切换为 Azure 的请求结构。
|
||||
|
||||
<Note>
|
||||
实时语音使用单独的配置路径
|
||||
(`plugins.entries.voice-call.config.realtime.providers.openai.azureEndpoint`),不受 `models.providers.openai.baseUrl` 影响。相关 Azure 设置请参阅 [语音和语音识别](#voice-and-speech) 下的 **实时语音** 折叠面板。
|
||||
(`plugins.entries.voice-call.config.realtime.providers.openai.azureEndpoint`),不会受 `models.providers.openai.baseUrl` 影响。有关其实 Azure 设置,请参见 [语音与语音识别](#voice-and-speech) 下的 **实时语音** 手风琴项。
|
||||
</Note>
|
||||
|
||||
在以下情况下使用 Azure OpenAI:
|
||||
@ -508,9 +500,8 @@ GPT-5 贡献为人格持续性、执行安全、工具纪律、输出形态、
|
||||
|
||||
### 配置
|
||||
|
||||
对于通过内置 `openai` 提供商进行的 Azure 图像生成,请将
|
||||
`models.providers.openai.baseUrl` 指向你的 Azure 资源,并将 `apiKey` 设置为
|
||||
Azure OpenAI 密钥(而不是 OpenAI 平台密钥):
|
||||
若要通过内置 `openai` provider 使用 Azure 图像生成,请将
|
||||
`models.providers.openai.baseUrl` 指向你的 Azure 资源,并将 `apiKey` 设置为 Azure OpenAI key(而不是 OpenAI Platform key):
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -525,7 +516,7 @@ Azure OpenAI 密钥(而不是 OpenAI 平台密钥):
|
||||
}
|
||||
```
|
||||
|
||||
OpenClaw 会为 Azure 图像生成路径识别以下 Azure 主机后缀:
|
||||
OpenClaw 会将以下 Azure 主机后缀识别为 Azure 图像生成路径:
|
||||
|
||||
- `*.openai.azure.com`
|
||||
- `*.services.ai.azure.com`
|
||||
@ -533,80 +524,77 @@ OpenClaw 会为 Azure 图像生成路径识别以下 Azure 主机后缀:
|
||||
|
||||
对于发送到已识别 Azure 主机的图像生成请求,OpenClaw 会:
|
||||
|
||||
- 发送 `api-key` 头,而不是 `Authorization: Bearer`
|
||||
- 使用部署范围路径(`/openai/deployments/{deployment}/...`)
|
||||
- 发送 `api-key` 标头,而不是 `Authorization: Bearer`
|
||||
- 使用按 deployment 作用域的路径(`/openai/deployments/{deployment}/...`)
|
||||
- 为每个请求附加 `?api-version=...`
|
||||
- 对 Azure 图像生成调用使用默认 600 秒请求超时。
|
||||
每次调用的 `timeoutMs` 值仍会覆盖此默认值。
|
||||
|
||||
其他基础 URL(公共 OpenAI、OpenAI 兼容代理)则继续使用标准
|
||||
OpenAI 图像请求格式。
|
||||
其他 base URL(公共 OpenAI、OpenAI 兼容代理)则继续使用标准 OpenAI 图像请求结构。
|
||||
|
||||
<Note>
|
||||
`openai` 提供商图像生成路径的 Azure 路由需要
|
||||
OpenClaw 2026.4.22 或更高版本。更早版本会将任何自定义
|
||||
`openai.baseUrl` 视为公共 OpenAI 端点,因此在 Azure 图像部署上会失败。
|
||||
`openai` provider 图像生成路径的 Azure 路由功能需要 OpenClaw 2026.4.22 或更高版本。更早版本会将任何自定义
|
||||
`openai.baseUrl` 都视为公共 OpenAI 端点,并会在 Azure 图像 deployment 上失败。
|
||||
</Note>
|
||||
|
||||
### API 版本
|
||||
|
||||
设置 `AZURE_OPENAI_API_VERSION` 可为 Azure 图像生成路径固定特定的 Azure 预览版或 GA 版本:
|
||||
设置 `AZURE_OPENAI_API_VERSION` 可为 Azure 图像生成路径固定特定 Azure 预览版或 GA 版本:
|
||||
|
||||
```bash
|
||||
export AZURE_OPENAI_API_VERSION="2024-12-01-preview"
|
||||
```
|
||||
|
||||
当该变量未设置时,默认值为 `2024-12-01-preview`。
|
||||
如果该变量未设置,则默认值为 `2024-12-01-preview`。
|
||||
|
||||
### 模型名称就是部署名称
|
||||
### 模型名称就是 deployment 名称
|
||||
|
||||
Azure OpenAI 将模型绑定到部署。对于通过内置 `openai` 提供商路由的 Azure 图像生成请求,OpenClaw 中的 `model` 字段必须是你在 Azure 门户中配置的 **Azure 部署名称**,而不是公共 OpenAI 模型 id。
|
||||
Azure OpenAI 将模型绑定到 deployment。对于通过内置 `openai` provider 路由的 Azure 图像生成请求,OpenClaw 中的 `model` 字段必须是你在 Azure 门户中配置的**Azure deployment 名称**,而不是公共 OpenAI 模型 ID。
|
||||
|
||||
如果你创建了一个名为 `gpt-image-2-prod` 的部署,用于提供 `gpt-image-2`:
|
||||
如果你创建了一个名为 `gpt-image-2-prod`、提供 `gpt-image-2` 的 deployment:
|
||||
|
||||
```
|
||||
/tool image_generate model=openai/gpt-image-2-prod prompt="A clean poster" size=1024x1024 count=1
|
||||
```
|
||||
|
||||
同样的部署名称规则也适用于通过内置 `openai` 提供商路由的图像生成调用。
|
||||
同样的 deployment 名称规则也适用于通过内置 `openai` provider 路由的图像生成调用。
|
||||
|
||||
### 区域可用性
|
||||
|
||||
Azure 图像生成当前仅在部分区域可用
|
||||
Azure 图像生成目前仅在部分区域可用
|
||||
(例如 `eastus2`、`swedencentral`、`polandcentral`、`westus3`、
|
||||
`uaenorth`)。在创建部署之前,请先查看 Microsoft 当前的区域列表,并确认你所在区域提供对应的具体模型。
|
||||
`uaenorth`)。在创建 deployment 之前,请先查看 Microsoft 当前的区域列表,并确认你的区域提供该具体模型。
|
||||
|
||||
### 参数差异
|
||||
|
||||
Azure OpenAI 和公共 OpenAI 并不总是接受相同的图像参数。
|
||||
Azure 可能会拒绝公共 OpenAI 允许的某些选项(例如在 `gpt-image-2` 上的某些
|
||||
`background` 值),或者仅在特定模型版本上提供这些选项。这些差异来自 Azure 和底层模型,而不是 OpenClaw。如果 Azure 请求因验证错误而失败,请在 Azure 门户中检查你的具体部署和 API 版本所支持的参数集。
|
||||
Azure 可能会拒绝公共 OpenAI 允许的选项(例如在 `gpt-image-2` 上的某些
|
||||
`background` 值),或仅在特定模型版本上提供这些选项。这些差异来自 Azure 和底层模型,而不是 OpenClaw。如果 Azure 请求因验证错误失败,请在 Azure 门户中检查你的具体 deployment 和 API 版本所支持的参数集。
|
||||
|
||||
<Note>
|
||||
Azure OpenAI 使用原生传输和兼容行为,但不会接收
|
||||
OpenClaw 的隐藏归因头——请参阅 [高级配置](#advanced-configuration) 下 **原生与 OpenAI 兼容路径** 折叠面板。
|
||||
Azure OpenAI 使用原生传输和兼容行为,但不会接收 OpenClaw 的隐藏归因标头——参见 [高级配置](#advanced-configuration) 下的 **原生与 OpenAI 兼容路径** 手风琴项。
|
||||
|
||||
对于 Azure 上的聊天或 Responses 流量(除图像生成之外),请使用新手引导流程或专用 Azure 提供商配置——单独设置 `openai.baseUrl` 并不会自动采用 Azure API / 认证格式。另有一个单独的
|
||||
`azure-openai-responses/*` 提供商;请参阅下方的服务端压缩折叠面板。
|
||||
对于 Azure 上的聊天或 Responses 流量(图像生成之外),请使用新手引导流程或专用 Azure provider 配置——仅设置 `openai.baseUrl` 并不会采用 Azure 的 API/认证结构。另有一个单独的
|
||||
`azure-openai-responses/*` provider;参见下方的服务端压缩手风琴项。
|
||||
</Note>
|
||||
|
||||
## 高级配置
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="传输(WebSocket 与 SSE)">
|
||||
OpenClaw 对 `openai/*` 和 `openai-codex/*` 均采用 WebSocket 优先、SSE 回退(`"auto"`)策略。
|
||||
对于 `openai/*` 和 `openai-codex/*`,OpenClaw 都采用 WebSocket 优先、SSE 回退(`"auto"`)策略。
|
||||
|
||||
在 `"auto"` 模式下,OpenClaw 会:
|
||||
- 在回退到 SSE 之前,对一次早期 WebSocket 故障重试一次
|
||||
- 在故障后,将 WebSocket 标记为降级约 60 秒,并在冷却期间使用 SSE
|
||||
- 为重试和重连附加稳定的会话与回合身份标头
|
||||
- 在不同传输变体之间规范化使用计数器(`input_tokens` / `prompt_tokens`)
|
||||
- 在回退到 SSE 之前重试一次早期 WebSocket 失败
|
||||
- 失败后将 WebSocket 标记为降级状态约 60 秒,并在冷却期间使用 SSE
|
||||
- 为重试和重连附加稳定的会话和轮次身份标头
|
||||
- 在不同传输变体之间规范化使用量计数器(`input_tokens` / `prompt_tokens`)
|
||||
|
||||
| 值 | 行为 |
|
||||
|-------|----------|
|
||||
| `"auto"`(默认) | WebSocket 优先,SSE 回退 |
|
||||
| `"sse"` | 仅强制使用 SSE |
|
||||
| `"websocket"` | 仅强制使用 WebSocket |
|
||||
| `"sse"` | 强制仅使用 SSE |
|
||||
| `"websocket"` | 强制仅使用 WebSocket |
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -651,13 +639,13 @@ OpenClaw 的隐藏归因头——请参阅 [高级配置](#advanced-configuratio
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="快速模式">
|
||||
OpenClaw 为 `openai/*` 和 `openai-codex/*` 暴露了一个共享的快速模式开关:
|
||||
<Accordion title="Fast 模式">
|
||||
OpenClaw 为 `openai/*` 和 `openai-codex/*` 提供共享的 Fast 模式开关:
|
||||
|
||||
- **聊天 / UI:** `/fast status|on|off`
|
||||
- **聊天/UI:** `/fast status|on|off`
|
||||
- **配置:** `agents.defaults.models["<provider>/<model>"].params.fastMode`
|
||||
|
||||
启用后,OpenClaw 会将快速模式映射为 OpenAI 优先处理(`service_tier = "priority"`)。现有的 `service_tier` 值会被保留,快速模式不会重写 `reasoning` 或 `text.verbosity`。
|
||||
启用后,OpenClaw 会将 Fast 模式映射为 OpenAI 优先处理(`service_tier = "priority"`)。现有的 `service_tier` 值会被保留,Fast 模式不会重写 `reasoning` 或 `text.verbosity`。
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -672,13 +660,13 @@ OpenClaw 的隐藏归因头——请参阅 [高级配置](#advanced-configuratio
|
||||
```
|
||||
|
||||
<Note>
|
||||
会话覆盖优先于配置。在 Sessions UI 中清除会话覆盖后,会话将恢复为配置的默认值。
|
||||
会话覆盖优先于配置。在 Sessions UI 中清除会话覆盖后,会话会恢复为配置中的默认值。
|
||||
</Note>
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="优先处理(service_tier)">
|
||||
OpenAI 的 API 通过 `service_tier` 暴露优先处理能力。你可以在 OpenClaw 中按模型设置:
|
||||
OpenAI 的 API 通过 `service_tier` 暴露优先处理能力。你可以在 OpenClaw 中按模型进行设置:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -695,23 +683,23 @@ OpenClaw 的隐藏归因头——请参阅 [高级配置](#advanced-configuratio
|
||||
支持的值:`auto`、`default`、`flex`、`priority`。
|
||||
|
||||
<Warning>
|
||||
`serviceTier` 仅会转发到原生 OpenAI 端点(`api.openai.com`)和原生 Codex 端点(`chatgpt.com/backend-api`)。如果你通过代理路由任一提供商,OpenClaw 会保持 `service_tier` 不变。
|
||||
`serviceTier` 仅会转发到原生 OpenAI 端点(`api.openai.com`)和原生 Codex 端点(`chatgpt.com/backend-api`)。如果你通过代理路由任一 provider,OpenClaw 会保持 `service_tier` 不变。
|
||||
</Warning>
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="服务端压缩(Responses API)">
|
||||
对于直接 OpenAI Responses 模型(`api.openai.com` 上的 `openai/*`),OpenAI plugin 的 Pi-harness 流包装器会自动启用服务端压缩:
|
||||
对于直接 OpenAI Responses 模型(`api.openai.com` 上的 `openai/*`),OpenAI 插件的 Pi harness 流包装器会自动启用服务端压缩:
|
||||
|
||||
- 强制 `store: true`(除非模型兼容性设置 `supportsStore: false`)
|
||||
- 强制 `store: true`(除非模型兼容性设置了 `supportsStore: false`)
|
||||
- 注入 `context_management: [{ type: "compaction", compact_threshold: ... }]`
|
||||
- 默认 `compact_threshold`:`contextWindow` 的 70%(如果不可用则为 `80000`)
|
||||
- 默认 `compact_threshold`:`contextWindow` 的 70%(若不可用则为 `80000`)
|
||||
|
||||
这适用于内置 Pi harness 路径,也适用于嵌入式运行所使用的 OpenAI 提供商钩子。原生 Codex app-server harness 通过 Codex 自行管理上下文,并通过 `agents.defaults.embeddedHarness.runtime` 单独配置。
|
||||
这适用于内置 Pi harness 路径,以及内嵌运行所使用的 OpenAI provider hooks。原生 Codex app-server harness 通过 Codex 自行管理上下文,并通过 `agents.defaults.agentRuntime.id` 单独配置。
|
||||
|
||||
<Tabs>
|
||||
<Tab title="显式启用">
|
||||
对于 Azure OpenAI Responses 之类的兼容端点,这很有用:
|
||||
适用于 Azure OpenAI Responses 等兼容端点:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -763,13 +751,13 @@ OpenClaw 的隐藏归因头——请参阅 [高级配置](#advanced-configuratio
|
||||
</Tabs>
|
||||
|
||||
<Note>
|
||||
`responsesServerCompaction` 仅控制 `context_management` 注入。直接 OpenAI Responses 模型仍会强制 `store: true`,除非兼容性设置 `supportsStore: false`。
|
||||
`responsesServerCompaction` 仅控制 `context_management` 注入。直接 OpenAI Responses 模型仍会强制 `store: true`,除非兼容性设置了 `supportsStore: false`。
|
||||
</Note>
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="严格智能体 GPT 模式">
|
||||
对于 `openai/*` 上的 GPT-5 系列运行,OpenClaw 可以使用更严格的嵌入式执行契约:
|
||||
对于 `openai/*` 上的 GPT-5 系列运行,OpenClaw 可以使用更严格的内嵌执行契约:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -782,35 +770,35 @@ OpenClaw 的隐藏归因头——请参阅 [高级配置](#advanced-configuratio
|
||||
```
|
||||
|
||||
使用 `strict-agentic` 时,OpenClaw 会:
|
||||
- 当存在可用工具操作时,不再将“只有计划的回合”视为成功进展
|
||||
- 通过“立即行动”的引导重试该回合
|
||||
- 对于重要工作自动启用 `update_plan`
|
||||
- 如果模型持续只规划不执行,则显式显示阻塞状态
|
||||
- 当工具操作可用时,不再将仅有计划的轮次视为成功推进
|
||||
- 使用“立即行动”的引导重试该轮次
|
||||
- 对重要工作自动启用 `update_plan`
|
||||
- 如果模型持续规划但不执行,则显式呈现阻塞状态
|
||||
|
||||
<Note>
|
||||
仅作用于 OpenAI 和 Codex 的 GPT-5 系列运行。其他提供商和较旧模型系列保持默认行为。
|
||||
仅适用于 OpenAI 和 Codex 的 GPT-5 系列运行。其他 provider 和较旧模型家族仍保持默认行为。
|
||||
</Note>
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="原生与 OpenAI 兼容路径">
|
||||
OpenClaw 会将直接 OpenAI、Codex 和 Azure OpenAI 端点,与通用 OpenAI 兼容 `/v1` 代理区别对待:
|
||||
OpenClaw 对直接 OpenAI、Codex 和 Azure OpenAI 端点,与通用 OpenAI 兼容 `/v1` 代理的处理方式不同:
|
||||
|
||||
**原生路径**(`openai/*`、Azure OpenAI):
|
||||
- 仅对支持 OpenAI `none` effort 的模型保留 `reasoning: { effort: "none" }`
|
||||
- 对拒绝 `reasoning.effort: "none"` 的模型或代理省略禁用推理设置
|
||||
- 默认将工具 schema 设为严格模式
|
||||
- 仅在已验证的原生主机上附加隐藏归因头
|
||||
- 保留 OpenAI 专用请求格式(`service_tier`、`store`、reasoning 兼容性、提示词缓存提示)
|
||||
- 默认对工具 schema 使用严格模式
|
||||
- 仅在已验证的原生主机上附加隐藏归因标头
|
||||
- 保留 OpenAI 专属请求结构(`service_tier`、`store`、reasoning 兼容性、提示缓存提示)
|
||||
|
||||
**代理 / 兼容路径:**
|
||||
- 使用更宽松的兼容行为
|
||||
- 从非原生 `openai-completions` 负载中移除 Completions `store`
|
||||
- 接受适用于 OpenAI 兼容 Completions 代理的高级 `params.extra_body` / `params.extraBody` 透传 JSON
|
||||
- 接受适用于 OpenAI 兼容 Completions 代理(如 vLLM)的 `params.chat_template_kwargs`
|
||||
- 不强制严格工具 schema,也不附加原生专用标头
|
||||
**代理/兼容路径:**
|
||||
- 使用较宽松的兼容行为
|
||||
- 从非原生 `openai-completions` 载荷中剥离 Completions `store`
|
||||
- 接受用于 OpenAI 兼容 Completions 代理的高级 `params.extra_body`/`params.extraBody` 透传 JSON
|
||||
- 接受用于 OpenAI 兼容 Completions 代理(如 vLLM)的 `params.chat_template_kwargs`
|
||||
- 不强制严格工具 schema 或原生专属标头
|
||||
|
||||
Azure OpenAI 使用原生传输和兼容行为,但不会接收隐藏归因头。
|
||||
Azure OpenAI 使用原生传输和兼容行为,但不会接收隐藏归因标头。
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
@ -1,91 +1,128 @@
|
||||
---
|
||||
read_when:
|
||||
- 你想要配置内存搜索提供商或嵌入模型
|
||||
- 你想要配置 Memory 搜索提供商或嵌入模型
|
||||
- 你想要设置 QMD 后端
|
||||
- 你想要调整混合搜索、MMR 或时间衰减
|
||||
- 你想要启用多模态内存索引
|
||||
summary: 内存搜索、嵌入提供商、QMD、混合搜索和多模态索引的所有配置选项
|
||||
title: 内存配置参考
|
||||
- 你想要调优混合搜索、MMR 或时间衰减
|
||||
- 你想要启用多模态 Memory 索引
|
||||
sidebarTitle: Memory config
|
||||
summary: Memory 搜索、嵌入提供商、QMD、混合搜索和多模态索引的所有配置项
|
||||
title: Memory 配置参考
|
||||
x-i18n:
|
||||
generated_at: "2026-04-25T23:14:59Z"
|
||||
generated_at: "2026-04-26T07:51:16Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 6c3e000969bee0d3ed0174e61df17c7da4166ef949db86405e2730e9d95002ea
|
||||
source_hash: 15fd747abc6d0d43cfc869faa0b5e6c1618681ef3b02068207321d60d449a901
|
||||
source_path: reference/memory-config.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
此页面列出了 OpenClaw 内存搜索的所有配置选项。有关概念概览,请参见:
|
||||
此页面列出了 OpenClaw Memory 搜索的所有配置项。有关概念概览,请参见:
|
||||
|
||||
- [Memory Overview](/zh-CN/concepts/memory) —— 内存的工作方式
|
||||
- [Builtin Engine](/zh-CN/concepts/memory-builtin) —— 默认的 SQLite 后端
|
||||
- [QMD Engine](/zh-CN/concepts/memory-qmd) —— 本地优先的 sidecar
|
||||
- [Memory Search](/zh-CN/concepts/memory-search) —— 搜索流水线与调优
|
||||
- [Active Memory](/zh-CN/concepts/active-memory) —— 为交互式会话启用内存子智能体
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Memory 概览" href="/zh-CN/concepts/memory">
|
||||
Memory 的工作方式。
|
||||
</Card>
|
||||
<Card title="内置引擎" href="/zh-CN/concepts/memory-builtin">
|
||||
默认的 SQLite 后端。
|
||||
</Card>
|
||||
<Card title="QMD 引擎" href="/zh-CN/concepts/memory-qmd">
|
||||
本地优先的 sidecar。
|
||||
</Card>
|
||||
<Card title="Memory 搜索" href="/zh-CN/concepts/memory-search">
|
||||
搜索管线和调优。
|
||||
</Card>
|
||||
<Card title="Active Memory" href="/zh-CN/concepts/active-memory">
|
||||
用于交互式会话的 Memory 子智能体。
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
除非另有说明,所有内存搜索设置都位于 `openclaw.json` 中的 `agents.defaults.memorySearch` 下。
|
||||
除非另有说明,所有 Memory 搜索设置都位于 `openclaw.json` 的 `agents.defaults.memorySearch` 下。
|
||||
|
||||
如果你要查找 **active memory** 的功能开关和子智能体配置,它位于 `plugins.entries.active-memory` 下,而不是 `memorySearch` 下。
|
||||
<Note>
|
||||
如果你要找的是 **Active Memory** 功能开关和子智能体配置,它位于 `plugins.entries.active-memory` 下,而不是 `memorySearch`。
|
||||
|
||||
Active memory 使用双门控模型:
|
||||
Active Memory 使用双门控模型:
|
||||
|
||||
1. 该插件必须已启用,并且目标指向当前智能体 ID
|
||||
2. 该请求必须是符合条件的交互式持久聊天会话
|
||||
1. 插件必须已启用,并以当前智能体 id 为目标
|
||||
2. 请求必须是符合条件的交互式持久聊天会话
|
||||
|
||||
有关激活模型、插件自有配置、转录持久化以及安全的渐进式发布模式,请参见 [Active Memory](/zh-CN/concepts/active-memory)。
|
||||
有关激活模型、插件自有配置、transcript 持久化和安全发布模式,请参见 [Active Memory](/zh-CN/concepts/active-memory)。
|
||||
</Note>
|
||||
|
||||
---
|
||||
|
||||
## 提供商选择
|
||||
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| ---------- | --------- | -------------- | --------------------------------------------------------------------------------------------------------------- |
|
||||
| `provider` | `string` | 自动检测 | 嵌入适配器 ID:`bedrock`、`gemini`、`github-copilot`、`local`、`mistral`、`ollama`、`openai`、`voyage` |
|
||||
| `model` | `string` | 提供商默认值 | 嵌入模型名称 |
|
||||
| `fallback` | `string` | `"none"` | 主提供商失败时使用的后备适配器 ID |
|
||||
| `enabled` | `boolean` | `true` | 启用或禁用内存搜索 |
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| ---------- | --------- | ---------------- | ------------------------------------------------------------------------------------------------------------- |
|
||||
| `provider` | `string` | 自动检测 | 嵌入适配器 id:`bedrock`、`gemini`、`github-copilot`、`local`、`mistral`、`ollama`、`openai`、`voyage` |
|
||||
| `model` | `string` | 提供商默认值 | 嵌入模型名称 |
|
||||
| `fallback` | `string` | `"none"` | 当主适配器失败时使用的回退适配器 id |
|
||||
| `enabled` | `boolean` | `true` | 启用或禁用 Memory 搜索 |
|
||||
|
||||
### 自动检测顺序
|
||||
|
||||
当未设置 `provider` 时,OpenClaw 会选择第一个可用的提供商:
|
||||
当未设置 `provider` 时,OpenClaw 会选择第一个可用项:
|
||||
|
||||
1. `local` —— 如果已配置 `memorySearch.local.modelPath` 且该文件存在。
|
||||
2. `github-copilot` —— 如果可以解析到 GitHub Copilot token(环境变量或认证配置文件)。
|
||||
3. `openai` —— 如果可以解析到 OpenAI 密钥。
|
||||
4. `gemini` —— 如果可以解析到 Gemini 密钥。
|
||||
5. `voyage` —— 如果可以解析到 Voyage 密钥。
|
||||
6. `mistral` —— 如果可以解析到 Mistral 密钥。
|
||||
7. `bedrock` —— 如果 AWS SDK 凭证链可以成功解析(实例角色、访问密钥、配置文件、SSO、Web 身份或共享配置)。
|
||||
<Steps>
|
||||
<Step title="local">
|
||||
如果配置了 `memorySearch.local.modelPath` 且文件存在,则选择它。
|
||||
</Step>
|
||||
<Step title="github-copilot">
|
||||
如果可以解析到 GitHub Copilot token(环境变量或认证配置文件),则选择它。
|
||||
</Step>
|
||||
<Step title="openai">
|
||||
如果可以解析到 OpenAI key,则选择它。
|
||||
</Step>
|
||||
<Step title="gemini">
|
||||
如果可以解析到 Gemini key,则选择它。
|
||||
</Step>
|
||||
<Step title="voyage">
|
||||
如果可以解析到 Voyage key,则选择它。
|
||||
</Step>
|
||||
<Step title="mistral">
|
||||
如果可以解析到 Mistral key,则选择它。
|
||||
</Step>
|
||||
<Step title="bedrock">
|
||||
如果 AWS SDK 凭证链可以解析成功(实例角色、访问密钥、profile、SSO、Web identity 或共享配置),则选择它。
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
支持 `ollama`,但不会自动检测到它(需要显式设置)。
|
||||
支持 `ollama`,但不会自动检测(需要显式设置)。
|
||||
|
||||
### API 密钥解析
|
||||
|
||||
远程嵌入需要 API 密钥。Bedrock 则改用 AWS SDK 默认凭证链(实例角色、SSO、访问密钥)。
|
||||
远程嵌入需要 API key。Bedrock 则使用 AWS SDK 默认凭证链(实例角色、SSO、访问密钥)。
|
||||
|
||||
| 提供商 | 环境变量 | 配置键 |
|
||||
| 提供商 | 环境变量 | 配置键 |
|
||||
| -------------- | -------------------------------------------------- | --------------------------------- |
|
||||
| Bedrock | AWS 凭证链 | 不需要 API 密钥 |
|
||||
| Bedrock | AWS 凭证链 | 不需要 API key |
|
||||
| Gemini | `GEMINI_API_KEY` | `models.providers.google.apiKey` |
|
||||
| GitHub Copilot | `COPILOT_GITHUB_TOKEN`, `GH_TOKEN`, `GITHUB_TOKEN` | 通过设备登录的认证配置文件 |
|
||||
| GitHub Copilot | `COPILOT_GITHUB_TOKEN`、`GH_TOKEN`、`GITHUB_TOKEN` | 通过设备登录的认证配置文件 |
|
||||
| Mistral | `MISTRAL_API_KEY` | `models.providers.mistral.apiKey` |
|
||||
| Ollama | `OLLAMA_API_KEY`(占位) | -- |
|
||||
| Ollama | `OLLAMA_API_KEY`(占位符) | -- |
|
||||
| OpenAI | `OPENAI_API_KEY` | `models.providers.openai.apiKey` |
|
||||
| Voyage | `VOYAGE_API_KEY` | `models.providers.voyage.apiKey` |
|
||||
|
||||
Codex OAuth 仅覆盖聊天/补全,不满足嵌入请求的认证要求。
|
||||
<Note>
|
||||
Codex OAuth 仅覆盖 chat/completions,不满足嵌入请求。
|
||||
</Note>
|
||||
|
||||
---
|
||||
|
||||
## 远程端点配置
|
||||
|
||||
用于自定义 OpenAI 兼容端点或覆盖提供商默认值:
|
||||
用于自定义兼容 OpenAI 的端点或覆盖提供商默认值:
|
||||
|
||||
| 键 | 类型 | 说明 |
|
||||
| ---------------- | -------- | ------------------------------------ |
|
||||
| `remote.baseUrl` | `string` | 自定义 API 基础 URL |
|
||||
| `remote.apiKey` | `string` | 覆盖 API 密钥 |
|
||||
| `remote.headers` | `object` | 额外的 HTTP 标头(与提供商默认值合并) |
|
||||
<ParamField path="remote.baseUrl" type="string">
|
||||
自定义 API 基础 URL。
|
||||
</ParamField>
|
||||
<ParamField path="remote.apiKey" type="string">
|
||||
覆盖 API key。
|
||||
</ParamField>
|
||||
<ParamField path="remote.headers" type="object">
|
||||
额外的 HTTP headers(与提供商默认值合并)。
|
||||
</ParamField>
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -106,122 +143,113 @@ Codex OAuth 仅覆盖聊天/补全,不满足嵌入请求的认证要求。
|
||||
|
||||
---
|
||||
|
||||
## Gemini 专属配置
|
||||
## 提供商特定配置
|
||||
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| ---------------------- | -------- | ---------------------- | ------------------------------------------ |
|
||||
| `model` | `string` | `gemini-embedding-001` | 也支持 `gemini-embedding-2-preview` |
|
||||
| `outputDimensionality` | `number` | `3072` | 对于 Embedding 2:可选 768、1536 或 3072 |
|
||||
<AccordionGroup>
|
||||
<Accordion title="Gemini">
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| ---------------------- | -------- | ---------------------- | ------------------------------------------ |
|
||||
| `model` | `string` | `gemini-embedding-001` | 也支持 `gemini-embedding-2-preview` |
|
||||
| `outputDimensionality` | `number` | `3072` | 对于 Embedding 2:768、1536 或 3072 |
|
||||
|
||||
<Warning>
|
||||
更改模型或 `outputDimensionality` 会触发自动全量重建索引。
|
||||
</Warning>
|
||||
<Warning>
|
||||
更改模型或 `outputDimensionality` 会触发自动全量重新索引。
|
||||
</Warning>
|
||||
|
||||
---
|
||||
</Accordion>
|
||||
<Accordion title="Bedrock">
|
||||
Bedrock 使用 AWS SDK 默认凭证链——不需要 API key。如果 OpenClaw 运行在启用了 Bedrock 实例角色的 EC2 上,只需设置提供商和模型:
|
||||
|
||||
## Bedrock 嵌入配置
|
||||
|
||||
Bedrock 使用 AWS SDK 默认凭证链 —— 不需要 API 密钥。
|
||||
如果 OpenClaw 运行在具有 Bedrock 权限实例角色的 EC2 上,只需设置提供商和模型:
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
defaults: {
|
||||
memorySearch: {
|
||||
provider: "bedrock",
|
||||
model: "amazon.titan-embed-text-v2:0",
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
defaults: {
|
||||
memorySearch: {
|
||||
provider: "bedrock",
|
||||
model: "amazon.titan-embed-text-v2:0",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
}
|
||||
```
|
||||
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| ---------------------- | -------- | ------------------------------ | ------------------------- |
|
||||
| `model` | `string` | `amazon.titan-embed-text-v2:0` | 任意 Bedrock 嵌入模型 ID |
|
||||
| `outputDimensionality` | `number` | 模型默认值 | 对于 Titan V2:256、512 或 1024 |
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| ---------------------- | -------- | ------------------------------ | ------------------------------- |
|
||||
| `model` | `string` | `amazon.titan-embed-text-v2:0` | 任意 Bedrock 嵌入模型 id |
|
||||
| `outputDimensionality` | `number` | 模型默认值 | 对于 Titan V2:256、512 或 1024 |
|
||||
|
||||
### 支持的模型
|
||||
**支持的模型**(含家族检测和默认维度):
|
||||
|
||||
支持以下模型(包含系列检测和维度默认值):
|
||||
| 模型 ID | 提供商 | 默认维度 | 可配置维度 |
|
||||
| ------------------------------------------ | ---------- | ------------ | -------------------- |
|
||||
| `amazon.titan-embed-text-v2:0` | Amazon | 1024 | 256、512、1024 |
|
||||
| `amazon.titan-embed-text-v1` | Amazon | 1536 | -- |
|
||||
| `amazon.titan-embed-g1-text-02` | Amazon | 1536 | -- |
|
||||
| `amazon.titan-embed-image-v1` | Amazon | 1024 | -- |
|
||||
| `amazon.nova-2-multimodal-embeddings-v1:0` | Amazon | 1024 | 256、384、1024、3072 |
|
||||
| `cohere.embed-english-v3` | Cohere | 1024 | -- |
|
||||
| `cohere.embed-multilingual-v3` | Cohere | 1024 | -- |
|
||||
| `cohere.embed-v4:0` | Cohere | 1536 | 256-1536 |
|
||||
| `twelvelabs.marengo-embed-3-0-v1:0` | TwelveLabs | 512 | -- |
|
||||
| `twelvelabs.marengo-embed-2-7-v1:0` | TwelveLabs | 1024 | -- |
|
||||
|
||||
| 模型 ID | 提供商 | 默认维度 | 可配置维度 |
|
||||
| ------------------------------------------ | ---------- | -------- | -------------------- |
|
||||
| `amazon.titan-embed-text-v2:0` | Amazon | 1024 | 256、512、1024 |
|
||||
| `amazon.titan-embed-text-v1` | Amazon | 1536 | -- |
|
||||
| `amazon.titan-embed-g1-text-02` | Amazon | 1536 | -- |
|
||||
| `amazon.titan-embed-image-v1` | Amazon | 1024 | -- |
|
||||
| `amazon.nova-2-multimodal-embeddings-v1:0` | Amazon | 1024 | 256、384、1024、3072 |
|
||||
| `cohere.embed-english-v3` | Cohere | 1024 | -- |
|
||||
| `cohere.embed-multilingual-v3` | Cohere | 1024 | -- |
|
||||
| `cohere.embed-v4:0` | Cohere | 1536 | 256-1536 |
|
||||
| `twelvelabs.marengo-embed-3-0-v1:0` | TwelveLabs | 512 | -- |
|
||||
| `twelvelabs.marengo-embed-2-7-v1:0` | TwelveLabs | 1024 | -- |
|
||||
带吞吐量后缀的变体(例如 `amazon.titan-embed-text-v1:2:8k`)会继承基础模型的配置。
|
||||
|
||||
带吞吐后缀的变体(例如 `amazon.titan-embed-text-v1:2:8k`)会继承基础模型的配置。
|
||||
**认证:** Bedrock 认证使用标准 AWS SDK 凭证解析顺序:
|
||||
|
||||
### 认证
|
||||
1. 环境变量(`AWS_ACCESS_KEY_ID` + `AWS_SECRET_ACCESS_KEY`)
|
||||
2. SSO token 缓存
|
||||
3. Web identity token 凭证
|
||||
4. 共享凭证和配置文件
|
||||
5. ECS 或 EC2 元数据凭证
|
||||
|
||||
Bedrock 认证使用标准 AWS SDK 凭证解析顺序:
|
||||
区域会从 `AWS_REGION`、`AWS_DEFAULT_REGION`、`amazon-bedrock` provider 的 `baseUrl` 中解析,否则默认使用 `us-east-1`。
|
||||
|
||||
1. 环境变量(`AWS_ACCESS_KEY_ID` + `AWS_SECRET_ACCESS_KEY`)
|
||||
2. SSO token 缓存
|
||||
3. Web 身份 token 凭证
|
||||
4. 共享凭证和配置文件
|
||||
5. ECS 或 EC2 元数据凭证
|
||||
**IAM 权限:** IAM 角色或用户需要:
|
||||
|
||||
区域会从 `AWS_REGION`、`AWS_DEFAULT_REGION`、`amazon-bedrock` 提供商的 `baseUrl` 中解析,或默认使用 `us-east-1`。
|
||||
```json
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": "bedrock:InvokeModel",
|
||||
"Resource": "*"
|
||||
}
|
||||
```
|
||||
|
||||
### IAM 权限
|
||||
为了实现最小权限,请将 `InvokeModel` 限定到特定模型:
|
||||
|
||||
IAM 角色或用户需要:
|
||||
```
|
||||
arn:aws:bedrock:*::foundation-model/amazon.titan-embed-text-v2:0
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": "bedrock:InvokeModel",
|
||||
"Resource": "*"
|
||||
}
|
||||
```
|
||||
</Accordion>
|
||||
<Accordion title="Local(GGUF + node-llama-cpp)">
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| --------------------- | ------------------ | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `local.modelPath` | `string` | 自动下载 | GGUF 模型文件路径 |
|
||||
| `local.modelCacheDir` | `string` | node-llama-cpp 默认值 | 下载模型的缓存目录 |
|
||||
| `local.contextSize` | `number \| "auto"` | `4096` | 嵌入上下文的上下文窗口大小。4096 可覆盖典型分块(128–512 tokens),同时限制非权重 VRAM。对于受限主机,可降到 1024–2048。`"auto"` 使用模型训练时的最大值——不建议用于 8B+ 模型(Qwen3-Embedding-8B:40 960 tokens → 大约 32 GB VRAM,而 4096 时约为 8.8 GB)。 |
|
||||
|
||||
为了遵循最小权限原则,请将 `InvokeModel` 限定到具体模型:
|
||||
默认模型:`embeddinggemma-300m-qat-Q8_0.gguf`(约 0.6 GB,自动下载)。需要原生构建:`pnpm approve-builds` 然后 `pnpm rebuild node-llama-cpp`。
|
||||
|
||||
```
|
||||
arn:aws:bedrock:*::foundation-model/amazon.titan-embed-text-v2:0
|
||||
```
|
||||
使用独立 CLI 验证 Gateway 网关所使用的同一提供商路径:
|
||||
|
||||
---
|
||||
```bash
|
||||
openclaw memory status --deep --agent main
|
||||
openclaw memory index --force --agent main
|
||||
```
|
||||
|
||||
## 本地嵌入配置
|
||||
如果 `provider` 是 `auto`,只有当 `local.modelPath` 指向一个已存在的本地文件时,才会选择 `local`。`hf:` 和 HTTP(S) 模型引用仍可通过 `provider: "local"` 显式使用,但在模型实际落盘之前,它们不会让 `auto` 优先选择 local。
|
||||
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| --------------------- | ------------------ | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `local.modelPath` | `string` | 自动下载 | GGUF 模型文件路径 |
|
||||
| `local.modelCacheDir` | `string` | `node-llama-cpp` 默认值 | 已下载模型的缓存目录 |
|
||||
| `local.contextSize` | `number \| "auto"` | `4096` | 嵌入上下文的上下文窗口大小。4096 可覆盖典型分块(128–512 tokens),同时限制非权重显存占用。在资源受限的主机上可降至 1024–2048。`"auto"` 会使用模型训练时的最大值 —— 不建议用于 8B+ 模型(Qwen3-Embedding-8B:40 960 tokens → 约 32 GB VRAM,而在 4096 时约为 8.8 GB)。 |
|
||||
|
||||
默认模型:`embeddinggemma-300m-qat-Q8_0.gguf`(约 0.6 GB,自动下载)。
|
||||
需要原生构建:`pnpm approve-builds`,然后执行 `pnpm rebuild node-llama-cpp`。
|
||||
|
||||
使用独立 CLI 来验证与 Gateway 网关 相同的提供商路径:
|
||||
|
||||
```bash
|
||||
openclaw memory status --deep --agent main
|
||||
openclaw memory index --force --agent main
|
||||
```
|
||||
|
||||
如果 `provider` 为 `auto`,只有当 `local.modelPath` 指向一个已存在的本地文件时,才会选择 `local`。`hf:` 和 HTTP(S) 模型引用仍可在 `provider: "local"` 时显式使用,但在模型尚未存在于磁盘上之前,它们不会让 `auto` 优先选择 local。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### 内联嵌入超时
|
||||
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| ----------------------------------- | -------- | -------------- | -------------------------------------------- |
|
||||
| `sync.embeddingBatchTimeoutSeconds` | `number` | 提供商默认值 | 覆盖内存索引期间内联嵌入批次的超时时间 |
|
||||
<ParamField path="sync.embeddingBatchTimeoutSeconds" type="number">
|
||||
覆盖 Memory 索引期间内联嵌入批次的超时时间。
|
||||
|
||||
未设置时,将使用提供商默认值:对于 `local`、`ollama` 和 `lmstudio` 等本地/自托管提供商为 600 秒,对于托管提供商为 120 秒。
|
||||
|
||||
当本地 CPU 受限的嵌入批次运行正常但速度较慢时,请增大此值。
|
||||
未设置时使用提供商默认值:对于 `local`、`ollama` 和 `lmstudio` 等本地 / 自托管提供商为 600 秒,对于托管提供商为 120 秒。当本地 CPU 密集型嵌入批次运行正常但较慢时,可增大该值。
|
||||
</ParamField>
|
||||
|
||||
---
|
||||
|
||||
@ -229,28 +257,30 @@ openclaw memory index --force --agent main
|
||||
|
||||
全部位于 `memorySearch.query.hybrid` 下:
|
||||
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| --------------------- | --------- | ------- | ---------------------------- |
|
||||
| `enabled` | `boolean` | `true` | 启用混合 BM25 + 向量搜索 |
|
||||
| `vectorWeight` | `number` | `0.7` | 向量分数的权重(0-1) |
|
||||
| `textWeight` | `number` | `0.3` | BM25 分数的权重(0-1) |
|
||||
| `candidateMultiplier` | `number` | `4` | 候选池大小乘数 |
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| --------------------- | --------- | ------- | ---------------------------------- |
|
||||
| `enabled` | `boolean` | `true` | 启用混合 BM25 + 向量搜索 |
|
||||
| `vectorWeight` | `number` | `0.7` | 向量分数权重(0-1) |
|
||||
| `textWeight` | `number` | `0.3` | BM25 分数权重(0-1) |
|
||||
| `candidateMultiplier` | `number` | `4` | 候选池大小乘数 |
|
||||
|
||||
### MMR(多样性)
|
||||
<Tabs>
|
||||
<Tab title="MMR(多样性)">
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| ------------- | --------- | ------- | ------------------------------------ |
|
||||
| `mmr.enabled` | `boolean` | `false` | 启用 MMR 重排序 |
|
||||
| `mmr.lambda` | `number` | `0.7` | 0 = 最大多样性,1 = 最大相关性 |
|
||||
</Tab>
|
||||
<Tab title="时间衰减(新近性)">
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| ---------------------------- | --------- | ------- | ------------------------- |
|
||||
| `temporalDecay.enabled` | `boolean` | `false` | 启用新近性加权 |
|
||||
| `temporalDecay.halfLifeDays` | `number` | `30` | 分数每 N 天减半 |
|
||||
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| ------------- | --------- | ------- | ---------------------------------- |
|
||||
| `mmr.enabled` | `boolean` | `false` | 启用 MMR 重排序 |
|
||||
| `mmr.lambda` | `number` | `0.7` | 0 = 最大多样性,1 = 最大相关性 |
|
||||
常青文件(`MEMORY.md`、`memory/` 中无日期的文件)永不衰减。
|
||||
|
||||
### 时间衰减(新近性)
|
||||
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| ---------------------------- | --------- | ------- | ----------------------- |
|
||||
| `temporalDecay.enabled` | `boolean` | `false` | 启用新近性加权 |
|
||||
| `temporalDecay.halfLifeDays` | `number` | `30` | 分数每 N 天减半 |
|
||||
|
||||
常青文件(`MEMORY.md`、`memory/` 中不带日期的文件)永远不会衰减。
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### 完整示例
|
||||
|
||||
@ -275,11 +305,11 @@ openclaw memory index --force --agent main
|
||||
|
||||
---
|
||||
|
||||
## 其他内存路径
|
||||
## 附加 Memory 路径
|
||||
|
||||
| 键 | 类型 | 说明 |
|
||||
| ------------ | ---------- | ---------------------------------- |
|
||||
| `extraPaths` | `string[]` | 要建立索引的其他目录或文件 |
|
||||
| 键 | 类型 | 说明 |
|
||||
| ------------ | ---------- | ---------------------------------------- |
|
||||
| `extraPaths` | `string[]` | 需要索引的附加目录或文件 |
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -293,79 +323,80 @@ openclaw memory index --force --agent main
|
||||
}
|
||||
```
|
||||
|
||||
路径可以是绝对路径,也可以是相对于工作区的路径。目录会递归扫描其中的 `.md` 文件。符号链接的处理取决于当前使用的后端:内置引擎会忽略符号链接,而 QMD 会遵循底层 QMD 扫描器的行为。
|
||||
路径可以是绝对路径,也可以是相对工作区路径。目录会递归扫描 `.md` 文件。符号链接处理取决于当前后端:内置引擎会忽略符号链接,而 QMD 会遵循底层 QMD 扫描器的行为。
|
||||
|
||||
对于按智能体范围进行的跨智能体转录搜索,请使用 `agents.list[].memorySearch.qmd.extraCollections`,而不是 `memory.qmd.paths`。这些额外集合遵循相同的 `{ path, name, pattern? }` 结构,但会按智能体进行合并,并且当路径指向当前工作区之外时,可以保留显式指定的共享名称。
|
||||
如果同一个已解析路径同时出现在 `memory.qmd.paths` 和 `memorySearch.qmd.extraCollections` 中,QMD 会保留第一项并跳过重复项。
|
||||
对于按智能体范围的跨智能体 transcript 搜索,请使用 `agents.list[].memorySearch.qmd.extraCollections`,而不是 `memory.qmd.paths`。这些额外集合遵循相同的 `{ path, name, pattern? }` 结构,但它们会按智能体合并,并且当路径指向当前工作区之外时,可以保留显式共享名称。如果同一个解析后的路径同时出现在 `memory.qmd.paths` 和 `memorySearch.qmd.extraCollections` 中,QMD 会保留第一个条目并跳过重复项。
|
||||
|
||||
---
|
||||
|
||||
## 多模态内存(Gemini)
|
||||
## 多模态 Memory(Gemini)
|
||||
|
||||
使用 Gemini Embedding 2 为图像和音频与 Markdown 一起建立索引:
|
||||
使用 Gemini Embedding 2,为图像和音频与 Markdown 一起建立索引:
|
||||
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| ------------------------- | ---------- | ---------- | -------------------------------------- |
|
||||
| `multimodal.enabled` | `boolean` | `false` | 启用多模态索引 |
|
||||
| `multimodal.modalities` | `string[]` | -- | `["image"]`、`["audio"]` 或 `["all"]` |
|
||||
| `multimodal.maxFileBytes` | `number` | `10000000` | 建立索引的最大文件大小 |
|
||||
| `multimodal.enabled` | `boolean` | `false` | 启用多模态索引 |
|
||||
| `multimodal.modalities` | `string[]` | -- | `["image"]`、`["audio"]` 或 `["all"]` |
|
||||
| `multimodal.maxFileBytes` | `number` | `10000000` | 建立索引的最大文件大小 |
|
||||
|
||||
仅适用于 `extraPaths` 中的文件。默认内存根目录仍然只索引 Markdown。
|
||||
需要 `gemini-embedding-2-preview`。`fallback` 必须为 `"none"`。
|
||||
<Note>
|
||||
仅适用于 `extraPaths` 中的文件。默认 Memory 根目录仍然只支持 Markdown。需要 `gemini-embedding-2-preview`。`fallback` 必须是 `"none"`。
|
||||
</Note>
|
||||
|
||||
支持的格式:`.jpg`、`.jpeg`、`.png`、`.webp`、`.gif`、`.heic`、`.heif`
|
||||
(图像);`.mp3`、`.wav`、`.ogg`、`.opus`、`.m4a`、`.aac`、`.flac`(音频)。
|
||||
支持的格式:`.jpg`、`.jpeg`、`.png`、`.webp`、`.gif`、`.heic`、`.heif`(图像);`.mp3`、`.wav`、`.ogg`、`.opus`、`.m4a`、`.aac`、`.flac`(音频)。
|
||||
|
||||
---
|
||||
|
||||
## 嵌入缓存
|
||||
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| ------------------ | --------- | ------- | --------------------------------- |
|
||||
| `cache.enabled` | `boolean` | `false` | 在 SQLite 中缓存分块嵌入 |
|
||||
| `cache.maxEntries` | `number` | `50000` | 最大缓存嵌入数量 |
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| ------------------ | --------- | ------- | -------------------------------- |
|
||||
| `cache.enabled` | `boolean` | `false` | 在 SQLite 中缓存分块嵌入 |
|
||||
| `cache.maxEntries` | `number` | `50000` | 最大缓存嵌入数量 |
|
||||
|
||||
可防止在重建索引或更新转录时,对未更改的文本重复进行嵌入。
|
||||
防止在重新索引或 transcript 更新期间,对未更改的文本重复执行嵌入。
|
||||
|
||||
---
|
||||
|
||||
## 批量索引
|
||||
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| ----------------------------- | --------- | ------- | ------------------------ |
|
||||
| `remote.batch.enabled` | `boolean` | `false` | 启用批量嵌入 API |
|
||||
| `remote.batch.concurrency` | `number` | `2` | 并行批处理任务数 |
|
||||
| `remote.batch.wait` | `boolean` | `true` | 等待批处理完成 |
|
||||
| `remote.batch.pollIntervalMs` | `number` | -- | 轮询间隔 |
|
||||
| `remote.batch.timeoutMinutes` | `number` | -- | 批处理超时时间 |
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| ----------------------------- | --------- | ------- | -------------------------- |
|
||||
| `remote.batch.enabled` | `boolean` | `false` | 启用批量嵌入 API |
|
||||
| `remote.batch.concurrency` | `number` | `2` | 并行批处理作业数 |
|
||||
| `remote.batch.wait` | `boolean` | `true` | 等待批处理完成 |
|
||||
| `remote.batch.pollIntervalMs` | `number` | -- | 轮询间隔 |
|
||||
| `remote.batch.timeoutMinutes` | `number` | -- | 批处理超时 |
|
||||
|
||||
适用于 `openai`、`gemini` 和 `voyage`。对于大规模回填,OpenAI 批处理通常最快且成本最低。
|
||||
适用于 `openai`、`gemini` 和 `voyage`。对于大型回填,OpenAI 批处理通常最快且最便宜。
|
||||
|
||||
这与 `sync.embeddingBatchTimeoutSeconds` 是分开的,后者控制本地/自托管提供商使用的内联嵌入调用,以及在未启用提供商批量 API 时托管提供商使用的内联嵌入调用。
|
||||
这与 `sync.embeddingBatchTimeoutSeconds` 是分开的;后者控制的是本地 / 自托管提供商使用的内联嵌入调用,以及在未启用提供商批量 API 时托管提供商使用的内联嵌入调用。
|
||||
|
||||
---
|
||||
|
||||
## 会话内存搜索(实验性)
|
||||
## 会话 Memory 搜索(实验性)
|
||||
|
||||
为会话转录建立索引,并通过 `memory_search` 提供结果:
|
||||
将会话 transcript 建立索引,并通过 `memory_search` 暴露:
|
||||
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| ----------------------------- | ---------- | ------------ | --------------------------------------- |
|
||||
| `experimental.sessionMemory` | `boolean` | `false` | 启用会话索引 |
|
||||
| `sources` | `string[]` | `["memory"]` | 添加 `"sessions"` 以包含转录 |
|
||||
| `sync.sessions.deltaBytes` | `number` | `100000` | 触发重建索引的字节阈值 |
|
||||
| `sync.sessions.deltaMessages` | `number` | `50` | 触发重建索引的消息阈值 |
|
||||
| `experimental.sessionMemory` | `boolean` | `false` | 启用会话索引 |
|
||||
| `sources` | `string[]` | `["memory"]` | 添加 `"sessions"` 以包含 transcript |
|
||||
| `sync.sessions.deltaBytes` | `number` | `100000` | 触发重新索引的字节阈值 |
|
||||
| `sync.sessions.deltaMessages` | `number` | `50` | 触发重新索引的消息阈值 |
|
||||
|
||||
会话索引是选择启用的,并且会异步运行。结果可能会略有滞后。会话日志存储在磁盘上,因此请将文件系统访问视为信任边界。
|
||||
<Warning>
|
||||
会话索引为选择性启用,并以异步方式运行。结果可能会略有滞后。会话日志保存在磁盘上,因此应将文件系统访问视为信任边界。
|
||||
</Warning>
|
||||
|
||||
---
|
||||
|
||||
## SQLite 向量加速(sqlite-vec)
|
||||
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| ---------------------------- | --------- | --------- | ----------------------------- |
|
||||
| `store.vector.enabled` | `boolean` | `true` | 使用 sqlite-vec 执行向量查询 |
|
||||
| `store.vector.extensionPath` | `string` | 内置 | 覆盖 sqlite-vec 路径 |
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| ---------------------------- | --------- | ------- | --------------------------------- |
|
||||
| `store.vector.enabled` | `boolean` | `true` | 对向量查询使用 sqlite-vec |
|
||||
| `store.vector.extensionPath` | `string` | 内置 | 覆盖 sqlite-vec 路径 |
|
||||
|
||||
当 sqlite-vec 不可用时,OpenClaw 会自动回退到进程内余弦相似度计算。
|
||||
|
||||
@ -373,87 +404,86 @@ openclaw memory index --force --agent main
|
||||
|
||||
## 索引存储
|
||||
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| --------------------- | -------- | ------------------------------------- | ------------------------------------- |
|
||||
| `store.path` | `string` | `~/.openclaw/memory/{agentId}.sqlite` | 索引位置(支持 `{agentId}` 占位符) |
|
||||
| `store.fts.tokenizer` | `string` | `unicode61` | FTS5 分词器(`unicode61` 或 `trigram`) |
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| --------------------- | -------- | ------------------------------------- | ------------------------------------------- |
|
||||
| `store.path` | `string` | `~/.openclaw/memory/{agentId}.sqlite` | 索引位置(支持 `{agentId}` token) |
|
||||
| `store.fts.tokenizer` | `string` | `unicode61` | FTS5 tokenizer(`unicode61` 或 `trigram`) |
|
||||
|
||||
---
|
||||
|
||||
## QMD 后端配置
|
||||
|
||||
设置 `memory.backend = "qmd"` 以启用。所有 QMD 设置都位于
|
||||
`memory.qmd` 下:
|
||||
设置 `memory.backend = "qmd"` 以启用。所有 QMD 设置都位于 `memory.qmd` 下:
|
||||
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| ------------------------ | --------- | -------- | -------------------------------------------- |
|
||||
| `command` | `string` | `qmd` | QMD 可执行文件路径 |
|
||||
| `searchMode` | `string` | `search` | 搜索命令:`search`、`vsearch`、`query` |
|
||||
| `includeDefaultMemory` | `boolean` | `true` | 自动索引 `MEMORY.md` + `memory/**/*.md` |
|
||||
| `paths[]` | `array` | -- | 额外路径:`{ name, path, pattern? }` |
|
||||
| `sessions.enabled` | `boolean` | `false` | 索引会话转录 |
|
||||
| `sessions.retentionDays` | `number` | -- | 转录保留时长 |
|
||||
| `sessions.exportDir` | `string` | -- | 导出目录 |
|
||||
| `command` | `string` | `qmd` | QMD 可执行文件路径 |
|
||||
| `searchMode` | `string` | `search` | 搜索命令:`search`、`vsearch`、`query` |
|
||||
| `includeDefaultMemory` | `boolean` | `true` | 自动索引 `MEMORY.md` + `memory/**/*.md` |
|
||||
| `paths[]` | `array` | -- | 额外路径:`{ name, path, pattern? }` |
|
||||
| `sessions.enabled` | `boolean` | `false` | 索引会话 transcript |
|
||||
| `sessions.retentionDays` | `number` | -- | transcript 保留期 |
|
||||
| `sessions.exportDir` | `string` | -- | 导出目录 |
|
||||
|
||||
OpenClaw 优先使用当前的 QMD collection 和 MCP 查询结构,但在需要时也会通过回退到旧版 `--mask` collection 标志和旧版 MCP 工具名称来兼容较老的 QMD 版本。
|
||||
OpenClaw 优先使用当前的 QMD collection 和 MCP query 结构,但在需要时会回退到旧版 `--mask` collection 标志和旧版 MCP 工具名,以保持旧版 QMD 仍可工作。
|
||||
|
||||
QMD 模型覆盖保留在 QMD 侧,而不是放在 OpenClaw 配置中。如果你需要全局覆盖 QMD 的模型,请在 Gateway 网关 运行时环境中设置环境变量,例如
|
||||
`QMD_EMBED_MODEL`、`QMD_RERANK_MODEL` 和 `QMD_GENERATE_MODEL`。
|
||||
<Note>
|
||||
QMD 模型覆盖保留在 QMD 一侧,而不是 OpenClaw 配置中。如果你需要全局覆盖 QMD 的模型,请在 Gateway 网关运行时环境中设置环境变量,例如 `QMD_EMBED_MODEL`、`QMD_RERANK_MODEL` 和 `QMD_GENERATE_MODEL`。
|
||||
</Note>
|
||||
|
||||
### 更新计划
|
||||
<AccordionGroup>
|
||||
<Accordion title="更新计划">
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| ------------------------- | --------- | ------- | ------------------------------------- |
|
||||
| `update.interval` | `string` | `5m` | 刷新间隔 |
|
||||
| `update.debounceMs` | `number` | `15000` | 文件变更防抖 |
|
||||
| `update.onBoot` | `boolean` | `true` | 启动时刷新 |
|
||||
| `update.waitForBootSync` | `boolean` | `false` | 在刷新完成前阻塞启动 |
|
||||
| `update.embedInterval` | `string` | -- | 单独的嵌入频率 |
|
||||
| `update.commandTimeoutMs` | `number` | -- | QMD 命令超时 |
|
||||
| `update.updateTimeoutMs` | `number` | -- | QMD 更新操作超时 |
|
||||
| `update.embedTimeoutMs` | `number` | -- | QMD 嵌入操作超时 |
|
||||
</Accordion>
|
||||
<Accordion title="限制">
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| ------------------------- | -------- | ------- | -------------------------- |
|
||||
| `limits.maxResults` | `number` | `6` | 最大搜索结果数 |
|
||||
| `limits.maxSnippetChars` | `number` | -- | 限制片段长度 |
|
||||
| `limits.maxInjectedChars` | `number` | -- | 限制注入总字符数 |
|
||||
| `limits.timeoutMs` | `number` | `4000` | 搜索超时 |
|
||||
</Accordion>
|
||||
<Accordion title="作用域">
|
||||
控制哪些会话可以接收 QMD 搜索结果。schema 与 [`session.sendPolicy`](/zh-CN/gateway/config-agents#session) 相同:
|
||||
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| ------------------------- | --------- | --------- | ------------------------------ |
|
||||
| `update.interval` | `string` | `5m` | 刷新间隔 |
|
||||
| `update.debounceMs` | `number` | `15000` | 文件变更防抖 |
|
||||
| `update.onBoot` | `boolean` | `true` | 启动时刷新 |
|
||||
| `update.waitForBootSync` | `boolean` | `false` | 阻塞启动直到刷新完成 |
|
||||
| `update.embedInterval` | `string` | -- | 单独的嵌入执行周期 |
|
||||
| `update.commandTimeoutMs` | `number` | -- | QMD 命令超时时间 |
|
||||
| `update.updateTimeoutMs` | `number` | -- | QMD 更新操作超时时间 |
|
||||
| `update.embedTimeoutMs` | `number` | -- | QMD 嵌入操作超时时间 |
|
||||
|
||||
### 限制
|
||||
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| ------------------------- | -------- | ------- | ------------------------ |
|
||||
| `limits.maxResults` | `number` | `6` | 最大搜索结果数 |
|
||||
| `limits.maxSnippetChars` | `number` | -- | 限制摘要片段长度 |
|
||||
| `limits.maxInjectedChars` | `number` | -- | 限制注入的总字符数 |
|
||||
| `limits.timeoutMs` | `number` | `4000` | 搜索超时时间 |
|
||||
|
||||
### 作用范围
|
||||
|
||||
控制哪些会话可以接收 QMD 搜索结果。使用与
|
||||
[`session.sendPolicy`](/zh-CN/gateway/config-agents#session) 相同的 schema:
|
||||
|
||||
```json5
|
||||
{
|
||||
memory: {
|
||||
qmd: {
|
||||
scope: {
|
||||
default: "deny",
|
||||
rules: [{ action: "allow", match: { chatType: "direct" } }],
|
||||
```json5
|
||||
{
|
||||
memory: {
|
||||
qmd: {
|
||||
scope: {
|
||||
default: "deny",
|
||||
rules: [{ action: "allow", match: { chatType: "direct" } }],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
}
|
||||
```
|
||||
|
||||
内置默认值允许私信和渠道会话,同时仍然拒绝群组。
|
||||
内置默认值允许 direct 和渠道会话,同时仍然拒绝群组。
|
||||
|
||||
默认仅限私信。`match.keyPrefix` 匹配规范化后的会话键;
|
||||
`match.rawKeyPrefix` 匹配包含 `agent:<id>:` 的原始键。
|
||||
默认仅限私信。`match.keyPrefix` 匹配规范化后的会话键;`match.rawKeyPrefix` 匹配包含 `agent:<id>:` 的原始键。
|
||||
|
||||
### 引用
|
||||
</Accordion>
|
||||
<Accordion title="引用">
|
||||
`memory.citations` 适用于所有后端:
|
||||
|
||||
`memory.citations` 适用于所有后端:
|
||||
| 值 | 行为 |
|
||||
| ---------------- | --------------------------------------------------- |
|
||||
| `auto`(默认) | 在片段中包含 `Source: <path#line>` 页脚 |
|
||||
| `on` | 始终包含页脚 |
|
||||
| `off` | 省略页脚(路径仍会在内部传递给智能体) |
|
||||
|
||||
| 值 | 行为 |
|
||||
| ---------------- | ------------------------------------------------- |
|
||||
| `auto`(默认) | 在摘要片段中包含 `Source: <path#line>` 页脚 |
|
||||
| `on` | 始终包含页脚 |
|
||||
| `off` | 省略页脚(路径仍会在内部传递给智能体) |
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### 完整 QMD 示例
|
||||
|
||||
@ -480,19 +510,18 @@ QMD 模型覆盖保留在 QMD 侧,而不是放在 OpenClaw 配置中。如果
|
||||
|
||||
## Dreaming
|
||||
|
||||
Dreaming 配置位于 `plugins.entries.memory-core.config.dreaming` 下,
|
||||
而不在 `agents.defaults.memorySearch` 下。
|
||||
Dreaming 配置位于 `plugins.entries.memory-core.config.dreaming` 下,而不是 `agents.defaults.memorySearch` 下。
|
||||
|
||||
Dreaming 作为一次定时扫描运行,并将内部的 light/deep/REM 阶段作为实现细节使用。
|
||||
Dreaming 以一次计划扫描运行,并将内部的 light / deep / REM 阶段作为实现细节使用。
|
||||
|
||||
有关概念行为和斜杠命令,请参见 [Dreaming](/zh-CN/concepts/dreaming)。
|
||||
关于概念性行为和斜杠命令,请参见 [Dreaming](/zh-CN/concepts/dreaming)。
|
||||
|
||||
### 用户设置
|
||||
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| ----------- | --------- | ----------- | ---------------------------------- |
|
||||
| `enabled` | `boolean` | `false` | 完全启用或禁用 Dreaming |
|
||||
| `frequency` | `string` | `0 3 * * *` | 完整 Dreaming 扫描的可选 cron 周期 |
|
||||
| 键 | 类型 | 默认值 | 说明 |
|
||||
| ----------- | --------- | ----------- | ------------------------------------------------- |
|
||||
| `enabled` | `boolean` | `false` | 完全启用或禁用 Dreaming |
|
||||
| `frequency` | `string` | `0 3 * * *` | 完整 Dreaming 扫描的可选 cron 频率 |
|
||||
|
||||
### 示例
|
||||
|
||||
@ -513,14 +542,14 @@ Dreaming 作为一次定时扫描运行,并将内部的 light/deep/REM 阶段
|
||||
}
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
- Dreaming 将机器状态写入 `memory/.dreams/`。
|
||||
- Dreaming 将人类可读的叙事输出写入 `DREAMS.md`(或现有的 `dreams.md`)。
|
||||
- light/deep/REM 阶段策略和阈值属于内部行为,不是面向用户的配置。
|
||||
<Note>
|
||||
- Dreaming 会将机器状态写入 `memory/.dreams/`。
|
||||
- Dreaming 会将人类可读的叙事输出写入 `DREAMS.md`(或现有的 `dreams.md`)。
|
||||
- light / deep / REM 阶段策略和阈值属于内部行为,不是面向用户的配置。
|
||||
</Note>
|
||||
|
||||
## 相关内容
|
||||
|
||||
- [Memory overview](/zh-CN/concepts/memory)
|
||||
- [Memory search](/zh-CN/concepts/memory-search)
|
||||
- [Configuration reference](/zh-CN/gateway/configuration-reference)
|
||||
- [配置参考](/zh-CN/gateway/configuration-reference)
|
||||
- [Memory 概览](/zh-CN/concepts/memory)
|
||||
- [Memory 搜索](/zh-CN/concepts/memory-search)
|
||||
|
||||
@ -1,40 +1,37 @@
|
||||
---
|
||||
read_when:
|
||||
- 为 Claude Code / Codex / Gemini CLI 安装或配置 `acpx` harness
|
||||
- 启用 `plugin-tools` 或 OpenClaw-tools MCP 桥接
|
||||
- 为 Claude Code / Codex / Gemini CLI 安装或配置 acpx harness
|
||||
- 启用 plugin-tools 或 OpenClaw-tools MCP 桥接
|
||||
- 配置 ACP 权限模式
|
||||
summary: 设置 ACP 智能体:`acpx` harness 配置、插件设置、权限
|
||||
title: ACP 智能体——设置
|
||||
summary: 设置 ACP 智能体:acpx harness 配置、插件设置和权限
|
||||
title: ACP 智能体 — 设置
|
||||
x-i18n:
|
||||
generated_at: "2026-04-26T03:54:10Z"
|
||||
generated_at: "2026-04-26T07:51:15Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 0520b3e5fcc34be478aea807527b4a60c349267650a8f59ea2f79150d54161f8
|
||||
source_hash: 5c7a638dd26b9343ea5a183954dd3ce3822b904bd2f46dd24f13a6785a646ea3
|
||||
source_path: tools/acp-agents-setup.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
有关概览、操作手册和核心概念,请参阅 [ACP 智能体](/zh-CN/tools/acp-agents)。
|
||||
有关概览、操作员运行手册和概念,请参阅 [ACP 智能体](/zh-CN/tools/acp-agents)。
|
||||
|
||||
以下各节介绍 `acpx` harness 配置、MCP 桥接的插件设置以及权限配置。
|
||||
以下章节涵盖 acpx harness 配置、MCP 桥接的插件设置以及权限配置。
|
||||
|
||||
仅当你正在设置 ACP/acpx 路线时使用本页。对于原生 Codex
|
||||
app-server 运行时配置,请使用 [Codex harness](/zh-CN/plugins/codex-harness)。对于
|
||||
OpenAI API 密钥或 Codex OAuth 模型提供商配置,请使用
|
||||
[OpenAI](/zh-CN/providers/openai)。
|
||||
仅当你在设置 ACP/acpx 路线时使用本页。对于原生 Codex app-server 运行时配置,请使用 [Codex harness](/zh-CN/plugins/codex-harness)。对于 OpenAI API key 或 Codex OAuth 模型提供商配置,请使用 [OpenAI](/zh-CN/providers/openai)。
|
||||
|
||||
Codex 有两条 OpenClaw 路线:
|
||||
Codex 在 OpenClaw 中有两条路线:
|
||||
|
||||
| 路线 | 配置/命令 | 设置页面 |
|
||||
| -------------------------- | ------------------------------------------------------ | --------------------------------------- |
|
||||
| 原生 Codex app-server | `/codex ...`,`embeddedHarness.runtime: "codex"` | [Codex harness](/zh-CN/plugins/codex-harness) |
|
||||
| 原生 Codex app-server | `/codex ...`,`agentRuntime.id: "codex"` | [Codex harness](/zh-CN/plugins/codex-harness) |
|
||||
| 显式 Codex ACP 适配器 | `/acp spawn codex`,`runtime: "acp", agentId: "codex"` | 本页 |
|
||||
|
||||
除非你明确需要 ACP/acpx 行为,否则优先使用原生路线。
|
||||
|
||||
## `acpx` harness 支持(当前)
|
||||
## acpx harness 支持(当前)
|
||||
|
||||
当前 `acpx` 内置的 harness 别名:
|
||||
当前 acpx 内置 harness 别名:
|
||||
|
||||
- `claude`
|
||||
- `codex`
|
||||
@ -51,15 +48,12 @@ Codex 有两条 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` 路径)。
|
||||
|
||||
模型控制取决于适配器能力。Codex ACP 模型引用会在启动前由
|
||||
OpenClaw 规范化。其他 harness 需要 ACP `models` 加 `session/set_model`
|
||||
支持;如果某个 harness 既不暴露该 ACP 能力,也不提供自己的启动模型标志,
|
||||
那么 OpenClaw/`acpx` 无法强制选择模型。
|
||||
模型控制取决于适配器能力。Codex ACP 模型引用会在启动前由 OpenClaw 进行规范化。其他 harness 需要 ACP `models` 加上 `session/set_model` 支持;如果某个 harness 既不暴露该 ACP 能力,也没有自身的启动模型标志,那么 OpenClaw/acpx 就无法强制选择模型。
|
||||
|
||||
## 必需配置
|
||||
|
||||
@ -69,7 +63,7 @@ OpenClaw 规范化。其他 harness 需要 ACP `models` 加 `session/set_model`
|
||||
{
|
||||
acp: {
|
||||
enabled: true,
|
||||
// 可选。默认值为 true;设置为 false 可暂停 ACP 分发,同时保留 /acp 控制。
|
||||
// 可选。默认值为 true;设为 false 可暂停 ACP 分发,同时保留 /acp 控制。
|
||||
dispatch: { enabled: true },
|
||||
backend: "acpx",
|
||||
defaultAgent: "codex",
|
||||
@ -101,7 +95,7 @@ OpenClaw 规范化。其他 harness 需要 ACP `models` 加 `session/set_model`
|
||||
}
|
||||
```
|
||||
|
||||
线程绑定配置取决于渠道适配器。以下是 Discord 的示例:
|
||||
线程绑定配置取决于渠道适配器。以下是 Discord 示例:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -123,27 +117,25 @@ OpenClaw 规范化。其他 harness 需要 ACP `models` 加 `session/set_model`
|
||||
}
|
||||
```
|
||||
|
||||
如果线程绑定的 ACP 派生无法工作,请先验证适配器功能标志:
|
||||
如果线程绑定的 ACP 启动无效,请先验证适配器功能标志:
|
||||
|
||||
- Discord:`channels.discord.threadBindings.spawnAcpSessions=true`
|
||||
|
||||
当前会话绑定不需要创建子线程。它们需要一个活动的会话上下文,以及一个暴露 ACP 会话绑定的渠道适配器。
|
||||
当前对话绑定不需要创建子线程。它们需要活动的对话上下文,以及暴露 ACP 对话绑定的渠道适配器。
|
||||
|
||||
请参阅 [配置参考](/zh-CN/gateway/configuration-reference)。
|
||||
参见 [配置参考](/zh-CN/gateway/configuration-reference)。
|
||||
|
||||
## `acpx` 后端的插件设置
|
||||
## acpx 后端的插件设置
|
||||
|
||||
全新安装默认启用内置的 `acpx` 运行时插件,因此 ACP
|
||||
通常无需手动安装插件步骤即可工作。
|
||||
全新安装默认启用内置的 `acpx` 运行时插件,因此 ACP 通常无需手动安装插件即可工作。
|
||||
|
||||
先从这里开始:
|
||||
先执行:
|
||||
|
||||
```text
|
||||
/acp doctor
|
||||
```
|
||||
|
||||
如果你禁用了 `acpx`、通过 `plugins.allow` / `plugins.deny` 拒绝了它,或者想
|
||||
切换到本地开发检出版本,请使用显式插件路径:
|
||||
如果你禁用了 `acpx`、通过 `plugins.allow` / `plugins.deny` 拒绝了它,或者想切换到本地开发检出版本,请使用显式插件路径:
|
||||
|
||||
```bash
|
||||
openclaw plugins install acpx
|
||||
@ -162,11 +154,9 @@ openclaw plugins install ./path/to/local/acpx-plugin
|
||||
/acp doctor
|
||||
```
|
||||
|
||||
### `acpx` 命令和版本配置
|
||||
### acpx 命令和版本配置
|
||||
|
||||
默认情况下,内置的 `acpx` 插件会注册嵌入式 ACP 后端,而不会在
|
||||
Gateway 网关启动期间派生 ACP 智能体。运行 `/acp doctor` 可进行显式实时探测。只有当你需要
|
||||
Gateway 网关在启动时探测已配置智能体时,才设置 `OPENCLAW_ACPX_RUNTIME_STARTUP_PROBE=1`。
|
||||
默认情况下,内置 `acpx` 插件会注册嵌入式 ACP 后端,而不会在 Gateway 网关启动期间生成 ACP 智能体。运行 `/acp doctor` 可进行显式的实时探测。仅当你需要 Gateway 网关在启动时探测已配置智能体时,才设置 `OPENCLAW_ACPX_RUNTIME_STARTUP_PROBE=1`。
|
||||
|
||||
在插件配置中覆盖命令或版本:
|
||||
|
||||
@ -186,89 +176,80 @@ Gateway 网关在启动时探测已配置智能体时,才设置 `OPENCLAW_ACPX
|
||||
}
|
||||
```
|
||||
|
||||
- `command` 接受绝对路径、相对路径(从 OpenClaw 工作区解析)或命令名。
|
||||
- `command` 接受绝对路径、相对路径(相对于 OpenClaw 工作区解析)或命令名。
|
||||
- `expectedVersion: "any"` 会禁用严格版本匹配。
|
||||
- 自定义 `command` 路径会禁用插件本地自动安装。
|
||||
|
||||
请参阅 [插件](/zh-CN/tools/plugin)。
|
||||
参见 [Plugins](/zh-CN/tools/plugin)。
|
||||
|
||||
### 自动依赖安装
|
||||
|
||||
当你使用 `npm install -g openclaw` 全局安装 OpenClaw 时,`acpx`
|
||||
运行时依赖(特定平台二进制文件)会通过 postinstall 钩子自动安装。如果自动安装失败,
|
||||
Gateway 网关仍会正常启动,并通过 `openclaw acp doctor` 报告缺失的依赖。
|
||||
当你通过 `npm install -g openclaw` 全局安装 OpenClaw 时,acpx 运行时依赖(平台特定二进制文件)会通过 postinstall 钩子自动安装。如果自动安装失败,Gateway 网关仍会正常启动,并通过 `openclaw acp doctor` 报告缺失的依赖。
|
||||
|
||||
### 插件工具 MCP 桥接
|
||||
|
||||
默认情况下,ACPX 会话**不会**向 ACP harness 暴露 OpenClaw 已注册插件的工具。
|
||||
默认情况下,ACPX 会话**不会**向 ACP harness 暴露 OpenClaw 插件注册的工具。
|
||||
|
||||
如果你希望 Codex 或 Claude Code 等 ACP 智能体能够调用已安装的
|
||||
OpenClaw 插件工具,例如 memory recall/store,请启用专用桥接:
|
||||
如果你希望 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 网关中已经处于活动状态的插件工具。
|
||||
- 这会扩大 ACP harness 的工具表面。
|
||||
- ACP 智能体仅能访问 Gateway 网关中已激活的插件工具。
|
||||
- 应将这视为与允许这些插件在 OpenClaw 本身中执行相同的信任边界。
|
||||
- 启用前请审查已安装插件。
|
||||
- 启用前请检查已安装的插件。
|
||||
|
||||
自定义 `mcpServers` 仍按原样工作。内置的插件工具桥接是一个额外的可选便捷功能,不是通用 MCP 服务器配置的替代品。
|
||||
自定义 `mcpServers` 仍按原样工作。内置的 plugin-tools 桥接只是额外的可选便利功能,并不是通用 MCP 服务器配置的替代品。
|
||||
|
||||
### OpenClaw 工具 MCP 桥接
|
||||
|
||||
默认情况下,ACPX 会话也**不会**通过 MCP 暴露内置的 OpenClaw 工具。当 ACP 智能体需要选定的
|
||||
内置工具(例如 `cron`)时,请启用单独的核心工具桥接:
|
||||
默认情况下,ACPX 会话也**不会**通过 MCP 暴露内置 OpenClaw 工具。当 ACP 智能体需要使用选定的内置工具(例如 `cron`)时,请启用独立的核心工具桥接:
|
||||
|
||||
```bash
|
||||
openclaw config set plugins.entries.acpx.config.openClawToolsMcpBridge true
|
||||
```
|
||||
|
||||
这会带来以下效果:
|
||||
其作用如下:
|
||||
|
||||
- 在 ACPX 会话引导期间注入一个名为 `openclaw-tools` 的内置 MCP 服务器。
|
||||
- 在 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 网关。
|
||||
|
||||
### 健康探测智能体配置
|
||||
### 健康探针智能体配置
|
||||
|
||||
当 `/acp doctor` 或可选启用的启动探测检查后端时,内置的
|
||||
`acpx` 插件会探测一个 harness 智能体。如果设置了 `acp.allowedAgents`,它
|
||||
默认使用第一个允许的智能体;否则默认使用 `codex`。如果你的部署
|
||||
需要使用不同的 ACP 智能体进行健康检查,请显式设置探测智能体:
|
||||
当 `/acp doctor` 或选择启用的启动探针检查后端时,内置 `acpx` 插件会探测一个 harness 智能体。如果设置了 `acp.allowedAgents`,则默认探测第一个允许的智能体;否则默认探测 `codex`。如果你的部署需要使用不同的 ACP 智能体进行健康检查,请显式设置探针智能体:
|
||||
|
||||
```bash
|
||||
openclaw config set plugins.entries.acpx.config.probeAgent claude
|
||||
```
|
||||
|
||||
更改此值后请重启 Gateway 网关。
|
||||
更改该值后请重启 Gateway 网关。
|
||||
|
||||
## 权限配置
|
||||
|
||||
ACP 会话以非交互方式运行——没有 TTY 可用于批准或拒绝文件写入和 shell 执行权限提示。`acpx` 插件提供了两个控制权限处理方式的配置键:
|
||||
ACP 会话以非交互方式运行——没有 TTY 可用于批准或拒绝文件写入和 shell 执行权限提示。acpx 插件提供了两个配置键来控制权限处理方式:
|
||||
|
||||
这些 ACPX harness 权限与 OpenClaw 执行审批是分开的,也与 CLI 后端供应商绕过标志(例如 Claude CLI `--permission-mode bypassPermissions`)分开。ACPX `approve-all` 是 ACP 会话在 harness 层级的紧急放开开关。
|
||||
这些 ACPX harness 权限独立于 OpenClaw exec 批准,也独立于 CLI 后端供应商绕过标志,例如 Claude CLI `--permission-mode bypassPermissions`。ACPX `approve-all` 是 ACP 会话的 harness 级紧急放行开关。
|
||||
|
||||
### `permissionMode`
|
||||
|
||||
@ -276,18 +257,18 @@ ACP 会话以非交互方式运行——没有 TTY 可用于批准或拒绝文
|
||||
|
||||
| 值 | 行为 |
|
||||
| --------------- | --------------------------------------------------------- |
|
||||
| `approve-all` | 自动批准所有文件写入和 shell 命令。 |
|
||||
| `approve-all` | 自动批准所有文件写入和 shell 命令。 |
|
||||
| `approve-reads` | 仅自动批准读取;写入和执行需要提示。 |
|
||||
| `deny-all` | 拒绝所有权限提示。 |
|
||||
| `deny-all` | 拒绝所有权限提示。 |
|
||||
|
||||
### `nonInteractivePermissions`
|
||||
|
||||
控制在本应显示权限提示但没有可交互 TTY 可用时会发生什么(对于 ACP 会话,这种情况始终成立)。
|
||||
控制当本应显示权限提示、但没有可用交互式 TTY 时会发生什么(对于 ACP 会话这始终如此)。
|
||||
|
||||
| 值 | 行为 |
|
||||
| ------ | ----------------------------------------------------------------- |
|
||||
| `fail` | 以 `AcpRuntimeError` 中止会话。**(默认)** |
|
||||
| `deny` | 静默拒绝权限并继续(优雅降级)。 |
|
||||
| `fail` | 以 `AcpRuntimeError` 中止会话。**(默认)** |
|
||||
| `deny` | 静默拒绝权限并继续(平滑降级)。 |
|
||||
|
||||
### 配置
|
||||
|
||||
@ -302,10 +283,10 @@ openclaw config set plugins.entries.acpx.config.nonInteractivePermissions fail
|
||||
|
||||
> **重要:** OpenClaw 当前默认使用 `permissionMode=approve-reads` 和 `nonInteractivePermissions=fail`。在非交互式 ACP 会话中,任何触发权限提示的写入或执行操作都可能因 `AcpRuntimeError: Permission prompt unavailable in non-interactive mode` 而失败。
|
||||
>
|
||||
> 如果你需要限制权限,请将 `nonInteractivePermissions` 设置为 `deny`,这样会话就会优雅降级而不是崩溃。
|
||||
> 如果你需要限制权限,请将 `nonInteractivePermissions` 设为 `deny`,这样会话会平滑降级,而不是直接崩溃。
|
||||
|
||||
## 相关
|
||||
## 相关内容
|
||||
|
||||
- [ACP 智能体](/zh-CN/tools/acp-agents) —— 概览、操作手册、核心概念
|
||||
- [子智能体](/zh-CN/tools/subagents)
|
||||
- [ACP 智能体](/zh-CN/tools/acp-agents) — 概览、操作员运行手册、概念
|
||||
- [Sub-agents](/zh-CN/tools/subagents)
|
||||
- [多智能体路由](/zh-CN/concepts/multi-agent)
|
||||
|
||||
@ -1,100 +1,121 @@
|
||||
---
|
||||
read_when:
|
||||
- 通过 ACP 运行编码 harnesses
|
||||
- 在消息渠道上设置与会话绑定的 ACP 会话
|
||||
- 将消息渠道中的对话绑定到持久化 ACP 会话
|
||||
- 通过 ACP 运行编码 harness
|
||||
- 在消息渠道上设置绑定到会话的 ACP 会话
|
||||
- 将消息渠道会话绑定到持久化 ACP 会话
|
||||
- 排查 ACP 后端、插件接线或完成结果投递问题
|
||||
- 从聊天中操作 `/acp` 命令
|
||||
- 在聊天中操作 `/acp` 命令
|
||||
sidebarTitle: ACP agents
|
||||
summary: 通过 ACP 后端运行外部编码 harnesses(Claude Code、Cursor、Gemini CLI、显式 Codex ACP、OpenClaw ACP、OpenCode)
|
||||
summary: 通过 ACP 后端运行外部编码 harness(Claude Code、Cursor、Gemini CLI、显式 Codex ACP、OpenClaw ACP、OpenCode)
|
||||
title: ACP 智能体
|
||||
x-i18n:
|
||||
generated_at: "2026-04-26T06:20:25Z"
|
||||
generated_at: "2026-04-26T07:51:28Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 00f111cabc46074f5185fefae232bf5d8dfb120fbfdde84a5ea2bfd01c956218
|
||||
source_hash: e3b8550be4cf0da2593b0770e302833e1722820d3c922e5508a253685cd0cb6b
|
||||
source_path: tools/acp-agents.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
[Agent Client Protocol(ACP)](https://agentclientprotocol.com/) 会话
|
||||
|
||||
让 OpenClaw 通过 ACP 后端插件运行外部编码 harnesses(例如 Pi、Claude Code、Cursor、Copilot、Droid、OpenClaw ACP、OpenCode、Gemini CLI,以及其他受支持的 ACPX harnesses)。
|
||||
[Agent Client Protocol (ACP)](https://agentclientprotocol.com/) 会话
|
||||
让 OpenClaw 通过 ACP 后端插件运行外部编码 harness(例如 Pi、Claude Code、
|
||||
Cursor、Copilot、Droid、OpenClaw ACP、OpenCode、Gemini CLI,以及其他
|
||||
受支持的 ACPX harness)。
|
||||
|
||||
每个 ACP 会话启动都会被跟踪为一个[后台任务](/zh-CN/automation/tasks)。
|
||||
|
||||
<Note>
|
||||
**ACP 是外部 harness 路径,不是默认的 Codex 路径。** 原生 Codex app-server 插件负责 `/codex ...` 控制以及 `embeddedHarness.runtime: "codex"` 嵌入式运行时;ACP 负责 `/acp ...` 控制和 `sessions_spawn({ runtime: "acp" })` 会话。
|
||||
**ACP 是外部 harness 路径,不是默认的 Codex 路径。**
|
||||
原生 Codex 应用服务器插件负责 `/codex ...` 控制,以及
|
||||
`agentRuntime.id: "codex"` 内嵌运行时;ACP 负责
|
||||
`/acp ...` 控制和 `sessions_spawn({ runtime: "acp" })` 会话。
|
||||
|
||||
如果你想让 Codex 或 Claude Code 作为外部 MCP 客户端,直接连接到现有的 OpenClaw 渠道对话,请使用 [`openclaw mcp serve`](/zh-CN/cli/mcp) 而不是 ACP。
|
||||
如果你想让 Codex 或 Claude Code 作为外部 MCP 客户端
|
||||
直接连接到现有的 OpenClaw 渠道会话,请使用
|
||||
[`openclaw mcp serve`](/zh-CN/cli/mcp),而不是 ACP。
|
||||
</Note>
|
||||
|
||||
## 我想看哪个页面?
|
||||
## 我需要哪一页?
|
||||
|
||||
| 你想要…… | 使用这个 | 说明 |
|
||||
| 你想要… | 使用这个 | 说明 |
|
||||
| ----------------------------------------------------------------------------------------------- | ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| 在当前对话中绑定或控制 Codex | `/codex bind`、`/codex threads` | 当启用 `codex` 插件时,使用原生 Codex app-server 路径;包括绑定聊天回复、图片转发、模型/快速/权限设置、停止和引导控制。ACP 是显式回退方案 |
|
||||
| 通过 OpenClaw _运行_ Claude Code、Gemini CLI、显式 Codex ACP 或其他外部 harness | 本页 | 聊天绑定会话、`/acp spawn`、`sessions_spawn({ runtime: "acp" })`、后台任务、运行时控制 |
|
||||
| 将一个 OpenClaw Gateway 网关会话 _作为_ ACP 服务器暴露给编辑器或客户端 | [`openclaw acp`](/zh-CN/cli/acp) | 桥接模式。IDE/客户端 通过 stdio/WebSocket 使用 ACP 与 OpenClaw 通信 |
|
||||
| 在当前会话中绑定或控制 Codex | `/codex bind`、`/codex threads` | 当启用 `codex` 插件时使用原生 Codex 应用服务器路径;包括绑定聊天回复、图像转发、模型/fast/permissions、停止和 steer 控制。ACP 是显式回退路径 |
|
||||
| 通过 OpenClaw 运行 Claude Code、Gemini CLI、显式 Codex ACP 或其他外部 harness | 本页 | 绑定聊天的会话、`/acp spawn`、`sessions_spawn({ runtime: "acp" })`、后台任务、运行时控制 |
|
||||
| 将一个 OpenClaw Gateway 网关会话作为 ACP 服务器暴露给编辑器或客户端 | [`openclaw acp`](/zh-CN/cli/acp) | 桥接模式。IDE/客户端 通过 stdio/WebSocket 使用 ACP 与 OpenClaw 通信 |
|
||||
| 复用本地 AI CLI 作为纯文本回退模型 | [CLI Backends](/zh-CN/gateway/cli-backends) | 不是 ACP。没有 OpenClaw 工具、没有 ACP 控制、没有 harness 运行时 |
|
||||
|
||||
## 这是开箱即用的吗?
|
||||
## 开箱即用吗?
|
||||
|
||||
通常可以。全新安装默认启用内置的 `acpx` 运行时插件,并附带插件本地固定版本的 `acpx` 二进制文件;OpenClaw 会在启动时探测并自我修复它。运行 `/acp doctor` 可执行就绪性检查。
|
||||
通常可以。全新安装默认启用了内置的 `acpx` 运行时插件,
|
||||
并带有插件本地固定版本的 `acpx` 二进制,OpenClaw 会在启动时探测它
|
||||
并执行自修复。运行 `/acp doctor` 可进行就绪检查。
|
||||
|
||||
只有在 ACP **真正可用** 时,OpenClaw 才会向智能体介绍 ACP 启动功能:必须启用 ACP、不能禁用分发、当前会话不能被沙箱阻止,并且必须已加载运行时后端。如果这些条件不满足,ACP 插件 Skills 和 `sessions_spawn` 的 ACP 指导会保持隐藏,这样智能体就不会建议使用不可用的后端。
|
||||
只有当 ACP **真正可用** 时,OpenClaw 才会向智能体介绍 ACP 启动功能:
|
||||
ACP 必须已启用、分发不能被禁用、当前会话不能被沙箱阻止,并且必须已加载
|
||||
一个运行时后端。如果这些条件不满足,ACP 插件 Skills 和
|
||||
`sessions_spawn` 的 ACP 指南会保持隐藏,这样智能体就不会建议
|
||||
一个不可用的后端。
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="首次运行的常见问题">
|
||||
- 如果设置了 `plugins.allow`,它就是一个限制性的插件清单,并且**必须**包含 `acpx`;否则内置默认项会被有意阻止,`/acp doctor` 会报告缺少 allowlist 条目。
|
||||
- 目标 harness 适配器(Codex、Claude 等)在你第一次使用时,可能会按需通过 `npx` 获取。
|
||||
- 该 harness 所需的供应商认证仍然必须存在于主机上。
|
||||
- 如果主机没有 npm 或网络访问能力,首次运行时获取适配器将会失败,直到缓存被预热或适配器通过其他方式安装。
|
||||
<Accordion title="首次运行注意事项">
|
||||
- 如果设置了 `plugins.allow`,它就是一个限制性的插件清单,并且**必须**包含 `acpx`;否则内置默认值会被有意阻止,`/acp doctor` 会报告缺少允许列表条目。
|
||||
- 目标 harness 适配器(Codex、Claude 等)可能会在你首次使用时通过 `npx` 按需拉取。
|
||||
- 该 harness 的供应商认证仍然必须存在于主机上。
|
||||
- 如果主机没有 npm 或网络访问能力,首次运行的适配器拉取会失败,直到缓存被预热或适配器以其他方式安装为止。
|
||||
</Accordion>
|
||||
<Accordion title="运行时前置条件">
|
||||
ACP 会启动一个真实的外部 harness 进程。OpenClaw 负责路由、后台任务状态、结果投递、绑定和策略;harness 负责自己的 provider 登录、模型目录、文件系统行为和原生工具。
|
||||
<Accordion title="运行时前提条件">
|
||||
ACP 会启动一个真实的外部 harness 进程。OpenClaw 负责路由、
|
||||
后台任务状态、投递、绑定和策略;harness
|
||||
负责其 provider 登录、模型目录、文件系统行为以及
|
||||
原生工具。
|
||||
|
||||
在责怪 OpenClaw 之前,请先确认:
|
||||
|
||||
- `/acp doctor` 报告后端已启用且健康。
|
||||
- 当设置了 allowlist 时,目标 id 已被 `acp.allowedAgents` 允许。
|
||||
- 当设置了 `acp.allowedAgents` 允许列表时,目标 id 在允许范围内。
|
||||
- harness 命令可以在 Gateway 网关主机上启动。
|
||||
- 该 harness 所需的 provider 认证已存在(`claude`、`codex`、`gemini`、`opencode`、`droid` 等)。
|
||||
- 所选模型对该 harness 确实存在——模型 id 不能在不同 harness 之间通用。
|
||||
- 请求的 `cwd` 存在且可访问,或者省略 `cwd`,让后端使用其默认值。
|
||||
- 权限模式与工作内容匹配。非交互式会话无法点击原生权限提示,因此大量写入/执行的编码运行通常需要一个能以无头方式继续执行的 ACPX 权限配置文件。
|
||||
- 所选模型确实存在于该 harness 中——模型 id 在不同 harness 之间并不通用。
|
||||
- 请求的 `cwd` 存在且可访问,或者省略 `cwd` 让后端使用其默认值。
|
||||
- 权限模式与工作类型匹配。非交互会话无法点击原生权限提示,因此大量写入/exec 的编码运行通常需要一个可以无头继续执行的 ACPX 权限配置文件。
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
默认情况下,OpenClaw 插件工具和内置 OpenClaw 工具**不会**暴露给 ACP harnesses。只有在 harness 应该直接调用这些工具时,才在[ACP 智能体 — 设置](/zh-CN/tools/acp-agents-setup)中启用显式 MCP 桥接。
|
||||
默认情况下,OpenClaw 插件工具和内置 OpenClaw 工具**不会**
|
||||
暴露给 ACP harness。只有在 harness
|
||||
确实应直接调用这些工具时,才在
|
||||
[ACP 智能体 — 设置](/zh-CN/tools/acp-agents-setup) 中启用显式 MCP 桥接。
|
||||
|
||||
## 支持的 harness 目标
|
||||
|
||||
使用内置 `acpx` 后端时,可以将这些 harness id 用作 `/acp spawn <id>` 或 `sessions_spawn({ runtime: "acp", agentId: "<id>" })` 的目标:
|
||||
使用内置 `acpx` 后端时,可将这些 harness id 用作 `/acp spawn <id>`
|
||||
或 `sessions_spawn({ runtime: "acp", agentId: "<id>" })` 的目标:
|
||||
|
||||
| Harness id | 典型后端 | 说明 |
|
||||
| ---------- | ---------------------------------------------- | ----------------------------------------------------------------------------------- |
|
||||
| `claude` | Claude Code ACP 适配器 | 需要主机上已有 Claude Code 认证。 |
|
||||
| `codex` | Codex ACP 适配器 | 仅当原生 `/codex` 不可用或明确请求 ACP 时,才作为显式 ACP 回退。 |
|
||||
| `codex` | Codex ACP 适配器 | 仅在原生 `/codex` 不可用或明确要求 ACP 时,作为显式 ACP 回退。 |
|
||||
| `copilot` | GitHub Copilot ACP 适配器 | 需要 Copilot CLI/运行时认证。 |
|
||||
| `cursor` | Cursor CLI ACP(`cursor-agent acp`) | 如果本地安装暴露的是不同的 ACP 入口点,请覆盖 acpx 命令。 |
|
||||
| `droid` | Factory Droid CLI | 需要 Factory/Droid 认证,或在 harness 环境中设置 `FACTORY_API_KEY`。 |
|
||||
| `gemini` | Gemini CLI ACP 适配器 | 需要 Gemini CLI 认证或 API key 设置。 |
|
||||
| `gemini` | Gemini CLI ACP 适配器 | 需要 Gemini CLI 认证或 API 密钥设置。 |
|
||||
| `iflow` | iFlow CLI | 适配器可用性和模型控制取决于已安装的 CLI。 |
|
||||
| `kilocode` | Kilo Code CLI | 适配器可用性和模型控制取决于已安装的 CLI。 |
|
||||
| `kimi` | Kimi/Moonshot CLI | 需要主机上已有 Kimi/Moonshot 认证。 |
|
||||
| `kiro` | Kiro CLI | 适配器可用性和模型控制取决于已安装的 CLI。 |
|
||||
| `opencode` | OpenCode ACP 适配器 | 需要 OpenCode CLI/provider 认证。 |
|
||||
| `openclaw` | 通过 `openclaw acp` 的 OpenClaw Gateway 网关桥接 | 让支持 ACP 的 harness 反向连接到一个 OpenClaw Gateway 网关会话。 |
|
||||
| `pi` | Pi/嵌入式 OpenClaw 运行时 | 用于 OpenClaw 原生 harness 实验。 |
|
||||
| `qwen` | Qwen Code / Qwen CLI | 需要主机上有兼容 Qwen 的认证。 |
|
||||
| `openclaw` | 通过 `openclaw acp` 实现的 OpenClaw Gateway 网关桥接 | 允许一个支持 ACP 的 harness 反向连接到一个 OpenClaw Gateway 网关会话。 |
|
||||
| `pi` | Pi/内嵌 OpenClaw 运行时 | 用于 OpenClaw 原生 harness 实验。 |
|
||||
| `qwen` | Qwen Code / Qwen CLI | 需要主机上兼容 Qwen 的认证。 |
|
||||
|
||||
自定义 acpx 智能体别名可以在 acpx 本身中配置,但 OpenClaw 策略仍会在分发前检查 `acp.allowedAgents` 以及任何 `agents.list[].runtime.acp.agent` 映射。
|
||||
可以在 acpx 自身中配置自定义 acpx 智能体别名,但 OpenClaw
|
||||
策略仍然会检查 `acp.allowedAgents`,以及
|
||||
任何 `agents.list[].runtime.acp.agent` 映射,然后才进行分发。
|
||||
|
||||
## 操作手册
|
||||
|
||||
从聊天中快速执行 `/acp` 流程:
|
||||
在聊天中使用 `/acp` 的快速流程:
|
||||
|
||||
<Steps>
|
||||
<Step title="启动">
|
||||
@ -103,19 +124,19 @@ x-i18n:
|
||||
`/acp spawn codex --bind here`。
|
||||
</Step>
|
||||
<Step title="工作">
|
||||
在已绑定的对话或线程中继续,或者显式指定该会话
|
||||
key。
|
||||
在已绑定的会话或线程中继续(或者显式指定会话
|
||||
键)。
|
||||
</Step>
|
||||
<Step title="检查状态">
|
||||
`/acp status`
|
||||
</Step>
|
||||
<Step title="调优">
|
||||
<Step title="调整">
|
||||
`/acp model <provider/model>`、
|
||||
`/acp permissions <profile>`、
|
||||
`/acp timeout <seconds>`。
|
||||
</Step>
|
||||
<Step title="引导">
|
||||
不替换上下文:`/acp steer 收紧日志记录并继续`。
|
||||
在不替换上下文的情况下:`/acp steer tighten logging and continue`。
|
||||
</Step>
|
||||
<Step title="停止">
|
||||
`/acp cancel`(当前轮次)或 `/acp close`(会话 + 绑定)。
|
||||
@ -124,116 +145,139 @@ x-i18n:
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="生命周期细节">
|
||||
- 启动会创建或恢复一个 ACP 运行时会话,在 OpenClaw 会话存储中记录 ACP 元数据,并且当运行由父级拥有时,可能会创建一个后台任务。
|
||||
- 绑定后的后续消息会直接发送到 ACP 会话,直到绑定被关闭、失焦、重置或过期。
|
||||
- Gateway 网关命令保持在本地执行。`/acp ...`、`/status` 和 `/unfocus` 绝不会作为普通提示文本发送给已绑定的 ACP harness。
|
||||
- 启动会创建或恢复一个 ACP 运行时会话,在 OpenClaw 会话存储中记录 ACP 元数据,并且在该运行由父级拥有时可能会创建一个后台任务。
|
||||
- 绑定后的后续消息会直接发送到 ACP 会话,直到绑定被关闭、取消聚焦、重置或过期。
|
||||
- Gateway 网关命令会保留在本地。`/acp ...`、`/status` 和 `/unfocus` 永远不会作为普通提示文本发送给已绑定的 ACP harness。
|
||||
- `cancel` 会在后端支持取消时中止当前轮次;它不会删除绑定或会话元数据。
|
||||
- `close` 会从 OpenClaw 的视角结束 ACP 会话并移除绑定。如果 harness 支持恢复,它仍可能保留自己的上游历史记录。
|
||||
- 空闲运行时工作进程在 `acp.runtime.ttlMinutes` 后可被清理;已存储的会话元数据仍可通过 `/acp sessions` 使用。
|
||||
- `close` 会从 OpenClaw 的视角结束 ACP 会话并移除绑定。如果 harness 支持恢复,它仍可能保留自己的上游历史。
|
||||
- 空闲运行时工作进程会在 `acp.runtime.ttlMinutes` 之后进入可清理状态;已存储的会话元数据仍可通过 `/acp sessions` 查看。
|
||||
</Accordion>
|
||||
<Accordion title="原生 Codex 路由规则">
|
||||
当启用了**原生 Codex 插件**时,应路由到它的自然语言触发词:
|
||||
当原生 Codex
|
||||
插件已启用时,应路由到**原生 Codex 插件**的自然语言触发词:
|
||||
|
||||
- “将这个 Discord 渠道绑定到 Codex。”
|
||||
- “把这个 Discord 频道绑定到 Codex。”
|
||||
- “把这个聊天附加到 Codex 线程 `<id>`。”
|
||||
- “显示 Codex 线程,然后绑定当前这个。”
|
||||
- “显示 Codex 线程,然后绑定这个。”
|
||||
|
||||
原生 Codex 对话绑定是默认的聊天控制路径。
|
||||
OpenClaw 动态工具仍然通过 OpenClaw 执行,而
|
||||
Codex 原生工具(例如 shell/apply-patch)则在 Codex 内部执行。
|
||||
对于 Codex 原生工具事件,OpenClaw 会在每一轮注入一个原生
|
||||
hook 中继,因此插件钩子可以阻止 `before_tool_call`、观察
|
||||
`after_tool_call`,并通过 OpenClaw 审批流程路由 Codex 的 `PermissionRequest` 事件。Codex 的 `Stop` 钩子会被中继到
|
||||
OpenClaw 的 `before_agent_finalize`,在这里插件可以在 Codex 最终生成答案之前请求再进行一次
|
||||
模型调用。该中继刻意保持保守:它不会修改 Codex 原生工具
|
||||
参数,也不会重写 Codex 线程记录。只有当你想使用 ACP 运行时/会话模型时,才使用显式 ACP。嵌入式 Codex
|
||||
支持边界记录在
|
||||
[Codex harness v1 支持契约](/zh-CN/plugins/codex-harness#v1-support-contract)中。
|
||||
原生 Codex 会话绑定是默认的聊天控制路径。
|
||||
OpenClaw 动态工具仍通过 OpenClaw 执行,而
|
||||
Codex 原生工具(如 shell/apply-patch)则在 Codex 内执行。
|
||||
对于 Codex 原生工具事件,OpenClaw 会按轮次注入一个原生
|
||||
hook 中继,使插件钩子能够阻止 `before_tool_call`、观察
|
||||
`after_tool_call`,并将 Codex `PermissionRequest` 事件
|
||||
通过 OpenClaw 审批进行路由。Codex `Stop` 钩子会被中继到
|
||||
OpenClaw `before_agent_finalize`,插件可在其中请求模型在 Codex 最终输出答案前
|
||||
再进行一次传递。该中继保持刻意保守:
|
||||
它不会修改 Codex 原生工具参数,也不会重写 Codex 线程记录。只有当你想使用 ACP 运行时/会话模型时,
|
||||
才应使用显式 ACP。内嵌 Codex
|
||||
支持边界记录于
|
||||
[Codex harness v1 支持契约](/zh-CN/plugins/codex-harness#v1-support-contract)。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="模型 / provider / 运行时选择速查表">
|
||||
- `openai-codex/*` — PI Codex OAuth/订阅路径。
|
||||
- `openai/*` 加 `embeddedHarness.runtime: "codex"` — 原生 Codex app-server 嵌入式运行时。
|
||||
- `/codex ...` — 原生 Codex 对话控制。
|
||||
- `openai/*` 加 `agentRuntime.id: "codex"` — 原生 Codex 应用服务器内嵌运行时。
|
||||
- `/codex ...` — 原生 Codex 会话控制。
|
||||
- `/acp ...` 或 `runtime: "acp"` — 显式 ACP/acpx 控制。
|
||||
</Accordion>
|
||||
<Accordion title="ACP 路由自然语言触发词">
|
||||
应该路由到 ACP 运行时的触发词:
|
||||
<Accordion title="ACP 路由的自然语言触发词">
|
||||
应路由到 ACP 运行时的触发词:
|
||||
|
||||
- “把这个任务作为一次性 Claude Code ACP 会话运行,并总结结果。”
|
||||
- “这个任务使用 Gemini CLI 在线程中运行,然后把后续内容保持在同一个线程里。”
|
||||
- “对此任务使用 Gemini CLI 在线程中运行,然后将后续内容继续保留在同一个线程中。”
|
||||
- “通过 ACP 在线程后台运行 Codex。”
|
||||
|
||||
OpenClaw 会选择 `runtime: "acp"`,解析 harness `agentId`,在支持时绑定到当前对话或线程,并将后续消息路由到该会话,直到关闭或过期。只有在显式指定 ACP/acpx,或者原生 Codex 插件无法满足所请求的操作时,Codex 才会走这条路径。
|
||||
OpenClaw 会选择 `runtime: "acp"`,解析 harness `agentId`,
|
||||
在支持时绑定到当前会话或线程,并且
|
||||
将后续消息路由到该会话,直到关闭/过期。只有在显式要求 ACP/acpx
|
||||
或原生 Codex 插件对所请求操作不可用时,Codex 才会走这条路径。
|
||||
|
||||
对于 `sessions_spawn`,只有当 ACP 已启用、请求方未被沙箱隔离,并且已加载 ACP 运行时后端时,才会公布 `runtime: "acp"`。它面向 `codex`、`claude`、`droid`、`gemini` 或 `opencode` 等 ACP harness id。不要传入来自 `agents_list` 的普通 OpenClaw 配置智能体 id,除非该条目已显式配置 `agents.list[].runtime.type="acp"`;否则请使用默认子智能体运行时。当某个 OpenClaw 智能体配置了 `runtime.type="acp"` 时,OpenClaw 会使用 `runtime.acp.agent` 作为底层 harness id。
|
||||
对于 `sessions_spawn`,只有在 ACP
|
||||
已启用、请求方未被沙箱隔离,且 ACP 运行时
|
||||
后端已加载时,才会公布 `runtime: "acp"`。
|
||||
它面向 `codex`、
|
||||
`claude`、`droid`、`gemini` 或 `opencode` 这类 ACP harness id。不要传入来自
|
||||
`agents_list` 的普通 OpenClaw 配置智能体 id,除非该条目
|
||||
明确配置了 `agents.list[].runtime.type="acp"`;
|
||||
否则请使用默认的子智能体运行时。当某个 OpenClaw 智能体
|
||||
配置了 `runtime.type="acp"` 时,OpenClaw 会使用
|
||||
`runtime.acp.agent` 作为底层 harness id。
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## ACP 与子智能体的区别
|
||||
|
||||
当你想使用外部 harness 运行时时,请使用 ACP。当启用了 `codex` 插件并且你想进行 Codex 对话绑定/控制时,请使用**原生 Codex app-server**。当你想要 OpenClaw 原生委派执行时,请使用**子智能体**。
|
||||
当你需要外部 harness 运行时时,请使用 ACP。当 `codex`
|
||||
插件已启用,并且你需要 Codex 会话绑定/控制时,请使用**原生 Codex
|
||||
应用服务器**。当你需要 OpenClaw 原生的
|
||||
委派运行时,请使用**子智能体**。
|
||||
|
||||
| 区域 | ACP 会话 | 子智能体运行 |
|
||||
| ------------- | ------------------------------------- | ---------------------------------- |
|
||||
| 运行时 | ACP 后端插件(例如 acpx) | OpenClaw 原生子智能体运行时 |
|
||||
| 会话 key | `agent:<agentId>:acp:<uuid>` | `agent:<agentId>:subagent:<uuid>` |
|
||||
| 主要命令 | `/acp ...` | `/subagents ...` |
|
||||
| 会话键 | `agent:<agentId>:acp:<uuid>` | `agent:<agentId>:subagent:<uuid>` |
|
||||
| 主命令 | `/acp ...` | `/subagents ...` |
|
||||
| 启动工具 | `sessions_spawn` 配合 `runtime:"acp"` | `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 控制、会话恢复、后台任务跟踪以及可选的对话/线程绑定。
|
||||
ACP Claude 是一个**harness 会话**,具备 ACP 控制、会话恢复、
|
||||
后台任务跟踪,以及可选的会话/线程绑定。
|
||||
|
||||
CLI 后端是独立的纯文本本地回退运行时——参见
|
||||
CLI 后端则是独立的纯文本本地回退运行时——参见
|
||||
[CLI Backends](/zh-CN/gateway/cli-backends)。
|
||||
|
||||
对于操作人员,实际规则是:
|
||||
对于操作员来说,实际规则是:
|
||||
|
||||
- **想要 `/acp spawn`、可绑定会话、运行时控制或持久化 harness 工作?** 使用 ACP。
|
||||
- **想通过原始 CLI 获得简单的本地文本回退?** 使用 CLI 后端。
|
||||
- **想要 `/acp spawn`、可绑定会话、运行时控制,或持久化 harness 工作?** 用 ACP。
|
||||
- **想要通过原始 CLI 实现简单的本地文本回退?** 用 CLI 后端。
|
||||
|
||||
## 绑定会话
|
||||
|
||||
### 心智模型
|
||||
|
||||
- **聊天界面**——人们持续对话的地方(Discord 渠道、Telegram 话题、iMessage 聊天)。
|
||||
- **ACP 会话**——OpenClaw 路由到的持久 Codex/Claude/Gemini 运行时状态。
|
||||
- **子线程/话题**——仅在使用 `--thread ...` 时创建的可选附加消息界面。
|
||||
- **运行时工作区**——harness 运行所在的文件系统位置(`cwd`、仓库检出目录、后端工作区)。它独立于聊天界面。
|
||||
- **聊天界面**——人们持续交流的地方(Discord 频道、Telegram 话题、iMessage 聊天)。
|
||||
- **ACP 会话**——OpenClaw 路由到的持久化 Codex/Claude/Gemini 运行时状态。
|
||||
- **子线程/话题**——仅在使用 `--thread ...` 时创建的可选额外消息界面。
|
||||
- **运行时工作区**——harness 运行所在的文件系统位置(`cwd`、仓库检出、后端工作区)。它独立于聊天界面。
|
||||
|
||||
### 当前对话绑定
|
||||
### 当前会话绑定
|
||||
|
||||
`/acp spawn <harness> --bind here` 会将当前对话固定到新启动的 ACP 会话——不创建子线程,使用相同聊天界面。OpenClaw 继续负责传输、认证、安全和结果投递。该对话中的后续消息会路由到同一个会话;`/new` 和 `/reset` 会就地重置该会话;`/acp close` 会移除绑定。
|
||||
`/acp spawn <harness> --bind here` 会将当前会话固定绑定到
|
||||
已启动的 ACP 会话——不创建子线程,使用同一个聊天界面。OpenClaw 继续
|
||||
负责传输、认证、安全性和投递。该会话中的后续消息会路由到同一个
|
||||
会话;`/new` 和 `/reset` 会原地重置该
|
||||
会话;`/acp close` 会移除绑定。
|
||||
|
||||
示例:
|
||||
|
||||
```text
|
||||
/codex bind # 原生 Codex 绑定,将未来消息路由到这里
|
||||
/codex bind # 原生 Codex 绑定,后续消息路由到这里
|
||||
/codex model gpt-5.4 # 调整已绑定的原生 Codex 线程
|
||||
/codex stop # 控制当前活跃的原生 Codex 轮次
|
||||
/acp spawn codex --bind here # 为 Codex 显式使用 ACP 回退
|
||||
/acp spawn codex --thread auto # 可能创建一个子线程/话题并绑定到那里
|
||||
/codex stop # 控制当前活动的原生 Codex 轮次
|
||||
/acp spawn codex --bind here # 针对 Codex 的显式 ACP 回退
|
||||
/acp spawn codex --thread auto # 可能会创建一个子线程/话题并绑定到那里
|
||||
/acp spawn codex --bind here --cwd /workspace/repo # 相同聊天绑定,Codex 在 /workspace/repo 中运行
|
||||
```
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="绑定规则与互斥关系">
|
||||
<Accordion title="绑定规则与排他性">
|
||||
- `--bind here` 和 `--thread ...` 互斥。
|
||||
- `--bind here` 仅适用于声明支持当前对话绑定的渠道;否则 OpenClaw 会返回明确的不支持消息。绑定会在 Gateway 网关重启后继续保留。
|
||||
- 在 Discord 上,只有当 OpenClaw 需要为 `--thread auto|here` 创建子线程时,才需要 `spawnAcpSessions`——`--bind here` 不需要。
|
||||
- 如果你启动到不同的 ACP 智能体但未指定 `--cwd`,OpenClaw 默认会继承**目标智能体的**工作区。继承路径缺失(`ENOENT`/`ENOTDIR`)时会回退到后端默认值;其他访问错误(例如 `EACCES`)会作为启动错误暴露出来。
|
||||
- 在已绑定的对话中,Gateway 网关管理命令会保持本地执行——即使普通后续文本会路由到已绑定的 ACP 会话,`/acp ...` 命令仍由 OpenClaw 处理;只要该界面启用了命令处理,`/status` 和 `/unfocus` 也始终在本地执行。
|
||||
- `--bind here` 仅适用于声明支持当前会话绑定的渠道;否则 OpenClaw 会返回明确的不支持消息。绑定会在 Gateway 网关重启后继续保留。
|
||||
- 在 Discord 上,只有当 OpenClaw 需要为 `--thread auto|here` 创建子线程时,才需要 `spawnAcpSessions`——对于 `--bind here` 则不需要。
|
||||
- 如果你在未指定 `--cwd` 的情况下启动到另一个 ACP 智能体,OpenClaw 默认会继承**目标智能体的**工作区。缺失的继承路径(`ENOENT`/`ENOTDIR`)会回退到后端默认值;其他访问错误(例如 `EACCES`)会作为启动错误直接显示。
|
||||
- Gateway 网关管理命令会保留在绑定会话本地——即使普通后续文本会被路由到已绑定的 ACP 会话,`/acp ...` 命令仍由 OpenClaw 处理;只要该界面启用了命令处理,`/status` 和 `/unfocus` 也始终保留在本地。
|
||||
</Accordion>
|
||||
<Accordion title="线程绑定会话">
|
||||
当某个渠道适配器启用了线程绑定时:
|
||||
@ -241,43 +285,44 @@ CLI 后端是独立的纯文本本地回退运行时——参见
|
||||
- OpenClaw 会将一个线程绑定到目标 ACP 会话。
|
||||
- 该线程中的后续消息会路由到已绑定的 ACP 会话。
|
||||
- ACP 输出会投递回同一个线程。
|
||||
- 失焦/关闭/归档/空闲超时或最大存活时间到期都会移除该绑定。
|
||||
- `/acp close`、`/acp cancel`、`/acp status`、`/status` 和 `/unfocus` 是 Gateway 网关命令,而不是发给 ACP harness 的提示词。
|
||||
- 取消聚焦/关闭/归档/空闲超时或最大存活期到期都会移除绑定。
|
||||
- `/acp close`、`/acp cancel`、`/acp status`、`/status` 和 `/unfocus` 是 Gateway 网关命令,不是发给 ACP harness 的提示。
|
||||
|
||||
线程绑定 ACP 所需的功能开关:
|
||||
线程绑定 ACP 所需的功能标志:
|
||||
|
||||
- `acp.enabled=true`
|
||||
- `acp.dispatch.enabled` 默认开启(设为 `false` 可暂停 ACP 分发)。
|
||||
- 已启用渠道适配器的 ACP 线程启动开关(适配器特定):
|
||||
- 渠道适配器 ACP 线程启动标志已启用(依适配器而定):
|
||||
- Discord:`channels.discord.threadBindings.spawnAcpSessions=true`
|
||||
- Telegram:`channels.telegram.threadBindings.spawnAcpSessions=true`
|
||||
|
||||
线程绑定支持取决于适配器。如果当前渠道
|
||||
线程绑定支持因适配器而异。如果当前渠道
|
||||
适配器不支持线程绑定,OpenClaw 会返回明确的
|
||||
不支持/不可用消息。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="支持线程的渠道">
|
||||
- 任何暴露会话/线程绑定能力的渠道适配器。
|
||||
- 当前内置支持:**Discord** 线程/渠道、**Telegram** 话题(群组/超级群组中的 forum topics 和私信话题)。
|
||||
- 当前内置支持:**Discord** 线程/频道、**Telegram** 话题(群组/超级群组中的论坛话题以及私信话题)。
|
||||
- 插件渠道也可以通过相同的绑定接口添加支持。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 持久化渠道绑定
|
||||
|
||||
对于非临时工作流,可在顶层 `bindings[]` 条目中配置持久化 ACP 绑定。
|
||||
对于非临时工作流,请在
|
||||
顶层 `bindings[]` 条目中配置持久化 ACP 绑定。
|
||||
|
||||
### 绑定模型
|
||||
|
||||
<ParamField path="bindings[].type" type='"acp"'>
|
||||
标记一个持久化 ACP 对话绑定。
|
||||
标记一个持久化 ACP 会话绑定。
|
||||
</ParamField>
|
||||
<ParamField path="bindings[].match" type="object">
|
||||
标识目标对话。不同渠道的格式如下:
|
||||
标识目标会话。各渠道的结构如下:
|
||||
|
||||
- **Discord 渠道/线程:** `match.channel="discord"` + `match.peer.id="<channelOrThreadId>"`
|
||||
- **Telegram forum topic:** `match.channel="telegram"` + `match.peer.id="<chatId>:topic:<topicId>"`
|
||||
- **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:*>"`。对于稳定的群组绑定,优先使用 `chat_id:*` 或 `chat_identifier:*`。
|
||||
- **iMessage 私信/群组:** `match.channel="imessage"` + `match.peer.id="<handle|chat_id:*|chat_guid:*|chat_identifier:*>"`。对于稳定的群组绑定,优先使用 `chat_id:*`。
|
||||
</ParamField>
|
||||
@ -285,7 +330,7 @@ CLI 后端是独立的纯文本本地回退运行时——参见
|
||||
所属的 OpenClaw 智能体 id。
|
||||
</ParamField>
|
||||
<ParamField path="bindings[].acp.mode" type='"persistent" | "oneshot"'>
|
||||
可选的 ACP 覆盖项。
|
||||
可选的 ACP 覆盖值。
|
||||
</ParamField>
|
||||
<ParamField path="bindings[].acp.label" type="string">
|
||||
可选的面向操作员标签。
|
||||
@ -294,7 +339,7 @@ CLI 后端是独立的纯文本本地回退运行时——参见
|
||||
可选的运行时工作目录。
|
||||
</ParamField>
|
||||
<ParamField path="bindings[].acp.backend" type="string">
|
||||
可选的后端覆盖项。
|
||||
可选的后端覆盖值。
|
||||
</ParamField>
|
||||
|
||||
### 每个智能体的运行时默认值
|
||||
@ -395,21 +440,21 @@ CLI 后端是独立的纯文本本地回退运行时——参见
|
||||
|
||||
### 行为
|
||||
|
||||
- OpenClaw 会在使用前确保已存在配置好的 ACP 会话。
|
||||
- 该渠道或话题中的消息会路由到配置的 ACP 会话。
|
||||
- 在已绑定的对话中,`/new` 和 `/reset` 会就地重置同一个 ACP 会话 key。
|
||||
- 临时运行时绑定(例如由线程聚焦流程创建的绑定)在存在时仍然适用。
|
||||
- 对于跨智能体的 ACP 启动,如果未显式指定 `cwd`,OpenClaw 会从智能体配置中继承目标智能体的工作区。
|
||||
- 缺失的继承工作区路径会回退到后端默认 `cwd`;非缺失类访问失败会作为启动错误暴露出来。
|
||||
- OpenClaw 会在使用前确保已配置的 ACP 会话存在。
|
||||
- 该频道或话题中的消息会被路由到已配置的 ACP 会话。
|
||||
- 在已绑定的会话中,`/new` 和 `/reset` 会原地重置同一个 ACP 会话键。
|
||||
- 临时运行时绑定(例如由线程聚焦流程创建的绑定)在存在时仍然会生效。
|
||||
- 对于跨智能体 ACP 启动,如果未显式指定 `cwd`,OpenClaw 会从智能体配置中继承目标智能体工作区。
|
||||
- 缺失的继承工作区路径会回退到后端默认 `cwd`;非缺失型访问失败会作为启动错误直接显示。
|
||||
|
||||
## 启动 ACP 会话
|
||||
|
||||
启动 ACP 会话有两种方式:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="从 sessions_spawn">
|
||||
<Tab title="来自 sessions_spawn">
|
||||
使用 `runtime: "acp"` 从智能体轮次或
|
||||
工具调用中启动 ACP 会话。
|
||||
工具调用中启动一个 ACP 会话。
|
||||
|
||||
```json
|
||||
{
|
||||
@ -422,14 +467,15 @@ CLI 后端是独立的纯文本本地回退运行时——参见
|
||||
```
|
||||
|
||||
<Note>
|
||||
`runtime` 默认为 `subagent`,因此对于 ACP 会话请显式设置 `runtime: "acp"`。如果省略 `agentId`,OpenClaw 会在已配置时使用
|
||||
`runtime` 默认为 `subagent`,因此对于 ACP 会话需要显式设置 `runtime: "acp"`。
|
||||
如果省略 `agentId`,OpenClaw 会在已配置时使用
|
||||
`acp.defaultAgent`。`mode: "session"` 需要
|
||||
`thread: true` 才能保持持久化的绑定对话。
|
||||
`thread: true` 才能保持一个持久化的绑定会话。
|
||||
</Note>
|
||||
|
||||
</Tab>
|
||||
<Tab title="从 /acp 命令">
|
||||
使用 `/acp spawn` 从聊天中进行显式操作员控制。
|
||||
<Tab title="来自 /acp 命令">
|
||||
使用 `/acp spawn` 从聊天中进行显式的操作员控制。
|
||||
|
||||
```text
|
||||
/acp spawn codex --mode persistent --thread auto
|
||||
@ -446,7 +492,7 @@ CLI 后端是独立的纯文本本地回退运行时——参见
|
||||
- `--cwd <absolute-path>`
|
||||
- `--label <name>`
|
||||
|
||||
参见[Slash commands](/zh-CN/tools/slash-commands)。
|
||||
参见 [Slash commands](/zh-CN/tools/slash-commands)。
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
@ -460,7 +506,7 @@ CLI 后端是独立的纯文本本地回退运行时——参见
|
||||
对于 ACP 会话,必须为 `"acp"`。
|
||||
</ParamField>
|
||||
<ParamField path="agentId" type="string">
|
||||
ACP 目标 harness id。如果设置了 `acp.defaultAgent`,则回退到它。
|
||||
ACP 目标 harness id。如果已设置,则会回退到 `acp.defaultAgent`。
|
||||
</ParamField>
|
||||
<ParamField path="thread" type="boolean" default="false">
|
||||
在支持时请求线程绑定流程。
|
||||
@ -472,67 +518,67 @@ CLI 后端是独立的纯文本本地回退运行时——参见
|
||||
</ParamField>
|
||||
<ParamField path="cwd" type="string">
|
||||
请求的运行时工作目录(由后端/运行时
|
||||
策略验证)。如果省略,ACP 启动会在已配置时继承目标智能体的工作区;
|
||||
策略验证)。如果省略,ACP 启动会在已配置时继承目标智能体工作区;
|
||||
缺失的继承路径会回退到后端
|
||||
默认值,而实际访问错误会被返回。
|
||||
默认值,而真实访问错误会直接返回。
|
||||
</ParamField>
|
||||
<ParamField path="label" type="string">
|
||||
用于会话/横幅文本中的面向操作员标签。
|
||||
在会话/横幅文本中使用的面向操作员标签。
|
||||
</ParamField>
|
||||
<ParamField path="resumeSessionId" type="string">
|
||||
恢复现有 ACP 会话,而不是创建新会话。该
|
||||
智能体会通过 `session/load` 重放其对话历史。需要
|
||||
`runtime: "acp"`。
|
||||
恢复现有 ACP 会话,而不是创建一个新会话。
|
||||
智能体会通过 `session/load` 重放其会话历史。
|
||||
需要 `runtime: "acp"`。
|
||||
</ParamField>
|
||||
<ParamField path="streamTo" type='"parent"'>
|
||||
`"parent"` 会将初始 ACP 运行的进度摘要以系统事件形式流式回传到
|
||||
请求方会话。接受的响应包括
|
||||
指向会话范围 JSONL 日志的 `streamLogPath`
|
||||
(`<sessionId>.acp-stream.jsonl`),你可以 tail 它以查看完整的中继历史。
|
||||
`"parent"` 会将初始 ACP 运行的进度摘要以系统事件形式流式返回到
|
||||
请求方会话。接受的响应中可能包含
|
||||
指向会话范围 JSONL 日志
|
||||
(`<sessionId>.acp-stream.jsonl`)的 `streamLogPath`,你可以跟踪它以查看完整中继历史。
|
||||
</ParamField>
|
||||
<ParamField path="runTimeoutSeconds" type="number">
|
||||
在 N 秒后中止 ACP 子轮次。`0` 会让该轮次走
|
||||
Gateway 网关的无超时路径。相同的值会同时应用于 Gateway 网关
|
||||
运行和 ACP 运行时,这样卡住或额度耗尽的 harnesses 就不会
|
||||
Gateway 网关的无超时路径。相同的值会同时应用到 Gateway 网关
|
||||
运行和 ACP 运行时,这样卡住/配额耗尽的 harness 就不会
|
||||
无限期占用父智能体通道。
|
||||
</ParamField>
|
||||
<ParamField path="model" type="string">
|
||||
对 ACP 子会话的显式模型覆盖。Codex ACP 启动
|
||||
会在 `session/new` 之前将 OpenClaw Codex 引用(例如 `openai-codex/gpt-5.4`)规范化为 Codex
|
||||
ACP 启动配置;斜杠形式,例如
|
||||
`openai-codex/gpt-5.4/high`,也会设置 Codex ACP 推理强度。
|
||||
其他 harnesses 必须声明 ACP `models` 并支持
|
||||
对 ACP 子会话的显式模型覆盖。Codex ACP 启动会在
|
||||
`session/new` 之前,将 OpenClaw Codex 引用(例如 `openai-codex/gpt-5.4`)标准化为 Codex
|
||||
ACP 启动配置;使用斜杠形式(例如
|
||||
`openai-codex/gpt-5.4/high`)还会设置 Codex ACP 的推理强度。
|
||||
其他 harness 必须声明 ACP `models` 并支持
|
||||
`session/set_model`;否则 OpenClaw/acpx 会明确失败,而不是
|
||||
静默回退到目标智能体默认值。
|
||||
</ParamField>
|
||||
<ParamField path="thinking" type="string">
|
||||
显式思考/推理强度。对于 Codex ACP,`minimal` 映射为
|
||||
显式的 thinking/推理强度。对于 Codex ACP,`minimal` 映射为
|
||||
低强度,`low`/`medium`/`high`/`xhigh` 直接映射,而 `off`
|
||||
会省略推理强度启动覆盖。
|
||||
则省略推理强度启动覆盖。
|
||||
</ParamField>
|
||||
|
||||
## 启动绑定和线程模式
|
||||
## 启动绑定与线程模式
|
||||
|
||||
<Tabs>
|
||||
<Tab title="--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` 调用中同时使用。
|
||||
|
||||
</Tab>
|
||||
<Tab title="--thread auto|here|off">
|
||||
| 模式 | 行为 |
|
||||
| ------ | --------------------------------------------------------------------------------------------------- |
|
||||
| `auto` | 在当前活跃线程中:绑定该线程。在线程外:在支持时创建并绑定一个子线程。 |
|
||||
| `here` | 要求当前处于活跃线程中;否则失败。 |
|
||||
| `auto` | 在活动线程中:绑定该线程。在线程外:在支持时创建/绑定一个子线程。 |
|
||||
| `here` | 要求当前处于活动线程中;如果不在线程中则失败。 |
|
||||
| `off` | 不绑定。会话以未绑定状态启动。 |
|
||||
|
||||
说明:
|
||||
@ -541,7 +587,7 @@ CLI 后端是独立的纯文本本地回退运行时——参见
|
||||
- 线程绑定启动需要渠道策略支持:
|
||||
- Discord:`channels.discord.threadBindings.spawnAcpSessions=true`
|
||||
- Telegram:`channels.telegram.threadBindings.spawnAcpSessions=true`
|
||||
- 当你想固定当前对话且不创建子线程时,请使用 `--bind here`。
|
||||
- 如果你想固定当前会话而不创建子线程,请使用 `--bind here`。
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
@ -549,71 +595,71 @@ CLI 后端是独立的纯文本本地回退运行时——参见
|
||||
## 投递模型
|
||||
|
||||
ACP 会话既可以是交互式工作区,也可以是由父级拥有的
|
||||
后台工作。投递路径取决于这种形态。
|
||||
后台工作。投递路径取决于其形态。
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="交互式 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 输出会被投递回同一个
|
||||
频道/线程/话题。
|
||||
|
||||
OpenClaw 发送给 harness 的内容:
|
||||
|
||||
- 普通绑定后的后续消息会作为提示文本发送,附件仅在 harness/后端支持时附带发送。
|
||||
- `/acp` 管理命令和本地 Gateway 网关命令会在 ACP 分发前被拦截。
|
||||
- 运行时生成的完成事件会按目标具体展开。OpenClaw 智能体会收到 OpenClaw 的内部运行时上下文 envelope;外部 ACP harnesses 会收到包含子结果和指令的纯提示。原始 `<<<BEGIN_OPENCLAW_INTERNAL_CONTEXT>>>` envelope 绝不能发送给外部 harnesses,也不能作为 ACP 用户转录文本持久化。
|
||||
- ACP 转录条目使用用户可见的触发文本或纯完成提示。内部事件元数据会尽可能以结构化形式保留在 OpenClaw 中,不被视为用户编写的聊天内容。
|
||||
- 普通的绑定后续消息会作为提示文本发送,外加附件——但仅在 harness/后端支持它们时才会附带。
|
||||
- `/acp` 管理命令和本地 Gateway 网关命令会在 ACP 分发之前被拦截。
|
||||
- 运行时生成的完成事件会按目标具体化。OpenClaw 智能体会收到 OpenClaw 的内部 runtime-context 信封;外部 ACP harness 会收到一个普通提示,其中包含子结果和指令。原始 `<<<BEGIN_OPENCLAW_INTERNAL_CONTEXT>>>` 信封绝不应发送给外部 harness,也不应作为 ACP 用户转录文本持久化。
|
||||
- ACP 转录条目使用用户可见的触发文本或普通完成提示。在可能的情况下,内部事件元数据会在 OpenClaw 中保持结构化,不会被视为用户撰写的聊天内容。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="父级拥有的一次性 ACP 会话">
|
||||
由另一个智能体运行启动的一次性 ACP 会话是后台
|
||||
由另一个智能体运行所启动的一次性 ACP 会话是后台
|
||||
子级,类似于子智能体:
|
||||
|
||||
- 父级通过 `sessions_spawn({ runtime: "acp", mode: "run" })` 请求工作。
|
||||
- 子级在自己的 ACP harness 会话中运行。
|
||||
- 子级在它自己的 ACP harness 会话中运行。
|
||||
- 子级轮次运行在与原生子智能体启动相同的后台通道上,因此缓慢的 ACP harness 不会阻塞无关的主会话工作。
|
||||
- 完成结果会通过任务完成通知路径回传。OpenClaw 会在发送给外部 harness 之前,将内部完成元数据转换为纯 ACP 提示,因此 harnesses 看不到 OpenClaw 专用的运行时上下文标记。
|
||||
- 当需要面向用户的回复时,父级会用普通 assistant 语气重写子结果。
|
||||
- 完成会通过任务完成通知路径回传。OpenClaw 会在发送给外部 harness 之前,将内部完成元数据转换为普通 ACP 提示,因此 harness 不会看到 OpenClaw 专用的运行时上下文标记。
|
||||
- 当需要面向用户的回复时,父级会用正常助手口吻重写子级结果。
|
||||
|
||||
**不要**把这条路径当作父级
|
||||
和子级之间的点对点聊天。子级已经有一条返回父级的
|
||||
完成通道。
|
||||
**不要**将此路径视为父级
|
||||
与子级之间的点对点聊天。子级已经拥有一条回传给
|
||||
父级的完成通道。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="sessions_send 和 A2A 投递">
|
||||
`sessions_send` 可在启动后指向另一个会话。对于普通
|
||||
对等会话,OpenClaw 会在注入消息后使用智能体到智能体(A2A)的后续路径:
|
||||
<Accordion title="sessions_send 与 A2A 投递">
|
||||
`sessions_send` 可以在启动之后以另一个会话为目标。对于普通
|
||||
对等会话,OpenClaw 会在注入消息后使用一条智能体到智能体(A2A)跟进路径:
|
||||
|
||||
- 等待目标会话的回复。
|
||||
- 可选地让请求方和目标交换有限轮数的后续消息。
|
||||
- 可选地让请求方和目标交换有限数量的后续轮次。
|
||||
- 要求目标生成一条通知消息。
|
||||
- 将该通知投递到可见渠道或线程。
|
||||
- 将该通知投递到可见频道或线程。
|
||||
|
||||
该 A2A 路径是对等发送的一种回退方案,用于发送方需要
|
||||
可见后续消息的情况。当一个无关会话可以
|
||||
看见并向 ACP 目标发送消息时,它仍会保持启用,例如在宽泛的
|
||||
对于发送方需要一个
|
||||
可见跟进的对等发送场景,这条 A2A 路径是一种回退方案。当一个无关会话能够
|
||||
看到并向 ACP 目标发送消息时,它仍然会保持启用,例如在宽泛的
|
||||
`tools.sessions.visibility` 设置下。
|
||||
|
||||
只有当请求方是其自己父级拥有的一次性 ACP 子级的
|
||||
父级时,OpenClaw 才会跳过 A2A 后续流程。在这种情况下,
|
||||
如果在任务完成之上再运行 A2A,可能会用
|
||||
子级结果唤醒父级,将父级的回复再转发回子级,并
|
||||
造成父子回声循环。对于这种已拥有子级的情况,`sessions_send` 结果会报告
|
||||
只有当请求方是其自身父级拥有的一次性 ACP 子级的
|
||||
父级时,OpenClaw 才会跳过 A2A 跟进。在这种情况下,
|
||||
在任务完成之上再运行 A2A 可能会用
|
||||
子级结果唤醒父级,再把父级回复转发回子级,从而
|
||||
形成父子回声循环。对于这种已拥有子级的情况,`sessions_send` 结果会报告
|
||||
`delivery.status="skipped"`,
|
||||
因为完成路径已经负责结果处理。
|
||||
因为完成路径已经负责处理该结果。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="恢复现有会话">
|
||||
使用 `resumeSessionId` 继续之前的 ACP 会话,而不是
|
||||
重新开始。该智能体会通过
|
||||
`session/load` 重放其对话历史,因此它可以带着之前的完整上下文继续。
|
||||
使用 `resumeSessionId` 继续一个先前的 ACP 会话,而不是
|
||||
重新开始。智能体会通过
|
||||
`session/load` 重放其会话历史,因此它可以带着此前的完整上下文继续。
|
||||
|
||||
```json
|
||||
{
|
||||
@ -626,53 +672,53 @@ ACP 会话既可以是交互式工作区,也可以是由父级拥有的
|
||||
|
||||
常见使用场景:
|
||||
|
||||
- 将 Codex 会话从你的笔记本交接到手机——告诉你的智能体接着你上次的进度继续。
|
||||
- 继续你先前在 CLI 中交互式启动、现在想通过智能体无头继续的编码会话。
|
||||
- 继续处理因 Gateway 网关重启或空闲超时而中断的工作。
|
||||
- 将一个 Codex 会话从你的笔记本交接到手机——告诉你的智能体从你停下的地方继续。
|
||||
- 继续你之前在 CLI 中以交互方式开始、现在要通过智能体无头继续的编码会话。
|
||||
- 接续因 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,启动会以明确错误失败——不会静默回退到新会话。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="部署后冒烟测试">
|
||||
Gateway 网关部署后,请运行一次实时端到端检查,
|
||||
而不要只相信单元测试:
|
||||
在 Gateway 网关部署之后,请运行一次实时端到端检查,而不要
|
||||
只依赖单元测试:
|
||||
|
||||
1. 在目标主机上验证已部署的 Gateway 网关版本和提交。
|
||||
2. 打开一个临时 ACPX 桥接会话并连接到真实智能体。
|
||||
3. 要求该智能体调用 `sessions_spawn`,参数为 `runtime: "acp"`、`agentId: "codex"`、`mode: "run"`,任务为 `Reply with exactly LIVE-ACP-SPAWN-OK`。
|
||||
4. 验证 `accepted=yes`、存在真实的 `childSessionKey`,并且没有验证器错误。
|
||||
5. 清理临时桥接会话。
|
||||
2. 打开一个指向实时智能体的临时 ACPX 桥接会话。
|
||||
3. 要求该智能体调用 `sessions_spawn`,参数为 `runtime: "acp"`、`agentId: "codex"`、`mode: "run"`,任务内容为 `Reply with exactly LIVE-ACP-SPAWN-OK`。
|
||||
4. 验证 `accepted=yes`、存在真实的 `childSessionKey`,且没有验证器错误。
|
||||
5. 清理该临时桥接会话。
|
||||
|
||||
将检查门槛保持在 `mode: "run"`,并跳过 `streamTo: "parent"`——
|
||||
线程绑定的 `mode: "session"` 和流式中继路径属于
|
||||
独立且更丰富的集成验证步骤。
|
||||
请将关卡保持在 `mode: "run"`,并跳过 `streamTo: "parent"`——
|
||||
线程绑定的 `mode: "session"` 和流式中继路径属于另外的、
|
||||
更丰富的集成验证阶段。
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 沙箱兼容性
|
||||
|
||||
ACP 会话当前运行在主机运行时上,**不是**在
|
||||
OpenClaw 沙箱内部运行。
|
||||
ACP 会话目前运行在主机运行时上,**不在**
|
||||
OpenClaw 沙箱内部。
|
||||
|
||||
<Warning>
|
||||
**安全边界:**
|
||||
|
||||
- 外部 harness 可以根据其自身 CLI 权限和所选 `cwd` 进行读写。
|
||||
- OpenClaw 的沙箱策略**不会**包装 ACP harness 执行。
|
||||
- OpenClaw 仍会强制执行 ACP 功能开关、允许的智能体、会话所有权、渠道绑定和 Gateway 网关投递策略。
|
||||
- 对于受沙箱强制约束的 OpenClaw 原生工作,请使用 `runtime: "subagent"`。
|
||||
- OpenClaw 的沙箱策略**不会**包裹 ACP harness 执行。
|
||||
- OpenClaw 仍会强制执行 ACP 功能门控、允许的智能体、会话所有权、渠道绑定和 Gateway 网关投递策略。
|
||||
- 对于需要强制沙箱隔离的 OpenClaw 原生工作,请使用 `runtime: "subagent"`。
|
||||
</Warning>
|
||||
|
||||
当前限制:
|
||||
|
||||
- 如果请求方会话处于沙箱隔离状态,ACP 启动会同时对 `sessions_spawn({ runtime: "acp" })` 和 `/acp spawn` 被阻止。
|
||||
- 使用 `runtime: "acp"` 的 `sessions_spawn` 不支持 `sandbox: "require"`。
|
||||
- 如果请求方会话已被沙箱隔离,则 `sessions_spawn({ runtime: "acp" })` 和 `/acp spawn` 的 ACP 启动都会被阻止。
|
||||
- `sessions_spawn` 配合 `runtime: "acp"` 不支持 `sandbox: "require"`。
|
||||
|
||||
## 会话目标解析
|
||||
|
||||
@ -683,15 +729,15 @@ OpenClaw 沙箱内部运行。
|
||||
|
||||
1. 显式目标参数(或 `/acp steer` 的 `--session`)
|
||||
- 先尝试 key
|
||||
- 再尝试 UUID 形状的 session id
|
||||
- 然后尝试 label
|
||||
2. 当前线程绑定(如果这个对话/线程已绑定到 ACP 会话)。
|
||||
3. 当前请求方会话回退。
|
||||
- 然后尝试 UUID 形态的 session id
|
||||
- 再尝试 label
|
||||
2. 当前线程绑定(如果当前会话/线程已绑定到某个 ACP 会话)。
|
||||
3. 当前请求方会话回退值。
|
||||
|
||||
当前对话绑定和线程绑定都会参与
|
||||
当前会话绑定和线程绑定都会参与
|
||||
第 2 步。
|
||||
|
||||
如果无法解析任何目标,OpenClaw 会返回明确错误
|
||||
如果无法解析出目标,OpenClaw 会返回明确错误
|
||||
(`Unable to resolve session target: ...`)。
|
||||
|
||||
## ACP 控制
|
||||
@ -700,46 +746,47 @@ OpenClaw 沙箱内部运行。
|
||||
| -------------------- | --------------------------------------------------------- | ------------------------------------------------------------- |
|
||||
| `/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 steer` | 向正在运行的会话发送引导指令。 | `/acp steer --session support inbox prioritize failing tests` |
|
||||
| `/acp close` | 关闭会话并解除线程目标绑定。 | `/acp close` |
|
||||
| `/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 status` 会显示生效的运行时选项,以及运行时级别和
|
||||
后端级别的会话标识符。当后端缺少某项能力时,不支持控制的错误会被明确显示。`/acp sessions` 会为当前已绑定或请求方会话读取
|
||||
`/acp status` 会显示生效中的运行时选项,以及运行时级别和
|
||||
后端级别的会话标识符。当某个后端缺少某项能力时,不支持控制错误会被
|
||||
明确显示。`/acp sessions` 会读取当前绑定或请求方会话的
|
||||
存储;目标令牌
|
||||
(`session-key`、`session-id` 或 `session-label`)会通过
|
||||
Gateway 网关会话发现进行解析,包括自定义的每智能体 `session.store`
|
||||
Gateway 网关会话发现进行解析,其中包括自定义的按智能体划分的 `session.store`
|
||||
根目录。
|
||||
|
||||
### 运行时选项映射
|
||||
|
||||
`/acp` 提供便捷命令和通用设置器。等价
|
||||
`/acp` 提供便捷命令和一个通用设置器。等价
|
||||
操作如下:
|
||||
|
||||
| 命令 | 映射到 | 说明 |
|
||||
| ---------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `/acp model <id>` | 运行时配置键 `model` | 对于 Codex ACP,OpenClaw 会将 `openai-codex/<model>` 规范化为适配器模型 id,并将斜杠推理后缀(例如 `openai-codex/gpt-5.4/high`)映射为 `reasoning_effort`。 |
|
||||
| `/acp set thinking <level>` | 运行时配置键 `thinking` | 对于 Codex ACP,只要适配器支持,OpenClaw 就会发送对应的 `reasoning_effort`。 |
|
||||
| `/acp model <id>` | 运行时配置键 `model` | 对于 Codex ACP,OpenClaw 会将 `openai-codex/<model>` 标准化为适配器模型 id,并将斜杠推理后缀(例如 `openai-codex/gpt-5.4/high`)映射为 `reasoning_effort`。 |
|
||||
| `/acp set thinking <level>` | 运行时配置键 `thinking` | 对于 Codex ACP,在适配器支持时,OpenClaw 会发送相应的 `reasoning_effort`。 |
|
||||
| `/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` | 清除所有运行时覆盖 | — |
|
||||
| `/acp reset-options` | 清除所有运行时覆盖值 | — |
|
||||
|
||||
## acpx harness、插件设置和权限
|
||||
|
||||
关于 acpx harness 配置(Claude Code / Codex / Gemini CLI
|
||||
别名)、plugin-tools 和 OpenClaw-tools MCP 桥接,以及 ACP
|
||||
有关 acpx harness 配置(Claude Code / Codex / Gemini CLI
|
||||
别名)、插件工具和 OpenClaw 工具的 MCP 桥接,以及 ACP
|
||||
权限模式,请参见
|
||||
[ACP 智能体 — 设置](/zh-CN/tools/acp-agents-setup)。
|
||||
|
||||
@ -747,28 +794,28 @@ Gateway 网关会话发现进行解析,包括自定义的每智能体 `session
|
||||
|
||||
| 症状 | 可能原因 | 修复方法 |
|
||||
| --------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `ACP runtime backend is not configured` | 后端插件缺失、被禁用,或被 `plugins.allow` 阻止。 | 安装并启用后端插件;如果设置了该 allowlist,请将 `acpx` 加入 `plugins.allow`,然后运行 `/acp doctor`。 |
|
||||
| `ACP runtime backend is not configured` | 后端插件缺失、被禁用,或被 `plugins.allow` 阻止。 | 安装并启用后端插件;如果设置了 `plugins.allow` 允许列表,请将 `acpx` 包含进去,然后运行 `/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` | 智能体不在 allowlist 中。 | 使用被允许的 `agentId`,或更新 `acp.allowedAgents`。 |
|
||||
| `/acp doctor` 在启动后立即报告后端未就绪 | 插件依赖探测或自我修复仍在运行。 | 稍等片刻后重新运行 `/acp doctor`;如果仍然不健康,请检查后端安装错误以及插件 allow/deny 策略。 |
|
||||
| 找不到 harness 命令 | 适配器 CLI 未安装,或首次运行时 `npx` 获取失败。 | 在 Gateway 网关主机上安装/预热该适配器,或显式配置 acpx 智能体命令。 |
|
||||
| harness 返回 model-not-found | 该模型 id 对另一个 provider/harness 有效,但对当前 ACP 目标无效。 | 使用该 harness 列出的模型、在 harness 中配置该模型,或省略该覆盖。 |
|
||||
| harness 返回供应商认证错误 | OpenClaw 本身健康,但目标 CLI/provider 尚未登录。 | 在 Gateway 网关主机环境中登录或提供所需的 provider key。 |
|
||||
| `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 dispatch is disabled by policy (acp.dispatch.enabled=false)` | 来自普通线程消息的分发已被禁用。 | 设置 `acp.dispatch.enabled=true`。 |
|
||||
| `ACP agent "<id>" is not allowed by policy` | 智能体不在允许列表中。 | 使用被允许的 `agentId`,或更新 `acp.allowedAgents`。 |
|
||||
| `/acp doctor` 在启动后立刻报告后端未就绪 | 插件依赖探测或自修复仍在运行。 | 稍等片刻后重新运行 `/acp doctor`;如果仍不健康,请检查后端安装错误以及插件允许/拒绝策略。 |
|
||||
| 找不到 harness 命令 | 适配器 CLI 未安装,或首次运行的 `npx` 拉取失败。 | 在 Gateway 网关主机上安装/预热适配器,或显式配置 acpx 智能体命令。 |
|
||||
| harness 返回找不到模型 | 该模型 id 对另一个 provider/harness 有效,但不适用于当前 ACP 目标。 | 使用该 harness 列出的模型、在 harness 中配置该模型,或省略该覆盖值。 |
|
||||
| harness 返回供应商认证错误 | OpenClaw 本身正常,但目标 CLI/provider 未登录。 | 在 Gateway 网关主机环境中登录或提供所需的 provider 密钥。 |
|
||||
| `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[]`,或切换到受支持的渠道。 |
|
||||
| `--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"`,或从非沙箱隔离会话中将 ACP 与 `sandbox="inherit"` 一起使用。 |
|
||||
| `Cannot apply --model ... did not advertise model support` | 目标 harness 未暴露通用 ACP 模型切换支持。 | 使用声明了 ACP `models`/`session/set_model` 的 harness,使用 Codex ACP 模型引用,或如果该 harness 有自己的启动标志,则直接在其中配置模型。 |
|
||||
| `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。 |
|
||||
| `Cannot apply --model ... did not advertise model support` | 目标 harness 未暴露通用 ACP 模型切换支持。 | 使用声明了 ACP `models`/`session/set_model` 的 harness、使用 Codex ACP 模型引用,或如果 harness 有自己的启动标志,则直接在其中配置模型。 |
|
||||
| 已绑定会话缺少 ACP 元数据 | ACP 会话元数据已过期或被删除。 | 使用 `/acp spawn` 重新创建,然后重新绑定/聚焦线程。 |
|
||||
| `AcpRuntimeError: Permission prompt unavailable in non-interactive mode` | `permissionMode` 在非交互 ACP 会话中阻止写入/执行。 | 将 `plugins.entries.acpx.config.permissionMode` 设置为 `approve-all` 并重启 gateway。参见[权限配置](/zh-CN/tools/acp-agents-setup#permission-configuration)。 |
|
||||
| ACP 会话很早失败且几乎没有输出 | 权限提示被 `permissionMode`/`nonInteractivePermissions` 阻止。 | 检查 gateway 日志中的 `AcpRuntimeError`。如需完整权限,设置 `permissionMode=approve-all`;如需优雅降级,设置 `nonInteractivePermissions=deny`。 |
|
||||
| ACP 会话在完成工作后无限期卡住 | harness 进程已结束,但 ACP 会话未报告完成。 | 使用 `ps aux \| grep acpx` 监控;手动终止过期进程。 |
|
||||
| harness 看到了 `<<<BEGIN_OPENCLAW_INTERNAL_CONTEXT>>>` | 内部事件 envelope 泄漏到了 ACP 边界之外。 | 更新 OpenClaw 并重新运行完成流程;外部 harnesses 应只接收纯完成提示。 |
|
||||
| `AcpRuntimeError: Permission prompt unavailable in non-interactive mode` | `permissionMode` 在非交互式 ACP 会话中阻止了写入/exec。 | 将 `plugins.entries.acpx.config.permissionMode` 设置为 `approve-all` 并重启 Gateway 网关。参见[权限配置](/zh-CN/tools/acp-agents-setup#permission-configuration)。 |
|
||||
| ACP 会话很早失败且几乎没有输出 | 权限提示被 `permissionMode`/`nonInteractivePermissions` 阻止。 | 检查 Gateway 网关日志中的 `AcpRuntimeError`。若要授予完整权限,设置 `permissionMode=approve-all`;若要优雅降级,设置 `nonInteractivePermissions=deny`。 |
|
||||
| ACP 会话在完成工作后无限期卡住 | harness 进程已结束,但 ACP 会话没有报告完成。 | 使用 `ps aux \| grep acpx` 监控;手动杀掉过期进程。 |
|
||||
| harness 看到了 `<<<BEGIN_OPENCLAW_INTERNAL_CONTEXT>>>` | 内部事件信封泄露到了 ACP 边界之外。 | 更新 OpenClaw 并重新运行完成流程;外部 harness 应只接收普通完成提示。 |
|
||||
|
||||
## 相关内容
|
||||
|
||||
|
||||
@ -2,25 +2,25 @@
|
||||
read_when:
|
||||
- 安装或配置插件
|
||||
- 了解插件发现和加载规则
|
||||
- 使用与 Codex/Claude 兼容的插件包
|
||||
- 处理与 Codex/Claude 兼容的插件捆绑包
|
||||
sidebarTitle: Install and Configure
|
||||
summary: 安装、配置并管理 OpenClaw 插件
|
||||
summary: 安装、配置和管理 OpenClaw 插件
|
||||
title: 插件
|
||||
x-i18n:
|
||||
generated_at: "2026-04-26T06:20:17Z"
|
||||
generated_at: "2026-04-26T07:51:23Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 48348e09d38a5cce734098cdcbbc2e37a38928754bfed488e273407f3006d877
|
||||
source_hash: e5f774ccc52b70eb8626cc7d5421482079af87566fed3013846a9d7e4b3c0863
|
||||
source_path: tools/plugin.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
插件通过新增功能来扩展 OpenClaw:渠道、模型提供商、智能体 harness、工具、Skills、语音、实时转写、实时语音、媒体理解、图像生成、视频生成、网页抓取、网页搜索等。有些插件是**核心**插件(随 OpenClaw 一起提供),另一些是**外部**插件(由社区发布到 npm)。
|
||||
插件可为 OpenClaw 扩展新能力:渠道、模型提供商、智能体 harness、工具、Skills、语音、实时转录、实时语音、媒体理解、图像生成、视频生成、网页抓取、网络搜索等。有些插件属于**核心**插件(随 OpenClaw 一起发布),另一些则是**外部**插件(由社区发布到 npm)。
|
||||
|
||||
## 快速开始
|
||||
|
||||
<Steps>
|
||||
<Step title="查看已加载的内容">
|
||||
<Step title="查看已加载内容">
|
||||
```bash
|
||||
openclaw plugins list
|
||||
```
|
||||
@ -28,10 +28,10 @@ x-i18n:
|
||||
|
||||
<Step title="安装插件">
|
||||
```bash
|
||||
# 从 npm 安装
|
||||
# 来自 npm
|
||||
openclaw plugins install @openclaw/voice-call
|
||||
|
||||
# 从本地目录或归档文件安装
|
||||
# 来自本地目录或归档文件
|
||||
openclaw plugins install ./my-plugin
|
||||
openclaw plugins install ./my-plugin.tgz
|
||||
```
|
||||
@ -43,12 +43,12 @@ x-i18n:
|
||||
openclaw gateway restart
|
||||
```
|
||||
|
||||
然后在你的配置文件中,通过 `plugins.entries.\<id\>.config` 进行配置。
|
||||
然后在配置文件中的 `plugins.entries.\<id\>.config` 下进行配置。
|
||||
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
如果你更喜欢聊天原生控制方式,可启用 `commands.plugins: true` 并使用:
|
||||
如果你更喜欢原生聊天控制,可启用 `commands.plugins: true` 并使用:
|
||||
|
||||
```text
|
||||
/plugin install clawhub:@openclaw/voice-call
|
||||
@ -58,26 +58,24 @@ x-i18n:
|
||||
|
||||
安装路径使用与 CLI 相同的解析器:本地路径/归档文件、显式 `clawhub:<pkg>`,或裸包规范(优先 ClawHub,然后回退到 npm)。
|
||||
|
||||
如果配置无效,安装通常会以失败关闭的方式结束,并提示你运行 `openclaw doctor --fix`。唯一的恢复例外,是针对选择启用 `openclaw.install.allowInvalidConfigRecovery` 的插件,提供的一条受限的内置插件重装路径。
|
||||
如果配置无效,安装通常会以安全失败方式终止,并提示你使用 `openclaw doctor --fix`。唯一的恢复例外是一个狭义的内置插件重装路径,适用于选择加入 `openclaw.install.allowInvalidConfigRecovery` 的插件。
|
||||
|
||||
打包版 OpenClaw 安装不会急切安装每个内置插件的运行时依赖树。当某个由 OpenClaw 拥有的内置插件通过插件配置、旧版渠道配置或默认启用的清单处于活动状态时,启动修复只会在导入它之前修复该插件声明的运行时依赖。仅持久化的渠道身份验证状态本身,不会为 Gateway 网关启动时的运行时依赖修复激活某个内置渠道。
|
||||
显式禁用仍然优先生效:`plugins.entries.<id>.enabled: false`、`plugins.deny`、`plugins.enabled: false` 和 `channels.<id>.enabled: false` 会阻止该插件/渠道进行自动的内置运行时依赖修复。
|
||||
外部插件和自定义加载路径仍必须通过
|
||||
`openclaw plugins install` 安装。
|
||||
打包形式的 OpenClaw 安装不会急切安装每个内置插件的运行时依赖树。当某个 OpenClaw 自带的内置插件因插件配置、旧版渠道配置或默认启用的清单而处于激活状态时,启动修复仅会在导入该插件之前修复该插件声明的运行时依赖。仅凭持久化的渠道认证状态,并不会激活某个内置渠道来进行 Gateway 网关启动时的运行时依赖修复。
|
||||
显式禁用仍然优先:`plugins.entries.<id>.enabled: false`、`plugins.deny`、`plugins.enabled: false` 和 `channels.<id>.enabled: false` 都会阻止对该插件/渠道进行自动的内置运行时依赖修复。
|
||||
外部插件和自定义加载路径仍然必须通过 `openclaw plugins install` 安装。
|
||||
|
||||
## 插件类型
|
||||
|
||||
OpenClaw 可识别两种插件格式:
|
||||
OpenClaw 识别两种插件格式:
|
||||
|
||||
| 格式 | 工作方式 | 示例 |
|
||||
| ---------- | ------------------------------------------------------------------ | ------------------------------------------------------ |
|
||||
| **原生** | `openclaw.plugin.json` + 运行时模块;在进程内执行 | 官方插件、社区 npm 包 |
|
||||
| **Bundle** | 兼容 Codex/Claude/Cursor 的布局;映射到 OpenClaw 功能 | `.codex-plugin/`、`.claude-plugin/`、`.cursor-plugin/` |
|
||||
| **Native** | `openclaw.plugin.json` + 运行时模块;在进程内执行 | 官方插件、社区 npm 包 |
|
||||
| **Bundle** | 与 Codex/Claude/Cursor 兼容的布局;映射到 OpenClaw 功能 | `.codex-plugin/`、`.claude-plugin/`、`.cursor-plugin/` |
|
||||
|
||||
两者都会显示在 `openclaw plugins list` 中。有关 bundle 的详细信息,请参见 [Plugin Bundles](/zh-CN/plugins/bundles)。
|
||||
这两类都会显示在 `openclaw plugins list` 中。有关 bundle 的详细信息,请参阅 [Plugin Bundles](/zh-CN/plugins/bundles)。
|
||||
|
||||
如果你正在编写原生插件,请从 [构建插件](/zh-CN/plugins/building-plugins)
|
||||
和 [插件 SDK 概览](/zh-CN/plugins/sdk-overview) 开始。
|
||||
如果你正在编写 Native 插件,请从 [构建插件](/zh-CN/plugins/building-plugins) 和 [插件 SDK 概览](/zh-CN/plugins/sdk-overview) 开始。
|
||||
|
||||
## 官方插件
|
||||
|
||||
@ -92,7 +90,7 @@ OpenClaw 可识别两种插件格式:
|
||||
| Zalo | `@openclaw/zalo` | [Zalo](/zh-CN/channels/zalo) |
|
||||
| Zalo Personal | `@openclaw/zalouser` | [Zalo Personal](/zh-CN/plugins/zalouser) |
|
||||
|
||||
### 核心(随 OpenClaw 一起提供)
|
||||
### 核心(随 OpenClaw 一起发布)
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="模型提供商(默认启用)">
|
||||
@ -104,8 +102,8 @@ OpenClaw 可识别两种插件格式:
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Memory 插件">
|
||||
- `memory-core` — 内置内存搜索(默认通过 `plugins.slots.memory`)
|
||||
- `memory-lancedb` — 按需安装的长期记忆,带自动召回/捕获功能(设置 `plugins.slots.memory = "memory-lancedb"`)
|
||||
- `memory-core` — 内置 Memory 搜索(默认通过 `plugins.slots.memory`)
|
||||
- `memory-lancedb` — 按需安装的长期 Memory,带自动召回/捕获功能(设置 `plugins.slots.memory = "memory-lancedb"`)
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="语音提供商(默认启用)">
|
||||
@ -113,12 +111,12 @@ OpenClaw 可识别两种插件格式:
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="其他">
|
||||
- `browser` — 用于浏览器工具、`openclaw browser` CLI、`browser.request` gateway 方法、浏览器运行时以及默认浏览器控制服务的内置浏览器插件(默认启用;替换前请先禁用)
|
||||
- `browser` — 为浏览器工具、`openclaw browser` CLI、`browser.request` Gateway 网关方法、浏览器运行时和默认浏览器控制服务提供支持的内置浏览器插件(默认启用;替换它之前请先禁用)
|
||||
- `copilot-proxy` — VS Code Copilot Proxy 桥接(默认禁用)
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
在找第三方插件?请参见 [社区插件](/zh-CN/plugins/community)。
|
||||
在找第三方插件?请参见 [Community Plugins](/zh-CN/plugins/community)。
|
||||
|
||||
## 配置
|
||||
|
||||
@ -141,19 +139,18 @@ OpenClaw 可识别两种插件格式:
|
||||
| `enabled` | 主开关(默认:`true`) |
|
||||
| `allow` | 插件允许列表(可选) |
|
||||
| `deny` | 插件拒绝列表(可选;拒绝优先) |
|
||||
| `load.paths` | 额外的插件文件/目录 |
|
||||
| `slots` | 独占槽位选择器(例如 `memory`、`contextEngine`) |
|
||||
| `load.paths` | 额外插件文件/目录 |
|
||||
| `slots` | 独占插槽选择器(例如 `memory`、`contextEngine`) |
|
||||
| `entries.\<id\>` | 每个插件的开关 + 配置 |
|
||||
|
||||
配置更改**需要重启网关**。如果 Gateway 网关在启用配置监听和进程内重启的情况下运行(默认的 `openclaw gateway` 路径),通常会在配置写入完成后稍等片刻自动执行重启。
|
||||
对于原生插件运行时代码或生命周期钩子,没有受支持的热重载路径;在你期望更新后的 `register(api)` 代码、`api.on(...)` 钩子、工具、服务或提供商/运行时钩子生效之前,请重启为实时渠道提供服务的 Gateway 网关进程。
|
||||
配置更改**需要重启 Gateway 网关**。如果 Gateway 网关以启用了配置监视和进程内重启的方式运行(默认的 `openclaw gateway` 路径),那么在配置写入落地后,这个重启通常会自动在片刻后执行。
|
||||
对于 Native 插件运行时代码或生命周期钩子,不存在受支持的热重载路径;在你期望更新后的 `register(api)` 代码、`api.on(...)` 钩子、工具、服务或提供商/运行时钩子生效之前,请重启为实时渠道提供服务的 Gateway 网关进程。
|
||||
|
||||
`openclaw plugins list` 是本地插件注册表/配置快照。
|
||||
其中的 `enabled` 插件表示持久化注册表和当前配置允许该插件参与运行。它并不能证明某个已经运行中的远程 Gateway 网关子进程已重启到相同的插件代码。在 VPS/容器部署中,如果有包装器进程,请将重启命令发送到实际的 `openclaw gateway run` 进程,或针对正在运行的 Gateway 网关使用 `openclaw gateway restart`。
|
||||
`openclaw plugins list` 是本地插件注册表/配置快照。这里显示某个插件为 `enabled`,意味着持久化注册表和当前配置允许该插件参与运行。这并不能证明一个已经在运行的远程 Gateway 网关子进程已经重启并使用了相同的插件代码。在 VPS/容器部署中,如果有包装进程,请将重启信号发送给实际的 `openclaw gateway run` 进程,或针对正在运行的 Gateway 网关使用 `openclaw gateway restart`。
|
||||
|
||||
<Accordion title="插件状态:disabled、missing 与 invalid">
|
||||
<Accordion title="插件状态:disabled vs missing vs invalid">
|
||||
- **Disabled**:插件存在,但启用规则将其关闭。配置会被保留。
|
||||
- **Missing**:配置引用了某个插件 id,但发现流程没有找到它。
|
||||
- **Missing**:配置引用了某个插件 id,但发现阶段没有找到它。
|
||||
- **Invalid**:插件存在,但其配置与声明的 schema 不匹配。
|
||||
</Accordion>
|
||||
|
||||
@ -163,7 +160,7 @@ OpenClaw 按以下顺序扫描插件(先匹配者优先):
|
||||
|
||||
<Steps>
|
||||
<Step title="配置路径">
|
||||
`plugins.load.paths` — 显式文件或目录路径。指回 OpenClaw 自身打包内置插件目录的路径会被忽略;请运行 `openclaw doctor --fix` 以移除这些过时别名。
|
||||
`plugins.load.paths` — 显式文件或目录路径。那些指回 OpenClaw 自身打包内置插件目录的路径会被忽略;请运行 `openclaw doctor --fix` 来移除这些过时别名。
|
||||
</Step>
|
||||
|
||||
<Step title="工作区插件">
|
||||
@ -175,7 +172,7 @@ OpenClaw 按以下顺序扫描插件(先匹配者优先):
|
||||
</Step>
|
||||
|
||||
<Step title="内置插件">
|
||||
随 OpenClaw 一起提供。其中许多默认启用(模型提供商、语音)。
|
||||
随 OpenClaw 一起发布。许多默认启用(模型提供商、语音)。
|
||||
其他则需要显式启用。
|
||||
</Step>
|
||||
</Steps>
|
||||
@ -186,25 +183,21 @@ OpenClaw 按以下顺序扫描插件(先匹配者优先):
|
||||
- `plugins.deny` 始终优先于 allow
|
||||
- `plugins.entries.\<id\>.enabled: false` 会禁用该插件
|
||||
- 来自工作区的插件**默认禁用**(必须显式启用)
|
||||
- 内置插件遵循内建的默认开启集合,除非被覆盖
|
||||
- 独占槽位可强制启用该槽位中所选的插件
|
||||
- 某些内置的可选启用插件会在配置指定某个由插件拥有的表面时自动启用,例如提供商模型引用、渠道配置或 harness 运行时
|
||||
- OpenAI 系列的 Codex 路由保持独立的插件边界:
|
||||
`openai-codex/*` 属于 OpenAI 插件,而内置的 Codex
|
||||
app-server 插件则通过 `embeddedHarness.runtime: "codex"` 或旧版
|
||||
`codex/*` 模型引用选择
|
||||
- 内置插件遵循内建的默认启用集合,除非被覆盖
|
||||
- 独占插槽可以强制启用该插槽所选中的插件
|
||||
- 某些内置选择加入型插件会在配置命名某个插件拥有的表面时自动启用,例如提供商模型引用、渠道配置或 harness 运行时
|
||||
- OpenAI 系列 Codex 路由保持独立的插件边界:
|
||||
`openai-codex/*` 属于 OpenAI 插件,而内置的 Codex app-server 插件则由 `agentRuntime.id: "codex"` 或旧版 `codex/*` 模型引用选择
|
||||
|
||||
## 运行时钩子故障排除
|
||||
|
||||
如果某个插件出现在 `plugins list` 中,但 `register(api)` 的副作用或钩子没有在实时聊天流量中运行,请先检查以下内容:
|
||||
|
||||
- 运行 `openclaw gateway status --deep --require-rpc`,并确认活动中的 Gateway 网关 URL、配置文件、配置路径和进程,正是你正在编辑的那些。
|
||||
- 在插件安装/配置/代码更改后,重启实时 Gateway 网关。在包装容器中,PID 1 可能只是一个监督进程;请重启或向子进程 `openclaw gateway run` 发送信号。
|
||||
- 使用 `openclaw plugins inspect <id> --json` 确认钩子注册和诊断信息。非内置的会话钩子,如 `llm_input`、
|
||||
`llm_output`、`before_agent_finalize` 和 `agent_end`,需要
|
||||
`plugins.entries.<id>.hooks.allowConversationAccess=true`。
|
||||
- 对于模型切换,优先使用 `before_model_resolve`。它会在智能体轮次的模型解析之前运行;`llm_output` 只会在某次模型尝试产生助手输出后运行。
|
||||
- 如需证明会话实际使用的模型,请使用 `openclaw sessions` 或 Gateway 网关的会话/状态表面;调试提供商负载时,请使用 `--raw-stream --raw-stream-path <path>` 启动 Gateway 网关。
|
||||
- 运行 `openclaw gateway status --deep --require-rpc`,确认当前活动的 Gateway 网关 URL、profile、配置路径和进程就是你正在编辑的那一个。
|
||||
- 在插件安装/配置/代码更改后重启实时 Gateway 网关。在包装容器中,PID 1 可能只是一个 supervisor;请重启或发送信号给子进程 `openclaw gateway run`。
|
||||
- 使用 `openclaw plugins inspect <id> --json` 确认钩子注册和诊断信息。诸如 `llm_input`、`llm_output`、`before_agent_finalize` 和 `agent_end` 这类非内置的会话钩子需要 `plugins.entries.<id>.hooks.allowConversationAccess=true`。
|
||||
- 对于模型切换,优先使用 `before_model_resolve`。它会在智能体轮次的模型解析之前运行;`llm_output` 只会在某次模型尝试产生 assistant 输出之后运行。
|
||||
- 若要证明当前会话实际使用的模型,请使用 `openclaw sessions` 或 Gateway 网关会话/状态表面;调试提供商负载时,请使用 `--raw-stream --raw-stream-path <path>` 启动 Gateway 网关。
|
||||
|
||||
### 重复的渠道或工具所有权
|
||||
|
||||
@ -214,25 +207,24 @@ OpenClaw 按以下顺序扫描插件(先匹配者优先):
|
||||
- `channel setup already registered: <channel-id> (<plugin-id>)`
|
||||
- `plugin tool name conflict (<plugin-id>): <tool-name>`
|
||||
|
||||
这些错误意味着有多个已启用插件正在尝试拥有相同的渠道、设置流程或工具名称。最常见的原因是,某个外部渠道插件与一个现在已提供相同渠道 id 的内置插件同时安装。
|
||||
这些意味着有多个已启用插件试图拥有相同的渠道、设置流程或工具名称。最常见的原因是:某个外部渠道插件与如今已提供相同渠道 id 的内置插件同时安装。
|
||||
|
||||
调试步骤:
|
||||
|
||||
- 运行 `openclaw plugins list --enabled --verbose`,查看每个已启用插件及其来源。
|
||||
- 对每个可疑插件运行 `openclaw plugins inspect <id> --json`,并比较 `channels`、`channelConfigs`、`tools` 和诊断信息。
|
||||
- 在安装或删除插件包后,运行 `openclaw plugins registry --refresh`,以便让持久化元数据反映当前安装状态。
|
||||
- 在安装、注册表或配置变更后重启 Gateway 网关。
|
||||
- 对每个可疑插件运行 `openclaw plugins inspect <id> --json`,比较 `channels`、`channelConfigs`、`tools` 和诊断信息。
|
||||
- 在安装或移除插件包后运行 `openclaw plugins registry --refresh`,以便持久化元数据反映当前安装状态。
|
||||
- 在安装、注册表或配置更改后重启 Gateway 网关。
|
||||
|
||||
修复选项:
|
||||
修复方式:
|
||||
|
||||
- 如果某个插件有意替代另一个使用相同渠道 id 的插件,则首选插件应声明 `channelConfigs.<channel-id>.preferOver`,并填入优先级较低的插件 id。参见 [/plugins/manifest#replacing-another-channel-plugin](/zh-CN/plugins/manifest#replacing-another-channel-plugin)。
|
||||
- 如果重复是意外造成的,请使用
|
||||
`plugins.entries.<plugin-id>.enabled: false` 禁用其中一方,或删除过时的插件安装。
|
||||
- 如果你显式启用了这两个插件,OpenClaw 会保留这一请求并报告冲突。请为该渠道选择一个所有者,或重命名插件拥有的工具,以确保运行时表面明确无歧义。
|
||||
- 如果某个插件有意替换另一个拥有相同渠道 id 的插件,则首选插件应声明 `channelConfigs.<channel-id>.preferOver`,并指定优先级更低的插件 id。参见 [/plugins/manifest#replacing-another-channel-plugin](/zh-CN/plugins/manifest#replacing-another-channel-plugin)。
|
||||
- 如果重复是意外发生的,请通过 `plugins.entries.<plugin-id>.enabled: false` 禁用其中一方,或移除过时的插件安装。
|
||||
- 如果你显式启用了两个插件,OpenClaw 会保留这一请求并报告冲突。请为该渠道选择一个唯一所有者,或者重命名插件拥有的工具,以确保运行时表面明确无歧义。
|
||||
|
||||
## 插件槽位(独占类别)
|
||||
## 插件插槽(独占类别)
|
||||
|
||||
某些类别是独占的(同一时间只能有一个处于活动状态):
|
||||
有些类别是独占的(一次只能有一个激活):
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -245,10 +237,10 @@ OpenClaw 按以下顺序扫描插件(先匹配者优先):
|
||||
}
|
||||
```
|
||||
|
||||
| 槽位 | 控制内容 | 默认值 |
|
||||
| 插槽 | 控制内容 | 默认值 |
|
||||
| --------------- | --------------------- | ------------------- |
|
||||
| `memory` | 活动中的 Memory 插件 | `memory-core` |
|
||||
| `contextEngine` | 活动中的上下文引擎 | `legacy`(内置) |
|
||||
| `memory` | 当前激活的 Memory 插件 | `memory-core` |
|
||||
| `contextEngine` | 当前激活的上下文引擎 | `legacy`(内置) |
|
||||
|
||||
## CLI 参考
|
||||
|
||||
@ -262,23 +254,23 @@ openclaw plugins inspect <id> --json # 机器可读
|
||||
openclaw plugins inspect --all # 全量表格
|
||||
openclaw plugins info <id> # inspect 的别名
|
||||
openclaw plugins doctor # 诊断
|
||||
openclaw plugins registry # 查看持久化注册表状态
|
||||
openclaw plugins registry # 检查持久化注册表状态
|
||||
openclaw plugins registry --refresh # 重建持久化注册表
|
||||
openclaw doctor --fix # 修复插件注册表状态
|
||||
|
||||
openclaw plugins install <package> # 安装(优先 ClawHub,然后 npm)
|
||||
openclaw plugins install <package> # 安装(优先 ClawHub,再回退到 npm)
|
||||
openclaw plugins install clawhub:<pkg> # 仅从 ClawHub 安装
|
||||
openclaw plugins install <spec> --force # 覆盖现有安装
|
||||
openclaw plugins install <path> # 从本地路径安装
|
||||
openclaw plugins install -l <path> # 链接(不复制),用于开发
|
||||
openclaw plugins install <plugin> --marketplace <source>
|
||||
openclaw plugins install <plugin> --marketplace https://github.com/<owner>/<repo>
|
||||
openclaw plugins install <spec> --pin # 记录精确解析后的 npm spec
|
||||
openclaw plugins install <spec> --pin # 记录精确解析后的 npm 规范
|
||||
openclaw plugins install <spec> --dangerously-force-unsafe-install
|
||||
openclaw plugins update <id-or-npm-spec> # 更新单个插件
|
||||
openclaw plugins update <id-or-npm-spec> --dangerously-force-unsafe-install
|
||||
openclaw plugins update --all # 更新全部
|
||||
openclaw plugins uninstall <id> # 删除配置和插件索引记录
|
||||
openclaw plugins uninstall <id> # 移除配置和插件索引记录
|
||||
openclaw plugins uninstall <id> --keep-files
|
||||
openclaw plugins marketplace list <source>
|
||||
openclaw plugins marketplace list <source> --json
|
||||
@ -287,33 +279,32 @@ openclaw plugins enable <id>
|
||||
openclaw plugins disable <id>
|
||||
```
|
||||
|
||||
内置插件随 OpenClaw 一起提供。许多默认启用(例如内置模型提供商、内置语音提供商以及内置浏览器插件)。其他内置插件仍需要 `openclaw plugins enable <id>`。
|
||||
内置插件随 OpenClaw 一起发布。许多默认启用(例如内置模型提供商、内置语音提供商,以及内置浏览器插件)。其他内置插件仍然需要执行 `openclaw plugins enable <id>`。
|
||||
|
||||
`--force` 会原地覆盖一个已安装的插件或 hook 包。对于已跟踪 npm 插件的常规升级,请使用
|
||||
`openclaw plugins update <id-or-npm-spec>`。它不支持与 `--link` 一起使用,因为后者会复用源路径,而不是复制到受管理的安装目标中。
|
||||
`--force` 会原地覆盖现有已安装插件或 hook pack。对于已跟踪的 npm 插件的常规升级,请使用 `openclaw plugins update <id-or-npm-spec>`。它不支持与 `--link` 一起使用,因为 `--link` 会复用源路径,而不是复制到受管理的安装目标。
|
||||
|
||||
当 `plugins.allow` 已设置时,`openclaw plugins install` 会在启用插件之前,将已安装插件的 id 添加到该允许列表中,因此重启后会立即可加载。
|
||||
当已经设置了 `plugins.allow` 时,`openclaw plugins install` 会在启用插件之前将已安装插件 id 添加到该允许列表中,因此重启后可立即加载。
|
||||
|
||||
OpenClaw 会保留一个持久化的本地插件注册表,作为插件清单、贡献归属和启动规划的冷读取模型。安装、更新、卸载、启用和禁用流程会在更改插件状态后刷新该注册表。同一个 `plugins/installs.json` 文件会在顶层 `installRecords` 中保存持久安装元数据,并在 `plugins` 中保存可重建的 manifest 元数据。如果注册表缺失、陈旧或无效,`openclaw plugins registry --refresh` 会基于安装记录、配置策略以及 manifest/package 元数据,重建其 manifest 视图,而无需加载插件运行时模块。
|
||||
`openclaw plugins update <id-or-npm-spec>` 适用于已跟踪的安装。传入带 dist-tag 或精确版本的 npm 包 spec 时,会将包名解析回已跟踪的插件记录,并为未来更新记录新的 spec。传入不带版本的包名时,会将精确固定版本的安装移回注册表默认发布线。如果已安装的 npm 插件已经与解析后的版本和记录的制品标识一致,OpenClaw 会跳过更新,而不会下载、重新安装或重写配置。
|
||||
OpenClaw 将持久化的本地插件注册表作为插件清单、贡献归属和启动规划的冷读取模型。安装、更新、卸载、启用和禁用流程在更改插件状态后都会刷新该注册表。同一个 `plugins/installs.json` 文件会在顶层 `installRecords` 中保留持久安装元数据,并在 `plugins` 中保留可重建的清单元数据。如果注册表缺失、过期或无效,`openclaw plugins registry --refresh` 会根据安装记录、配置策略和清单/包元数据重建其清单视图,而不会加载插件运行时模块。
|
||||
`openclaw plugins update <id-or-npm-spec>` 适用于已跟踪安装。传入带 dist-tag 或精确版本的 npm 包规范时,它会将包名解析回已跟踪插件记录,并为后续更新记录新的规范。传入不带版本的包名时,会将精确固定版本的安装移回注册表的默认发布线。如果已安装的 npm 插件已经与解析出的版本和记录的制品标识匹配,OpenClaw 会跳过更新,而不会下载、重新安装或重写配置。
|
||||
|
||||
`--pin` 仅适用于 npm。它不支持与 `--marketplace` 一起使用,因为 marketplace 安装会持久保存 marketplace 源元数据,而不是 npm spec。
|
||||
`--pin` 仅适用于 npm。不支持与 `--marketplace` 一起使用,因为 marketplace 安装会持久化 marketplace 源元数据,而不是 npm 规范。
|
||||
|
||||
`--dangerously-force-unsafe-install` 是一个用于应对内置危险代码扫描器误报的破窗式覆盖选项。它允许插件安装和插件更新在遇到内置 `critical` 发现时继续执行,但仍不会绕过插件 `before_install` 策略阻止或扫描失败阻止。
|
||||
`--dangerously-force-unsafe-install` 是内置危险代码扫描器出现误报时的应急覆盖开关。它允许插件安装和插件更新在遇到内置 `critical` 发现时继续进行,但仍然不会绕过插件 `before_install` 策略阻止或扫描失败阻止。
|
||||
|
||||
这个 CLI 标志仅适用于插件安装/更新流程。由 Gateway 网关支持的 Skills 依赖安装则使用对应的 `dangerouslyForceUnsafeInstall` 请求覆盖参数,而 `openclaw skills install` 仍然是独立的 ClawHub Skills 下载/安装流程。
|
||||
此 CLI 标志仅适用于插件安装/更新流程。由 Gateway 网关支持的 Skill 依赖安装则改用对应的 `dangerouslyForceUnsafeInstall` 请求覆盖,而 `openclaw skills install` 仍然是独立的 ClawHub Skill 下载/安装流程。
|
||||
|
||||
兼容的 bundle 会参与同样的插件 list/inspect/enable/disable 流程。当前运行时支持包括 bundle Skills、Claude command-skills、Claude `settings.json` 默认值、Claude `.lsp.json` 和 manifest 声明的 `lspServers` 默认值、Cursor command-skills,以及兼容的 Codex hook 目录。
|
||||
兼容的 bundle 会参与同一套插件 list/inspect/enable/disable 流程。当前运行时支持包括 bundle Skills、Claude command-skills、Claude `settings.json` 默认值、Claude `.lsp.json` 和清单声明的 `lspServers` 默认值、Cursor command-skills,以及兼容的 Codex hook 目录。
|
||||
|
||||
`openclaw plugins inspect <id>` 还会报告已检测到的 bundle 能力,以及由 bundle 支持的或不支持的 MCP 和 LSP 服务器条目。
|
||||
`openclaw plugins inspect <id>` 还会报告检测到的 bundle 能力,以及 bundle 支持插件中受支持或不受支持的 MCP 和 LSP 服务器条目。
|
||||
|
||||
Marketplace 源可以是 `~/.claude/plugins/known_marketplaces.json` 中 Claude 已知 marketplace 名称、本地 marketplace 根目录或 `marketplace.json` 路径、类似 `owner/repo` 的 GitHub 简写、GitHub 仓库 URL,或 git URL。对于远程 marketplace,插件条目必须保留在克隆的 marketplace 仓库内,并且只能使用相对路径源。
|
||||
Marketplace 源可以是 `~/.claude/plugins/known_marketplaces.json` 中的 Claude 已知 marketplace 名称、本地 marketplace 根目录或 `marketplace.json` 路径、类似 `owner/repo` 的 GitHub 简写、GitHub 仓库 URL 或 git URL。对于远程 marketplace,插件条目必须保持在克隆后的 marketplace 仓库内部,并且只能使用相对路径源。
|
||||
|
||||
完整详情请参见 [`openclaw plugins` CLI 参考](/zh-CN/cli/plugins)。
|
||||
|
||||
## 插件 API 概览
|
||||
|
||||
原生插件会导出一个入口对象,并暴露 `register(api)`。旧版插件仍可能使用 `activate(api)` 作为旧别名,但新插件应使用 `register`。
|
||||
Native 插件会导出一个入口对象,并暴露 `register(api)`。较旧的插件可能仍然使用 `activate(api)` 作为旧版别名,但新插件应使用 `register`。
|
||||
|
||||
```typescript
|
||||
export default definePluginEntry({
|
||||
@ -333,19 +324,20 @@ export default definePluginEntry({
|
||||
});
|
||||
```
|
||||
|
||||
OpenClaw 会加载该入口对象,并在插件激活期间调用 `register(api)`。加载器仍会为旧插件回退到 `activate(api)`,但内置插件和新的外部插件应将 `register` 视为公开契约。
|
||||
OpenClaw 会加载入口对象,并在插件激活期间调用 `register(api)`。加载器仍然会为旧插件回退到 `activate(api)`,但内置插件和新的外部插件应将 `register` 视为公开契约。
|
||||
|
||||
`api.registrationMode` 会告诉插件其入口被加载的原因:
|
||||
`api.registrationMode` 会告诉插件为什么要加载它的入口:
|
||||
|
||||
| 模式 | 含义 |
|
||||
| --------------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `full` | 运行时激活。注册工具、钩子、服务、命令、路由以及其他实时副作用。 |
|
||||
| `discovery` | 只读能力发现。注册提供商和元数据;可信的插件入口代码可能会被加载,但应跳过实时副作用。 |
|
||||
| `full` | 运行时激活。注册工具、钩子、服务、命令、路由和其他实时副作用。 |
|
||||
| `discovery` | 只读能力发现。注册提供商和元数据;受信任的插件入口代码可能会被加载,但应跳过实时副作用。 |
|
||||
| `setup-only` | 通过轻量级设置入口加载渠道设置元数据。 |
|
||||
| `setup-runtime` | 需要运行时入口的渠道设置加载。 |
|
||||
| `setup-runtime` | 加载同时也需要运行时入口的渠道设置。 |
|
||||
| `cli-metadata` | 仅收集 CLI 命令元数据。 |
|
||||
|
||||
对于会打开套接字、数据库、后台工作线程或长生命周期客户端的插件入口,应使用 `api.registrationMode === "full"` 来保护这些副作用。发现加载与激活加载会分别缓存,并且不会替换正在运行的 Gateway 网关注册表。发现是非激活式的,而不是免导入的:OpenClaw 可能会求值可信的插件入口或渠道插件模块,以构建快照。请保持模块顶层轻量且无副作用,并将网络客户端、子进程、监听器、凭证读取和服务启动移到完整运行时路径之后。
|
||||
那些会打开套接字、数据库、后台工作线程或长生命周期客户端的插件入口,应使用 `api.registrationMode === "full"` 来保护这些副作用。
|
||||
发现加载会与激活加载分别缓存,并不会替换正在运行的 Gateway 网关注册表。发现是非激活的,而不是免导入的:OpenClaw 可能会求值受信任的插件入口或渠道插件模块,以构建快照。请保持模块顶层轻量且无副作用,并将网络客户端、子进程、监听器、凭证读取和服务启动移动到完整运行时路径之后。
|
||||
|
||||
常见注册方法:
|
||||
|
||||
@ -362,32 +354,31 @@ OpenClaw 会加载该入口对象,并在插件激活期间调用 `register(api
|
||||
| `registerImageGenerationProvider` | 图像生成 |
|
||||
| `registerMusicGenerationProvider` | 音乐生成 |
|
||||
| `registerVideoGenerationProvider` | 视频生成 |
|
||||
| `registerWebFetchProvider` | 网页抓取 / 抓取提供商 |
|
||||
| `registerWebSearchProvider` | 网页搜索 |
|
||||
| `registerWebFetchProvider` | Web 抓取 / 抓取提供商 |
|
||||
| `registerWebSearchProvider` | 网络搜索 |
|
||||
| `registerHttpRoute` | HTTP 端点 |
|
||||
| `registerCommand` / `registerCli` | CLI 命令 |
|
||||
| `registerContextEngine` | 上下文引擎 |
|
||||
| `registerService` | 后台服务 |
|
||||
|
||||
类型化生命周期钩子的钩子守卫行为:
|
||||
类型化生命周期钩子的守卫行为:
|
||||
|
||||
- `before_tool_call`:`{ block: true }` 为终止性结果;会跳过更低优先级的处理器。
|
||||
- `before_tool_call`:`{ block: false }` 是无操作,不会清除更早的阻止。
|
||||
- `before_install`:`{ block: true }` 为终止性结果;会跳过更低优先级的处理器。
|
||||
- `before_install`:`{ block: false }` 是无操作,不会清除更早的阻止。
|
||||
- `message_sending`:`{ cancel: true }` 为终止性结果;会跳过更低优先级的处理器。
|
||||
- `message_sending`:`{ cancel: false }` 是无操作,不会清除更早的取消。
|
||||
- `before_tool_call`:`{ block: true }` 是终止性的;优先级更低的处理器会被跳过。
|
||||
- `before_tool_call`:`{ block: false }` 是空操作,不会清除更早的阻止结果。
|
||||
- `before_install`:`{ block: true }` 是终止性的;优先级更低的处理器会被跳过。
|
||||
- `before_install`:`{ block: false }` 是空操作,不会清除更早的阻止结果。
|
||||
- `message_sending`:`{ cancel: true }` 是终止性的;优先级更低的处理器会被跳过。
|
||||
- `message_sending`:`{ cancel: false }` 是空操作,不会清除更早的取消结果。
|
||||
|
||||
原生 Codex app-server 会将桥接的 Codex 原生工具事件回传到这个钩子表面。插件可以通过 `before_tool_call` 阻止原生 Codex 工具,通过 `after_tool_call` 观察结果,并参与 Codex `PermissionRequest` 审批。该桥接当前还不会重写 Codex 原生工具参数。Codex 运行时支持的精确边界位于
|
||||
[Codex harness v1 支持契约](/zh-CN/plugins/codex-harness#v1-support-contract)。
|
||||
Native Codex app-server 会将 Codex 原生工具事件桥接回这个钩子接口。插件可以通过 `before_tool_call` 阻止原生 Codex 工具,通过 `after_tool_call` 观察结果,并参与 Codex `PermissionRequest` 审批。该桥接目前还不会重写 Codex 原生工具参数。准确的 Codex 运行时支持边界请参见 [Codex harness v1 support contract](/zh-CN/plugins/codex-harness#v1-support-contract)。
|
||||
|
||||
有关完整的类型化钩子行为,请参见 [SDK 概览](/zh-CN/plugins/sdk-overview#hook-decision-semantics)。
|
||||
有关完整的类型化钩子行为,请参见 [插件 SDK 概览](/zh-CN/plugins/sdk-overview#hook-decision-semantics)。
|
||||
|
||||
## 相关内容
|
||||
|
||||
- [构建插件](/zh-CN/plugins/building-plugins) — 创建你自己的插件
|
||||
- [Plugin Bundles](/zh-CN/plugins/bundles) — Codex/Claude/Cursor bundle 兼容性
|
||||
- [插件 manifest](/zh-CN/plugins/manifest) — manifest schema
|
||||
- [Plugin manifest](/zh-CN/plugins/manifest) — manifest schema
|
||||
- [注册工具](/zh-CN/plugins/building-plugins#registering-agent-tools) — 在插件中添加智能体工具
|
||||
- [插件内部机制](/zh-CN/plugins/architecture) — 能力模型和加载管线
|
||||
- [社区插件](/zh-CN/plugins/community) — 第三方列表
|
||||
- [插件架构内部机制](/zh-CN/plugins/architecture) — 能力模型和加载流水线
|
||||
- [Community Plugins](/zh-CN/plugins/community) — 第三方列表
|
||||
|
||||
@ -1,30 +1,34 @@
|
||||
---
|
||||
read_when:
|
||||
- 为回复启用文本转语音
|
||||
- 配置 TTS 提供商、回退链或角色语音
|
||||
- 使用 `/tts` 命令或指令
|
||||
- 配置 TTS provider、回退链或 persona
|
||||
- 使用 /tts 命令或指令
|
||||
sidebarTitle: Text to speech (TTS)
|
||||
summary: 用于外发回复的文本转语音——提供商、角色语音、斜杠命令,以及按渠道区分的输出
|
||||
summary: 用于外发回复的文本转语音 —— 提供商、persona、斜杠命令和按渠道输出
|
||||
title: 文本转语音
|
||||
x-i18n:
|
||||
generated_at: "2026-04-26T06:20:29Z"
|
||||
generated_at: "2026-04-26T07:51:29Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 9844f0efe139e4ea4dd8f15b2476c5b55aa0d97c89e7b54125b29580e3b8c78e
|
||||
source_hash: 199a84fde8f7fd380667a39c448ac8158e0aab071b77be41b87431d10d8b4219
|
||||
source_path: tools/tts.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
OpenClaw 可以将外发回复转换为音频,覆盖 **13 个语音提供商**,并在 Feishu、Matrix、Telegram 和 WhatsApp 上发送原生语音消息,在其他所有地方发送音频附件,以及为电话和 Talk 提供 PCM/Ulaw 流。
|
||||
OpenClaw 可以将外发回复转换为音频,支持 **13 个语音提供商**,
|
||||
并在 Feishu、Matrix、Telegram 和 WhatsApp 上发送原生语音消息,
|
||||
在其他所有地方发送音频附件,以及为电话和 Talk 提供 PCM/Ulaw 流。
|
||||
|
||||
## 快速开始
|
||||
|
||||
<Steps>
|
||||
<Step title="选择提供商">
|
||||
OpenAI 和 ElevenLabs 是最可靠的托管选项。Microsoft 和 Local CLI 无需 API 密钥即可使用。完整列表请参见 [提供商矩阵](#supported-providers)。
|
||||
<Step title="选择一个提供商">
|
||||
OpenAI 和 ElevenLabs 是最可靠的托管选项。Microsoft 和
|
||||
Local CLI 无需 API 密钥即可使用。完整列表请参阅[提供商矩阵](#supported-providers)。
|
||||
</Step>
|
||||
<Step title="设置 API 密钥">
|
||||
导出你的提供商所需的环境变量(例如 `OPENAI_API_KEY`、`ELEVENLABS_API_KEY`)。Microsoft 和 Local CLI 不需要密钥。
|
||||
导出你的提供商所需的环境变量(例如 `OPENAI_API_KEY`、
|
||||
`ELEVENLABS_API_KEY`)。Microsoft 和 Local CLI 不需要密钥。
|
||||
</Step>
|
||||
<Step title="在配置中启用">
|
||||
设置 `messages.tts.auto: "always"` 和 `messages.tts.provider`:
|
||||
@ -42,12 +46,14 @@ OpenClaw 可以将外发回复转换为音频,覆盖 **13 个语音提供商**
|
||||
|
||||
</Step>
|
||||
<Step title="在聊天中试用">
|
||||
`/tts status` 会显示当前状态。`/tts audio Hello from OpenClaw` 会发送一次性的音频回复。
|
||||
`/tts status` 会显示当前状态。`/tts audio Hello from OpenClaw`
|
||||
会发送一次性音频回复。
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
<Note>
|
||||
默认情况下,自动 TTS **关闭**。当未设置 `messages.tts.provider` 时,OpenClaw 会按注册表自动选择顺序挑选第一个已配置的提供商。
|
||||
自动 TTS 默认**关闭**。当 `messages.tts.provider` 未设置时,
|
||||
OpenClaw 会按照注册表自动选择顺序选择第一个已配置的提供商。
|
||||
</Note>
|
||||
|
||||
## 支持的提供商
|
||||
@ -55,29 +61,37 @@ OpenClaw 可以将外发回复转换为音频,覆盖 **13 个语音提供商**
|
||||
| 提供商 | 认证 | 说明 |
|
||||
| ----------------- | ---------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- |
|
||||
| **Azure Speech** | `AZURE_SPEECH_KEY` + `AZURE_SPEECH_REGION`(也支持 `AZURE_SPEECH_API_KEY`、`SPEECH_KEY`、`SPEECH_REGION`) | 原生 Ogg/Opus 语音便笺输出和电话支持。 |
|
||||
| **ElevenLabs** | `ELEVENLABS_API_KEY` 或 `XI_API_KEY` | 支持语音克隆、多语言,并可通过 `seed` 实现确定性输出。 |
|
||||
| **Google Gemini** | `GEMINI_API_KEY` 或 `GOOGLE_API_KEY` | Gemini API TTS;通过 `promptTemplate: "audio-profile-v1"` 支持角色语音感知。 |
|
||||
| **ElevenLabs** | `ELEVENLABS_API_KEY` 或 `XI_API_KEY` | 支持语音克隆、多语言,可通过 `seed` 实现确定性。 |
|
||||
| **Google Gemini** | `GEMINI_API_KEY` 或 `GOOGLE_API_KEY` | Gemini API TTS;通过 `promptTemplate: "audio-profile-v1"` 支持 persona。 |
|
||||
| **Gradium** | `GRADIUM_API_KEY` | 支持语音便笺和电话输出。 |
|
||||
| **Inworld** | `INWORLD_API_KEY` | 流式 TTS API。支持原生 Opus 语音便笺和 PCM 电话。 |
|
||||
| **Local CLI** | 无 | 运行已配置的本地 TTS 命令。 |
|
||||
| **Microsoft** | 无 | 通过 `node-edge-tts` 使用公开的 Edge 神经网络 TTS。尽力而为,不提供 SLA。 |
|
||||
| **Inworld** | `INWORLD_API_KEY` | 流式 TTS API。原生 Opus 语音便笺和 PCM 电话支持。 |
|
||||
| **Local CLI** | none | 运行已配置的本地 TTS 命令。 |
|
||||
| **Microsoft** | none | 通过 `node-edge-tts` 使用公开的 Edge neural TTS。尽力而为,无 SLA。 |
|
||||
| **MiniMax** | `MINIMAX_API_KEY`(或 Token Plan:`MINIMAX_OAUTH_TOKEN`、`MINIMAX_CODE_PLAN_KEY`、`MINIMAX_CODING_API_KEY`) | T2A v2 API。默认使用 `speech-2.8-hd`。 |
|
||||
| **OpenAI** | `OPENAI_API_KEY` | 也用于自动摘要;支持角色语音 `instructions`。 |
|
||||
| **OpenAI** | `OPENAI_API_KEY` | 也用于自动摘要;支持 persona `instructions`。 |
|
||||
| **OpenRouter** | `OPENROUTER_API_KEY`(可复用 `models.providers.openrouter.apiKey`) | 默认模型为 `hexgrad/kokoro-82m`。 |
|
||||
| **Volcengine** | `VOLCENGINE_TTS_API_KEY` 或 `BYTEPLUS_SEED_SPEECH_API_KEY`(旧版 AppID/token:`VOLCENGINE_TTS_APPID`/`_TOKEN`) | BytePlus Seed Speech HTTP API。 |
|
||||
| **Vydra** | `VYDRA_API_KEY` | 共享的图像、视频和语音提供商。 |
|
||||
| **xAI** | `XAI_API_KEY` | xAI 批量 TTS。不支持原生 Opus 语音便笺。 |
|
||||
| **Xiaomi MiMo** | `XIAOMI_API_KEY` | 通过 Xiaomi 聊天补全实现的 MiMo TTS。 |
|
||||
| **Volcengine** | `VOLCENGINE_TTS_API_KEY` 或 `BYTEPLUS_SEED_SPEECH_API_KEY`(旧版 AppID/token:`VOLCENGINE_TTS_APPID`/`_TOKEN`) | BytePlus(国际版) Seed Speech HTTP API。 |
|
||||
| **Vydra** | `VYDRA_API_KEY` | 共享图像、视频和语音提供商。 |
|
||||
| **xAI** | `XAI_API_KEY` | xAI 批量 TTS。**不**支持原生 Opus 语音便笺。 |
|
||||
| **Xiaomi MiMo** | `XIAOMI_API_KEY` | 通过 Xiaomi 聊天补全实现 MiMo TTS。 |
|
||||
|
||||
如果配置了多个提供商,则会优先使用选中的提供商,其他提供商作为回退选项。自动摘要使用 `summaryModel`(或 `agents.defaults.model.primary`),因此如果你保留摘要启用状态,对应提供商也必须完成认证。
|
||||
如果配置了多个提供商,则会优先使用已选中的那个,
|
||||
其他提供商作为回退选项。自动摘要使用 `summaryModel`(或
|
||||
`agents.defaults.model.primary`),因此如果你保持摘要启用,
|
||||
该提供商也必须已通过认证。
|
||||
|
||||
<Warning>
|
||||
内置的 **Microsoft** 提供商通过 `node-edge-tts` 使用 Microsoft Edge 的在线神经网络 TTS 服务。它是公开的 Web 服务,没有已发布的 SLA 或配额——请将其视为尽力而为的服务。旧版提供商 id `edge` 会被规范化为 `microsoft`,并且 `openclaw doctor --fix` 会重写持久化配置;新配置应始终使用 `microsoft`。
|
||||
内置的 **Microsoft** provider 通过 `node-edge-tts` 使用 Microsoft Edge 的在线 neural TTS
|
||||
服务。这是一个公开的 Web 服务,没有公布的
|
||||
SLA 或配额 —— 请将其视为尽力而为。旧版 provider id `edge` 会被
|
||||
规范化为 `microsoft`,而且 `openclaw doctor --fix` 会重写已持久化的
|
||||
配置;新配置应始终使用 `microsoft`。
|
||||
</Warning>
|
||||
|
||||
## 配置
|
||||
|
||||
TTS 配置位于 `~/.openclaw/openclaw.json` 的 `messages.tts` 下。选择一个预设,并调整对应的提供商配置块:
|
||||
TTS 配置位于 `~/.openclaw/openclaw.json` 的 `messages.tts` 下。选择一个
|
||||
预设并调整 provider 块:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Azure Speech">
|
||||
@ -133,7 +147,7 @@ TTS 配置位于 `~/.openclaw/openclaw.json` 的 `messages.tts` 下。选择一
|
||||
apiKey: "${GEMINI_API_KEY}",
|
||||
model: "gemini-3.1-flash-tts-preview",
|
||||
voiceName: "Kore",
|
||||
// 可选的自然语言风格提示:
|
||||
// Optional natural-language style prompts:
|
||||
// audioProfile: "Speak in a calm, podcast-host tone.",
|
||||
// speakerName: "Alex",
|
||||
},
|
||||
@ -201,7 +215,7 @@ TTS 配置位于 `~/.openclaw/openclaw.json` 的 `messages.tts` 下。选择一
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Microsoft(无密钥)">
|
||||
<Tab title="Microsoft (no key)">
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
@ -355,9 +369,11 @@ TTS 配置位于 `~/.openclaw/openclaw.json` 的 `messages.tts` 下。选择一
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### 按智能体覆盖语音设置
|
||||
### 按智能体覆盖语音
|
||||
|
||||
当某个智能体需要使用不同的提供商、语音、模型、角色语音或自动 TTS 模式时,请使用 `agents.list[].tts`。该智能体配置块会在 `messages.tts` 之上进行深度合并,因此提供商凭证可以保留在全局提供商配置中:
|
||||
当某个智能体需要使用不同的 provider、
|
||||
voice、model、persona 或自动 TTS 模式时,请使用 `agents.list[].tts`。智能体块会在
|
||||
`messages.tts` 之上执行深度合并,因此 provider 凭证可以保留在全局 provider 配置中:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -385,20 +401,58 @@ TTS 配置位于 `~/.openclaw/openclaw.json` 的 `messages.tts` 下。选择一
|
||||
}
|
||||
```
|
||||
|
||||
要固定某个智能体的角色语音,请在提供商配置旁设置 `agents.list[].tts.persona` —— 它只会覆盖该智能体的全局 `messages.tts.persona`。
|
||||
要固定某个智能体的 persona,请在 provider
|
||||
配置旁设置 `agents.list[].tts.persona` —— 它只会覆盖该智能体的全局 `messages.tts.persona`。
|
||||
|
||||
自动回复、`/tts audio`、`/tts status` 以及 `tts` 智能体工具的优先级顺序如下:
|
||||
自动回复、`/tts audio`、`/tts status` 以及
|
||||
`tts` 智能体工具的优先级顺序如下:
|
||||
|
||||
1. `messages.tts`
|
||||
2. 当前激活的 `agents.list[].tts`
|
||||
3. 此主机上的本地 `/tts` 偏好设置
|
||||
4. 启用[模型覆盖](#model-driven-directives)时的内联 `[[tts:...]]` 指令
|
||||
3. 渠道覆盖(当该渠道支持 `channels.<channel>.tts` 时)
|
||||
4. 账号覆盖(当渠道传入 `channels.<channel>.accounts.<id>.tts` 时)
|
||||
5. 当前主机的本地 `/tts` 偏好设置
|
||||
6. 启用[模型覆盖](#model-driven-directives)时的内联 `[[tts:...]]` 指令
|
||||
|
||||
## 角色语音
|
||||
渠道和账号覆盖使用与 `messages.tts` 相同的结构,并在更早的层之上执行
|
||||
深度合并,因此共享的 provider 凭证可以保留在
|
||||
`messages.tts` 中,而某个渠道或 bot 账号只更改 voice、model、persona
|
||||
或自动模式:
|
||||
|
||||
**persona** 是一种稳定的语音身份,可在不同提供商之间以确定性的方式应用。它可以优先选择某个提供商、定义与提供商无关的提示意图,并携带针对特定提供商的语音、模型、提示模板、种子和语音设置绑定。
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
tts: {
|
||||
provider: "openai",
|
||||
providers: {
|
||||
openai: { apiKey: "${OPENAI_API_KEY}", model: "gpt-4o-mini-tts" },
|
||||
},
|
||||
},
|
||||
},
|
||||
channels: {
|
||||
feishu: {
|
||||
accounts: {
|
||||
english: {
|
||||
tts: {
|
||||
providers: {
|
||||
openai: { voice: "shimmer" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 最小角色语音
|
||||
## Personas
|
||||
|
||||
**persona** 是一种稳定的语音身份,可以在不同 provider 之间以确定性的方式
|
||||
应用。它可以偏好某个 provider,定义与 provider 无关的提示意图,
|
||||
并携带与 provider 相关的 voice、model、提示模板、
|
||||
seed 和语音设置绑定。
|
||||
|
||||
### 最小 persona
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -408,7 +462,7 @@ TTS 配置位于 `~/.openclaw/openclaw.json` 的 `messages.tts` 下。选择一
|
||||
persona: "narrator",
|
||||
personas: {
|
||||
narrator: {
|
||||
label: "Narrator",
|
||||
label: "旁白",
|
||||
provider: "elevenlabs",
|
||||
providers: {
|
||||
elevenlabs: { voiceId: "EXAVITQu4vr4xnSDxMaL", modelId: "eleven_multilingual_v2" },
|
||||
@ -420,7 +474,7 @@ TTS 配置位于 `~/.openclaw/openclaw.json` 的 `messages.tts` 下。选择一
|
||||
}
|
||||
```
|
||||
|
||||
### 完整角色语音(与提供商无关的提示)
|
||||
### 完整 persona(与 provider 无关的提示)
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -431,17 +485,17 @@ TTS 配置位于 `~/.openclaw/openclaw.json` 的 `messages.tts` 下。选择一
|
||||
personas: {
|
||||
alfred: {
|
||||
label: "Alfred",
|
||||
description: "Dry, warm British butler narrator.",
|
||||
description: "冷淡、温暖的英式管家旁白。",
|
||||
provider: "google",
|
||||
fallbackPolicy: "preserve-persona",
|
||||
prompt: {
|
||||
profile: "A brilliant British butler. Dry, witty, warm, charming, emotionally expressive, never generic.",
|
||||
scene: "A quiet late-night study. Close-mic narration for a trusted operator.",
|
||||
sampleContext: "The speaker is answering a private technical request with concise confidence and dry warmth.",
|
||||
style: "Refined, understated, lightly amused.",
|
||||
accent: "British English.",
|
||||
pacing: "Measured, with short dramatic pauses.",
|
||||
constraints: ["Do not read configuration values aloud.", "Do not explain the persona."],
|
||||
profile: "一位才华横溢的英国管家。冷幽默、机智、温暖、迷人、富有情感表达力,绝不显得平庸。",
|
||||
scene: "安静的深夜书房。为受信任的操作员进行近距离麦克风旁白。",
|
||||
sampleContext: "说话者正在以简洁的自信和冷静的温暖回应一个私人技术请求。",
|
||||
style: "精致、克制、略带 amused。",
|
||||
accent: "英式英语。",
|
||||
pacing: "节奏从容,带有短暂的戏剧性停顿。",
|
||||
constraints: ["不要大声读出配置值。", "不要解释这个 persona。"],
|
||||
},
|
||||
providers: {
|
||||
google: {
|
||||
@ -470,60 +524,74 @@ TTS 配置位于 `~/.openclaw/openclaw.json` 的 `messages.tts` 下。选择一
|
||||
}
|
||||
```
|
||||
|
||||
### 角色语音解析
|
||||
### Persona 解析
|
||||
|
||||
当前激活的角色语音会按确定性顺序选择:
|
||||
当前 persona 会按确定性方式选择:
|
||||
|
||||
1. `/tts persona <id>` 本地偏好设置(如果已设置)。
|
||||
2. `messages.tts.persona`(如果已设置)。
|
||||
3. 不使用角色语音。
|
||||
1. 如果设置了,则使用 `/tts persona <id>` 本地偏好。
|
||||
2. 如果设置了,则使用 `messages.tts.persona`。
|
||||
3. 否则不使用 persona。
|
||||
|
||||
提供商选择按“显式优先”的顺序进行:
|
||||
Provider 选择按“显式优先”运行:
|
||||
|
||||
1. 直接覆盖项(CLI、Gateway 网关、Talk、允许的 TTS 指令)。
|
||||
2. `/tts provider <id>` 本地偏好设置。
|
||||
3. 当前角色语音的 `provider`。
|
||||
1. 直接覆盖(CLI、Gateway 网关、Talk、允许的 TTS 指令)。
|
||||
2. `/tts provider <id>` 本地偏好。
|
||||
3. 当前 persona 的 `provider`。
|
||||
4. `messages.tts.provider`。
|
||||
5. 注册表自动选择。
|
||||
|
||||
对于每次提供商尝试,OpenClaw 会按以下顺序合并配置:
|
||||
对于每次 provider 尝试,OpenClaw 会按以下顺序合并配置:
|
||||
|
||||
1. `messages.tts.providers.<id>`
|
||||
2. `messages.tts.personas.<persona>.providers.<id>`
|
||||
3. 受信任的请求覆盖项
|
||||
4. 允许的模型发出的 TTS 指令覆盖项
|
||||
3. 受信任请求覆盖
|
||||
4. 允许的模型发出的 TTS 指令覆盖
|
||||
|
||||
### 提供商如何使用角色语音提示
|
||||
### Provider 如何使用 persona 提示
|
||||
|
||||
角色语音提示字段(`profile`、`scene`、`sampleContext`、`style`、`accent`、`pacing`、`constraints`)是**与提供商无关的**。每个提供商会自行决定如何使用它们:
|
||||
Persona 提示字段(`profile`、`scene`、`sampleContext`、`style`、`accent`、
|
||||
`pacing`、`constraints`)都是**与 provider 无关的**。每个 provider 会自行决定
|
||||
如何使用它们:
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Google Gemini">
|
||||
仅当实际生效的 Google 提供商配置设置了 `promptTemplate: "audio-profile-v1"` 或 `personaPrompt` 时,才会将角色语音提示字段包装进 Gemini TTS 提示结构中。较旧的 `audioProfile` 和 `speakerName` 字段仍会作为 Google 特定的提示文本预置到前面。在 `[[tts:text]]` 块中的内联音频标签(例如 `[whispers]` 或 `[laughs]`)会保留在 Gemini 转录文本中;OpenClaw 不会生成这些标签。
|
||||
仅当有效的 Google provider 配置设置了 `promptTemplate: "audio-profile-v1"`
|
||||
或 `personaPrompt` 时,才会将 persona 提示字段包装成 Gemini TTS 提示结构。
|
||||
较旧的 `audioProfile` 和 `speakerName` 字段仍会
|
||||
作为 Google 专用提示文本预先附加。像
|
||||
`[whispers]` 或 `[laughs]` 这样的内联音频标签,如果位于 `[[tts:text]]` 块中,
|
||||
会保留在 Gemini 转录里;OpenClaw 不会生成这些标签。
|
||||
</Accordion>
|
||||
<Accordion title="OpenAI">
|
||||
仅当未显式配置 OpenAI `instructions` 时,才会将角色语音提示字段映射到请求的 `instructions` 字段。显式的 `instructions` 始终优先。
|
||||
仅当未显式配置 OpenAI `instructions` 时,
|
||||
才会将 persona 提示字段映射到请求的 `instructions` 字段。
|
||||
显式 `instructions` 始终优先。
|
||||
</Accordion>
|
||||
<Accordion title="其他提供商">
|
||||
仅使用 `personas.<id>.providers.<provider>` 下特定于提供商的角色语音绑定。除非该提供商自行实现了角色语音提示映射,否则角色语音提示字段会被忽略。
|
||||
<Accordion title="其他 provider">
|
||||
仅使用 `personas.<id>.providers.<provider>` 下
|
||||
与 provider 相关的 persona 绑定。除非 provider 自己实现了 persona 提示映射,
|
||||
否则会忽略 persona 提示字段。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### 回退策略
|
||||
|
||||
当某个角色语音对正在尝试的提供商**没有绑定**时,`fallbackPolicy` 控制其行为:
|
||||
`fallbackPolicy` 用于控制当 persona 对被尝试的 provider **没有绑定**时的行为:
|
||||
|
||||
| 策略 | 行为 |
|
||||
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `preserve-persona` | **默认。** 与提供商无关的提示字段会继续可用;提供商可以使用它们,也可以忽略它们。 |
|
||||
| `provider-defaults` | 在本次尝试的提示准备过程中省略角色语音;提供商使用其中性的默认值,同时继续回退到其他提供商。 |
|
||||
| `fail` | 跳过该提供商尝试,并设置 `reasonCode: "not_configured"` 和 `personaBinding: "missing"`。仍会继续尝试回退提供商。 |
|
||||
| `preserve-persona` | **默认值。** 与 provider 无关的提示字段仍然可用;provider 可以使用它们,也可以忽略它们。 |
|
||||
| `provider-defaults` | 在该次尝试的提示准备中省略 persona;provider 使用其中性默认值,同时继续回退到其他 provider。 |
|
||||
| `fail` | 以 `reasonCode: "not_configured"` 和 `personaBinding: "missing"` 跳过该 provider 尝试。仍然会继续尝试回退 provider。 |
|
||||
|
||||
只有当**所有**尝试过的提供商都被跳过或失败时,整个 TTS 请求才会失败。
|
||||
只有当**每个**被尝试的 provider 都被跳过
|
||||
或失败时,整个 TTS 请求才会失败。
|
||||
|
||||
## 模型驱动指令
|
||||
|
||||
默认情况下,助手**可以**发出 `[[tts:...]]` 指令,以覆盖单条回复的语音、模型或速度,还可以附带一个可选的 `[[tts:text]]...[[/tts:text]]` 块,用于只应出现在音频中的表现性提示:
|
||||
默认情况下,助手**可以**发出 `[[tts:...]]` 指令来为单次回复覆盖
|
||||
voice、model 或 speed,并且还可以附带一个可选的
|
||||
`[[tts:text]]...[[/tts:text]]` 块,用于只应出现在音频中的表现性提示:
|
||||
|
||||
```text
|
||||
Here you go.
|
||||
@ -532,19 +600,23 @@ Here you go.
|
||||
[[tts:text]](laughs) Read the song once more.[[/tts:text]]
|
||||
```
|
||||
|
||||
当 `messages.tts.auto` 为 `"tagged"` 时,**必须使用指令**才能触发音频。即使这些指令拆分在相邻的多个块中,流式分块传输也会在渠道看到文本之前将指令从可见文本中剥离。
|
||||
当 `messages.tts.auto` 为 `"tagged"` 时,**必须使用指令**才会触发
|
||||
音频。分块流式传输在渠道看到内容之前会将指令从可见文本中移除,即使它们被拆分在相邻的块中也是如此。
|
||||
|
||||
除非设置了 `modelOverrides.allowProvider: true`,否则 `provider=...` 会被忽略。当回复声明了 `provider=...` 时,该指令中的其他键只会由该提供商解析;不受支持的键会被剥离,并作为 TTS 指令警告报告。
|
||||
除非设置 `modelOverrides.allowProvider: true`,否则 `provider=...` 会被忽略。当某个
|
||||
回复声明 `provider=...` 时,该指令中的其他键仅会由该 provider 解析;
|
||||
不受支持的键会被移除,并报告为 TTS
|
||||
指令警告。
|
||||
|
||||
**可用的指令键:**
|
||||
|
||||
- `provider`(已注册的提供商 id;需要 `allowProvider: true`)
|
||||
- `provider`(已注册 provider id;需要 `allowProvider: true`)
|
||||
- `voice` / `voiceName` / `voice_name` / `google_voice` / `voiceId`
|
||||
- `model` / `google_model`
|
||||
- `stability`、`similarityBoost`、`style`、`speed`、`useSpeakerBoost`
|
||||
- `vol` / `volume`(MiniMax 音量,0–10)
|
||||
- `pitch`(MiniMax 整数音高,−12 到 12;小数值会被截断)
|
||||
- `emotion`(Volcengine 情绪标签)
|
||||
- `emotion`(Volcengine 情感标签)
|
||||
- `applyTextNormalization`(`auto|on|off`)
|
||||
- `languageCode`(ISO 639-1)
|
||||
- `seed`
|
||||
@ -555,7 +627,7 @@ Here you go.
|
||||
{ messages: { tts: { modelOverrides: { enabled: false } } } }
|
||||
```
|
||||
|
||||
**允许切换提供商,同时保持其他调节项可配置:**
|
||||
**允许切换 provider,同时保持其他旋钮可配置:**
|
||||
|
||||
```json5
|
||||
{ messages: { tts: { modelOverrides: { enabled: true, allowProvider: true, allowSeed: false } } } }
|
||||
@ -563,7 +635,8 @@ Here you go.
|
||||
|
||||
## 斜杠命令
|
||||
|
||||
使用单一命令 `/tts`。在 Discord 上,OpenClaw 还会注册 `/voice`,因为 `/tts` 是 Discord 的内置命令——文本形式的 `/tts ...` 仍然可用。
|
||||
单个命令 `/tts`。在 Discord 上,OpenClaw 还会注册 `/voice`,因为
|
||||
`/tts` 是 Discord 的内置命令 —— 文本 `/tts ...` 仍然可用。
|
||||
|
||||
```text
|
||||
/tts off | on | status
|
||||
@ -577,70 +650,88 @@ Here you go.
|
||||
```
|
||||
|
||||
<Note>
|
||||
这些命令要求发送者已获授权(适用 allowlist/owner 规则),并且必须启用 `commands.text` 或原生命令注册。
|
||||
命令要求发送者已获授权(适用 allowlist/所有者规则),并且必须启用
|
||||
`commands.text` 或原生命令注册。
|
||||
</Note>
|
||||
|
||||
行为说明:
|
||||
|
||||
- `/tts on` 会将本地 TTS 偏好写为 `always`;`/tts off` 会将其写为 `off`。
|
||||
- `/tts chat on|off|default` 会为当前聊天写入一个作用域为会话的自动 TTS 覆盖项。
|
||||
- `/tts persona <id>` 会写入本地角色语音偏好;`/tts persona off` 会清除此偏好。
|
||||
- `/tts latest` 会从当前会话转录中读取最新的助手回复,并将其作为一次性音频发送。它只会在会话条目中存储该回复的哈希值,以防止重复发送语音。
|
||||
- `/tts audio` 会生成一次性的音频回复(**不会**开启 TTS)。
|
||||
- `limit` 和 `summary` 存储在**本地偏好设置**中,而不是主配置里。
|
||||
- `/tts status` 包含最近一次尝试的回退诊断信息——`Fallback: <primary> -> <used>`、`Attempts: ...`,以及每次尝试的详细信息(`provider:outcome(reasonCode) latency`)。
|
||||
- `/status` 会在启用 TTS 时显示当前激活的 TTS 模式,以及已配置的提供商、模型、语音和已脱敏的自定义端点元数据。
|
||||
- `/tts on` 会将本地 TTS 偏好写为 `always`;`/tts off` 会写为 `off`。
|
||||
- `/tts chat on|off|default` 会为当前聊天写入一个会话作用域的自动 TTS 覆盖。
|
||||
- `/tts persona <id>` 会写入本地 persona 偏好;`/tts persona off` 会清除它。
|
||||
- `/tts latest` 会从当前会话转录中读取最新的助手回复,并将其作为音频发送一次。它只会在会话条目上存储该回复的哈希,以抑制重复发送语音。
|
||||
- `/tts audio` 会生成一次性音频回复(**不会**切换 TTS 为开启)。
|
||||
- `limit` 和 `summary` 存储在**本地偏好**中,而不是主配置里。
|
||||
- `/tts status` 包含最近一次尝试的回退诊断 —— `Fallback: <primary> -> <used>`、`Attempts: ...`,以及每次尝试的详细信息(`provider:outcome(reasonCode) latency`)。
|
||||
- `/status` 会在启用 TTS 时显示当前 TTS 模式,以及已配置的 provider、model、voice 和已净化的自定义端点元数据。
|
||||
|
||||
## 按用户区分的偏好设置
|
||||
## 按用户偏好
|
||||
|
||||
斜杠命令会将本地覆盖项写入 `prefsPath`。默认值为 `~/.openclaw/settings/tts.json`;你也可以通过 `OPENCLAW_TTS_PREFS` 环境变量或 `messages.tts.prefsPath` 进行覆盖。
|
||||
斜杠命令会将本地覆盖写入 `prefsPath`。默认路径是
|
||||
`~/.openclaw/settings/tts.json`;可以通过 `OPENCLAW_TTS_PREFS` 环境变量
|
||||
或 `messages.tts.prefsPath` 覆盖。
|
||||
|
||||
| 存储字段 | 作用 |
|
||||
| 存储字段 | 效果 |
|
||||
| ------------ | -------------------------------------------- |
|
||||
| `auto` | 本地自动 TTS 覆盖项(`always`、`off`、…) |
|
||||
| `provider` | 本地主提供商覆盖项 |
|
||||
| `persona` | 本地角色语音覆盖项 |
|
||||
| `auto` | 本地自动 TTS 覆盖(`always`、`off`、…) |
|
||||
| `provider` | 本地主 provider 覆盖 |
|
||||
| `persona` | 本地 persona 覆盖 |
|
||||
| `maxLength` | 摘要阈值(默认 `1500` 个字符) |
|
||||
| `summarize` | 摘要开关(默认 `true`) |
|
||||
|
||||
这些字段会覆盖该主机上由 `messages.tts` 加上当前激活的 `agents.list[].tts` 配置块所形成的实际配置。
|
||||
这些设置会覆盖当前主机上来自 `messages.tts` 加活动
|
||||
`agents.list[].tts` 块的有效配置。
|
||||
|
||||
## 输出格式(固定)
|
||||
|
||||
TTS 语音传递由渠道能力驱动。渠道插件会声明,语音样式的 TTS 是否应请求提供商生成原生 `voice-note` 目标,还是保持普通的 `audio-file` 合成路径,仅将兼容的输出标记为语音传递。
|
||||
TTS 语音投递由渠道能力驱动。渠道插件会声明
|
||||
语音风格 TTS 是应要求 provider 输出原生 `voice-note` 目标,
|
||||
还是保持常规 `audio-file` 合成,并仅将兼容输出标记为可用于语音投递。
|
||||
|
||||
- **支持语音便笺的渠道**:语音便笺回复优先使用 Opus(ElevenLabs 的 `opus_48000_64`,OpenAI 的 `opus`)。
|
||||
- 48 kHz / 64 kbps 是语音消息的良好折中方案。
|
||||
- **Feishu / WhatsApp**:当语音便笺回复以 MP3/WebM/WAV/M4A 或其他常见音频文件格式生成时,渠道插件会先通过 `ffmpeg` 将其转码为 48 kHz Ogg/Opus,再发送原生语音消息。WhatsApp 会通过带有 `ptt: true` 和 `audio/ogg; codecs=opus` 的 Baileys `audio` 负载发送结果。如果转换失败,Feishu 会收到原始文件作为附件;而 WhatsApp 发送会失败,而不是发布不兼容的 PTT 负载。
|
||||
- **BlueBubbles**:保持提供商合成走普通音频文件路径;MP3 和 CAF 输出会被标记为用于 iMessage 语音备忘录投递。
|
||||
- **其他渠道**:使用 MP3(ElevenLabs 的 `mp3_44100_128`,OpenAI 的 `mp3`)。
|
||||
- 48 kHz / 64 kbps 是语音消息在质量与体积之间的良好平衡。
|
||||
- **Feishu / WhatsApp**:当语音便笺回复生成为 MP3/WebM/WAV/M4A
|
||||
或其他可能的音频文件时,渠道插件会在发送原生语音消息之前,
|
||||
使用 `ffmpeg` 将其转码为 48 kHz
|
||||
Ogg/Opus。WhatsApp 会通过 Baileys 的 `audio` 负载发送结果,并带上 `ptt: true` 和
|
||||
`audio/ogg; codecs=opus`。如果转换失败,Feishu 会将原文件作为附件接收;WhatsApp 发送会失败,而不是发布不兼容的
|
||||
PTT 负载。
|
||||
- **BlueBubbles**:保持 provider 合成走常规 audio-file 路径;MP3
|
||||
和 CAF 输出会被标记为用于 iMessage 语音备忘录投递。
|
||||
- **其他渠道**:MP3(ElevenLabs 的 `mp3_44100_128`,OpenAI 的 `mp3`)。
|
||||
- 44.1 kHz / 128 kbps 是语音清晰度的默认平衡点。
|
||||
- **MiniMax**:普通音频附件使用 MP3(`speech-2.8-hd` 模型,32 kHz 采样率)。对于渠道声明的语音便笺目标,当渠道声明支持转码时,OpenClaw 会在投递前通过 `ffmpeg` 将 MiniMax MP3 转码为 48 kHz Opus。
|
||||
- **Xiaomi MiMo**:默认使用 MP3,或在配置时使用 WAV。对于渠道声明的语音便笺目标,当渠道声明支持转码时,OpenClaw 会在投递前通过 `ffmpeg` 将 Xiaomi 输出转码为 48 kHz Opus。
|
||||
- **Local CLI**:使用已配置的 `outputFormat`。语音便笺目标会被转换为 Ogg/Opus,电话输出会通过 `ffmpeg` 转换为原始 16 kHz 单声道 PCM。
|
||||
- **Google Gemini**:Gemini API TTS 返回原始 24 kHz PCM。OpenClaw 会将其封装为 WAV 作为音频附件,将其转码为 48 kHz Opus 用于语音便笺目标,并为 Talk/电话直接返回 PCM。
|
||||
- **MiniMax**:常规音频附件使用 MP3(`speech-2.8-hd` 模型,32 kHz 采样率)。对于渠道声明的语音便笺目标,当渠道声明支持转码时,OpenClaw 会在投递前使用 `ffmpeg` 将 MiniMax MP3 转码为 48 kHz Opus。
|
||||
- **Xiaomi MiMo**:默认使用 MP3,或在配置时使用 WAV。对于渠道声明的语音便笺目标,当渠道声明支持转码时,OpenClaw 会在投递前使用 `ffmpeg` 将 Xiaomi 输出转码为 48 kHz Opus。
|
||||
- **Local CLI**:使用已配置的 `outputFormat`。语音便笺目标
|
||||
会被转换为 Ogg/Opus,电话输出会被转换为原始 16 kHz 单声道 PCM,
|
||||
使用 `ffmpeg` 完成。
|
||||
- **Google Gemini**:Gemini API TTS 返回原始 24 kHz PCM。OpenClaw 会将其封装为 WAV 用于音频附件,将其转码为 48 kHz Opus 用于语音便笺目标,并为 Talk/电话直接返回 PCM。
|
||||
- **Gradium**:音频附件使用 WAV,语音便笺目标使用 Opus,电话使用 8 kHz 的 `ulaw_8000`。
|
||||
- **Inworld**:普通音频附件使用 MP3,语音便笺目标使用原生 `OGG_OPUS`,Talk/电话使用 22050 Hz 的原始 `PCM`。
|
||||
- **xAI**:默认使用 MP3;`responseFormat` 可以是 `mp3`、`wav`、`pcm`、`mulaw` 或 `alaw`。OpenClaw 使用 xAI 的批处理 REST TTS 端点并返回完整的音频附件;此提供商路径不使用 xAI 的流式 TTS WebSocket。此路径不支持原生 Opus 语音便笺格式。
|
||||
- **Microsoft**:使用 `microsoft.outputFormat`(默认值为 `audio-24khz-48kbitrate-mono-mp3`)。
|
||||
- 内置传输层接受 `outputFormat`,但服务并不一定提供所有格式。
|
||||
- **Inworld**:常规音频附件使用 MP3,语音便笺目标使用原生 `OGG_OPUS`,Talk/电话使用 22050 Hz 的原始 `PCM`。
|
||||
- **xAI**:默认使用 MP3;`responseFormat` 可以是 `mp3`、`wav`、`pcm`、`mulaw` 或 `alaw`。OpenClaw 使用 xAI 的批量 REST TTS 端点并返回完整音频附件;此 provider 路径不使用 xAI 的流式 TTS WebSocket。不支持原生 Opus 语音便笺格式。
|
||||
- **Microsoft**:使用 `microsoft.outputFormat`(默认 `audio-24khz-48kbitrate-mono-mp3`)。
|
||||
- 内置传输接受 `outputFormat`,但服务并不提供所有格式。
|
||||
- 输出格式值遵循 Microsoft Speech 输出格式(包括 Ogg/WebM Opus)。
|
||||
- Telegram `sendVoice` 接受 OGG/MP3/M4A;如果你需要有保障的 Opus 语音消息,请使用 OpenAI/ElevenLabs。
|
||||
- 如果配置的 Microsoft 输出格式失败,OpenClaw 会回退重试 MP3。
|
||||
- Telegram `sendVoice` 接受 OGG/MP3/M4A;如果你需要
|
||||
保证使用 Opus 语音消息,请使用 OpenAI/ElevenLabs。
|
||||
- 如果已配置的 Microsoft 输出格式失败,OpenClaw 会回退重试 MP3。
|
||||
|
||||
OpenAI/ElevenLabs 的输出格式按渠道固定(见上文)。
|
||||
OpenAI/ElevenLabs 输出格式按渠道固定(见上文)。
|
||||
|
||||
## 自动 TTS 行为
|
||||
|
||||
启用 `messages.tts.auto` 后,OpenClaw 会:
|
||||
当启用 `messages.tts.auto` 时,OpenClaw 会:
|
||||
|
||||
- 如果回复已包含媒体或 `MEDIA:` 指令,则跳过 TTS。
|
||||
- 跳过非常短的回复(少于 10 个字符)。
|
||||
- 当启用摘要时,使用 `summaryModel`(或 `agents.defaults.model.primary`)对长回复生成摘要。
|
||||
- 当启用摘要时,使用
|
||||
`summaryModel`(或 `agents.defaults.model.primary`)对长回复进行摘要。
|
||||
- 将生成的音频附加到回复中。
|
||||
- 在 `mode: "final"` 下,流式最终回复在文本流完成后,仍会发送仅音频的 TTS;生成的媒体会经过与普通回复附件相同的渠道媒体规范化流程。
|
||||
- 在 `mode: "final"` 下,对于流式最终回复,仍会在文本流完成后发送仅音频 TTS;
|
||||
生成的媒体会经过与常规回复附件相同的渠道媒体规范化流程。
|
||||
|
||||
如果回复超过 `maxLength`,且摘要关闭(或摘要模型没有 API 密钥),则会跳过音频,仅发送普通文本回复。
|
||||
如果回复超过 `maxLength` 且摘要关闭(或摘要模型没有 API 密钥),
|
||||
则会跳过音频,并发送常规文本回复。
|
||||
|
||||
```text
|
||||
Reply -> TTS enabled?
|
||||
@ -654,23 +745,23 @@ Reply -> TTS enabled?
|
||||
yes -> summarize -> TTS -> attach audio
|
||||
```
|
||||
|
||||
## 按渠道区分的输出格式
|
||||
## 按渠道划分的输出格式
|
||||
|
||||
| 目标 | 格式 |
|
||||
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Feishu / Matrix / Telegram / WhatsApp | 语音便笺回复优先使用 **Opus**(ElevenLabs 使用 `opus_48000_64`,OpenAI 使用 `opus`)。48 kHz / 64 kbps 在清晰度和体积之间取得平衡。 |
|
||||
| 其他渠道 | **MP3**(ElevenLabs 使用 `mp3_44100_128`,OpenAI 使用 `mp3`)。44.1 kHz / 128 kbps 是语音的默认配置。 |
|
||||
| Talk / 电话 | 提供商原生 **PCM**(Inworld 为 22050 Hz,Google 为 24 kHz),或电话场景使用 Gradium 的 `ulaw_8000`。 |
|
||||
| Feishu / Matrix / Telegram / WhatsApp | 语音便笺回复优先使用 **Opus**(ElevenLabs 的 `opus_48000_64`,OpenAI 的 `opus`)。48 kHz / 64 kbps 在清晰度和体积之间取得平衡。 |
|
||||
| 其他渠道 | **MP3**(ElevenLabs 的 `mp3_44100_128`,OpenAI 的 `mp3`)。44.1 kHz / 128 kbps 是语音的默认配置。 |
|
||||
| Talk / 电话 | provider 原生 **PCM**(Inworld 22050 Hz、Google 24 kHz),或用于电话的 Gradium `ulaw_8000`。 |
|
||||
|
||||
各提供商说明:
|
||||
各 provider 说明:
|
||||
|
||||
- **Feishu / WhatsApp 转码:** 当语音便笺回复以 MP3/WebM/WAV/M4A 形式生成时,渠道插件会使用 `ffmpeg` 将其转码为 48 kHz Ogg/Opus。WhatsApp 通过带有 `ptt: true` 和 `audio/ogg; codecs=opus` 的 Baileys 发送。如果转换失败:Feishu 会回退为附加原始文件;WhatsApp 发送会失败,而不会发布不兼容的 PTT 负载。
|
||||
- **MiniMax / Xiaomi MiMo:** 默认使用 MP3(MiniMax `speech-2.8-hd` 为 32 kHz);对于语音便笺目标,会通过 `ffmpeg` 转码为 48 kHz Opus。
|
||||
- **Local CLI:** 使用已配置的 `outputFormat`。语音便笺目标会转换为 Ogg/Opus,电话输出会转换为原始 16 kHz 单声道 PCM。
|
||||
- **Google Gemini:** 返回原始 24 kHz PCM。OpenClaw 会将其封装为 WAV 作为附件,对语音便笺目标转码为 48 kHz Opus,并为 Talk/电话直接返回 PCM。
|
||||
- **Inworld:** MP3 附件、原生 `OGG_OPUS` 语音便笺、用于 Talk/电话的原始 `PCM` 22050 Hz。
|
||||
- **xAI:** 默认使用 MP3;`responseFormat` 可以是 `mp3|wav|pcm|mulaw|alaw`。使用 xAI 的批处理 REST 端点——**不**使用流式 WebSocket TTS。**不**支持原生 Opus 语音便笺格式。
|
||||
- **Microsoft:** 使用 `microsoft.outputFormat`(默认 `audio-24khz-48kbitrate-mono-mp3`)。Telegram `sendVoice` 接受 OGG/MP3/M4A;如果你需要可保证的 Opus 语音消息,请使用 OpenAI/ElevenLabs。如果配置的 Microsoft 格式失败,OpenClaw 会回退重试 MP3。
|
||||
- **Feishu / WhatsApp 转码:** 当语音便笺回复生成为 MP3/WebM/WAV/M4A 时,渠道插件会使用 `ffmpeg` 将其转码为 48 kHz Ogg/Opus。WhatsApp 会通过 Baileys 发送,并带上 `ptt: true` 和 `audio/ogg; codecs=opus`。如果转换失败:Feishu 会回退为附加原始文件;WhatsApp 发送会失败,而不是发布不兼容的 PTT 负载。
|
||||
- **MiniMax / Xiaomi MiMo:** 默认 MP3(MiniMax `speech-2.8-hd` 为 32 kHz);对于语音便笺目标,会通过 `ffmpeg` 转码为 48 kHz Opus。
|
||||
- **Local CLI:** 使用已配置的 `outputFormat`。语音便笺目标会被转换为 Ogg/Opus,电话输出会被转换为原始 16 kHz 单声道 PCM。
|
||||
- **Google Gemini:** 返回原始 24 kHz PCM。OpenClaw 会将其封装为 WAV 用于附件,转码为 48 kHz Opus 用于语音便笺目标,并为 Talk/电话直接返回 PCM。
|
||||
- **Inworld:** 附件使用 MP3,语音便笺使用原生 `OGG_OPUS`,Talk/电话使用 22050 Hz 原始 `PCM`。
|
||||
- **xAI:** 默认 MP3;`responseFormat` 可以是 `mp3|wav|pcm|mulaw|alaw`。使用 xAI 的批量 REST 端点 —— **不**使用流式 WebSocket TTS。不支持原生 Opus 语音便笺格式。
|
||||
- **Microsoft:** 使用 `microsoft.outputFormat`(默认 `audio-24khz-48kbitrate-mono-mp3`)。Telegram `sendVoice` 接受 OGG/MP3/M4A;如果你需要保证使用 Opus 语音消息,请使用 OpenAI/ElevenLabs。如果已配置的 Microsoft 格式失败,OpenClaw 会回退重试 MP3。
|
||||
|
||||
OpenAI 和 ElevenLabs 的输出格式按渠道固定,如上所列。
|
||||
|
||||
@ -679,178 +770,181 @@ OpenAI 和 ElevenLabs 的输出格式按渠道固定,如上所列。
|
||||
<AccordionGroup>
|
||||
<Accordion title="顶层 messages.tts.*">
|
||||
<ParamField path="auto" type='"off" | "always" | "inbound" | "tagged"'>
|
||||
自动 TTS 模式。`inbound` 仅在收到入站语音消息后发送音频;`tagged` 仅当回复包含 `[[tts:...]]` 指令或 `[[tts:text]]` 块时发送音频。
|
||||
自动 TTS 模式。`inbound` 仅在收到入站语音消息后发送音频;`tagged` 仅在回复包含 `[[tts:...]]` 指令或 `[[tts:text]]` 块时发送音频。
|
||||
</ParamField>
|
||||
<ParamField path="enabled" type="boolean" deprecated>
|
||||
旧版开关。`openclaw doctor --fix` 会将其迁移为 `auto`。
|
||||
旧版开关。`openclaw doctor --fix` 会将其迁移到 `auto`。
|
||||
</ParamField>
|
||||
<ParamField path="mode" type='"final" | "all"' default="final">
|
||||
`"all"` 除最终回复外,还包括工具/块回复。
|
||||
`"all"` 除最终回复外,还包括工具/分块回复。
|
||||
</ParamField>
|
||||
<ParamField path="provider" type="string">
|
||||
语音提供商 id。未设置时,OpenClaw 会按注册表自动选择顺序使用第一个已配置的提供商。旧版 `provider: "edge"` 会被 `openclaw doctor --fix` 重写为 `"microsoft"`。
|
||||
语音 provider id。未设置时,OpenClaw 会按注册表自动选择顺序使用第一个已配置的 provider。旧版 `provider: "edge"` 会被 `openclaw doctor --fix` 重写为 `"microsoft"`。
|
||||
</ParamField>
|
||||
<ParamField path="persona" type="string">
|
||||
来自 `personas` 的当前激活角色语音 id。会规范化为小写。
|
||||
来自 `personas` 的当前 persona id。会规范化为小写。
|
||||
</ParamField>
|
||||
<ParamField path="personas.<id>" type="object">
|
||||
稳定的语音身份。字段包括:`label`、`description`、`provider`、`fallbackPolicy`、`prompt`、`providers.<provider>`。参见 [角色语音](#personas)。
|
||||
稳定的语音身份。字段包括:`label`、`description`、`provider`、`fallbackPolicy`、`prompt`、`providers.<provider>`。参见 [Personas](#personas)。
|
||||
</ParamField>
|
||||
<ParamField path="summaryModel" type="string">
|
||||
用于自动摘要的低成本模型;默认值为 `agents.defaults.model.primary`。接受 `provider/model` 或已配置的模型别名。
|
||||
用于自动摘要的低成本模型;默认是 `agents.defaults.model.primary`。接受 `provider/model` 或已配置的模型别名。
|
||||
</ParamField>
|
||||
<ParamField path="modelOverrides" type="object">
|
||||
允许模型发出 TTS 指令。`enabled` 默认为 `true`;`allowProvider` 默认为 `false`。
|
||||
</ParamField>
|
||||
<ParamField path="providers.<id>" type="object">
|
||||
以语音提供商 id 为键的提供商自有设置。旧版直接配置块(`messages.tts.openai`、`.elevenlabs`、`.microsoft`、`.edge`)会由 `openclaw doctor --fix` 重写;提交时只应使用 `messages.tts.providers.<id>`。
|
||||
由 provider 拥有的设置,按语音 provider id 作为键。旧版直接块(`messages.tts.openai`、`.elevenlabs`、`.microsoft`、`.edge`)会被 `openclaw doctor --fix` 重写;提交时仅保留 `messages.tts.providers.<id>`。
|
||||
</ParamField>
|
||||
<ParamField path="maxTextLength" type="number">
|
||||
TTS 输入字符数的硬上限。超出时,`/tts audio` 会失败。
|
||||
TTS 输入字符数的硬上限。超过时,`/tts audio` 会失败。
|
||||
</ParamField>
|
||||
<ParamField path="timeoutMs" type="number">
|
||||
请求超时时间(毫秒)。
|
||||
</ParamField>
|
||||
<ParamField path="prefsPath" type="string">
|
||||
覆盖本地偏好 JSON 路径(提供商/限制/摘要)。默认值为 `~/.openclaw/settings/tts.json`。
|
||||
覆盖本地 prefs JSON 路径(provider/limit/summary)。默认是 `~/.openclaw/settings/tts.json`。
|
||||
</ParamField>
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Azure Speech">
|
||||
<ParamField path="apiKey" type="string">环境变量:`AZURE_SPEECH_KEY`、`AZURE_SPEECH_API_KEY` 或 `SPEECH_KEY`。</ParamField>
|
||||
<ParamField path="region" type="string">Azure Speech 区域(例如 `eastus`)。环境变量:`AZURE_SPEECH_REGION` 或 `SPEECH_REGION`。</ParamField>
|
||||
<ParamField path="endpoint" type="string">可选的 Azure Speech 端点覆盖项(别名 `baseUrl`)。</ParamField>
|
||||
<ParamField path="voice" type="string">Azure 语音 ShortName。默认值为 `en-US-JennyNeural`。</ParamField>
|
||||
<ParamField path="lang" type="string">SSML 语言代码。默认值为 `en-US`。</ParamField>
|
||||
<ParamField path="outputFormat" type="string">标准音频使用的 Azure `X-Microsoft-OutputFormat`。默认值为 `audio-24khz-48kbitrate-mono-mp3`。</ParamField>
|
||||
<ParamField path="voiceNoteOutputFormat" type="string">语音便笺输出使用的 Azure `X-Microsoft-OutputFormat`。默认值为 `ogg-24khz-16bit-mono-opus`。</ParamField>
|
||||
<ParamField path="endpoint" type="string">可选的 Azure Speech 端点覆盖(别名 `baseUrl`)。</ParamField>
|
||||
<ParamField path="voice" type="string">Azure voice ShortName。默认是 `en-US-JennyNeural`。</ParamField>
|
||||
<ParamField path="lang" type="string">SSML 语言代码。默认是 `en-US`。</ParamField>
|
||||
<ParamField path="outputFormat" type="string">标准音频的 Azure `X-Microsoft-OutputFormat`。默认是 `audio-24khz-48kbitrate-mono-mp3`。</ParamField>
|
||||
<ParamField path="voiceNoteOutputFormat" type="string">语音便笺输出的 Azure `X-Microsoft-OutputFormat`。默认是 `ogg-24khz-16bit-mono-opus`。</ParamField>
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="ElevenLabs">
|
||||
<ParamField path="apiKey" type="string">回退到 `ELEVENLABS_API_KEY` 或 `XI_API_KEY`。</ParamField>
|
||||
<ParamField path="model" type="string">模型 id(例如 `eleven_multilingual_v2`、`eleven_v3`)。</ParamField>
|
||||
<ParamField path="voiceId" type="string">ElevenLabs 语音 id。</ParamField>
|
||||
<ParamField path="voiceId" type="string">ElevenLabs voice id。</ParamField>
|
||||
<ParamField path="voiceSettings" type="object">
|
||||
`stability`、`similarityBoost`、`style`(每个均为 `0..1`)、`useSpeakerBoost`(`true|false`)、`speed`(`0.5..2.0`,`1.0` = 正常)。
|
||||
`stability`、`similarityBoost`、`style`(各自范围 `0..1`),`useSpeakerBoost`(`true|false`),`speed`(`0.5..2.0`,`1.0` = 正常)。
|
||||
</ParamField>
|
||||
<ParamField path="applyTextNormalization" type='"auto" | "on" | "off"'>文本规范化模式。</ParamField>
|
||||
<ParamField path="languageCode" type="string">2 字母 ISO 639-1(例如 `en`、`de`)。</ParamField>
|
||||
<ParamField path="seed" type="number">整数 `0..4294967295`,用于尽力实现确定性输出。</ParamField>
|
||||
<ParamField path="baseUrl" type="string">覆盖 ElevenLabs API 基础 URL。</ParamField>
|
||||
<ParamField path="seed" type="number">整数 `0..4294967295`,用于尽力而为的确定性。</ParamField>
|
||||
<ParamField path="baseUrl" type="string">覆盖 ElevenLabs API base URL。</ParamField>
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Google Gemini">
|
||||
<ParamField path="apiKey" type="string">回退到 `GEMINI_API_KEY` / `GOOGLE_API_KEY`。如果省略,TTS 可在环境变量回退前复用 `models.providers.google.apiKey`。</ParamField>
|
||||
<ParamField path="model" type="string">Gemini TTS 模型。默认值为 `gemini-3.1-flash-tts-preview`。</ParamField>
|
||||
<ParamField path="voiceName" type="string">Gemini 预构建语音名称。默认值为 `Kore`。别名:`voice`。</ParamField>
|
||||
<ParamField path="audioProfile" type="string">在朗读文本前预置的自然语言风格提示。</ParamField>
|
||||
<ParamField path="speakerName" type="string">当你的提示使用具名说话者时,在朗读文本前预置的可选说话者标签。</ParamField>
|
||||
<ParamField path="promptTemplate" type='"audio-profile-v1"'>设置为 `audio-profile-v1` 时,会将当前激活角色语音的提示字段包装进确定性的 Gemini TTS 提示结构中。</ParamField>
|
||||
<ParamField path="personaPrompt" type="string">附加到模板 Director's Notes 中的 Google 特定额外角色语音提示文本。</ParamField>
|
||||
<ParamField path="apiKey" type="string">回退到 `GEMINI_API_KEY` / `GOOGLE_API_KEY`。如果省略,TTS 在回退到环境变量之前还可以复用 `models.providers.google.apiKey`。</ParamField>
|
||||
<ParamField path="model" type="string">Gemini TTS 模型。默认是 `gemini-3.1-flash-tts-preview`。</ParamField>
|
||||
<ParamField path="voiceName" type="string">Gemini 预置 voice 名称。默认是 `Kore`。别名:`voice`。</ParamField>
|
||||
<ParamField path="audioProfile" type="string">在朗读文本前附加的自然语言风格提示。</ParamField>
|
||||
<ParamField path="speakerName" type="string">当你的提示使用具名说话者时,在朗读文本前附加的可选说话者标签。</ParamField>
|
||||
<ParamField path="promptTemplate" type='"audio-profile-v1"'>设置为 `audio-profile-v1` 时,会将当前 persona 提示字段包装为确定性的 Gemini TTS 提示结构。</ParamField>
|
||||
<ParamField path="personaPrompt" type="string">附加到模板 Director's Notes 的 Google 专用额外 persona 提示文本。</ParamField>
|
||||
<ParamField path="baseUrl" type="string">仅接受 `https://generativelanguage.googleapis.com`。</ParamField>
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Gradium">
|
||||
<ParamField path="apiKey" type="string">环境变量:`GRADIUM_API_KEY`。</ParamField>
|
||||
<ParamField path="baseUrl" type="string">默认值为 `https://api.gradium.ai`。</ParamField>
|
||||
<ParamField path="voiceId" type="string">默认值为 Emma(`YTpq7expH9539ERJ`)。</ParamField>
|
||||
<ParamField path="baseUrl" type="string">默认是 `https://api.gradium.ai`。</ParamField>
|
||||
<ParamField path="voiceId" type="string">默认是 Emma(`YTpq7expH9539ERJ`)。</ParamField>
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Inworld">
|
||||
<ParamField path="apiKey" type="string">环境变量:`INWORLD_API_KEY`。</ParamField>
|
||||
<ParamField path="baseUrl" type="string">默认值为 `https://api.inworld.ai`。</ParamField>
|
||||
<ParamField path="modelId" type="string">默认值为 `inworld-tts-1.5-max`。还支持:`inworld-tts-1.5-mini`、`inworld-tts-1-max`、`inworld-tts-1`。</ParamField>
|
||||
<ParamField path="voiceId" type="string">默认值为 `Sarah`。</ParamField>
|
||||
<ParamField path="baseUrl" type="string">默认是 `https://api.inworld.ai`。</ParamField>
|
||||
<ParamField path="modelId" type="string">默认是 `inworld-tts-1.5-max`。也支持:`inworld-tts-1.5-mini`、`inworld-tts-1-max`、`inworld-tts-1`。</ParamField>
|
||||
<ParamField path="voiceId" type="string">默认是 `Sarah`。</ParamField>
|
||||
<ParamField path="temperature" type="number">采样温度 `0..2`。</ParamField>
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Local CLI (tts-local-cli)">
|
||||
<ParamField path="command" type="string">用于 CLI TTS 的本地可执行文件或命令字符串。</ParamField>
|
||||
<ParamField path="args" type="string[]">命令参数。支持 `{{Text}}`、`{{OutputPath}}`、`{{OutputDir}}`、`{{OutputBase}}` 占位符。</ParamField>
|
||||
<ParamField path="outputFormat" type='"mp3" | "opus" | "wav"'>预期的 CLI 输出格式。音频附件默认值为 `mp3`。</ParamField>
|
||||
<ParamField path="timeoutMs" type="number">命令超时时间(毫秒)。默认值为 `120000`。</ParamField>
|
||||
<ParamField path="outputFormat" type='"mp3" | "opus" | "wav"'>预期的 CLI 输出格式。音频附件默认是 `mp3`。</ParamField>
|
||||
<ParamField path="timeoutMs" type="number">命令超时时间(毫秒)。默认 `120000`。</ParamField>
|
||||
<ParamField path="cwd" type="string">可选的命令工作目录。</ParamField>
|
||||
<ParamField path="env" type="Record<string, string>">命令的可选环境变量覆盖项。</ParamField>
|
||||
<ParamField path="env" type="Record<string, string>">命令的可选环境变量覆盖。</ParamField>
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Microsoft(无 API 密钥)">
|
||||
<ParamField path="enabled" type="boolean" default="true">允许使用 Microsoft 语音。</ParamField>
|
||||
<ParamField path="voice" type="string">Microsoft 神经网络语音名称(例如 `en-US-MichelleNeural`)。</ParamField>
|
||||
<ParamField path="voice" type="string">Microsoft neural voice 名称(例如 `en-US-MichelleNeural`)。</ParamField>
|
||||
<ParamField path="lang" type="string">语言代码(例如 `en-US`)。</ParamField>
|
||||
<ParamField path="outputFormat" type="string">Microsoft 输出格式。默认值为 `audio-24khz-48kbitrate-mono-mp3`。内置的基于 Edge 的传输层并不支持所有格式。</ParamField>
|
||||
<ParamField path="outputFormat" type="string">Microsoft 输出格式。默认是 `audio-24khz-48kbitrate-mono-mp3`。并非所有格式都受内置的 Edge 后端传输支持。</ParamField>
|
||||
<ParamField path="rate / pitch / volume" type="string">百分比字符串(例如 `+10%`、`-5%`)。</ParamField>
|
||||
<ParamField path="saveSubtitles" type="boolean">将 JSON 字幕写入音频文件旁边。</ParamField>
|
||||
<ParamField path="saveSubtitles" type="boolean">在音频文件旁写入 JSON 字幕。</ParamField>
|
||||
<ParamField path="proxy" type="string">Microsoft 语音请求的代理 URL。</ParamField>
|
||||
<ParamField path="timeoutMs" type="number">请求超时覆盖项(毫秒)。</ParamField>
|
||||
<ParamField path="edge.*" type="object" deprecated>旧版别名。运行 `openclaw doctor --fix` 可将持久化配置重写为 `providers.microsoft`。</ParamField>
|
||||
<ParamField path="timeoutMs" type="number">请求超时覆盖(毫秒)。</ParamField>
|
||||
<ParamField path="edge.*" type="object" deprecated>旧版别名。运行 `openclaw doctor --fix` 可将已持久化配置重写到 `providers.microsoft`。</ParamField>
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="MiniMax">
|
||||
<ParamField path="apiKey" type="string">回退到 `MINIMAX_API_KEY`。Token Plan 认证通过 `MINIMAX_OAUTH_TOKEN`、`MINIMAX_CODE_PLAN_KEY` 或 `MINIMAX_CODING_API_KEY`。</ParamField>
|
||||
<ParamField path="baseUrl" type="string">默认值为 `https://api.minimax.io`。环境变量:`MINIMAX_API_HOST`。</ParamField>
|
||||
<ParamField path="model" type="string">默认值为 `speech-2.8-hd`。环境变量:`MINIMAX_TTS_MODEL`。</ParamField>
|
||||
<ParamField path="voiceId" type="string">默认值为 `English_expressive_narrator`。环境变量:`MINIMAX_TTS_VOICE_ID`。</ParamField>
|
||||
<ParamField path="speed" type="number">`0.5..2.0`。默认值为 `1.0`。</ParamField>
|
||||
<ParamField path="vol" type="number">`(0, 10]`。默认值为 `1.0`。</ParamField>
|
||||
<ParamField path="pitch" type="number">整数 `-12..12`。默认值为 `0`。小数值会在请求前被截断。</ParamField>
|
||||
<ParamField path="baseUrl" type="string">默认是 `https://api.minimax.io`。环境变量:`MINIMAX_API_HOST`。</ParamField>
|
||||
<ParamField path="model" type="string">默认是 `speech-2.8-hd`。环境变量:`MINIMAX_TTS_MODEL`。</ParamField>
|
||||
<ParamField path="voiceId" type="string">默认是 `English_expressive_narrator`。环境变量:`MINIMAX_TTS_VOICE_ID`。</ParamField>
|
||||
<ParamField path="speed" type="number">`0.5..2.0`。默认 `1.0`。</ParamField>
|
||||
<ParamField path="vol" type="number">`(0, 10]`。默认 `1.0`。</ParamField>
|
||||
<ParamField path="pitch" type="number">整数 `-12..12`。默认 `0`。小数值会在请求前被截断。</ParamField>
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="OpenAI">
|
||||
<ParamField path="apiKey" type="string">回退到 `OPENAI_API_KEY`。</ParamField>
|
||||
<ParamField path="model" type="string">OpenAI TTS 模型 id(例如 `gpt-4o-mini-tts`)。</ParamField>
|
||||
<ParamField path="voice" type="string">语音名称(例如 `alloy`、`cedar`)。</ParamField>
|
||||
<ParamField path="instructions" type="string">显式的 OpenAI `instructions` 字段。设置后,角色语音提示字段**不会**自动映射。</ParamField>
|
||||
<ParamField path="voice" type="string">voice 名称(例如 `alloy`、`cedar`)。</ParamField>
|
||||
<ParamField path="instructions" type="string">显式 OpenAI `instructions` 字段。设置后,persona 提示字段**不会**自动映射。</ParamField>
|
||||
<ParamField path="baseUrl" type="string">
|
||||
覆盖 OpenAI TTS 端点。解析顺序:配置 → `OPENAI_TTS_BASE_URL` → `https://api.openai.com/v1`。非默认值会被视为与 OpenAI 兼容的 TTS 端点,因此接受自定义模型名称和语音名称。
|
||||
覆盖 OpenAI TTS 端点。解析顺序:配置 → `OPENAI_TTS_BASE_URL` → `https://api.openai.com/v1`。非默认值会被视为 OpenAI 兼容的 TTS 端点,因此接受自定义模型和 voice 名称。
|
||||
</ParamField>
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="OpenRouter">
|
||||
<ParamField path="apiKey" type="string">环境变量:`OPENROUTER_API_KEY`。可复用 `models.providers.openrouter.apiKey`。</ParamField>
|
||||
<ParamField path="baseUrl" type="string">默认值为 `https://openrouter.ai/api/v1`。旧版 `https://openrouter.ai/v1` 会被规范化。</ParamField>
|
||||
<ParamField path="model" type="string">默认值为 `hexgrad/kokoro-82m`。别名:`modelId`。</ParamField>
|
||||
<ParamField path="voice" type="string">默认值为 `af_alloy`。别名:`voiceId`。</ParamField>
|
||||
<ParamField path="responseFormat" type='"mp3" | "pcm"'>默认值为 `mp3`。</ParamField>
|
||||
<ParamField path="speed" type="number">提供商原生速度覆盖项。</ParamField>
|
||||
<ParamField path="baseUrl" type="string">默认是 `https://openrouter.ai/api/v1`。旧版 `https://openrouter.ai/v1` 会被规范化。</ParamField>
|
||||
<ParamField path="model" type="string">默认是 `hexgrad/kokoro-82m`。别名:`modelId`。</ParamField>
|
||||
<ParamField path="voice" type="string">默认是 `af_alloy`。别名:`voiceId`。</ParamField>
|
||||
<ParamField path="responseFormat" type='"mp3" | "pcm"'>默认是 `mp3`。</ParamField>
|
||||
<ParamField path="speed" type="number">provider 原生速度覆盖。</ParamField>
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Volcengine(BytePlus Seed Speech)">
|
||||
<Accordion title="Volcengine(BytePlus(国际版) Seed Speech)">
|
||||
<ParamField path="apiKey" type="string">环境变量:`VOLCENGINE_TTS_API_KEY` 或 `BYTEPLUS_SEED_SPEECH_API_KEY`。</ParamField>
|
||||
<ParamField path="resourceId" type="string">默认值为 `seed-tts-1.0`。环境变量:`VOLCENGINE_TTS_RESOURCE_ID`。当你的项目具有 TTS 2.0 权限时,请使用 `seed-tts-2.0`。</ParamField>
|
||||
<ParamField path="appKey" type="string">App key 请求头。默认值为 `aGjiRDfUWi`。环境变量:`VOLCENGINE_TTS_APP_KEY`。</ParamField>
|
||||
<ParamField path="resourceId" type="string">默认是 `seed-tts-1.0`。环境变量:`VOLCENGINE_TTS_RESOURCE_ID`。当你的项目具有 TTS 2.0 权限时,请使用 `seed-tts-2.0`。</ParamField>
|
||||
<ParamField path="appKey" type="string">App key header。默认是 `aGjiRDfUWi`。环境变量:`VOLCENGINE_TTS_APP_KEY`。</ParamField>
|
||||
<ParamField path="baseUrl" type="string">覆盖 Seed Speech TTS HTTP 端点。环境变量:`VOLCENGINE_TTS_BASE_URL`。</ParamField>
|
||||
<ParamField path="voice" type="string">语音类型。默认值为 `en_female_anna_mars_bigtts`。环境变量:`VOLCENGINE_TTS_VOICE`。</ParamField>
|
||||
<ParamField path="speedRatio" type="number">提供商原生速度比率。</ParamField>
|
||||
<ParamField path="emotion" type="string">提供商原生情绪标签。</ParamField>
|
||||
<ParamField path="appId / token / cluster" type="string" deprecated>旧版 Volcengine Speech Console 字段。环境变量:`VOLCENGINE_TTS_APPID`、`VOLCENGINE_TTS_TOKEN`、`VOLCENGINE_TTS_CLUSTER`(默认值为 `volcano_tts`)。</ParamField>
|
||||
<ParamField path="voice" type="string">voice 类型。默认是 `en_female_anna_mars_bigtts`。环境变量:`VOLCENGINE_TTS_VOICE`。</ParamField>
|
||||
<ParamField path="speedRatio" type="number">provider 原生速度比例。</ParamField>
|
||||
<ParamField path="emotion" type="string">provider 原生情感标签。</ParamField>
|
||||
<ParamField path="appId / token / cluster" type="string" deprecated>旧版 Volcengine Speech Console 字段。环境变量:`VOLCENGINE_TTS_APPID`、`VOLCENGINE_TTS_TOKEN`、`VOLCENGINE_TTS_CLUSTER`(默认 `volcano_tts`)。</ParamField>
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="xAI">
|
||||
<ParamField path="apiKey" type="string">环境变量:`XAI_API_KEY`。</ParamField>
|
||||
<ParamField path="baseUrl" type="string">默认值为 `https://api.x.ai/v1`。环境变量:`XAI_BASE_URL`。</ParamField>
|
||||
<ParamField path="voiceId" type="string">默认值为 `eve`。可用实时语音:`ara`、`eve`、`leo`、`rex`、`sal`、`una`。</ParamField>
|
||||
<ParamField path="language" type="string">BCP-47 语言代码或 `auto`。默认值为 `en`。</ParamField>
|
||||
<ParamField path="responseFormat" type='"mp3" | "wav" | "pcm" | "mulaw" | "alaw"'>默认值为 `mp3`。</ParamField>
|
||||
<ParamField path="speed" type="number">提供商原生速度覆盖项。</ParamField>
|
||||
<ParamField path="baseUrl" type="string">默认是 `https://api.x.ai/v1`。环境变量:`XAI_BASE_URL`。</ParamField>
|
||||
<ParamField path="voiceId" type="string">默认是 `eve`。实时语音有:`ara`、`eve`、`leo`、`rex`、`sal`、`una`。</ParamField>
|
||||
<ParamField path="language" type="string">BCP-47 语言代码或 `auto`。默认是 `en`。</ParamField>
|
||||
<ParamField path="responseFormat" type='"mp3" | "wav" | "pcm" | "mulaw" | "alaw"'>默认是 `mp3`。</ParamField>
|
||||
<ParamField path="speed" type="number">provider 原生速度覆盖。</ParamField>
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Xiaomi MiMo">
|
||||
<ParamField path="apiKey" type="string">环境变量:`XIAOMI_API_KEY`。</ParamField>
|
||||
<ParamField path="baseUrl" type="string">默认值为 `https://api.xiaomimimo.com/v1`。环境变量:`XIAOMI_BASE_URL`。</ParamField>
|
||||
<ParamField path="model" type="string">默认值为 `mimo-v2.5-tts`。环境变量:`XIAOMI_TTS_MODEL`。还支持 `mimo-v2-tts`。</ParamField>
|
||||
<ParamField path="voice" type="string">默认值为 `mimo_default`。环境变量:`XIAOMI_TTS_VOICE`。</ParamField>
|
||||
<ParamField path="format" type='"mp3" | "wav"'>默认值为 `mp3`。环境变量:`XIAOMI_TTS_FORMAT`。</ParamField>
|
||||
<ParamField path="style" type="string">可选的自然语言风格指令,作为用户消息发送;不会被朗读。</ParamField>
|
||||
<ParamField path="baseUrl" type="string">默认是 `https://api.xiaomimimo.com/v1`。环境变量:`XIAOMI_BASE_URL`。</ParamField>
|
||||
<ParamField path="model" type="string">默认是 `mimo-v2.5-tts`。环境变量:`XIAOMI_TTS_MODEL`。也支持 `mimo-v2-tts`。</ParamField>
|
||||
<ParamField path="voice" type="string">默认是 `mimo_default`。环境变量:`XIAOMI_TTS_VOICE`。</ParamField>
|
||||
<ParamField path="format" type='"mp3" | "wav"'>默认是 `mp3`。环境变量:`XIAOMI_TTS_FORMAT`。</ParamField>
|
||||
<ParamField path="style" type="string">可选的自然语言风格说明,会作为用户消息发送;不会被朗读。</ParamField>
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 智能体工具
|
||||
|
||||
`tts` 工具将文本转换为语音,并返回一个用于回复投递的音频附件。在 Feishu、Matrix、Telegram 和 WhatsApp 上,音频会作为语音消息投递,而不是文件附件。当 `ffmpeg` 可用时,Feishu 和 WhatsApp 在此路径上可以对非 Opus 的 TTS 输出进行转码。
|
||||
`tts` 工具可将文本转换为语音,并返回用于回复投递的音频附件。在 Feishu、Matrix、Telegram 和 WhatsApp 上,音频会作为语音消息投递,而不是文件附件。若 `ffmpeg` 可用,Feishu 和 WhatsApp 在此路径上还可以对非 Opus 的 TTS 输出进行转码。
|
||||
|
||||
WhatsApp 通过 Baileys 将音频作为 PTT 语音便笺发送(`audio` 配合 `ptt: true`),并将可见文本与 PTT 音频**分开发送**,因为客户端对语音便笺字幕的渲染并不一致。
|
||||
WhatsApp 会通过 Baileys 将音频作为 PTT 语音便笺发送(带有
|
||||
`ptt: true` 的 `audio`),并将可见文本与 PTT 音频**分开发送**,因为
|
||||
客户端并不总是能稳定显示语音便笺上的标题。
|
||||
|
||||
该工具接受可选的 `channel` 和 `timeoutMs` 字段;`timeoutMs` 是按次调用的提供商请求超时时间,单位为毫秒。
|
||||
该工具接受可选的 `channel` 和 `timeoutMs` 字段;`timeoutMs` 是
|
||||
按调用生效的 provider 请求超时时间(毫秒)。
|
||||
|
||||
## Gateway 网关 RPC
|
||||
|
||||
@ -860,26 +954,26 @@ WhatsApp 通过 Baileys 将音频作为 PTT 语音便笺发送(`audio` 配合
|
||||
| `tts.enable` | 将本地自动偏好设置为 `always`。 |
|
||||
| `tts.disable` | 将本地自动偏好设置为 `off`。 |
|
||||
| `tts.convert` | 一次性文本 → 音频。 |
|
||||
| `tts.setProvider` | 设置本地提供商偏好。 |
|
||||
| `tts.setPersona` | 设置本地角色语音偏好。 |
|
||||
| `tts.providers` | 列出已配置的提供商及其状态。 |
|
||||
| `tts.setProvider` | 设置本地 provider 偏好。 |
|
||||
| `tts.setPersona` | 设置本地 persona 偏好。 |
|
||||
| `tts.providers` | 列出已配置的 provider 及其状态。 |
|
||||
|
||||
## 服务链接
|
||||
|
||||
- [OpenAI 文本转语音指南](https://platform.openai.com/docs/guides/text-to-speech)
|
||||
- [OpenAI Audio API 参考](https://platform.openai.com/docs/api-reference/audio)
|
||||
- [Azure Speech REST 文本转语音](https://learn.microsoft.com/azure/ai-services/speech-service/rest-text-to-speech)
|
||||
- [OpenAI text-to-speech guide](https://platform.openai.com/docs/guides/text-to-speech)
|
||||
- [OpenAI Audio API reference](https://platform.openai.com/docs/api-reference/audio)
|
||||
- [Azure Speech REST text-to-speech](https://learn.microsoft.com/azure/ai-services/speech-service/rest-text-to-speech)
|
||||
- [Azure Speech provider](/zh-CN/providers/azure-speech)
|
||||
- [ElevenLabs 文本转语音](https://elevenlabs.io/docs/api-reference/text-to-speech)
|
||||
- [ElevenLabs 认证](https://elevenlabs.io/docs/api-reference/authentication)
|
||||
- [ElevenLabs Text to Speech](https://elevenlabs.io/docs/api-reference/text-to-speech)
|
||||
- [ElevenLabs Authentication](https://elevenlabs.io/docs/api-reference/authentication)
|
||||
- [Gradium](/zh-CN/providers/gradium)
|
||||
- [Inworld TTS API](https://docs.inworld.ai/tts/tts)
|
||||
- [MiniMax T2A v2 API](https://platform.minimaxi.com/document/T2A%20V2)
|
||||
- [Volcengine TTS HTTP API](/zh-CN/providers/volcengine#text-to-speech)
|
||||
- [Xiaomi MiMo 语音合成](/zh-CN/providers/xiaomi#text-to-speech)
|
||||
- [Xiaomi MiMo speech synthesis](/zh-CN/providers/xiaomi#text-to-speech)
|
||||
- [node-edge-tts](https://github.com/SchneeHertz/node-edge-tts)
|
||||
- [Microsoft Speech 输出格式](https://learn.microsoft.com/azure/ai-services/speech-service/rest-text-to-speech#audio-outputs)
|
||||
- [xAI 文本转语音](https://docs.x.ai/developers/rest-api-reference/inference/voice#text-to-speech-rest)
|
||||
- [Microsoft Speech output formats](https://learn.microsoft.com/azure/ai-services/speech-service/rest-text-to-speech#audio-outputs)
|
||||
- [xAI text to speech](https://docs.x.ai/developers/rest-api-reference/inference/voice#text-to-speech-rest)
|
||||
|
||||
## 相关内容
|
||||
|
||||
|
||||
@ -1,185 +1,216 @@
|
||||
---
|
||||
read_when:
|
||||
- 你想通过浏览器操作 Gateway 网关
|
||||
- 你希望在不使用 SSH 隧道的情况下通过 Tailnet 访问
|
||||
summary: 基于浏览器的 Gateway 网关控制 UI(聊天、节点、配置)
|
||||
- 你想在不使用 SSH 隧道的情况下通过 Tailnet 访问
|
||||
sidebarTitle: Control UI
|
||||
summary: 用于 Gateway 网关的浏览器控制 UI(聊天、节点、配置)
|
||||
title: 控制 UI
|
||||
x-i18n:
|
||||
generated_at: "2026-04-26T00:39:24Z"
|
||||
generated_at: "2026-04-26T07:51:51Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 6b8b92415bedb9102a42cf5a01ec3872318d713a8de1d95d3931a9d199d237ee
|
||||
source_hash: 9e7828a71cd04d40858d879e19f7436db6168c0cffab91a1591dfad93e25762d
|
||||
source_path: web/control-ui.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
Control UI 是一个由 Gateway 网关提供服务的小型 **Vite + Lit** 单页应用:
|
||||
控制 UI 是一个小型的 **Vite + Lit** 单页应用,由 Gateway 网关提供服务:
|
||||
|
||||
- 默认:`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"` 时使用 trusted-proxy 身份标头
|
||||
- 当 `gateway.auth.allowTailscale: true` 时使用 Tailscale Serve 身份头
|
||||
- 当 `gateway.auth.mode: "trusted-proxy"` 时使用受信任代理身份头
|
||||
|
||||
仪表板设置面板会为当前浏览器标签页会话保存 token 和所选的 gateway URL;不会持久化保存密码。新手引导通常会在首次连接时为共享密钥认证生成一个 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”
|
||||
**你会看到:** “已断开连接(1008):需要配对”
|
||||
|
||||
**批准设备的方法:**
|
||||
<Steps>
|
||||
<Step title="列出待处理请求">
|
||||
```bash
|
||||
openclaw devices list
|
||||
```
|
||||
</Step>
|
||||
<Step title="按请求 ID 批准">
|
||||
```bash
|
||||
openclaw devices approve <requestId>
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
```bash
|
||||
# 列出待处理请求
|
||||
openclaw devices list
|
||||
如果浏览器使用已更改的认证详情(角色/作用域/公钥)重试配对,先前的待处理请求会被替换,并创建新的 `requestId`。批准前请重新运行 `openclaw devices list`。
|
||||
|
||||
# 按请求 ID 批准
|
||||
openclaw devices approve <requestId>
|
||||
```
|
||||
如果浏览器已经配对,而你将其从只读访问更改为写入/管理员访问,这会被视为审批升级,而不是静默重连。OpenClaw 会保持旧审批处于活动状态,阻止更宽泛的重连,并要求你显式批准新的作用域集合。
|
||||
|
||||
如果浏览器在认证详情发生变化后重试配对(角色/作用域/公钥),之前的待处理请求会被新请求取代,并创建一个新的 `requestId`。批准前请重新运行 `openclaw devices list`。
|
||||
一旦获得批准,设备会被记住,除非你使用 `openclaw devices revoke --device <id> --role <role>` 撤销,否则不会再次要求重新批准。有关 token 轮换和撤销,请参见 [Devices CLI](/zh-CN/cli/devices)。
|
||||
|
||||
如果浏览器已经完成配对,而你将其从只读访问改为写入/管理员访问,这会被视为批准升级,而不是静默重连。OpenClaw 会保留旧的批准仍然有效,阻止更高权限的重连,并要求你显式批准新的作用域集合。
|
||||
|
||||
一旦获得批准,该设备会被记住,除非你使用 `openclaw devices revoke --device <id> --role <role>` 撤销它,否则无需再次批准。有关 token 轮换和撤销,请参阅 [Devices CLI](/zh-CN/cli/devices)。
|
||||
|
||||
**说明:**
|
||||
|
||||
- 直接的本地 local loopback 浏览器连接(`127.0.0.1` / `localhost`)会自动获批。
|
||||
<Note>
|
||||
- 直接本地 local loopback 浏览器连接(`127.0.0.1` / `localhost`)会被自动批准。
|
||||
- Tailnet 和 LAN 浏览器连接仍然需要显式批准,即使它们来自同一台机器。
|
||||
- 每个浏览器配置文件都会生成唯一的设备 ID,因此切换浏览器或清除浏览器数据都需要重新配对。
|
||||
</Note>
|
||||
|
||||
## 个人身份(浏览器本地)
|
||||
|
||||
Control UI 支持按浏览器设置个人身份(显示名称和头像),它会附加到发出的消息中,以便在共享会话中标注归属。它存储在浏览器存储中,仅限当前浏览器配置文件,不会同步到其他设备,也不会在服务端持久化;只有你实际发送的消息中,正常的对话记录作者元数据会保留。清除站点数据或切换浏览器后,它会重置为空。
|
||||
控制 UI 支持按浏览器设置个人身份(显示名称和头像),并将其附加到出站消息中,以便在共享会话中进行归因。它存储在浏览器存储中,作用域仅限当前浏览器配置文件,不会同步到其他设备,也不会在服务器端持久化,超出你实际发送消息上的常规转录作者元数据范围。清除站点数据或切换浏览器会将其重置为空。
|
||||
|
||||
同样的浏览器本地模式也适用于助手头像覆盖。上传的助手头像只会在本地浏览器中覆盖 gateway 解析出的身份,绝不会通过 `config.patch` 往返。共享的 `ui.assistant.avatar` 配置字段仍可供直接写入该字段的非 UI 客户端使用(例如脚本化 gateway 或自定义仪表板)。
|
||||
|
||||
## 运行时配置端点
|
||||
|
||||
Control UI 会从 `__/openclaw/control-ui-config.json` 获取其运行时设置。该端点受与其余 HTTP 接口相同的 gateway 认证保护:未认证的浏览器无法获取它,而成功获取则要求已经具有有效的 gateway token/密码、Tailscale Serve 身份或 trusted-proxy 身份之一。
|
||||
控制 UI 会从 `/__openclaw/control-ui-config.json` 获取其运行时设置。该端点受与其余 HTTP 表面相同的 gateway 认证保护:未认证的浏览器无法获取它,成功获取需要已有有效的 gateway token/password、Tailscale Serve 身份或受信任代理身份之一。
|
||||
|
||||
## 语言支持
|
||||
|
||||
Control UI 可以在首次加载时根据你的浏览器区域设置进行本地化。若要稍后覆盖它,请打开 **Overview -> Gateway Access -> Language**。区域选择器位于 Gateway Access 卡片中,而不是在 Appearance 下。
|
||||
控制 UI 可在首次加载时根据你的浏览器语言环境进行本地化。若要稍后覆盖,请打开**概览 -> Gateway Access -> 语言**。语言选择器位于 Gateway Access 卡片中,而不在外观下。
|
||||
|
||||
- 支持的区域设置:`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`)
|
||||
- 通过 WebRTC 直接从浏览器与 OpenAI Realtime 通话。Gateway 网关会通过 `talk.realtime.session` 签发一个短期有效的 Realtime 客户端密钥;浏览器会将麦克风音频直接发送给 OpenAI,并通过 `chat.send` 中继 `openclaw_agent_consult` 工具调用,以供配置中的更大型 OpenClaw 模型使用。
|
||||
- 在聊天中流式显示工具调用和实时工具输出卡片(智能体事件)
|
||||
- 渠道:内置以及内置/外部渠道插件的状态、QR 登录和按渠道配置(`channels.status`、`web.login.*`、`config.patch`)
|
||||
- 实例:在线列表 + 刷新(`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 密钥更新(`skills.*`)
|
||||
- 节点:列表 + 能力(`node.list`)
|
||||
- Exec 批准:编辑 gateway 或节点允许列表 + `exec host=gateway/node` 的询问策略(`exec.approvals.*`)
|
||||
- 配置:查看/编辑 `~/.openclaw/openclaw.json`(`config.get`、`config.set`)
|
||||
- 配置:带验证地应用并重启(`config.apply`),并唤醒最后一个活跃会话
|
||||
- 配置写入包含 base-hash 保护,以防覆盖并发编辑
|
||||
- 配置写入(`config.set` / `config.apply` / `config.patch`)也会对提交的配置负载中的 SecretRef 执行活跃预解析;未解析的活跃已提交引用会在写入前被拒绝
|
||||
- 配置 schema + 表单渲染(`config.schema` / `config.schema.lookup`,包括字段 `title` / `description`、匹配的 UI 提示、直接子项摘要、嵌套对象/通配符/数组/组合节点上的文档元数据,以及可用时的插件 + 渠道 schema);只有当快照可以安全进行原始往返时,Raw JSON 编辑器才可用
|
||||
- 如果某个快照无法安全地进行原始往返,Control UI 会强制使用表单模式,并对该快照禁用原始模式
|
||||
- Raw JSON 编辑器中的“Reset to saved”会保留原始编写形态(格式、注释、`$include` 布局),而不是重新渲染扁平化快照,因此当快照可以安全往返时,外部编辑在重置后仍能保留
|
||||
- 结构化 SecretRef 对象值会在表单文本输入中以只读方式呈现,以防对象被意外损坏并转换为字符串
|
||||
- 调试:Status/health/models 快照 + 事件日志 + 手动 RPC 调用(`status`、`health`、`models.list`)
|
||||
- 日志:实时跟踪 gateway 文件日志,并支持筛选/导出(`logs.tail`)
|
||||
- 更新:运行 package/git 更新并重启(`update.run`),附带重启报告
|
||||
|
||||
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`。
|
||||
<AccordionGroup>
|
||||
<Accordion title="聊天和通话">
|
||||
- 通过 Gateway 网关 WS 与模型聊天(`chat.history`、`chat.send`、`chat.abort`、`chat.inject`)。
|
||||
- 通过 WebRTC 直接在浏览器中与 OpenAI Realtime 通话。Gateway 网关使用 `talk.realtime.session` 生成一个短期 Realtime 客户端密钥;浏览器将麦克风音频直接发送到 OpenAI,并通过 `chat.send` 将 `openclaw_agent_consult` 工具调用中继回去,用于已配置的更大 OpenClaw 模型。
|
||||
- 在聊天中流式显示工具调用 + 实时工具输出卡片(智能体事件)。
|
||||
</Accordion>
|
||||
<Accordion title="渠道、实例、会话、Dreaming">
|
||||
- 渠道:内置以及内置/外部插件渠道状态、QR 登录和按渠道配置(`channels.status`、`web.login.*`、`config.patch`)。
|
||||
- 实例:在线状态列表 + 刷新(`system-presence`)。
|
||||
- 会话:列表 + 按会话设置模型/思考/fast/verbose/trace/reasoning 覆盖(`sessions.list`、`sessions.patch`)。
|
||||
- Dreams:Dreaming 状态、启用/禁用开关以及 Dream Diary 读取器(`doctor.memory.status`、`doctor.memory.dreamDiary`、`config.patch`)。
|
||||
</Accordion>
|
||||
<Accordion title="Cron、Skills、节点、exec 批准">
|
||||
- Cron 作业:列出/添加/编辑/运行/启用/禁用 + 运行历史(`cron.*`)。
|
||||
- Skills:状态、启用/禁用、安装、API key 更新(`skills.*`)。
|
||||
- 节点:列表 + 能力上限(`node.list`)。
|
||||
- Exec 批准:编辑 gateway 或节点允许列表 + 为 `exec host=gateway/node` 设置询问策略(`exec.approvals.*`)。
|
||||
</Accordion>
|
||||
<Accordion title="配置">
|
||||
- 查看/编辑 `~/.openclaw/openclaw.json`(`config.get`、`config.set`)。
|
||||
- 带验证的应用 + 重启(`config.apply`),并唤醒最后一个活动会话。
|
||||
- 写入包含 base-hash 守卫,以防止覆盖并发编辑。
|
||||
- 写入(`config.set`/`config.apply`/`config.patch`)会对提交配置负载中的引用执行活动 SecretRef 解析预检;未解析的活动提交引用会在写入前被拒绝。
|
||||
- Schema + 表单渲染(`config.schema` / `config.schema.lookup`,包括字段 `title` / `description`、匹配的 UI 提示、直接子项摘要、嵌套对象/通配符/数组/组合节点上的文档元数据,以及在可用时的插件 + 渠道 schema);仅当快照支持安全的原始往返时才提供原始 JSON 编辑器。
|
||||
- 如果某个快照无法安全地进行原始往返,控制 UI 会强制使用表单模式,并对该快照禁用原始模式。
|
||||
- 原始 JSON 编辑器中的“重置为已保存”会保留原始编写的结构(格式、注释、`$include` 布局),而不是重新渲染扁平化快照,因此当快照可安全往返时,外部编辑在重置后仍会保留。
|
||||
- 结构化 SecretRef 对象值会在表单文本输入中以只读方式呈现,以防止对象被意外转换为字符串而损坏。
|
||||
</Accordion>
|
||||
<Accordion title="调试、日志、更新">
|
||||
- 调试:状态/健康/模型快照 + 事件日志 + 手动 RPC 调用(`status`、`health`、`models.list`)。
|
||||
- 日志:带过滤/导出的 gateway 文件日志实时 tail(`logs.tail`)。
|
||||
- 更新:运行包/git 更新 + 重启(`update.run`),并附带重启报告。
|
||||
</Accordion>
|
||||
<Accordion title="Cron 作业面板说明">
|
||||
- 对于隔离作业,投递默认是公告摘要。如果你希望仅供内部运行,可以切换为 none。
|
||||
- 选择 announce 时会显示渠道/目标字段。
|
||||
- Webhook 模式使用 `delivery.mode = "webhook"`,并将 `delivery.to` 设为有效的 HTTP(S) webhook URL。
|
||||
- 对于主会话作业,可使用 webhook 和 none 投递模式。
|
||||
- 高级编辑控件包括运行后删除、清除智能体覆盖、cron 精确/错峰选项、智能体模型/思考覆盖,以及尽力投递切换。
|
||||
- 表单验证是行内的,并带有字段级错误;在修复前,无效值会禁用保存按钮。
|
||||
- 设置 `cron.webhookToken` 可发送专用 bearer token;如果省略,则 webhook 发送时不会带认证头。
|
||||
- 已弃用回退:存储的遗留作业若带有 `notify: true`,在迁移前仍可使用 `cron.webhook`。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 聊天行为
|
||||
|
||||
- `chat.send` 是**非阻塞**的:它会立即确认并返回 `{ runId, status: "started" }`,响应则通过 `chat` 事件流式传输。
|
||||
- 使用相同的 `idempotencyKey` 重新发送时,运行中会返回 `{ status: "in_flight" }`,完成后会返回 `{ status: "ok" }`。
|
||||
- `chat.history` 的响应具有大小限制,以确保 UI 安全。当对话记录条目过大时,Gateway 网关可能会截断较长的文本字段、省略较重的元数据块,并用占位符替换超大消息(`[chat.history omitted: message too large]`)。
|
||||
- 助手/生成的图片会持久化为受管媒体引用,并通过经过认证的 Gateway 网关媒体 URL 返回,因此重新加载时不依赖聊天历史响应中保留原始 base64 图片负载。
|
||||
- `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.history` 短暂返回较旧的快照,聊天视图会保持本地乐观显示的用户/助手消息可见;一旦 Gateway 网关历史记录追上,这些本地消息就会被规范对话记录替换。
|
||||
- `chat.inject` 会向会话对话记录追加一条助手注释,并广播一个 `chat` 事件,用于仅 UI 的更新(不运行智能体,不进行渠道投递)。
|
||||
- 聊天头部中的 model 和 thinking 选择器会立即通过 `sessions.patch` 更新当前活跃会话;它们是持久的会话覆盖,而不是仅单轮发送选项。
|
||||
- 当最新的 Gateway 网关会话用量报告显示上下文压力较高时,聊天输入区域会显示上下文提示,并且在建议的压缩级别下,会显示一个 compact 按钮来运行常规会话压缩路径。过期的 token 快照会被隐藏,直到 Gateway 网关再次报告最新用量。
|
||||
- Talk 模式使用支持浏览器 WebRTC 会话的已注册实时语音 provider。可通过设置 `talk.provider: "openai"` 加上 `talk.providers.openai.apiKey` 来配置 OpenAI,或复用 Voice Call 实时 provider 配置。浏览器永远不会收到标准 OpenAI API 密钥;它只会收到临时 Realtime 客户端密钥。Google Live 实时语音支持后端 Voice Call 和 Google Meet 桥接,但暂不支持此浏览器 WebRTC 路径。Realtime 会话提示由 Gateway 网关组装;`talk.realtime.session` 不接受调用方提供的指令覆盖。
|
||||
- 在聊天输入框中,Talk 控件是位于麦克风听写按钮旁边的波形按钮。当 Talk 启动时,输入框状态行会显示 `Connecting Talk...`,然后在音频连接期间显示 `Talk live`,或者在实时工具调用通过 `chat.send` 咨询已配置的大型 OpenClaw 模型时显示 `Asking OpenClaw...`。
|
||||
- 停止:
|
||||
- 点击 **Stop**(调用 `chat.abort`)
|
||||
- 当某次运行处于活动状态时,普通后续消息会排队。点击已排队消息上的 **Steer**,可将该后续消息注入到当前运行中的轮次。
|
||||
- 输入 `/stop`(或独立的中止短语,如 `stop`、`stop action`、`stop run`、`stop openclaw`、`please stop`)可进行带外中止
|
||||
- `chat.abort` 支持 `{ sessionKey }`(无需 `runId`)来中止该会话的所有活动运行
|
||||
- 中止后的部分保留:
|
||||
- 当某次运行被中止时,部分助手文本仍可能在 UI 中显示
|
||||
- 当存在缓冲输出时,Gateway 网关会将中止时的部分助手文本持久化到对话记录历史中
|
||||
- 持久化条目会包含中止元数据,以便对话记录使用方区分中止部分与正常完成输出
|
||||
<AccordionGroup>
|
||||
<Accordion title="发送和历史语义">
|
||||
- `chat.send` 是**非阻塞的**:它会立即以 `{ runId, status: "started" }` 确认,响应会通过 `chat` 事件流式返回。
|
||||
- 使用相同的 `idempotencyKey` 重新发送时,运行期间会返回 `{ status: "in_flight" }`,完成后返回 `{ status: "ok" }`。
|
||||
- `chat.history` 响应为了 UI 安全而有大小限制。当转录条目过大时,Gateway 网关可能会截断长文本字段、省略较重的元数据块,并用占位符替换过大的消息(`[chat.history omitted: message too large]`)。
|
||||
- 助手/生成的图片会作为托管媒体引用持久化,并通过已认证的 Gateway 网关媒体 URL 返回,因此重新加载不依赖原始 base64 图片负载持续保留在聊天历史响应中。
|
||||
- `chat.history` 还会从可见助手文本中移除仅用于显示的内联指令标签(例如 `[[reply_to_*]]` 和 `[[audio_as_voice]]`)、纯文本工具调用 XML 负载(包括 `<tool_call>...</tool_call>`、`<function_call>...</function_call>`、`<tool_calls>...</tool_calls>`、`<function_calls>...</function_calls>` 以及被截断的工具调用块),并省略整个可见文本仅为精确静默 token `NO_REPLY` / `no_reply` 的助手条目,同时移除泄露的 ASCII/全角模型控制 token。
|
||||
- 在发送进行中以及最终历史刷新期间,如果 `chat.history` 短暂返回较旧快照,聊天视图会保持本地乐观用户/助手消息可见;一旦 Gateway 网关历史追上,这些本地消息就会被规范转录替换。
|
||||
- `chat.inject` 会向会话转录附加一条助手注释,并广播一个 `chat` 事件用于仅 UI 更新(不触发智能体运行,也不进行渠道投递)。
|
||||
- 聊天头部的模型和思考选择器会通过 `sessions.patch` 立即修补活动会话;它们是持久的会话覆盖,而不是单轮发送选项。
|
||||
- 当最新的 Gateway 网关会话使用情况报告显示上下文压力较高时,聊天编辑区域会显示上下文提示,并在建议压缩级别时显示一个压缩按钮,运行正常的会话压缩路径。陈旧的 token 快照会被隐藏,直到 Gateway 网关再次报告最新使用情况。
|
||||
</Accordion>
|
||||
<Accordion title="通话模式(浏览器 WebRTC)">
|
||||
通话模式使用一个已注册的实时语音提供商,该提供商支持浏览器 WebRTC 会话。配置 OpenAI 时,请使用 `talk.provider: "openai"` 加上 `talk.providers.openai.apiKey`,或者复用 Voice Call 实时提供商配置。浏览器绝不会收到标准 OpenAI API key;它只会收到临时 Realtime 客户端密钥。Google Live 实时语音支持后端 Voice Call 和 Google Meet 插件桥接,但暂不支持此浏览器 WebRTC 路径。Realtime 会话提示由 Gateway 网关组装;`talk.realtime.session` 不接受调用方提供的指令覆盖。
|
||||
|
||||
在聊天编辑器中,Talk 控件是麦克风听写按钮旁边的波形按钮。当 Talk 启动时,编辑器状态行会显示 `Connecting Talk...`,音频连接后显示 `Talk live`,或者当实时工具调用正通过 `chat.send` 咨询已配置的大模型时显示 `Asking OpenClaw...`。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="停止和中止">
|
||||
- 点击**停止**(调用 `chat.abort`)。
|
||||
- 当某次运行处于活动状态时,普通后续消息会排队。点击队列消息上的**Steer**,可将该后续消息注入当前运行中的轮次。
|
||||
- 输入 `/stop`(或独立的中止短语,例如 `stop`、`stop action`、`stop run`、`stop openclaw`、`please stop`)以带外中止。
|
||||
- `chat.abort` 支持 `{ sessionKey }`(无需 `runId`)来中止该会话的所有活动运行。
|
||||
</Accordion>
|
||||
<Accordion title="中止时的部分内容保留">
|
||||
- 当某次运行被中止时,部分助手文本仍可在 UI 中显示。
|
||||
- 当存在缓冲输出时,Gateway 网关会将中止时的部分助手文本持久化到转录历史中。
|
||||
- 持久化条目包含中止元数据,因此转录使用方可以区分中止的部分内容和正常完成输出。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## PWA 安装和 Web Push
|
||||
|
||||
Control UI 内置了 `manifest.webmanifest` 和 service worker,因此现代浏览器可以将其安装为独立 PWA。Web Push 允许 Gateway 网关在标签页或浏览器窗口未打开时,通过通知唤醒已安装的 PWA。
|
||||
控制 UI 内置了一个 `manifest.webmanifest` 和一个 service worker,因此现代浏览器可以将其安装为独立的 PWA。Web Push 允许 Gateway 网关通过通知唤醒已安装的 PWA,即使标签页或浏览器窗口未打开也是如此。
|
||||
|
||||
| Surface | 作用 |
|
||||
| ----------------------------------------------------- | ---- |
|
||||
| `ui/public/manifest.webmanifest` | PWA 清单。浏览器一旦可以访问它,就会提供“安装应用”选项。 |
|
||||
| `ui/public/sw.js` | 处理 `push` 事件和通知点击的 service worker。 |
|
||||
| `push/vapid-keys.json`(位于 OpenClaw 状态目录下) | 自动生成的 VAPID 密钥对,用于对 Web Push 负载进行签名。 |
|
||||
| `push/web-push-subscriptions.json` | 持久化的浏览器订阅端点。 |
|
||||
| 表面 | 功能 |
|
||||
| ----------------------------------------------------- | ------------------------------------------------------------------ |
|
||||
| `ui/public/manifest.webmanifest` | PWA 清单。浏览器一旦可以访问它,就会提供“安装应用”。 |
|
||||
| `ui/public/sw.js` | 处理 `push` 事件和通知点击的 service worker。 |
|
||||
| `push/vapid-keys.json`(位于 OpenClaw 状态目录下) | 自动生成的 VAPID 密钥对,用于签署 Web Push 负载。 |
|
||||
| `push/web-push-subscriptions.json` | 持久化的浏览器订阅端点。 |
|
||||
|
||||
当你希望固定密钥时(例如多主机部署、密钥轮换或测试),可以通过 Gateway 网关进程上的环境变量覆盖 VAPID 密钥对:
|
||||
当你希望固定密钥时(例如多主机部署、密钥轮换或测试),可通过 Gateway 网关进程上的环境变量覆盖 VAPID 密钥对:
|
||||
|
||||
- `OPENCLAW_VAPID_PUBLIC_KEY`
|
||||
- `OPENCLAW_VAPID_PRIVATE_KEY`
|
||||
- `OPENCLAW_VAPID_SUBJECT`(默认为 `mailto:openclaw@localhost`)
|
||||
- `OPENCLAW_VAPID_SUBJECT`(默认值为 `mailto:openclaw@localhost`)
|
||||
|
||||
Control UI 使用以下这些受作用域保护的 Gateway 网关方法来注册和测试浏览器订阅:
|
||||
控制 UI 使用以下受作用域限制的 Gateway 网关方法来注册和测试浏览器订阅:
|
||||
|
||||
- `push.web.vapidPublicKey` —— 获取当前活动的 VAPID 公钥。
|
||||
- `push.web.subscribe` —— 注册一个 `endpoint` 以及 `keys.p256dh` / `keys.auth`。
|
||||
- `push.web.unsubscribe` —— 删除一个已注册的端点。
|
||||
- `push.web.test` —— 向调用者的订阅发送测试通知。
|
||||
- `push.web.vapidPublicKey` — 获取当前活动的 VAPID 公钥。
|
||||
- `push.web.subscribe` — 注册一个 `endpoint` 以及 `keys.p256dh` / `keys.auth`。
|
||||
- `push.web.unsubscribe` — 移除已注册的端点。
|
||||
- `push.web.test` — 向调用者的订阅发送一条测试通知。
|
||||
|
||||
Web Push 独立于 iOS APNS 中继路径
|
||||
(有关基于中继的推送,请参阅 [配置](/zh-CN/gateway/configuration))
|
||||
以及现有的 `push.test` 方法,后者面向原生移动端配对。
|
||||
<Note>
|
||||
Web Push 独立于 iOS APNS 中继路径(有关基于中继的推送,请参见 [配置](/zh-CN/gateway/configuration))以及现有的 `push.test` 方法,后者面向原生移动配对。
|
||||
</Note>
|
||||
|
||||
## 托管嵌入
|
||||
|
||||
助手消息可以使用 `[embed ...]`
|
||||
短代码以内联方式渲染托管网页内容。iframe 沙箱策略由
|
||||
`gateway.controlUi.embedSandbox` 控制:
|
||||
助手消息可以通过 `[embed ...]` shortcode 内联渲染托管的 Web 内容。iframe 沙箱策略由 `gateway.controlUi.embedSandbox` 控制:
|
||||
|
||||
- `strict`:禁用托管嵌入中的脚本执行
|
||||
- `scripts`:允许交互式嵌入,同时保持源隔离;这是默认值,通常足以支持自包含的浏览器游戏/小组件
|
||||
- `trusted`:在 `allow-scripts` 之上额外添加 `allow-same-origin`,用于那些确实需要更高权限的同站文档
|
||||
<Tabs>
|
||||
<Tab title="strict">
|
||||
禁止在托管嵌入中执行脚本。
|
||||
</Tab>
|
||||
<Tab title="scripts (default)">
|
||||
允许交互式嵌入,同时保持源隔离;这是默认值,通常足以满足自包含的浏览器游戏/小组件。
|
||||
</Tab>
|
||||
<Tab title="trusted">
|
||||
在 `allow-scripts` 之上再添加 `allow-same-origin`,用于那些确实需要更高权限的同站文档。
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
示例:
|
||||
|
||||
@ -193,126 +224,130 @@ Web Push 独立于 iOS APNS 中继路径
|
||||
}
|
||||
```
|
||||
|
||||
仅当嵌入文档确实需要同源行为时才使用 `trusted`。对于大多数由智能体生成的游戏和交互式画布,`scripts` 是更安全的选择。
|
||||
<Warning>
|
||||
仅当嵌入文档确实需要 same-origin 行为时才使用 `trusted`。对于大多数智能体生成的游戏和交互式画布,`scripts` 是更安全的选择。
|
||||
</Warning>
|
||||
|
||||
默认情况下,绝对外部 `http(s)` 嵌入 URL 仍会被阻止。如果你确实希望 `[embed url="https://..."]` 加载第三方页面,请设置
|
||||
`gateway.controlUi.allowExternalEmbedUrls: true`。
|
||||
绝对外部 `http(s)` 嵌入 URL 默认仍会被阻止。如果你确实希望 `[embed url="https://..."]` 加载第三方页面,请设置 `gateway.controlUi.allowExternalEmbedUrls: true`。
|
||||
|
||||
## Tailnet 访问(推荐)
|
||||
|
||||
### 集成 Tailscale Serve(首选)
|
||||
<Tabs>
|
||||
<Tab title="集成 Tailscale Serve(首选)">
|
||||
让 Gateway 网关保持在 loopback 上,并由 Tailscale Serve 通过 HTTPS 代理:
|
||||
|
||||
让 Gateway 网关保持绑定在 loopback,并使用 Tailscale Serve 通过 HTTPS 进行代理:
|
||||
```bash
|
||||
openclaw gateway --tailscale serve
|
||||
```
|
||||
|
||||
```bash
|
||||
openclaw gateway --tailscale serve
|
||||
```
|
||||
打开:
|
||||
|
||||
打开:
|
||||
- `https://<magicdns>/`(或你配置的 `gateway.controlUi.basePath`)
|
||||
|
||||
- `https://<magicdns>/`(或你配置的 `gateway.controlUi.basePath`)
|
||||
默认情况下,当 `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"`。
|
||||
|
||||
默认情况下,当 `gateway.auth.allowTailscale` 为 `true` 时,Control UI/WebSocket Serve 请求可以通过 Tailscale 身份标头
|
||||
(`tailscale-user-login`)进行认证。OpenClaw
|
||||
会通过使用 `tailscale whois` 解析 `x-forwarded-for` 地址并与标头匹配来验证该身份,而且只有在请求命中 loopback 且带有 Tailscale 的 `x-forwarded-*` 标头时才会接受这些身份。若你希望即使对 Serve 流量也要求显式共享密钥凭证,请设置
|
||||
`gateway.auth.allowTailscale: false`。然后使用 `gateway.auth.mode: "token"` 或
|
||||
`"password"`。
|
||||
对于该异步 Serve 身份路径,来自同一客户端 IP 和认证作用域的失败认证尝试会在写入限速记录前被串行化。因此,来自同一浏览器的并发错误重试在第二个请求上可能会显示 `retry later`,而不是两个普通不匹配并行竞争。
|
||||
无 token 的 Serve 认证假设 gateway 主机是可信的。如果该主机上可能运行不受信任的本地代码,请要求使用 token/密码认证。
|
||||
对于该异步 Serve 身份路径,来自同一客户端 IP 和认证作用域的失败认证尝试会在写入限流之前串行化。因此,同一浏览器的并发错误重试在第二个请求上可能显示 `retry later`,而不是两个普通不匹配并行竞争。
|
||||
|
||||
### 绑定到 tailnet + token
|
||||
<Warning>
|
||||
无 token 的 Serve 认证假定 gateway 主机是可信的。如果该主机上可能运行不受信任的本地代码,请要求 token/password 认证。
|
||||
</Warning>
|
||||
|
||||
```bash
|
||||
openclaw gateway --bind tailnet --token "$(openssl rand -hex 32)"
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="绑定到 tailnet + token">
|
||||
```bash
|
||||
openclaw gateway --bind tailnet --token "$(openssl rand -hex 32)"
|
||||
```
|
||||
|
||||
然后打开:
|
||||
然后打开:
|
||||
|
||||
- `http://<tailscale-ip>:18789/`(或你配置的 `gateway.controlUi.basePath`)
|
||||
- `http://<tailscale-ip>:18789/`(或你配置的 `gateway.controlUi.basePath`)
|
||||
|
||||
将匹配的共享密钥粘贴到 UI 设置中(作为
|
||||
`connect.params.auth.token` 或 `connect.params.auth.password` 发送)。
|
||||
将匹配的共享密钥粘贴到 UI 设置中(作为 `connect.params.auth.token` 或 `connect.params.auth.password` 发送)。
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## 不安全的 HTTP
|
||||
|
||||
如果你通过明文 HTTP 打开仪表板(`http://<lan-ip>` 或 `http://<tailscale-ip>`),
|
||||
浏览器会运行在**非安全上下文**中,并阻止 WebCrypto。默认情况下,
|
||||
OpenClaw 会**阻止**没有设备身份的 Control UI 连接。
|
||||
如果你通过明文 HTTP(`http://<lan-ip>` 或 `http://<tailscale-ip>`)打开仪表板,浏览器会运行在**非安全上下文**中,并阻止 WebCrypto。默认情况下,OpenClaw 会**阻止**没有设备身份的控制 UI 连接。
|
||||
|
||||
文档化的例外情况:
|
||||
|
||||
- 仅限 localhost 的不安全 HTTP 兼容模式,使用 `gateway.controlUi.allowInsecureAuth=true`
|
||||
- 通过 `gateway.auth.mode: "trusted-proxy"` 成功进行 operator Control UI 认证
|
||||
- 紧急兜底 `gateway.controlUi.dangerouslyDisableDeviceAuth=true`
|
||||
- 通过 `gateway.auth.mode: "trusted-proxy"` 成功完成的操作员控制 UI 认证
|
||||
- 紧急兜底开关 `gateway.controlUi.dangerouslyDisableDeviceAuth=true`
|
||||
|
||||
**推荐修复方式:** 使用 HTTPS(Tailscale Serve)或在本地打开 UI:
|
||||
|
||||
- `https://<magicdns>/`(Serve)
|
||||
- `http://127.0.0.1:18789/`(在 gateway 主机上)
|
||||
|
||||
**不安全认证开关行为:**
|
||||
<AccordionGroup>
|
||||
<Accordion title="不安全认证开关行为">
|
||||
```json5
|
||||
{
|
||||
gateway: {
|
||||
controlUi: { allowInsecureAuth: true },
|
||||
bind: "tailnet",
|
||||
auth: { mode: "token", token: "replace-me" },
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
```json5
|
||||
{
|
||||
gateway: {
|
||||
controlUi: { allowInsecureAuth: true },
|
||||
bind: "tailnet",
|
||||
auth: { mode: "token", token: "replace-me" },
|
||||
},
|
||||
}
|
||||
```
|
||||
`allowInsecureAuth` 仅是本地兼容性开关:
|
||||
|
||||
`allowInsecureAuth` 只是一个本地兼容性开关:
|
||||
- 它允许 localhost 控制 UI 会话在非安全 HTTP 上下文中无设备身份继续运行。
|
||||
- 它不会绕过配对检查。
|
||||
- 它不会放宽远程(非 localhost)设备身份要求。
|
||||
|
||||
- 它允许 localhost Control UI 会话在非安全 HTTP 上下文中在没有设备身份的情况下继续进行。
|
||||
- 它不会绕过配对检查。
|
||||
- 它不会放宽远程(非 localhost)设备身份要求。
|
||||
</Accordion>
|
||||
<Accordion title="仅限紧急兜底">
|
||||
```json5
|
||||
{
|
||||
gateway: {
|
||||
controlUi: { dangerouslyDisableDeviceAuth: true },
|
||||
bind: "tailnet",
|
||||
auth: { mode: "token", token: "replace-me" },
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
**仅限紧急兜底:**
|
||||
<Warning>
|
||||
`dangerouslyDisableDeviceAuth` 会禁用控制 UI 设备身份检查,这是一次严重的安全降级。紧急使用后请尽快恢复。
|
||||
</Warning>
|
||||
|
||||
```json5
|
||||
{
|
||||
gateway: {
|
||||
controlUi: { dangerouslyDisableDeviceAuth: true },
|
||||
bind: "tailnet",
|
||||
auth: { mode: "token", token: "replace-me" },
|
||||
},
|
||||
}
|
||||
```
|
||||
</Accordion>
|
||||
<Accordion title="受信任代理说明">
|
||||
- 成功的受信任代理认证可以让**操作员**控制 UI 会话在没有设备身份的情况下接入。
|
||||
- 这**不适用于**节点角色控制 UI 会话。
|
||||
- 同主机 loopback 反向代理仍不满足受信任代理认证;请参见 [受信任代理认证](/zh-CN/gateway/trusted-proxy-auth)。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
`dangerouslyDisableDeviceAuth` 会禁用 Control UI 设备身份检查,这是一次严重的安全降级。紧急使用后请尽快恢复。
|
||||
|
||||
Trusted-proxy 说明:
|
||||
|
||||
- 成功的 trusted-proxy 认证可以允许**operator** Control UI 会话在没有设备身份的情况下接入
|
||||
- 这**不**适用于 node-role Control UI 会话
|
||||
- 同主机 loopback 反向代理仍然不满足 trusted-proxy 认证;请参阅
|
||||
[Trusted proxy auth](/zh-CN/gateway/trusted-proxy-auth)
|
||||
|
||||
有关 HTTPS 设置指导,请参阅 [Tailscale](/zh-CN/gateway/tailscale)。
|
||||
有关 HTTPS 设置指导,请参见 [Tailscale](/zh-CN/gateway/tailscale)。
|
||||
|
||||
## 内容安全策略
|
||||
|
||||
Control UI 内置了严格的 `img-src` 策略:仅允许**同源**资源、`data:` URL 和本地生成的 `blob:` URL。远程 `http(s)` 和协议相对图片 URL 会被浏览器拒绝,不会发起网络请求。
|
||||
控制 UI 采用严格的 `img-src` 策略:仅允许**同源**资源、`data:` URL 和本地生成的 `blob:` URL。远程 `http(s)` 和协议相对图片 URL 会被浏览器拒绝,并且不会发起网络获取。
|
||||
|
||||
这在实践中的含义如下:
|
||||
这在实际中的含义:
|
||||
|
||||
- 通过相对路径提供的头像和图片(例如 `/avatars/<id>`)仍然可以渲染,包括那些 UI 获取后转换为本地 `blob:` URL 的、需要认证的头像路由。
|
||||
- 内联 `data:image/...` URL 仍然可以渲染(这对协议内负载很有用)。
|
||||
- 由 Control UI 创建的本地 `blob:` URL 仍然可以渲染。
|
||||
- 渠道元数据输出的远程头像 URL 会在 Control UI 的头像辅助函数中被剥离,并替换为内置 logo/badge,因此即使某个渠道已被攻陷或存在恶意行为,也无法强迫 operator 浏览器发起任意远程图片请求。
|
||||
- 通过相对路径提供的头像和图片(例如 `/avatars/<id>`)仍可渲染,包括那些需要认证、由 UI 获取并转换为本地 `blob:` URL 的头像路由。
|
||||
- 内联 `data:image/...` URL 仍可渲染(对协议内负载很有用)。
|
||||
- 控制 UI 创建的本地 `blob:` 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 header 转发,并使用经过认证的 blob URL,因此图像仍能在仪表板中渲染。
|
||||
|
||||
如果你禁用 gateway 认证(不建议在共享主机上这样做),头像路由也会像 gateway 的其他部分一样变为无需认证。
|
||||
如果你禁用了 gateway 认证(不建议在共享主机上这样做),头像路由也会变为未认证状态,与其余 gateway 保持一致。
|
||||
|
||||
## 构建 UI
|
||||
|
||||
@ -322,56 +357,58 @@ Gateway 网关从 `dist/control-ui` 提供静态文件。使用以下命令构
|
||||
pnpm ui:build
|
||||
```
|
||||
|
||||
可选的绝对 base(当你希望使用固定资源 URL 时):
|
||||
可选的绝对 base(当你想使用固定资源 URL 时):
|
||||
|
||||
```bash
|
||||
OPENCLAW_CONTROL_UI_BASE_PATH=/openclaw/ pnpm ui:build
|
||||
```
|
||||
|
||||
用于本地开发(独立开发服务器):
|
||||
本地开发(独立 dev server):
|
||||
|
||||
```bash
|
||||
pnpm ui:dev
|
||||
```
|
||||
|
||||
然后将 UI 指向你的 Gateway WS URL(例如 `ws://127.0.0.1:18789`)。
|
||||
然后将 UI 指向你的 Gateway 网关 WS URL(例如 `ws://127.0.0.1:18789`)。
|
||||
|
||||
## 调试/测试:开发服务器 + 远程 Gateway
|
||||
## 调试/测试:dev server + 远程 Gateway 网关
|
||||
|
||||
Control UI 是静态文件;WebSocket 目标可配置,并且可以
|
||||
不同于 HTTP 来源。当你希望在本地使用 Vite 开发服务器,而 Gateway 网关运行在别处时,这非常有用。
|
||||
控制 UI 是静态文件;WebSocket 目标是可配置的,并且可以不同于 HTTP 源。这在你希望本地运行 Vite dev server、而 Gateway 网关运行在其他地方时非常有用。
|
||||
|
||||
1. 启动 UI 开发服务器:`pnpm ui:dev`
|
||||
2. 打开类似下面的 URL:
|
||||
<Steps>
|
||||
<Step title="启动 UI dev server">
|
||||
```bash
|
||||
pnpm ui:dev
|
||||
```
|
||||
</Step>
|
||||
<Step title="使用 gatewayUrl 打开">
|
||||
```text
|
||||
http://localhost:5173/?gatewayUrl=ws://<gateway-host>:18789
|
||||
```
|
||||
|
||||
```text
|
||||
http://localhost:5173/?gatewayUrl=ws://<gateway-host>:18789
|
||||
```
|
||||
可选的一次性认证(如果需要):
|
||||
|
||||
可选的一次性认证(如果需要):
|
||||
```text
|
||||
http://localhost:5173/?gatewayUrl=wss://<gateway-host>:18789#token=<gateway-token>
|
||||
```
|
||||
|
||||
```text
|
||||
http://localhost:5173/?gatewayUrl=wss://<gateway-host>:18789#token=<gateway-token>
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
说明:
|
||||
|
||||
- `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 网关启动时可能会根据生效的运行时 bind 和端口,自动填充本地 origin,如 `http://localhost:<port>` 和
|
||||
`http://127.0.0.1:<port>`,但远程浏览器 origin 仍然需要显式条目。
|
||||
- 除非是严格受控的本地测试,否则不要使用 `gateway.controlUi.allowedOrigins: ["*"]`。
|
||||
它表示允许任意浏览器 origin,而不是“匹配我正在
|
||||
使用的任意主机”。
|
||||
- `gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true` 会启用
|
||||
Host 标头 origin 回退模式,但这是一种危险的安全模式。
|
||||
<AccordionGroup>
|
||||
<Accordion title="说明">
|
||||
- `gatewayUrl` 会在加载后存储到 `localStorage` 中,并从 URL 中移除。
|
||||
- 应尽可能通过 URL 片段(`#token=...`)传递 `token`。片段不会发送到服务器,因此可避免请求日志和 Referer 泄露。遗留的 `?token=` 查询参数仍会出于兼容性导入一次,但仅作为回退,并会在引导后立即移除。
|
||||
- `password` 仅保存在内存中。
|
||||
- 设置了 `gatewayUrl` 时,UI 不会回退到配置或环境凭证。请显式提供 `token`(或 `password`)。缺少显式凭证会报错。
|
||||
- 当 Gateway 网关位于 TLS 后面时(Tailscale Serve、HTTPS 代理等),请使用 `wss://`。
|
||||
- `gatewayUrl` 仅在顶层窗口中接受(不接受嵌入式窗口),以防止点击劫持。
|
||||
- 非 loopback 控制 UI 部署必须显式设置 `gateway.controlUi.allowedOrigins`(完整 origin)。这也包括远程开发配置。
|
||||
- Gateway 网关启动时可能会根据有效运行时绑定和端口,自动填入本地 origin,例如 `http://localhost:<port>` 和 `http://127.0.0.1:<port>`,但远程浏览器 origin 仍需要显式条目。
|
||||
- 除了严格受控的本地测试外,不要使用 `gateway.controlUi.allowedOrigins: ["*"]`。它表示允许任何浏览器 origin,而不是“匹配我正在使用的任意主机”。
|
||||
- `gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true` 会启用 Host header origin 回退模式,但这是危险的安全模式。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
示例:
|
||||
|
||||
@ -385,11 +422,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 仪表板
|
||||
- [WebChat](/zh-CN/web/webchat) — 基于浏览器的聊天界面
|
||||
- [仪表板](/zh-CN/web/dashboard) — gateway 仪表板
|
||||
- [健康检查](/zh-CN/gateway/health) — gateway 健康监控
|
||||
- [TUI](/zh-CN/web/tui) — 终端用户界面
|
||||
- [Health Checks](/zh-CN/gateway/health) — gateway 健康监控
|
||||
- [WebChat](/zh-CN/web/webchat) — 基于浏览器的聊天界面
|
||||
|
||||
Loading…
Reference in New Issue
Block a user