chore(i18n): refresh zh-CN translations
This commit is contained in:
parent
9544aa6db4
commit
dabcf4fb21
@ -1,138 +1,146 @@
|
||||
---
|
||||
read_when:
|
||||
- 设置 BlueBubbles 渠道
|
||||
- 故障排除 webhook 配对
|
||||
- Webhook 配对故障排除
|
||||
- 在 macOS 上配置 iMessage
|
||||
summary: 通过 BlueBubbles macOS 服务器的 iMessage(REST 发送/接收、正在输入、回应、配对、高级操作)。
|
||||
sidebarTitle: BlueBubbles
|
||||
summary: 通过 BlueBubbles macOS 服务器使用 iMessage(REST 发送/接收、正在输入、表情回应、配对、高级操作)。
|
||||
title: BlueBubbles
|
||||
x-i18n:
|
||||
generated_at: "2026-04-26T04:50:07Z"
|
||||
generated_at: "2026-04-26T06:59:34Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 15ca98edc92fa6525167bd8ef814ae17d18bab72f445b75e5df7b361883392b4
|
||||
source_hash: d9a9eef02110f9e40f60c0bbd413c7ad7e33c377a7cf9ca2ae43aa170100ff77
|
||||
source_path: channels/bluebubbles.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
Status:内置插件,通过 HTTP 与 BlueBubbles macOS 服务器通信。由于其 API 更丰富且设置比旧版 `imsg` 渠道更简单,因此**推荐用于 iMessage 集成**。
|
||||
Status:通过 HTTP 与 BlueBubbles macOS 服务器通信的内置插件。由于其 API 更丰富且设置比旧版 imsg 渠道更简单,**推荐用于 iMessage 集成**。
|
||||
|
||||
## 内置插件
|
||||
|
||||
当前的 OpenClaw 版本已内置 BlueBubbles,因此普通打包构建**不需要**单独执行 `openclaw plugins install` 步骤。
|
||||
<Note>
|
||||
当前的 OpenClaw 发布版本已内置 BlueBubbles,因此普通打包构建不需要单独执行 `openclaw plugins install` 步骤。
|
||||
</Note>
|
||||
|
||||
## 概览
|
||||
|
||||
- 通过 BlueBubbles 辅助应用在 macOS 上运行([bluebubbles.app](https://bluebubbles.app))。
|
||||
- 推荐/已测试:macOS Sequoia(15)。macOS Tahoe(26)可用;但当前在 Tahoe 上编辑功能已损坏,群组图标更新也可能显示成功但不会同步。
|
||||
- OpenClaw 通过它的 REST API 与其通信(`GET /api/v1/ping`、`POST /message/text`、`POST /chat/:id/*`)。
|
||||
- 传入消息通过 webhook 到达;传出回复、输入指示器、已读回执和 tapback 都通过 REST 调用完成。
|
||||
- 附件和贴纸会作为入站媒体被接收(并在可能时提供给智能体)。
|
||||
- 会自动合成 MP3 或 CAF 音频的 Auto-TTS 回复,会以 iMessage 语音备忘录气泡的形式发送,而不是作为普通文件附件。
|
||||
- 配对/allowlist 的工作方式与其他渠道相同(`/channels/pairing` 等),使用 `channels.bluebubbles.allowFrom` + pairing 代码。
|
||||
- Reactions 会像 Slack/Telegram 一样作为系统事件呈现,因此智能体可以在回复前“提及”它们。
|
||||
- 高级功能:编辑、撤回、回复线程、消息效果、群组管理。
|
||||
- 推荐/已测试:macOS Sequoia(15)。macOS Tahoe(26)可用;当前在 Tahoe 上编辑功能不可用,群组图标更新也可能报告成功但不会同步。
|
||||
- OpenClaw 通过其 REST API 与它通信(`GET /api/v1/ping`、`POST /message/text`、`POST /chat/:id/*`)。
|
||||
- 传入消息通过 webhook 到达;传出回复、正在输入指示、已读回执和 tapback 都通过 REST 调用完成。
|
||||
- 附件和贴纸会作为入站媒体导入(并在可能时呈现给智能体)。
|
||||
- 自动 TTS 回复如果合成为 MP3 或 CAF 音频,将作为 iMessage 语音备忘录气泡发送,而不是普通文件附件。
|
||||
- 配对/allowlist 的工作方式与其他渠道相同(`/channels/pairing` 等),使用 `channels.bluebubbles.allowFrom` + 配对码。
|
||||
- 表情回应会像 Slack/Telegram 一样作为系统事件呈现,因此智能体可以在回复前“提及”它们。
|
||||
- 高级功能:编辑、撤回发送、回复线程、消息效果、群组管理。
|
||||
|
||||
## 快速开始
|
||||
|
||||
1. 在你的 Mac 上安装 BlueBubbles 服务器(按照 [bluebubbles.app/install](https://bluebubbles.app/install) 上的说明操作)。
|
||||
2. 在 BlueBubbles 配置中启用 web API 并设置密码。
|
||||
3. 运行 `openclaw onboard` 并选择 BlueBubbles,或手动配置:
|
||||
<Steps>
|
||||
<Step title="安装 BlueBubbles">
|
||||
在你的 Mac 上安装 BlueBubbles 服务器(按照 [bluebubbles.app/install](https://bluebubbles.app/install) 上的说明操作)。
|
||||
</Step>
|
||||
<Step title="启用 Web API">
|
||||
在 BlueBubbles 配置中,启用 Web API 并设置密码。
|
||||
</Step>
|
||||
<Step title="配置 OpenClaw">
|
||||
运行 `openclaw onboard` 并选择 BlueBubbles,或手动配置:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enabled: true,
|
||||
serverUrl: "http://192.168.1.100:1234",
|
||||
password: "example-password",
|
||||
webhookPath: "/bluebubbles-webhook",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
enabled: true,
|
||||
serverUrl: "http://192.168.1.100:1234",
|
||||
password: "example-password",
|
||||
webhookPath: "/bluebubbles-webhook",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
4. 将 BlueBubbles webhook 指向你的 Gateway 网关(示例:`https://your-gateway-host:3000/bluebubbles-webhook?password=<password>`)。
|
||||
5. 启动 Gateway 网关;它会注册 webhook 处理器并开始配对。
|
||||
</Step>
|
||||
<Step title="将 webhook 指向 Gateway 网关">
|
||||
将 BlueBubbles webhook 指向你的 Gateway 网关(示例:`https://your-gateway-host:3000/bluebubbles-webhook?password=<password>`)。
|
||||
</Step>
|
||||
<Step title="启动 Gateway 网关">
|
||||
启动 Gateway 网关;它会注册 webhook 处理器并开始配对。
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
安全说明:
|
||||
<Warning>
|
||||
**安全性**
|
||||
|
||||
- 始终设置 webhook 密码。
|
||||
- webhook 身份验证始终是必需的。无论 local loopback/代理拓扑如何,除非 BlueBubbles webhook 请求包含与 `channels.bluebubbles.password` 匹配的密码/guid(例如 `?password=<password>` 或 `x-password`),否则 OpenClaw 会拒绝这些请求。
|
||||
- 始终要求进行 webhook 身份验证。OpenClaw 会拒绝 BlueBubbles webhook 请求,除非它们包含与 `channels.bluebubbles.password` 匹配的 password/guid(例如 `?password=<password>` 或 `x-password`),无论 loopback/代理拓扑如何。
|
||||
- 在读取/解析完整 webhook 请求体之前,会先检查密码身份验证。
|
||||
</Warning>
|
||||
|
||||
## 保持 Messages.app 处于活跃状态(VM / 无头设置)
|
||||
## 保持 Messages.app 处于活动状态(VM / 无头设置)
|
||||
|
||||
某些 macOS VM / 常开设置中,Messages.app 可能会进入“空闲”状态(传入事件会停止,直到应用被打开/切到前台)。一个简单的解决方法是使用 AppleScript + LaunchAgent **每 5 分钟触碰一次 Messages**。
|
||||
某些 macOS VM / 常开设置可能会导致 Messages.app 进入“空闲”状态(在应用被打开/切到前台之前,传入事件会停止)。一个简单的变通方案是使用 AppleScript + LaunchAgent **每 5 分钟触发一次 Messages**。
|
||||
|
||||
### 1)保存 AppleScript
|
||||
<Steps>
|
||||
<Step title="保存 AppleScript">
|
||||
将以下内容保存为 `~/Scripts/poke-messages.scpt`:
|
||||
|
||||
将以下内容保存为:
|
||||
```applescript
|
||||
try
|
||||
tell application "Messages"
|
||||
if not running then
|
||||
launch
|
||||
end if
|
||||
|
||||
- `~/Scripts/poke-messages.scpt`
|
||||
-- Touch the scripting interface to keep the process responsive.
|
||||
set _chatCount to (count of chats)
|
||||
end tell
|
||||
on error
|
||||
-- Ignore transient failures (first-run prompts, locked session, etc).
|
||||
end try
|
||||
```
|
||||
|
||||
示例脚本(非交互式;不会抢占焦点):
|
||||
</Step>
|
||||
<Step title="安装 LaunchAgent">
|
||||
将以下内容保存为 `~/Library/LaunchAgents/com.user.poke-messages.plist`:
|
||||
|
||||
```applescript
|
||||
try
|
||||
tell application "Messages"
|
||||
if not running then
|
||||
launch
|
||||
end if
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.user.poke-messages</string>
|
||||
|
||||
-- Touch the scripting interface to keep the process responsive.
|
||||
set _chatCount to (count of chats)
|
||||
end tell
|
||||
on error
|
||||
-- Ignore transient failures (first-run prompts, locked session, etc).
|
||||
end try
|
||||
```
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/bin/bash</string>
|
||||
<string>-lc</string>
|
||||
<string>/usr/bin/osascript "$HOME/Scripts/poke-messages.scpt"</string>
|
||||
</array>
|
||||
|
||||
### 2)安装 LaunchAgent
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
||||
将以下内容保存为:
|
||||
<key>StartInterval</key>
|
||||
<integer>300</integer>
|
||||
|
||||
- `~/Library/LaunchAgents/com.user.poke-messages.plist`
|
||||
<key>StandardOutPath</key>
|
||||
<string>/tmp/poke-messages.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/tmp/poke-messages.err</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.user.poke-messages</string>
|
||||
这会**每 300 秒**运行一次,并且**在登录时**运行。首次运行可能会触发 macOS 的**自动化**提示(`osascript` → Messages)。请在运行该 LaunchAgent 的同一用户会话中批准这些提示。
|
||||
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/bin/bash</string>
|
||||
<string>-lc</string>
|
||||
<string>/usr/bin/osascript "$HOME/Scripts/poke-messages.scpt"</string>
|
||||
</array>
|
||||
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
||||
<key>StartInterval</key>
|
||||
<integer>300</integer>
|
||||
|
||||
<key>StandardOutPath</key>
|
||||
<string>/tmp/poke-messages.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/tmp/poke-messages.err</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
- 该任务会**每 300 秒**运行一次,并且会在**登录时**运行。
|
||||
- 首次运行时可能会触发 macOS 的**自动化**提示(`osascript` → Messages)。请在运行该 LaunchAgent 的同一用户会话中批准它们。
|
||||
|
||||
加载它:
|
||||
|
||||
```bash
|
||||
launchctl unload ~/Library/LaunchAgents/com.user.poke-messages.plist 2>/dev/null || true
|
||||
launchctl load ~/Library/LaunchAgents/com.user.poke-messages.plist
|
||||
```
|
||||
</Step>
|
||||
<Step title="加载它">
|
||||
```bash
|
||||
launchctl unload ~/Library/LaunchAgents/com.user.poke-messages.plist 2>/dev/null || true
|
||||
launchctl load ~/Library/LaunchAgents/com.user.poke-messages.plist
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## 新手引导
|
||||
|
||||
@ -144,11 +152,21 @@ openclaw onboard
|
||||
|
||||
向导会提示你输入:
|
||||
|
||||
- **Server URL**(必填):BlueBubbles 服务器地址(例如 `http://192.168.1.100:1234`)
|
||||
- **Password**(必填):BlueBubbles Server 设置中的 API 密码
|
||||
- **Webhook path**(可选):默认为 `/bluebubbles-webhook`
|
||||
- **DM policy**:pairing、allowlist、open 或 disabled
|
||||
- **Allow list**:电话号码、电子邮件地址或聊天目标
|
||||
<ParamField path="Server URL" type="string" required>
|
||||
BlueBubbles 服务器地址(例如 `http://192.168.1.100:1234`)。
|
||||
</ParamField>
|
||||
<ParamField path="Password" type="string" required>
|
||||
来自 BlueBubbles Server 设置的 API 密码。
|
||||
</ParamField>
|
||||
<ParamField path="Webhook path" type="string" default="/bluebubbles-webhook">
|
||||
Webhook 端点路径。
|
||||
</ParamField>
|
||||
<ParamField path="DM policy" type="string">
|
||||
`pairing`、`allowlist`、`open` 或 `disabled`。
|
||||
</ParamField>
|
||||
<ParamField path="Allow list" type="string[]">
|
||||
电话号码、电子邮件或聊天目标。
|
||||
</ParamField>
|
||||
|
||||
你也可以通过 CLI 添加 BlueBubbles:
|
||||
|
||||
@ -158,28 +176,29 @@ openclaw channels add bluebubbles --http-url http://192.168.1.100:1234 --passwor
|
||||
|
||||
## 访问控制(私信 + 群组)
|
||||
|
||||
私信:
|
||||
<Tabs>
|
||||
<Tab title="私信">
|
||||
- 默认值:`channels.bluebubbles.dmPolicy = "pairing"`。
|
||||
- 未知发送者会收到一个配对码;在获批之前,消息会被忽略(代码在 1 小时后过期)。
|
||||
- 通过以下命令批准:
|
||||
- `openclaw pairing list bluebubbles`
|
||||
- `openclaw pairing approve bluebubbles <CODE>`
|
||||
- 配对是默认的令牌交换方式。详情请参见:[Pairing](/zh-CN/channels/pairing)
|
||||
</Tab>
|
||||
<Tab title="群组">
|
||||
- `channels.bluebubbles.groupPolicy = open | allowlist | disabled`(默认:`allowlist`)。
|
||||
- 当设置为 `allowlist` 时,`channels.bluebubbles.groupAllowFrom` 用于控制哪些人可以在群组中触发。
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
- 默认值:`channels.bluebubbles.dmPolicy = "pairing"`。
|
||||
- 未知发送者会收到一个 pairing 代码;在获准之前,消息会被忽略(代码 1 小时后过期)。
|
||||
- 可通过以下方式批准:
|
||||
- `openclaw pairing list bluebubbles`
|
||||
- `openclaw pairing approve bluebubbles <CODE>`
|
||||
- Pairing 是默认的令牌交换方式。详情请参见:[Pairing](/zh-CN/channels/pairing)
|
||||
### 联系人名称增强(macOS,可选)
|
||||
|
||||
群组:
|
||||
BlueBubbles 群组 webhook 通常只包含原始参与者地址。如果你希望 `GroupMembers` 上下文改为显示本地联系人名称,可以选择在 macOS 上启用本地联系人增强:
|
||||
|
||||
- `channels.bluebubbles.groupPolicy = open | allowlist | disabled`(默认值:`allowlist`)。
|
||||
- 当设置为 `allowlist` 时,`channels.bluebubbles.groupAllowFrom` 用于控制谁可以在群组中触发。
|
||||
|
||||
### 联系人姓名增强(macOS,可选)
|
||||
|
||||
BlueBubbles 群组 webhook 通常只包含原始参与者地址。如果你希望 `GroupMembers` 上下文改为显示本地联系人姓名,可以在 macOS 上选择启用本地通讯录增强:
|
||||
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts = true` 可启用查找。默认值:`false`。
|
||||
- 查找仅会在群组访问、命令授权和提及门控允许消息通过之后运行。
|
||||
- 只会增强未命名的电话参与者。
|
||||
- 如果未找到本地匹配项,则仍会回退为原始电话号码。
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts = true` 启用查找。默认值:`false`。
|
||||
- 只有在群组访问、命令授权和提及门控都已允许该消息通过之后,才会执行查找。
|
||||
- 只有未命名的电话参与者会被增强。
|
||||
- 当未找到本地匹配项时,原始电话号码仍会作为回退值保留。
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -193,13 +212,13 @@ BlueBubbles 群组 webhook 通常只包含原始参与者地址。如果你希
|
||||
|
||||
### 提及门控(群组)
|
||||
|
||||
BlueBubbles 支持群聊提及门控,与 iMessage/WhatsApp 的行为一致:
|
||||
BlueBubbles 支持群聊中的提及门控,与 iMessage/WhatsApp 行为一致:
|
||||
|
||||
- 使用 `agents.list[].groupChat.mentionPatterns`(或 `messages.groupChat.mentionPatterns`)检测提及。
|
||||
- 当群组启用了 `requireMention` 时,智能体仅会在被提及时响应。
|
||||
- 当某个群组启用 `requireMention` 时,智能体只会在被提及时响应。
|
||||
- 来自已授权发送者的控制命令会绕过提及门控。
|
||||
|
||||
按群组配置:
|
||||
每个群组的配置:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -209,7 +228,7 @@ BlueBubbles 支持群聊提及门控,与 iMessage/WhatsApp 的行为一致:
|
||||
groupAllowFrom: ["+15555550123"],
|
||||
groups: {
|
||||
"*": { requireMention: true }, // 所有群组的默认值
|
||||
"iMessage;-;chat123": { requireMention: false }, // 针对特定群组的覆盖
|
||||
"iMessage;-;chat123": { requireMention: false }, // 覆盖特定群组
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -220,11 +239,11 @@ BlueBubbles 支持群聊提及门控,与 iMessage/WhatsApp 的行为一致:
|
||||
|
||||
- 控制命令(例如 `/config`、`/model`)需要授权。
|
||||
- 使用 `allowFrom` 和 `groupAllowFrom` 来确定命令授权。
|
||||
- 已授权发送者即使在群组中没有提及,也可以运行控制命令。
|
||||
- 已授权的发送者即使在群组中未提及,也可以运行控制命令。
|
||||
|
||||
### 按群组设置 systemPrompt
|
||||
### 每个群组的系统提示词
|
||||
|
||||
`channels.bluebubbles.groups.*` 下的每个条目都接受一个可选的 `systemPrompt` 字符串。该值会在该群组中处理消息的每一轮时注入到智能体的系统提示词中,因此你可以在不编辑智能体提示词的情况下,为每个群组设置人格或行为规则:
|
||||
`channels.bluebubbles.groups.*` 下的每个条目都接受一个可选的 `systemPrompt` 字符串。每次处理该群组中的消息时,这个值都会注入到智能体的系统提示词中,因此你可以为每个群组设置不同的人设或行为规则,而无需编辑智能体提示词:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -232,7 +251,7 @@ BlueBubbles 支持群聊提及门控,与 iMessage/WhatsApp 的行为一致:
|
||||
bluebubbles: {
|
||||
groups: {
|
||||
"iMessage;-;chat123": {
|
||||
systemPrompt: "将回复控制在 3 句以内。模仿该群组的随意语气。",
|
||||
systemPrompt: "Keep responses under 3 sentences. Mirror the group's casual tone.",
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -240,11 +259,11 @@ BlueBubbles 支持群聊提及门控,与 iMessage/WhatsApp 的行为一致:
|
||||
}
|
||||
```
|
||||
|
||||
该键与 BlueBubbles 报告的群组 `chatGuid` / `chatIdentifier` / 数字 `chatId` 相匹配,而 `"*"` 通配符条目则为所有没有精确匹配的群组提供默认值(与 `requireMention` 和按群组工具策略使用相同的模式)。精确匹配始终优先于通配符。私信会忽略此字段;请改用智能体级别或账户级别的提示词定制。
|
||||
该键会匹配 BlueBubbles 报告的 `chatGuid` / `chatIdentifier` / 数字 `chatId` 中的任意一种,而 `"*"` 通配符条目会为所有没有精确匹配的群组提供默认值(与 `requireMention` 和每组工具策略使用相同的模式)。精确匹配始终优先于通配符。私信会忽略此字段;请改用智能体级别或账户级别的提示词自定义。
|
||||
|
||||
#### 示例:线程回复与 tapback reactions(Private API)
|
||||
#### 示例:线程回复和 tapback 表情回应(Private API)
|
||||
|
||||
启用 BlueBubbles Private API 后,入站消息会带有简短消息 ID(例如 `[[reply_to:5]]`),智能体可以调用 `action=reply` 将回复串到特定消息下,或调用 `action=react` 添加一个 tapback。按群组设置 `systemPrompt` 是让智能体稳定选择正确工具的一种可靠方式:
|
||||
启用 BlueBubbles Private API 后,入站消息会附带短消息 ID(例如 `[[reply_to:5]]`),智能体可以调用 `action=reply` 以在线程中回复特定消息,或调用 `action=react` 发送一个 tapback。每个群组的 `systemPrompt` 是确保智能体选择正确工具的可靠方式:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -253,14 +272,13 @@ BlueBubbles 支持群聊提及门控,与 iMessage/WhatsApp 的行为一致:
|
||||
groups: {
|
||||
"iMessage;+;chat-family": {
|
||||
systemPrompt: [
|
||||
"在此群组中回复时,始终使用上下文中的",
|
||||
"[[reply_to:N]] messageId 调用 action=reply,",
|
||||
"这样你的回复会串在触发消息下方。",
|
||||
"绝不要发送一条新的、未关联的消息。",
|
||||
"When replying in this group, always call action=reply with the",
|
||||
"[[reply_to:N]] messageId from context so your response threads",
|
||||
"under the triggering message. Never send a new unlinked message.",
|
||||
"",
|
||||
"对于简短确认(‘ok’、‘got it’、‘on it’),",
|
||||
"请使用 action=react 搭配合适的 tapback emoji(❤️、👍、😂、‼️、❓),",
|
||||
"而不是发送文字回复。",
|
||||
"For short acknowledgements ('ok', 'got it', 'on it'), use",
|
||||
"action=react with an appropriate tapback emoji (❤️, 👍, 😂, ‼️, ❓)",
|
||||
"instead of sending a text reply.",
|
||||
].join(" "),
|
||||
},
|
||||
},
|
||||
@ -269,24 +287,24 @@ BlueBubbles 支持群聊提及门控,与 iMessage/WhatsApp 的行为一致:
|
||||
}
|
||||
```
|
||||
|
||||
Tapback reactions 和线程回复都需要 BlueBubbles Private API;底层机制请参见[高级操作](#advanced-actions)和[消息 ID](#message-ids-short-vs-full)。
|
||||
tapback 表情回应和线程回复都需要 BlueBubbles Private API;底层机制请参见 [Advanced actions](#advanced-actions) 和 [Message IDs](#message-ids-short-vs-full)。
|
||||
|
||||
## ACP 会话绑定
|
||||
|
||||
BlueBubbles 聊天可以转换为持久的 ACP 工作区,而无需更改传输层。
|
||||
BlueBubbles 聊天可以在不改变传输层的情况下转换为持久 ACP 工作区。
|
||||
|
||||
快速操作流程:
|
||||
|
||||
- 在私信或允许的群聊中运行 `/acp spawn codex --bind here`。
|
||||
- 之后,该 BlueBubbles 会话中的消息会路由到已生成的 ACP 会话。
|
||||
- `/new` 和 `/reset` 会在原地重置同一个已绑定的 ACP 会话。
|
||||
- 该 BlueBubbles 会话中的后续消息会路由到新创建的 ACP 会话。
|
||||
- `/new` 和 `/reset` 会在原位置重置同一个已绑定的 ACP 会话。
|
||||
- `/acp close` 会关闭 ACP 会话并移除绑定。
|
||||
|
||||
也支持通过顶层 `bindings[]` 条目配置持久绑定,其中 `type: "acp"` 且 `match.channel: "bluebubbles"`。
|
||||
也支持通过顶层 `bindings[]` 条目配置持久绑定,使用 `type: "acp"` 和 `match.channel: "bluebubbles"`。
|
||||
|
||||
`match.peer.id` 可以使用任何受支持的 BlueBubbles 目标形式:
|
||||
`match.peer.id` 可以使用任何受支持的 BlueBubbles 目标格式:
|
||||
|
||||
- 规范化的私信句柄,例如 `+15555550123` 或 `user@example.com`
|
||||
- 规范化的私信标识,例如 `+15555550123` 或 `user@example.com`
|
||||
- `chat_id:<id>`
|
||||
- `chat_guid:<guid>`
|
||||
- `chat_identifier:<identifier>`
|
||||
@ -327,9 +345,9 @@ BlueBubbles 聊天可以转换为持久的 ACP 工作区,而无需更改传输
|
||||
|
||||
## 正在输入 + 已读回执
|
||||
|
||||
- **输入指示器**:会在生成回复之前和期间自动发送。
|
||||
- **已读回执**:由 `channels.bluebubbles.sendReadReceipts` 控制(默认值:`true`)。
|
||||
- **输入指示器**:OpenClaw 会发送输入开始事件;BlueBubbles 会在发送消息或超时后自动清除输入状态(通过 DELETE 手动停止并不可靠)。
|
||||
- **正在输入指示**:会在生成回复之前和期间自动发送。
|
||||
- **已读回执**:由 `channels.bluebubbles.sendReadReceipts` 控制(默认:`true`)。
|
||||
- **正在输入指示**:OpenClaw 会发送开始输入事件;BlueBubbles 会在发送完成或超时后自动清除输入状态(通过 DELETE 手动停止并不可靠)。
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -350,8 +368,8 @@ BlueBubbles 在配置中启用后支持高级消息操作:
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
actions: {
|
||||
reactions: true, // tapback(默认:true)
|
||||
edit: true, // 编辑已发送消息(macOS 13+,在 macOS 26 Tahoe 上已损坏)
|
||||
reactions: true, // tapback 表情回应(默认:true)
|
||||
edit: true, // 编辑已发送消息(macOS 13+,在 macOS 26 Tahoe 上不可用)
|
||||
unsend: true, // 撤回消息(macOS 13+)
|
||||
reply: true, // 按消息 GUID 进行线程回复
|
||||
sendWithEffect: true, // 消息效果(slam、loud 等)
|
||||
@ -359,7 +377,7 @@ BlueBubbles 在配置中启用后支持高级消息操作:
|
||||
setGroupIcon: true, // 设置群聊图标/照片(在 macOS 26 Tahoe 上不稳定)
|
||||
addParticipant: true, // 向群组添加参与者
|
||||
removeParticipant: true, // 从群组移除参与者
|
||||
leaveGroup: true, // 离开群聊
|
||||
leaveGroup: true, // 退出群聊
|
||||
sendAttachment: true, // 发送附件/媒体
|
||||
},
|
||||
},
|
||||
@ -367,21 +385,23 @@ BlueBubbles 在配置中启用后支持高级消息操作:
|
||||
}
|
||||
```
|
||||
|
||||
可用操作:
|
||||
|
||||
- **react**:添加/移除 tapback reactions(`messageId`、`emoji`、`remove`)。iMessage 原生的 tapback 集合为 `love`、`like`、`dislike`、`laugh`、`emphasize` 和 `question`。当智能体选择了该集合之外的 emoji(例如 `👀`)时,reaction 工具会回退到 `love`,这样 tapback 仍能显示,而不会导致整个请求失败。已配置的确认 reactions 仍会严格校验,并在值未知时报错。
|
||||
- **edit**:编辑已发送消息(`messageId`、`text`)
|
||||
- **unsend**:撤回消息(`messageId`)
|
||||
- **reply**:回复特定消息(`messageId`、`text`、`to`)
|
||||
- **sendWithEffect**:使用 iMessage 效果发送(`text`、`to`、`effectId`)
|
||||
- **renameGroup**:重命名群聊(`chatGuid`、`displayName`)
|
||||
- **setGroupIcon**:设置群聊图标/照片(`chatGuid`、`media`)—— 在 macOS 26 Tahoe 上不稳定(API 可能返回成功,但图标不会同步)。
|
||||
- **addParticipant**:向群组添加成员(`chatGuid`、`address`)
|
||||
- **removeParticipant**:从群组移除成员(`chatGuid`、`address`)
|
||||
- **leaveGroup**:离开群聊(`chatGuid`)
|
||||
- **upload-file**:发送媒体/文件(`to`、`buffer`、`filename`、`asVoice`)
|
||||
- 语音备忘录:设置 `asVoice: true`,并使用 **MP3** 或 **CAF** 音频,以 iMessage 语音消息形式发送。BlueBubbles 在发送语音备忘录时会将 MP3 转换为 CAF。
|
||||
- 旧别名:`sendAttachment` 仍然可用,但 `upload-file` 是规范的操作名称。
|
||||
<AccordionGroup>
|
||||
<Accordion title="可用操作">
|
||||
- **react**:添加/移除 tapback 表情回应(`messageId`、`emoji`、`remove`)。iMessage 原生的 tapback 集合为 `love`、`like`、`dislike`、`laugh`、`emphasize` 和 `question`。当智能体选择了集合之外的 emoji(例如 `👀`)时,表情回应工具会回退为 `love`,这样 tapback 仍然可以渲染,而不是让整个请求失败。已配置的确认表情回应仍会严格校验,并在值未知时报错。
|
||||
- **edit**:编辑已发送消息(`messageId`、`text`)。
|
||||
- **unsend**:撤回消息(`messageId`)。
|
||||
- **reply**:回复特定消息(`messageId`、`text`、`to`)。
|
||||
- **sendWithEffect**:使用 iMessage 效果发送(`text`、`to`、`effectId`)。
|
||||
- **renameGroup**:重命名群聊(`chatGuid`、`displayName`)。
|
||||
- **setGroupIcon**:设置群聊图标/照片(`chatGuid`、`media`)—— 在 macOS 26 Tahoe 上不稳定(API 可能返回成功,但图标不会同步)。
|
||||
- **addParticipant**:向群组添加某人(`chatGuid`、`address`)。
|
||||
- **removeParticipant**:从群组移除某人(`chatGuid`、`address`)。
|
||||
- **leaveGroup**:退出群聊(`chatGuid`)。
|
||||
- **upload-file**:发送媒体/文件(`to`、`buffer`、`filename`、`asVoice`)。
|
||||
- 语音备忘录:将 `asVoice: true` 与 **MP3** 或 **CAF** 音频一起使用,以作为 iMessage 语音消息发送。BlueBubbles 在发送语音备忘录时会将 MP3 转换为 CAF。
|
||||
- 旧别名:`sendAttachment` 仍然可用,但 `upload-file` 是规范操作名称。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### 消息 ID(短 ID 与完整 ID)
|
||||
|
||||
@ -389,153 +409,183 @@ OpenClaw 可能会显示_短_消息 ID(例如 `1`、`2`)以节省 token。
|
||||
|
||||
- `MessageSid` / `ReplyToId` 可以是短 ID。
|
||||
- `MessageSidFull` / `ReplyToIdFull` 包含提供商的完整 ID。
|
||||
- 短 ID 存储于内存中;在重启或缓存逐出后可能失效。
|
||||
- 操作接受短或完整 `messageId`,但如果短 ID 已不可用,将会报错。
|
||||
- 短 ID 仅存在于内存中;它们可能会在重启或缓存逐出后失效。
|
||||
- 操作接受短或完整 `messageId`,但如果短 ID 不再可用,就会报错。
|
||||
|
||||
对于持久自动化和存储,请使用完整 ID:
|
||||
|
||||
- 模板:`{{MessageSidFull}}`、`{{ReplyToIdFull}}`
|
||||
- 上下文:入站负载中的 `MessageSidFull` / `ReplyToIdFull`
|
||||
|
||||
模板变量请参见[配置](/zh-CN/gateway/configuration)。
|
||||
模板变量请参见 [配置](/zh-CN/gateway/configuration)。
|
||||
|
||||
<a id="coalescing-split-send-dms-command--url-in-one-composition"></a>
|
||||
|
||||
## 合并拆分发送的私信(单次输入中的命令 + URL)
|
||||
## 合并拆分发送的私信(一次输入中的命令 + URL)
|
||||
|
||||
当用户在 iMessage 中将命令和 URL 一起输入时——例如 `Dump https://example.com/article`——Apple 会将这次发送拆成**两次独立的 webhook 投递**:
|
||||
当用户在 iMessage 中同时输入命令和 URL 时——例如 `Dump https://example.com/article`——Apple 会将发送拆分为**两个独立的 webhook 投递**:
|
||||
|
||||
1. 一条文本消息(`"Dump"`)。
|
||||
2. 一个 URL 预览气泡(`"https://..."`),并带有 OG 预览图片作为附件。
|
||||
2. 一个 URL 预览气泡(`"https://..."`),其 OG 预览图片作为附件发送。
|
||||
|
||||
在大多数设置中,这两个 webhook 会相隔约 0.8-2.0 秒到达 OpenClaw。如果不进行合并,智能体会在第 1 轮只收到命令,于是作出回复(通常是“把 URL 发给我”),直到第 2 轮才看到 URL——这时命令上下文已经丢失。
|
||||
在大多数设置中,这两个 webhook 会相隔约 0.8 - 2.0 秒到达 OpenClaw。如果不进行合并,智能体在第 1 轮只会收到命令本身,随后作出回复(通常是“把 URL 发给我”),直到第 2 轮才看到 URL —— 到那时命令上下文已经丢失。
|
||||
|
||||
`channels.bluebubbles.coalesceSameSenderDms` 可让私信将来自同一发送者的连续 webhook 合并为单个智能体轮次。群聊则继续按每条消息分别处理,以保留多用户轮次结构。
|
||||
`channels.bluebubbles.coalesceSameSenderDms` 可让私信选择启用:将来自同一发送者、连续到达的 webhook 合并为同一个智能体轮次。群聊仍会按每条消息分别处理,从而保留多用户的轮次结构。
|
||||
|
||||
### 何时启用
|
||||
<Tabs>
|
||||
<Tab title="何时启用">
|
||||
在以下情况下启用:
|
||||
|
||||
在以下情况下启用:
|
||||
- 你提供的 Skills 期望在一条消息中收到 `command + payload`(dump、paste、save、queue 等)。
|
||||
- 你的用户会把 URL、图片或长内容与命令一起粘贴发送。
|
||||
- 你可以接受私信轮次增加的延迟(见下文)。
|
||||
|
||||
- 你提供的 Skills 期望在一条消息中接收 `命令 + 负载`(dump、paste、save、queue 等)。
|
||||
- 你的用户会将 URL、图片或长内容与命令一起粘贴发送。
|
||||
- 你可以接受增加的私信轮次延迟(见下文)。
|
||||
在以下情况下保持禁用:
|
||||
|
||||
在以下情况下保持禁用:
|
||||
- 你需要单词型私信触发命令的最低延迟。
|
||||
- 你的所有流程都是不带后续负载的一次性命令。
|
||||
|
||||
- 你需要单词私信触发命令的最低延迟。
|
||||
- 你的所有流程都是不带后续负载的一次性命令。
|
||||
</Tab>
|
||||
<Tab title="启用方式">
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
coalesceSameSenderDms: true, // 选择启用(默认:false)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 启用方式
|
||||
启用该标志且未显式设置 `messages.inbound.byChannel.bluebubbles` 时,去抖窗口会扩大到 **2500 ms**(不启用合并时的默认值为 500 ms)。这个更大的窗口是必需的——Apple 0.8 - 2.0 秒的拆分发送节奏无法适配更紧的默认窗口。
|
||||
|
||||
如果你想自行调整窗口:
|
||||
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
inbound: {
|
||||
byChannel: {
|
||||
// 2500 ms 适用于大多数设置;如果你的 Mac 较慢
|
||||
// 或处于内存压力下(观察到的间隔可能会超过 2 秒),请提高到 4000 ms。
|
||||
bluebubbles: 2500,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Tab>
|
||||
<Tab title="权衡">
|
||||
- **私信控制命令会增加延迟。** 启用该标志后,私信控制命令消息(如 `Dump`、`Save` 等)在分发前会等待最多一个去抖窗口,以防后续还有负载 webhook 到来。群聊命令仍保持即时分发。
|
||||
- **合并后的输出有上限**—— 合并文本最多 4000 个字符,并带有明确的 `…[truncated]` 标记;附件最多 20 个;源条目最多 10 个(超出后保留第一条和最新条目)。每个源 `messageId` 仍会进入入站去重,因此后续如果 MessagePoller 重放任意单个事件,仍会被识别为重复。
|
||||
- **按渠道选择启用。** 其他渠道(Telegram、WhatsApp、Slack、……)不受影响。
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
### 场景以及智能体看到的内容
|
||||
|
||||
| 用户输入内容 | Apple 投递内容 | 标志关闭(默认) | 标志开启 + 2500 ms 窗口 |
|
||||
| ------------------------------------------------------------------ | ------------------------- | --------------------------------------- | ----------------------------------------------------------------------- |
|
||||
| `Dump https://example.com`(一次发送) | 2 个 webhook,相隔约 1 秒 | 两个智能体轮次:“Dump” 单独一轮,然后是 URL | 一个轮次:合并文本 `Dump https://example.com` |
|
||||
| `Save this 📎image.jpg caption`(附件 + 文本) | 2 个 webhook | 两个轮次 | 一个轮次:文本 + 图片 |
|
||||
| `/status`(独立命令) | 1 个 webhook | 即时分发 | **最多等待一个窗口,然后分发** |
|
||||
| 单独粘贴的 URL | 1 个 webhook | 即时分发 | 即时分发(桶中只有一个条目) |
|
||||
| 文本 + URL 作为两条有意分开发送的消息,间隔数分钟 | 超出窗口的 2 个 webhook | 两个轮次 | 两个轮次(窗口会在它们之间过期) |
|
||||
| 快速洪泛(窗口内 >10 条小型私信) | N 个 webhook | N 个轮次 | 一个轮次,输出有界(应用第一条 + 最新条目、文本/附件上限) |
|
||||
|
||||
### 拆分发送合并故障排除
|
||||
|
||||
如果该标志已启用,但拆分发送仍然以两个轮次到达,请逐层检查:
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="配置是否已实际加载">
|
||||
```
|
||||
grep coalesceSameSenderDms ~/.openclaw/openclaw.json
|
||||
```
|
||||
|
||||
然后执行 `openclaw gateway restart` —— 该标志会在 debouncer-registry 创建时读取。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="去抖窗口对你的设置是否足够宽">
|
||||
查看位于 `~/Library/Logs/bluebubbles-server/main.log` 的 BlueBubbles 服务器日志:
|
||||
|
||||
```
|
||||
grep -E "Dispatching event to webhook" main.log | tail -20
|
||||
```
|
||||
|
||||
测量 `"Dump"` 这类文本分发与随后 `"https://..."; Attachments:` 分发之间的间隔。将 `messages.inbound.byChannel.bluebubbles` 提高到足以覆盖该间隔的值。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="会话 JSONL 时间戳 ≠ webhook 到达时间">
|
||||
会话事件时间戳(`~/.openclaw/agents/<id>/sessions/*.jsonl`)反映的是 Gateway 网关何时将消息交给智能体,**而不是** webhook 何时到达。若排队中的第二条消息被标记为 `[Queued messages while agent was busy]`,表示第一个轮次在第二个 webhook 到达时仍在运行—— 合并桶已经刷新。请根据 BB 服务器日志而不是会话日志来调整窗口。
|
||||
</Accordion>
|
||||
<Accordion title="内存压力导致回复分发变慢">
|
||||
在较小的机器(8 GB)上,智能体轮次可能会耗时到让合并桶在回复完成前就已刷新,而 URL 会作为排队的第二轮到达。检查 `memory_pressure` 和 `ps -o rss -p $(pgrep openclaw-gateway)`;如果 Gateway 网关超过约 500 MB RSS 且压缩器处于活动状态,请关闭其他高负载进程,或升级到更大的主机。
|
||||
</Accordion>
|
||||
<Accordion title="引用回复发送走的是另一条路径">
|
||||
如果用户将 `Dump` 作为对已有 URL 气泡的**回复**发送(iMessage 会在 Dump 气泡上显示 “1 Reply” 标记),则 URL 位于 `replyToBody` 中,而不是第二个 webhook 中。此时不适用合并—— 这是 Skills/提示词问题,而不是 debouncer 问题。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 分块流式传输
|
||||
|
||||
控制回复是作为单条消息发送,还是按块流式发送:
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
bluebubbles: {
|
||||
coalesceSameSenderDms: true, // 选择启用(默认:false)
|
||||
blockStreaming: true, // 启用分块流式传输(默认关闭)
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
启用该标志后,如果未显式设置 `messages.inbound.byChannel.bluebubbles`,防抖窗口会扩展到 **2500 ms**(非合并模式的默认值为 500 ms)。需要更宽的窗口——Apple 的拆分发送节奏为 0.8-2.0 秒,无法落入更紧的默认窗口。
|
||||
|
||||
如需自行调整窗口:
|
||||
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
inbound: {
|
||||
byChannel: {
|
||||
// 2500 ms 适用于大多数设置;如果你的 Mac 较慢
|
||||
// 或处于内存压力下(观察到间隔可能会超过 2 秒),可提高到 4000 ms。
|
||||
bluebubbles: 2500,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 权衡
|
||||
|
||||
- **私信控制命令的延迟增加。** 启用该标志后,私信控制命令消息(如 `Dump`、`Save` 等)现在会在分发前最多等待一个防抖窗口,以防后续还有负载 webhook 到来。群聊命令仍保持即时分发。
|
||||
- **合并输出是有界的**——合并文本上限为 4000 个字符,并带有显式的 `…[truncated]` 标记;附件上限为 20;源条目上限为 10(超过后保留首条和最新条)。每个源 `messageId` 仍会进入入站去重,因此之后若 MessagePoller 重放任意单个事件,仍会被识别为重复项。
|
||||
- **按渠道选择启用。** 其他渠道(Telegram、WhatsApp、Slack、……)不受影响。
|
||||
|
||||
### 场景以及智能体看到的内容
|
||||
|
||||
| 用户输入内容 | Apple 投递方式 | 标志关闭(默认) | 标志开启 + 2500 ms 窗口 |
|
||||
| ------------------------------------------------------------------ | ------------------------- | --------------------------------------- | ----------------------------------------------------------------------- |
|
||||
| `Dump https://example.com`(一次发送) | 2 个 webhook,相隔约 1 秒 | 两个智能体轮次:仅有 “Dump”,然后是 URL | 一个轮次:合并文本 `Dump https://example.com` |
|
||||
| `Save this 📎image.jpg caption`(附件 + 文本) | 2 个 webhook | 两个轮次 | 一个轮次:文本 + 图片 |
|
||||
| `/status`(独立命令) | 1 个 webhook | 即时分发 | **最多等待整个窗口后再分发** |
|
||||
| 单独粘贴的 URL | 1 个 webhook | 即时分发 | 即时分发(桶中只有一个条目) |
|
||||
| 文本 + URL 故意分成两条消息发送,相隔数分钟 | 2 个 webhook,超出窗口 | 两个轮次 | 两个轮次(窗口已在它们之间过期) |
|
||||
| 快速洪泛(窗口内超过 10 条小型私信) | N 个 webhook | N 个轮次 | 一个轮次,有界输出(应用首条 + 最新条保留、文本/附件上限) |
|
||||
|
||||
### 拆分发送合并的故障排除
|
||||
|
||||
如果标志已开启,但拆分发送仍然作为两个轮次到达,请检查每一层:
|
||||
|
||||
1. **配置是否确实已加载。**
|
||||
|
||||
```
|
||||
grep coalesceSameSenderDms ~/.openclaw/openclaw.json
|
||||
```
|
||||
|
||||
然后执行 `openclaw gateway restart` —— 该标志会在 debouncer-registry 创建时读取。
|
||||
|
||||
2. **你的设置是否有足够宽的防抖窗口。** 查看 `~/Library/Logs/bluebubbles-server/main.log` 下的 BlueBubbles 服务器日志:
|
||||
|
||||
```
|
||||
grep -E "Dispatching event to webhook" main.log | tail -20
|
||||
```
|
||||
|
||||
测量 `"Dump"` 这类文本投递与其后 `"https://..."`; Attachments:` 投递之间的间隔。将 `messages.inbound.byChannel.bluebubbles` 调高到能够从容覆盖该间隔。
|
||||
|
||||
3. **会话 JSONL 时间戳 ≠ webhook 到达时间。** 会话事件时间戳(`~/.openclaw/agents/<id>/sessions/*.jsonl`)反映的是 Gateway 网关何时将消息交给智能体,**而不是** webhook 何时到达。如果排队中的第二条消息带有 `[Queued messages while agent was busy]` 标签,说明第二个 webhook 到达时,第一轮仍在运行——合并桶已经刷新。请根据 BB 服务器日志而不是会话日志来调整窗口。
|
||||
|
||||
4. **内存压力导致回复分发变慢。** 在较小的机器(8 GB)上,智能体轮次可能耗时较长,导致在回复完成前合并桶就已刷新,URL 于是作为排队的第二轮消息到达。检查 `memory_pressure` 和 `ps -o rss -p $(pgrep openclaw-gateway)`;如果 Gateway 网关 RSS 超过约 500 MB 且压缩器处于活跃状态,请关闭其他高负载进程或升级到更大的主机。
|
||||
|
||||
5. **回复引用发送是另一条路径。** 如果用户将 `Dump` 作为对现有 URL 气泡的**回复**发送(iMessage 会在 Dump 气泡上显示 “1 Reply” 标记),那么 URL 位于 `replyToBody` 中,而不是第二个 webhook。此时合并机制不适用——这是 Skills/提示词问题,而不是防抖器问题。
|
||||
|
||||
## 分块流式传输
|
||||
|
||||
控制响应是作为单条消息发送,还是按块流式发送:
|
||||
__OC_I18N_900017__
|
||||
## 媒体 + 限制
|
||||
|
||||
- 入站附件会被下载并存储到媒体缓存中。
|
||||
- 入站和出站媒体都通过 `channels.bluebubbles.mediaMaxMb` 限制媒体大小(默认:8 MB)。
|
||||
- 入站附件会被下载并存储在媒体缓存中。
|
||||
- 入站和出站媒体可通过 `channels.bluebubbles.mediaMaxMb` 设置媒体大小上限(默认:8 MB)。
|
||||
- 出站文本会按 `channels.bluebubbles.textChunkLimit` 分块(默认:4000 个字符)。
|
||||
|
||||
## 配置参考
|
||||
|
||||
完整配置:[配置](/gateway/configuration)
|
||||
完整配置: [配置](/zh-CN/gateway/configuration)
|
||||
|
||||
提供商选项:
|
||||
|
||||
- `channels.bluebubbles.enabled`:启用/禁用该渠道。
|
||||
- `channels.bluebubbles.serverUrl`:BlueBubbles REST API 基础 URL。
|
||||
- `channels.bluebubbles.password`:API 密码。
|
||||
- `channels.bluebubbles.webhookPath`:webhook 端点路径(默认:`/bluebubbles-webhook`)。
|
||||
- `channels.bluebubbles.dmPolicy`:`pairing | allowlist | open | disabled`(默认:`pairing`)。
|
||||
- `channels.bluebubbles.allowFrom`:私信 allowlist(句柄、电子邮件、E.164 号码、`chat_id:*`、`chat_guid:*`)。
|
||||
- `channels.bluebubbles.groupPolicy`:`open | allowlist | disabled`(默认:`allowlist`)。
|
||||
- `channels.bluebubbles.groupAllowFrom`:群组发送者 allowlist。
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts`:在 macOS 上,可在门控通过后选择性地从本地通讯录增强未命名的群组参与者。默认:`false`。
|
||||
- `channels.bluebubbles.groups`:按群组配置(`requireMention` 等)。
|
||||
- `channels.bluebubbles.sendReadReceipts`:发送已读回执(默认:`true`)。
|
||||
- `channels.bluebubbles.blockStreaming`:启用分块流式传输(默认:`false`;流式回复需要启用)。
|
||||
- `channels.bluebubbles.textChunkLimit`:出站分块大小,单位为字符(默认:4000)。
|
||||
- `channels.bluebubbles.sendTimeoutMs`:通过 `/api/v1/message/text` 发送出站文本时,每个请求的超时时间(毫秒,默认:30000)。在 macOS 26 设置中,如果 Private API iMessage 发送可能在 iMessage 框架内部停滞 60+ 秒,请调高此值;例如 `45000` 或 `60000`。探测、聊天查询、reactions、编辑和健康检查目前仍保持较短的 10 秒默认值;后续计划扩展到 reactions 和编辑。按账户覆盖:`channels.bluebubbles.accounts.<accountId>.sendTimeoutMs`。
|
||||
- `channels.bluebubbles.chunkMode`:`length`(默认)仅在超过 `textChunkLimit` 时分割;`newline` 会先按空行(段落边界)分割,然后再按长度分块。
|
||||
- `channels.bluebubbles.mediaMaxMb`:入站/出站媒体大小上限,单位为 MB(默认:8)。
|
||||
- `channels.bluebubbles.mediaLocalRoots`:允许用于出站本地媒体路径的绝对本地目录显式 allowlist。默认情况下,除非配置此项,否则会拒绝本地路径发送。按账户覆盖:`channels.bluebubbles.accounts.<accountId>.mediaLocalRoots`。
|
||||
- `channels.bluebubbles.coalesceSameSenderDms`:将同一发送者的连续私信 webhook 合并为一个智能体轮次,以便 Apple 的“文本 + URL”拆分发送作为一条消息到达(默认:`false`)。有关场景、窗口调优和权衡,请参见[合并拆分发送的私信](#coalescing-split-send-dms-command--url-in-one-composition)。如果启用且未显式设置 `messages.inbound.byChannel.bluebubbles`,默认入站防抖窗口会从 500 ms 扩大到 2500 ms。
|
||||
- `channels.bluebubbles.historyLimit`:用于上下文的群组消息最大数量(0 表示禁用)。
|
||||
- `channels.bluebubbles.dmHistoryLimit`:私信历史记录上限。
|
||||
- `channels.bluebubbles.actions`:启用/禁用特定操作。
|
||||
- `channels.bluebubbles.accounts`:多账户配置。
|
||||
<AccordionGroup>
|
||||
<Accordion title="连接与 webhook">
|
||||
- `channels.bluebubbles.enabled`:启用/禁用该渠道。
|
||||
- `channels.bluebubbles.serverUrl`:BlueBubbles REST API 基础 URL。
|
||||
- `channels.bluebubbles.password`:API 密码。
|
||||
- `channels.bluebubbles.webhookPath`:Webhook 端点路径(默认:`/bluebubbles-webhook`)。
|
||||
</Accordion>
|
||||
<Accordion title="访问策略">
|
||||
- `channels.bluebubbles.dmPolicy`:`pairing | allowlist | open | disabled`(默认:`pairing`)。
|
||||
- `channels.bluebubbles.allowFrom`:私信 allowlist(handle、电子邮件、E.164 号码、`chat_id:*`、`chat_guid:*`)。
|
||||
- `channels.bluebubbles.groupPolicy`:`open | allowlist | disabled`(默认:`allowlist`)。
|
||||
- `channels.bluebubbles.groupAllowFrom`:群组发送者 allowlist。
|
||||
- `channels.bluebubbles.enrichGroupParticipantsFromContacts`:在 macOS 上,可在门控通过后选择性地从本地联系人中增强未命名的群组参与者信息。默认:`false`。
|
||||
- `channels.bluebubbles.groups`:每个群组的配置(`requireMention` 等)。
|
||||
</Accordion>
|
||||
<Accordion title="投递与分块">
|
||||
- `channels.bluebubbles.sendReadReceipts`:发送已读回执(默认:`true`)。
|
||||
- `channels.bluebubbles.blockStreaming`:启用分块流式传输(默认:`false`;流式回复所必需)。
|
||||
- `channels.bluebubbles.textChunkLimit`:出站分块的字符数上限(默认:4000)。
|
||||
- `channels.bluebubbles.sendTimeoutMs`:通过 `/api/v1/message/text` 发送出站文本时,每个请求的超时时间(毫秒,默认:30000)。在 macOS 26 设置中,如果 Private API 的 iMessage 发送可能在 iMessage 框架内部卡住 60+ 秒,请调高该值;例如 `45000` 或 `60000`。探测、聊天查找、表情回应、编辑和健康检查当前仍保持较短的 10 秒默认值;后续计划将扩展覆盖到表情回应和编辑。每个账户的覆盖项:`channels.bluebubbles.accounts.<accountId>.sendTimeoutMs`。
|
||||
- `channels.bluebubbles.chunkMode`:`length`(默认)仅在超过 `textChunkLimit` 时拆分;`newline` 会先按空行(段落边界)拆分,再按长度分块。
|
||||
</Accordion>
|
||||
<Accordion title="媒体与历史记录">
|
||||
- `channels.bluebubbles.mediaMaxMb`:入站/出站媒体大小上限(MB,默认:8)。
|
||||
- `channels.bluebubbles.mediaLocalRoots`:允许用于出站本地媒体路径的绝对本地目录显式 allowlist。默认会拒绝发送本地路径,除非已配置该项。每个账户的覆盖项:`channels.bluebubbles.accounts.<accountId>.mediaLocalRoots`。
|
||||
- `channels.bluebubbles.coalesceSameSenderDms`:将来自同一发送者、连续到达的私信 webhook 合并为一个智能体轮次,以便 Apple 的文本 + URL 拆分发送能作为单条消息到达(默认:`false`)。场景、窗口调优和权衡请参见[合并拆分发送的私信](#coalescing-split-send-dms-command--url-in-one-composition)。若启用且未显式设置 `messages.inbound.byChannel.bluebubbles`,默认入站去抖窗口会从 500 ms 扩大到 2500 ms。
|
||||
- `channels.bluebubbles.historyLimit`:用于上下文的群组消息最大数量(0 表示禁用)。
|
||||
- `channels.bluebubbles.dmHistoryLimit`:私信历史记录上限。
|
||||
</Accordion>
|
||||
<Accordion title="操作与账户">
|
||||
- `channels.bluebubbles.actions`:启用/禁用特定操作。
|
||||
- `channels.bluebubbles.accounts`:多账户配置。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
相关全局选项:
|
||||
|
||||
@ -544,42 +594,42 @@ __OC_I18N_900017__
|
||||
|
||||
## 寻址 / 投递目标
|
||||
|
||||
优先使用 `chat_guid` 以获得稳定路由:
|
||||
为获得稳定路由,优先使用 `chat_guid`:
|
||||
|
||||
- `chat_guid:iMessage;-;+15555550123`(群组首选)
|
||||
- `chat_id:123`
|
||||
- `chat_identifier:...`
|
||||
- 直接句柄:`+15555550123`、`user@example.com`
|
||||
- 如果直接句柄没有现有私信聊天,OpenClaw 会通过 `POST /api/v1/chat/new` 创建一个。这要求启用 BlueBubbles Private API。
|
||||
- 直接 handle:`+15555550123`、`user@example.com`
|
||||
- 如果某个直接 handle 没有现有私信聊天,OpenClaw 会通过 `POST /api/v1/chat/new` 创建一个。这要求启用 BlueBubbles Private API。
|
||||
|
||||
### iMessage 与 SMS 路由
|
||||
|
||||
当同一句柄在 Mac 上同时存在 iMessage 聊天和 SMS 聊天时(例如某个电话号码已注册 iMessage,但也曾收到过绿色气泡回退消息),OpenClaw 会优先选择 iMessage 聊天,绝不会静默降级到 SMS。如需强制使用 SMS 聊天,请使用显式的 `sms:` 目标前缀(例如 `sms:+15555550123`)。对于没有匹配 iMessage 聊天的句柄,仍会通过 BlueBubbles 报告的聊天进行发送。
|
||||
当同一个 handle 在 Mac 上同时存在 iMessage 聊天和 SMS 聊天时(例如某个电话号码已注册 iMessage,但也收到过绿色气泡回退消息),OpenClaw 会优先选择 iMessage 聊天,并且绝不会静默降级为 SMS。若要强制使用 SMS 聊天,请使用显式的 `sms:` 目标前缀(例如 `sms:+15555550123`)。如果某个 handle 没有匹配的 iMessage 聊天,仍会通过 BlueBubbles 报告的可用聊天发送。
|
||||
|
||||
## 安全
|
||||
## 安全性
|
||||
|
||||
- webhook 请求通过将查询参数或请求头中的 `guid`/`password` 与 `channels.bluebubbles.password` 比较来完成身份验证。
|
||||
- 请对 API 密码和 webhook 端点保密(将其视为凭证)。
|
||||
- BlueBubbles webhook 身份验证没有 localhost 绕过。如果你代理 webhook 流量,请在整个请求链路中保留 BlueBubbles 密码。这里的 `gateway.trustedProxies` 不能替代 `channels.bluebubbles.password`。参见[Gateway 网关安全](/gateway/security#reverse-proxy-configuration)。
|
||||
- 如果要将 BlueBubbles 服务器暴露到你的 LAN 之外,请启用 HTTPS + 防火墙规则。
|
||||
- Webhook 请求通过将 `guid`/`password` 查询参数或请求头与 `channels.bluebubbles.password` 进行比较来完成身份验证。
|
||||
- 请对 API 密码和 webhook 端点保密(将它们视为凭证)。
|
||||
- BlueBubbles webhook 身份验证没有 localhost 绕过。如果你代理 webhook 流量,请在端到端请求中保留 BlueBubbles 密码。这里的 `gateway.trustedProxies` 不能替代 `channels.bluebubbles.password`。参见 [Gateway 网关安全性](/zh-CN/gateway/security#reverse-proxy-configuration)。
|
||||
- 如果要在局域网之外暴露 BlueBubbles 服务器,请启用 HTTPS + 防火墙规则。
|
||||
|
||||
## 故障排除
|
||||
|
||||
- 如果输入/已读事件停止工作,请检查 BlueBubbles webhook 日志,并确认 Gateway 网关路径与 `channels.bluebubbles.webhookPath` 匹配。
|
||||
- Pairing 代码一小时后过期;请使用 `openclaw pairing list bluebubbles` 和 `openclaw pairing approve bluebubbles <code>`。
|
||||
- Reactions 需要 BlueBubbles Private API(`POST /api/v1/message/react`);请确保服务器版本已提供该接口。
|
||||
- 编辑/撤回需要 macOS 13+ 和兼容的 BlueBubbles 服务器版本。在 macOS 26(Tahoe)上,由于 Private API 变更,编辑当前已损坏。
|
||||
- 如果正在输入/已读事件停止工作,请检查 BlueBubbles webhook 日志,并确认 Gateway 网关路径与 `channels.bluebubbles.webhookPath` 匹配。
|
||||
- 配对码会在一小时后过期;请使用 `openclaw pairing list bluebubbles` 和 `openclaw pairing approve bluebubbles <code>`。
|
||||
- 表情回应需要 BlueBubbles private API(`POST /api/v1/message/react`);请确保服务器版本已提供该接口。
|
||||
- 编辑/撤回需要 macOS 13+ 和兼容的 BlueBubbles 服务器版本。在 macOS 26(Tahoe)上,由于 private API 变更,编辑功能当前不可用。
|
||||
- 群组图标更新在 macOS 26(Tahoe)上可能不稳定:API 可能返回成功,但新图标不会同步。
|
||||
- OpenClaw 会根据 BlueBubbles 服务器的 macOS 版本自动隐藏已知损坏的操作。如果在 macOS 26(Tahoe)上仍显示编辑功能,请使用 `channels.bluebubbles.actions.edit=false` 手动禁用它。
|
||||
- 已启用 `coalesceSameSenderDms`,但拆分发送(例如 `Dump` + URL)仍作为两个轮次到达:请参见[拆分发送合并的故障排除](#split-send-coalescing-troubleshooting)检查清单——常见原因包括防抖窗口过窄、误将会话日志时间戳当作 webhook 到达时间,或回复引用发送(其使用的是 `replyToBody`,而不是第二个 webhook)。
|
||||
- 如需查看 Status/健康信息:`openclaw status --all` 或 `openclaw status --deep`。
|
||||
- OpenClaw 会根据 BlueBubbles 服务器的 macOS 版本自动隐藏已知不可用的操作。如果在 macOS 26(Tahoe)上仍显示编辑,请使用 `channels.bluebubbles.actions.edit=false` 手动禁用。
|
||||
- 已启用 `coalesceSameSenderDms`,但拆分发送(例如 `Dump` + URL)仍然作为两个轮次到达:请参见[拆分发送合并故障排除](#split-send-coalescing-troubleshooting)检查清单—— 常见原因包括去抖窗口过窄、误将会话日志时间戳当作 webhook 到达时间,或引用回复发送(它使用 `replyToBody`,而不是第二个 webhook)。
|
||||
- 查看 Status/健康信息:`openclaw status --all` 或 `openclaw status --deep`。
|
||||
|
||||
有关一般渠道工作流参考,请参见[Channels](/zh-CN/channels)和 [Plugins](/zh-CN/tools/plugin) 指南。
|
||||
有关一般渠道工作流程参考,请参见[渠道](/zh-CN/channels)和[插件](/zh-CN/tools/plugin)指南。
|
||||
|
||||
## 相关内容
|
||||
|
||||
- [Channels Overview](/zh-CN/channels) — 所有受支持的渠道
|
||||
- [Pairing](/zh-CN/channels/pairing) — 私信身份验证与配对流程
|
||||
- [Groups](/zh-CN/channels/groups) — 群聊行为与提及门控
|
||||
- [Channel Routing](/zh-CN/channels/channel-routing) — 消息的会话路由
|
||||
- [Security](/zh-CN/gateway/security) — 访问模型与加固
|
||||
- [渠道路由](/zh-CN/channels/channel-routing) —— 消息的会话路由
|
||||
- [渠道概览](/zh-CN/channels) —— 所有受支持的渠道
|
||||
- [群组](/zh-CN/channels/groups) —— 群聊行为与提及门控
|
||||
- [配对](/zh-CN/channels/pairing) —— 私信身份验证与配对流程
|
||||
- [安全性](/zh-CN/gateway/security) —— 访问模型与加固
|
||||
|
||||
@ -5,37 +5,41 @@ read_when:
|
||||
summary: '`openclaw node` 的 CLI 参考(无头节点主机)'
|
||||
title: 节点
|
||||
x-i18n:
|
||||
generated_at: "2026-04-26T04:29:33Z"
|
||||
generated_at: "2026-04-26T06:59:34Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: ebeeb6a271c7f265943197d816adc3ad46c61b1671885638f4c9be8c321aec9f
|
||||
source_hash: 40f623b163a3c3bcd2d3ff218c5e62a4acba45f7e3f16694d8da62a004b77706
|
||||
source_path: cli/node.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# `openclaw node`
|
||||
|
||||
运行一个**无头节点主机**,连接到 Gateway 网关 WebSocket,并在这台机器上暴露 `system.run` / `system.which`。
|
||||
运行一个**无头节点主机**,连接到 Gateway 网关 WebSocket,并在这台机器上暴露
|
||||
`system.run` / `system.which`。
|
||||
|
||||
## 为什么使用节点主机?
|
||||
## 为什么要使用节点主机?
|
||||
|
||||
当你希望智能体能够**在你网络中的其他机器上运行命令**,而又不想在那里安装完整的 macOS 配套应用时,可以使用节点主机。
|
||||
当你希望智能体能够**在你网络中的其他机器上运行命令**,而又不想在那些机器上安装完整的 macOS 配套应用时,可以使用节点主机。
|
||||
|
||||
常见用例:
|
||||
|
||||
- 在远程 Linux/Windows 机器上运行命令(构建服务器、实验室机器、NAS)。
|
||||
- 将 exec 保持为 Gateway 网关上的**沙箱隔离**执行,但把已批准的运行委派给其他主机。
|
||||
- 为自动化或 CI 节点提供一个轻量级、无头的执行目标。
|
||||
- 将 exec 保持在 Gateway 网关上的**沙箱隔离**中,但把已批准的运行委派给其他主机。
|
||||
- 为自动化或 CI 节点提供轻量级、无头的执行目标。
|
||||
|
||||
执行仍然受**exec 审批**和节点主机上每个智能体的允许列表保护,因此你可以让命令访问保持在明确且受限的范围内。
|
||||
执行仍然受到**exec 批准**和节点主机上每个智能体允许列表的保护,因此你可以让命令访问范围保持明确且可控。
|
||||
|
||||
## 浏览器代理(零配置)
|
||||
|
||||
如果节点上的 `browser.enabled` 未被禁用,节点主机会自动通告一个浏览器代理。这样智能体无需额外配置,就可以在该节点上使用浏览器自动化。
|
||||
如果节点上未禁用 `browser.enabled`,节点主机会自动声明一个浏览器代理。这使得智能体无需额外配置即可在该节点上使用浏览器自动化。
|
||||
|
||||
默认情况下,该代理会暴露节点正常的浏览器配置文件表面。如果你设置了 `nodeHost.browserProxy.allowProfiles`,代理将变为限制模式:不在允许列表中的配置文件目标会被拒绝,并且通过代理会阻止持久化配置文件的创建/删除路由。
|
||||
默认情况下,代理会暴露该节点的常规浏览器配置文件表面。如果你设置了
|
||||
`nodeHost.browserProxy.allowProfiles`,代理就会变为受限模式:
|
||||
针对不在允许列表中的配置文件目标会被拒绝,并且通过该代理会阻止持久化配置文件的
|
||||
create/delete 路由。
|
||||
|
||||
如有需要,可在节点上禁用它:
|
||||
如有需要,可在节点上禁用:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -64,17 +68,17 @@ openclaw node run --host <gateway-host> --port 18789
|
||||
|
||||
## 节点主机的 Gateway 网关认证
|
||||
|
||||
`openclaw node run` 和 `openclaw node install` 会从配置/环境变量中解析 Gateway 网关认证(节点命令不支持 `--token`/`--password` 标志):
|
||||
`openclaw node run` 和 `openclaw node install` 会从配置/环境变量中解析 Gateway 网关认证信息(节点命令不支持 `--token`/`--password` 标志):
|
||||
|
||||
- 首先检查 `OPENCLAW_GATEWAY_TOKEN` / `OPENCLAW_GATEWAY_PASSWORD`。
|
||||
- 然后回退到本地配置:`gateway.auth.token` / `gateway.auth.password`。
|
||||
- 在本地模式下,节点主机有意不继承 `gateway.remote.token` / `gateway.remote.password`。
|
||||
- 如果通过 SecretRef 显式配置了 `gateway.auth.token` / `gateway.auth.password` 但无法解析,则节点认证解析会以关闭方式失败(不会用远程回退来掩盖问题)。
|
||||
- 在 `gateway.mode=remote` 中,远程客户端字段(`gateway.remote.token` / `gateway.remote.password`)也会按照远程优先级规则纳入候选。
|
||||
- 节点主机认证解析仅接受 `OPENCLAW_GATEWAY_*` 环境变量。
|
||||
- 在本地模式下,节点主机不会继承 `gateway.remote.token` / `gateway.remote.password`。
|
||||
- 如果通过 SecretRef 显式配置了 `gateway.auth.token` / `gateway.auth.password` 但未成功解析,节点认证解析将会失败并关闭(不会用远程回退掩盖该问题)。
|
||||
- 在 `gateway.mode=remote` 中,根据远程优先级规则,远程客户端字段(`gateway.remote.token` / `gateway.remote.password`)也可参与解析。
|
||||
- 节点主机认证解析只会识别 `OPENCLAW_GATEWAY_*` 环境变量。
|
||||
|
||||
对于连接到受信任私有网络中非 loopback `ws://` Gateway 网关的节点,请设置 `OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1`。如果未设置,节点启动将以关闭方式失败,并要求你使用 `wss://`、SSH 隧道或 Tailscale。
|
||||
这是进程环境变量级别的显式启用项,不是 `openclaw.json` 配置键。
|
||||
对于连接到受信任私有网络中非 loopback `ws://` Gateway 网关的节点,请设置 `OPENCLAW_ALLOW_INSECURE_PRIVATE_WS=1`。如果未设置,节点启动将失败并关闭,并提示你使用 `wss://`、SSH 隧道或 Tailscale。
|
||||
这是一个进程环境变量显式启用项,而不是 `openclaw.json` 配置键。
|
||||
如果 `openclaw node install` 的安装命令环境中存在该变量,它会被持久化到受监管的节点服务中。
|
||||
|
||||
## 服务(后台)
|
||||
@ -94,9 +98,9 @@ openclaw node install --host <gateway-host> --port 18789
|
||||
- `--node-id <id>`:覆盖节点 id(会清除配对令牌)
|
||||
- `--display-name <name>`:覆盖节点显示名称
|
||||
- `--runtime <runtime>`:服务运行时(`node` 或 `bun`)
|
||||
- `--force`:如果已安装,则重新安装/覆盖
|
||||
- `--force`:如果已安装则重新安装/覆盖
|
||||
|
||||
管理服务:
|
||||
管理该服务:
|
||||
|
||||
```bash
|
||||
openclaw node status
|
||||
@ -110,17 +114,19 @@ openclaw node uninstall
|
||||
|
||||
服务命令支持 `--json`,用于机器可读输出。
|
||||
|
||||
节点主机会在进程内重试 Gateway 网关重启和网络关闭。如果 Gateway 网关报告终止性的 token/password/bootstrap 认证暂停,节点主机会记录关闭详情并以非零状态退出,以便 launchd/systemd 使用最新的配置和凭证将其重启。需要配对的暂停会保留在前台流程中,以便批准待处理请求。
|
||||
|
||||
## 配对
|
||||
|
||||
首次连接会在 Gateway 网关上创建一个待处理的设备配对请求(`role: node`)。
|
||||
可通过以下命令批准:
|
||||
通过以下命令批准:
|
||||
|
||||
```bash
|
||||
openclaw devices list
|
||||
openclaw devices approve <requestId>
|
||||
```
|
||||
|
||||
在严格受控的节点网络中,Gateway 网关运营者可以显式启用:对来自受信任 CIDR 的首次节点配对自动批准:
|
||||
在控制严格的节点网络中,Gateway 网关操作员可以显式启用:对来自受信任 CIDR 的首次节点配对自动批准:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -134,22 +140,23 @@ openclaw devices approve <requestId>
|
||||
}
|
||||
```
|
||||
|
||||
此功能默认禁用。它只适用于没有请求作用域的全新 `role: node` 配对。运营者/浏览器客户端、Control UI、WebChat,以及角色、作用域、元数据或公钥升级,仍然需要手动批准。
|
||||
默认禁用。它仅适用于没有请求作用域的全新 `role: node` 配对。操作员/浏览器客户端、Control UI、WebChat,以及角色、作用域、元数据或公钥升级,仍然需要手动批准。
|
||||
|
||||
如果节点在认证细节发生变化后重试配对(角色/作用域/公钥),之前待处理的请求会被替代,并创建新的 `requestId`。
|
||||
请在批准前再次运行 `openclaw devices list`。
|
||||
如果节点使用变更后的认证详情(角色/作用域/公钥)重试配对,之前待处理的请求会被替代,并创建新的 `requestId`。
|
||||
批准前请再次运行 `openclaw devices list`。
|
||||
|
||||
节点主机会将其节点 id、令牌、显示名称以及 Gateway 网关连接信息存储在 `~/.openclaw/node.json` 中。
|
||||
节点主机会将其节点 id、令牌、显示名称和 Gateway 网关连接信息存储在
|
||||
`~/.openclaw/node.json` 中。
|
||||
|
||||
## Exec 审批
|
||||
## Exec 批准
|
||||
|
||||
`system.run` 受本地 exec 审批控制:
|
||||
`system.run` 受本地 exec 批准控制:
|
||||
|
||||
- `~/.openclaw/exec-approvals.json`
|
||||
- [Exec 审批](/zh-CN/tools/exec-approvals)
|
||||
- [Exec 批准](/zh-CN/tools/exec-approvals)
|
||||
- `openclaw approvals --node <id|name|ip>`(从 Gateway 网关编辑)
|
||||
|
||||
对于已批准的异步节点 exec,OpenClaw 会在提示前准备一个规范化的 `systemRunPlan`。后续已批准的 `system.run` 转发会复用该已存储计划,因此如果在创建审批请求之后再编辑 command/cwd/session 字段,将会被拒绝,而不是改变节点实际执行的内容。
|
||||
对于已批准的异步节点 exec,OpenClaw 会在提示之前准备规范化的 `systemRunPlan`。之后获批的 `system.run` 转发会重用这个已存储的计划,因此在批准请求创建后,如果再编辑命令/cwd/session 字段,将被拒绝,而不是改变节点实际执行的内容。
|
||||
|
||||
## 相关内容
|
||||
|
||||
|
||||
@ -3,19 +3,19 @@ read_when:
|
||||
- 配置 `tools.*` 策略、允许列表或实验性功能
|
||||
- 注册自定义提供商或覆盖基础 URL
|
||||
- 设置与 OpenAI 兼容的自托管端点
|
||||
summary: 工具配置(策略、实验性开关、提供商支持的工具)以及自定义提供商 / 基础 URL 设置
|
||||
title: 配置 —— 工具和自定义提供商
|
||||
sidebarTitle: Tools and custom providers
|
||||
summary: 工具配置(策略、实验性开关、由 provider 支持的工具)以及自定义 provider / 基础 URL 设置
|
||||
title: 配置——工具和自定义提供商
|
||||
x-i18n:
|
||||
generated_at: "2026-04-25T06:52:28Z"
|
||||
generated_at: "2026-04-26T06:59:35Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: d63b080550a6c95d714d3bb42c2b079368040aa09378d88c2e498ccd5ec113c1
|
||||
source_hash: ef030940b155224e614675a85c7a81567fd3a493e5ec1c25c5956d49cbc11b86
|
||||
source_path: gateway/config-tools.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
`tools.*` 配置键以及自定义提供商 / 基础 URL 设置。有关智能体、渠道和其他顶层配置键,请参阅
|
||||
[配置参考](/zh-CN/gateway/configuration-reference)。
|
||||
`tools.*` 配置键和自定义提供商 / 基础 URL 设置。有关智能体、渠道和其他顶级配置键,请参阅[配置参考](/zh-CN/gateway/configuration-reference)。
|
||||
|
||||
## 工具
|
||||
|
||||
@ -23,35 +23,37 @@ x-i18n:
|
||||
|
||||
`tools.profile` 会在 `tools.allow` / `tools.deny` 之前设置基础允许列表:
|
||||
|
||||
本地新手引导会在未设置时,将新的本地配置默认设为 `tools.profile: "coding"`(现有的显式配置档案会被保留)。
|
||||
<Note>
|
||||
本地新手引导在未设置时,默认将新的本地配置设为 `tools.profile: "coding"`(现有的显式配置档案会被保留)。
|
||||
</Note>
|
||||
|
||||
| 配置档案 | 包含内容 |
|
||||
| 配置档案 | 包含 |
|
||||
| ----------- | ------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `minimal` | 仅 `session_status` |
|
||||
| `minimal` | 仅 `session_status` |
|
||||
| `coding` | `group:fs`、`group:runtime`、`group:web`、`group:sessions`、`group:memory`、`cron`、`image`、`image_generate`、`video_generate` |
|
||||
| `messaging` | `group:messaging`、`sessions_list`、`sessions_history`、`sessions_send`、`session_status` |
|
||||
| `full` | 无限制(与未设置相同) |
|
||||
| `messaging` | `group:messaging`、`sessions_list`、`sessions_history`、`sessions_send`、`session_status` |
|
||||
| `full` | 无限制(与未设置相同) |
|
||||
|
||||
### 工具分组
|
||||
|
||||
| 分组 | 工具 |
|
||||
| 分组 | 工具 |
|
||||
| ------------------ | ----------------------------------------------------------------------------------------------------------------------- |
|
||||
| `group:runtime` | `exec`、`process`、`code_execution`(`bash` 可作为 `exec` 的别名使用) |
|
||||
| `group:fs` | `read`、`write`、`edit`、`apply_patch` |
|
||||
| `group:runtime` | `exec`、`process`、`code_execution`(`bash` 可作为 `exec` 的别名使用) |
|
||||
| `group:fs` | `read`、`write`、`edit`、`apply_patch` |
|
||||
| `group:sessions` | `sessions_list`、`sessions_history`、`sessions_send`、`sessions_spawn`、`sessions_yield`、`subagents`、`session_status` |
|
||||
| `group:memory` | `memory_search`、`memory_get` |
|
||||
| `group:web` | `web_search`、`x_search`、`web_fetch` |
|
||||
| `group:ui` | `browser`、`canvas` |
|
||||
| `group:automation` | `cron`、`gateway` |
|
||||
| `group:messaging` | `message` |
|
||||
| `group:nodes` | `nodes` |
|
||||
| `group:agents` | `agents_list` |
|
||||
| `group:media` | `image`、`image_generate`、`video_generate`、`tts` |
|
||||
| `group:openclaw` | 所有内置工具(不包括提供商插件) |
|
||||
| `group:memory` | `memory_search`、`memory_get` |
|
||||
| `group:web` | `web_search`、`x_search`、`web_fetch` |
|
||||
| `group:ui` | `browser`、`canvas` |
|
||||
| `group:automation` | `cron`、`gateway` |
|
||||
| `group:messaging` | `message` |
|
||||
| `group:nodes` | `nodes` |
|
||||
| `group:agents` | `agents_list` |
|
||||
| `group:media` | `image`、`image_generate`、`video_generate`、`tts` |
|
||||
| `group:openclaw` | 所有内置工具(不包括提供商插件) |
|
||||
|
||||
### `tools.allow` / `tools.deny`
|
||||
|
||||
全局工具允许 / 拒绝策略(`deny` 优先生效)。不区分大小写,支持 `*` 通配符。即使 Docker 沙箱关闭,也会应用。
|
||||
全局工具允许 / 拒绝策略(拒绝优先)。不区分大小写,支持 `*` 通配符。即使 Docker 沙箱已关闭,也会应用。
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -61,7 +63,7 @@ x-i18n:
|
||||
|
||||
### `tools.byProvider`
|
||||
|
||||
进一步限制特定提供商或模型可用的工具。顺序为:基础配置档案 → 提供商配置档案 → allow / deny。
|
||||
进一步限制特定提供商或模型可用的工具。顺序:基础配置档案 → 提供商配置档案 → allow / deny。
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -77,7 +79,7 @@ x-i18n:
|
||||
|
||||
### `tools.elevated`
|
||||
|
||||
控制沙箱之外的提升权限 `exec` 访问:
|
||||
控制沙箱外的提升权限 `exec` 访问:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -93,9 +95,9 @@ x-i18n:
|
||||
}
|
||||
```
|
||||
|
||||
- 按智能体覆盖(`agents.list[].tools.elevated`)只能进一步收紧限制。
|
||||
- 每个智能体的覆盖设置(`agents.list[].tools.elevated`)只能进一步收紧限制。
|
||||
- `/elevated on|off|ask|full` 会按会话存储状态;内联指令仅应用于单条消息。
|
||||
- 提升权限的 `exec` 会绕过沙箱隔离,并使用已配置的逃逸路径(默认是 `gateway`,如果 `exec` 目标是 `node`,则使用 `node`)。
|
||||
- 提升权限的 `exec` 会绕过沙箱隔离,并使用已配置的逃逸路径(默认是 `gateway`,或者当 `exec` 目标为 `node` 时使用 `node`)。
|
||||
|
||||
### `tools.exec`
|
||||
|
||||
@ -119,8 +121,7 @@ x-i18n:
|
||||
|
||||
### `tools.loopDetection`
|
||||
|
||||
工具循环安全检查**默认禁用**。设置 `enabled: true` 以启用检测。
|
||||
可以在全局 `tools.loopDetection` 中定义设置,并在每个智能体的 `agents.list[].tools.loopDetection` 中覆盖。
|
||||
工具循环安全检查**默认禁用**。设置 `enabled: true` 以启用检测。设置可在全局 `tools.loopDetection` 中定义,并可在每个智能体的 `agents.list[].tools.loopDetection` 中覆盖。
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -141,14 +142,31 @@ x-i18n:
|
||||
}
|
||||
```
|
||||
|
||||
- `historySize`:为循环分析保留的最大工具调用历史记录数。
|
||||
- `warningThreshold`:针对重复且无进展模式发出警告的阈值。
|
||||
- `criticalThreshold`:用于阻止严重循环的更高重复阈值。
|
||||
- `globalCircuitBreakerThreshold`:对任何无进展运行进行硬停止的阈值。
|
||||
- `detectors.genericRepeat`:对重复调用相同工具 / 相同参数发出警告。
|
||||
- `detectors.knownPollNoProgress`:对已知轮询工具(`process.poll`、`command_status` 等)的无进展情况发出警告 / 阻止。
|
||||
- `detectors.pingPong`:对交替出现的无进展成对模式发出警告 / 阻止。
|
||||
- 如果 `warningThreshold >= criticalThreshold` 或 `criticalThreshold >= globalCircuitBreakerThreshold`,校验将失败。
|
||||
<ParamField path="historySize" type="number">
|
||||
为循环分析保留的最大工具调用历史记录数。
|
||||
</ParamField>
|
||||
<ParamField path="warningThreshold" type="number">
|
||||
用于发出警告的重复无进展模式阈值。
|
||||
</ParamField>
|
||||
<ParamField path="criticalThreshold" type="number">
|
||||
用于阻止严重循环的更高重复阈值。
|
||||
</ParamField>
|
||||
<ParamField path="globalCircuitBreakerThreshold" type="number">
|
||||
针对任何无进展运行的硬停止阈值。
|
||||
</ParamField>
|
||||
<ParamField path="detectors.genericRepeat" type="boolean">
|
||||
对重复的同工具 / 同参数调用发出警告。
|
||||
</ParamField>
|
||||
<ParamField path="detectors.knownPollNoProgress" type="boolean">
|
||||
对已知的轮询工具(`process.poll`、`command_status` 等)发出警告 / 阻止。
|
||||
</ParamField>
|
||||
<ParamField path="detectors.pingPong" type="boolean">
|
||||
对交替出现的无进展成对模式发出警告 / 阻止。
|
||||
</ParamField>
|
||||
|
||||
<Warning>
|
||||
如果 `warningThreshold >= criticalThreshold` 或 `criticalThreshold >= globalCircuitBreakerThreshold`,验证将失败。
|
||||
</Warning>
|
||||
|
||||
### `tools.web`
|
||||
|
||||
@ -182,7 +200,7 @@ x-i18n:
|
||||
|
||||
### `tools.media`
|
||||
|
||||
配置传入媒体理解(图像 / 音频 / 视频):
|
||||
配置入站媒体理解(图像 / 音频 / 视频):
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -190,7 +208,7 @@ x-i18n:
|
||||
media: {
|
||||
concurrency: 2,
|
||||
asyncCompletion: {
|
||||
directSend: false, // 选择启用:将完成的异步音乐 / 视频直接发送到渠道
|
||||
directSend: false, // 选择启用:将已完成的异步音乐 / 视频直接发送到渠道
|
||||
},
|
||||
audio: {
|
||||
enabled: true,
|
||||
@ -214,34 +232,33 @@ x-i18n:
|
||||
}
|
||||
```
|
||||
|
||||
<Accordion title="媒体模型条目字段">
|
||||
<AccordionGroup>
|
||||
<Accordion title="媒体模型条目字段">
|
||||
**提供商条目**(`type: "provider"` 或省略):
|
||||
|
||||
**提供商条目**(`type: "provider"` 或省略):
|
||||
- `provider`:API 提供商 id(`openai`、`anthropic`、`google` / `gemini`、`groq` 等)
|
||||
- `model`:模型 id 覆盖值
|
||||
- `profile` / `preferredProfile`:`auth-profiles.json` 配置档案选择
|
||||
|
||||
- `provider`:API 提供商 id(`openai`、`anthropic`、`google` / `gemini`、`groq` 等)
|
||||
- `model`:模型 id 覆盖值
|
||||
- `profile` / `preferredProfile`:`auth-profiles.json` 配置档案选择
|
||||
**CLI 条目**(`type: "cli"`):
|
||||
|
||||
**CLI 条目**(`type: "cli"`):
|
||||
- `command`:要运行的可执行文件
|
||||
- `args`:模板化参数(支持 `{{MediaPath}}`、`{{Prompt}}`、`{{MaxChars}}` 等)
|
||||
|
||||
- `command`:要运行的可执行文件
|
||||
- `args`:模板化参数(支持 `{{MediaPath}}`、`{{Prompt}}`、`{{MaxChars}}` 等)
|
||||
**通用字段:**
|
||||
|
||||
**通用字段:**
|
||||
- `capabilities`:可选列表(`image`、`audio`、`video`)。默认值:`openai` / `anthropic` / `minimax` → 图像,`google` → 图像 + 音频 + 视频,`groq` → 音频。
|
||||
- `prompt`、`maxChars`、`maxBytes`、`timeoutSeconds`、`language`:每个条目的覆盖设置。
|
||||
- 失败时会回退到下一个条目。
|
||||
|
||||
- `capabilities`:可选列表(`image`、`audio`、`video`)。默认值:`openai` / `anthropic` / `minimax` → 图像,`google` → 图像 + 音频 + 视频,`groq` → 音频。
|
||||
- `prompt`、`maxChars`、`maxBytes`、`timeoutSeconds`、`language`:每个条目的覆盖设置。
|
||||
- 如果失败,会回退到下一个条目。
|
||||
提供商认证遵循标准顺序:`auth-profiles.json` → 环境变量 → `models.providers.*.apiKey`。
|
||||
|
||||
提供商认证遵循标准顺序:`auth-profiles.json` → 环境变量 → `models.providers.*.apiKey`。
|
||||
**异步完成字段:**
|
||||
|
||||
**异步完成字段:**
|
||||
- `asyncCompletion.directSend`:当为 `true` 时,已完成的异步 `music_generate` 和 `video_generate` 任务会优先尝试直接投递到渠道。默认值:`false`(旧版请求者会话唤醒 / 模型投递路径)。
|
||||
|
||||
- `asyncCompletion.directSend`:当设为 `true` 时,已完成的异步 `music_generate`
|
||||
和 `video_generate` 任务会先尝试直接投递到渠道。默认值:`false`
|
||||
(旧版请求者会话唤醒 / 模型投递路径)。
|
||||
|
||||
</Accordion>
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### `tools.agentToAgent`
|
||||
|
||||
@ -258,9 +275,9 @@ x-i18n:
|
||||
|
||||
### `tools.sessions`
|
||||
|
||||
控制会话工具(`sessions_list`、`sessions_history`、`sessions_send`)可以定位哪些会话。
|
||||
控制哪些会话可以被会话工具(`sessions_list`、`sessions_history`、`sessions_send`)作为目标。
|
||||
|
||||
默认值:`tree`(当前会话 + 由其生成的会话,例如子智能体)。
|
||||
默认值:`tree`(当前会话 + 由其派生的会话,例如子智能体)。
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -273,13 +290,15 @@ x-i18n:
|
||||
}
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
- `self`:仅当前会话键。
|
||||
- `tree`:当前会话 + 由当前会话生成的会话(子智能体)。
|
||||
- `agent`:属于当前智能体 id 的任何会话(如果你在同一个智能体 id 下按发送者运行会话,可能包括其他用户)。
|
||||
- `all`:任何会话。跨智能体定位仍然需要 `tools.agentToAgent`。
|
||||
- 沙箱限制:当当前会话处于沙箱隔离中,且 `agents.defaults.sandbox.sessionToolsVisibility="spawned"` 时,即使 `tools.sessions.visibility="all"`,可见性也会被强制为 `tree`。
|
||||
<AccordionGroup>
|
||||
<Accordion title="可见性范围">
|
||||
- `self`:仅当前会话键。
|
||||
- `tree`:当前会话 + 由当前会话派生的会话(子智能体)。
|
||||
- `agent`:属于当前智能体 id 的任意会话(如果你在同一智能体 id 下按发送者运行会话,则可能包含其他用户)。
|
||||
- `all`:任意会话。跨智能体定向仍然需要 `tools.agentToAgent`。
|
||||
- 沙箱钳制:当当前会话处于沙箱隔离中,且 `agents.defaults.sandbox.sessionToolsVisibility="spawned"` 时,即使 `tools.sessions.visibility="all"`,可见性也会被强制为 `tree`。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### `tools.sessions_spawn`
|
||||
|
||||
@ -291,7 +310,7 @@ x-i18n:
|
||||
sessions_spawn: {
|
||||
attachments: {
|
||||
enabled: false, // 选择启用:设为 true 以允许内联文件附件
|
||||
maxTotalBytes: 5242880, // 所有文件总计 5 MB
|
||||
maxTotalBytes: 5242880, // 所有文件合计 5 MB
|
||||
maxFiles: 50,
|
||||
maxFileBytes: 1048576, // 每个文件 1 MB
|
||||
retainOnSessionKeep: false, // 当 cleanup="keep" 时保留附件
|
||||
@ -301,20 +320,22 @@ x-i18n:
|
||||
}
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
- 仅 `runtime: "subagent"` 支持附件。ACP 运行时会拒绝它们。
|
||||
- 文件会被实体化到子工作区的 `.openclaw/attachments/<uuid>/` 中,并带有一个 `.manifest.json`。
|
||||
- 附件内容会自动从转录持久化中脱敏。
|
||||
- Base64 输入会使用严格的字母表 / 填充校验,以及解码前大小保护进行验证。
|
||||
- 目录文件权限为 `0700`,文件权限为 `0600`。
|
||||
- 清理遵循 `cleanup` 策略:`delete` 总是删除附件;`keep` 仅在 `retainOnSessionKeep: true` 时保留它们。
|
||||
<AccordionGroup>
|
||||
<Accordion title="附件说明">
|
||||
- 附件仅支持 `runtime: "subagent"`。ACP 运行时会拒绝它们。
|
||||
- 文件会被实体化到子工作区的 `.openclaw/attachments/<uuid>/` 中,并附带一个 `.manifest.json`。
|
||||
- 附件内容会自动从转录持久化中脱敏。
|
||||
- Base64 输入会进行严格的字母表 / 填充检查,并在解码前执行大小保护检查。
|
||||
- 文件权限为:目录 `0700`,文件 `0600`。
|
||||
- 清理遵循 `cleanup` 策略:`delete` 总是删除附件;`keep` 仅在 `retainOnSessionKeep: true` 时保留附件。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
<a id="toolsexperimental"></a>
|
||||
|
||||
### `tools.experimental`
|
||||
|
||||
实验性的内置工具标志。默认关闭,除非适用 strict-agentic GPT-5 自动启用规则。
|
||||
实验性内置工具标志。默认关闭,除非适用 strict-agentic GPT-5 自动启用规则。
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -326,11 +347,9 @@ x-i18n:
|
||||
}
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
- `planTool`:为非简单的多步骤工作跟踪启用结构化 `update_plan` 工具。
|
||||
- 默认值:`false`,除非 `agents.defaults.embeddedPi.executionContract`(或每个智能体的覆盖值)被设置为 `"strict-agentic"`,并且运行的是 OpenAI 或 OpenAI Codex GPT-5 系列。设为 `true` 可在该范围之外强制启用此工具;设为 `false` 则即使在 strict-agentic GPT-5 运行中也保持关闭。
|
||||
- 启用后,系统提示词还会添加使用指引,以便模型仅在重要工作中使用它,并且最多只保留一个 `in_progress` 步骤。
|
||||
- `planTool`:为非琐碎的多步骤工作跟踪启用结构化的 `update_plan` 工具。
|
||||
- 默认值:`false`,除非 `agents.defaults.embeddedPi.executionContract`(或每个智能体的覆盖设置)被设为 `"strict-agentic"`,且运行使用的是 OpenAI 或 OpenAI Codex 的 GPT-5 系列。设为 `true` 可在该范围之外强制启用该工具;设为 `false` 则即使在 strict-agentic GPT-5 运行中也保持关闭。
|
||||
- 启用后,系统提示词还会添加使用指南,以便模型仅在实质性工作中使用它,并且最多只保持一个步骤处于 `in_progress`。
|
||||
|
||||
### `agents.defaults.subagents`
|
||||
|
||||
@ -350,8 +369,8 @@ x-i18n:
|
||||
}
|
||||
```
|
||||
|
||||
- `model`:生成的子智能体默认使用的模型。如果省略,子智能体会继承调用方的模型。
|
||||
- `allowAgents`:当请求方智能体未设置自己的 `subagents.allowAgents` 时,`sessions_spawn` 目标智能体 id 的默认允许列表(`["*"]` = 任意;默认:仅同一智能体)。
|
||||
- `model`:派生子智能体的默认模型。如果省略,子智能体将继承调用方的模型。
|
||||
- `allowAgents`:当请求智能体未设置自己的 `subagents.allowAgents` 时,`sessions_spawn` 目标智能体 id 的默认允许列表(`["*"]` = 任意;默认:仅相同智能体)。
|
||||
- `runTimeoutSeconds`:当工具调用省略 `runTimeoutSeconds` 时,`sessions_spawn` 的默认超时时间(秒)。`0` 表示无超时。
|
||||
- 每个子智能体的工具策略:`tools.subagents.tools.allow` / `tools.subagents.tools.deny`。
|
||||
|
||||
@ -388,286 +407,281 @@ OpenClaw 使用内置模型目录。可通过配置中的 `models.providers` 或
|
||||
}
|
||||
```
|
||||
|
||||
- 如需自定义认证,请使用 `authHeader: true` + `headers`。
|
||||
- 使用 `OPENCLAW_AGENT_DIR`(或旧版环境变量别名 `PI_CODING_AGENT_DIR`)覆盖智能体配置根目录。
|
||||
- 匹配提供商 ID 的合并优先级:
|
||||
- 非空的智能体 `models.json` `baseUrl` 值优先。
|
||||
- 非空的智能体 `apiKey` 值仅在当前配置 / auth-profile 上下文中该提供商不是由 SecretRef 管理时优先。
|
||||
- 由 SecretRef 管理的提供商 `apiKey` 值会从源标记刷新(环境变量引用为 `ENV_VAR_NAME`,文件 / exec 引用为 `secretref-managed`),而不是持久化已解析的密钥。
|
||||
- 由 SecretRef 管理的提供商头部值会从源标记刷新(环境变量引用为 `secretref-env:ENV_VAR_NAME`,文件 / exec 引用为 `secretref-managed`)。
|
||||
- 空的或缺失的智能体 `apiKey` / `baseUrl` 会回退到配置中的 `models.providers`。
|
||||
- 匹配模型的 `contextWindow` / `maxTokens` 会在显式配置值与隐式目录值之间采用较高的值。
|
||||
- 匹配模型的 `contextTokens` 会在存在时保留显式运行时上限;当你希望限制生效上下文而不修改模型原生元数据时,请使用它。
|
||||
- 当你希望配置完全重写 `models.json` 时,请使用 `models.mode: "replace"`。
|
||||
- 标记持久化以源为准:标记写入自当前活动的源配置快照(解析前),而不是来自解析后的运行时密钥值。
|
||||
<AccordionGroup>
|
||||
<Accordion title="认证和合并优先级">
|
||||
- 对于自定义认证需求,使用 `authHeader: true` + `headers`。
|
||||
- 使用 `OPENCLAW_AGENT_DIR`(或旧版环境变量别名 `PI_CODING_AGENT_DIR`)覆盖智能体配置根目录。
|
||||
- 对匹配的提供商 ID,合并优先级如下:
|
||||
- 非空的智能体 `models.json` `baseUrl` 值优先。
|
||||
- 非空的智能体 `apiKey` 值仅在该提供商在当前配置 / 认证档案上下文中不是由 SecretRef 管理时优先。
|
||||
- 由 SecretRef 管理的提供商 `apiKey` 值会从源标记刷新(环境变量引用使用 `ENV_VAR_NAME`,文件 / exec 引用使用 `secretref-managed`),而不是持久化已解析的密钥。
|
||||
- 由 SecretRef 管理的提供商 header 值会从源标记刷新(环境变量引用使用 `secretref-env:ENV_VAR_NAME`,文件 / exec 引用使用 `secretref-managed`)。
|
||||
- 空或缺失的智能体 `apiKey` / `baseUrl` 会回退到配置中的 `models.providers`。
|
||||
- 匹配模型的 `contextWindow` / `maxTokens` 会在显式配置值和隐式目录值之间取较高者。
|
||||
- 匹配模型的 `contextTokens` 会在存在时保留显式运行时上限;当你希望限制有效上下文而不更改模型原生元数据时,请使用它。
|
||||
- 当你希望配置完全重写 `models.json` 时,使用 `models.mode: "replace"`。
|
||||
- 标记持久化以来源为准:标记从活动源配置快照(解析前)写入,而不是从已解析的运行时密钥值写入。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### 提供商字段详情
|
||||
|
||||
- `models.mode`:提供商目录行为(`merge` 或 `replace`)。
|
||||
- `models.providers`:以提供商 id 为键的自定义提供商映射。
|
||||
- 安全编辑:使用 `openclaw config set models.providers.<id> '<json>' --strict-json --merge` 或 `openclaw config set models.providers.<id>.models '<json-array>' --strict-json --merge` 进行增量更新。`config set` 会拒绝破坏性替换,除非你传入 `--replace`。
|
||||
- `models.providers.*.api`:请求适配器(`openai-completions`、`openai-responses`、`anthropic-messages`、`google-generative-ai` 等)。
|
||||
- `models.providers.*.apiKey`:提供商凭证(优先使用 SecretRef / 环境变量替换)。
|
||||
- `models.providers.*.auth`:认证策略(`api-key`、`token`、`oauth`、`aws-sdk`)。
|
||||
- `models.providers.*.injectNumCtxForOpenAICompat`:对于 Ollama + `openai-completions`,向请求中注入 `options.num_ctx`(默认:`true`)。
|
||||
- `models.providers.*.authHeader`:在需要时强制通过 `Authorization` 头传输凭证。
|
||||
- `models.providers.*.baseUrl`:上游 API 基础 URL。
|
||||
- `models.providers.*.headers`:用于代理 / 租户路由的额外静态头部。
|
||||
- `models.providers.*.request`:模型提供商 HTTP 请求的传输覆盖设置。
|
||||
- `request.headers`:额外头部(与提供商默认值合并)。值支持 SecretRef。
|
||||
- `request.auth`:认证策略覆盖。模式:`"provider-default"`(使用提供商内置认证)、`"authorization-bearer"`(配合 `token`)、`"header"`(配合 `headerName`、`value` 和可选的 `prefix`)。
|
||||
- `request.proxy`:HTTP 代理覆盖。模式:`"env-proxy"`(使用 `HTTP_PROXY` / `HTTPS_PROXY` 环境变量)、`"explicit-proxy"`(配合 `url`)。两种模式都接受可选的 `tls` 子对象。
|
||||
- `request.tls`:直连时的 TLS 覆盖。字段:`ca`、`cert`、`key`、`passphrase`(都支持 SecretRef)、`serverName`、`insecureSkipVerify`。
|
||||
- `request.allowPrivateNetwork`:当设为 `true` 时,如果 DNS 将 `baseUrl` 解析到私有、CGNAT 或类似网段,则允许通过提供商 HTTP 抓取防护访问 HTTPS `baseUrl`(这是针对受信任、自托管、与 OpenAI 兼容端点的运维人员选择启用项)。WebSocket 也使用相同的 `request` 处理头部 / TLS,但不使用该抓取 SSRF 防护门。默认值为 `false`。
|
||||
- `models.providers.*.models`:显式提供商模型目录条目。
|
||||
- `models.providers.*.models.*.contextWindow`:模型原生上下文窗口元数据。
|
||||
- `models.providers.*.models.*.contextTokens`:可选的运行时上下文上限。当你希望有效上下文预算小于模型原生 `contextWindow` 时使用;当两者不同,`openclaw models list` 会同时显示这两个值。
|
||||
- `models.providers.*.models.*.compat.supportsDeveloperRole`:可选兼容性提示。对于 `api: "openai-completions"` 且 `baseUrl` 为非空、非原生值(主机不是 `api.openai.com`)的情况,OpenClaw 会在运行时将其强制设为 `false`。空的 / 省略的 `baseUrl` 会保留默认的 OpenAI 行为。
|
||||
- `models.providers.*.models.*.compat.requiresStringContent`:针对仅支持字符串的 OpenAI 兼容聊天端点的可选兼容性提示。当设为 `true` 时,OpenClaw 会在发送请求前将纯文本 `messages[].content` 数组展平为纯字符串。
|
||||
- `plugins.entries.amazon-bedrock.config.discovery`:Bedrock 自动发现设置根。
|
||||
- `plugins.entries.amazon-bedrock.config.discovery.enabled`:开启 / 关闭隐式发现。
|
||||
- `plugins.entries.amazon-bedrock.config.discovery.region`:用于发现的 AWS 区域。
|
||||
- `plugins.entries.amazon-bedrock.config.discovery.providerFilter`:用于定向发现的可选 provider-id 过滤器。
|
||||
- `plugins.entries.amazon-bedrock.config.discovery.refreshInterval`:发现刷新轮询间隔。
|
||||
- `plugins.entries.amazon-bedrock.config.discovery.defaultContextWindow`:已发现模型的回退上下文窗口。
|
||||
- `plugins.entries.amazon-bedrock.config.discovery.defaultMaxTokens`:已发现模型的回退最大输出 token 数。
|
||||
<AccordionGroup>
|
||||
<Accordion title="顶级目录">
|
||||
- `models.mode`:提供商目录行为(`merge` 或 `replace`)。
|
||||
- `models.providers`:以提供商 id 为键的自定义提供商映射。
|
||||
- 安全编辑:对增量更新,使用 `openclaw config set models.providers.<id> '<json>' --strict-json --merge` 或 `openclaw config set models.providers.<id>.models '<json-array>' --strict-json --merge`。除非传入 `--replace`,否则 `config set` 会拒绝破坏性替换。
|
||||
</Accordion>
|
||||
<Accordion title="提供商连接和认证">
|
||||
- `models.providers.*.api`:请求适配器(`openai-completions`、`openai-responses`、`anthropic-messages`、`google-generative-ai` 等)。
|
||||
- `models.providers.*.apiKey`:提供商凭证(优先使用 SecretRef / 环境变量替换)。
|
||||
- `models.providers.*.auth`:认证策略(`api-key`、`token`、`oauth`、`aws-sdk`)。
|
||||
- `models.providers.*.injectNumCtxForOpenAICompat`:对于 Ollama + `openai-completions`,向请求中注入 `options.num_ctx`(默认:`true`)。
|
||||
- `models.providers.*.authHeader`:在需要时强制通过 `Authorization` header 传输凭证。
|
||||
- `models.providers.*.baseUrl`:上游 API 基础 URL。
|
||||
- `models.providers.*.headers`:用于代理 / 租户路由的额外静态 headers。
|
||||
</Accordion>
|
||||
<Accordion title="请求传输覆盖">
|
||||
`models.providers.*.request`:模型提供商 HTTP 请求的传输覆盖设置。
|
||||
|
||||
- `request.headers`:额外 headers(与提供商默认值合并)。值支持 SecretRef。
|
||||
- `request.auth`:认证策略覆盖。模式:`"provider-default"`(使用提供商内置认证)、`"authorization-bearer"`(配合 `token`)、`"header"`(配合 `headerName`、`value`、可选的 `prefix`)。
|
||||
- `request.proxy`:HTTP 代理覆盖。模式:`"env-proxy"`(使用 `HTTP_PROXY` / `HTTPS_PROXY` 环境变量)、`"explicit-proxy"`(配合 `url`)。两种模式都接受可选的 `tls` 子对象。
|
||||
- `request.tls`:直连的 TLS 覆盖。字段:`ca`、`cert`、`key`、`passphrase`(均支持 SecretRef)、`serverName`、`insecureSkipVerify`。
|
||||
- `request.allowPrivateNetwork`:当为 `true` 时,当 DNS 解析到私有、CGNAT 或类似网段时,允许通过提供商 HTTP 抓取保护向 `baseUrl` 发起 HTTPS 请求(这是针对受信任自托管 OpenAI 兼容端点的运维人员选择启用项)。WebSocket 使用相同的 `request` 来处理 headers / TLS,但不使用该抓取 SSRF 防护门控。默认值为 `false`。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="模型目录条目">
|
||||
- `models.providers.*.models`:显式提供商模型目录条目。
|
||||
- `models.providers.*.models.*.contextWindow`:模型原生上下文窗口元数据。
|
||||
- `models.providers.*.models.*.contextTokens`:可选运行时上下文上限。当你希望有效上下文预算小于模型原生 `contextWindow` 时使用它;当两者不同,`openclaw models list` 会同时显示这两个值。
|
||||
- `models.providers.*.models.*.compat.supportsDeveloperRole`:可选兼容性提示。对于 `api: "openai-completions"` 且 `baseUrl` 为非空非原生值(主机不是 `api.openai.com`)的情况,OpenClaw 会在运行时强制将其设为 `false`。空或省略的 `baseUrl` 会保留默认 OpenAI 行为。
|
||||
- `models.providers.*.models.*.compat.requiresStringContent`:用于仅支持字符串的 OpenAI 兼容聊天端点的可选兼容性提示。当为 `true` 时,OpenClaw 会在发送请求前将纯文本 `messages[].content` 数组压平成普通字符串。
|
||||
</Accordion>
|
||||
<Accordion title="Amazon Bedrock 发现">
|
||||
- `plugins.entries.amazon-bedrock.config.discovery`:Bedrock 自动发现设置根。
|
||||
- `plugins.entries.amazon-bedrock.config.discovery.enabled`:打开 / 关闭隐式发现。
|
||||
- `plugins.entries.amazon-bedrock.config.discovery.region`:用于发现的 AWS 区域。
|
||||
- `plugins.entries.amazon-bedrock.config.discovery.providerFilter`:用于定向发现的可选 provider-id 过滤器。
|
||||
- `plugins.entries.amazon-bedrock.config.discovery.refreshInterval`:发现刷新的轮询间隔。
|
||||
- `plugins.entries.amazon-bedrock.config.discovery.defaultContextWindow`:已发现模型的回退上下文窗口。
|
||||
- `plugins.entries.amazon-bedrock.config.discovery.defaultMaxTokens`:已发现模型的回退最大输出 token 数。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### 提供商示例
|
||||
|
||||
<Accordion title="Cerebras(GLM 4.6 / 4.7)">
|
||||
|
||||
```json5
|
||||
{
|
||||
env: { CEREBRAS_API_KEY: "sk-..." },
|
||||
agents: {
|
||||
defaults: {
|
||||
model: {
|
||||
primary: "cerebras/zai-glm-4.7",
|
||||
fallbacks: ["cerebras/zai-glm-4.6"],
|
||||
<AccordionGroup>
|
||||
<Accordion title="Cerebras(GLM 4.6 / 4.7)">
|
||||
```json5
|
||||
{
|
||||
env: { CEREBRAS_API_KEY: "sk-..." },
|
||||
agents: {
|
||||
defaults: {
|
||||
model: {
|
||||
primary: "cerebras/zai-glm-4.7",
|
||||
fallbacks: ["cerebras/zai-glm-4.6"],
|
||||
},
|
||||
models: {
|
||||
"cerebras/zai-glm-4.7": { alias: "GLM 4.7 (Cerebras)" },
|
||||
"cerebras/zai-glm-4.6": { alias: "GLM 4.6 (Cerebras)" },
|
||||
},
|
||||
},
|
||||
},
|
||||
models: {
|
||||
"cerebras/zai-glm-4.7": { alias: "GLM 4.7 (Cerebras)" },
|
||||
"cerebras/zai-glm-4.6": { alias: "GLM 4.6 (Cerebras)" },
|
||||
},
|
||||
},
|
||||
},
|
||||
models: {
|
||||
mode: "merge",
|
||||
providers: {
|
||||
cerebras: {
|
||||
baseUrl: "https://api.cerebras.ai/v1",
|
||||
apiKey: "${CEREBRAS_API_KEY}",
|
||||
api: "openai-completions",
|
||||
models: [
|
||||
{ id: "zai-glm-4.7", name: "GLM 4.7 (Cerebras)" },
|
||||
{ id: "zai-glm-4.6", name: "GLM 4.6 (Cerebras)" },
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Cerebras 请使用 `cerebras/zai-glm-4.7`;Z.AI 直连请使用 `zai/glm-4.7`。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="OpenCode">
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
defaults: {
|
||||
model: { primary: "opencode/claude-opus-4-6" },
|
||||
models: { "opencode/claude-opus-4-6": { alias: "Opus" } },
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
设置 `OPENCODE_API_KEY`(或 `OPENCODE_ZEN_API_KEY`)。Zen 目录请使用 `opencode/...` 引用,Go 目录请使用 `opencode-go/...` 引用。快捷方式:`openclaw onboard --auth-choice opencode-zen` 或 `openclaw onboard --auth-choice opencode-go`。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Z.AI(GLM-4.7)">
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
defaults: {
|
||||
model: { primary: "zai/glm-4.7" },
|
||||
models: { "zai/glm-4.7": {} },
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
设置 `ZAI_API_KEY`。`z.ai/*` 和 `z-ai/*` 都是可接受的别名。快捷方式:`openclaw onboard --auth-choice zai-api-key`。
|
||||
|
||||
- 通用端点:`https://api.z.ai/api/paas/v4`
|
||||
- 编码端点(默认):`https://api.z.ai/api/coding/paas/v4`
|
||||
- 对于通用端点,请定义一个覆盖基础 URL 的自定义提供商。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Moonshot AI(Kimi)">
|
||||
|
||||
```json5
|
||||
{
|
||||
env: { MOONSHOT_API_KEY: "sk-..." },
|
||||
agents: {
|
||||
defaults: {
|
||||
model: { primary: "moonshot/kimi-k2.6" },
|
||||
models: { "moonshot/kimi-k2.6": { alias: "Kimi K2.6" } },
|
||||
},
|
||||
},
|
||||
models: {
|
||||
mode: "merge",
|
||||
providers: {
|
||||
moonshot: {
|
||||
baseUrl: "https://api.moonshot.ai/v1",
|
||||
apiKey: "${MOONSHOT_API_KEY}",
|
||||
api: "openai-completions",
|
||||
models: [
|
||||
{
|
||||
id: "kimi-k2.6",
|
||||
name: "Kimi K2.6",
|
||||
reasoning: false,
|
||||
input: ["text", "image"],
|
||||
cost: { input: 0.95, output: 4, cacheRead: 0.16, cacheWrite: 0 },
|
||||
contextWindow: 262144,
|
||||
maxTokens: 262144,
|
||||
mode: "merge",
|
||||
providers: {
|
||||
cerebras: {
|
||||
baseUrl: "https://api.cerebras.ai/v1",
|
||||
apiKey: "${CEREBRAS_API_KEY}",
|
||||
api: "openai-completions",
|
||||
models: [
|
||||
{ id: "zai-glm-4.7", name: "GLM 4.7 (Cerebras)" },
|
||||
{ id: "zai-glm-4.6", name: "GLM 4.6 (Cerebras)" },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
}
|
||||
```
|
||||
|
||||
对于中国端点:`baseUrl: "https://api.moonshot.cn/v1"` 或 `openclaw onboard --auth-choice moonshot-api-key-cn`。
|
||||
对于 Cerebras,使用 `cerebras/zai-glm-4.7`;对于 Z.AI 直连,使用 `zai/glm-4.7`。
|
||||
|
||||
原生 Moonshot 端点会在共享的
|
||||
`openai-completions` 传输上声明流式使用兼容性,而 OpenClaw 会依据端点能力
|
||||
而不只是内置提供商 id 本身来处理这一点。
|
||||
</Accordion>
|
||||
<Accordion title="Kimi Coding">
|
||||
```json5
|
||||
{
|
||||
env: { KIMI_API_KEY: "sk-..." },
|
||||
agents: {
|
||||
defaults: {
|
||||
model: { primary: "kimi/kimi-code" },
|
||||
models: { "kimi/kimi-code": { alias: "Kimi Code" } },
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
</Accordion>
|
||||
与 Anthropic 兼容的内置提供商。快捷方式:`openclaw onboard --auth-choice kimi-code-api-key`。
|
||||
|
||||
<Accordion title="Kimi Coding">
|
||||
|
||||
```json5
|
||||
{
|
||||
env: { KIMI_API_KEY: "sk-..." },
|
||||
agents: {
|
||||
defaults: {
|
||||
model: { primary: "kimi/kimi-code" },
|
||||
models: { "kimi/kimi-code": { alias: "Kimi Code" } },
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
与 Anthropic 兼容,内置提供商。快捷方式:`openclaw onboard --auth-choice kimi-code-api-key`。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Synthetic(与 Anthropic 兼容)">
|
||||
|
||||
```json5
|
||||
{
|
||||
env: { SYNTHETIC_API_KEY: "sk-..." },
|
||||
agents: {
|
||||
defaults: {
|
||||
model: { primary: "synthetic/hf:MiniMaxAI/MiniMax-M2.5" },
|
||||
models: { "synthetic/hf:MiniMaxAI/MiniMax-M2.5": { alias: "MiniMax M2.5" } },
|
||||
},
|
||||
},
|
||||
models: {
|
||||
mode: "merge",
|
||||
providers: {
|
||||
synthetic: {
|
||||
baseUrl: "https://api.synthetic.new/anthropic",
|
||||
apiKey: "${SYNTHETIC_API_KEY}",
|
||||
api: "anthropic-messages",
|
||||
models: [
|
||||
{
|
||||
id: "hf:MiniMaxAI/MiniMax-M2.5",
|
||||
name: "MiniMax M2.5",
|
||||
reasoning: true,
|
||||
input: ["text"],
|
||||
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||
contextWindow: 192000,
|
||||
maxTokens: 65536,
|
||||
</Accordion>
|
||||
<Accordion title="本地模型(LM Studio)">
|
||||
参见[本地模型](/zh-CN/gateway/local-models)。简而言之:在高性能硬件上通过 LM Studio Responses API 运行大型本地模型;同时保留已合并的托管模型作为回退。
|
||||
</Accordion>
|
||||
<Accordion title="MiniMax M2.7(直连)">
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
defaults: {
|
||||
model: { primary: "minimax/MiniMax-M2.7" },
|
||||
models: {
|
||||
"minimax/MiniMax-M2.7": { alias: "Minimax" },
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
基础 URL 不应包含 `/v1`(Anthropic 客户端会追加它)。快捷方式:`openclaw onboard --auth-choice synthetic-api-key`。
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="MiniMax M2.7(直连)">
|
||||
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
defaults: {
|
||||
model: { primary: "minimax/MiniMax-M2.7" },
|
||||
models: {
|
||||
"minimax/MiniMax-M2.7": { alias: "Minimax" },
|
||||
},
|
||||
},
|
||||
},
|
||||
models: {
|
||||
mode: "merge",
|
||||
providers: {
|
||||
minimax: {
|
||||
baseUrl: "https://api.minimax.io/anthropic",
|
||||
apiKey: "${MINIMAX_API_KEY}",
|
||||
api: "anthropic-messages",
|
||||
models: [
|
||||
{
|
||||
id: "MiniMax-M2.7",
|
||||
name: "MiniMax M2.7",
|
||||
reasoning: true,
|
||||
input: ["text"],
|
||||
cost: { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0.375 },
|
||||
contextWindow: 204800,
|
||||
maxTokens: 131072,
|
||||
mode: "merge",
|
||||
providers: {
|
||||
minimax: {
|
||||
baseUrl: "https://api.minimax.io/anthropic",
|
||||
apiKey: "${MINIMAX_API_KEY}",
|
||||
api: "anthropic-messages",
|
||||
models: [
|
||||
{
|
||||
id: "MiniMax-M2.7",
|
||||
name: "MiniMax M2.7",
|
||||
reasoning: true,
|
||||
input: ["text"],
|
||||
cost: { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0.375 },
|
||||
contextWindow: 204800,
|
||||
maxTokens: 131072,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
}
|
||||
```
|
||||
|
||||
设置 `MINIMAX_API_KEY`。快捷方式:
|
||||
`openclaw onboard --auth-choice minimax-global-api` 或
|
||||
`openclaw onboard --auth-choice minimax-cn-api`。
|
||||
模型目录默认仅包含 M2.7。
|
||||
在与 Anthropic 兼容的流式路径上,OpenClaw 默认会禁用 MiniMax thinking,
|
||||
除非你自行显式设置 `thinking`。`/fast on` 或
|
||||
`params.fastMode: true` 会将 `MiniMax-M2.7` 重写为
|
||||
`MiniMax-M2.7-highspeed`。
|
||||
设置 `MINIMAX_API_KEY`。快捷方式:`openclaw onboard --auth-choice minimax-global-api` 或 `openclaw onboard --auth-choice minimax-cn-api`。模型目录默认仅包含 M2.7。在 Anthropic 兼容的流式传输路径上,除非你显式设置 `thinking`,否则 OpenClaw 默认会禁用 MiniMax thinking。`/fast on` 或 `params.fastMode: true` 会将 `MiniMax-M2.7` 重写为 `MiniMax-M2.7-highspeed`。
|
||||
|
||||
</Accordion>
|
||||
</Accordion>
|
||||
<Accordion title="Moonshot AI(Kimi)">
|
||||
```json5
|
||||
{
|
||||
env: { MOONSHOT_API_KEY: "sk-..." },
|
||||
agents: {
|
||||
defaults: {
|
||||
model: { primary: "moonshot/kimi-k2.6" },
|
||||
models: { "moonshot/kimi-k2.6": { alias: "Kimi K2.6" } },
|
||||
},
|
||||
},
|
||||
models: {
|
||||
mode: "merge",
|
||||
providers: {
|
||||
moonshot: {
|
||||
baseUrl: "https://api.moonshot.ai/v1",
|
||||
apiKey: "${MOONSHOT_API_KEY}",
|
||||
api: "openai-completions",
|
||||
models: [
|
||||
{
|
||||
id: "kimi-k2.6",
|
||||
name: "Kimi K2.6",
|
||||
reasoning: false,
|
||||
input: ["text", "image"],
|
||||
cost: { input: 0.95, output: 4, cacheRead: 0.16, cacheWrite: 0 },
|
||||
contextWindow: 262144,
|
||||
maxTokens: 262144,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<Accordion title="本地模型(LM Studio)">
|
||||
对于中国端点:`baseUrl: "https://api.moonshot.cn/v1"` 或 `openclaw onboard --auth-choice moonshot-api-key-cn`。
|
||||
|
||||
参见 [本地模型](/zh-CN/gateway/local-models)。简而言之:在性能足够强的硬件上,通过 LM Studio Responses API 运行大型本地模型;同时保留已合并的托管模型作为回退。
|
||||
原生 Moonshot 端点在共享的 `openai-completions` 传输上声明了流式传输使用兼容性,OpenClaw 会根据端点能力而不仅仅是内置提供商 id 来判断这一点。
|
||||
|
||||
</Accordion>
|
||||
</Accordion>
|
||||
<Accordion title="OpenCode">
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
defaults: {
|
||||
model: { primary: "opencode/claude-opus-4-6" },
|
||||
models: { "opencode/claude-opus-4-6": { alias: "Opus" } },
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
设置 `OPENCODE_API_KEY`(或 `OPENCODE_ZEN_API_KEY`)。对 Zen 目录使用 `opencode/...` 引用,对 Go 目录使用 `opencode-go/...` 引用。快捷方式:`openclaw onboard --auth-choice opencode-zen` 或 `openclaw onboard --auth-choice opencode-go`。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Synthetic(与 Anthropic 兼容)">
|
||||
```json5
|
||||
{
|
||||
env: { SYNTHETIC_API_KEY: "sk-..." },
|
||||
agents: {
|
||||
defaults: {
|
||||
model: { primary: "synthetic/hf:MiniMaxAI/MiniMax-M2.5" },
|
||||
models: { "synthetic/hf:MiniMaxAI/MiniMax-M2.5": { alias: "MiniMax M2.5" } },
|
||||
},
|
||||
},
|
||||
models: {
|
||||
mode: "merge",
|
||||
providers: {
|
||||
synthetic: {
|
||||
baseUrl: "https://api.synthetic.new/anthropic",
|
||||
apiKey: "${SYNTHETIC_API_KEY}",
|
||||
api: "anthropic-messages",
|
||||
models: [
|
||||
{
|
||||
id: "hf:MiniMaxAI/MiniMax-M2.5",
|
||||
name: "MiniMax M2.5",
|
||||
reasoning: true,
|
||||
input: ["text"],
|
||||
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||
contextWindow: 192000,
|
||||
maxTokens: 65536,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
基础 URL 不应包含 `/v1`(Anthropic 客户端会附加它)。快捷方式:`openclaw onboard --auth-choice synthetic-api-key`。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Z.AI(GLM-4.7)">
|
||||
```json5
|
||||
{
|
||||
agents: {
|
||||
defaults: {
|
||||
model: { primary: "zai/glm-4.7" },
|
||||
models: { "zai/glm-4.7": {} },
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
设置 `ZAI_API_KEY`。`z.ai/*` 和 `z-ai/*` 都是可接受的别名。快捷方式:`openclaw onboard --auth-choice zai-api-key`。
|
||||
|
||||
- 通用端点:`https://api.z.ai/api/paas/v4`
|
||||
- Coding 端点(默认):`https://api.z.ai/api/coding/paas/v4`
|
||||
- 对于通用端点,请定义带有基础 URL 覆盖的自定义提供商。
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
---
|
||||
|
||||
## 相关内容
|
||||
|
||||
- [配置参考](/zh-CN/gateway/configuration-reference) —— 其他顶层键
|
||||
- [配置 —— 智能体](/zh-CN/gateway/config-agents)
|
||||
- [配置 —— 渠道](/zh-CN/gateway/config-channels)
|
||||
- [配置——智能体](/zh-CN/gateway/config-agents)
|
||||
- [配置——渠道](/zh-CN/gateway/config-channels)
|
||||
- [配置参考](/zh-CN/gateway/configuration-reference) —— 其他顶级键
|
||||
- [工具和插件](/zh-CN/tools)
|
||||
|
||||
@ -1,26 +1,26 @@
|
||||
---
|
||||
read_when:
|
||||
- 你希望将 OpenClaw 模型使用情况、消息流或会话指标发送到 OpenTelemetry 收集器
|
||||
- 你想将 OpenClaw 的模型使用情况、消息流或会话指标发送到 OpenTelemetry 收集器
|
||||
- 你正在将追踪、指标或日志接入 Grafana、Datadog、Honeycomb、New Relic、Tempo 或其他 OTLP 后端
|
||||
- 你需要准确的指标名称、Span 名称或属性结构来构建仪表板或告警
|
||||
summary: 通过 diagnostics-otel 插件(OTLP/HTTP)将 OpenClaw 诊断数据导出到任何 OpenTelemetry 收集器
|
||||
- 你需要确切的指标名称、span 名称或属性结构来构建仪表板或告警
|
||||
summary: 通过 diagnostics-otel 插件(OTLP/HTTP),将 OpenClaw 诊断数据导出到任何 OpenTelemetry 收集器
|
||||
title: OpenTelemetry 导出
|
||||
x-i18n:
|
||||
generated_at: "2026-04-26T04:44:23Z"
|
||||
generated_at: "2026-04-26T06:59:36Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 2f2389c4efc2984d27e571152ce3cfea2ffeddc99084695f1c6ab6c97e6b7f7b
|
||||
source_hash: 6b0a8e2e9e808597c6a139306d4b1264e198edb95579a5f7ba36db049ec96afe
|
||||
source_path: gateway/opentelemetry.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
OpenClaw 通过内置的 `diagnostics-otel` 插件使用 **OTLP/HTTP(protobuf)** 导出诊断数据。任何接受 OTLP/HTTP 的收集器或后端都无需修改代码即可使用。有关本地文件日志以及如何读取它们,请参阅 [日志](/zh-CN/logging)。
|
||||
OpenClaw 通过内置的 `diagnostics-otel` 插件,使用 **OTLP/HTTP(protobuf)** 导出诊断数据。任何接受 OTLP/HTTP 的收集器或后端都无需代码改动即可使用。关于本地文件日志以及如何读取它们,请参阅 [Logging](/zh-CN/logging)。
|
||||
|
||||
## 工作方式
|
||||
## 它是如何协同工作的
|
||||
|
||||
- **诊断事件** 是 Gateway 网关和内置插件为模型运行、消息流、会话、队列和 exec 发出的结构化进程内记录。
|
||||
- **诊断事件** 是由 Gateway 网关和内置插件为模型运行、消息流、会话、队列和 exec 发出的结构化进程内记录。
|
||||
- **`diagnostics-otel` 插件** 订阅这些事件,并通过 OTLP/HTTP 将其导出为 OpenTelemetry **指标**、**追踪** 和 **日志**。
|
||||
- 只有在诊断功能面和插件都已启用时,导出器才会附加,因此默认情况下进程内开销几乎为零。
|
||||
- 只有在诊断功能和插件都启用时,导出器才会附加,因此默认情况下进程内开销几乎为零。
|
||||
|
||||
## 快速开始
|
||||
|
||||
@ -56,18 +56,18 @@ openclaw plugins enable diagnostics-otel
|
||||
```
|
||||
|
||||
<Note>
|
||||
`protocol` 目前仅支持 `http/protobuf`。`grpc` 会被忽略。
|
||||
`protocol` 当前仅支持 `http/protobuf`。`grpc` 会被忽略。
|
||||
</Note>
|
||||
|
||||
## 导出的信号
|
||||
|
||||
| 信号 | 包含内容 |
|
||||
| ----------- | --------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **指标** | 用于令牌使用量、成本、运行时长、消息流、队列通道、会话状态、exec 和内存压力的计数器与直方图。 |
|
||||
| **追踪** | 用于模型使用、模型调用、工具执行、exec、webhook/消息处理、上下文组装和工具循环的 Span。 |
|
||||
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| **指标** | 用于 token 使用量、成本、运行时长、消息流、队列通道、会话状态、exec 和内存压力的计数器与直方图。 |
|
||||
| **追踪** | 用于模型使用、模型调用、harness 生命周期、工具执行、exec、webhook/消息处理、上下文组装和工具循环的 span。 |
|
||||
| **日志** | 当启用 `diagnostics.otel.logs` 时,通过 OTLP 导出的结构化 `logging.file` 记录。 |
|
||||
|
||||
你可以独立切换 `traces`、`metrics` 和 `logs`。当 `diagnostics.otel.enabled` 为 true 时,这三者默认都开启。
|
||||
可以独立切换 `traces`、`metrics` 和 `logs`。当 `diagnostics.otel.enabled` 为 true 时,这三项默认都开启。
|
||||
|
||||
## 配置参考
|
||||
|
||||
@ -106,32 +106,32 @@ 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` 配置键未设置时,使用按信号划分的端点覆盖。信号专用配置优先于信号专用环境变量,而信号专用环境变量优先于共享端点。 |
|
||||
| `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_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` | 当另一个预加载项或宿主进程已注册全局 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` | 当另一个 preload 或宿主进程已经注册了全局 OpenTelemetry SDK 时,设置为 `1`。此时插件会跳过自身的 NodeSDK 生命周期,但仍会连接诊断监听器,并遵守 `traces` / `metrics` / `logs`。 |
|
||||
|
||||
## 隐私与内容采集
|
||||
## 隐私与内容捕获
|
||||
|
||||
默认情况下**不会**导出原始模型/工具内容。Span 携带的是有界标识符(渠道、提供商、模型、错误类别、仅哈希的请求 id),绝不会包含提示词文本、响应文本、工具输入、工具输出或会话键。
|
||||
默认**不会**导出原始模型/工具内容。span 携带的是有界标识符(渠道、提供商、模型、错误类别、仅哈希的请求 ID),绝不会包含提示词文本、响应文本、工具输入、工具输出或会话键。
|
||||
|
||||
仅当你的收集器和保留策略已获批准可处理提示词、响应、工具或系统提示文本时,才将 `diagnostics.otel.captureContent.*` 设为 `true`。每个子键都需单独选择启用:
|
||||
仅当你的收集器和保留策略已获批准可存储提示词、响应、工具或系统提示文本时,才将 `diagnostics.otel.captureContent.*` 设为 `true`。每个子键都需要独立选择启用:
|
||||
|
||||
- `inputMessages` — 用户提示内容。
|
||||
- `outputMessages` — 模型响应内容。
|
||||
- `toolInputs` — 工具参数负载。
|
||||
- `toolOutputs` — 工具结果负载。
|
||||
- `systemPrompt` — 组装后的 system/developer 提示词。
|
||||
- `inputMessages` —— 用户提示内容。
|
||||
- `outputMessages` —— 模型响应内容。
|
||||
- `toolInputs` —— 工具参数负载。
|
||||
- `toolOutputs` —— 工具结果负载。
|
||||
- `systemPrompt` —— 组装后的 system/developer 提示词。
|
||||
|
||||
当启用任一子键时,模型和工具 Span 仅会为该类内容附加有界、已脱敏的 `openclaw.content.*` 属性。
|
||||
当启用任一子键时,模型和工具 span 仅会为该类内容添加有界、已脱敏的 `openclaw.content.*` 属性。
|
||||
|
||||
## 采样与刷新
|
||||
|
||||
- **追踪:** `diagnostics.otel.sampleRate`(仅根 Span,`0.0` 丢弃全部,`1.0` 保留全部)。
|
||||
- **追踪:** `diagnostics.otel.sampleRate`(仅根 span,`0.0` 表示全部丢弃,`1.0` 表示全部保留)。
|
||||
- **指标:** `diagnostics.otel.flushIntervalMs`(最小值为 `1000`)。
|
||||
- **日志:** OTLP 日志遵循 `logging.level`(文件日志级别)。控制台脱敏**不会**应用于 OTLP 日志。高流量部署应优先使用 OTLP 收集器采样/过滤,而不是本地采样。
|
||||
- **日志:** OTLP 日志遵循 `logging.level`(文件日志级别)。控制台脱敏**不会**应用到 OTLP 日志。高流量部署应优先使用 OTLP 收集器采样/过滤,而不是本地采样。
|
||||
|
||||
## 导出的指标
|
||||
|
||||
@ -142,7 +142,7 @@ openclaw plugins enable diagnostics-otel
|
||||
- `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.operation.duration`(直方图,单位为秒,GenAI 语义约定指标,属性:`gen_ai.provider.name`、`gen_ai.operation.name`、`gen_ai.request.model`,可选 `error.type`)
|
||||
|
||||
### 消息流
|
||||
|
||||
@ -166,6 +166,10 @@ openclaw plugins enable diagnostics-otel
|
||||
- `openclaw.session.stuck_age_ms`(直方图,属性:`openclaw.state`)
|
||||
- `openclaw.run.attempt`(计数器,属性:`openclaw.attempt`)
|
||||
|
||||
### Harness 生命周期
|
||||
|
||||
- `openclaw.harness.duration_ms`(直方图,属性:`openclaw.harness.id`、`openclaw.harness.plugin`、`openclaw.outcome`,错误时还包括 `openclaw.harness.phase`)
|
||||
|
||||
### Exec
|
||||
|
||||
- `openclaw.exec.duration_ms`(直方图,属性:`openclaw.exec.target`、`openclaw.exec.mode`、`openclaw.outcome`、`openclaw.failureKind`)
|
||||
@ -178,19 +182,23 @@ openclaw plugins enable diagnostics-otel
|
||||
- `openclaw.tool.loop.iterations`(计数器,属性:`openclaw.toolName`、`openclaw.outcome`)
|
||||
- `openclaw.tool.loop.duration_ms`(直方图,属性:`openclaw.toolName`、`openclaw.outcome`)
|
||||
|
||||
## 导出的 Span
|
||||
## 导出的 span
|
||||
|
||||
- `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 语义约定时使用 `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 语义约定时使用 `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.provider.request_id_hash`(上游提供商请求 ID 的有界 SHA 哈希;不会导出原始 ID)
|
||||
- `openclaw.harness.run`
|
||||
- `openclaw.harness.id`、`openclaw.harness.plugin`、`openclaw.outcome`、`openclaw.provider`、`openclaw.model`、`openclaw.channel`
|
||||
- 完成时:`openclaw.harness.result_classification`、`openclaw.harness.yield_detected`、`openclaw.harness.items.started`、`openclaw.harness.items.completed`、`openclaw.harness.items.active`
|
||||
- 出错时:`openclaw.harness.phase`、`openclaw.errorCategory`、可选的 `openclaw.harness.cleanup_failed`
|
||||
- `openclaw.tool.execution`
|
||||
- `gen_ai.tool.name`、`openclaw.toolName`、`openclaw.errorCategory`、`openclaw.tool.params.*`
|
||||
- `openclaw.exec`
|
||||
@ -206,21 +214,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`(不包含提示词、历史记录、响应或会话键内容)
|
||||
- `openclaw.prompt.size`、`openclaw.history.size`、`openclaw.context.tokens`、`openclaw.errorCategory`(不包含 prompt、history、response 或 session-key 内容)
|
||||
- `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.*` 属性,仅适用于你选择启用的特定内容类别。
|
||||
当显式启用内容捕获时,模型和工具 span 还可以包含有界、已脱敏的 `openclaw.content.*` 属性,用于你选择启用的特定内容类别。
|
||||
|
||||
## 诊断事件目录
|
||||
|
||||
下列事件为上述指标和 Span 提供基础。插件也可以直接订阅这些事件,而无需 OTLP 导出。
|
||||
以下事件为上面的指标和 span 提供支持。插件也可以直接订阅它们,而无需 OTLP 导出。
|
||||
|
||||
**模型使用情况**
|
||||
|
||||
- `model.usage` — 令牌、成本、时长、上下文、提供商/模型/渠道、会话 id。`usage` 是提供商/轮次级别的成本与遥测计量;`context.used` 是当前提示词/上下文快照,在涉及缓存输入或工具循环调用时,它可能低于提供商的 `usage.total`。
|
||||
- `model.usage` — token、成本、时长、上下文、提供商/模型/渠道、会话 ID。`usage` 是提供商/轮次级别的成本和遥测统计;`context.used` 是当前的 prompt/上下文快照,在涉及缓存输入或工具循环调用时,可能低于提供商的 `usage.total`。
|
||||
|
||||
**消息流**
|
||||
|
||||
@ -233,15 +241,19 @@ openclaw plugins enable diagnostics-otel
|
||||
- `queue.lane.enqueue` / `queue.lane.dequeue`
|
||||
- `session.state` / `session.stuck`
|
||||
- `run.attempt`
|
||||
- `diagnostic.heartbeat`(聚合计数器:webhook/队列/会话)
|
||||
- `diagnostic.heartbeat`(聚合计数器:webhooks/queue/session)
|
||||
|
||||
**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`。
|
||||
|
||||
**Exec**
|
||||
|
||||
- `exec.process.completed` — 最终结果、时长、目标、模式、退出码和失败类型。不包含命令文本和工作目录。
|
||||
- `exec.process.completed` — 终态结果、时长、目标、模式、退出码和失败类型。不包含命令文本和工作目录。
|
||||
|
||||
## 不使用导出器
|
||||
|
||||
你可以在不运行 `diagnostics-otel` 的情况下,让插件或自定义接收端仍然可用诊断事件:
|
||||
你可以在不运行 `diagnostics-otel` 的情况下,仍然让诊断事件可供插件或自定义 sink 使用:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -249,7 +261,7 @@ openclaw plugins enable diagnostics-otel
|
||||
}
|
||||
```
|
||||
|
||||
如果你想在不提高 `logging.level` 的情况下获得定向调试输出,请使用诊断标记。标记不区分大小写,并支持通配符(例如 `telegram.*` 或 `*`):
|
||||
如需在不提高 `logging.level` 的情况下获取定向调试输出,请使用诊断标志。标志不区分大小写,并支持通配符(例如 `telegram.*` 或 `*`):
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -263,8 +275,8 @@ openclaw plugins enable diagnostics-otel
|
||||
OPENCLAW_DIAGNOSTICS=telegram.http,telegram.payload openclaw gateway
|
||||
```
|
||||
|
||||
标记输出会进入标准日志文件(`logging.file`),并且仍会由 `logging.redactSensitive` 进行脱敏。完整指南:
|
||||
[诊断标记](/zh-CN/diagnostics/flags)。
|
||||
标志输出会写入标准日志文件(`logging.file`),并且仍会由 `logging.redactSensitive` 进行脱敏。完整指南请参阅:
|
||||
[Diagnostics flags](/zh-CN/diagnostics/flags)。
|
||||
|
||||
## 禁用
|
||||
|
||||
@ -274,13 +286,13 @@ OPENCLAW_DIAGNOSTICS=telegram.http,telegram.payload openclaw gateway
|
||||
}
|
||||
```
|
||||
|
||||
你也可以不将 `diagnostics-otel` 放入 `plugins.allow`,或者运行
|
||||
你也可以不将 `diagnostics-otel` 加入 `plugins.allow`,或运行
|
||||
`openclaw plugins disable diagnostics-otel`。
|
||||
|
||||
## 相关内容
|
||||
|
||||
- [日志](/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.*` 字段参考
|
||||
- [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.*` 字段参考
|
||||
|
||||
@ -1,21 +1,21 @@
|
||||
---
|
||||
read_when:
|
||||
- 你正在构建一个 OpenClaw 插件
|
||||
- 你需要发布一个插件配置 schema,或调试插件校验错误
|
||||
- 你需要发布插件配置 schema,或调试插件校验错误
|
||||
summary: 插件清单 + JSON schema 要求(严格配置校验)
|
||||
title: 插件清单
|
||||
x-i18n:
|
||||
generated_at: "2026-04-26T06:01:21Z"
|
||||
generated_at: "2026-04-26T06:59:33Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: fa906a38666a3773130bb8b4725f73c7b1534f5ab10408acbec8b4b732ecd578
|
||||
source_hash: 12eae5bd8e3ca47e7d2fb2202cd32abba8d79136d14dd5e38f0aac1c30c02e35
|
||||
source_path: plugins/manifest.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
此页面仅适用于**原生 OpenClaw 插件清单**。
|
||||
|
||||
有关兼容的 bundle 布局,请参阅 [插件 bundles](/zh-CN/plugins/bundles)。
|
||||
有关兼容的 bundle 布局,请参见 [插件 bundles](/zh-CN/plugins/bundles)。
|
||||
|
||||
兼容的 bundle 格式使用不同的清单文件:
|
||||
|
||||
@ -23,31 +23,31 @@ x-i18n:
|
||||
- Claude bundle:`.claude-plugin/plugin.json`,或不带清单的默认 Claude 组件布局
|
||||
- Cursor bundle:`.cursor-plugin/plugin.json`
|
||||
|
||||
OpenClaw 也会自动检测这些 bundle 布局,但它们不会按照此处描述的 `openclaw.plugin.json` schema 进行校验。
|
||||
OpenClaw 也会自动检测这些 bundle 布局,但不会根据此处描述的 `openclaw.plugin.json` schema 对它们进行校验。
|
||||
|
||||
对于兼容 bundles,当布局符合 OpenClaw 运行时预期时,OpenClaw 当前会读取 bundle 元数据,以及已声明的 skill 根目录、Claude 命令根目录、Claude bundle `settings.json` 默认值、Claude bundle LSP 默认值,以及受支持的 hook packs。
|
||||
对于兼容 bundle,当其布局符合 OpenClaw 运行时预期时,OpenClaw 当前会读取 bundle 元数据、声明的 skill 根目录、Claude 命令根目录、Claude bundle `settings.json` 默认值、Claude bundle LSP 默认值,以及受支持的 hook packs。
|
||||
|
||||
每个原生 OpenClaw 插件**都必须**在**插件根目录**中提供一个 `openclaw.plugin.json` 文件。OpenClaw 使用此清单在**不执行插件代码**的情况下校验配置。缺失或无效的清单会被视为插件错误,并阻止配置校验。
|
||||
|
||||
查看完整的插件系统指南:[插件](/zh-CN/tools/plugin)。
|
||||
有关原生能力模型和当前外部兼容性指南,请参阅:
|
||||
请参阅完整的插件系统指南:[插件](/zh-CN/tools/plugin)。
|
||||
关于原生能力模型和当前外部兼容性指导,请参见:
|
||||
[能力模型](/zh-CN/plugins/architecture#public-capability-model)。
|
||||
|
||||
## 此文件的作用
|
||||
|
||||
`openclaw.plugin.json` 是 OpenClaw 在**加载你的插件代码之前**读取的元数据。下面的所有内容都必须足够轻量,能够在不启动插件运行时的情况下进行检查。
|
||||
`openclaw.plugin.json` 是 OpenClaw 在**加载你的插件代码之前**读取的元数据。下面的所有内容都必须足够轻量,以便无需启动插件运行时即可检查。
|
||||
|
||||
**用于:**
|
||||
**请将它用于:**
|
||||
|
||||
- 插件标识、配置校验,以及配置 UI 提示
|
||||
- 凭证、onboarding 和设置元数据(别名、自动启用、提供商环境变量、凭证选项)
|
||||
- 认证、新手引导和设置元数据(别名、自动启用、provider 环境变量、认证选项)
|
||||
- 控制平面界面的激活提示
|
||||
- 简写模型家族归属
|
||||
- 静态能力归属快照(`contracts`)
|
||||
- 共享 `openclaw qa` 主机可检查的 QA 运行器元数据
|
||||
- 合并到目录和校验界面的渠道特定配置元数据
|
||||
- 供共享 `openclaw qa` 主机检查的 QA 运行器元数据
|
||||
- 合并到目录和校验界面中的渠道专用配置元数据
|
||||
|
||||
**不要用于:**注册运行时行为、声明代码入口点,或 npm 安装元数据。这些应放在你的插件代码和 `package.json` 中。
|
||||
**不要将它用于:**注册运行时行为、声明代码入口点,或 npm 安装元数据。这些应放在你的插件代码和 `package.json` 中。
|
||||
|
||||
## 最小示例
|
||||
|
||||
@ -96,19 +96,19 @@ OpenClaw 也会自动检测这些 bundle 布局,但它们不会按照此处描
|
||||
"provider": "openrouter",
|
||||
"method": "api-key",
|
||||
"choiceId": "openrouter-api-key",
|
||||
"choiceLabel": "OpenRouter API 密钥",
|
||||
"choiceLabel": "OpenRouter API key",
|
||||
"groupId": "openrouter",
|
||||
"groupLabel": "OpenRouter",
|
||||
"optionKey": "openrouterApiKey",
|
||||
"cliFlag": "--openrouter-api-key",
|
||||
"cliOption": "--openrouter-api-key <key>",
|
||||
"cliDescription": "OpenRouter API 密钥",
|
||||
"cliDescription": "OpenRouter API key",
|
||||
"onboardingScopes": ["text-inference"]
|
||||
}
|
||||
],
|
||||
"uiHints": {
|
||||
"apiKey": {
|
||||
"label": "API 密钥",
|
||||
"label": "API key",
|
||||
"placeholder": "sk-or-v1-...",
|
||||
"sensitive": true
|
||||
}
|
||||
@ -129,32 +129,32 @@ OpenClaw 也会自动检测这些 bundle 布局,但它们不会按照此处描
|
||||
|
||||
| 字段 | 必填 | 类型 | 含义 |
|
||||
| ------------------------------------ | -------- | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `id` | 是 | `string` | 规范插件 id。这是 `plugins.entries.<id>` 中使用的 id。 |
|
||||
| `id` | 是 | `string` | 规范插件 id。这是在 `plugins.entries.<id>` 中使用的 id。 |
|
||||
| `configSchema` | 是 | `object` | 此插件配置的内联 JSON Schema。 |
|
||||
| `enabledByDefault` | 否 | `true` | 将内置插件标记为默认启用。省略该字段,或设置为任何非 `true` 的值,则该插件默认保持禁用。 |
|
||||
| `legacyPluginIds` | 否 | `string[]` | 会规范化为此规范插件 id 的旧版 id。 |
|
||||
| `autoEnableWhenConfiguredProviders` | 否 | `string[]` | 当凭证、配置或模型引用提到这些 provider id 时,应自动启用此插件。 |
|
||||
| `kind` | 否 | `"memory"` \| `"context-engine"` | 声明一个由 `plugins.slots.*` 使用的互斥插件类型。 |
|
||||
| `channels` | 否 | `string[]` | 此插件拥有的渠道 id。用于发现和配置校验。 |
|
||||
| `providers` | 否 | `string[]` | 此插件拥有的 provider id。 |
|
||||
| `providerDiscoveryEntry` | 否 | `string` | 轻量级 provider 发现模块路径,相对于插件根目录,用于可在不激活完整插件运行时的情况下加载的、受清单作用域约束的 provider 目录元数据。 |
|
||||
| `enabledByDefault` | 否 | `true` | 将内置插件标记为默认启用。省略此字段,或将其设为任何非 `true` 的值,以保持插件默认禁用。 |
|
||||
| `legacyPluginIds` | 否 | `string[]` | 会归一化为此规范插件 id 的旧版 id。 |
|
||||
| `autoEnableWhenConfiguredProviders` | 否 | `string[]` | 当认证、配置或模型引用提到这些 provider id 时,应自动启用此插件。 |
|
||||
| `kind` | 否 | `"memory"` \| `"context-engine"` | 声明一个由 `plugins.slots.*` 使用的排他性插件类型。 |
|
||||
| `channels` | 否 | `string[]` | 由此插件拥有的渠道 id。用于发现和配置校验。 |
|
||||
| `providers` | 否 | `string[]` | 由此插件拥有的 provider id。 |
|
||||
| `providerDiscoveryEntry` | 否 | `string` | 轻量级 provider 发现模块路径,相对于插件根目录,用于可在不激活完整插件运行时的情况下加载的、限定于清单范围的 provider 目录元数据。 |
|
||||
| `modelSupport` | 否 | `object` | 由清单拥有的简写模型家族元数据,用于在运行时之前自动加载插件。 |
|
||||
| `modelCatalog` | 否 | `object` | 适用于此插件拥有的 providers 的声明式模型目录元数据。这是未来只读列表、onboarding、模型选择器、别名和抑制功能的控制平面契约,无需加载插件运行时。 |
|
||||
| `providerEndpoints` | 否 | `object[]` | 由清单拥有的 endpoint host/baseUrl 元数据,用于核心在 provider 运行时加载前必须分类的 provider 路由。 |
|
||||
| `cliBackends` | 否 | `string[]` | 此插件拥有的 CLI 推理后端 id。用于根据显式配置引用在启动时自动激活。 |
|
||||
| `syntheticAuthRefs` | 否 | `string[]` | provider 或 CLI 后端引用;在运行时加载前的冷模型发现期间,应探测其由插件拥有的 synthetic auth hook。 |
|
||||
| `nonSecretAuthMarkers` | 否 | `string[]` | 由内置插件拥有的占位 API 密钥值,表示非机密的本地、OAuth 或环境凭证状态。 |
|
||||
| `commandAliases` | 否 | `object[]` | 此插件拥有的命令名称;在运行时加载前,这些命令应生成具备插件感知能力的配置和 CLI 诊断信息。 |
|
||||
| `providerAuthEnvVars` | 否 | `Record<string, string[]>` | 用于 provider 凭证/Status 查询的已弃用兼容性环境变量元数据。新插件优先使用 `setup.providers[].envVars`;在弃用窗口期内,OpenClaw 仍会读取此字段。 |
|
||||
| `providerAuthAliases` | 否 | `Record<string, string>` | 应复用另一个 provider id 进行凭证查询的 provider id,例如共享基础 provider API 密钥和凭证配置文件的 coding provider。 |
|
||||
| `channelEnvVars` | 否 | `Record<string, string[]>` | OpenClaw 可在不加载插件代码的情况下检查的轻量渠道环境变量元数据。将其用于通用启动/配置辅助工具应可见的、由环境变量驱动的渠道设置或凭证界面。 |
|
||||
| `providerAuthChoices` | 否 | `object[]` | 用于 onboarding 选择器、首选 provider 解析和简单 CLI flag 连接的轻量凭证选项元数据。 |
|
||||
| `activation` | 否 | `object` | 用于 provider、命令、渠道、路由和能力触发加载的轻量激活规划器元数据。仅为元数据;插件运行时仍拥有实际行为。 |
|
||||
| `setup` | 否 | `object` | 发现和设置界面可在不加载插件运行时的情况下检查的轻量设置/onboarding 描述符。 |
|
||||
| `qaRunners` | 否 | `object[]` | 共享 `openclaw qa` 主机在插件运行时加载前使用的轻量 QA 运行器描述符。 |
|
||||
| `contracts` | 否 | `object` | 面向外部 auth hooks、speech、realtime transcription、realtime voice、media-understanding、image-generation、music-generation、video-generation、web-fetch、web search 和工具归属的静态内置能力快照。 |
|
||||
| `mediaUnderstandingProviderMetadata` | 否 | `Record<string, object>` | 针对 `contracts.mediaUnderstandingProviders` 中声明的 provider id 的轻量 media-understanding 默认值。 |
|
||||
| `channelConfigs` | 否 | `Record<string, object>` | 由清单拥有的渠道配置元数据,会在运行时加载前合并到发现和校验界面中。 |
|
||||
| `modelCatalog` | 否 | `object` | 由此插件拥有的 provider 的声明式模型目录元数据。这是未来只读列表、新手引导、模型选择器、别名和抑制功能的控制平面契约,且无需加载插件运行时。 |
|
||||
| `providerEndpoints` | 否 | `object[]` | 由清单拥有的端点 host/baseUrl 元数据,用于核心系统必须在 provider 运行时加载前分类的 provider 路由。 |
|
||||
| `cliBackends` | 否 | `string[]` | 由此插件拥有的 CLI 推理后端 id。用于根据显式配置引用在启动时自动激活。 |
|
||||
| `syntheticAuthRefs` | 否 | `string[]` | provider 或 CLI 后端引用,在运行时加载前进行冷模型发现期间,应探测其由插件拥有的合成认证 hook。 |
|
||||
| `nonSecretAuthMarkers` | 否 | `string[]` | 由内置插件拥有的占位 API key 值,表示非机密的本地、OAuth 或环境凭证状态。 |
|
||||
| `commandAliases` | 否 | `object[]` | 由此插件拥有的命令名称,在运行时加载前应生成具备插件感知能力的配置和 CLI 诊断信息。 |
|
||||
| `providerAuthEnvVars` | 否 | `Record<string, string[]>` | 已弃用的兼容性环境变量元数据,用于 provider 认证/Status 查询。对于新插件,优先使用 `setup.providers[].envVars`;在弃用窗口期间,OpenClaw 仍会读取此字段。 |
|
||||
| `providerAuthAliases` | 否 | `Record<string, string>` | 应复用另一个 provider id 进行认证查询的 provider id,例如共享基础 provider API key 和认证配置文件的编码 provider。 |
|
||||
| `channelEnvVars` | 否 | `Record<string, string[]>` | OpenClaw 可在不加载插件代码的情况下检查的轻量级渠道环境变量元数据。将其用于通用启动/配置辅助工具需要识别的、由环境变量驱动的渠道设置或认证界面。 |
|
||||
| `providerAuthChoices` | 否 | `object[]` | 面向新手引导选择器、首选 provider 解析和简单 CLI 标志接线的轻量级认证选项元数据。 |
|
||||
| `activation` | 否 | `object` | 面向 provider、命令、渠道、路由和能力触发加载的轻量级激活规划器元数据。仅为元数据;实际行为仍由插件运行时拥有。 |
|
||||
| `setup` | 否 | `object` | 轻量级设置/新手引导描述符,供发现和设置界面在不加载插件运行时的情况下检查。 |
|
||||
| `qaRunners` | 否 | `object[]` | 在插件运行时加载前,由共享 `openclaw qa` 主机使用的轻量级 QA 运行器描述符。 |
|
||||
| `contracts` | 否 | `object` | 外部认证 hooks、语音、实时转写、实时语音、媒体理解、图像生成、音乐生成、视频生成、网页抓取、网页搜索和工具归属的静态内置能力快照。 |
|
||||
| `mediaUnderstandingProviderMetadata` | 否 | `Record<string, object>` | 为 `contracts.mediaUnderstandingProviders` 中声明的 provider id 提供的轻量级媒体理解默认值。 |
|
||||
| `channelConfigs` | 否 | `Record<string, object>` | 由清单拥有的渠道配置元数据,在运行时加载前合并到发现和校验界面中。 |
|
||||
| `skills` | 否 | `string[]` | 要加载的 Skills 目录,相对于插件根目录。 |
|
||||
| `name` | 否 | `string` | 人类可读的插件名称。 |
|
||||
| `description` | 否 | `string` | 显示在插件界面中的简短摘要。 |
|
||||
@ -163,32 +163,32 @@ OpenClaw 也会自动检测这些 bundle 布局,但它们不会按照此处描
|
||||
|
||||
## `providerAuthChoices` 参考
|
||||
|
||||
每个 `providerAuthChoices` 条目描述一个 onboarding 或凭证选项。
|
||||
每个 `providerAuthChoices` 条目都描述一个新手引导或认证选项。
|
||||
OpenClaw 会在 provider 运行时加载前读取它。
|
||||
Provider 设置列表会使用这些清单选项、从描述符派生的设置选项,以及安装目录元数据,而无需加载 provider 运行时。
|
||||
provider 设置列表会使用这些清单选项、从描述符派生的设置选项,以及安装目录元数据,而无需加载 provider 运行时。
|
||||
|
||||
| 字段 | 必填 | 类型 | 含义 |
|
||||
| --------------------- | -------- | ----------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
|
||||
| `provider` | 是 | `string` | 此选项所属的 provider id。 |
|
||||
| `method` | 是 | `string` | 要分发到的凭证方法 id。 |
|
||||
| `choiceId` | 是 | `string` | onboarding 和 CLI 流程中使用的稳定凭证选项 id。 |
|
||||
| `choiceLabel` | 否 | `string` | 面向用户的标签。如果省略,OpenClaw 会回退到 `choiceId`。 |
|
||||
| `choiceHint` | 否 | `string` | 选择器的简短辅助文本。 |
|
||||
| `assistantPriority` | 否 | `number` | 在由助手驱动的交互式选择器中,值越小排序越靠前。 |
|
||||
| `assistantVisibility` | 否 | `"visible"` \| `"manual-only"` | 在助手选择器中隐藏该选项,同时仍允许手动通过 CLI 选择。 |
|
||||
| `method` | 是 | `string` | 要分派到的认证方法 id。 |
|
||||
| `choiceId` | 是 | `string` | 供新手引导和 CLI 流程使用的稳定认证选项 id。 |
|
||||
| `choiceLabel` | 否 | `string` | 面向用户的标签。如省略,OpenClaw 会回退到 `choiceId`。 |
|
||||
| `choiceHint` | 否 | `string` | 选择器中显示的简短帮助文本。 |
|
||||
| `assistantPriority` | 否 | `number` | 在由助手驱动的交互式选择器中,数值越小排序越靠前。 |
|
||||
| `assistantVisibility` | 否 | `"visible"` \| `"manual-only"` | 在助手选择器中隐藏此选项,但仍允许手动通过 CLI 选择。 |
|
||||
| `deprecatedChoiceIds` | 否 | `string[]` | 应将用户重定向到此替代选项的旧版选项 id。 |
|
||||
| `groupId` | 否 | `string` | 用于对相关选项分组的可选组 id。 |
|
||||
| `groupId` | 否 | `string` | 用于对相关选项分组的可选分组 id。 |
|
||||
| `groupLabel` | 否 | `string` | 该分组面向用户的标签。 |
|
||||
| `groupHint` | 否 | `string` | 该分组的简短辅助文本。 |
|
||||
| `optionKey` | 否 | `string` | 用于简单单 flag 凭证流程的内部选项键。 |
|
||||
| `cliFlag` | 否 | `string` | CLI flag 名称,例如 `--openrouter-api-key`。 |
|
||||
| `groupHint` | 否 | `string` | 该分组的简短帮助文本。 |
|
||||
| `optionKey` | 否 | `string` | 用于简单单标志认证流程的内部选项键。 |
|
||||
| `cliFlag` | 否 | `string` | CLI 标志名称,例如 `--openrouter-api-key`。 |
|
||||
| `cliOption` | 否 | `string` | 完整的 CLI 选项形式,例如 `--openrouter-api-key <key>`。 |
|
||||
| `cliDescription` | 否 | `string` | CLI 帮助中使用的说明。 |
|
||||
| `onboardingScopes` | 否 | `Array<"text-inference" \| "image-generation">` | 此选项应出现在哪些 onboarding 界面中。如果省略,默认值为 `["text-inference"]`。 |
|
||||
| `cliDescription` | 否 | `string` | 用于 CLI 帮助中的说明。 |
|
||||
| `onboardingScopes` | 否 | `Array<"text-inference" \| "image-generation">` | 此选项应出现在哪些新手引导界面中。如省略,默认值为 `["text-inference"]`。 |
|
||||
|
||||
## `commandAliases` 参考
|
||||
|
||||
当插件拥有一个运行时命令名称,而用户可能会错误地将其放入 `plugins.allow`,或尝试将其作为根 CLI 命令运行时,请使用 `commandAliases`。OpenClaw 使用此元数据在不导入插件运行时代码的情况下提供诊断信息。
|
||||
当插件拥有一个运行时命令名称,而用户可能会误将其放入 `plugins.allow`,或尝试将其作为根 CLI 命令运行时,请使用 `commandAliases`。OpenClaw 使用此元数据在不导入插件运行时代码的情况下提供诊断信息。
|
||||
|
||||
```json
|
||||
{
|
||||
@ -205,18 +205,18 @@ Provider 设置列表会使用这些清单选项、从描述符派生的设置
|
||||
| 字段 | 必填 | 类型 | 含义 |
|
||||
| ------------ | -------- | ----------------- | ----------------------------------------------------------------------- |
|
||||
| `name` | 是 | `string` | 属于此插件的命令名称。 |
|
||||
| `kind` | 否 | `"runtime-slash"` | 将该别名标记为聊天 slash 命令,而不是根 CLI 命令。 |
|
||||
| `cliCommand` | 否 | `string` | 若存在,用于建议 CLI 操作的相关根 CLI 命令。 |
|
||||
| `kind` | 否 | `"runtime-slash"` | 将该别名标记为聊天斜杠命令,而不是根 CLI 命令。 |
|
||||
| `cliCommand` | 否 | `string` | 若存在,用于 CLI 操作时建议的相关根 CLI 命令。 |
|
||||
|
||||
## `activation` 参考
|
||||
|
||||
当插件可以低成本声明哪些控制平面事件应将其纳入激活/加载计划时,请使用 `activation`。
|
||||
当插件可以低成本地声明哪些控制平面事件应将其包含到激活/加载计划中时,请使用 `activation`。
|
||||
|
||||
此代码块是规划器元数据,不是生命周期 API。它不会注册运行时行为,不会替代 `register(...)`,也不保证插件代码已经执行。激活规划器使用这些字段来缩小候选插件范围,然后再回退到现有的清单归属元数据,例如 `providers`、`channels`、`commandAliases`、`setup.providers`、`contracts.tools` 和 hooks。
|
||||
此块是规划器元数据,而不是生命周期 API。它不会注册运行时行为,不会替代 `register(...)`,也不保证插件代码已经执行。激活规划器使用这些字段在回退到现有清单归属元数据(如 `providers`、`channels`、`commandAliases`、`setup.providers`、`contracts.tools` 和 hooks)之前缩小候选插件范围。
|
||||
|
||||
优先使用已经能描述归属关系的最窄元数据。当这些字段能够表达该关系时,请使用 `providers`、`channels`、`commandAliases`、setup 描述符或 `contracts`。只有在这些归属字段无法表示额外规划提示时,才使用 `activation`。
|
||||
优先使用已经描述归属关系的最窄元数据。当 `providers`、`channels`、`commandAliases`、设置描述符或 `contracts` 已能表达这种关系时,请使用这些字段。对于无法通过这些归属字段表示的额外规划器提示,再使用 `activation`。
|
||||
|
||||
此代码块仅是元数据。它不会注册运行时行为,也不会替代 `register(...)`、`setupEntry` 或其他运行时/插件入口点。当前使用方会在更广泛的插件加载之前将其作为缩小范围的提示,因此缺失激活元数据通常只会带来性能成本;在旧版清单归属回退仍然存在时,它不应改变正确性。
|
||||
此块仅为元数据。它不会注册运行时行为,也不会替代 `register(...)`、`setupEntry` 或其他运行时/插件入口点。当前使用方会在更广泛的插件加载前将其作为缩小范围的提示,因此缺少激活元数据通常只会带来性能成本;在旧版清单归属回退仍存在时,不应影响正确性。
|
||||
|
||||
```json
|
||||
{
|
||||
@ -232,27 +232,27 @@ Provider 设置列表会使用这些清单选项、从描述符派生的设置
|
||||
|
||||
| 字段 | 必填 | 类型 | 含义 |
|
||||
| ---------------- | -------- | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
|
||||
| `onProviders` | 否 | `string[]` | 应将此插件纳入激活/加载计划的 provider id。 |
|
||||
| `onCommands` | 否 | `string[]` | 应将此插件纳入激活/加载计划的命令 id。 |
|
||||
| `onChannels` | 否 | `string[]` | 应将此插件纳入激活/加载计划的渠道 id。 |
|
||||
| `onRoutes` | 否 | `string[]` | 应将此插件纳入激活/加载计划的路由类型。 |
|
||||
| `onCapabilities` | 否 | `Array<"provider" \| "channel" \| "tool" \| "hook">` | 控制平面激活规划使用的宽泛能力提示。可能时优先使用更窄的字段。 |
|
||||
| `onProviders` | 否 | `string[]` | 应将此插件包含到激活/加载计划中的 provider id。 |
|
||||
| `onCommands` | 否 | `string[]` | 应将此插件包含到激活/加载计划中的命令 id。 |
|
||||
| `onChannels` | 否 | `string[]` | 应将此插件包含到激活/加载计划中的渠道 id。 |
|
||||
| `onRoutes` | 否 | `string[]` | 应将此插件包含到激活/加载计划中的路由类型。 |
|
||||
| `onCapabilities` | 否 | `Array<"provider" \| "channel" \| "tool" \| "hook">` | 控制平面激活规划中使用的宽泛能力提示。若可能,优先使用更窄的字段。 |
|
||||
|
||||
当前在线使用方:
|
||||
|
||||
- 由命令触发的 CLI 规划会回退到旧版
|
||||
`commandAliases[].cliCommand` 或 `commandAliases[].name`
|
||||
- 当缺少显式渠道激活元数据时,由渠道触发的设置/渠道规划会回退到旧版 `channels[]`
|
||||
归属
|
||||
- 当缺少显式 provider
|
||||
激活元数据时,由 provider 触发的设置/运行时规划会回退到旧版
|
||||
`providers[]` 和顶层 `cliBackends[]` 归属
|
||||
- 由渠道触发的设置/渠道规划在缺少显式渠道激活元数据时,会回退到旧版 `channels[]`
|
||||
归属关系
|
||||
- 由 provider 触发的设置/运行时规划在缺少显式 provider
|
||||
激活元数据时,会回退到旧版 `providers[]` 和顶层 `cliBackends[]`
|
||||
归属关系
|
||||
|
||||
规划器诊断可以区分显式激活提示和清单归属回退。例如,`activation-command-hint` 表示匹配了 `activation.onCommands`,而 `manifest-command-alias` 表示规划器改用了 `commandAliases` 归属。这些原因标签用于宿主诊断和测试;插件作者应继续声明最能描述归属关系的元数据。
|
||||
规划器诊断可以区分显式激活提示和清单归属回退。例如,`activation-command-hint` 表示匹配了 `activation.onCommands`,而 `manifest-command-alias` 表示规划器改用了 `commandAliases` 归属关系。这些原因标签用于宿主诊断和测试;插件作者应继续声明最能描述归属关系的元数据。
|
||||
|
||||
## `qaRunners` 参考
|
||||
|
||||
当插件在共享的 `openclaw qa` 根命令下提供一个或多个传输运行器时,请使用 `qaRunners`。保持此元数据轻量且静态;插件运行时仍通过导出 `qaRunnerCliRegistrations` 的轻量级 `runtime-api.ts` 界面拥有实际 CLI 注册逻辑。
|
||||
当插件在共享 `openclaw qa` 根命令下贡献一个或多个传输运行器时,请使用 `qaRunners`。保持此元数据轻量且静态;实际 CLI 注册仍由插件运行时通过一个轻量级的 `runtime-api.ts` 接口负责,该接口导出 `qaRunnerCliRegistrations`。
|
||||
|
||||
```json
|
||||
{
|
||||
@ -268,11 +268,11 @@ Provider 设置列表会使用这些清单选项、从描述符派生的设置
|
||||
| 字段 | 必填 | 类型 | 含义 |
|
||||
| ------------- | -------- | -------- | ------------------------------------------------------------------ |
|
||||
| `commandName` | 是 | `string` | 挂载在 `openclaw qa` 下的子命令,例如 `matrix`。 |
|
||||
| `description` | 否 | `string` | 当共享宿主需要一个占位命令时使用的回退帮助文本。 |
|
||||
| `description` | 否 | `string` | 当共享宿主需要一个存根命令时使用的回退帮助文本。 |
|
||||
|
||||
## `setup` 参考
|
||||
|
||||
当设置和 onboarding 界面在运行时加载前需要轻量的、由插件拥有的元数据时,请使用 `setup`。
|
||||
当设置和新手引导界面需要在运行时加载前获取由插件拥有的轻量级元数据时,请使用 `setup`。
|
||||
|
||||
```json
|
||||
{
|
||||
@ -291,17 +291,17 @@ Provider 设置列表会使用这些清单选项、从描述符派生的设置
|
||||
}
|
||||
```
|
||||
|
||||
顶层 `cliBackends` 仍然有效,并继续描述 CLI 推理后端。`setup.cliBackends` 是面向控制平面/设置流程的设置专用描述符界面,应保持为仅元数据。
|
||||
顶层 `cliBackends` 仍然有效,并继续描述 CLI 推理后端。`setup.cliBackends` 是用于控制平面/设置流程的、仅元数据的设置专用描述符界面。
|
||||
|
||||
存在时,`setup.providers` 和 `setup.cliBackends` 是设置发现的首选“描述符优先”查询界面。如果描述符仅用于缩小候选插件范围,而设置仍需要更丰富的设置期运行时 hooks,请设置 `requiresRuntime: true`,并保留 `setup-api` 作为回退执行路径。
|
||||
存在时,`setup.providers` 和 `setup.cliBackends` 是设置发现中首选的描述符优先查询界面。如果描述符仅用于缩小候选插件范围,而设置仍需要更丰富的设置期运行时 hooks,请设置 `requiresRuntime: true`,并保留 `setup-api` 作为回退执行路径。
|
||||
|
||||
OpenClaw 还会将 `setup.providers[].envVars` 纳入通用 provider 凭证和环境变量查询。`providerAuthEnvVars` 在弃用窗口期内仍通过兼容适配器受到支持,但仍在使用它的非内置插件会收到清单诊断。新插件应将设置/Status 环境变量元数据放在 `setup.providers[].envVars` 上。
|
||||
OpenClaw 还会将 `setup.providers[].envVars` 纳入通用 provider 认证和环境变量查询。`providerAuthEnvVars` 在弃用窗口期间仍通过兼容适配器受支持,但仍在使用它的非内置插件会收到清单诊断。新插件应将设置/Status 环境变量元数据放在 `setup.providers[].envVars` 上。
|
||||
|
||||
当没有可用的 setup 条目时,或者当 `setup.requiresRuntime: false` 声明不需要设置运行时时,OpenClaw 也可以根据 `setup.providers[].authMethods` 推导简单的设置选项。对于自定义标签、CLI flags、onboarding 范围和助手元数据,显式的 `providerAuthChoices` 条目仍然是首选。
|
||||
当没有可用的设置入口,或 `setup.requiresRuntime: false` 声明设置运行时并非必需时,OpenClaw 还可以根据 `setup.providers[].authMethods` 派生简单的设置选项。对于自定义标签、CLI 标志、新手引导范围和助手元数据,显式的 `providerAuthChoices` 条目仍是首选。
|
||||
|
||||
只有当这些描述符足以支持设置界面时,才设置 `requiresRuntime: false`。OpenClaw 会将显式 `false` 视为仅描述符契约,并且不会为设置查询执行 `setup-api` 或 `openclaw.setupEntry`。如果一个仅描述符插件仍提供了这些设置运行时入口之一,OpenClaw 会报告一条附加诊断并继续忽略它。省略 `requiresRuntime` 会保留旧版回退行为,以确保那些添加了描述符但未添加该标志的现有插件不会出错。
|
||||
只有当这些描述符足以支撑设置界面时,才将 `requiresRuntime: false` 设为 `false`。OpenClaw 将显式 `false` 视为仅描述符契约,并且不会为设置查询执行 `setup-api` 或 `openclaw.setupEntry`。如果一个仅描述符插件仍提供了这些设置运行时入口之一,OpenClaw 会报告一条附加诊断,并继续忽略它。省略 `requiresRuntime` 会保留旧版回退行为,以免那些添加了描述符但未设置该标志的现有插件发生中断。
|
||||
|
||||
由于设置查询可能会执行由插件拥有的 `setup-api` 代码,因此归一化后的 `setup.providers[].id` 和 `setup.cliBackends[]` 值在已发现插件之间必须保持唯一。归属不明确时会采用失败关闭,而不是按照发现顺序挑选一个胜出者。
|
||||
由于设置查询可能会执行由插件拥有的 `setup-api` 代码,归一化后的 `setup.providers[].id` 和 `setup.cliBackends[]` 值在已发现插件之间必须保持唯一。归属关系不明确时会采用失败关闭,而不是根据发现顺序选择一个赢家。
|
||||
|
||||
当设置运行时确实执行时,如果 `setup-api` 注册了清单描述符未声明的 provider 或 CLI 后端,或者某个描述符没有匹配的运行时注册,设置注册表诊断会报告描述符漂移。这些诊断是附加性的,不会拒绝旧版插件。
|
||||
|
||||
@ -309,22 +309,22 @@ OpenClaw 还会将 `setup.providers[].envVars` 纳入通用 provider 凭证和
|
||||
|
||||
| 字段 | 必填 | 类型 | 含义 |
|
||||
| ------------- | -------- | ---------- | ------------------------------------------------------------------------------------ |
|
||||
| `id` | 是 | `string` | 在设置或 onboarding 期间公开的 provider id。请保持归一化后的 id 在全局唯一。 |
|
||||
| `authMethods` | 否 | `string[]` | 该 provider 在不加载完整运行时的情况下支持的设置/凭证方法 id。 |
|
||||
| `id` | 是 | `string` | 在设置或新手引导期间公开的 provider id。保持归一化 id 在全局范围内唯一。 |
|
||||
| `authMethods` | 否 | `string[]` | 此 provider 在不加载完整运行时的情况下支持的设置/认证方法 id。 |
|
||||
| `envVars` | 否 | `string[]` | 通用设置/Status 界面可在插件运行时加载前检查的环境变量。 |
|
||||
|
||||
### `setup` 字段
|
||||
|
||||
| 字段 | 必填 | 类型 | 含义 |
|
||||
| ------------------ | -------- | ---------- | --------------------------------------------------------------------------------------------------- |
|
||||
| `providers` | 否 | `object[]` | 在设置和 onboarding 期间公开的 provider 设置描述符。 |
|
||||
| `cliBackends` | 否 | `string[]` | 用于描述符优先设置查询的设置期后端 id。请保持归一化后的 id 在全局唯一。 |
|
||||
| `providers` | 否 | `object[]` | 在设置和新手引导期间公开的 provider 设置描述符。 |
|
||||
| `cliBackends` | 否 | `string[]` | 用于描述符优先设置查询的设置期后端 id。保持归一化 id 在全局范围内唯一。 |
|
||||
| `configMigrations` | 否 | `string[]` | 由此插件设置界面拥有的配置迁移 id。 |
|
||||
| `requiresRuntime` | 否 | `boolean` | 在描述符查询之后,设置是否仍需要执行 `setup-api`。 |
|
||||
|
||||
## `uiHints` 参考
|
||||
|
||||
`uiHints` 是一个从配置字段名称到小型渲染提示的映射。
|
||||
`uiHints` 是一个从配置字段名映射到小型渲染提示的映射表。
|
||||
|
||||
```json
|
||||
{
|
||||
@ -339,20 +339,20 @@ OpenClaw 还会将 `setup.providers[].envVars` 纳入通用 provider 凭证和
|
||||
}
|
||||
```
|
||||
|
||||
每个字段提示可以包含:
|
||||
每个字段提示可包含:
|
||||
|
||||
| 字段 | 类型 | 含义 |
|
||||
| ------------- | ---------- | --------------------------------------- |
|
||||
| `label` | `string` | 面向用户的字段标签。 |
|
||||
| `help` | `string` | 简短辅助文本。 |
|
||||
| `help` | `string` | 简短帮助文本。 |
|
||||
| `tags` | `string[]` | 可选的 UI 标签。 |
|
||||
| `advanced` | `boolean` | 将该字段标记为高级项。 |
|
||||
| `advanced` | `boolean` | 将该字段标记为高级选项。 |
|
||||
| `sensitive` | `boolean` | 将该字段标记为机密或敏感。 |
|
||||
| `placeholder` | `string` | 表单输入的占位文本。 |
|
||||
|
||||
## `contracts` 参考
|
||||
|
||||
仅当 OpenClaw 可以在不导入插件运行时的情况下读取静态能力归属元数据时,才使用 `contracts`。
|
||||
仅当需要 OpenClaw 在不导入插件运行时的情况下读取静态能力归属元数据时,才使用 `contracts`。
|
||||
|
||||
```json
|
||||
{
|
||||
@ -379,27 +379,27 @@ OpenClaw 还会将 `setup.providers[].envVars` 纳入通用 provider 凭证和
|
||||
| -------------------------------- | ---------- | --------------------------------------------------------------------- |
|
||||
| `embeddedExtensionFactories` | `string[]` | Codex app-server 扩展工厂 id,目前为 `codex-app-server`。 |
|
||||
| `agentToolResultMiddleware` | `string[]` | 内置插件可为其注册工具结果中间件的运行时 id。 |
|
||||
| `externalAuthProviders` | `string[]` | 此插件拥有其外部凭证配置文件 hook 的 provider id。 |
|
||||
| `speechProviders` | `string[]` | 此插件拥有的 speech provider id。 |
|
||||
| `realtimeTranscriptionProviders` | `string[]` | 此插件拥有的 realtime-transcription provider id。 |
|
||||
| `realtimeVoiceProviders` | `string[]` | 此插件拥有的 realtime-voice provider id。 |
|
||||
| `memoryEmbeddingProviders` | `string[]` | 此插件拥有的 Memory embedding provider id。 |
|
||||
| `mediaUnderstandingProviders` | `string[]` | 此插件拥有的 media-understanding provider id。 |
|
||||
| `imageGenerationProviders` | `string[]` | 此插件拥有的 image-generation provider id。 |
|
||||
| `videoGenerationProviders` | `string[]` | 此插件拥有的 video-generation provider id。 |
|
||||
| `webFetchProviders` | `string[]` | 此插件拥有的 web-fetch provider id。 |
|
||||
| `webSearchProviders` | `string[]` | 此插件拥有的 web search provider id。 |
|
||||
| `tools` | `string[]` | 此插件拥有的 Agent 工具名称,用于内置契约检查。 |
|
||||
| `externalAuthProviders` | `string[]` | 此插件拥有其外部认证配置文件 hook 的 provider id。 |
|
||||
| `speechProviders` | `string[]` | 此插件拥有的语音 provider id。 |
|
||||
| `realtimeTranscriptionProviders` | `string[]` | 此插件拥有的实时转写 provider id。 |
|
||||
| `realtimeVoiceProviders` | `string[]` | 此插件拥有的实时语音 provider id。 |
|
||||
| `memoryEmbeddingProviders` | `string[]` | 此插件拥有的 Memory 嵌入 provider id。 |
|
||||
| `mediaUnderstandingProviders` | `string[]` | 此插件拥有的媒体理解 provider id。 |
|
||||
| `imageGenerationProviders` | `string[]` | 此插件拥有的图像生成 provider id。 |
|
||||
| `videoGenerationProviders` | `string[]` | 此插件拥有的视频生成 provider id。 |
|
||||
| `webFetchProviders` | `string[]` | 此插件拥有的网页抓取 provider id。 |
|
||||
| `webSearchProviders` | `string[]` | 此插件拥有的网页搜索 provider id。 |
|
||||
| `tools` | `string[]` | 此插件为内置契约检查所拥有的智能体工具名称。 |
|
||||
|
||||
`contracts.embeddedExtensionFactories` 保留用于内置的、仅限 Codex app-server 的扩展工厂。内置工具结果转换应声明 `contracts.agentToolResultMiddleware`,并改为使用 `api.registerAgentToolResultMiddleware(...)` 注册。外部插件不能注册工具结果中间件,因为该接口可以在模型看到高信任工具输出之前重写它。
|
||||
`contracts.embeddedExtensionFactories` 保留给仅用于内置 Codex app-server 的扩展工厂。内置工具结果转换应声明 `contracts.agentToolResultMiddleware`,并通过 `api.registerAgentToolResultMiddleware(...)` 进行注册。外部插件不能注册工具结果中间件,因为该接口可以在模型看到输出前重写高信任度的工具输出。
|
||||
|
||||
实现了 `resolveExternalAuthProfiles` 的 provider 插件应声明 `contracts.externalAuthProviders`。未声明该字段的插件仍会通过一个已弃用的兼容性回退路径运行,但该回退路径更慢,并将在迁移窗口结束后移除。
|
||||
实现 `resolveExternalAuthProfiles` 的 provider 插件应声明 `contracts.externalAuthProviders`。未声明该字段的插件仍会通过一个已弃用的兼容性回退路径运行,但该回退更慢,并将在迁移窗口结束后移除。
|
||||
|
||||
内置的 Memory embedding providers 应为其公开的每个适配器 id 声明 `contracts.memoryEmbeddingProviders`,包括诸如 `local` 之类的内置适配器。独立 CLI 路径使用此清单契约在完整 Gateway 网关运行时注册 providers 之前,仅加载所属插件。
|
||||
内置 Memory 嵌入 provider 应为其公开的每个适配器 id 声明 `contracts.memoryEmbeddingProviders`,包括诸如 `local` 之类的内置适配器。独立 CLI 路径使用此清单契约在完整 Gateway 网关运行时注册 provider 之前,仅加载其所属插件。
|
||||
|
||||
## `mediaUnderstandingProviderMetadata` 参考
|
||||
|
||||
当某个 media-understanding provider 具有默认模型、自动凭证回退优先级或原生文档支持,而通用核心辅助工具需要在运行时加载前知道这些信息时,请使用 `mediaUnderstandingProviderMetadata`。键还必须在 `contracts.mediaUnderstandingProviders` 中声明。
|
||||
当媒体理解 provider 具有默认模型、自动认证回退优先级,或 generic core helpers 在运行时加载前需要的原生文档支持时,请使用 `mediaUnderstandingProviderMetadata`。其中的键也必须在 `contracts.mediaUnderstandingProviders` 中声明。
|
||||
|
||||
```json
|
||||
{
|
||||
@ -422,27 +422,29 @@ OpenClaw 还会将 `setup.providers[].envVars` 纳入通用 provider 凭证和
|
||||
}
|
||||
```
|
||||
|
||||
每个 provider 条目可以包含:
|
||||
每个 provider 条目可包含:
|
||||
|
||||
| 字段 | 类型 | 含义 |
|
||||
| ---------------------- | ----------------------------------- | ---------------------------------------------------------------------------- |
|
||||
| `capabilities` | `("image" \| "audio" \| "video")[]` | 该 provider 公开的媒体能力。 |
|
||||
| `defaultModels` | `Record<string, string>` | 当配置未指定模型时使用的“能力到模型”默认值。 |
|
||||
| `autoPriority` | `Record<string, number>` | 用于基于凭证自动回退 provider 时的优先级,数字越小排序越靠前。 |
|
||||
| `capabilities` | `("image" \| "audio" \| "video")[]` | 此 provider 公开的媒体能力。 |
|
||||
| `defaultModels` | `Record<string, string>` | 当配置未指定模型时使用的能力到模型默认值映射。 |
|
||||
| `autoPriority` | `Record<string, number>` | 基于凭证的自动 provider 回退中,数值越小排序越靠前。 |
|
||||
| `nativeDocumentInputs` | `"pdf"[]` | 该 provider 支持的原生文档输入。 |
|
||||
|
||||
## `channelConfigs` 参考
|
||||
|
||||
当渠道插件在运行时加载前需要轻量配置元数据时,请使用 `channelConfigs`。当没有可用的 setup 条目,或 `setup.requiresRuntime: false` 声明不需要设置运行时时,只读的渠道设置/Status 发现可以直接使用此元数据来处理已配置的外部渠道。
|
||||
当渠道插件需要在运行时加载前获取轻量级配置元数据时,请使用 `channelConfigs`。当没有可用的设置入口,或 `setup.requiresRuntime: false` 声明设置运行时并非必需时,只读渠道设置/Status 发现可以直接使用这些元数据来处理已配置的外部渠道。
|
||||
|
||||
`channelConfigs` 是插件清单元数据,不是新的顶层用户配置部分。用户仍然在 `channels.<channel-id>` 下配置渠道实例。OpenClaw 会读取清单元数据,以便在插件运行时代码执行前确定哪个插件拥有该已配置渠道。
|
||||
`channelConfigs` 是插件清单元数据,而不是新的顶层用户配置区段。用户仍然在 `channels.<channel-id>` 下配置渠道实例。OpenClaw 会读取清单元数据,以在插件运行时代码执行前判断哪个插件拥有该已配置渠道。
|
||||
|
||||
对于渠道插件,`configSchema` 和 `channelConfigs` 描述的是不同路径:
|
||||
|
||||
- `configSchema` 校验 `plugins.entries.<plugin-id>.config`
|
||||
- `channelConfigs.<channel-id>.schema` 校验 `channels.<channel-id>`
|
||||
|
||||
声明了 `channels[]` 的非内置插件也应声明匹配的 `channelConfigs` 条目。若缺少这些条目,OpenClaw 仍可加载该插件,但冷路径配置 schema、设置和控制 UI 界面在插件运行时执行之前将无法知道该渠道拥有的选项结构。
|
||||
声明了 `channels[]` 的非内置插件也应声明匹配的 `channelConfigs` 条目。若缺少这些条目,OpenClaw 仍可加载插件,但冷路径配置 schema、设置以及 Control UI 界面在插件运行时执行前将无法知道该渠道拥有的选项结构。
|
||||
|
||||
`channelConfigs.<channel-id>.commands.nativeCommandsAutoEnabled` 和 `nativeSkillsAutoEnabled` 可以为运行时加载前执行的命令配置检查声明静态 `auto` 默认值。内置渠道也可以通过 `package.json#openclaw.channel.commands` 连同其其他由包拥有的渠道目录元数据一起发布相同的默认值。
|
||||
|
||||
```json
|
||||
{
|
||||
@ -463,25 +465,30 @@ OpenClaw 还会将 `setup.providers[].envVars` 纳入通用 provider 凭证和
|
||||
},
|
||||
"label": "Matrix",
|
||||
"description": "Matrix homeserver connection",
|
||||
"commands": {
|
||||
"nativeCommandsAutoEnabled": true,
|
||||
"nativeSkillsAutoEnabled": true
|
||||
},
|
||||
"preferOver": ["matrix-legacy"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
每个渠道条目可以包含:
|
||||
每个渠道条目可包含:
|
||||
|
||||
| 字段 | 类型 | 含义 |
|
||||
| ------------- | ------------------------ | ----------------------------------------------------------------------------------------- |
|
||||
| `schema` | `object` | `channels.<id>` 的 JSON Schema。每个已声明的渠道配置条目都必须提供。 |
|
||||
| `uiHints` | `Record<string, object>` | 该渠道配置部分可选的 UI 标签/占位符/敏感性提示。 |
|
||||
| `label` | `string` | 当运行时元数据尚未准备好时,合并到选择器和检查界面中的渠道标签。 |
|
||||
| `description` | `string` | 用于检查和目录界面的简短渠道描述。 |
|
||||
| `preferOver` | `string[]` | 在选择界面中,此渠道应优先于的旧版或较低优先级插件 id。 |
|
||||
| `uiHints` | `Record<string, object>` | 该渠道配置区段的可选 UI 标签/占位符/敏感性提示。 |
|
||||
| `label` | `string` | 当运行时元数据尚未就绪时,合并到选择器和检查界面中的渠道标签。 |
|
||||
| `description` | `string` | 用于检查和目录界面的简短渠道说明。 |
|
||||
| `commands` | `object` | 用于运行时前配置检查的静态原生命令和原生 Skills 自动默认值。 |
|
||||
| `preferOver` | `string[]` | 此渠道在选择界面中应优先于的旧版或较低优先级插件 id。 |
|
||||
|
||||
### 替换另一个渠道插件
|
||||
|
||||
当你的插件是某个渠道 id 的首选拥有者,而另一个插件也可以提供该渠道时,请使用 `preferOver`。常见情况包括重命名后的插件 id、取代内置插件的独立插件,或为了配置兼容性而保留相同渠道 id 的维护分支。
|
||||
当你的插件是某个渠道 id 的首选拥有者,而另一个插件也能提供该渠道时,请使用 `preferOver`。常见情况包括插件 id 已重命名、独立插件取代内置插件,或为保持配置兼容性而沿用相同渠道 id 的维护分支。
|
||||
|
||||
```json
|
||||
{
|
||||
@ -502,13 +509,13 @@ OpenClaw 还会将 `setup.providers[].envVars` 纳入通用 provider 凭证和
|
||||
}
|
||||
```
|
||||
|
||||
当配置了 `channels.chat` 时,OpenClaw 会同时考虑渠道 id 和首选插件 id。如果较低优先级的插件之所以被选中只是因为它是内置的或默认启用的,OpenClaw 会在生效的运行时配置中禁用它,以便只有一个插件拥有该渠道及其工具。显式的用户选择仍然优先:如果用户显式启用了两个插件,OpenClaw 会保留该选择,并报告重复渠道/工具诊断,而不是静默更改请求的插件集合。
|
||||
当配置了 `channels.chat` 时,OpenClaw 会同时考虑渠道 id 和首选插件 id。如果较低优先级的插件之所以被选中,仅仅是因为它是内置插件或默认启用,OpenClaw 会在生效的运行时配置中禁用它,以便由单个插件拥有该渠道及其工具。显式的用户选择仍然优先:如果用户明确启用了这两个插件,OpenClaw 会保留该选择,并报告重复渠道/工具诊断,而不是静默更改请求的插件集合。
|
||||
|
||||
请将 `preferOver` 限定为那些确实可以提供同一渠道的插件 id。它不是通用优先级字段,也不会重命名用户配置键。
|
||||
将 `preferOver` 的范围限定为确实能够提供同一渠道的插件 id。它不是通用优先级字段,也不会重命名用户配置键。
|
||||
|
||||
## `modelSupport` 参考
|
||||
|
||||
当 OpenClaw 应在插件运行时加载前,根据 `gpt-5.5` 或 `claude-sonnet-4.6` 之类的简写模型 id 推断你的 provider 插件时,请使用 `modelSupport`。
|
||||
当 OpenClaw 应在插件运行时加载前,根据诸如 `gpt-5.5` 或 `claude-sonnet-4.6` 这样的简写模型 id 推断你的 provider 插件时,请使用 `modelSupport`。
|
||||
|
||||
```json
|
||||
{
|
||||
@ -519,23 +526,23 @@ OpenClaw 还会将 `setup.providers[].envVars` 纳入通用 provider 凭证和
|
||||
}
|
||||
```
|
||||
|
||||
OpenClaw 按以下优先级应用:
|
||||
OpenClaw 应用以下优先级:
|
||||
|
||||
- 显式 `provider/model` 引用使用所属 `providers` 清单元数据
|
||||
- `modelPatterns` 优先于 `modelPrefixes`
|
||||
- 如果一个非内置插件和一个内置插件同时匹配,则非内置插件胜出
|
||||
- 剩余的歧义会被忽略,直到用户或配置指定一个 provider
|
||||
- 如果一个非内置插件和一个内置插件都匹配,则非内置插件胜出
|
||||
- 剩余歧义会被忽略,直到用户或配置指定某个 provider
|
||||
|
||||
字段:
|
||||
|
||||
| 字段 | 类型 | 含义 |
|
||||
| --------------- | ---------- | ------------------------------------------------------------------------------- |
|
||||
| `modelPrefixes` | `string[]` | 使用 `startsWith` 与简写模型 id 进行匹配的前缀。 |
|
||||
| `modelPatterns` | `string[]` | 在移除 profile 后缀后,针对简写模型 id 进行匹配的正则表达式源码。 |
|
||||
| `modelPrefixes` | `string[]` | 对简写模型 id 使用 `startsWith` 进行匹配的前缀。 |
|
||||
| `modelPatterns` | `string[]` | 在移除配置文件后缀后,对简写模型 id 进行匹配的正则表达式源码。 |
|
||||
|
||||
## `modelCatalog` 参考
|
||||
|
||||
当 OpenClaw 应在加载插件运行时之前知道 provider 模型元数据时,请使用 `modelCatalog`。这是由清单拥有的固定目录行、provider 别名、抑制规则和发现模式的数据源。运行时刷新仍属于 provider 运行时代码,但清单会告知核心何时需要运行时。
|
||||
当 OpenClaw 需要在加载插件运行时之前了解 provider 模型元数据时,请使用 `modelCatalog`。这是固定目录行、provider 别名、抑制规则和发现模式的清单拥有来源。运行时刷新仍属于 provider 运行时代码,但清单会告知核心系统何时需要运行时。
|
||||
|
||||
```json
|
||||
{
|
||||
@ -588,111 +595,112 @@ OpenClaw 按以下优先级应用:
|
||||
|
||||
| 字段 | 类型 | 含义 |
|
||||
| -------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
|
||||
| `providers` | `Record<string, object>` | 由此插件拥有的 provider id 的目录条目。键也应出现在顶层 `providers` 中。 |
|
||||
| `aliases` | `Record<string, object>` | 在目录或抑制规划中应解析为所属 provider 的 provider 别名。 |
|
||||
| `suppressions` | `object[]` | 由于 provider 特定原因,被此插件从其他来源抑制的模型条目。 |
|
||||
| `discovery` | `Record<string, "static" \| "refreshable" \| "runtime">` | provider 目录是否可从清单元数据读取、刷新到缓存,或需要运行时。 |
|
||||
| `providers` | `Record<string, object>` | 由此插件拥有的 provider id 的目录行。键也应出现在顶层 `providers` 中。 |
|
||||
| `aliases` | `Record<string, object>` | 为目录或抑制规划而应解析到某个所属 provider 的 provider 别名。 |
|
||||
| `suppressions` | `object[]` | 由于特定 provider 原因而被此插件抑制的、来自其他来源的模型行。 |
|
||||
| `discovery` | `Record<string, "static" \| "refreshable" \| "runtime">` | provider 目录是否可从清单元数据读取、可刷新到缓存,或需要运行时。 |
|
||||
|
||||
Provider 字段:
|
||||
provider 字段:
|
||||
|
||||
| 字段 | 类型 | 含义 |
|
||||
| --------- | ------------------------ | ----------------------------------------------------------------- |
|
||||
| `baseUrl` | `string` | 该 provider 目录中模型的可选默认 base URL。 |
|
||||
| `api` | `ModelApi` | 该 provider 目录中模型的可选默认 API 适配器。 |
|
||||
| `headers` | `Record<string, string>` | 适用于该 provider 目录的可选静态 headers。 |
|
||||
| `models` | `object[]` | 必填的模型条目。没有 `id` 的条目会被忽略。 |
|
||||
| `baseUrl` | `string` | 此 provider 目录中模型的可选默认 base URL。 |
|
||||
| `api` | `ModelApi` | 此 provider 目录中模型的可选默认 API 适配器。 |
|
||||
| `headers` | `Record<string, string>` | 适用于此 provider 目录的可选静态 headers。 |
|
||||
| `models` | `object[]` | 必需的模型行。没有 `id` 的行会被忽略。 |
|
||||
|
||||
模型字段:
|
||||
|
||||
| 字段 | 类型 | 含义 |
|
||||
| --------------- | -------------------------------------------------------------- | --------------------------------------------------------------------------- |
|
||||
| `id` | `string` | provider 本地模型 id,不带 `provider/` 前缀。 |
|
||||
| `name` | `string` | 可选的显示名称。 |
|
||||
| `api` | `ModelApi` | 可选的每模型 API 覆盖值。 |
|
||||
| `baseUrl` | `string` | 可选的每模型 base URL 覆盖值。 |
|
||||
| `headers` | `Record<string, string>` | 可选的每模型静态 headers。 |
|
||||
| `input` | `Array<"text" \| "image" \| "document" \| "audio" \| "video">` | 模型接受的模态。 |
|
||||
| `name` | `string` | 可选显示名称。 |
|
||||
| `api` | `ModelApi` | 可选的逐模型 API 覆盖。 |
|
||||
| `baseUrl` | `string` | 可选的逐模型 base URL 覆盖。 |
|
||||
| `headers` | `Record<string, string>` | 可选的逐模型静态 headers。 |
|
||||
| `input` | `Array<"text" \| "image" \| "document" \| "audio" \| "video">` | 模型可接受的模态。 |
|
||||
| `reasoning` | `boolean` | 模型是否公开 reasoning 行为。 |
|
||||
| `contextWindow` | `number` | 原生 provider 上下文窗口。 |
|
||||
| `contextTokens` | `number` | 当与 `contextWindow` 不同时,可选的实际运行时上下文上限。 |
|
||||
| `contextWindow` | `number` | provider 原生上下文窗口。 |
|
||||
| `contextTokens` | `number` | 当与 `contextWindow` 不同时的可选有效运行时上下文上限。 |
|
||||
| `maxTokens` | `number` | 已知时的最大输出 token 数。 |
|
||||
| `cost` | `object` | 可选的每百万 token 美元定价,包括可选的 `tieredPricing`。 |
|
||||
| `compat` | `object` | 与 OpenClaw 模型配置兼容性相匹配的可选兼容性标志。 |
|
||||
| `status` | `"available"` \| `"preview"` \| `"deprecated"` \| `"disabled"` | 列表状态。仅当该条目绝对不能出现时才使用抑制。 |
|
||||
| `statusReason` | `string` | 与非可用状态一同显示的可选原因。 |
|
||||
| `compat` | `object` | 与 OpenClaw 模型配置兼容性匹配的可选兼容性标志。 |
|
||||
| `status` | `"available"` \| `"preview"` \| `"deprecated"` \| `"disabled"` | 列表状态。仅当该行完全不应出现时才使用 suppress。 |
|
||||
| `statusReason` | `string` | 与非可用状态一起显示的可选原因。 |
|
||||
| `replaces` | `string[]` | 此模型取代的较旧 provider 本地模型 id。 |
|
||||
| `replacedBy` | `string` | 已弃用条目的替代 provider 本地模型 id。 |
|
||||
| `replacedBy` | `string` | 用于已弃用行的替代 provider 本地模型 id。 |
|
||||
| `tags` | `string[]` | 供选择器和过滤器使用的稳定标签。 |
|
||||
|
||||
不要将仅运行时数据放入 `modelCatalog`。如果某个 provider 需要账户状态、API 请求或本地进程发现才能知道完整模型集,请在 `discovery` 中将该 provider 声明为 `refreshable` 或 `runtime`。
|
||||
不要将仅运行时数据放入 `modelCatalog`。如果某个 provider 需要账户状态、API 请求或本地进程发现来获知完整模型集合,请在 `discovery` 中将该 provider 声明为 `refreshable` 或 `runtime`。
|
||||
|
||||
### OpenClaw Provider Index
|
||||
|
||||
OpenClaw Provider Index 是由 OpenClaw 拥有的预览元数据,用于其插件可能尚未安装的 providers。它不是插件清单的一部分。插件清单仍然是已安装插件的权威来源。Provider Index 是未来可安装 provider 和预安装模型选择器界面在 provider 插件尚未安装时将使用的内部回退契约。
|
||||
OpenClaw Provider Index 是由 OpenClaw 拥有的预览元数据,用于其插件可能尚未安装的 provider。它不是插件清单的一部分。插件清单仍然是已安装插件的权威来源。Provider Index 是未来可安装 provider 和安装前模型选择界面在 provider 插件尚未安装时会使用的内部回退契约。
|
||||
|
||||
目录权威顺序:
|
||||
|
||||
1. 用户配置。
|
||||
2. 已安装插件清单中的 `modelCatalog`。
|
||||
3. 通过显式刷新得到的模型目录缓存。
|
||||
4. OpenClaw Provider Index 预览条目。
|
||||
3. 来自显式刷新的模型目录缓存。
|
||||
4. OpenClaw Provider Index 预览行。
|
||||
|
||||
Provider Index 不得包含机密、启用状态、运行时 hooks 或实时账户特定模型数据。它的预览目录使用与插件清单相同的 `modelCatalog` provider 条目结构,但除非像 `api`、`baseUrl`、定价或兼容性标志这类运行时适配器字段有意与已安装插件清单保持一致,否则应限制为稳定的显示元数据。具有实时 `/models` 发现能力的 providers 应通过显式模型目录缓存路径写入刷新后的条目,而不是在常规列表或 onboarding 中调用 provider API。
|
||||
Provider Index 不得包含机密、启用状态、运行时 hooks 或实时的账户专属模型数据。其预览目录使用与插件清单相同的 `modelCatalog` provider 行结构,但除非像 `api`、`baseUrl`、定价或兼容性标志等运行时适配器字段被有意与已安装插件清单保持一致,否则应仅限于稳定的显示元数据。具有实时 `/models` 发现能力的 provider 应通过显式模型目录缓存路径写入刷新后的行,而不是让常规列表或新手引导去调用 provider API。
|
||||
|
||||
Provider Index 条目还可以携带可安装插件元数据,用于那些插件已移出核心或尚未安装的 providers。此元数据遵循渠道目录模式:包名、npm 安装说明、预期完整性,以及轻量凭证选项标签,足以显示一个可安装的设置选项。一旦插件安装完成,其清单即成为优先来源,Provider Index 中该 provider 的条目会被忽略。
|
||||
Provider Index 条目也可以携带适用于其插件已移出核心或尚未安装的 provider 的可安装插件元数据。此元数据沿用渠道目录模式:包名、npm 安装规格、预期完整性以及轻量级认证选项标签,足以展示一个可安装的设置选项。一旦插件安装完成,其清单即成为权威来源,Provider Index 中该 provider 的条目将被忽略。
|
||||
|
||||
旧版顶层能力键已弃用。使用 `openclaw doctor --fix` 将 `speechProviders`、`realtimeTranscriptionProviders`、`realtimeVoiceProviders`、`mediaUnderstandingProviders`、`imageGenerationProviders`、`videoGenerationProviders`、`webFetchProviders` 和 `webSearchProviders` 移动到 `contracts` 下;常规清单加载不再将这些顶层字段视为能力归属。
|
||||
旧版顶层能力键已弃用。使用 `openclaw doctor --fix` 将 `speechProviders`、`realtimeTranscriptionProviders`、`realtimeVoiceProviders`、`mediaUnderstandingProviders`、`imageGenerationProviders`、`videoGenerationProviders`、`webFetchProviders` 和 `webSearchProviders` 移动到 `contracts` 下;常规清单加载已不再将这些顶层字段视为能力归属。
|
||||
|
||||
## 清单与 package.json 的区别
|
||||
## 清单与 `package.json` 的区别
|
||||
|
||||
这两个文件承担不同的职责:
|
||||
|
||||
| 文件 | 用途 |
|
||||
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `openclaw.plugin.json` | 发现、配置校验、凭证选项元数据,以及必须在插件代码运行前存在的 UI 提示 |
|
||||
| `package.json` | npm 元数据、依赖安装,以及 `openclaw` 代码块中用于入口点、安装门控、设置或目录元数据的内容 |
|
||||
| `openclaw.plugin.json` | 插件代码运行前必须存在的发现、配置校验、认证选项元数据和 UI 提示 |
|
||||
| `package.json` | npm 元数据、依赖安装,以及用于入口点、安装门控、设置或目录元数据的 `openclaw` 区块 |
|
||||
|
||||
如果你不确定某段元数据应放在哪里,请使用以下规则:
|
||||
如果你不确定某条元数据应放在哪里,请使用这条规则:
|
||||
|
||||
- 如果 OpenClaw 必须在加载插件代码之前知道它,就把它放在 `openclaw.plugin.json` 中
|
||||
- 如果它与打包、入口文件或 npm 安装行为有关,就把它放在 `package.json` 中
|
||||
- 如果 OpenClaw 必须在加载插件代码前知道它,就把它放在 `openclaw.plugin.json`
|
||||
- 如果它与打包、入口文件或 npm 安装行为有关,就把它放在 `package.json`
|
||||
|
||||
### 影响发现的 `package.json` 字段
|
||||
### 会影响发现的 `package.json` 字段
|
||||
|
||||
某些运行时前插件元数据有意放在 `package.json` 的 `openclaw` 代码块下,而不是 `openclaw.plugin.json` 中。
|
||||
某些运行时前插件元数据有意放在 `package.json` 的 `openclaw` 区块下,而不是 `openclaw.plugin.json` 中。
|
||||
|
||||
重要示例:
|
||||
|
||||
| 字段 | 含义 |
|
||||
| ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `openclaw.extensions` | 声明原生插件入口点。必须保持在插件包目录内。 |
|
||||
| `openclaw.runtimeExtensions` | 声明已安装包的已构建 JavaScript 运行时入口点。必须保持在插件包目录内。 |
|
||||
| `openclaw.setupEntry` | 在 onboarding、延迟渠道启动以及只读渠道 Status/SecretRef 发现期间使用的轻量级、仅设置入口点。必须保持在插件包目录内。 |
|
||||
| `openclaw.runtimeSetupEntry` | 声明已安装包的已构建 JavaScript 设置入口点。必须保持在插件包目录内。 |
|
||||
| `openclaw.channel` | 轻量渠道目录元数据,例如标签、文档路径、别名和选择文案。 |
|
||||
| `openclaw.channel.configuredState` | 轻量级 configured-state 检查器元数据,可在不加载完整渠道运行时的情况下回答“是否已经存在仅由环境变量驱动的设置?”。 |
|
||||
| `openclaw.channel.persistedAuthState` | 轻量级持久化凭证检查器元数据,可在不加载完整渠道运行时的情况下回答“是否已经有任何账号登录?”。 |
|
||||
| `openclaw.runtimeExtensions` | 为已安装包声明已构建的 JavaScript 运行时入口点。必须保持在插件包目录内。 |
|
||||
| `openclaw.setupEntry` | 在新手引导、延迟渠道启动和只读渠道 Status/SecretRef 发现期间使用的轻量级仅设置入口点。必须保持在插件包目录内。 |
|
||||
| `openclaw.runtimeSetupEntry` | 为已安装包声明已构建的 JavaScript 设置入口点。必须保持在插件包目录内。 |
|
||||
| `openclaw.channel` | 轻量级渠道目录元数据,例如标签、文档路径、别名和选择文案。 |
|
||||
| `openclaw.channel.commands` | 在渠道运行时加载前,供配置、审计和命令列表界面使用的静态原生命令和原生 Skills 自动默认元数据。 |
|
||||
| `openclaw.channel.configuredState` | 轻量级已配置状态检查器元数据,可在不加载完整渠道运行时的情况下回答“是否已经存在仅环境变量的设置?”。 |
|
||||
| `openclaw.channel.persistedAuthState` | 轻量级持久化认证状态检查器元数据,可在不加载完整渠道运行时的情况下回答“是否已经有任何内容登录?”。 |
|
||||
| `openclaw.install.npmSpec` / `openclaw.install.localPath` | 内置和外部发布插件的安装/更新提示。 |
|
||||
| `openclaw.install.defaultChoice` | 当存在多个安装源时的首选安装路径。 |
|
||||
| `openclaw.install.defaultChoice` | 当有多个安装来源可用时的首选安装路径。 |
|
||||
| `openclaw.install.minHostVersion` | 最低支持的 OpenClaw 宿主版本,使用类似 `>=2026.3.22` 的 semver 下限。 |
|
||||
| `openclaw.install.expectedIntegrity` | 预期的 npm 分发完整性字符串,例如 `sha512-...`;安装和更新流程会据此校验获取的构件。 |
|
||||
| `openclaw.install.allowInvalidConfigRecovery` | 当配置无效时,允许一条受限的内置插件重装恢复路径。 |
|
||||
| `openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen` | 允许在启动期间先加载仅设置用的渠道界面,再加载完整渠道插件。 |
|
||||
| `openclaw.install.expectedIntegrity` | 预期的 npm 分发完整性字符串,例如 `sha512-...`;安装和更新流程会据此校验获取到的工件。 |
|
||||
| `openclaw.install.allowInvalidConfigRecovery` | 当配置无效时,允许一个范围受限的内置插件重新安装恢复路径。 |
|
||||
| `openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen` | 允许在启动期间先加载仅设置的渠道界面,再加载完整渠道插件。 |
|
||||
|
||||
清单元数据决定了在运行时加载前,onboarding 中会出现哪些 provider/渠道/设置选项。`package.json#openclaw.install` 则告诉 onboarding,当用户选择这些选项之一时,应如何获取或启用该插件。不要将安装提示移到 `openclaw.plugin.json` 中。
|
||||
清单元数据决定了在运行时加载前,新手引导中会出现哪些 provider/渠道/设置选项。`package.json#openclaw.install` 则告诉新手引导,当用户选择这些选项之一时,应如何获取或启用该插件。不要将安装提示移入 `openclaw.plugin.json`。
|
||||
|
||||
`openclaw.install.minHostVersion` 会在安装和清单注册表加载期间强制执行。无效值会被拒绝;较新的但有效的值会让旧宿主跳过该插件。
|
||||
`openclaw.install.minHostVersion` 会在安装和清单注册表加载期间强制执行。无效值会被拒绝;对较旧宿主而言虽较新但有效的值,则会在旧宿主上跳过该插件。
|
||||
|
||||
精确的 npm 版本固定已经在 `npmSpec` 中,例如
|
||||
`"npmSpec": "@wecom/wecom-openclaw-plugin@1.2.3"`。官方外部目录条目应将精确 spec 与 `expectedIntegrity` 配对使用,以便当获取到的 npm 构件不再匹配固定版本时,更新流程会采用失败关闭。为了兼容性,交互式 onboarding 仍会提供受信任注册表的 npm specs,包括裸包名和 dist-tags。目录诊断可以区分精确、浮动、带完整性固定、缺少完整性、包名不匹配和无效默认选项来源。它们还会在存在 `expectedIntegrity` 但没有可用于固定的有效 npm 源时发出警告。当存在 `expectedIntegrity` 时,安装/更新流程会强制执行它;当省略该字段时,注册表解析结果会被记录,但不会附带完整性固定。
|
||||
精确的 npm 版本固定已经存在于 `npmSpec` 中,例如
|
||||
`"npmSpec": "@wecom/wecom-openclaw-plugin@1.2.3"`。官方外部目录条目应将精确规格与 `expectedIntegrity` 配对使用,以便在获取到的 npm 工件不再匹配固定发布版本时,更新流程采用失败关闭。出于兼容性考虑,交互式新手引导仍会提供受信任注册表的 npm 规格,包括裸包名和 dist-tags。目录诊断可以区分精确、浮动、带完整性固定、缺少完整性、包名不匹配以及无效默认选项来源等情况。它们还会在存在 `expectedIntegrity` 但没有可用于固定的有效 npm 来源时发出警告。当存在 `expectedIntegrity` 时,安装/更新流程会强制执行它;当省略该字段时,注册表解析结果会被记录,但不带完整性固定。
|
||||
|
||||
当 Status、渠道列表或 SecretRef 扫描需要在不加载完整运行时的情况下识别已配置账号时,渠道插件应提供 `openclaw.setupEntry`。该设置入口应公开渠道元数据,以及对设置安全的配置、Status 和 secrets 适配器;网络客户端、网关监听器和传输运行时应保留在主扩展入口点中。
|
||||
当 Status、渠道列表或 SecretRef 扫描需要在不加载完整运行时的情况下识别已配置账户时,渠道插件应提供 `openclaw.setupEntry`。该设置入口应公开渠道元数据,以及可安全用于设置的配置、Status 和 secrets 适配器;将网络客户端、网关监听器和传输运行时保留在主扩展入口点中。
|
||||
|
||||
运行时入口点字段不会覆盖源入口点字段的包边界检查。例如,`openclaw.runtimeExtensions` 不能让一个越界的 `openclaw.extensions` 路径变得可加载。
|
||||
运行时入口点字段不会覆盖针对源码入口点字段的包边界检查。例如,`openclaw.runtimeExtensions` 不能让一个越界的 `openclaw.extensions` 路径变得可加载。
|
||||
|
||||
`openclaw.install.allowInvalidConfigRecovery` 的作用范围是刻意受限的。它不会让任意损坏的配置变得可安装。目前它只允许安装流程从特定的陈旧内置插件升级失败中恢复,例如缺失的内置插件路径,或同一内置插件对应的陈旧 `channels.<id>` 条目。无关的配置错误仍会阻止安装,并引导操作员使用 `openclaw doctor --fix`。
|
||||
`openclaw.install.allowInvalidConfigRecovery` 的范围是有意收窄的。它不会让任意损坏配置都变得可安装。当前它仅允许安装流程从特定的陈旧内置插件升级失败中恢复,例如缺失的内置插件路径,或该同一内置插件对应的陈旧 `channels.<id>` 条目。无关的配置错误仍会阻止安装,并将操作人员引导到 `openclaw doctor --fix`。
|
||||
|
||||
`openclaw.channel.persistedAuthState` 是一个微型检查器模块的包元数据:
|
||||
`openclaw.channel.persistedAuthState` 是用于一个微型检查器模块的包元数据:
|
||||
|
||||
```json
|
||||
{
|
||||
@ -708,9 +716,9 @@ Provider Index 条目还可以携带可安装插件元数据,用于那些插
|
||||
}
|
||||
```
|
||||
|
||||
当设置、Doctor 或 configured-state 流程需要在完整渠道插件加载前执行轻量级的是/否凭证探测时,请使用它。目标导出应是一个只读取持久化状态的小函数;不要通过完整渠道运行时 barrel 转发它。
|
||||
当设置、Doctor 或已配置状态流程需要在完整渠道插件加载前进行一次轻量级的是/否认证探测时,请使用它。目标导出应是一个只读取持久化状态的小函数;不要通过完整渠道运行时 barrel 来路由它。
|
||||
|
||||
`openclaw.channel.configuredState` 对轻量级的、仅由环境变量驱动的配置检查使用相同结构:
|
||||
`openclaw.channel.configuredState` 对轻量级仅环境变量已配置检查采用相同结构:
|
||||
|
||||
```json
|
||||
{
|
||||
@ -726,54 +734,53 @@ Provider Index 条目还可以携带可安装插件元数据,用于那些插
|
||||
}
|
||||
```
|
||||
|
||||
当某个渠道可以通过环境变量或其他微型非运行时输入来回答 configured-state 时,请使用它。如果该检查需要完整配置解析或真实渠道运行时,请将该逻辑保留在插件 `config.hasConfiguredState` hook 中。
|
||||
当某个渠道可以仅根据环境变量或其他微小的非运行时输入来回答已配置状态时,请使用它。如果检查需要完整配置解析或真实渠道运行时,请将该逻辑保留在插件 `config.hasConfiguredState` hook 中。
|
||||
|
||||
## 发现优先级(重复插件 id)
|
||||
|
||||
OpenClaw 会从多个根路径发现插件(内置、全局安装、工作区、显式配置选择的路径)。如果两个发现结果共享同一个 `id`,则只保留**最高优先级**的清单;较低优先级的重复项会被丢弃,而不是并排加载。
|
||||
OpenClaw 会从多个根位置发现插件(内置、全局安装、工作区、显式配置选定路径)。如果两个发现结果共享相同的 `id`,则只保留**优先级最高**的清单;较低优先级的重复项会被丢弃,而不是与其并行加载。
|
||||
|
||||
优先级从高到低如下:
|
||||
优先级从高到低:
|
||||
|
||||
1. **配置选中** —— 在 `plugins.entries.<id>` 中显式固定的路径
|
||||
2. **内置** —— 随 OpenClaw 一起发布的插件
|
||||
3. **全局安装** —— 安装到全局 OpenClaw 插件根目录的插件
|
||||
1. **配置选定** —— 在 `plugins.entries.<id>` 中显式固定的路径
|
||||
2. **内置** —— 随 OpenClaw 一同发布的插件
|
||||
3. **全局安装** —— 安装到全局 OpenClaw 插件根目录中的插件
|
||||
4. **工作区** —— 相对于当前工作区发现的插件
|
||||
|
||||
影响:
|
||||
|
||||
- 工作区中某个内置插件的 fork 或陈旧副本不会遮蔽内置构建。
|
||||
- 若要真正用本地插件覆盖内置插件,请通过 `plugins.entries.<id>` 固定它,使其依靠优先级获胜,而不是依赖工作区发现。
|
||||
- 被丢弃的重复项会记录到日志中,以便 Doctor 和启动诊断能够指向被舍弃的副本。
|
||||
- 放在工作区中的某个内置插件的分支版本或陈旧副本,不会遮蔽内置构建版本。
|
||||
- 若要真正用本地插件覆盖内置插件,请通过 `plugins.entries.<id>` 固定它,使其依靠优先级取胜,而不是依赖工作区发现。
|
||||
- 被丢弃的重复项会被记录日志,以便 Doctor 和启动诊断能够指向被舍弃的副本。
|
||||
|
||||
## JSON Schema 要求
|
||||
|
||||
- **每个插件都必须提供一个 JSON Schema**,即使它不接受任何配置。
|
||||
- 空 schema 也是可以接受的(例如 `{ "type": "object", "additionalProperties": false }`)。
|
||||
- Schema 会在配置读取/写入时校验,而不是在运行时校验。
|
||||
- 可以接受空 schema(例如 `{ "type": "object", "additionalProperties": false }`)。
|
||||
- Schema 会在配置读写时校验,而不是在运行时校验。
|
||||
|
||||
## 校验行为
|
||||
|
||||
- 未知的 `channels.*` 键是**错误**,除非该渠道 id 已由
|
||||
某个插件清单声明。
|
||||
- 未知的 `channels.*` 键是**错误**,除非该渠道 id 由某个插件清单声明。
|
||||
- `plugins.entries.<id>`、`plugins.allow`、`plugins.deny` 和 `plugins.slots.*`
|
||||
必须引用**可发现的**插件 id。未知 id 属于**错误**。
|
||||
- 如果插件已安装,但其清单或 schema 损坏或缺失,
|
||||
校验会失败,Doctor 会报告该插件错误。
|
||||
- 如果插件配置存在,但插件已**禁用**,该配置会被保留,
|
||||
并会在 Doctor + 日志中显示一条**警告**。
|
||||
必须引用**可发现**的插件 id。未知 id 属于**错误**。
|
||||
- 如果某个插件已安装,但其清单或 schema 损坏或缺失,
|
||||
校验将失败,Doctor 会报告该插件错误。
|
||||
- 如果插件配置存在,但插件处于**禁用**状态,配置会被保留,并且
|
||||
Doctor + 日志中会显示一条**警告**。
|
||||
|
||||
有关完整的 `plugins.*` schema,请参阅[配置参考](/zh-CN/gateway/configuration)。
|
||||
有关完整的 `plugins.*` schema,请参见[配置参考](/zh-CN/gateway/configuration)。
|
||||
|
||||
## 说明
|
||||
## 注意事项
|
||||
|
||||
- 清单对于**原生 OpenClaw 插件**是**必需的**,包括本地文件系统加载。运行时仍会单独加载插件模块;清单仅用于发现 + 校验。
|
||||
- 原生清单使用 JSON5 解析,因此只要最终值仍然是对象,就接受注释、尾随逗号和未加引号的键。
|
||||
- 清单加载器只读取文档中说明过的清单字段。请避免使用自定义顶层键。
|
||||
- 原生清单使用 JSON5 解析,因此注释、尾随逗号和未加引号的键都被接受,只要最终值仍然是一个对象。
|
||||
- 清单加载器只会读取文档中记录的清单字段。避免使用自定义顶层键。
|
||||
- 当插件不需要时,可以省略 `channels`、`providers`、`cliBackends` 和 `skills`。
|
||||
- `providerDiscoveryEntry` 必须保持轻量,不应导入宽泛的运行时代码;应将其用于静态 provider 目录元数据或窄范围发现描述符,而不是请求时执行。
|
||||
- 互斥插件类型通过 `plugins.slots.*` 选择:`kind: "memory"` 通过 `plugins.slots.memory` 选择,`kind: "context-engine"` 通过 `plugins.slots.contextEngine` 选择(默认值为 `legacy`)。
|
||||
- 环境变量元数据(`setup.providers[].envVars`、已弃用的 `providerAuthEnvVars` 和 `channelEnvVars`)仅是声明式的。Status、审计、cron 投递校验及其他只读界面在将某个环境变量视为已配置前,仍会应用插件信任和有效激活策略。
|
||||
- 有关需要 provider 代码的运行时向导元数据,请参阅[Provider 运行时钩子](/zh-CN/plugins/architecture-internals#provider-runtime-hooks)。
|
||||
- `providerDiscoveryEntry` 必须保持轻量,不应导入宽泛的运行时代码;应将其用于静态 provider 目录元数据或狭义发现描述符,而不是请求时执行。
|
||||
- 排他性插件类型通过 `plugins.slots.*` 选择:`kind: "memory"` 通过 `plugins.slots.memory`,`kind: "context-engine"` 通过 `plugins.slots.contextEngine`(默认 `legacy`)。
|
||||
- 环境变量元数据(`setup.providers[].envVars`、已弃用的 `providerAuthEnvVars` 和 `channelEnvVars`)仅为声明式。Status、审计、cron 投递校验和其他只读界面在将某个环境变量视为已配置之前,仍会应用插件信任和生效激活策略。
|
||||
- 有关需要 provider 代码的运行时向导元数据,请参见[Provider 运行时钩子](/zh-CN/plugins/architecture-internals#provider-runtime-hooks)。
|
||||
- 如果你的插件依赖原生模块,请记录构建步骤以及任何包管理器 allowlist 要求(例如 pnpm `allow-build-scripts` + `pnpm rebuild <package>`)。
|
||||
|
||||
## 相关内容
|
||||
@ -785,7 +792,7 @@ OpenClaw 会从多个根路径发现插件(内置、全局安装、工作区
|
||||
<Card title="插件架构" href="/zh-CN/plugins/architecture" icon="diagram-project">
|
||||
内部架构和能力模型。
|
||||
</Card>
|
||||
<Card title="SDK 概览" href="/zh-CN/plugins/sdk-overview" icon="book">
|
||||
<Card title="插件 SDK 概览" href="/zh-CN/plugins/sdk-overview" icon="book">
|
||||
插件 SDK 参考和子路径导入。
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user