chore(i18n): refresh zh-CN translations

This commit is contained in:
openclaw-docs-i18n[bot] 2026-04-28 02:21:34 +00:00
parent d8a0c9368e
commit 884c8723ea
6 changed files with 979 additions and 958 deletions

View File

@ -1,24 +1,24 @@
---
read_when:
- 你想了解 memory_search 的工作方式
- 你想了解 memory_search 是如何工作的
- 你想选择一个嵌入提供商
- 你想调搜索质量
- 你想调搜索质量
summary: 内存搜索如何使用嵌入和混合检索来查找相关笔记
title: 内存搜索
x-i18n:
generated_at: "2026-04-27T10:58:15Z"
generated_at: "2026-04-28T02:18:30Z"
model: gpt-5.4
provider: openai
source_hash: 7c6dbc694a6ac6b9ab8773ebee245bb18d92a226c56f4ebb5df4dfa255ad940a
source_hash: 3e6c44d90f49a797bda01b9a575928c128a334f89ae14fc3620e65562a866aa9
source_path: concepts/memory-search.md
workflow: 15
---
`memory_search` 会从你的内存文件中查找相关笔记,即使措辞与原始文本不同也能找到。它的工作方式是先将内存索引为小块,然后使用嵌入、关键词或两者结合来搜索这些内容
`memory_search` 会从你的记忆文件中查找相关笔记,即使措辞与原文不同也可以。它的工作方式是将记忆内容索引为小块,然后使用嵌入、关键词或两者结合来进行搜索。
## 快速开始
如果你已配置 GitHub Copilot 订阅、OpenAI、Gemini、Voyage 或 Mistral API 密钥,内存搜索会自动工作。若要显式设置提供商:
如果你已配置 GitHub Copilot 订阅、OpenAI、Gemini、Voyage 或 Mistral API key,内存搜索会自动工作。若要显式设置提供商:
```json5
{
@ -32,13 +32,15 @@ x-i18n:
}
```
如果你想使用无需 API 密钥的本地嵌入,请在 OpenClaw 旁安装可选的 `node-llama-cpp` 运行时包,并使用 `provider: "local"`
对于多端点设置,`provider` 也可以是自定义的 `models.providers.<id>` 条目,例如 `ollama-5080`,前提是该提供商设置了 `api: "ollama"` 或其他嵌入适配器所有者
某些与 OpenAI 兼容的嵌入端点需要非对称标签,例如搜索时使用 `input_type: "query"`,索引块时使用 `input_type: "document"``"passage"`。请使用 `memorySearch.queryInputType``memorySearch.documentInputType` 进行配置;参见[内存配置参考](/zh-CN/reference/memory-config#provider-specific-config)。
如果你想使用无需 API key 的本地嵌入,请在 OpenClaw 旁边安装可选的 `node-llama-cpp` 运行时包,并使用 `provider: "local"`
某些与 OpenAI 兼容的嵌入端点需要非对称标签,例如搜索时使用 `input_type: "query"`,为已索引分块使用 `input_type: "document"``"passage"`。可通过 `memorySearch.queryInputType``memorySearch.documentInputType` 进行配置;参见 [Memory configuration reference](/zh-CN/reference/memory-config#provider-specific-config)。
## 支持的提供商
| 提供商 | ID | 需要 API 密钥 | 说明 |
| 提供商 | ID | 需要 API key | 说明 |
| -------------- | ---------------- | ------------- | ---------------------------------------------------- |
| Bedrock | `bedrock` | 否 | 当 AWS 凭证链可解析时自动检测 |
| Gemini | `gemini` | 是 | 支持图像/音频索引 |
@ -51,7 +53,7 @@ x-i18n:
## 搜索如何工作
OpenClaw 会并行运行两条检索路径,然后合并结果:
OpenClaw 会并行运行两条检索路径,合并结果:
```mermaid
flowchart LR
@ -64,31 +66,31 @@ flowchart LR
M --> R["Top Results"]
```
- **向量搜索** 查找语义相近的笔记“gateway host” 可以匹配 “the machine running OpenClaw”
- **BM25 关键词搜索** 查找精确匹配ID、错误字符串、配置键)。
- **向量搜索** 查找语义相近的笔记“gateway host” 可以匹配 “the machine running OpenClaw”
- **BM25 关键词搜索** 查找精确匹配ID、错误字符串、配置键
如果只有一条路径可用(没有嵌入或没有 FTS则仅运行另一条路径。
当嵌入不可用时OpenClaw 仍会基于 FTS 结果使用词法排序,而不是只退化为原始精确匹配排序。这种降级模式会提升查询词覆盖更强且文件路径更相关的片段,因此即使没有 `sqlite-vec` 或嵌入提供商,也能保持不错的召回效果。
当嵌入不可用时OpenClaw 仍会对 FTS 结果使用词法排序,而不只是退化为原始的精确匹配顺序。这种降级模式会提升那些查询词覆盖更强、文件路径更相关的分块,从而即使没有 `sqlite-vec` 或嵌入提供商,也能保持较好的召回效果。
## 提升搜索质量
当你有大量历史笔记时,有两个可选功能会很有帮助:
当你有大量笔记历史时,两项可选功能会有所帮助:
### 时间衰减
旧笔记的排权重会逐渐降低,因此最近的信息会优先显示。默认半衰期为 30 天,这意味着上个月的笔记得分会降原始权重的 50%。像 `MEMORY.md` 这样的常青文件永远不会衰减。
旧笔记的排权重会逐渐降低,因此最近的信息会优先显示。默认半衰期为 30 天,这意味着上个月的笔记得分会降原始权重的 50%。像 `MEMORY.md` 这样的常青文件永远不会衰减。
<Tip>
如果你的智能体已经积累了数月的日常笔记,并且过时信息总是排在最新上下文之前,请启用时间衰减。
如果你的智能体积累了数个月的每日笔记,而过时信息总是排在最新上下文之前,请启用时间衰减。
</Tip>
### MMR多样性
减少重复结果。如果五条笔记都提到了相同的路由器配置MMR 会确保顶部结果覆盖不同主题,而不是重复返回相似内容。
减少重复结果。如果五条笔记都提到同一份路由器配置MMR 会确保顶部结果覆盖不同主题,而不是反复出现相似内容。
<Tip>
如果 `memory_search` 总是从不同的每日日志中返回几乎重复的片段,请启用 MMR。
如果 `memory_search` 总是从不同的每日笔记中返回近乎重复的片段,请启用 MMR。
</Tip>
### 同时启用两者
@ -110,32 +112,32 @@ flowchart LR
}
```
## 多模态内存
## 多模态记忆
借助 Gemini Embedding 2你可以在 Markdown 之外一并索引图像和音频文件。搜索查询仍然是文本,但可以匹配视觉和音频内容。设置方法请参见[内存配置参考](/zh-CN/reference/memory-config)。
使用 Gemini Embedding 2 时,你可以在 Markdown 之外同时索引图像和音频文件。搜索查询仍然是文本,但它们可以匹配视觉和音频内容。设置方法请参见 [Memory configuration reference](/zh-CN/reference/memory-config)。
## 会话内存搜索
你也可以选择为会话转录建立索引,以便 `memory_search` 能回忆更早的对话。这是通过 `memorySearch.experimental.sessionMemory` 选择启用的实验功能。详情请参见[配置参考](/zh-CN/reference/memory-config)。
你也可以选择为会话转录建立索引,这样 `memory_search`能回忆更早的对话。这是通过 `memorySearch.experimental.sessionMemory` 选择启用的。详情请参见 [configuration reference](/zh-CN/reference/memory-config)。
## 故障排除
**没有结果?** 运行 `openclaw memory status` 检查索引。如果索引为空,运行 `openclaw memory index --force`
**没有结果?** 运行 `openclaw memory status` 检查索引。如果为空,运行 `openclaw memory index --force`
**只有关键词匹配?** 你的嵌入提供商可能尚未配置。检查 `openclaw memory status --deep`
**只有关键词匹配?** 你的嵌入提供商可能尚未配置。检查 `openclaw memory status --deep`
**本地嵌入超时?** `ollama`、`lmstudio` 和 `local` 默认使用更长的内联批处理超时时间。如果只是主机较慢,请设置 `agents.defaults.memorySearch.sync.embeddingBatchTimeoutSeconds`,然后重新运行 `openclaw memory index --force`
**找不到 CJK 文本?** 使用 `openclaw memory index --force` 重建 FTS 索引。
**找不到 CJK 文本?** 使用 `openclaw memory index --force`新构建 FTS 索引。
## 延伸阅读
## 进一步阅读
- [Active Memory](/zh-CN/concepts/active-memory) -- 用于交互式聊天会话的子智能体内存
- [Active Memory](/zh-CN/concepts/active-memory) -- 用于交互式聊天会话的子智能体记忆
- [Memory](/zh-CN/concepts/memory) -- 文件布局、后端、工具
- [内存配置参考](/zh-CN/reference/memory-config) -- 所有配置项
- [Memory configuration reference](/zh-CN/reference/memory-config) -- 所有配置项
## 相关内容
- [Memory 概览](/zh-CN/concepts/memory)
- [Memory overview](/zh-CN/concepts/memory)
- [Active memory](/zh-CN/concepts/active-memory)
- [内置内存引擎](/zh-CN/concepts/memory-builtin)
- [Builtin memory engine](/zh-CN/concepts/memory-builtin)

View File

@ -1,27 +1,27 @@
---
read_when:
- 实现提供商运行时钩子、渠道生命周期或软件包打包 bundles
- 实现提供商运行时钩子、渠道生命周期或软件包打包
- 调试插件加载顺序或注册表状态
- 添加新的插件能力或上下文引擎插件
summary: 插件架构内部机制加载流水线、注册表、运行时钩子、HTTP 路由和参考表格
title: 插件架构内部机制
x-i18n:
generated_at: "2026-04-28T01:41:59Z"
generated_at: "2026-04-28T02:18:31Z"
model: gpt-5.4
provider: openai
source_hash: 6a32b52a2a817596d39a0281d4eeeb3820c8cecc1e7d2d93ab280fd967228bc3
source_hash: 75bca04941f21d711a259137faab57a430d40cf3ea74ab9b3bfdce11a3d28e00
source_path: plugins/architecture-internals.md
workflow: 15
---
关于公开的能力模型、插件形态以及所有权/执行契约,请参阅 [插件架构](/zh-CN/plugins/architecture)。本页是内部机制的参考加载流水线、注册表、运行时钩子、Gateway 网关 HTTP 路由、导入路径和模式表
有关公开能力模型、插件形状以及所有权/执行契约,请参阅 [插件架构](/zh-CN/plugins/architecture)。本页是内部机制的参考加载流水线、注册表、运行时钩子、Gateway 网关 HTTP 路由、导入路径和 schema 表格
## 加载流水线
在启动时OpenClaw 大致会执行以下步骤
在启动时OpenClaw 大致会这样做
1. 发现候选插件根目录
2. 读取原生或兼容 bundle 清单以及软件包元数据
2. 读取原生或兼容 bundle 的 manifest 和 package 元数据
3. 拒绝不安全的候选项
4. 规范化插件配置(`plugins.enabled`、`allow`、`deny`、`entries`、`slots`、`load.paths`
5. 为每个候选项决定是否启用
@ -30,80 +30,81 @@ x-i18n:
8. 将注册表暴露给命令/运行时表面
<Note>
`activate``register` 的旧别名——加载器会解析存在的那个(`def.register ?? def.activate`),并在相同位置调用。所有内置插件都使用 `register`;新插件优先使用 `register`
`activate``register` 的旧别名——加载器会解析现有项(`def.register ?? def.activate`),并在同一时机调用它。所有内置插件都使用 `register`;新插件优先使用 `register`
</Note>
安全门槛发生在运行时执行**之前**。当入口逃逸出插件根目录、路径对所有用户可写,或者对于非内置插件路径所有权看起来可疑时,候选项会被阻止。
安全门禁发生在**运行时执行之前**。当入口逃逸出插件根目录、路径可被所有用户写入,或对于非内置插件而言路径所有权看起来可疑时,候选项会被阻止。
### 清单优先行为
### Manifest 优先的行为
清单是控制平面的事实来源。OpenClaw 使用它来:
manifest 是控制平面的真实来源。OpenClaw 使用它来:
- 标识插件
- 发现声明的渠道/Skills/配置模式或 bundle 能力
- 发现声明的渠道/Skills/配置 schema 或 bundle 能力
- 验证 `plugins.entries.<id>.config`
- 增强 Control UI 标签/占位符
- 补充 Control UI 标签/占位符
- 显示安装/目录元数据
- 在不加载插件运行时的情况下,保留轻量激活和设置描述符
- 在不加载插件运行时的情况下,保留低成本的激活和设置描述符
对于原生插件,运行时模块是数据平面部分。它会注册实际行为,例如钩子、工具、命令或 provider 流程。
对于原生插件,运行时模块是数据平面部分。它会注册实际行为,例如钩子、工具、命令或提供商流程。
可选的清单 `activation``setup` 块仍保留在控制平面上。它们只是用于激活规划和设置发现的纯元数据描述符;它们不会替代运行时注册、`register(...)` 或 `setupEntry`
首批实时激活使用方现在会使用清单中的命令、渠道和 provider 提示,在更广泛的注册表实体化之前缩小插件加载范围:
可选的 manifest `activation``setup` 块保留在控制平面。它们是仅元数据的描述符,用于激活规划和设置发现;它们不会替代运行时注册、`register(...)` 或 `setupEntry`
最初的实时激活消费者现在会使用 manifest 中的命令、渠道和提供商提示,在更广泛的注册表物化之前缩小插件加载范围:
- CLI 加载会缩小到拥有所请求主命令的插件
- 渠道设置/插件解析会缩小到拥有所请求渠道 id 的插件
- 显式 provider 设置/运行时解析会缩小到拥有所请求 provider id 的插件
- 显式的提供商设置/运行时解析会缩小到拥有所请求提供商 id 的插件
- Gateway 网关启动规划使用 `activation.onStartup` 进行显式启动导入和启动退出选择;随着 OpenClaw 逐步摆脱隐式启动导入,每个插件都应声明它,而没有静态能力元数据且没有 `activation.onStartup` 的插件,出于兼容性仍会使用已弃用的隐式启动 sidecar 回退
激活规划器同时暴露面向现有调用方的仅 id API以及面向新诊断场景的 plan API。Plan 条目会报告为何选择某个插件,并将显式 `activation.*` 规划器提示与清单所有权回退区分开来,例如 `providers`、`channels`、`commandAliases`、`setup.providers`、`contracts.tools` 和钩子。这个原因拆分就是兼容性边界:现有插件元数据会继续工作,而新代码可以在不改变运行时加载语义的情况下检测宽泛提示或回退行为。
激活规划器既为现有调用方暴露仅含 id 的 API也为新的诊断暴露 plan API。计划条目会报告为什么选择了某个插件将显式的 `activation.*` 规划器提示与 manifest 所有权回退(例如 `providers`、`channels`、`commandAliases`、`setup.providers`、`contracts.tools` 和钩子)区分开来。这种原因拆分就是兼容性边界:现有插件元数据继续有效,而新代码可以在不改变运行时加载语义的前提下检测宽泛提示或回退行为。
设置发现现在优先使用描述符拥有的 id例如 `setup.providers``setup.cliBackends`,以便在回退到 `setup-api` 之前先缩小候选插件范围后者用于仍然需要设置期运行时钩子的插件。Provider 设置列表会使用清单中的 `providerAuthChoices`、从描述符派生的设置选项以及安装目录元数据,而无需加载 provider 运行时。显式 `setup.requiresRuntime: false` 是仅描述符层面的截断;省略 `requiresRuntime` 则会保留旧版 `setup-api` 回退以保证兼容性。如果多个已发现插件声称拥有同一个规范化后的设置 provider 或 CLI backend id设置查找会拒绝这个歧义所有者而不是依赖发现顺序。当设置运行时确实执行时注册表诊断会报告 `setup.providers` / `setup.cliBackends` 与由 `setup-api` 注册的 providers 或 CLI backends 之间的漂移,但不会阻止旧版插件。
设置发现现在优先使用描述符拥有的 id例如 `setup.providers``setup.cliBackends`,以在回退到 `setup-api` 之前缩小候选插件范围;后者用于仍需要设置时运行时钩子的插件。提供商设置列表会使用 manifest `providerAuthChoices`、描述符派生的设置选项以及安装目录元数据,而无需加载提供商运行时。显式的 `setup.requiresRuntime: false` 是仅描述符的截止点;省略 `requiresRuntime` 则会保留旧版 `setup-api` 回退以实现兼容性。如果有多个已发现插件声明了同一个规范化后的设置提供商或 CLI 后端 id设置查找会拒绝这个歧义所有者而不是依赖发现顺序。当设置运行时确实执行时注册表诊断会报告 `setup.providers` / `setup.cliBackends` 与由 `setup-api` 注册的提供商或 CLI 后端之间的漂移,但不会阻止旧版插件。
### 加载器会缓存什么
OpenClaw 会在进程内保留短期缓存,用于
OpenClaw 会保留以下生命周的进程内缓存:
- 发现结果
- 清单注册表数据
- manifest 注册表数据
- 已加载的插件注册表
这些缓存可减少突发启动和重复命令的开销。可以它们视为短生命周期的性能缓存,而不是持久化存储。
这些缓存可减少突发启动和重复命令的开销。可以安全地将它们视为短生命周期的性能缓存,而不是持久化存储。
Gateway 网关启动热路径应优先使用当前的 `PluginMetadataSnapshot`、派生的 `PluginLookUpTable`,或沿调用链显式传递的清单注册表。配置验证、启动自动启用和插件引导在可用时也会使用同一个快照。对于仍然从持久化已安装插件索引重建清单元数据的调用方OpenClaw 还保留了一个小型有界回退缓存;它以已安装索引、请求形态、配置策略、运行时根目录以及清单/软件包文件签名为键。该缓存仅用于重复的已安装索引重建回退;它不是可变的运行时插件注册表。
Gateway 网关启动热路径应优先使用当前的 `PluginMetadataSnapshot`、派生的 `PluginLookUpTable`,或通过调用链传递的显式 manifest 注册表。在可用时,配置验证、启动自动启用和插件引导都会使用同一个快照。对于仍然从持久化的已安装插件索引重建 manifest 元数据的调用方OpenClaw 还会保留一个小型有界回退缓存,其键由已安装索引、请求形状、配置策略、运行时根目录以及 manifest/package 文件签名组成。该缓存只是针对重复的已安装索引重建的回退;它不是可变的运行时插件注册表。
性能说明:
- 设置 `OPENCLAW_DISABLE_PLUGIN_DISCOVERY_CACHE=1``OPENCLAW_DISABLE_PLUGIN_MANIFEST_CACHE=1` 可禁用这些缓存。
- 设置 `OPENCLAW_DISABLE_INSTALLED_PLUGIN_MANIFEST_REGISTRY_CACHE=1` 可仅禁用已安装索引的清单注册表回退缓存。
- 设置 `OPENCLAW_DISABLE_INSTALLED_PLUGIN_MANIFEST_REGISTRY_CACHE=1` 仅禁用已安装索引的 manifest 注册表回退缓存。
- 使用 `OPENCLAW_PLUGIN_DISCOVERY_CACHE_MS``OPENCLAW_PLUGIN_MANIFEST_CACHE_MS` 调整缓存窗口。
## 注册表模型
已加载的插件不会直接修改任意核心全局状态。它们会注册到一个中心化的插件注册表中。
已加载的插件不会直接随意修改 core 全局状态。它们会注册到一个中央插件注册表中。
注册表会跟踪:
- 插件记录(身份、来源、源头、状态、诊断)
- 插件记录(标识、来源、源类型、状态、诊断)
- 工具
- 旧版钩子和类型化钩子
- 渠道
- providers
- 提供商
- Gateway 网关 RPC 处理器
- HTTP 路由
- CLI 注册器
- 后台服务
- 插件拥有的命令
然后,核心功能会从该注册表中读取,而不是直接与插件模块交互。这样可以保持单向加载
然后,core 功能会从该注册表中读取,而不是直接与插件模块交互。这使加载保持单向
- 插件模块 -> 注册表注册
- 核心运行时 -> 注册表消费
- core 运行时 -> 注册表消费
这种分离对于可维护性很重要。它意味着大多数核心表面只需要一个集成点:“读取注册表”,而不是“为每个插件模块做特殊处理”。
这种分离对可维护性很重要。它意味着大多数 core 表面只需要一个集成点:“读取注册表”,而不是“为每个插件模块做特殊处理”。
## 会话绑定回调
绑定会话的插件可以在审批结果确定时作出响应。
绑定会话的插件可以在批准结果确定后作出响应。
使用 `api.onConversationBindingResolved(...)` 可在绑定请求被批准或拒绝后接收回调:
@ -113,7 +114,7 @@ export default {
register(api) {
api.onConversationBindingResolved(async (event) => {
if (event.status === "approved") {
// 现在已存在此插件 + 会话的绑定。
// 这个插件 + 会话现在已有一个绑定。
console.log(event.binding?.conversationId);
return;
}
@ -129,91 +130,91 @@ export default {
- `status``"approved"` 或 `"denied"`
- `decision``"allow-once"`、`"allow-always"` 或 `"deny"`
- `binding`用于已批准请求的解析绑定
- `request`:原始请求摘要、分离提示、发送者 id 以及会话元数据
- `binding`:已批准请求的解析绑定
- `request`:原始请求摘要、分离提示、发送者 id 会话元数据
这个回调仅用于通知。它不会改变谁被允许绑定会话,并且它会在核心审批处理完成后运行。
此回调仅用于通知。它不会改变谁被允许绑定会话,并且它会在 core 批准处理完成后运行。
## Provider 运行时钩子
## 提供商运行时钩子
Provider 插件有三层:
提供商插件有三层:
- **清单元数据**,用于轻量的运行时前查找:
- **Manifest 元数据**,用于低成本的运行时前查找:
`setup.providers[].envVars`、已弃用的兼容项 `providerAuthEnvVars`
`providerAuthAliases`、`providerAuthChoices` 和 `channelEnvVars`
- **配置期钩子**`catalog`(旧称 `discovery`)以及
- **配置时钩子**`catalog`(旧版为 `discovery`)以及
`applyConfigDefaults`
- **运行时钩子**40 多个可选钩子,覆盖认证、模型解析、
流包装、思考级别、重放策略和用量端点。完整列表见
[钩子顺序和用法](#hook-order-and-usage)。
OpenClaw 仍然拥有通用的 Agent loop、故障转移、转录处理和工具策略。这些钩子是 provider 特定行为的扩展表面,因此无需整个自定义推理传输层
OpenClaw 仍然拥有通用的 Agent loop、故障转移、转录处理和工具策略。这些钩子是提供商特定行为的扩展表面,而无需实现一整套自定义推理传输
provider 具有基于环境变量的凭证,并且通用认证/状态/模型选择器路径需要在不加载插件运行时的情况下看到这些凭证时,请使用清单 `setup.providers[].envVars`。已弃用的 `providerAuthEnvVars` 在弃用窗口期间仍会由兼容适配器读取,并且使用它的非内置插件会收到一条清单诊断。当一个 provider id 应复用另一个 provider id 的环境变量、auth profiles、配置支持的认证以及 API 密钥新手引导选项时,请使用清单 `providerAuthAliases`。当新手引导/认证选项 CLI 表面需要在不加载 provider 运行时的情况下了解 provider 的选项 id、分组标签和简单的单 flag 认证接线时,请使用清单 `providerAuthChoices`。将 provider 运行时
`envVars` 保留用于面向运维者的提示,例如新手引导标签或 OAuth
提供商具有基于环境变量的凭证,且通用认证/状态/模型选择器路径需要在不加载提供商运行时的情况下看到这些凭证时,请使用 manifest `setup.providers[].envVars`。已弃用的 `providerAuthEnvVars` 在弃用窗口期间仍会由兼容适配器读取,使用它的非内置插件会收到一条 manifest 诊断。当一个提供商 id 应复用另一个提供商 id 的环境变量、认证配置文件、基于配置的认证和 API 密钥新手引导选项时,请使用 manifest `providerAuthAliases`。当新手引导/认证选项 CLI 表面需要在不加载提供商运行时的情况下了解该提供商的 choice id、分组标签和简单的单标志认证接线时请使用 manifest `providerAuthChoices`。保留提供商运行时
`envVars` 用于面向操作员的提示,例如新手引导标签或 OAuth
client-id/client-secret 设置变量。
当渠道具有由环境变量驱动的认证或设置,且通用 shell 环境变量回退、配置/状态检查或设置提示需要在不加载渠道运行时的情况下看到它们时,请使用清单 `channelEnvVars`
当渠道具有由环境变量驱动的认证或设置,且通用 shell 环境变量回退、配置/状态检查或设置提示需要在不加载渠道运行时的情况下看到这些信息时,请使用 manifest `channelEnvVars`
### 钩子顺序和用法
对于模型/provider 插件OpenClaw 大致按以下顺序调用钩子。
对于模型/提供商插件OpenClaw 大致会按以下顺序调用钩子。
“何时使用”列是快速决策指南。
| # | 钩子 | 作用 | 何时使用 |
| --- | --- | --- | --- |
| 1 | `catalog` | 在生成 `models.json` 期间,将 provider 配置发布到 `models.providers` 中 | provider 拥有目录或 base URL 默认值 |
| 2 | `applyConfigDefaults` | 在配置实体化期间,应用 provider 拥有的全局配置默认值 | 默认值取决于认证模式、环境变量或 provider 模型家族语义 |
| -- | _(内置模型查找)_ | OpenClaw 会先尝试常规注册表/目录路径 | _(不是插件钩子)_ |
| 3 | `normalizeModelId` | 在查找之前规范化旧版或预览版 model-id 别名 | provider 在规范模型解析前拥有别名清理逻辑 |
| 4 | `normalizeTransport` | 在通用模型组装前,规范化 provider 家族的 `api` / `baseUrl` | provider 在同一传输家族中为自定义 provider id 拥有传输清理逻辑 |
| 5 | `normalizeConfig` | 在运行时/provider 解析之前,规范化 `models.providers.<id>` | provider 需要应与插件一起存在的配置清理逻辑;内置的 Google 家族辅助逻辑也会为受支持的 Google 配置条目提供兜底 |
| 6 | `applyNativeStreamingUsageCompat` | 对配置 providers 应用原生流式用量兼容性重写 | provider 需要由端点驱动的原生流式用量元数据修正 |
| 7 | `resolveConfigApiKey` | 在加载运行时认证之前,为配置 providers 解析环境变量标记认证 | provider 具有 provider 自有的环境变量标记 API 密钥解析逻辑;`amazon-bedrock` 在此也具有内置的 AWS 环境变量标记解析器 |
| 8 | `resolveSyntheticAuth` | 在不持久化明文的情况下,暴露本地/自托管或配置支持的认证 | provider 可使用合成/本地凭证标记运行 |
| 9 | `resolveExternalAuthProfiles` | 叠加 provider 自有的外部认证 profilesCLI/应用自有凭证的默认 `persistence``runtime-only` | provider 复用外部认证凭证,而不持久化复制的刷新令牌;请在清单中声明 `contracts.externalAuthProviders` |
| 10 | `shouldDeferSyntheticProfileAuth` | 将已存储的合成 profile 占位符优先级降低到环境变量/配置支持认证之后 | provider 存储了不应获得更高优先级的合成占位 profile |
| 11 | `resolveDynamicModel` | 为本地注册表中尚不存在的 provider 自有模型 id 提供同步回退 | provider 接受任意上游模型 id |
| 12 | `prepareDynamicModel` | 先进行异步预热,然后再次运行 `resolveDynamicModel` | provider 在解析未知 id 之前需要网络元数据 |
| 13 | `normalizeResolvedModel` | 在嵌入式运行器使用已解析模型之前做最终重写 | provider 需要传输重写,但仍使用核心传输 |
| 14 | `contributeResolvedModelCompat` | 为位于另一兼容传输之后的供应商模型提供兼容标志 | provider 能在代理传输上识别自己的模型,而无需接管该 provider |
| 15 | `capabilities` | 由共享核心逻辑使用的 provider 自有转录/工具元数据 | provider 需要转录/provider 家族特性处理 |
| 16 | `normalizeToolSchemas` | 在嵌入式运行器看到工具模式之前对其进行规范化 | provider 需要传输家族级的模式清理 |
| 17 | `inspectToolSchemas` | 在规范化后暴露 provider 自有的模式诊断 | provider 希望提供关键字警告,而无需让核心了解 provider 特定规则 |
| 18 | `resolveReasoningOutputMode` | 选择原生或带标签的 reasoning-output 契约 | provider 需要带标签的 reasoning/final output而不是原生字段 |
| 19 | `prepareExtraParams` | 在通用流选项包装器之前进行请求参数规范化 | provider 需要默认请求参数或按 provider 进行参数清理 |
| 20 | `createStreamFn` | 使用自定义传输完全替换常规流路径 | provider 需要自定义线路协议,而不仅仅是包装器 |
| 21 | `wrapStreamFn` | 在应用通用包装器后对流函数再做包装 | provider 需要请求头/请求体/模型兼容包装,而不是自定义传输 |
| 22 | `resolveTransportTurnState` | 附加原生的逐轮传输请求头或元数据 | provider 希望通用传输发送 provider 原生轮次标识 |
| 23 | `resolveWebSocketSessionPolicy` | 附加原生 WebSocket 请求头或会话冷却策略 | provider 希望通用 WS 传输调整会话请求头或回退策略 |
| 24 | `formatApiKey` | auth profile 格式化器:将已存储 profile 转为运行时 `apiKey` 字符串 | provider 存储额外认证元数据,并需要自定义运行时令牌形态 |
| 25 | `refreshOAuth` | 为自定义刷新端点或刷新失败策略覆盖 OAuth 刷新逻辑 | provider 不适配共享的 `pi-ai` 刷新器 |
| 26 | `buildAuthDoctorHint` | 当 OAuth 刷新失败时附加修复提示 | provider 在刷新失败后需要 provider 自有的认证修复指引 |
| 27 | `matchesContextOverflowError` | provider 自有的上下文窗口溢出匹配器 | provider 存在通用启发式无法识别的原始溢出错误 |
| 28 | `classifyFailoverReason` | provider 自有的故障转移原因分类 | provider 可将原始 API/传输错误映射为速率限制、过载等 |
| 29 | `isCacheTtlEligible` | 面向代理/回程 providers 的提示缓存策略 | provider 需要代理特定的缓存 TTL 门控 |
| 30 | `buildMissingAuthMessage` | 替换通用的缺失认证恢复消息 | provider 需要 provider 特定的缺失认证恢复提示 |
| 31 | `suppressBuiltInModel` | 已弃用。运行时钩子不再调用;请改用清单 `modelCatalog.suppressions` | 这是用于隐藏过时上游条目的历史钩子;新的抑制数据应保留在插件清单中 |
| 32 | `augmentModelCatalog` | 在发现之后追加合成/最终目录条目 | provider 需要在 `models list` 和选择器中提供合成的前向兼容条目 |
| 33 | `resolveThinkingProfile` | 设置特定模型的 `/think` 级别、显示标签和默认值 | provider 为选定模型提供自定义思考阶梯或二元标签 |
| 34 | `isBinaryThinking` | 开/关式推理切换兼容钩子 | provider 仅暴露二元的思考开/关 |
| 35 | `supportsXHighThinking` | `xhigh` 推理支持兼容钩子 | provider 希望仅在部分模型上启用 `xhigh` |
| 36 | `resolveDefaultThinkingLevel` | 默认 `/think` 级别兼容钩子 | provider 为某个模型家族拥有默认 `/think` 策略 |
| 37 | `isModernModelRef` | 用于实时 profile 过滤和冒烟选择的现代模型匹配器 | provider 拥有实时/冒烟优选模型匹配逻辑 |
| 38 | `prepareRuntimeAuth` | 在推理前将已配置凭证交换为实际运行时令牌/密钥 | provider 需要令牌交换或短生命周期请求凭证 |
| 39 | `resolveUsageAuth` | 为 `/usage` 和相关状态表面解析用量/计费凭证 | provider 需要自定义的用量/配额令牌解析,或使用不同的用量凭证 |
| 40 | `fetchUsageSnapshot` | 在认证解析后获取并规范化 provider 特定的用量/配额快照 | provider 需要 provider 特定的用量端点或负载解析器 |
| 41 | `createEmbeddingProvider` | 为记忆/搜索构建 provider 自有的嵌入适配器 | 记忆嵌入行为应归属于 provider 插件 |
| 42 | `buildReplayPolicy` | 返回一个控制 provider 转录处理的重放策略 | provider 需要自定义转录策略(例如去除 thinking 块) |
| 43 | `sanitizeReplayHistory` | 在通用转录清理后重写重放历史 | provider 需要超出共享压缩辅助逻辑之外的 provider 特定重放重写 |
| 44 | `validateReplayTurns` | 在嵌入式运行器之前,对重放轮次进行最终验证或重塑 | provider 传输在通用净化之后需要更严格的轮次验证 |
| 45 | `onModelSelected` | 运行 provider 自有的选择后副作用 | 当某个模型变为活动状态时provider 需要遥测或 provider 自有状态 |
| --- | --------------------------------- | -------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| 1 | `catalog` | 在生成 `models.json` 期间将提供商配置发布到 `models.providers` 中 | 提供商拥有目录或 base URL 默认值 |
| 2 | `applyConfigDefaults` | 在配置物化期间应用提供商拥有的全局配置默认值 | 默认值依赖于认证模式、环境变量或提供商模型家族语义 |
| -- | _(内置模型查找)_ | OpenClaw 会先尝试正常的注册表/目录路径 | _(不是插件钩子)_ |
| 3 | `normalizeModelId` | 在查找前规范化旧版或预览版 model-id 别名 | 提供商在规范模型解析前拥有别名清理逻辑 |
| 4 | `normalizeTransport` | 在通用模型组装前规范化提供商家族的 `api` / `baseUrl` | 提供商在同一传输家族中对自定义提供商 id 拥有传输清理逻辑 |
| 5 | `normalizeConfig` | 在运行时/提供商解析前规范化 `models.providers.<id>` | 提供商需要与插件放在一起的配置清理;内置的 Google 家族辅助逻辑也会为受支持的 Google 配置条目提供兜底 |
| 6 | `applyNativeStreamingUsageCompat` | 对配置提供商应用原生流式用量兼容性重写 | 提供商需要基于端点驱动的原生流式用量元数据修复 |
| 7 | `resolveConfigApiKey` | 在加载运行时认证前,为配置提供商解析环境变量标记认证 | 提供商拥有自己的环境变量标记 API 密钥解析;`amazon-bedrock` 在这里也有一个内置的 AWS 环境变量标记解析器 |
| 8 | `resolveSyntheticAuth` | 在不持久化明文的情况下暴露本地/自托管或基于配置的认证 | 提供商可以使用 synthetic/local 凭证标记运行 |
| 9 | `resolveExternalAuthProfiles` | 叠加提供商拥有的外部认证配置文件CLI/应用拥有的凭证默认 `persistence``runtime-only` | 提供商可在不持久化复制的刷新令牌的情况下复用外部认证凭证;请在 manifest 中声明 `contracts.externalAuthProviders` |
| 10 | `shouldDeferSyntheticProfileAuth` | 将已存储的 synthetic 配置文件占位符排在环境变量/基于配置的认证之后 | 提供商存储了 synthetic 占位配置文件,而这些配置文件不应具有更高优先级 |
| 11 | `resolveDynamicModel` | 为本地注册表中尚不存在的提供商拥有模型 id 提供同步回退 | 提供商接受任意上游模型 id |
| 12 | `prepareDynamicModel` | 先进行异步预热,然后再次运行 `resolveDynamicModel` | 提供商在解析未知 id 之前需要网络元数据 |
| 13 | `normalizeResolvedModel` | 在嵌入式运行器使用已解析模型之前进行最终重写 | 提供商需要传输重写,但仍使用 core 传输 |
| 14 | `contributeResolvedModelCompat` | 为位于另一兼容传输之后的厂商模型贡献兼容性标志 | 提供商可在代理传输上识别自己的模型,而无需接管该提供商 |
| 15 | `capabilities` | 由共享 core 逻辑使用的提供商拥有的转录/工具元数据 | 提供商需要转录/提供商家族特有行为支持 |
| 16 | `normalizeToolSchemas` | 在嵌入式运行器看到之前规范化工具 schema | 提供商需要传输家族 schema 清理 |
| 17 | `inspectToolSchemas` | 在规范化后暴露提供商拥有的 schema 诊断 | 提供商希望提供关键字警告,而不必让 core 学会提供商特定规则 |
| 18 | `resolveReasoningOutputMode` | 选择原生或带标签的 reasoning-output 契约 | 提供商需要带标签的 reasoning/final output而不是原生字段 |
| 19 | `prepareExtraParams` | 在通用流选项包装器之前规范化请求参数 | 提供商需要默认请求参数或按提供商清理参数 |
| 20 | `createStreamFn` | 用自定义传输完全替换正常的流路径 | 提供商需要自定义线路协议,而不仅仅是包装器 |
| 21 | `wrapStreamFn` | 在应用通用包装器后进行流包装 | 提供商需要请求头/请求体/模型兼容性包装器,但不需要自定义传输 |
| 22 | `resolveTransportTurnState` | 附加原生的逐轮传输头或元数据 | 提供商希望通用传输发送提供商原生的轮次标识 |
| 23 | `resolveWebSocketSessionPolicy` | 附加原生 WebSocket 头或会话冷却策略 | 提供商希望通用 WS 传输调整会话头或回退策略 |
| 24 | `formatApiKey` | 认证配置文件格式化器:已存储配置文件会变为运行时 `apiKey` 字符串 | 提供商存储了额外认证元数据,并需要自定义运行时令牌形状 |
| 25 | `refreshOAuth` | 为自定义刷新端点或刷新失败策略覆盖 OAuth 刷新逻辑 | 提供商不适配共享的 `pi-ai` 刷新器 |
| 26 | `buildAuthDoctorHint` | 当 OAuth 刷新失败时追加修复提示 | 提供商在刷新失败后需要提供商拥有的认证修复指引 |
| 27 | `matchesContextOverflowError` | 提供商拥有的上下文窗口溢出匹配器 | 提供商有通用启发式无法识别的原始溢出错误 |
| 28 | `classifyFailoverReason` | 提供商拥有的故障转移原因分类 | 提供商可以将原始 API/传输错误映射为速率限制/过载等 |
| 29 | `isCacheTtlEligible` | 面向代理/回程提供商的提示缓存策略 | 提供商需要特定于代理的缓存 TTL 门禁 |
| 30 | `buildMissingAuthMessage` | 替换通用缺失认证恢复消息 | 提供商需要提供商特定的缺失认证恢复提示 |
| 31 | `suppressBuiltInModel` | 已弃用。运行时钩子不再被调用;请改用 manifest `modelCatalog.suppressions` | 这是用于隐藏过时上游条目的历史钩子;新的抑制数据应保留在插件 manifest 中 |
| 32 | `augmentModelCatalog` | 在发现后追加 synthetic/final 目录条目 | 提供商需要在 `models list` 和选择器中提供 synthetic 的前向兼容条目 |
| 33 | `resolveThinkingProfile` | 设置特定模型的 `/think` 级别、显示标签和默认值 | 提供商为选定模型公开自定义思考阶梯或二元标签 |
| 34 | `isBinaryThinking` | 开/关推理切换兼容性钩子 | 提供商只公开二元的思考开/关 |
| 35 | `supportsXHighThinking` | `xhigh` 推理支持兼容性钩子 | 提供商希望仅在部分模型上启用 `xhigh` |
| 36 | `resolveDefaultThinkingLevel` | 默认 `/think` 级别兼容性钩子 | 提供商拥有某个模型家族的默认 `/think` 策略 |
| 37 | `isModernModelRef` | 用于实时配置文件过滤和 smoke 选择的现代模型匹配器 | 提供商拥有 live/smoke 首选模型匹配逻辑 |
| 38 | `prepareRuntimeAuth` | 在推理之前,将已配置的凭证交换为实际运行时令牌/密钥 | 提供商需要令牌交换或短生命周期的请求凭证 |
| 39 | `resolveUsageAuth` | 为 `/usage` 和相关状态表面解析用量/计费凭证 | 提供商需要自定义用量/配额令牌解析,或使用不同的用量凭证 |
| 40 | `fetchUsageSnapshot` | 在认证解析后获取并规范化提供商特定的用量/配额快照 | 提供商需要提供商特定的用量端点或负载解析器 |
| 41 | `createEmbeddingProvider` | 为内存/搜索构建提供商拥有的嵌入适配器 | 内存嵌入行为应归属于提供商插件 |
| 42 | `buildReplayPolicy` | 返回一个控制提供商转录处理方式的重放策略 | 提供商需要自定义转录策略(例如剥离 thinking 块) |
| 43 | `sanitizeReplayHistory` | 在通用转录清理后重写重放历史 | 提供商需要超出共享压缩辅助工具范围的提供商特定重放重写 |
| 44 | `validateReplayTurns` | 在嵌入式运行器之前对重放轮次进行最终验证或重塑 | 提供商传输在通用清理后需要更严格的轮次验证 |
| 45 | `onModelSelected` | 在模型被选中后运行提供商拥有的后置副作用 | 当模型变为活动状态时,提供商需要遥测或提供商拥有的状态 |
`normalizeModelId`、`normalizeTransport` 和 `normalizeConfig` 会先检查匹配到的 provider 插件,然后继续尝试其他具备相应钩子能力的 provider 插件,直到某个插件实际更改了模型 id 或传输/配置。这样可以让别名/兼容 provider shim 正常工作,而不要求调用方知道是哪个内置插件拥有该重写逻辑。如果没有 provider 钩子重写某个受支持的 Google 家族配置条目,内置的 Google 配置规范化器仍会应用该兼容性清理。
`normalizeModelId`、`normalizeTransport` 和 `normalizeConfig` 会先检查匹配到的提供商插件,然后依次回退到其他具备相应钩子能力的提供商插件,直到有插件实际更改了模型 id 或传输/配置。这样可以让别名/兼容性提供商 shim 继续工作,而不要求调用方知道是哪个内置插件拥有这项重写逻辑。如果没有任何提供商钩子重写受支持的 Google 家族配置条目,内置的 Google 配置规范化器仍会应用该兼容性清理。
如果 provider 需要完全自定义的线路协议或自定义请求执行器,那就是另一类扩展。这些钩子适用于仍在 OpenClaw 常规推理循环上运行的 provider 行为。
如果提供商需要完全自定义的线路协议或自定义请求执行器,那就是另一类扩展。这些钩子适用于仍运行在 OpenClaw 正常推理循环上的提供商行为。
### Provider 示例
### 提供商示例
```ts
api.registerProvider({
@ -269,41 +270,41 @@ api.registerProvider({
### 内置示例
内置 provider 插件会组合使用上述钩子,以适配各个供应商的目录、认证、思考、重放和用量需求。权威钩子集合与各插件一起存放在 `extensions/` 下;本页仅说明其形态,而不是镜像完整列表。
内置提供商插件会组合使用上述钩子,以适配各厂商在目录、认证、思考、重放和用量方面的需求。权威的钩子集合位于 `extensions/` 下各插件内部;本页旨在说明这些形状,而不是镜像完整列表。
<AccordionGroup>
<Accordion title="直通式目录 providers">
<Accordion title="透传目录提供商">
OpenRouter、Kilocode、Z.AI、xAI 会注册 `catalog` 以及
`resolveDynamicModel` / `prepareDynamicModel`这样它们就可以在
OpenClaw 的静态目录之前暴露上游模型 id。
`resolveDynamicModel` / `prepareDynamicModel`从而能够在 OpenClaw
的静态目录之前暴露上游模型 id。
</Accordion>
<Accordion title="OAuth 和用量端点 providers">
<Accordion title="OAuth 和用量端点提供商">
GitHub Copilot、Gemini CLI、ChatGPT Codex、MiniMax、Xiaomi、z.ai 会将
`prepareRuntimeAuth``formatApiKey``resolveUsageAuth` +
`fetchUsageSnapshot`合使用,以接管令牌交换和 `/usage` 集成。
`fetchUsageSnapshot`对使用,以控制令牌交换和 `/usage` 集成。
</Accordion>
<Accordion title="重放转录清理家族">
<Accordion title="重放转录清理家族">
共享的命名家族(`google-gemini`、`passthrough-gemini`、
`anthropic-by-model`、`hybrid-anthropic-openai`允许 providers 通过
`buildReplayPolicy` 选择转录策略,而不是让每个插件各自重新实现清理逻辑。
`anthropic-by-model`、`hybrid-anthropic-openai`让提供商能够通过
`buildReplayPolicy` 选择转录策略,而不是让每个插件都重复实现清理逻辑。
</Accordion>
<Accordion title="仅目录 providers">
<Accordion title="仅目录提供商">
`byteplus`、`cloudflare-ai-gateway`、`huggingface`、`kimi-coding`、`nvidia`、
`qianfan`、`synthetic`、`together`、`venice`、`vercel-ai-gateway` 和
`volcengine` 仅注册 `catalog`,并复用共享推理循环。
</Accordion>
<Accordion title="Anthropic 专用流辅助逻辑">
Beta 请求头、`/fast` / `serviceTier` 以及 `context1m` 位于
Anthropic 插件公开`api.ts` / `contract-api.ts` 接缝中
<Accordion title="Anthropic 专用流辅助工具">
Beta 头、`/fast` / `serviceTier` 以及 `context1m` 位于
Anthropic 插件的公共 `api.ts` / `contract-api.ts` 接缝中
`wrapAnthropicProviderStream`、`resolveAnthropicBetas`、
`resolveAnthropicFastMode`、`resolveAnthropicServiceTier`),而不是位于
`resolveAnthropicFastMode`、`resolveAnthropicServiceTier`),而不是放在
通用 SDK 中。
</Accordion>
</AccordionGroup>
## 运行时辅助方法
## 运行时辅助工具
插件可以通过 `api.runtime` 访问选定的核心辅助方法。以 TTS 为例:
插件可以通过 `api.runtime` 访问部分 core 辅助工具。以 TTS 为例:
```ts
const clip = await api.runtime.tts.textToSpeech({
@ -324,14 +325,14 @@ const voices = await api.runtime.tts.listVoices({
说明:
- `textToSpeech` 会返回适用于文件/语音便笺表面的常规核心 TTS 输出负载
- 使用核心 `messages.tts` 配置和 provider 选择逻辑
- 返回 PCM 音频缓冲区 + 采样率。插件必须为各 provider 重新采样/编码。
- `listVoices` 对每个 provider 而言都是可选的。可将其用于供应商自有的语音选择器或设置流程。
- 语音列表可包含更丰富的元数据,例如区域设置、性别和 personality 标签,以支持 provider 感知的选择器。
- 前 OpenAI 和 ElevenLabs 支持电话语音。Microsoft 不支持。
- `textToSpeech` 会返回普通 core TTS 输出负载,用于文件/语音便笺表面
- 使用 core `messages.tts` 配置和提供商选择
- 返回 PCM 音频缓冲区 + 采样率。插件必须为提供商重新采样/编码。
- `listVoices` 对每个提供商来说都是可选的。可将其用于厂商拥有的语音选择器或设置流程。
- 语音列表可包含更丰富的元数据,例如 locale、gender 和 personality 标签,以支持提供商感知的选择器。
- 前 OpenAI 和 ElevenLabs 支持电话语音。Microsoft 不支持。
插件也可以通过 `api.registerSpeechProvider(...)` 注册语音 providers
插件也可以通过 `api.registerSpeechProvider(...)` 注册语音提供商
```ts
api.registerSpeechProvider({
@ -351,12 +352,12 @@ api.registerSpeechProvider({
说明:
- 将 TTS 策略、回退和回复投递保留在核心中。
- 将 speech providers 用于供应商自有的合成行为。
- 旧版 Microsoft `edge` 输入会被规范化为 `microsoft` provider id。
- 首选的所有权模型是面向公司的:随着 OpenClaw 增加这些能力契约,一个供应商插件可以统一拥有文本、语音、图像以及未来的媒体 providers
- 将 TTS 策略、回退和回复投递保留在 core 中。
- 语音提供商用于厂商拥有的语音合成行为。
- 旧版 Microsoft `edge` 输入会被规范化为 `microsoft` 提供商 id。
- 首选的所有权模型是面向公司的:随着 OpenClaw 增加这些能力契约,一个厂商插件可以拥有文本、语音、图像以及未来的媒体提供商
对于图像/音频/视频理解,插件会注册一个类型化的媒体理解 provider而不是通用的键值包:
对于图像/音频/视频理解,插件应注册一个类型化的媒体理解提供商,而不是一个通用的键值包:
```ts
api.registerMediaUnderstandingProvider({
@ -370,15 +371,15 @@ api.registerMediaUnderstandingProvider({
说明:
- 将编排、回退、配置和渠道接线保留在核心中。
- 将供应商行为保留在 provider 插件中。
- 增量扩展应保持类型化:新增可选方法、新增可选结果字段、新增可选能力。
- 视频生成已经遵循同样的模式:
- 核心拥有能力契约和运行时辅助方法
- 供应商插件注册 `api.registerVideoGenerationProvider(...)`
- 将编排、回退、配置和渠道接线保留在 core 中。
- 将厂商行为保留在提供商插件中。
- 增量扩展应保持类型化:新的可选方法、新的可选结果字段、新的可选能力。
- 视频生成已经遵循同模式:
- core 拥有能力契约和运行时辅助工具
- 商插件注册 `api.registerVideoGenerationProvider(...)`
- 功能/渠道插件消费 `api.runtime.videoGeneration.*`
对于媒体理解运行时辅助方法,插件可以调用:
对于媒体理解运行时辅助工具,插件可以调用:
```ts
const image = await api.runtime.mediaUnderstanding.describeImageFile({
@ -407,11 +408,11 @@ const { text } = await api.runtime.mediaUnderstanding.transcribeAudioFile({
说明:
- `api.runtime.mediaUnderstanding.*` 是图像/音频/视频理解的首选共享表面。
- 使用核心媒体理解音频配置(`tools.media.audio`)和 provider 回退顺序。
- 当未产生转录输出时返回 `{ text: undefined }`(例如输入被跳过/不受支持)
- 使用 core 媒体理解音频配置(`tools.media.audio`)和提供商回退顺序。
- 当未产生转录输出时(例如输入被跳过/不受支持),返回 `{ text: undefined }`
- `api.runtime.stt.transcribeAudioFile(...)` 仍保留为兼容性别名。
插件还可以通过 `api.runtime.subagent` 启动后台 subagent 运行:
插件还可以通过 `api.runtime.subagent` 启动后台子智能体运行:
```ts
const result = await api.runtime.subagent.run({
@ -425,14 +426,14 @@ const result = await api.runtime.subagent.run({
说明:
- `provider``model` 是每次运行可选覆盖项,不是持久性的会话更
- OpenClaw 只会为受信任的调用方接受这些覆盖字段。
- 对于插件自有的回退运行,运维者必须通过 `plugins.entries.<id>.subagent.allowModelOverride: true` 显式启用。
- 使用 `plugins.entries.<id>.subagent.allowedModels` 将受信任插件限制为特定的规范 `provider/model` 目标,或设置为 `"*"` 以显式允许任意目标。
- 不受信任插件的 subagent 运行仍可工作,但覆盖请求会被拒绝,而不会静默回退。
- 由插件创建的 subagent 会话会带上创建插件 id 的标签。回退 `api.runtime.subagent.deleteSession(...)` 只能删除这些自有会话;删除任意会话仍需要具有管理员作用域的 Gateway 网关请求。
- `provider``model` 是每次运行可选覆盖项,不是持久性的会话更。
- OpenClaw 只会为受信任调用方启用这些覆盖字段。
- 对于插件拥有的回退运行,操作员必须通过 `plugins.entries.<id>.subagent.allowModelOverride: true` 显式启用。
- 使用 `plugins.entries.<id>.subagent.allowedModels` 将受信任插件限制为特定的规范 `provider/model` 目标,或使用 `"*"` 以显式允许任意目标。
- 不受信任的插件子智能体运行仍然可用,但覆盖请求会被拒绝,而不是静默回退。
- 由插件创建的子智能体会话会带有创建插件 id 标签。回退 `api.runtime.subagent.deleteSession(...)` 只能删除这些所属会话;删除任意会话仍然需要管理员作用域的 Gateway 网关请求。
对于 Web 搜索,插件可以消费共享运行时辅助方法,而不是深入到智能体工具接线中:
对于 web 搜索,插件可以使用共享运行时辅助工具,而不是深入到智能体工具接线中:
```ts
const providers = api.runtime.webSearch.listProviders({
@ -449,13 +450,13 @@ const result = await api.runtime.webSearch.search({
```
插件也可以通过
`api.registerWebSearchProvider(...)` 注册 Web 搜索 providers
`api.registerWebSearchProvider(...)` 注册 Web 搜索提供商
说明:
- 将 provider 选择、凭证解析和共享请求语义保留在核心中。
- 将 Web 搜索 providers 用于供应商特定的搜索传输。
- `api.runtime.webSearch.*`功能/渠道插件的首选共享表面,适用于需要搜索能力但不依赖智能体工具包装器的场景
- 将提供商选择、凭证解析和共享请求语义保留在 core 中。
- Web 搜索提供商用于厂商特定的搜索传输。
- `api.runtime.webSearch.*`需要搜索行为但不依赖智能体工具包装器的功能/渠道插件的首选共享表面
### `api.runtime.imageGeneration`
@ -470,8 +471,8 @@ const providers = api.runtime.imageGeneration.listProviders({
});
```
- `generate(...)`:使用已配置的图像生成 provider 链生成图像。
- `listProviders(...)`:列出可用的图像生成 providers 及其能力。
- `generate(...)`:使用已配置的图像生成提供商链生成图像。
- `listProviders(...)`:列出可用的图像生成提供商及其能力。
## Gateway 网关 HTTP 路由
@ -493,44 +494,44 @@ api.registerHttpRoute({
路由字段:
- `path`Gateway 网关 HTTP 服务器下的路由路径。
- `auth`:必填。使用 `"gateway"` 以要求常规 Gateway 网关认证,或使用 `"plugin"` 以启用插件管理的认证/Webhook 校验
- `auth`:必填。使用 `"gateway"` 以要求普通 Gateway 网关认证,或使用 `"plugin"` 以启用插件管理的认证/webhook 验证
- `match`:可选。`"exact"`(默认)或 `"prefix"`
- `replaceExisting`:可选。允许同一个插件替换自己现有的路由注册。
- `replaceExisting`:可选。允许同一个插件替换自己现有的路由注册。
- `handler`:当路由处理了请求时返回 `true`
说明:
- `api.registerHttpHandler(...)` 已被移除,并会导致插件加载错误。请改用 `api.registerHttpRoute(...)`
- 插件路由必须显式声明 `auth`
- 精确的 `path + match` 冲突会被拒绝,除非设置了 `replaceExisting: true`且一个插件不能替换另一个插件的路由。
- 不同 `auth` 级别的重叠路由会被拒绝。仅在相同认证级别内保留 `exact`/`prefix` 的贯穿链。
- `auth: "plugin"` 路由**不会**自动获得运维者运行时作用域。它们用于插件管理的 Webhook/签名校验,而不是特权 Gateway 网关辅助调用。
- 精确的 `path + match` 冲突会被拒绝,除非设置了 `replaceExisting: true`且一个插件不能替换另一个插件的路由。
- 具有不同 `auth` 级别的重叠路由会被拒绝。仅在相同认证级别下保留 `exact`/`prefix` 贯穿链。
- `auth: "plugin"` 路由**不会**自动获得操作员运行时作用域。它们用于插件管理的 webhook/签名验证,而不是特权 Gateway 网关辅助调用。
- `auth: "gateway"` 路由会在 Gateway 网关请求运行时作用域内运行,但该作用域是有意保守的:
- 共享密钥 bearer 认证(`gateway.auth.mode = "token"` / `"password"`)会将插件路由运行时作用域固定为 `operator.write`,即使调用方发送了 `x-openclaw-scopes`
- 受信任的带身份 HTTP 模式(例如 `trusted-proxy` 或私有入口上的 `gateway.auth.mode = "none"`)仅在请求头显式存在时才会接受 `x-openclaw-scopes`
- 如果这些带身份的插件路由请求缺少 `x-openclaw-scopes`,运行时作用域会回退 `operator.write`
- 实用规则:不要假设经 Gateway 网关认证的插件路由天然就是隐式管理员表面。如果你的路由需要仅管理员可用的行为,请要求使用带身份的认证模式,并记录显式的 `x-openclaw-scopes` 请求头契约。
- 共享密钥 bearer 认证(`gateway.auth.mode = "token"` / `"password"`)会将插件路由运行时作用域固定为 `operator.write`,即使调用方发送了 `x-openclaw-scopes`
- 受信任的带身份 HTTP 模式(例如 `trusted-proxy` 或私有入口上的 `gateway.auth.mode = "none"`)仅在请求头显式存在时才会接受 `x-openclaw-scopes`
- 如果这些带身份的插件路由请求缺少 `x-openclaw-scopes`,运行时作用域会回退 `operator.write`
- 实用规则:不要假设一个使用 gateway 认证的插件路由就是隐式管理员表面。如果你的路由需要仅管理员可用的行为,请要求使用带身份的认证模式,并记录显式的 `x-openclaw-scopes` 请求头契约。
## 插件 SDK 导入路径
在编写新插件时,请使用较窄的 SDK 子路径,而不是单体式的 `openclaw/plugin-sdk` 根 barrel。核心子路径如下
在编写新插件时,请使用更窄的 SDK 子路径,而不是单体的 `openclaw/plugin-sdk` 根 barrel。Core 子路径包括
| 子路径 | 用途 |
| ----------------------------------- | -------------------------------------------------- |
| `openclaw/plugin-sdk/plugin-entry` | 插件注册原语 |
| `openclaw/plugin-sdk/channel-core` | 渠道入口/构建辅助方法 |
| `openclaw/plugin-sdk/core` | 通用共享辅助方法和 umbrella 契约 |
| `openclaw/plugin-sdk/config-schema` | 根 `openclaw.json` Zod 模式`OpenClawSchema` |
| `openclaw/plugin-sdk/channel-core` | 渠道入口/构建辅助工具 |
| `openclaw/plugin-sdk/core` | 通用共享辅助工具和 umbrella 契约 |
| `openclaw/plugin-sdk/config-schema` | 根 `openclaw.json` Zod schema`OpenClawSchema` |
渠道插件可从一组窄接缝中选择——`channel-setup`、
渠道插件可从一组接缝中选择——`channel-setup`、
`setup-runtime`、`setup-adapter-runtime`、`setup-tools`、`channel-pairing`、
`channel-contract`、`channel-feedback`、`channel-inbound`、`channel-lifecycle`、
`channel-reply-pipeline`、`command-auth`、`secret-input`、`webhook-ingress`、
`channel-targets``channel-actions`批行为应收敛到单一的
`approvalCapability` 契约,而不是混杂在无关的插件字段之间。
参见 [渠道插件](/zh-CN/plugins/sdk-channel-plugins)。
`channel-targets``channel-actions`。批行为应统一收敛到单一的
`approvalCapability` 契约,而不是分散混用在不相关的插件字段中。参见
[渠道插件](/zh-CN/plugins/sdk-channel-plugins)。
运行时和配置辅助方法位于对应的聚焦 `*-runtime` 子路径下
运行时和配置辅助工具位于匹配的聚焦 `*-runtime` 子路径下
`approval-runtime`、`agent-runtime`、`lazy-runtime`、`directory-runtime`、
`text-runtime`、`runtime-store`、`system-event-runtime`、`heartbeat-runtime`、
`channel-activity-runtime` 等)。优先使用 `config-types`
@ -543,85 +544,85 @@ api.registerHttpRoute({
新代码应改为导入更窄的通用原语。
</Info>
仓库内部入口点(按每个内置插件软件包根目录划分
仓库内部入口点(按每个内置插件 package 根目录
- `index.js` —— 内置插件入口
- `api.js` —— 辅助方法/类型 barrel
- `api.js` —— 辅助工具/类型 barrel
- `runtime-api.js` —— 仅运行时 barrel
- `setup-entry.js` —— 设置插件入口
外部插件只导入 `openclaw/plugin-sdk/*` 子路径。绝不要从核心或其他插件中导入另一个插件包的 `src/*`。由 facade 加载的入口点会在存在时优先使用当前活动的运行时配置快照,然后回退到磁盘上的已解析配置文件。
外部插件只导入 `openclaw/plugin-sdk/*` 子路径。绝不要从 core 或其他插件中导入另一个插件 package 的 `src/*`。通过 facade 加载的入口点会优先使用当前活动的运行时配置快照,如果不存在,则回退到磁盘上的已解析配置文件。
`image-generation`、`media-understanding` 和 `speech` 这样的能力专用子路径之所以存在,是因为内置插件目前正在使用它们。它们并不自动构成长期冻结的外部契约——在依赖这些路径时,请查看相关的 SDK 参考页
`image-generation`、`media-understanding` 和 `speech` 这样的能力专用子路径之所以存在,是因为内置插件目前正在使用它们。它们并不自动意味着长期冻结的外部契约——在依赖这些路径时,请查看相关的 SDK 参考页。
## 消息工具模式
## 消息工具 schema
对于表情反应、已读和投票等非消息原语,插件应拥有特定于渠道的 `describeMessageTool(...)` 模式贡献。共享发送呈现应使用通用的 `MessagePresentation` 契约,而不是 provider 原生的按钮、组件、块或卡片字段。
关于契约、回退规则、provider 映射和插件作者检查清单,请参见 [Message Presentation](/zh-CN/plugins/message-presentation)。
对于反应、已读和投票等非消息原语,插件应拥有渠道特定的 `describeMessageTool(...)` schema 贡献。共享发送呈现应使用通用 `MessagePresentation` 契约,而不是提供商原生的按钮、组件、块或卡片字段。有关契约、回退规则、提供商映射和插件作者清单,请参见 [Message Presentation](/zh-CN/plugins/message-presentation)。
具备发送能力的插件会通过消息能力声明它们能渲染的内容:
具备发送能力的插件通过消息能力声明它们可以渲染的内容:
- `presentation`:用于语义呈现块(`text`、`context`、`divider`、`buttons`、`select`
- `presentation`:用于语义呈现块(`text`、`context`、`divider`、`buttons`、`select`
- `delivery-pin`:用于固定投递请求
核心决定是原生渲染该呈现,还是将其降级为文本。不要从通用消息工具中暴露 provider 原生 UI 逃生口。面向旧版原生模式的已弃用 SDK 辅助方法仍为现有第三方插件导出,但新插件不应使用它们。
Core 会决定是原生渲染该呈现,还是将其降级为文本。不要从通用消息工具中暴露提供商原生 UI 逃生口。为旧版原生 schema 提供的已弃用 SDK 辅助工具仍会导出以支持现有第三方插件,但新插件不应使用它们。
## 渠道目标解析
渠道插件应拥有特定于渠道的目标语义。保持共享出站宿主的通用性,并使用消息适配器表面处理 provider 规则:
渠道插件应拥有渠道特定的目标语义。保持共享出站主机通用,并使用消息适配器表面来承载提供商规则:
- `messaging.inferTargetChatType({ to })` 决定规范化目标在目录查找前应被视为 `direct`、`group` 还是 `channel`
- `messaging.targetResolver.looksLikeId(raw, normalized)` 告诉核心某个输入是否应直接跳到类似 id 的解析,而不是目录搜索
- `messaging.targetResolver.resolveTarget(...)`插件的回退路径,用于核心在规范化之后或目录未命中之后需要最终的 provider 自有解析时使用
- `messaging.resolveOutboundSessionRoute(...)` 在目标解析完成后负责构建 provider 特定的会话路由
- `messaging.inferTargetChatType({ to })` 决定规范化目标在目录查找前应被视为 `direct`、`group` 还是 `channel`
- `messaging.targetResolver.looksLikeId(raw, normalized)` 告诉 core 某个输入是否应跳过目录搜索,直接进入类似 id 的解析
- `messaging.targetResolver.resolveTarget(...)`在规范化之后或目录未命中之后core 需要最终由提供商拥有的解析时所使用的插件回退
- `messaging.resolveOutboundSessionRoute(...)` 在目标被解析后拥有提供商特定的会话路由构造逻辑
推荐分:
推荐分:
- 对于应在搜索 peers/groups 之前发生的分类决策,使用 `inferTargetChatType`
- 对于“将其视为显式/原生目标 id”的判断,使用 `looksLikeId`
- 将 `resolveTarget` 用于 provider 特定的规范化回退,而不是广泛的目录搜索
- 将 chat id、thread id、JID、handle 和 room id 这类 provider 原生 id 保留在 `target` 值或 provider 特定参数中,而不是放在通用 SDK 字段里
- 对于“将其视为显式/原生目标 id”的检查,使用 `looksLikeId`
- 将 `resolveTarget` 用于提供商特定的规范化回退,而不是广泛的目录搜索
- 将 chat id、thread id、JID、handle 和 room id 这类提供商原生 id 保留在 `target` 值或提供商特定参数中,而不是放进通用 SDK 字段
## 配置支持的目录
## 基于配置的目录
从配置派生目录条目的插件应将该逻辑保留在插件中,并复用
`openclaw/plugin-sdk/directory-runtime` 中的共享辅助方法
如果插件从配置派生目录条目,应将该逻辑保留在插件中,并复用
`openclaw/plugin-sdk/directory-runtime` 中的共享辅助工具
当渠道需要配置支持的 peers/groups 时,请使用此方式,例如:
适用于渠道需要基于配置的 peers/groups 的情况,例如:
- 由 allowlist 驱动的私信 peers
- 已配置的渠道/群组映射
- 账户作用域提供的静态目录回退
- 账户作用域的静态目录回退
`directory-runtime` 中的共享辅助方法只处理通用操作:
`directory-runtime` 中的共享辅助工具只处理通用操作:
- 查询过滤
- 限制应用
- 去重/规范化辅助方法
- 限制应用
- 去重/规范化辅助工具
- 构建 `ChannelDirectoryEntry[]`
特定于渠道的账户检查和 id 规范化应保留在插件实现中。
渠道特定的账户检查和 id 规范化应保留在插件实现中。
## Provider 目录
## 提供商目录
Provider 插件可以通过
提供商插件可以通过
`registerProvider({ catalog: { run(...) { ... } } })` 为推理定义模型目录。
`catalog.run(...)` 返回与 OpenClaw 写入 `models.providers` 相同的形态:
`catalog.run(...)` 返回与 OpenClaw 写入
`models.providers` 相同的形状:
- `{ provider }`:一个 provider 条目
- `{ providers }`:多个 provider 条目
- `{ provider }`:一个提供商条目
- `{ providers }`:多个提供商条目
当插件拥有 provider 特定的模型 id、base URL 默认值或受认证控制的模型元数据时,请使用 `catalog`
当插件拥有提供商特定的模型 id、base URL 默认值或受认证限制的模型元数据时,请使用 `catalog`
`catalog.order` 控制插件目录相对于 OpenClaw 内置隐式 providers 的合并时机:
`catalog.order` 控制插件目录相对于 OpenClaw 内置隐式提供商的合并时机:
- `simple`:普通 API 密钥或环境变量驱动的 providers
- `profile`:存在 auth profiles 时出现的 providers
- `paired`会合成多个相关 provider 条目的 providers
- `late`:最后一轮,在其他隐式 providers 之后
- `simple`:普通 API 密钥或环境变量驱动的提供商
- `profile`:存在认证配置文件时出现的提供商
- `paired`合成多个相关提供商条目的提供商
- `late`:最后一轮,在其他隐式提供商之后
合并的 provider 会在键冲突时胜出,因此插件可以有意用相同的 provider id 覆盖一个内置 provider 条目。
出现的提供商会在键冲突时获胜,因此插件可以有意用相同提供商 id 覆盖内置提供商条目。
兼容性:
@ -630,32 +631,31 @@ Provider 插件可以通过
## 只读渠道检查
如果你的插件注册了一个渠道,优先实现
`plugin.config.inspectAccount(cfg, accountId)`,并同时保留 `resolveAccount(...)`
如果你的插件注册了一个渠道,优先实现
`plugin.config.inspectAccount(cfg, accountId)`,并同时实现 `resolveAccount(...)`
原因:
- `resolveAccount(...)` 是运行时路径。它可以假设凭证已完全实体化,并且在缺少必需密钥时快速失败。
- 只读命令路径,例如 `openclaw status`、`openclaw status --all`、
`openclaw channels status`、`openclaw channels resolve` 以及 doctor/配置修复流程,不应为了描述配置而必须实体化运行时凭证。
- `resolveAccount(...)` 是运行时路径。它可以假定凭证已被完全物化,并且在缺少所需 secret 时快速失败。
- 像 `openclaw status`、`openclaw status --all`、`openclaw channels status`、`openclaw channels resolve` 以及 doctor/配置修复流程这样的只读命令路径,不应只是为了描述配置就去物化运行时凭证。
推荐的 `inspectAccount(...)` 行为:
- 返回描述性的账户状态。
- 返回描述性的账户状态。
- 保留 `enabled``configured`
- 在相关时包含凭证来源/状态字段,例如:
- `tokenSource`、`tokenStatus`
- `botTokenSource`、`botTokenStatus`
- `appTokenSource`、`appTokenStatus`
- `signingSecretSource`、`signingSecretStatus`
- 你无需为了报告只读可用性而返回原始令牌值。返回 `tokenStatus: "available"`(以及匹配的来源字段)就足以支持状态类命令。
- 当凭证通过 SecretRef 配置但在当前命令路径中不可用时,使用 `configured_unavailable`
- 为了报告只读可用性,你不需要返回原始令牌值。返回 `tokenStatus: "available"`(以及对应的来源字段)就足以支持类似状态命令。
- 当凭证通过 SecretRef 配置但在当前命令路径中不可用时,使用 `configured_unavailable`
这样,只读命令就能报告“已配置,但在此命令路径中不可用”,而不是崩溃或错误地将该账户报告为未配置。
这样可以让只读命令报告“已配置,但在此命令路径中不可用”,而不是崩溃或错误地将该账户报告为未配置。
## 软件包打包 bundles
## 软件包打包
插件目录可以包含一个带有 `openclaw.extensions``package.json`
一个插件目录可以包含带有 `openclaw.extensions``package.json`
```json
{
@ -667,39 +667,38 @@ Provider 插件可以通过
}
```
每个条目都会成为一个插件。如果该打包列出多个扩展,插件 id 会变为 `name/<fileBase>`
每个条目都会变成一个插件。如果该 pack 列出多个 extensions则插件 id 会变成 `name/<fileBase>`
如果你的插件导入了 npm 依赖,请在该目录中安装它们,以便 `node_modules` 可用(`npm install` / `pnpm install`)。
如果你的插件导入了 npm 依赖,请在该目录中安装它们,以确保 `node_modules` 可用(`npm install` / `pnpm install`)。
安全护栏:每个 `openclaw.extensions` 条目在解析符号链接后都必须保持在插件目录内部。任何逃逸出软件包目录的条目都会被拒绝。
安全护栏:每个 `openclaw.extensions` 条目在解析符号链接后都必须保持在插件目录内部。逃逸出 package 目录的条目会被拒绝。
安全说明:`openclaw plugins install` 会使用项目本地的 `npm install --omit=dev --ignore-scripts` 安装插件依赖(无生命周期脚本、运行时无开发依赖),并忽略继承的全局 npm 安装设置。请保持插件依赖树为“纯 JS/TS”并避免依赖需要 `postinstall` 构建的软件包
安全说明:`openclaw plugins install` 会使用项目本地的 `npm install --omit=dev --ignore-scripts` 安装插件依赖(无生命周期脚本、运行时无开发依赖),并忽略继承的全局 npm 安装设置。请保持插件依赖树为“纯 JS/TS”并避免需要 `postinstall` 构建的 package
可选`openclaw.setupEntry` 可以指向一个轻量级的仅设置模块。当 OpenClaw 需要为已禁用的渠道插件提供设置表面,或者某个渠道插件已启用但仍未配置时,它会加载 `setupEntry`,而不是完整的插件入口。这样当你的主插件入口还会接入工具、钩子或其他仅运行时代码时,就能让启动和设置更轻量。
可选:`openclaw.setupEntry` 可以指向一个轻量级、仅用于设置的模块。当 OpenClaw 需要为一个已禁用的渠道插件提供设置表面时,或者当某个渠道插件已启用但尚未配置时,它会加载 `setupEntry`,而不是完整的插件入口。这样在主插件入口还会接线工具、钩子或其他仅运行时代码时,可以让启动和设置更轻量。
可选项:`openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen`
可以让渠道插件在 Gateway 网关的监听前启动阶段也进入相同的 `setupEntry`
路径,即使该渠道已经完成配置。
可选:`openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen`
可以让某个渠道插件在 Gateway 网关预监听启动阶段也选择相同的 `setupEntry` 路径,即使该渠道已经配置完成。
仅当 `setupEntry` 完全覆盖 Gateway 网关开始监听之前必须存在的启动表面时,才使用此项。实际上,这意味着设置入口必须注册启动所依赖的每一项渠道有能力,例如:
只有当 `setupEntry` 完全覆盖了 Gateway 网关开始监听之前必须存在的启动表面时,才使用此项。实际上,这意味着设置入口必须注册启动所依赖的每一项渠道有能力,例如:
- 渠道注册本身
- 任何必须在 Gateway 网关开始监听前可用的 HTTP 路由
- 任何必须在 Gateway 网关开始监听前可用的 HTTP 路由
- 任何必须在同一时间窗口内存在的 Gateway 网关方法、工具或服务
如果你的完整入口仍然拥有任何必需的启动能力,请不要启用此标志。保持插件使用默认行为,让 OpenClaw 在启动期间加载完整入口。
内置渠道还可以发布仅设置的契约表面辅助方法,以便核心在完整渠道运行时加载前进行查询。当前的设置提升表面是:
内置渠道还可以发布仅设置阶段的契约表面辅助工具,供 core 在完整渠道运行时加载之前查询。当前的设置提升表面是:
- `singleAccountKeysToMove`
- `namedAccountPromotionKeys`
- `resolveSingleAccountPromotionTarget(...)`
核心需要在不加载完整插件入口的情况下,将旧版单账户渠道配置提升到 `channels.<id>.accounts.*` 时,会使用该表面。Matrix 是当前的内置示例:当已存在命名账户时,它只会将认证/bootstrap 键移动到一个已命名的提升账户中,并且可以保留一个已配置但非规范的默认账户键,而不是总是创建 `accounts.default`
core 需要在不加载完整插件入口的情况下,将旧版单账户渠道配置提升到 `channels.<id>.accounts.*` 时,就会使用这组表面。Matrix 是当前的内置示例:当命名账户已存在时,它只会将认证/引导键移动到一个已命名的提升账户中,并且它可以保留一个已配置的非规范默认账户键,而不是总是创建 `accounts.default`
这些 setup patch 适配器让内置契约表面发现保持惰性。导入时保持轻提升表面只会在首次使用时加载,而不会在模块导入时重新进入内置渠道启动流程。
这些设置补丁适配器让内置契约表面发现保持惰性。导入时开销保持轻;提升表面只会在首次使用时加载,而不会在模块导入时重新进入内置渠道启动流程。
当这些启动表面包含 Gateway 网关 RPC 方法时,请将它们保留在插件特定前缀下。核心管理员命名空间(`config.*`、`exec.approvals.*`、`wizard.*`、`update.*`)仍是保留项,并始终解析为 `operator.admin`,即使某个插件请求了更窄的作用域也是如此
当这些启动表面包含 Gateway 网关 RPC 方法时,请将它们保留在插件特定的前缀下。Core 管理员命名空间(`config.*`、`exec.approvals.*`、`wizard.*`、`update.*`)仍然是保留的,并且始终解析为 `operator.admin`,即使某个插件请求了更窄的作用域。
示例:
@ -718,7 +717,7 @@ Provider 插件可以通过
### 渠道目录元数据
渠道插件可以通过 `openclaw.channel` 声明设置/发现元数据,并通过 `openclaw.install` 声明安装提示。这样可以让核心目录保持无数据。
渠道插件可以通过 `openclaw.channel` 公布设置/发现元数据,并通过 `openclaw.install` 公布安装提示。这样可以让 core 目录保持无数据。
示例:
@ -746,19 +745,19 @@ Provider 插件可以通过
}
```
除最小示例外,有用的 `openclaw.channel` 字段包括:
最小示例外,其他有用的 `openclaw.channel` 字段包括:
- `detailLabel`:用于更丰富目录/状态表面的次级标签
- `docsLabel`:覆盖文档链接的链接文本
- `preferOver`:此目录条目应优先于其显示的低优先级插件/渠道 id
- `preferOver`:此目录条目应优先于的低优先级插件/渠道 id
- `selectionDocsPrefix`、`selectionDocsOmitLabel`、`selectionExtras`:选择表面文案控制
- `markdownCapable`:将该渠道标记为支持 Markdown以用于出站格式化决策
- `exposure.configured`:设置为 `false` 时,在已配置渠道列表表面中隐藏该渠道
- `exposure.setup`:设置为 `false` 时,在交互式设置/配置选择器中隐藏该渠道
- `exposure.docs`:将该渠道标记为内部/私有,以用于文档导航表面
- `showConfigured` / `showInSetup`:仍接受的旧版兼容别名;优先使用 `exposure`
- `quickstartAllowFrom`:让该渠道加入标准快速开始 `allowFrom` 流程
- `forceAccountBinding`:即使存在一个账户,也要求显式账户绑定
- `markdownCapable`:将渠道标记为支持 Markdown以供出站格式决策使用
- `exposure.configured`设置为 `false` 时,在已配置渠道列表表面中隐藏该渠道
- `exposure.setup`设置为 `false` 时,在交互式设置/配置选择器中隐藏该渠道
- `exposure.docs`在文档导航表面中将该渠道标记为内部/私有
- `showConfigured` / `showInSetup`出于兼容性仍接受的旧别名;优先使用 `exposure`
- `quickstartAllowFrom`:让该渠道选择加入标准快速开始 `allowFrom` 流程
- `forceAccountBinding`:即使存在一个账户,也要求显式账户绑定
- `preferSessionLookupForAnnounceTarget`:在解析公告目标时优先使用会话查找
OpenClaw 还可以合并**外部渠道目录**(例如 MPM 注册表导出)。将 JSON 文件放到以下任一位置:
@ -767,20 +766,20 @@ OpenClaw 还可以合并**外部渠道目录**(例如 MPM 注册表导出)
- `~/.openclaw/mpm/catalog.json`
- `~/.openclaw/plugins/catalog.json`
或者将 `OPENCLAW_PLUGIN_CATALOG_PATHS`(或 `OPENCLAW_MPM_CATALOG_PATHS`)指向一个或多个 JSON 文件(以逗号/分号/`PATH` 分隔)。每个文件应包含 `{ "entries": [ { "name": "@scope/pkg", "openclaw": { "channel": {...}, "install": {...} } } ] }`。解析器也接受 `"packages"``"plugins"` 作为 `"entries"` 键的旧别名。
或者将 `OPENCLAW_PLUGIN_CATALOG_PATHS`(或 `OPENCLAW_MPM_CATALOG_PATHS`)指向一个或多个 JSON 文件(以逗号/分号/`PATH` 分隔)。每个文件应包含 `{ "entries": [ { "name": "@scope/pkg", "openclaw": { "channel": {...}, "install": {...} } } ] }`。解析器也接受 `"packages"``"plugins"` 作为 `"entries"` 键的旧别名。
生成的渠道目录条目和 provider 安装目录条目会在原始 `openclaw.install` 块旁暴露规范化后的安装源事实。这些规范化事实会标识 npm spec 是否为精确版本还是浮动选择器、是否存在预期完整性元数据,以及本地源路径是否也可用。当目录/软件包身份已知时,如果解析出的 npm 软件包名称与该身份不一致,这些规范化事实会发出警告。它们还会在 `defaultChoice` 无效、指向不可用源,或存在 npm 完整性元数据但没有有效 npm 源时发出警告。使用方应将 `installSource` 视为附加的可选字段,这样手工构建的条目和目录 shim 就不必合成它。
样一来,新手引导和诊断就可以在不导入插件运行时的情况下解释源平面状态。
生成的渠道目录条目和提供商安装目录条目会在原始 `openclaw.install` 块旁边暴露规范化后的安装源信息。这些规范化信息用于标识 npm 规格是精确版本还是浮动选择器、是否存在预期完整性元数据,以及本地源路径是否也可用。当目录/package 身份已知时,这些规范化信息会在解析出的 npm package 名称偏离该身份时发出警告。它们还会在 `defaultChoice` 无效或指向不可用源时发出警告,以及在存在 npm 完整性元数据但没有有效 npm 源时发出警告。使用方应将 `installSource` 视为附加的可选字段,这样手工构建的条目和目录 shim 就不必合成它。
使得新手引导和诊断能够在不导入插件运行时的情况下解释源平面状态。
官方外部 npm 条目应优先使用精确的 `npmSpec` `expectedIntegrity`。裸软件包名称和 dist-tag 仍可出于兼容性继续使用,但它们会暴露源平面警告,以便目录逐步转向锁定版本且带完整性校验的安装方式,而不会破坏现有插件。当新手引导从本地目录路径安装时,它会记录一个托管插件索引条目,带有 `source: "path"`,并在可能时记录相对于工作区的 `sourcePath`。绝对操作加载路径仍保留在 `plugins.load.paths` 中;安装记录会避免将本地工作站路径重复写入长期配置。这使得本地开发安装对源平面诊断可见,同时不会增加第二个原始文件系统路径泄露表面。持久化的 `plugins/installs.json` 插件索引是安装源的事实来源,并且可以在不加载插件运行时模块的情况下刷新。其 `installRecords` 映射即使在插件清单缺失或无效时也能持久保留;其 `plugins` 数组则是可重建的清单/缓存视图。
官方外部 npm 条目应优先使用精确的 `npmSpec``expectedIntegrity`。裸 package 名称和 dist-tag 出于兼容性仍可使用,但它们会暴露源平面警告,以便目录能够逐步迁移到固定版本、带完整性校验的安装方式,而不会破坏现有插件。当新手引导从本地目录路径安装时,它会记录一个受管插件索引条目,其中 `source: "path"`,并尽可能使用相对于工作区的 `sourcePath`。绝对的实际加载路径保留在 `plugins.load.paths` 中;安装记录会避免将本地工作站路径重复写入长期配置。这样可使本地开发安装对源平面诊断保持可见,而无需增加第二个原始文件系统路径暴露表面。持久化的 `plugins/installs.json` 插件索引是安装源的真实来源,并且可以在不加载插件运行时模块的情况下刷新。它的 `installRecords` 映射即使在插件 manifest 缺失或无效时也是持久的;它的 `plugins` 数组则是可重建的 manifest/缓存视图。
## 上下文引擎插件
上下文引擎插件拥有会话上下文编排能力,包括摄取、组装和压缩。通过
`api.registerContextEngine(id, factory)` 从你的插件中注册它们,然后使用
上下文引擎插件拥有会话上下文编排,负责摄取、组装和压缩。请在你的插件中通过
`api.registerContextEngine(id, factory)` 注册它们,然后使用
`plugins.slots.contextEngine` 选择活动引擎。
当你的插件需要替换或扩展默认上下文流水线,而不仅仅是添加记忆搜索或钩子时,请使用此方式
当你的插件需要替换或扩展默认上下文流水线,而不仅仅是添加内存搜索或钩子时,请使用它
```ts
import { buildMemorySystemPromptAddition } from "openclaw/plugin-sdk/core";
@ -808,7 +807,7 @@ export default function (api) {
}
```
如果你的引擎**不**拥有压缩算法,请保持 `compact()` 已实现,并显式委托
如果你的引擎**不**拥有压缩算法,请保持实现 `compact()`,并显式委托:
```ts
import {
@ -843,55 +842,55 @@ export default function (api) {
}
```
## 添加新能力
## 添加新能力
当插件需要当前 API 无法适配的行为时,不要通过私有深入访问来绕过插件系统。应添加缺失的能力。
当插件需要当前 API 无法覆盖的行为时,不要通过私有深入访问绕过插件系统。应当添加缺失的能力。
推荐顺序:
1. 定义核心契约
决定哪些共享行为应由核心拥有:策略、回退、配置合并、
生命周期、面向渠道的语义,以及运行时辅助方法形态
1. 定义 core 契约
决定哪些共享行为应由 core 拥有:策略、回退、配置合并、
生命周期、面向渠道的语义,以及运行时辅助工具形状
2. 添加类型化的插件注册/运行时表面
用最小且有用的类型化能力表面扩展 `OpenClawPluginApi` 和/或 `api.runtime`
3. 接入核心 + 渠道/功能使用方
渠道和功能插件应通过核心消费新能力,
而不是直接导入某个供应商实现。
4. 注册供应商实现
然后由供应商插件将其后端注册到该能力上
以最小但有用的类型化能力表面扩展 `OpenClawPluginApi` 和/或 `api.runtime`
3. 连接 core + 渠道/功能使用方
渠道和功能插件应通过 core 使用这项新能力,
而不是直接导入某个商实现。
4. 注册商实现
然后由厂商插件针对该能力注册其后端实现
5. 添加契约覆盖
添加测试,以便随着时间推移,所有权和注册形态仍保持明确
添加测试,使所有权和注册形状能够长期保持显式
正是 OpenClaw 在保持明确主张的同时,不会被硬编码为某个 provider 世界观的方式。有关具体文件清单和完整示例,请参阅 [能力扩展手册](/zh-CN/plugins/architecture)。
就是 OpenClaw 在保持明确主张的同时,不会被硬编码为某个提供商世界观的方式。有关具体的文件清单和完整示例,请参见 [能力扩展手册](/zh-CN/plugins/architecture)。
### 能力检查清单
### 能力清单
当你添加一个新能力时,实现通常应同时及以下表面:
当你添加一个新能力时,实现通常应同时及以下表面:
- `src/<capability>/types.ts` 中的核心契约类型
- `src/<capability>/runtime.ts` 中的核心运行器/运行时辅助方法
- `src/<capability>/types.ts` 中的 core 契约类型
- `src/<capability>/runtime.ts` 中的 core 运行器/运行时辅助工具
- `src/plugins/types.ts` 中的插件 API 注册表面
- `src/plugins/registry.ts` 中的插件注册表接线
- 当功能/渠道插件需要消费它时,放在 `src/plugins/runtime/*` 中的插件运行时暴露
- `src/test-utils/plugin-registration.ts` 中的捕获/测试辅助方法
- 当功能/渠道插件需要使用它时,位于 `src/plugins/runtime/*` 中的插件运行时暴露
- `src/test-utils/plugin-registration.ts` 中的捕获/测试辅助工具
- `src/plugins/contracts/registry.ts` 中的所有权/契约断言
- `docs/` 中面向运维者/插件的文档
- `docs/` 中面向操作员/插件的文档
如果这些表面中有某个缺失,通常说明该能力尚未完全集成。
如果其中某个表面缺失,通常说明这项能力尚未完全集成。
### 能力模板
最小模式:
```ts
// 核心契约
// core contract
export type VideoGenerationProviderPlugin = {
id: string;
label: string;
generateVideo: (req: VideoGenerationRequest) => Promise<VideoGenerationResult>;
};
// 插件 API
// plugin API
api.registerVideoGenerationProvider({
id: "openai",
label: "OpenAI",
@ -900,7 +899,7 @@ api.registerVideoGenerationProvider({
},
});
// 面向功能/渠道插件的共享运行时辅助方法
// feature/channel 插件的共享运行时辅助工具
const clip = await api.runtime.videoGeneration.generate({
prompt: "Show the robot walking through the lab.",
cfg,
@ -913,16 +912,16 @@ const clip = await api.runtime.videoGeneration.generate({
expect(findVideoGenerationProviderIdsForPlugin("openai")).toEqual(["openai"]);
```
这样规则就简单:
这样规则就保持简单:
- 核心拥有能力契约 + 编排
- 供应商插件拥有供应商实现
- 功能/渠道插件消费运行时辅助方法
- 契约测试让所有权保持明确
- core 拥有能力契约 + 编排
- 厂商插件拥有厂商实现
- 功能/渠道插件使用运行时辅助工具
- 契约测试使所有权保持显式
## 相关内容
- [插件架构](/zh-CN/plugins/architecture) —— 公开的能力模型和形态
- [插件架构](/zh-CN/plugins/architecture) —— 公开能力模型和形状
- [插件 SDK 子路径](/zh-CN/plugins/sdk-subpaths)
- [插件 SDK 设置](/zh-CN/plugins/sdk-setup)
- [构建插件](/zh-CN/plugins/building-plugins)

View File

@ -1,36 +1,31 @@
---
read_when:
- 你想创建一个新的 OpenClaw 插件
- 你需要一份插件开发的快速开始指南
- 你正在为 OpenClaw 添加新的渠道、提供商、工具或其他能力
- 你想创建一个新的 OpenClaw 插件
- 你需要一份用于插件开发的快速开始指南
- 你正在为 OpenClaw 添加一个新的渠道、提供商、工具或其他能力
sidebarTitle: Getting Started
summary: 几分钟内创建你的第一个 OpenClaw 插件
summary: 几分钟内创建你的第一个 OpenClaw 插件
title: 构建插件
x-i18n:
generated_at: "2026-04-27T12:54:09Z"
generated_at: "2026-04-28T02:18:27Z"
model: gpt-5.4
provider: openai
source_hash: 7bdae7b858a04f8c8b65be8b909aba528fc7ae0781856161d7b09e9bed8442e3
source_hash: 25b2f3f05a468d0ce017eb67877511f0e551f62322f16a00fee9f8b367a25494
source_path: plugins/building-plugins.md
workflow: 15
---
插件通过新增能力来扩展 OpenClaw渠道、模型提供商、
语音、实时转写、实时语音、媒体理解、图像生成、视频
生成、网页抓取、网页搜索、智能体工具,或这些能力的任意组合。
插件通过新增能力来扩展 OpenClaw渠道、模型提供商、语音、实时转录、实时语音、媒体理解、图像生成、视频生成、网页抓取、网页搜索、智能体工具或这些能力的任意组合。
你不需要将插件添加到 OpenClaw 仓库中。请发布到
[ClawHub](/zh-CN/tools/clawhub) 或 npm用户可使用
`openclaw plugins install <package-name>` 安装。OpenClaw 会优先尝试 ClawHub
并自动回退到 npm。
你不需要把你的插件添加到 OpenClaw 仓库中。发布到 [ClawHub](/zh-CN/tools/clawhub) 或 npm然后用户使用 `openclaw plugins install <package-name>` 安装即可。OpenClaw 会优先尝试 ClawHub并在失败时自动回退到 npm。
## 前提条件
- Node >= 22,以及一个包管理器npm 或 pnpm
- Node >= 22一个包管理器npm 或 pnpm
- 熟悉 TypeScriptESM
- 对于仓库内插件:已克隆仓库并执行 `pnpm install`
- 对于仓库内插件:已克隆仓库并完成 `pnpm install`
## 这是什么类型的插件?
## 你要构建哪种插件?
<CardGroup cols={3}>
<Card title="渠道插件" icon="messages-square" href="/zh-CN/plugins/sdk-channel-plugins">
@ -40,20 +35,18 @@ x-i18n:
添加一个模型提供商LLM、代理或自定义端点
</Card>
<Card title="工具 / 钩子插件" icon="wrench" href="/zh-CN/plugins/hooks">
注册智能体工具、事件钩子或服务继续阅读下文
注册智能体工具、事件钩子或服务——继续阅读下文
</Card>
</CardGroup>
对于在新手引导/设置运行时不保证已安装的渠道插件,请使用
`openclaw/plugin-sdk/channel-setup` 中的 `createOptionalChannelSetupSurface(...)`
它会生成一个设置适配器 + 向导组合,能够声明安装要求,并在插件安装前对真实配置写入采取失败关闭方式。
对于某个渠道插件,如果在新手引导 / 设置运行时不能保证它已安装,请使用 `openclaw/plugin-sdk/channel-setup` 中的 `createOptionalChannelSetupSurface(...)`。它会生成一个设置适配器 + 向导配对,用于提示安装要求,并在插件安装完成之前,对真实配置写入采取失败关闭策略。
## 快速开始:工具插件
本演练创建一个注册智能体工具的最小插件。渠道插件和提供商插件有各自的专用指南,见上方链接。
本演练创建一个注册智能体工具的最小插件。渠道插件和提供商插件有上方链接的专门指南
<Steps>
<Step title="创建 package 和清单">
<Step title="创建和清单">
<CodeGroup>
```json package.json
{
@ -78,7 +71,10 @@ x-i18n:
{
"id": "my-plugin",
"name": "My Plugin",
"description": "为 OpenClaw 添加一个自定义工具",
"description": "Adds a custom tool to OpenClaw",
"activation": {
"onStartup": true
},
"configSchema": {
"type": "object",
"additionalProperties": false
@ -87,9 +83,7 @@ x-i18n:
```
</CodeGroup>
每个插件都需要一个清单,即使没有配置也一样。完整 schema 请参见
[Manifest](/zh-CN/plugins/manifest)。标准的 ClawHub
发布片段位于 `docs/snippets/plugin-publish/`
每个插件都需要一个清单,即使没有任何配置也是如此;并且每个插件都应该有意识地声明 `activation.onStartup`。运行时注册的工具需要在启动时导入,因此本示例将其设置为 `true`。完整 schema 请参见 [Manifest](/zh-CN/plugins/manifest)。规范的 ClawHub 发布片段位于 `docs/snippets/plugin-publish/`
</Step>
@ -117,9 +111,7 @@ x-i18n:
});
```
`definePluginEntry` 用于非渠道插件。对于渠道,请使用
`defineChannelPluginEntry` — 请参见 [Channel Plugins](/zh-CN/plugins/sdk-channel-plugins)。
完整的入口点选项请参见 [入口点](/zh-CN/plugins/sdk-entrypoints)。
`definePluginEntry` 用于非渠道插件。对于渠道,请使用 `defineChannelPluginEntry`——参见 [Channel Plugins](/zh-CN/plugins/sdk-channel-plugins)。有关完整入口点选项,请参见 [Entry Points](/zh-CN/plugins/sdk-entrypoints)。
</Step>
@ -133,10 +125,9 @@ x-i18n:
openclaw plugins install clawhub:@myorg/openclaw-my-plugin
```
对于像 `@myorg/openclaw-my-plugin` 这样的裸 package 说明,
OpenClaw 也会先检查 ClawHub再检查 npm。
对于像 `@myorg/openclaw-my-plugin` 这样的裸包规范OpenClaw 也会先检查 ClawHub再检查 npm。
**仓库内插件:** 放在内置插件工作区树下会被自动发现。
**仓库内插件:** 放在内置插件工作区树下——会被自动发现。
```bash
pnpm test -- <bundled-plugin-root>/my-plugin/
@ -151,66 +142,57 @@ x-i18n:
| 能力 | 注册方法 | 详细指南 |
| ---------------------- | ------------------------------------------------ | ------------------------------------------------------------------------------- |
| 文本推理LLM | `api.registerProvider(...)` | [提供商插件](/zh-CN/plugins/sdk-provider-plugins) |
| CLI 推理后端 | `api.registerCliBackend(...)` | [CLI 后端](/zh-CN/gateway/cli-backends) |
| 渠道 / 消息 | `api.registerChannel(...)` | [渠道插件](/zh-CN/plugins/sdk-channel-plugins) |
| 语音TTS/STT | `api.registerSpeechProvider(...)` | [提供商插件](/zh-CN/plugins/sdk-provider-plugins#step-5-add-extra-capabilities) |
| 实时转写 | `api.registerRealtimeTranscriptionProvider(...)` | [提供商插件](/zh-CN/plugins/sdk-provider-plugins#step-5-add-extra-capabilities) |
| 实时语音 | `api.registerRealtimeVoiceProvider(...)` | [提供商插件](/zh-CN/plugins/sdk-provider-plugins#step-5-add-extra-capabilities) |
| 媒体理解 | `api.registerMediaUnderstandingProvider(...)` | [提供商插件](/zh-CN/plugins/sdk-provider-plugins#step-5-add-extra-capabilities) |
| 图像生成 | `api.registerImageGenerationProvider(...)` | [提供商插件](/zh-CN/plugins/sdk-provider-plugins#step-5-add-extra-capabilities) |
| 音乐生成 | `api.registerMusicGenerationProvider(...)` | [提供商插件](/zh-CN/plugins/sdk-provider-plugins#step-5-add-extra-capabilities) |
| 视频生成 | `api.registerVideoGenerationProvider(...)` | [提供商插件](/zh-CN/plugins/sdk-provider-plugins#step-5-add-extra-capabilities) |
| 网页抓取 | `api.registerWebFetchProvider(...)` | [提供商插件](/zh-CN/plugins/sdk-provider-plugins#step-5-add-extra-capabilities) |
| 网页搜索 | `api.registerWebSearchProvider(...)` | [提供商插件](/zh-CN/plugins/sdk-provider-plugins#step-5-add-extra-capabilities) |
| 文本推理LLM | `api.registerProvider(...)` | [Provider Plugins](/zh-CN/plugins/sdk-provider-plugins) |
| CLI 推理后端 | `api.registerCliBackend(...)` | [CLI Backends](/zh-CN/gateway/cli-backends) |
| 渠道 / 消息传递 | `api.registerChannel(...)` | [Channel Plugins](/zh-CN/plugins/sdk-channel-plugins) |
| 语音TTS/STT | `api.registerSpeechProvider(...)` | [Provider Plugins](/zh-CN/plugins/sdk-provider-plugins#step-5-add-extra-capabilities) |
| 实时转录 | `api.registerRealtimeTranscriptionProvider(...)` | [Provider Plugins](/zh-CN/plugins/sdk-provider-plugins#step-5-add-extra-capabilities) |
| 实时语音 | `api.registerRealtimeVoiceProvider(...)` | [Provider Plugins](/zh-CN/plugins/sdk-provider-plugins#step-5-add-extra-capabilities) |
| 媒体理解 | `api.registerMediaUnderstandingProvider(...)` | [Provider Plugins](/zh-CN/plugins/sdk-provider-plugins#step-5-add-extra-capabilities) |
| 图像生成 | `api.registerImageGenerationProvider(...)` | [Provider Plugins](/zh-CN/plugins/sdk-provider-plugins#step-5-add-extra-capabilities) |
| 音乐生成 | `api.registerMusicGenerationProvider(...)` | [Provider Plugins](/zh-CN/plugins/sdk-provider-plugins#step-5-add-extra-capabilities) |
| 视频生成 | `api.registerVideoGenerationProvider(...)` | [Provider Plugins](/zh-CN/plugins/sdk-provider-plugins#step-5-add-extra-capabilities) |
| 网页抓取 | `api.registerWebFetchProvider(...)` | [Provider Plugins](/zh-CN/plugins/sdk-provider-plugins#step-5-add-extra-capabilities) |
| 网页搜索 | `api.registerWebSearchProvider(...)` | [Provider Plugins](/zh-CN/plugins/sdk-provider-plugins#step-5-add-extra-capabilities) |
| 工具结果中间件 | `api.registerAgentToolResultMiddleware(...)` | [SDK 概览](/zh-CN/plugins/sdk-overview#registration-api) |
| 智能体工具 | `api.registerTool(...)` | 下文 |
| 自定义命令 | `api.registerCommand(...)` | [入口点](/zh-CN/plugins/sdk-entrypoints) |
| 智能体工具 | `api.registerTool(...)` | 下文 |
| 自定义命令 | `api.registerCommand(...)` | [Entry Points](/zh-CN/plugins/sdk-entrypoints) |
| 插件钩子 | `api.on(...)` | [插件钩子](/zh-CN/plugins/hooks) |
| 内部事件钩子 | `api.registerHook(...)` | [入口点](/zh-CN/plugins/sdk-entrypoints) |
| HTTP 路由 | `api.registerHttpRoute(...)` | [内部机制](/zh-CN/plugins/architecture-internals#gateway-http-routes) |
| CLI 子命令 | `api.registerCli(...)` | [入口点](/zh-CN/plugins/sdk-entrypoints) |
| 内部事件钩子 | `api.registerHook(...)` | [Entry Points](/zh-CN/plugins/sdk-entrypoints) |
| HTTP 路由 | `api.registerHttpRoute(...)` | [Internals](/zh-CN/plugins/architecture-internals#gateway-http-routes) |
| CLI 子命令 | `api.registerCli(...)` | [Entry Points](/zh-CN/plugins/sdk-entrypoints) |
完整注册 API 请参见 [SDK 概览](/zh-CN/plugins/sdk-overview#registration-api)。
内置插件在需要模型看到输出之前对工具结果进行异步重写时,可以使用 `api.registerAgentToolResultMiddleware(...)`
请在 `contracts.agentToolResultMiddleware` 中声明目标运行时,例如
`["pi", "codex"]`。这是一个受信任的内置插件扩展接口;外部
插件应优先使用常规 OpenClaw 插件钩子,除非 OpenClaw 为这项能力提供了明确的信任策略。
内置插件在需要模型看到输出之前,异步重写工具结果时,可以使用 `api.registerAgentToolResultMiddleware(...)`。请在 `contracts.agentToolResultMiddleware` 中声明目标运行时,例如 `["pi", "codex"]`。这是一个受信任的内置插件扩展点;对于外部插件,除非 OpenClaw 为此能力引入明确的信任策略,否则应优先使用常规的 OpenClaw 插件钩子。
如果你的插件注册了自定义 gateway RPC 方法,请使用
插件专用前缀。核心管理命名空间(`config.*`、
`exec.approvals.*`、`wizard.*`、`update.*`)仍然是保留的,并且始终解析为
`operator.admin`,即使某个插件请求了更窄的 scope。
如果你的插件注册了自定义的 Gateway 网关 RPC 方法,请将它们放在插件专属前缀下。核心管理命名空间(`config.*`、`exec.approvals.*`、`wizard.*`、`update.*`)保留给核心使用,即使插件请求了更窄的作用域,它们也始终会解析到 `operator.admin`
需要牢记的钩子保护语义:
需要注意的钩子守卫语义:
- `before_tool_call``{ block: true }` 是终结性的,会停止较低优先级处理器。
- `before_tool_call``{ block: true }` 是终止性结果,并会阻止更低优先级的处理器。
- `before_tool_call``{ block: false }` 会被视为未作决定。
- `before_tool_call``{ requireApproval: true }` 会暂停智能体执行,并通过 exec 审批覆盖层、Telegram 按钮、Discord 交互,或任意渠道上的 `/approve` 命令提示用户审批。
- `before_install``{ block: true }` 是终结性的,会停止较低优先级处理器。
- `before_tool_call``{ requireApproval: true }` 会暂停智能体执行,并通过 exec 审批覆盖层、Telegram 按钮、Discord 交互,或任意渠道上的 `/approve` 命令提示用户进行审批。
- `before_install``{ block: true }` 是终止性结果,并会阻止更低优先级的处理器。
- `before_install``{ block: false }` 会被视为未作决定。
- `message_sending``{ cancel: true }` 是终结性的,会停止较低优先级处理器。
- `message_sending``{ cancel: true }` 是终止性结果,并会阻止更低优先级的处理器。
- `message_sending``{ cancel: false }` 会被视为未作决定。
- `message_received`:当你需要入站线程/话题路由时,优先使用类型化的 `threadId` 字段。`metadata` 仅保留给渠道特定的附加信息。
- `message_sending`:优先使用类型化的路由字段 `replyToId` / `threadId`,而不是渠道特定的 metadata 键。
- `message_received`:当你需要入站线程 / 话题路由时,优先使用类型化的 `threadId` 字段。`metadata` 应保留用于渠道特定的额外信息。
- `message_sending`:优先使用类型化的 `replyToId` / `threadId` 路由字段,而不是渠道特定的 metadata 键。
`/approve` 命令会同时处理 exec 和插件审批,并带有有界回退:当找不到 exec 审批 id 时OpenClaw 会使用相同 id 通过插件审批重试。插件审批转发可通过配置中的 `approvals.plugin` 独立设置。
`/approve` 命令会同时处理 exec 和插件审批,并带有有界回退:当找不到某个 exec 审批 id 时OpenClaw 会通过插件审批重试同一个 id。插件审批转发可通过配置中的 `approvals.plugin` 独立设置。
如果自定义审批流程需要检测这个相同的有界回退场景,
请优先使用 `openclaw/plugin-sdk/error-runtime` 中的
`isApprovalNotFoundError`,而不是手动匹配审批过期字符串。
如果你的自定义审批流程需要检测这一相同的有界回退场景,优先使用 `openclaw/plugin-sdk/error-runtime` 中的 `isApprovalNotFoundError`,而不是手动匹配审批过期字符串。
示例和钩子参考请参见 [插件钩子](/zh-CN/plugins/hooks)。
## 注册智能体工具
工具是 LLM 可调用的类型化函数。它们可以是必需的(始终
可用),也可以是可选的(用户主动启用):
工具是 LLM 可调用的类型化函数。它们可以是必需的(始终可用)或可选的(用户主动启用):
```typescript
register(api) {
// 必需工具始终可用
// 必需工具——始终可用
api.registerTool({
name: "my_tool",
description: "Do a thing",
@ -220,7 +202,7 @@ register(api) {
},
});
// 可选工具 — 用户必须将其加入允许列表
// 可选工具——用户必须添加到 allowlist
api.registerTool(
{
name: "workflow_tool",
@ -235,7 +217,7 @@ register(api) {
}
```
用户可在配置中启用可选工具:
用户可在配置中启用可选工具:
```json5
{
@ -244,9 +226,9 @@ register(api) {
```
- 工具名称不得与核心工具冲突(冲突项会被跳过)
- 注册对象格式错误的工具,包括缺少 `parameters` 的情况,会被跳过并在插件诊断中报告,而不会破坏智能体运行
- 对有副作用或需要额外二进制依赖的工具,请使用 `optional: true`
- 用户可以通过将插件 id 添加到 `tools.allow` 来启用某个插件的全部工具
- 注册对象格式错误的工具,包括缺少 `parameters` 的情况,会被跳过并在插件诊断中报告,而不会破坏智能体运行
- 对有副作用或需要额外二进制依赖的工具,请使用 `optional: true`
- 用户可以通过将插件 id 添加到 `tools.allow` 来启用某个插件的全部工具
## 导入约定
@ -256,48 +238,42 @@ register(api) {
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store";
// 错误:单体根路径(已弃用,未来会移除)
// 错误:单体根路径(已弃用,将被移除)
import { ... } from "openclaw/plugin-sdk";
```
完整子路径参考请参见 [SDK 概览](/zh-CN/plugins/sdk-overview)。
在你的插件内部,请使用本地 barrel 文件(`api.ts`、`runtime-api.ts`)进行
内部导入——绝不要通过其 SDK 路径导入你自己的插件。
在你的插件内部,内部导入请使用本地 barrel 文件(`api.ts`、`runtime-api.ts`)——绝不要通过它自己的 SDK 路径导入你自己的插件。
对于提供商插件,请将提供商专用辅助工具保留在这些 package 根级
barrel 中,除非该扩展接口确实是通用的。当前的内置示例包括:
对于提供商插件,除非某个扩展点确实是通用的,否则应将提供商专用辅助工具保留在这些包根级 barrel 中。当前内置示例包括:
- AnthropicClaude 流封装器,以及 `service_tier` / beta 辅助工具
- AnthropicClaude 流包装器以及 `service_tier` / beta 辅助工具
- OpenAI提供商构建器、默认模型辅助工具、实时提供商
- OpenRouter提供商构建器以及新手引导/配置辅助工具
- OpenRouter提供商构建器以及新手引导 / 配置辅助工具
如果某个辅助工具只在一个内置提供商 package 内有用,请将它保留在该
package 根级扩展接口上,而不是将其提升到 `openclaw/plugin-sdk/*` 中。
如果某个辅助工具只在一个内置提供商包中有用,就应将它保留在该包根级扩展面上,而不是提升到 `openclaw/plugin-sdk/*` 中。
一些自动生成的 `openclaw/plugin-sdk/<bundled-id>` 辅助扩展接口仍然存在,
用于内置插件维护和兼容性,例如
`plugin-sdk/feishu-setup``plugin-sdk/zalo-setup`。请将这些视为保留接口,
而不是新第三方插件的默认模式。
某些生成的 `openclaw/plugin-sdk/<bundled-id>` 辅助扩展面仍然存在,用于内置插件维护和兼容性,例如 `plugin-sdk/feishu-setup``plugin-sdk/zalo-setup`。请将这些视为保留扩展面,而不是新第三方插件的默认模式。
## 提交前检查清单
<Check>**package.json** 具有正确的 `openclaw` 元数据</Check>
<Check>**openclaw.plugin.json** 清单存在且有效</Check>
<Check>**openclaw.plugin.json** 清单文件存在且有效</Check>
<Check>入口点使用 `defineChannelPluginEntry``definePluginEntry`</Check>
<Check>所有导入都使用聚焦的 `plugin-sdk/<subpath>` 路径</Check>
<Check>内部导入使用本地模块,而不是 SDK 自导入</Check>
<Check>测试通过(`pnpm test -- <bundled-plugin-root>/my-plugin/`</Check>
<Check>`pnpm check` 通过(仓库内插件)</Check>
## Beta 版本测试
## beta 发布测试
1. 关注 [openclaw/openclaw](https://github.com/openclaw/openclaw/releases) 的 GitHub 发布标签,并通过 `Watch` > `Releases` 订阅。Beta 标签格式类似 `v2026.3.N-beta.1`。你也可以为官方 OpenClaw X 账号 [@openclaw](https://x.com/openclaw) 开启通知,以获取发布公告。
2. Beta 标签一出现,就尽快使用该版本测试你的插件。稳定版之前的窗口通常只有几个小时。
3. 测试完成后,在 `plugin-forum` Discord 渠道中你的插件主题下发帖,内容写 `all good` 或说明损坏了什么。如果你还没有主题,请创建一个。
4. 如果有问题,请打开或更新一个标题为 `Beta blocker: <plugin-name> - <summary>` 的 issue并加上 `beta-blocker` 标签。将 issue 链接贴到你的主题中。
5. 向 `main` 提交一个标题为 `fix(<plugin-id>): beta blocker - <summary>` 的 PR并在 PR 和你的 Discord 主题中都链接该 issue。贡献者无法给 PR 加标签,因此标题是供维护者和自动化识别的 PR 侧信号。有 PR 的阻塞问题会被合并;没有 PR 的阻塞问题也可能照样发布。维护者会在 Beta 测试期间关注这些主题
6. 没有消息就表示一切正常。如果你错过了这个窗口,你的修复很可能会落到下一个周期。
1. 关注 [openclaw/openclaw](https://github.com/openclaw/openclaw/releases) 的 GitHub 发布标签,并通过 `Watch` > `Releases` 订阅。beta 标签看起来像 `v2026.3.N-beta.1`。你也可以为 OpenClaw 官方 X 账号 [@openclaw](https://x.com/openclaw) 开启通知,以获取发布公告。
2. beta 标签一出现就尽快用它测试你的插件。stable 发布前的窗口通常只有几个小时。
3. 测试后,在 Discord 频道 `plugin-forum` 中你的插件主题帖里发送 `all good` 或说明哪里坏了。如果你还没有主题帖,请创建一个。
4. 如果出了问题,创建或更新一个标题为 `Beta blocker: <plugin-name> - <summary>` 的 issue并加上 `beta-blocker` 标签。把该 issue 链接贴到你的主题帖中。
5. 向 `main` 提交一个标题为 `fix(<plugin-id>): beta blocker - <summary>` 的 PR并在 PR 和你的 Discord 主题帖中都链接该 issue。贡献者不能给 PR 打标签,因此标题是提供给维护者和自动化系统的 PR 侧信号。有 PR 的阻塞问题会被合并;没有 PR 的阻塞问题则可能仍会随版本发布。维护者会在 beta 测试期间关注这些主题帖
6. 没有消息就表示一切正常。如果你错过了这个窗口,你的修复很可能会进入下一个周期。
## 后续步骤
@ -322,10 +298,10 @@ package 根级扩展接口上,而不是将其提升到 `openclaw/plugin-sdk/*`
</Card>
</CardGroup>
## 相关
## 相关内容
- [插件架构](/zh-CN/plugins/architecture) — 内部架构深入解析
- [SDK 概览](/zh-CN/plugins/sdk-overview) — 插件 SDK 参考
- [Manifest](/zh-CN/plugins/manifest) — 插件清单格式
- [渠道插件](/zh-CN/plugins/sdk-channel-plugins) — 构建渠道插件
- [提供商插件](/zh-CN/plugins/sdk-provider-plugins) — 构建提供商插件
- [插件架构](/zh-CN/plugins/architecture) — 内部架构深入解析
- [SDK 概览](/zh-CN/plugins/sdk-overview) — 插件 SDK 参考
- [Manifest](/zh-CN/plugins/manifest) — 插件清单格式
- [Channel Plugins](/zh-CN/plugins/sdk-channel-plugins) — 构建渠道插件
- [Provider Plugins](/zh-CN/plugins/sdk-provider-plugins) — 构建提供商插件

View File

@ -5,10 +5,10 @@ read_when:
summary: 插件清单 + JSON schema 要求(严格配置校验)
title: 插件清单
x-i18n:
generated_at: "2026-04-28T02:06:47Z"
generated_at: "2026-04-28T02:18:32Z"
model: gpt-5.4
provider: openai
source_hash: 8610826b5c7b27a3dab2abb498c3506905a48680450f0c22cf08f91e76c0b62b
source_hash: bf1ce76231395a13b125c1845a495dd67089891d27c6ff98c499b1f70af07fba
source_path: plugins/manifest.md
workflow: 15
---
@ -20,33 +20,34 @@ x-i18n:
兼容的 bundle 格式使用不同的清单文件:
- Codex bundle`.codex-plugin/plugin.json`
- Claude bundle`.claude-plugin/plugin.json` 或不带清单的默认 Claude 组件布局
- Claude bundle`.claude-plugin/plugin.json`或不带清单的默认 Claude 组件布局
- Cursor bundle`.cursor-plugin/plugin.json`
OpenClaw 也会自动检测这些 bundle 布局,但不会根据此处描述的 `openclaw.plugin.json` schema 对它们进行校验。
对于兼容 bundleOpenClaw 前会在布局符合 OpenClaw 运行时预期时,读取 bundle 元数据,以及已声明的 skill 根目录、Claude 命令根目录、Claude bundle `settings.json` 默认值、Claude bundle LSP 默认值和受支持的 hook pack。
对于兼容 bundle当布局符合 OpenClaw 运行时预期时,OpenClaw 当前会读取 bundle 元数据,以及已声明的 skill 根目录、Claude 命令根目录、Claude bundle `settings.json` 默认值、Claude bundle 的 LSP 默认值,以及受支持的 hook pack。
每个原生 OpenClaw 插件**都必须**在**插件根目录**中提供一个 `openclaw.plugin.json` 文件。OpenClaw 使用此清单在**不执行插件代码的情况下**校验配置。缺失或无效的清单会被视为插件错误,并阻止配置校验。
每个原生 OpenClaw 插件**都必须**在**插件根目录**中提供一个 `openclaw.plugin.json` 文件。OpenClaw 使用此清单在**不执行插件代码**的情况下验配置。缺失或无效的清单会被视为插件错误,并阻止配置校验。
请参阅完整的插件系统指南:[插件](/zh-CN/tools/plugin)。
关于原生能力模型和当前外部兼容性指导,请参见:[能力模型](/zh-CN/plugins/architecture#public-capability-model)。
参见完整的插件系统指南:[插件](/zh-CN/tools/plugin)。
关于原生能力模型和当前外部兼容性指南,请参见:
[能力模型](/zh-CN/plugins/architecture#public-capability-model)。
## 此文件的作用
`openclaw.plugin.json` 是 OpenClaw 在**加载你的插件代码之前**读取的元数据。下所有内容都必须足够轻量,以便在不启动插件运行时的情况下进行检查。
`openclaw.plugin.json` 是 OpenClaw 在**加载你的插件代码之前**读取的元数据。下面的所有内容都必须足够轻量,以便在不启动插件运行时的情况下进行检查。
**用于:**
- 插件标识、配置校验配置 UI 提示
- 插件标识、配置校验,以及配置 UI 提示
- 认证、新手引导和设置元数据(别名、自动启用、提供商环境变量、认证选项)
- 控制平面界面的激活提示
- 简写模型家族归属
- 简写模型家族归属
- 静态能力归属快照(`contracts`
- 共享 `openclaw qa` 主机检查的 QA 运行器元数据
- 合并到目录和校验界面中的渠道专用配置元数据
- 共享 `openclaw qa` 主机检查的 QA 运行器元数据
- 合并到目录和校验界面中的渠道特定配置元数据
**不要用于:** 注册运行时行为、声明代码入口点或 npm 安装元数据。这些应放在你的插件代码和 `package.json` 中。
**不要用于:** 注册运行时行为、声明代码入口点或 npm 安装元数据。这些应放在你的插件代码和 `package.json` 中。
## 最小示例
@ -142,35 +143,35 @@ OpenClaw 也会自动检测这些 bundle 布局,但不会根据此处描述的
| 字段 | 必填 | 类型 | 含义 |
| ------------------------------------ | -------- | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id` | 是 | `string` | 规范插件 id。这是 `plugins.entries.<id>` 中使用的 id。 |
| `id` | 是 | `string` | 规范插件 id。这是 `plugins.entries.<id>` 中使用的 id。 |
| `configSchema` | 是 | `object` | 此插件配置的内联 JSON Schema。 |
| `enabledByDefault` | 否 | `true` | 将内置插件标记为默认启用。省略此字段,或将其设置为任何非 `true` 的值,则插件默认保持禁用。 |
| `enabledByDefault` | 否 | `true` | 将内置插件标记为默认启用。省略此字段,或设置为任何非 `true` 的值,则插件默认保持禁用。 |
| `legacyPluginIds` | 否 | `string[]` | 会规范化为此规范插件 id 的旧版 id。 |
| `autoEnableWhenConfiguredProviders` | 否 | `string[]` | 当认证、配置或模型引用提到这些 provider id 时,应自动启用此插件。 |
| `kind` | 否 | `"memory"` \| `"context-engine"` | 声明一个由 `plugins.slots.*` 使用的排他性插件类型。 |
| `channels` | 否 | `string[]` | 由此插件拥有的渠道 id。用于设备发现和配置校验。 |
| `autoEnableWhenConfiguredProviders` | 否 | `string[]` | 当认证、配置或模型引用提到这些提供商 id 时,应自动启用此插件。 |
| `kind` | 否 | `"memory"` \| `"context-engine"` | 声明`plugins.slots.*` 使用的互斥插件类型。 |
| `channels` | 否 | `string[]` | 由此插件拥有的渠道 id。用于 设备发现 和配置校验。 |
| `providers` | 否 | `string[]` | 由此插件拥有的提供商 id。 |
| `providerDiscoveryEntry` | 否 | `string` | 轻量级提供商发现模块路径,相对于插件根目录,用于可在不激活完整插件运行时的情况下加载的、限定在清单范围内的提供商目录元数据。 |
| `providerDiscoveryEntry` | 否 | `string` | 轻量级的 provider 设备发现模块路径,相对于插件根目录,用于作用域限定在清单内的 provider 目录元数据;这些元数据在不激活完整插件运行时的情况下加载。 |
| `modelSupport` | 否 | `object` | 由清单拥有的简写模型家族元数据,用于在运行时之前自动加载插件。 |
| `modelCatalog` | 否 | `object` | 由此插件拥有的提供商声明式模型目录元数据。这是未来只读列表、新手引导、模型选择器、别名和抑制功能在不加载插件运行时情况下的控制平面契约。 |
| `modelPricing` | 否 | `object` | 由提供商拥有的外部定价查询策略。用它将本地 / 自托管提供商排除在远程定价目录之外,或将 provider 引用映射到 OpenRouter / LiteLLM 目录 id而无需在核心中硬编码 provider id。 |
| `modelIdNormalization` | 否 | `object` | 在提供商运行时加载之前必须执行的、由提供商拥有的模型 id 别名 / 前缀清理规则。 |
| `providerEndpoints` | 否 | `object[]` | 由清单拥有的端点 host / baseUrl 元数据,用于核心在提供商运行时加载之前必须分类的 provider 路由。 |
| `providerRequest` | 否 | `object` | 在提供商运行时加载之前,由通用请求策略使用的低成本 provider 家族和请求兼容性元数据。 |
| `modelCatalog` | 否 | `object` | 由此插件拥有的提供商声明式模型目录元数据。这是未来只读列表展示、新手引导、模型选择器、别名和抑制功能的控制平面契约,且无需加载插件运行时。 |
| `modelPricing` | 否 | `object` | 由提供商拥有的外部定价查找策略。用它可将本地 / 自托管提供商排除在远程定价目录之外,或将提供商引用映射到 OpenRouter / LiteLLM 目录 id而无需在核心中硬编码提供商 id。 |
| `modelIdNormalization` | 否 | `object` | 由提供商拥有的模型 id 别名 / 前缀清理逻辑,必须在 provider 运行时加载前执行。 |
| `providerEndpoints` | 否 | `object[]` | 由清单拥有的提供商路由 endpoint 主机 / `baseUrl` 元数据,核心必须在 provider 运行时加载前对其进行分类。 |
| `providerRequest` | 否 | `object` | 廉价的 provider 家族和请求兼容性元数据,供通用请求策略在 provider 运行时加载前使用。 |
| `cliBackends` | 否 | `string[]` | 由此插件拥有的 CLI 推理后端 id。用于根据显式配置引用在启动时自动激活。 |
| `syntheticAuthRefs` | 否 | `string[]` | 在运行时加载之前、冷启动模型发现期间,应探测其插件自有 synthetic auth hook 的 provider 或 CLI 后端引用。 |
| `syntheticAuthRefs` | 否 | `string[]` | provider 或 CLI 后端引用;在运行时加载前进行冷启动模型发现期间,应探测其由插件拥有的合成认证 hook。 |
| `nonSecretAuthMarkers` | 否 | `string[]` | 由内置插件拥有的占位 API key 值表示非机密的本地、OAuth 或环境凭证状态。 |
| `commandAliases` | 否 | `object[]` | 由此插件拥有的命令名称,应在运行时加载之前产生带有插件感知能力的配置和 CLI 诊断信息。 |
| `providerAuthEnvVars` | 否 | `Record<string, string[]>` | 用于 provider 认证 / 状态查询的已弃用兼容环境变量元数据。新插件请优先使用 `setup.providers[].envVars`;在弃用窗口期内OpenClaw 仍会读取此字段。 |
| `providerAuthAliases` | 否 | `Record<string, string>` | 应复用另一个 provider id 进行认证查询的 provider id例如共享基础 provider API key 和认证配置文件的编码 provider。 |
| `channelEnvVars` | 否 | `Record<string, string[]>` | OpenClaw 可在不加载插件代码的情况下检查的低成本渠道环境变量元数据。将其用于通用启动 / 配置辅助工具应可见的、由环境变量驱动的渠道设置或认证界面。 |
| `providerAuthChoices` | 否 | `object[]` | 用于新手引导选择器、首选提供商解析和简单 CLI 标志接线的低成本认证选项元数据。 |
| `activation` | 否 | `object` | 面向 provider、命令、渠道、路由和能力触发加载的低成本激活规划器元数据。仅包含元数据;实际行为仍由插件运行时负责。 |
| `setup` | 否 | `object` | 可供设备发现和设置界面在不加载插件运行时的情况下检查的低成本设置 / 新手引导描述符。 |
| `qaRunners` | 否 | `object[]` | 在插件运行时加载之前,由共享 `openclaw qa` 主机使用的低成本 QA 运行器描述符。 |
| `contracts` | 否 | `object` | 面向外部认证 hook、语音、实时转写、实时语音、媒体理解、图像生成、音乐生成、视频生成、网页抓取、网页搜索和工具归属的静态内置能力快照。 |
| `mediaUnderstandingProviderMetadata` | 否 | `Record<string, object>` | 为 `contracts.mediaUnderstandingProviders` 中声明的 provider id 提供的低成本媒体理解默认值。 |
| `channelConfigs` | 否 | `Record<string, object>` | 由清单拥有的渠道配置元数据,在运行时加载前合并到设备发现和校验界面中。 |
| `commandAliases` | 否 | `object[]` | 由此插件拥有的命令名称;这些命令应在运行时加载前生成感知插件的配置和 CLI 诊断信息。 |
| `providerAuthEnvVars` | 否 | `Record<string, string[]>` | 已弃用的兼容性环境变量元数据,用于 provider 认证 / Status 查找。新插件优先使用 `setup.providers[].envVars`;在弃用窗口期间OpenClaw 仍会读取此字段。 |
| `providerAuthAliases` | 否 | `Record<string, string>` | 应复用另一个提供商 id 进行认证查找的提供商 id例如共享基础提供商 API key 和认证配置文件的编码提供商。 |
| `channelEnvVars` | 否 | `Record<string, string[]>` | OpenClaw 可在不加载插件代码的情况下检查的轻量级渠道环境变量元数据。将其用于由环境变量驱动的渠道设置或认证界面,以便通用启动 / 配置辅助器能够识别。 |
| `providerAuthChoices` | 否 | `object[]` | 轻量级认证选项元数据,用于新手引导选择器、首选提供商解析和简单 CLI 标志接线。 |
| `activation` | 否 | `object` | 用于启动、提供商、命令、渠道、路由和能力触发加载的轻量级激活规划器元数据。仅是元数据;实际行为仍由插件运行时负责。 |
| `setup` | 否 | `object` | 轻量级设置 / 新手引导描述符,供 设备发现 和设置界面在不加载插件运行时的情况下检查。 |
| `qaRunners` | 否 | `object[]` | 轻量级 QA 运行器描述符,供共享 `openclaw qa` 主机在插件运行时加载前使用。 |
| `contracts` | 否 | `object` | 静态内置能力快照,用于外部认证 hook、语音、实时转录、实时语音、媒体理解、图像生成、音乐生成、视频生成、网页抓取、网页搜索和工具归属。 |
| `mediaUnderstandingProviderMetadata` | 否 | `Record<string, object>` | 为 `contracts.mediaUnderstandingProviders` 中声明的提供商 id 提供的轻量级媒体理解默认元数据。 |
| `channelConfigs` | 否 | `Record<string, object>` | 由清单拥有的渠道配置元数据,在运行时加载前合并到 设备发现 和校验界面中。 |
| `skills` | 否 | `string[]` | 要加载的 Skills 目录,相对于插件根目录。 |
| `name` | 否 | `string` | 人类可读的插件名称。 |
| `description` | 否 | `string` | 在插件界面中显示的简短摘要。 |
@ -180,31 +181,31 @@ OpenClaw 也会自动检测这些 bundle 布局,但不会根据此处描述的
## `providerAuthChoices` 参考
每个 `providerAuthChoices` 条目描述一个新手引导或认证选项。
OpenClaw 会在提供商运行时加载之前读取它。
提供商设置列表会使用这些清单中的选项、从描述符派生的设置选项以及安装目录元数据,而无需加载提供商运行时。
OpenClaw 会在 provider 运行时加载前读取它。
provider 设置列表会使用这些清单选项、从描述符派生的设置选项,以及安装目录元数据,而无需加载 provider 运行时。
| 字段 | 必填 | 类型 | 含义 |
| --------------------- | -------- | ----------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| `provider` | 是 | `string` | 此选项所属的 provider id。 |
| `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。 |
| `provider` | 是 | `string` | 此选项所属的提供商 id。 |
| `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。 |
| `groupLabel` | 否 | `string` | 该分组面向用户的标签。 |
| `groupHint` | 否 | `string` | 该分组的简短辅助文本。 |
| `optionKey` | 否 | `string` | 简单单标志认证流程的内部选项键。 |
| `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">` | 此选项应显示在哪些新手引导界面中。如果省略,默认值为 `["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
{
@ -221,23 +222,29 @@ OpenClaw 会在提供商运行时加载之前读取它。
| 字段 | 必填 | 类型 | 含义 |
| ------------ | -------- | ----------------- | ----------------------------------------------------------------------- |
| `name` | 是 | `string` | 属于此插件的命令名称。 |
| `kind` | 否 | `"runtime-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`、设置描述符或 `contracts`当这些归属字段无法表示额外的规划器提示时,再使用 `activation`
对于 `claude-cli`、`codex-cli` 或 `google-gemini-cli` 这类 CLI 运行时别名,请使用顶层 `cliBackends``activation.onAgentHarnesses` 仅用于那些尚无归属字段可表示的嵌入式 Agent harness id。
优先使用已经能描述归属关系的最窄元数据。当这些字段可以表达该关系时,请使用 `providers`、`channels`、`commandAliases`、设置描述符或 `contracts`只有在这些归属字段无法表示额外规划提示时,才使用 `activation`
对于 `claude-cli`、`codex-cli` 或 `google-gemini-cli` 这类 CLI 运行时别名,请使用顶层 `cliBackends``activation.onAgentHarnesses` 仅用于那些尚无归属字段的嵌入式 Agent harness id。
此块仅包含元数据。它不会注册运行时行为,也不会替代 `register(...)`、`setupEntry` 或其他运行时 / 插件入口点。当前使用方会在更广泛的插件加载之前将其用作缩小范围的提示,因此缺少激活元数据通常只会带来性能成本;在旧版清单归属回退仍然存在时,它不应改变正确性。
此块仅是元数据。它不会注册运行时行为,也不会替代 `register(...)`、`setupEntry` 或其他运行时 / 插件入口点。当前使用方会在更广泛的插件加载之前,将其作为缩小范围的提示,因此缺少激活元数据通常只会带来性能损耗;在旧版清单归属回退机制仍存在时,不应改变正确性。
随着 OpenClaw 逐步摆脱隐式启动导入,每个插件都应有意识地设置 `activation.onStartup`
仅当插件必须在 Gateway 网关 启动期间运行时,才将其设为 `true`
当插件在启动时是惰性的,并且只应由更窄的触发条件加载时,将其设为 `false`
省略 `onStartup` 会保留已弃用的旧版隐式启动 sidecar 回退机制,这适用于没有静态能力元数据的插件;未来版本可能会停止在启动时加载这些插件,除非它们声明 `activation.onStartup: true`
```json
{
"activation": {
"onStartup": false,
"onProviders": ["openai"],
"onCommands": ["models"],
"onChannels": ["web"],
@ -249,28 +256,30 @@ OpenClaw 会在提供商运行时加载之前读取它。
```
| 字段 | 必填 | 类型 | 含义 |
| ------------------ | -------- | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `onProviders` | 否 | `string[]` | 应将此插件纳入激活 / 加载计划的 provider id。 |
| `onAgentHarnesses` | 否 | `string[]` | 应将此插件纳入激活 / 加载计划的嵌入式 Agent harness 运行时 id。对于 CLI 后端别名,请使用顶层 `cliBackends`。 |
| ------------------ | -------- | ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `onStartup` | 否 | `boolean` | 显式 Gateway 网关 启动激活。每个插件都应设置此项。`true` 会在启动期间导入插件;`false` 会选择退出已弃用的隐式 sidecar 启动回退,除非另一个匹配的触发条件要求加载。 |
| `onProviders` | 否 | `string[]` | 应将此插件纳入激活 / 加载计划的提供商 id。 |
| `onAgentHarnesses` | 否 | `string[]` | 应将此插件纳入激活 / 加载计划的嵌入式 Agent harness 运行时 id。CLI 后端别名请使用顶层 `cliBackends`。 |
| `onCommands` | 否 | `string[]` | 应将此插件纳入激活 / 加载计划的命令 id。 |
| `onChannels` | 否 | `string[]` | 应将此插件纳入激活 / 加载计划的渠道 id。 |
| `onRoutes` | 否 | `string[]` | 应将此插件纳入激活 / 加载计划的路由类型。 |
| `onConfigPaths` | 否 | `string[]` | 当这些相对于根的配置路径存在且未被显式禁用时,应将此插件纳入启动 / 加载计划。 |
| `onCapabilities` | 否 | `Array<"provider" \| "channel" \| "tool" \| "hook">` | 控制平面激活规划使用的宽泛能力提示。可能时优先使用更窄的字段。 |
| `onConfigPaths` | 否 | `string[]` | 当这些相对配置路径存在且未被显式禁用时,应将此插件纳入启动 / 加载计划。 |
| `onCapabilities` | 否 | `Array<"provider" \| "channel" \| "tool" \| "hook">` | 控制平面激活规划使用的宽泛能力提示。可能时优先使用更窄的字段。 |
当前的实时使用方:
当前在线使用方:
- 由命令触发的 CLI 规划会回退到旧版 `commandAliases[].cliCommand``commandAliases[].name`
- Agent 运行时启动规划对嵌入式 harness 使用 `activation.onAgentHarnesses`,对 CLI 运行时别名使用顶层 `cliBackends[]`
- 由渠道触发的设置 / 渠道规划在缺少显式渠道激活元数据时,会回退到旧版 `channels[]` 归属
- 启动插件规划会对 bundled browser 插件的 `browser` 块等非渠道根配置界面使用 `activation.onConfigPaths`
- 由提供商触发的设置 / 运行时规划在缺少显式提供商激活元数据时,会回退到旧版 `providers[]` 和顶层 `cliBackends[]` 归属
- Gateway 网关 启动规划使用 `activation.onStartup` 进行显式启动导入,并选择退出已弃用的隐式 sidecar 启动回退
- 命令触发的 CLI 规划会回退到旧版 `commandAliases[].cliCommand``commandAliases[].name`
- 智能体运行时启动规划对嵌入式 harness 使用 `activation.onAgentHarnesses`,对 CLI 运行时别名使用顶层 `cliBackends[]`
- 渠道触发的设置 / 渠道规划在缺少显式渠道激活元数据时,会回退到旧版 `channels[]` 归属
- 启动插件规划对非渠道根配置界面使用 `activation.onConfigPaths`,例如内置浏览器插件的 `browser`
- 提供商触发的设置 / 运行时规划在缺少显式提供商激活元数据时,会回退到旧版 `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
{
@ -286,11 +295,11 @@ OpenClaw 会在提供商运行时加载之前读取它。
| 字段 | 必填 | 类型 | 含义 |
| ------------- | -------- | -------- | ------------------------------------------------------------------ |
| `commandName` | 是 | `string` | 挂载在 `openclaw qa` 下的子命令,例如 `matrix`。 |
| `description` | 否 | `string` | 当共享宿主需要一个存根命令时使用的回退帮助文本。 |
| `description` | 否 | `string` | 当共享宿主需要一个 stub 命令时使用的后备帮助文本。 |
## `setup` 参考
当设置和新手引导界面在运行时加载之前需要低成本的插件自有元数据时,请使用 `setup`
当设置和新手引导界面在运行时加载前需要轻量级的、由插件拥有的元数据时,请使用 `setup`
```json
{
@ -309,40 +318,40 @@ OpenClaw 会在提供商运行时加载之前读取它。
}
```
顶层 `cliBackends` 然有效,并继续描述 CLI 推理后端。`setup.cliBackends` 是用于控制平面 / 设置流程的设置专用描述符界面,应保持为纯元数据。
顶层 `cliBackends` 然有效,并继续描述 CLI 推理后端。`setup.cliBackends` 是用于控制平面 / 设置流程的设置专用描述符界面,应保持为纯元数据。
当存在时,`setup.providers` 和 `setup.cliBackends` 是设置发现时首选的“描述符优先”查询界面。如果描述符仅缩小候选插件范围,而设置仍需要更丰富的设置期运行时 hook请将 `requiresRuntime` 设为 `true`,并保留 `setup-api` 作为回退执行路径。
存在 `setup.providers``setup.cliBackends` 时,它们是设置 设备发现 的首选描述符优先查找界面。如果描述符只用于缩小候选插件范围,而设置仍需要更丰富的设置期运行时 hook请将 `requiresRuntime: true` 设为 `true`,并保留 `setup-api` 作为后备执行路径。
OpenClaw 还会将 `setup.providers[].envVars` 纳入通用 provider 认证和环境变量查询中。`providerAuthEnvVars` 在弃用窗口期内仍通过兼容适配器受支持,但仍在使用它的非内置插件会收到清单诊断信息。新插件应将设置 / 状态环境变量元数据放在 `setup.providers[].envVars` 上。
OpenClaw 还会将 `setup.providers[].envVars` 纳入通用提供商认证和环境变量查找。`providerAuthEnvVars` 在弃用窗口期间仍通过兼容适配器受支持,但仍使用它的非内置插件会收到清单诊断信息。新插件应将设置 / Status 环境变量元数据放在 `setup.providers[].envVars` 上。
OpenClaw 还可以在没有设置入口,或 `setup.requiresRuntime: false` 声明不需要设置运行时时,根据 `setup.providers[].authMethods` 推导出简单的设置选项。对于自定义标签、CLI 标志、新手引导范围和助手元数据,显式的 `providerAuthChoices` 条目仍然是首选。
当没有可用的 setup 条目时,或当 `setup.requiresRuntime: false` 声明不需要设置运行时时OpenClaw 还可以从 `setup.providers[].authMethods` 派生简单的设置选项。对于自定义标签、CLI 标志、新手引导范围和助手元数据,显式的 `providerAuthChoices` 条目仍然是首选。
仅当这些描述符对设置界面已经足够时,才将 `requiresRuntime: false` 设为 `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 后端,或者某个描述符没有匹配的运行时注册,设置注册表诊断会报告描述符漂移。这些诊断是附加性的,不会拒绝旧版插件。
当设置运行时确实执行时,如果 `setup-api` 注册了清单描述符未声明的提供商或 CLI 后端,或者某个描述符没有匹配的运行时注册,设置注册表诊断会报告描述符漂移。这些诊断是附加性的,不会拒绝旧版插件。
### `setup.providers` 参考
| 字段 | 必填 | 类型 | 含义 |
| ------------- | -------- | ---------- | ------------------------------------------------------------------------------------ |
| `id` | 是 | `string` | 在设置或新手引导期间公开的 provider id。请确保规范化后的 id 在全局唯一。 |
| `authMethods` | 否 | `string[]` | 此 provider 在不加载完整运行时的情况下支持的设置 / 认证方法 id。 |
| `envVars` | 否 | `string[]` | 通用设置 / 状态界面可在插件运行时加载之前检查的环境变量。 |
| `id` | 是 | `string` | 在设置或新手引导期间暴露的提供商 id。保持规范化 id 在全局范围内唯一。 |
| `authMethods` | 否 | `string[]` | 此提供商在不加载完整运行时的情况下支持的设置 / 认证方法 id。 |
| `envVars` | 否 | `string[]` | 通用设置 / Status 界面可在插件运行时加载前检查的环境变量。 |
### `setup` 字段
| 字段 | 必填 | 类型 | 含义 |
| ------------------ | -------- | ---------- | --------------------------------------------------------------------------------------------------- |
| `providers` | 否 | `object[]` | 在设置和新手引导期间公开的 provider 设置描述符。 |
| `cliBackends` | 否 | `string[]` | 用于“描述符优先”设置查询的设置期后端 id。请确保规范化后的 id 在全局唯一。 |
| `configMigrations` | 否 | `string[]` | 由此插件设置界面拥有的配置迁移 id。 |
| `requiresRuntime` | 否 | `boolean` | 在描述符查之后,设置是否仍需要执行 `setup-api`。 |
| `providers` | 否 | `object[]` | 在设置和新手引导期间暴露的提供商设置描述符。 |
| `cliBackends` | 否 | `string[]` | 用于描述符优先设置查找的设置期后端 id。保持规范化 id 在全局范围内唯一。 |
| `configMigrations` | 否 | `string[]` | 由此插件设置界面拥有的配置迁移 id。 |
| `requiresRuntime` | 否 | `boolean` | 在描述符查之后,设置是否仍需要执行 `setup-api`。 |
## `uiHints` 参考
`uiHints` 是一个从配置字段名称到小型渲染提示的映射
`uiHints` 是一个从配置字段名映射到小型渲染提示的映射表
```json
{
@ -357,14 +366,14 @@ OpenClaw 还可以在没有设置入口,或 `setup.requiresRuntime: false` 声
}
```
每个字段提示可包含:
每个字段提示可包含:
| 字段 | 类型 | 含义 |
| ------------- | ---------- | --------------------------------------- |
| `label` | `string` | 面向用户的字段标签。 |
| `help` | `string` | 简短辅助文本。 |
| `tags` | `string[]` | 可选 UI 标签。 |
| `advanced` | `boolean` | 将该字段标记为高级字段。 |
| `tags` | `string[]` | 可选 UI 标签。 |
| `advanced` | `boolean` | 将该字段标记为高级。 |
| `sensitive` | `boolean` | 将该字段标记为机密或敏感。 |
| `placeholder` | `string` | 表单输入的占位文本。 |
@ -396,30 +405,30 @@ OpenClaw 还可以在没有设置入口,或 `setup.requiresRuntime: false` 声
| 字段 | 类型 | 含义 |
| -------------------------------- | ---------- | --------------------------------------------------------------------- |
| `embeddedExtensionFactories` | `string[]` | Codex app-server extension factory id目前为 `codex-app-server`。 |
| `embeddedExtensionFactories` | `string[]` | Codex app-server 扩展工厂 id目前为 `codex-app-server`。 |
| `agentToolResultMiddleware` | `string[]` | 内置插件可为其注册工具结果中间件的运行时 id。 |
| `externalAuthProviders` | `string[]` | 此插件拥有其外部认证配置文件 hook 的 provider id。 |
| `speechProviders` | `string[]` | 此插件拥有的语音 provider id。 |
| `realtimeTranscriptionProviders` | `string[]` | 此插件拥有的实时转写 provider id。 |
| `realtimeVoiceProviders` | `string[]` | 此插件拥有的实时语音 provider id。 |
| `memoryEmbeddingProviders` | `string[]` | 此插件拥有的 Memory embedding provider id。 |
| `mediaUnderstandingProviders` | `string[]` | 此插件拥有的媒体理解 provider id。 |
| `imageGenerationProviders` | `string[]` | 此插件拥有的图像生成 provider id。 |
| `videoGenerationProviders` | `string[]` | 此插件拥有的视频生成 provider id。 |
| `webFetchProviders` | `string[]` | 此插件拥有的网页抓取 provider id。 |
| `webSearchProviders` | `string[]` | 此插件拥有的网页搜索 provider id。 |
| `migrationProviders` | `string[]` | 此插件为 `openclaw migrate` 拥有的导入 provider id。 |
| `tools` | `string[]` | 此插件为内置契约检查拥有的智能体工具名称。 |
| `externalAuthProviders` | `string[]` | 其外部认证配置文件 hook 由此插件拥有的提供商 id。 |
| `speechProviders` | `string[]` | 由此插件拥有的语音提供商 id。 |
| `realtimeTranscriptionProviders` | `string[]` | 由此插件拥有的实时转录提供商 id。 |
| `realtimeVoiceProviders` | `string[]` | 由此插件拥有的实时语音提供商 id。 |
| `memoryEmbeddingProviders` | `string[]` | 由此插件拥有的 Memory Wiki 嵌入提供商 id。 |
| `mediaUnderstandingProviders` | `string[]` | 由此插件拥有的媒体理解提供商 id。 |
| `imageGenerationProviders` | `string[]` | 由此插件拥有的图像生成提供商 id。 |
| `videoGenerationProviders` | `string[]` | 由此插件拥有的视频生成提供商 id。 |
| `webFetchProviders` | `string[]` | 由此插件拥有的网页抓取提供商 id。 |
| `webSearchProviders` | `string[]` | 由此插件拥有的网页搜索提供商 id。 |
| `migrationProviders` | `string[]` | 此插件为 `openclaw migrate` 拥有的导入提供商 id。 |
| `tools` | `string[]` | 由此插件拥有、用于内置契约检查的 Agent 工具名称。 |
`contracts.embeddedExtensionFactories` 被保留下来,用于内置的仅 Codex app-server extension factory。内置工具结果转换应声明 `contracts.agentToolResultMiddleware`,并改用 `api.registerAgentToolResultMiddleware(...)` 注册。外部插件不能注册工具结果中间件,因为该接口可以在模型看到高信任工具输出之前重写它。
`contracts.embeddedExtensionFactories` 被保留用于内置的仅限 Codex app-server 的扩展工厂。内置工具结果转换应声明 `contracts.agentToolResultMiddleware`,并改用 `api.registerAgentToolResultMiddleware(...)` 进行注册。外部插件不能注册工具结果中间件,因为该接口可以在模型看到高信任工具输出之前重写它。
实现了 `resolveExternalAuthProfiles` 的 provider 插件应声明 `contracts.externalAuthProviders`。未声明该字段的插件仍会通过一个已弃用的兼容回退路径运行,但该回退路径更慢,并将在迁移窗口结束后移除。
实现了 `resolveExternalAuthProfiles` 的 provider 插件应声明 `contracts.externalAuthProviders`。未作此声明的插件仍会通过已弃用的兼容性回退机制运行,但该回退更慢,并将在迁移窗口结束后移除。
内置的 Memory embedding provider 应为其公开的每个适配器 id 声明 `contracts.memoryEmbeddingProviders`,包括内建适配器(如 `local`)。独立 CLI 路径使用此清单契约,在完整的 Gateway 网关运行时注册 provider 之前,仅加载归属插件。
内置 Memory LanceDB 嵌入提供商应为其暴露的每个适配器 id 声明 `contracts.memoryEmbeddingProviders`,包括诸如 `local` 之类的内置适配器。独立 CLI 路径使用此清单契约,在完整 Gateway 网关 运行时注册提供商之前仅加载拥有它的插件。
## `mediaUnderstandingProviderMetadata` 参考
当某个媒体理解 provider 具有默认模型、自动认证回退优先级,或 generic core helper 在运行时加载之前需要的原生文档支持时,请使用 `mediaUnderstandingProviderMetadata`。键名也必须在 `contracts.mediaUnderstandingProviders` 中声明。
当某个媒体理解提供商具有默认模型、自动认证回退优先级,或通用核心辅助器在运行时加载前所需的原生文档支持时,请使用 `mediaUnderstandingProviderMetadata`。键名也必须在 `contracts.mediaUnderstandingProviders` 中声明。
```json
{
@ -442,29 +451,29 @@ OpenClaw 还可以在没有设置入口,或 `setup.requiresRuntime: false` 声
}
```
每个 provider 条目可以包含:
每个提供商条目可包含:
| 字段 | 类型 | 含义 |
| ---------------------- | ----------------------------------- | ---------------------------------------------------------------------------- |
| `capabilities` | `("image" \| "audio" \| "video")[]` | 此 provider 公开的媒体能力。 |
| `defaultModels` | `Record<string, string>` | 当配置未指定模型时使用的“能力到模型”默认值。 |
| `autoPriority` | `Record<string, number>` | 用于基于凭证的自动 provider 回退时,数字越小排序越靠前。 |
| `nativeDocumentInputs` | `"pdf"[]` | 该 provider 支持的原生文档输入。 |
| `capabilities` | `("image" \| "audio" \| "video")[]` | 此提供商暴露的媒体能力。 |
| `defaultModels` | `Record<string, string>` | 当配置未指定模型时使用的能力到模型默认映射。 |
| `autoPriority` | `Record<string, number>` | 用于基于凭证的自动提供商回退时,数字越小排序越靠前。 |
| `nativeDocumentInputs` | `"pdf"[]` | 该提供商支持的原生文档输入。 |
## `channelConfigs` 参考
当渠道插件在运行时加载之前需要低成本配置元数据时,请使用 `channelConfigs`。对于已配置的外部渠道,如果没有可用的设置入口,或 `setup.requiresRuntime: false` 声明不需要设置运行时,只读的渠道设置 / 状态发现可以直接使用此元数据。
当渠道插件在运行时加载前需要轻量级配置元数据时,请使用 `channelConfigs`。对于已配置的外部渠道,如果没有可用的 setup 条目,或当 `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、设置和 Control UI 界面中,在插件运行时执行之前无法知道该渠道拥有的选项结构。
声明了 `channels[]` 的非内置插件也应声明匹配的 `channelConfigs` 条目。否则OpenClaw 仍加载该插件,但冷路径配置 schema、设置和 Control UI 界面在插件运行时执行之前无法知道该渠道拥有的选项结构。
`channelConfigs.<channel-id>.commands.nativeCommandsAutoEnabled``nativeSkillsAutoEnabled` 可以为在渠道运行时加载前执行的命令配置检查声明静态 `auto` 默认值。内置渠道也可以通过 `package.json#openclaw.channel.commands` 与其他由包拥有的渠道目录元数据一起发布相同的默认值
`channelConfigs.<channel-id>.commands.nativeCommandsAutoEnabled``nativeSkillsAutoEnabled` 可以为在渠道运行时加载前执行的命令配置检查声明静态 `auto` 默认值。内置渠道也可以通过 `package.json#openclaw.channel.commands` 发布相同的默认值,并与其其他由包拥有的渠道目录元数据一起提供
```json
{
@ -495,20 +504,20 @@ OpenClaw 还可以在没有设置入口,或 `setup.requiresRuntime: false` 声
}
```
每个渠道条目可包含:
每个渠道条目可包含:
| 字段 | 类型 | 含义 |
| ------------- | ------------------------ | ----------------------------------------------------------------------------------------- |
| `schema` | `object` | `channels.<id>` 的 JSON Schema。每个已声明的渠道配置条目都必须提供。 |
| `uiHints` | `Record<string, object>` | 该渠道配置区段的可选 UI 标签 / 占位符 / 敏感性提示。 |
| `label` | `string` | 当运行时元数据尚未就绪时,合并到选择器和检查界面中的渠道标签。 |
| `description` | `string` | 用于检查和目录界面的简短渠道描述。 |
| `description` | `string` | 用于检查和目录界面的简短渠道说明。 |
| `commands` | `object` | 用于运行时前配置检查的静态原生命令和原生 Skills 自动默认值。 |
| `preferOver` | `string[]` | 在选择界面中,渠道应优先于的旧版或较低优先级插件 id。 |
| `preferOver` | `string[]` | 在选择界面中,渠道应优先于的旧版或较低优先级插件 id。 |
### 替换另一个渠道插件
当你的插件是某个渠道 id 的首选归属者,而另一个插件也能提供该渠道时,请使用 `preferOver`。常见情况包括:插件 id 已重命名、独立插件取代了内置插件,或维护中的 fork 为了配置兼容性保留了相同的渠道 id。
当你的插件是某个渠道 id 的首选拥有者,而另一个插件也能提供该渠道时,请使用 `preferOver`。常见场景包括:插件 id 已重命名、独立插件取代了内置插件,或一个持续维护的分叉为了配置兼容性保留了相同的渠道 id。
```json
{
@ -529,13 +538,13 @@ OpenClaw 还可以在没有设置入口,或 `setup.requiresRuntime: false` 声
}
```
当配置了 `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
{
@ -546,23 +555,23 @@ OpenClaw 还可以在没有设置入口,或 `setup.requiresRuntime: false` 声
}
```
OpenClaw 按以下优先级处理
OpenClaw 按以下优先级应用
- 显式的 `provider/model` 引用使用归属 `providers` 清单元数据
- `modelPatterns` 优先级高`modelPrefixes`
- 显式的 `provider/model` 引用使用拥有它的 `providers` 清单元数据
- `modelPatterns` 优先于 `modelPrefixes`
- 如果一个非内置插件和一个内置插件都匹配,则非内置插件胜出
- 剩余的歧义会被忽略,直到用户或配置指定某个 provider
- 剩余的歧义会被忽略,直到用户或配置指定提供商
字段:
| 字段 | 类型 | 含义 |
| --------------- | ---------- | ------------------------------------------------------------------------------- |
| `modelPrefixes` | `string[]` | 对简写模型 id 使用 `startsWith` 进行匹配的前缀。 |
| `modelPatterns` | `string[]` | 在移除 profile 后缀后,对简写模型 id 进行匹配的正则表达式源码。 |
| `modelPrefixes` | `string[]` | 使用 `startsWith` 对简写模型 id 进行匹配的前缀。 |
| `modelPatterns` | `string[]` | 在移除配置文件后缀后,对简写模型 id 进行匹配的正则表达式源码。 |
## `modelCatalog` 参考
当 OpenClaw 应在加载插件运行时之前知道 provider 模型元数据时,请使用 `modelCatalog`。这是固定目录行、provider 别名、抑制规则和发现模式的清单归属来源。运行时刷新仍属于 provider 运行时代码,但清单会告知核心何时需要运行时。
当 OpenClaw 需要在加载插件运行时之前了解 provider 模型元数据时,请使用 `modelCatalog`。这是固定目录行、provider 别名、抑制规则和发现模式的清单拥有来源。运行时刷新仍属于 provider 运行时代码,但清单会告知核心何时需要运行时。
```json
{
@ -615,61 +624,61 @@ 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>` | 由此插件拥有的提供商 id 的目录条目。键名也应出现在顶层 `providers` 中。 |
| `aliases` | `Record<string, object>` | 应解析到某个已拥有提供商的 provider 别名,用于目录或抑制规划。 |
| `suppressions` | `object[]` | 出于提供商特定原因,由此插件对来自其他来源的模型条目进行抑制。 |
| `discovery` | `Record<string, "static" \| "refreshable" \| "runtime">` | 提供商目录是否可从清单元数据读取、刷新到缓存中,或必须依赖运行时。 |
`aliases` 参与模型目录规划中的 provider 归属查询。别名目标必须是由同一插件拥有的顶层 provider。当某个按 provider 过滤的列表使用别名时OpenClaw 可以读取归属清单,并在不加载 provider 运行时的情况下应用别名 API / base URL 覆盖。
`aliases` 会参与模型目录规划中的 provider 归属查找。别名目标必须是同一插件拥有的顶层提供商。当 provider 过滤列表使用某个别名时OpenClaw 可以读取拥有它的清单,并在不加载 provider 运行时的情况下应用别名 API / base URL 覆盖。
`suppressions` 取代了旧版 provider 运行时 `suppressBuiltInModel` hook。仅当 provider 由该插件拥有,或被声明为指向归属 provider `modelCatalog.aliases` 键时,抑制条目才会生效。在模型解析期间不再调用运行时抑制 hook
`suppressions` 取代了旧版 provider 运行时 `suppressBuiltInModel` hook。仅当提供商由该插件拥有,或被声明为指向已拥有提供商`modelCatalog.aliases` 键时,抑制条目才会生效。运行时抑制 hook 在模型解析期间不再调用。
provider 字段:
提供商字段:
| 字段 | 类型 | 含义 |
| --------- | ------------------------ | ----------------------------------------------------------------- |
| `baseUrl` | `string` | 此 provider 目录中模型的可选默认 base URL。 |
| `api` | `ModelApi` | 此 provider 目录中模型的可选默认 API 适配器。 |
| `headers` | `Record<string, string>` | 应用于此 provider 目录的可选静态 headers。 |
| `models` | `object[]` | 必填的模型行。没有 `id` 的行会被忽略。 |
| `baseUrl` | `string` | 此提供商目录中模型的可选默认 base URL。 |
| `api` | `ModelApi` | 此提供商目录中模型的可选默认 API 适配器。 |
| `headers` | `Record<string, string>` | 适用于此提供商目录的可选静态请求头。 |
| `models` | `object[]` | 必需的模型条目。没有 `id` 的条目会被忽略。 |
模型字段:
| 字段 | 类型 | 含义 |
| --------------- | -------------------------------------------------------------- | --------------------------------------------------------------------------- |
| `id` | `string` | provider 本地模型 id `provider/` 前缀。 |
| `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">` | 模型接受的模态。 |
| `reasoning` | `boolean` | 模型是否公开 reasoning 行为。 |
| `api` | `ModelApi` | 可选的每模型 API 覆盖。 |
| `baseUrl` | `string` | 可选的每模型 base URL 覆盖。 |
| `headers` | `Record<string, string>` | 可选的每模型静态请求头。 |
| `input` | `Array<"text" \| "image" \| "document" \| "audio" \| "video">` | 模型接受的模态。 |
| `reasoning` | `boolean` | 该模型是否暴露推理行为。 |
| `contextWindow` | `number` | provider 原生上下文窗口。 |
| `contextTokens` | `number` | 当与 `contextWindow` 不同时,可选的有效运行时上下文上限。 |
| `contextTokens` | `number` | 当与 `contextWindow` 不同时的可选有效运行时上下文上限。 |
| `maxTokens` | `number` | 已知时的最大输出 token 数。 |
| `cost` | `object` | 可选的每百万 token 美元定价,包括可选的 `tieredPricing`。 |
| `compat` | `object` | 与 OpenClaw 模型配置兼容性匹配的可选兼容标志。 |
| `status` | `"available"` \| `"preview"` \| `"deprecated"` \| `"disabled"` | 列表状态。仅当该行完全不应出现时才使用 suppression。 |
| `statusReason` | `string` | 与非可用状态一显示的可选原因。 |
| `replaces` | `string[]` | 被此模型取代的旧版 provider 本地模型 id。 |
| `replacedBy` | `string` | 已弃用的替代 provider 本地模型 id。 |
| `compat` | `object` | 与 OpenClaw 模型配置兼容性匹配的可选兼容标志。 |
| `status` | `"available"` \| `"preview"` \| `"deprecated"` \| `"disabled"` | 列表状态。仅当该条目完全不应出现时才使用抑制。 |
| `statusReason` | `string` | 与非可用状态一显示的可选原因。 |
| `replaces` | `string[]` | 被该模型取代的较旧 provider 本地模型 id。 |
| `replacedBy` | `string` | 已弃用条目的替代 provider 本地模型 id。 |
| `tags` | `string[]` | 供选择器和过滤器使用的稳定标签。 |
抑制字段:
| 字段 | 类型 | 含义 |
| -------------------------- | ---------- | --------------------------------------------------------------------------------------------------------- |
| `provider` | `string` | 要抑制其上游行的 provider id。必须由该插件拥有或声明为其归属别名。 |
| `provider` | `string` | 要抑制的上游条目的提供商 id。必须由此插件拥有或声明为已拥有的别名。 |
| `model` | `string` | 要抑制的 provider 本地模型 id。 |
| `reason` | `string` | 当直接请求被抑制的时显示的可选消息。 |
| `when.baseUrlHosts` | `string[]` | 仅当有效 provider base URL host 匹配时才应用抑制的可选列表。 |
| `when.providerConfigApiIn` | `string[]` | 仅当 provider 配置 `api` 的精确值匹配时才应用抑制的可选列表。 |
| `reason` | `string` | 当直接请求被抑制的条目时显示的可选消息。 |
| `when.baseUrlHosts` | `string[]` | 使抑制生效前所需的有效 provider base URL 主机的可选列表。 |
| `when.providerConfigApiIn` | `string[]` | 使抑制生效前所需的精确 provider 配置 `api`的可选列表。 |
不要在 `modelCatalog` 中放入仅运行时数据。只有当清单中的行足够完整,使按 provider 过滤的列表和选择器界面可以跳过注册表 / 运行时发现时,才使用 `static`。当清单中的行可作为有用的可列出种子或补充,但刷新 / 缓存稍后还可添加更多行时,请使用 `refreshable``refreshable` 行本身并不是权威来源。当 OpenClaw 必须加载 provider 运行时才能知道列表时,使用 `runtime`
不要在 `modelCatalog` 中放入仅运行时数据。只有当清单条目足够完整,能让 provider 过滤列表和选择器界面跳过注册表 / 运行时发现时,才使用 `static`。当清单条目可作为有用的可列出种子或补充,但刷新 / 缓存稍后还能添加更多条目时,使用 `refreshable`;可刷新条目本身并不具备权威性。当 OpenClaw 必须加载 provider 运行时才能知道列表内容时,使用 `runtime`
## `modelIdNormalization` 参考
对于必须在 provider 运行时加载之前发生的、低成本且由 provider 拥有的模型 id 清理,请使用 `modelIdNormalization`。这可将短模型名、provider 本地旧版 id 和代理前缀规则等别名保留在归属插件清单中,而不是放在核心模型选择表中
对于必须在 provider 运行时加载前完成的、轻量级的 provider 所有模型 id 清理,请使用 `modelIdNormalization`。这样可以把简短模型名、provider 本地旧版 id 和代理前缀规则等别名保留在拥有它们的插件清单中,而不是放在核心模型选择表里
```json
{
@ -689,33 +698,33 @@ provider 字段:
}
```
provider 字段:
提供商字段:
| 字段 | 类型 | 含义 |
| ------------------------------------ | ----------------------- | ----------------------------------------------------------------------------------------- |
| `aliases` | `Record<string,string>` | 不区分大小写的精确模型 id 别名。返回值会按原样返回。 |
| `stripPrefixes` | `string[]` | 在别名查找前要移除的前缀,适用于旧版 provider / model 重复场景。 |
| `aliases` | `Record<string,string>` | 不区分大小写的精确模型 id 别名。值会按原样返回。 |
| `stripPrefixes` | `string[]` | 在别名查找前要移除的前缀,适用于旧版 `provider/model` 重复情况。 |
| `prefixWhenBare` | `string` | 当规范化后的模型 id 尚未包含 `/` 时要添加的前缀。 |
| `prefixWhenBareAfterAliasStartsWith` | `object[]` | 别名查找后的条件裸 id 前缀规则,以 `modelPrefix``prefix` 为键。 |
| `prefixWhenBareAfterAliasStartsWith` | `object[]` | 别名查找后的条件裸 id 前缀规则,以 `modelPrefix``prefix` 为键。 |
## `providerEndpoints` 参考
对于通用请求策略在 provider 运行时加载之前必须知道的端点分类,请使用 `providerEndpoints`。每个 `endpointClass` 的含义仍由核心负责;插件清单负责 host 和 base URL 元数据。
对于通用请求策略在 provider 运行时加载前必须知道的 endpoint 分类,请使用 `providerEndpoints`。每个 `endpointClass` 的含义仍由核心负责;插件清单负责主机和 base URL 元数据。
端点字段:
endpoint 字段:
| 字段 | 类型 | 含义 |
| ------------------------------ | ---------- | ---------------------------------------------------------------------------------------------- |
| `endpointClass` | `string` | 已知的核心端点类,例如 `openrouter`、`moonshot-native` 或 `google-vertex`。 |
| `hosts` | `string[]` | 映射到该端点类的精确主机名。 |
| `hostSuffixes` | `string[]` | 映射到该端点类的主机后缀。若仅匹配域后缀,请以前缀 `.` 开头。 |
| `baseUrls` | `string[]` | 映射到该端点类的精确规范化 HTTP(S) base URL。 |
| `googleVertexRegion` | `string` | 精确全局主机所对应的静态 Google Vertex 区域。 |
| `googleVertexRegionHostSuffix` | `string` | 从匹配主机中剥离以暴露 Google Vertex 区域前缀的后缀。 |
| `endpointClass` | `string` | 已知的核心 endpoint 类别,例如 `openrouter`、`moonshot-native` 或 `google-vertex`。 |
| `hosts` | `string[]` | 映射到该 endpoint 类别的精确主机名。 |
| `hostSuffixes` | `string[]` | 映射到该 endpoint 类别的主机后缀。若仅匹配域名后缀,请以 `.` 开头。 |
| `baseUrls` | `string[]` | 映射到该 endpoint 类别的精确规范化 HTTP(S) base URL。 |
| `googleVertexRegion` | `string` | 用于精确全局主机的静态 Google Vertex 区域。 |
| `googleVertexRegionHostSuffix` | `string` | 从匹配主机中剥离以暴露 Google Vertex 区域前缀的后缀。 |
## `providerRequest` 参考
对于通用请求策略在不加载 provider 运行时的情况下所需的低成本请求兼容性元数据,请使用 `providerRequest`。与行为相关的 payload 重写应保留在 provider 运行时 hook 或共享 provider 家族 helper 中。
对于通用请求策略在不加载 provider 运行时的情况下所需的轻量级请求兼容性元数据,请使用 `providerRequest`。特定于行为的负载重写应保留在 provider 运行时 hook 或共享 provider 家族辅助器中。
```json
{
@ -733,17 +742,17 @@ provider 字段:
}
```
provider 字段:
提供商字段:
| 字段 | 类型 | 含义 |
| --------------------- | ------------ | -------------------------------------------------------------------------------------- |
| `family` | `string` | 供通用请求兼容性决策和诊断使用的 provider 家族标签。 |
| `compatibilityFamily` | `"moonshot"` | 供共享请求 helper 使用的可选 provider 家族兼容桶。 |
| `openAICompletions` | `object` | 与 OpenAI 兼容的 completions 请求标志,当前为 `supportsStreamingUsage`。 |
| `compatibilityFamily` | `"moonshot"` | 供共享请求辅助器使用的可选 provider 家族兼容性分组。 |
| `openAICompletions` | `object` | OpenAI 兼容 completions 请求标志,目前为 `supportsStreamingUsage`。 |
## `modelPricing` 参考
某个 provider 在运行时加载前需要控制平面定价行为时,请使用 `modelPricing`。Gateway 网关定价缓存会读取此元数据,而无需导入 provider 运行时代码。
当 provider 在运行时加载前需要控制平面定价行为时,请使用 `modelPricing`。Gateway 网关 定价缓存会读取这些元数据,而无需导入 provider 运行时代码。
```json
{
@ -764,54 +773,54 @@ provider 字段:
}
```
provider 字段:
提供商字段:
| 字段 | 类型 | 含义 |
| ------------ | ----------------- | -------------------------------------------------------------------------------------------------- |
| `external` | `boolean` | 对于绝不应拉取 OpenRouter 或 LiteLLM 定价的本地 / 自托管 provider请设为 `false`。 |
| `openRouter` | `false \| object` | OpenRouter 定价查询映射。设为 `false` 可禁用此 provider 的 OpenRouter 查询。 |
| `liteLLM` | `false \| object` | LiteLLM 定价查询映射。设为 `false` 可禁用此 provider 的 LiteLLM 查询。 |
| `external` | `boolean` | 对于本地 / 自托管 provider将其设为 `false`,这样它们就不会去获取 OpenRouter 或 LiteLLM 定价。 |
| `openRouter` | `false \| object` | OpenRouter 定价查找映射。`false` 会禁用该 provider 的 OpenRouter 查找。 |
| `liteLLM` | `false \| object` | LiteLLM 定价查找映射。`false` 会禁用该 provider 的 LiteLLM 查找。 |
来源字段:
| 字段 | 类型 | 含义 |
| -------------------------- | ------------------ | -------------------------------------------------------------------------------------------------------------------- |
| `provider` | `string` | 当外部目录 provider id 与 OpenClaw provider id 不同时使用的外部目录 provider id例如 `zai` provider 对应的 `z-ai`。 |
| `passthroughProviderModel` | `boolean` | 将包含斜杠的模型 id 视为嵌套的 provider / model 引用,适用于 OpenRouter 这类代理 provider。 |
| `modelIdTransforms` | `"version-dots"[]` | 额外的外部目录模型 id 变体。`version-dots` 会尝试带点的版本 id例如 `claude-opus-4.6`。 |
| `provider` | `string` | 当外部目录提供商 id 与 OpenClaw provider id 不同时使用的外部目录提供商 id例如 `zai` provider 对应的 `z-ai`。 |
| `passthroughProviderModel` | `boolean` | 将包含斜杠的模型 id 视为嵌套的 `provider/model` 引用,适用于 OpenRouter 之类的代理 provider。 |
| `modelIdTransforms` | `"version-dots"[]` | 额外的外部目录模型 id 变体。`version-dots` 会尝试`claude-opus-4.6` 这样的带点版本 id。 |
### OpenClaw Provider Index
OpenClaw Provider Index 是由 OpenClaw 拥有的预览元数据,用于其插件可能尚未安装的 provider。它不是插件清单的一部分。插件清单仍然是已安装插件的权威来源。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 不得包含密钥、启用状态、运行时 hook 或实时的账户专属模型数据。它的预览目录使用与插件清单相同的 `modelCatalog` provider 行结构,但应限制为稳定的显示元数据,除非像 `api`、`baseUrl`、定价或兼容标志等运行时适配器字段被有意与已安装插件清单保持一致。具有实时 `/models` 发现能力的 provider应通过显式模型目录缓存路径写入刷新后的行,而不是在常规列表或新手引导期间调用 provider API。
Provider Index 不得包含密钥、启用状态、运行时 hook 或实时的账号特定模型数据。它的预览目录使用与插件清单相同的 `modelCatalog` provider 条目结构,但除非有意与已安装插件清单保持一致,否则应限制为稳定的显示元数据,而不包括 `api`、`baseUrl`、定价或兼容性标志等运行时适配器字段。对于具有实时 `/models` 发现能力的 provider应通过显式模型目录缓存路径写入已刷新条目,而不是在普通列表展示或新手引导时调用 provider API。
对于其插件已移出核心或尚未安装的 providerProvider Index 条目还可携带可安装插件元数据。该元数据遵循渠道目录模式包名、npm 安装规范、预期完整性以及低成本认证选项标签,足以显示一个可安装的设置选项。一旦插件安装完成,就以其清单为准,并忽略该 provider 的 Provider Index 条目
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` 的区别
这两个文件承担不同职责
这两个文件承担的职责不同:
| 文件 | 用途 |
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `openclaw.plugin.json` | 发现、配置校验、认证选项元数据,以及在插件代码运行前必须存在的 UI 提示 |
| `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` 中。
@ -820,33 +829,33 @@ Provider Index 不得包含密钥、启用状态、运行时 hook 或实时的
| 字段 | 含义 |
| ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `openclaw.extensions` | 声明原生插件入口点。必须保持在插件包目录内。 |
| `openclaw.runtimeExtensions` | 声明已安装包的构建后 JavaScript 运行时入口点。必须保持在插件包目录内。 |
| `openclaw.setupEntry` | 在新手引导、延迟渠道启动和只读渠道状态 / 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.minHostVersion` | 最低支持的 OpenClaw 宿主版本,使用`>=2026.3.22` 这样的 semver 下限。 |
| `openclaw.install.expectedIntegrity` | 预期的 npm 分发完整性字符串,例如 `sha512-...`;安装和更新流程会据此校验获取的构件。 |
| `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.minHostVersion` | 最低支持的 OpenClaw 宿主版本,使用类似 `>=2026.3.22` 的 semver 下限。 |
| `openclaw.install.expectedIntegrity` | 预期的 npm 分发完整性字符串,例如 `sha512-...`;安装和更新流程会据此校验获取到的工件。 |
| `openclaw.install.allowInvalidConfigRecovery` | 当配置无效时,允许一个范围很窄的内置插件重装恢复路径。 |
| `openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen` | 允许在启动期间先加载仅设置的渠道界面,再加载完整渠道插件。 |
| `openclaw.startup.deferConfiguredChannelFullLoadUntilAfterListen` | 允许仅设置的渠道界面在启动期间先于完整渠道插件加载。 |
清单元数据决定了在运行时加载之前,哪些 provider / 渠道 / 设置选项会出现在新手引导中。`package.json#openclaw.install` 则告诉新手引导:当用户选择这些选项之一时,应如何获取或启用该插件。不要将安装提示移入 `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 构件不再匹配固定版本,更新流程就会以失败即关闭的方式终止。为兼容性考虑,交互式新手引导仍会提供受信任注册表 npm spec包括裸包名和 dist-tag。目录诊断可以区分精确源、浮动源、带完整性固定的源、缺少完整性的源、包名不匹配源以及无效默认选项源。它们还会在存在 `expectedIntegrity` 但没有可用于固定的有效 npm 源时发出警告。当存在 `expectedIntegrity` 时,安装 / 更新流程会强制校验它;若省略,则会记录注册表解析结果,但不附带完整性固定。
精确的 npm 版本锁定已经位`npmSpec` 中,例如 `"npmSpec": "@wecom/wecom-openclaw-plugin@1.2.3"`。官方外部目录条目应将精确版本与 `expectedIntegrity` 搭配使用,以便在获取到的 npm 工件不再匹配已锁定发布版本时,让更新流程以失败关闭的方式终止。为了兼容性,交互式新手引导仍会提供受信任注册表的 npm 规格,包括裸包名和 dist-tag。目录诊断可以区分精确源、浮动源、带完整性锁定源、缺少完整性源、包名不匹配源以及无效默认选项源。它们还会在 `expectedIntegrity` 存在但没有可用于锁定的有效 npm 来源时发出警告。当存在 `expectedIntegrity` 时,安装 / 更新流程会强制执行它;省略时,注册表解析结果会被记录,但不带完整性锁定。
状态、渠道列表或 SecretRef 扫描需要在不加载完整运行时的情况下识别已配置账户时,渠道插件应提供 `openclaw.setupEntry`设置入口应暴露渠道元数据,以及设置安全的配置、状态和 secrets 适配器网络客户端、Gateway 网关监听器和传输协议运行时应保留在主 extension 入口点中。
Status、渠道列表或 SecretRef 扫描需要在不加载完整运行时的情况下识别已配置账户时,渠道插件应提供 `openclaw.setupEntry`该设置入口应暴露渠道元数据以及对设置安全的配置、状态和密钥适配器网络客户端、Gateway 网关 监听器和传输运行时应保留在主扩展入口点中。
运行时入口点字段不会覆盖源码入口点字段的包边界检查。例如,`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
{
@ -862,9 +871,9 @@ Provider Index 不得包含密钥、启用状态、运行时 hook 或实时的
}
```
当设置、Doctor、Status 或只读存在性流程需要在完整渠道插件加载之前执行低成本的是 / 否认证探测时,请使用它。持久化认证状态不等同于已配置渠道状态:不要使用此元数据来自动启用插件、修复运行时依赖,或决定是否应加载渠道运行时。目标导出应是一个仅读取持久化状态的小函数;不要通过完整渠道运行时 barrel 暴露它。
当设置、doctor、状态或只读存在性流程需要在完整渠道插件加载前执行一个廉价的“是 / 否”认证探测时,请使用它。持久化认证状态不是已配置渠道状态:不要用这项元数据来自动启用插件、修复运行时依赖,或决定是否应加载某个渠道运行时。目标导出应是一个只读取持久化状态的小函数;不要通过完整渠道运行时 barrel 转发它。
`openclaw.channel.configuredState` 对仅环境变量的低成本已配置检查采用相同结构:
`openclaw.channel.configuredState`廉价的仅环境变量已配置检查采用相同结构:
```json
{
@ -880,62 +889,62 @@ Provider Index 不得包含密钥、启用状态、运行时 hook 或实时的
}
```
当某个渠道可以通过环境变量或其他极小的非运行时输入回答其已配置状态时,请使用它。如果检查需要完整配置解析或真实渠道运行时,请将逻辑保留在插件 `config.hasConfiguredState` hook 中。
当某个渠道可以根据环境变量或其他微型的非运行时输入来回答已配置状态时,请使用它。如果该检查需要完整配置解析或真实渠道运行时,请将逻辑保留在插件 `config.hasConfiguredState` hook 中。
## 发现优先级(重复插件 id
## 设备发现 优先级(重复插件 id
OpenClaw 会从多个根路径发现插件(内置、全局安装、工作区、配置中显式选择的路径)。如果两个发现结果共享相同的 `id`,则只保留**优先级最高**的清单;较低优先级的重复项会被丢弃,而不是与其并排加载。
OpenClaw 会从多个根目录发现插件(内置、全局安装、工作区、配置中显式选择的路径)。如果两次发现共享相同的 `id`,则只保留**优先级最高**的清单;优先级较低的重复项会被丢弃,而不是与其并行加载。
优先级从高到低如下
优先级从高到低:
1. **配置选择** —— 在 `plugins.entries.<id>` 中显式固定的路径
1. **配置选择** —— 在 `plugins.entries.<id>` 中显式固定的路径
2. **内置** —— 随 OpenClaw 一起发布的插件
3. **全局安装** —— 安装到全局 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 由某个插件清单声明。
- `plugins.entries.<id>`、`plugins.allow`、`plugins.deny` 和 `plugins.slots.*` 必须引用**可发现**的插件 id。未知 id 是**错误**。
- 如果某个插件已安装,但其清单或 schema 损坏或缺失校验会失败Doctor 会报告该插件错误。
- 如果插件配置存在,但插件处于**禁用**状态,则该配置会被保留,并在 Doctor + 日志中显示一个**警告**。
- `plugins.entries.<id>`、`plugins.allow`、`plugins.deny` 和 `plugins.slots.*` 必须引用**可发现**的插件 id。未知 id 是**错误**。
- 如果某个插件已安装,但其清单或 schema 缺失或损坏校验会失败Doctor 会报告该插件错误。
- 如果插件配置存在但插件处于**禁用**状态,则配置会被保留,并在 Doctor 和日志中显示**警告**。
完整 `plugins.*` schema 请参见[配置参考](/zh-CN/gateway/configuration)。
完整 `plugins.*` schema 请参见 [配置参考](/zh-CN/gateway/configuration)。
## 说明
- 对于**原生 OpenClaw 插件**,清单是**必需的**,包括本地文件系统加载。运行时仍会单独加载插件模块;清单仅用于发现 + 校验。
- 原生清单使用 JSON5 解析,因此支持注释、尾随逗号和未加引号的键,只要最终值仍然是一个对象即可
- 清单加载器只会读取有文档说明的清单字段。避免使用自定义顶层键。
- **原生 OpenClaw 插件必须提供清单**,包括本地文件系统加载的插件。运行时仍会单独加载插件模块;清单仅用于 设备发现 + 校验。
- 原生清单使用 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 runtime hooks](/zh-CN/plugins/architecture-internals#provider-runtime-hooks)。
- 如果你的插件依赖原生模块,请记录构建步骤以及任何包管理器 allowlist 要求(例如 pnpm `allow-build-scripts` + `pnpm rebuild <package>`)。
- 互斥插件类型通过 `plugins.slots.*` 选择:`kind: "memory"` 通过 `plugins.slots.memory``kind: "context-engine"` 通过 `plugins.slots.contextEngine`(默认 `legacy`)。
- 环境变量元数据(`setup.providers[].envVars`、已弃用的 `providerAuthEnvVars``channelEnvVars`)仅是声明式的。Status、审计、cron 投递校验和其他只读界面在将某个环境变量视为已配置之前,仍会应用插件信任和有效激活策略。
- 对于需要 provider 代码的运行时向导元数据,请参见 [provider 运行时 hooks](/zh-CN/plugins/architecture-internals#provider-runtime-hooks)。
- 如果你的插件依赖原生模块,请记录构建步骤以及任何包管理器允许列表要求(例如 pnpm `allow-build-scripts` + `pnpm rebuild <package>`)。
## 相关内容
<CardGroup cols={3}>
<Card title="构建插件" href="/zh-CN/plugins/building-plugins" icon="rocket">
插件入门指南。
插件入门指南。
</Card>
<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>

View File

@ -1,56 +1,56 @@
---
read_when:
- 你想通过 Ollama 使用云端或本地模型运行 OpenClaw
- 你想通过 Ollama 使用云端或本地模型运行 OpenClaw
- 你需要 Ollama 的设置和配置指南
- 你想使用 Ollama 视觉模型进行图像理解
summary: 使用 Ollama云端和本地模型运行 OpenClaw
title: Ollama
x-i18n:
generated_at: "2026-04-28T01:18:58Z"
generated_at: "2026-04-28T02:18:28Z"
model: gpt-5.4
provider: openai
source_hash: 80709e808ebcb694574e95a4269d29ade0532fe69f0f0386c2796871627560e6
source_hash: 3c5658a8024ca4bb90a8cf1256cf1db21a9a9a32e21c15c2f17f1513d29726f0
source_path: providers/ollama.md
workflow: 15
---
OpenClaw 通过 Ollama 的原生 API`/api/chat`)集成已托管的云模型以及本地/自托管的 Ollama 服务器。你可以通过三种模式使用 Ollama通过可访问的 Ollama 主机使用 `Cloud + Local`针对 `https://ollama.com` 使用 `Cloud only`,或针对可访问的 Ollama 主机使用 `Local only`
OpenClaw 通过 Ollama 的原生 API`/api/chat`)集成托管云模型和本地/自托管的 Ollama 服务器。你可以通过三种模式使用 Ollama通过可访问的 Ollama 主机使用 `Cloud + Local`直接对接 `https://ollama.com``Cloud only`,或对接可访问 Ollama 主机的 `Local only`
<Warning>
**远程 Ollama 用户**:不要在 OpenClaw 中使用 `/v1` OpenAI 兼容 URL`http://host:11434/v1`)。这会破坏工具调用,模型还可能将原始工具 JSON 作为纯文本输出。请改用原生 Ollama API URL`baseUrl: "http://host:11434"`(不带 `/v1`)。
**远程 Ollama 用户**:不要在 OpenClaw 中使用 `/v1` OpenAI 兼容 URL`http://host:11434/v1`)。这会破坏工具调用,模型还可能把原始工具 JSON 当作纯文本输出。请改用原生 Ollama API URL`baseUrl: "http://host:11434"`(不`/v1`)。
</Warning>
Ollama provider 配置使用 `baseUrl` 作为规范键名。OpenClaw 也接受 `baseURL` 以兼容 OpenAI SDK 风格的示例,但新配置应优先使用 `baseUrl`
Ollama provider 配置使用 `baseUrl` 作为规范键名。OpenClaw 也接受 `baseURL`以兼容 OpenAI SDK 风格的示例,但新配置应优先使用 `baseUrl`
## 凭证规则
<AccordionGroup>
<Accordion title="本地和局域网主机">
本地和局域网 Ollama 主机不需要真实的 bearer token。OpenClaw 仅对 loopback、私有网络、`.local` 和裸主机名的 Ollama base URL 使用本地 `ollama-local` 标记。
本地和局域网中的 Ollama 主机不需要真实的 bearer token。OpenClaw 仅对 loopback、私有网络、`.local` 和裸主机名的 Ollama base URL 使用本地 `ollama-local` 标记。
</Accordion>
<Accordion title="远程和 Ollama Cloud 主机">
远程公共主机和 Ollama Cloud`https://ollama.com`)需要通过 `OLLAMA_API_KEY`认证配置文件或提供商的 `apiKey` 提供真实凭证。
远程公共主机和 Ollama Cloud`https://ollama.com`)需要通过 `OLLAMA_API_KEY`auth profile 或提供商的 `apiKey` 提供真实凭证。
</Accordion>
<Accordion title="自定义 provider id">
设置了 `api: "ollama"` 的自定义 provider id 遵循相同规则。例如,指向私有局域网 Ollama 主机的 `ollama-remote` provider 可以使用 `apiKey: "ollama-local"`,子智能体将通过 Ollama provider hook 解析该标记,而不是将其视为缺失凭证
设置了 `api: "ollama"` 的自定义 provider id 遵循相同规则。例如,指向私有局域网 Ollama 主机的 `ollama-remote` 提供商可以使用 `apiKey: "ollama-local"`,子智能体会通过 Ollama provider hook 解析这个标记而不会将其视为缺失凭证。Memory 搜索也可以把 `agents.defaults.memorySearch.provider` 设置为该自定义 provider id这样 embeddings 就会使用匹配的 Ollama 端点
</Accordion>
<Accordion title="Memory 嵌入作用域">
当 Ollama 用于 Memory 嵌入时bearer 认证的作用域限定为声明它的主机
<Accordion title="Memory embedding 作用域">
当 Ollama 用于 memory embeddings 时bearer auth 的作用域限定在声明它的主机上
- provider 级别的密钥只会发送到该 provider 的 Ollama 主机。
- `agents.*.memorySearch.remote.apiKey` 只会发送到它自己的远程嵌入主机。
- `OLLAMA_API_KEY` 环境变量值会被视为 Ollama Cloud 约定,默认不会发送到本地或自托管主机。
- `agents.*.memorySearch.remote.apiKey` 只会发送到它自己的远程 embedding 主机。
- 单独的 `OLLAMA_API_KEY` 环境变量值会被视为 Ollama Cloud 约定,默认不会发送到本地或自托管主机。
</Accordion>
</AccordionGroup>
## 入门指南
选择你偏好的设置方和模式。
选择你偏好的设置方和模式。
<Tabs>
<Tab title="新手引导(推荐)">
**最适合:** 以最快路径完成可用的 Ollama 云端或本地设置。
**最适合:** 以最快方式完成可用的 Ollama 云端或本地设置。
<Steps>
<Step title="运行新手引导">
@ -61,12 +61,12 @@ Ollama provider 配置使用 `baseUrl` 作为规范键名。OpenClaw 也接受 `
从 provider 列表中选择 **Ollama**
</Step>
<Step title="选择你的模式">
- **Cloud + Local** 本地 Ollama 主机,加上通过该主机路由的云模型
- **Cloud only** 通过 `https://ollama.com` 使用托管的 Ollama 模型
- **Local only** 仅使用本地模型
- **Cloud + Local** — 本地 Ollama 主机,加上通过该主机路由的云模型
- **Cloud only** — 通过 `https://ollama.com` 使用托管的 Ollama 模型
- **Local only** — 仅使用本地模型
</Step>
<Step title="选择模型">
`Cloud only` 会提示输入 `OLLAMA_API_KEY` 并推荐托管云端默认模型。`Cloud + Local` 和 `Local only` 会要求提供一个 Ollama base URL发现可用模型并在所选本地模型尚不可用时自动拉取它。当 Ollama 报告已安装的 `:latest` 标签(例如 `gemma4:latest`)时,设置过程只会显示这个已安装模型一次,而不会同时显示 `gemma4``gemma4:latest`,也不会再次拉取不带标签的别名。`Cloud + Local` 还会检查该 Ollama 主机是否已登录以获得云访问权限
<Step title="选择一个模型">
`Cloud only` 会提示输入 `OLLAMA_API_KEY`,并建议使用托管云默认模型。`Cloud + Local` 和 `Local only` 会要求填写 Ollama base URL发现可用模型并在所选本地模型尚不可用时自动拉取它。当 Ollama 报告已安装的 `:latest` 标签(例如 `gemma4:latest`)时,设置界面只会显示这个已安装模型一次,而不会同时显示 `gemma4``gemma4:latest`,也不会再次拉取不带标签的别名。`Cloud + Local` 还会检查该 Ollama 主机是否已登录以启用云访问
</Step>
<Step title="验证模型可用">
```bash
@ -83,7 +83,7 @@ Ollama provider 配置使用 `baseUrl` 作为规范键名。OpenClaw 也接受 `
--accept-risk
```
也可以选择指定自定义 base URL 或模型:
也可以选择指定自定义 base URL 或模型:
```bash
openclaw onboard --non-interactive \
@ -96,12 +96,12 @@ Ollama provider 配置使用 `baseUrl` 作为规范键名。OpenClaw 也接受 `
</Tab>
<Tab title="手动设置">
**最适合:** 完全控云端或本地设置。
**最适合:** 完全控云端或本地设置。
<Steps>
<Step title="选择云端或本地">
- **Cloud + Local**:安装 Ollama使用 `ollama signin` 登录,并通过该主机路由云请求
- **Cloud only**:使用带有 `OLLAMA_API_KEY` `https://ollama.com`
- **Cloud only**:使用 `https://ollama.com` 并配合 `OLLAMA_API_KEY`
- **Local only**:从 [ollama.com/download](https://ollama.com/download) 安装 Ollama
</Step>
<Step title="拉取本地模型(仅本地)">
@ -114,7 +114,7 @@ Ollama provider 配置使用 `baseUrl` 作为规范键名。OpenClaw 也接受 `
```
</Step>
<Step title="为 OpenClaw 启用 Ollama">
对于 `Cloud only`,请使用你真实的 `OLLAMA_API_KEY`。对于依赖主机的设置,任何占位值都可以:
对于 `Cloud only`,请使用真实的 `OLLAMA_API_KEY`。对于基于主机的设置,任意占位值都可以:
```bash
# 云端
@ -127,7 +127,7 @@ Ollama provider 配置使用 `baseUrl` 作为规范键名。OpenClaw 也接受 `
openclaw config set models.providers.ollama.apiKey "OLLAMA_API_KEY"
```
</Step>
<Step title="查并设置你的模型">
<Step title="并设置你的模型">
```bash
openclaw models list
openclaw models set ollama/gemma4
@ -154,53 +154,54 @@ Ollama provider 配置使用 `baseUrl` 作为规范键名。OpenClaw 也接受 `
<Tabs>
<Tab title="Cloud + Local">
`Cloud + Local` 使用一个可访问的 Ollama 主机作为本地模型和云模型的统一控制点。这是 Ollama 首选的混合流程。
`Cloud + Local` 使用一个可访问的 Ollama 主机作为本地模型和云模型的统一控制点。这是 Ollama 推荐的混合流程。
在设置期间使用 **Cloud + Local**。OpenClaw 会提示输入 Ollama base URL从该主机发现本地模型并检查该主机是否已通过 `ollama signin` 登录以获得云访问权限。当主机已登录时OpenClaw 还会推荐托管云端默认模型,例如 `kimi-k2.5:cloud`、`minimax-m2.7:cloud` 和 `glm-5.1:cloud`
在设置期间使用 **Cloud + Local**。OpenClaw 会提示输入 Ollama base URL从该主机发现本地模型并检查该主机是否已通过 `ollama signin` 登录以启用云访问。当主机已登录时OpenClaw 还会建议托管云默认模型,例如 `kimi-k2.5:cloud`、`minimax-m2.7:cloud` 和 `glm-5.1:cloud`
如果主机尚未登录OpenClaw 会将设置保持为仅本地模式,直到你运行 `ollama signin`
如果主机尚未登录OpenClaw 会保持仅本地设置,直到你运行 `ollama signin`
</Tab>
<Tab title="Cloud only">
`Cloud only` 通过 Ollama 的托管 API `https://ollama.com` 运行
`Cloud only` 直接对接 Ollama 的托管 API`https://ollama.com`
在设置期间使用 **Cloud only**。OpenClaw 会提示输入 `OLLAMA_API_KEY`,设置 `baseUrl: "https://ollama.com"`,并填充托管云模型列表。此路径**不**需要本地 Ollama 服务器或 `ollama signin`
在设置期间使用 **Cloud only**。OpenClaw 会提示输入 `OLLAMA_API_KEY`,设置 `baseUrl: "https://ollama.com"`,并填充托管云模型列表。此路径 **不** 需要本地 Ollama 服务器或 `ollama signin`
`openclaw onboard` 期间显示的云模型列表会从 `https://ollama.com/api/tags` 实时获取,最多 500 ,因此模型选择器反映的是当前托管目录,而不是静态预设。如果设置时 `ollama.com` 无法访问或未返回模型OpenClaw 会回退到之前的硬编码推荐,以便新手引导仍能完成。
`openclaw onboard` 期间显示的云模型列表会从 `https://ollama.com/api/tags` 实时获取,最多 500 条,因此选择器反映的是当前托管目录,而不是静态种子列表。如果设置时 `ollama.com` 不可访问或未返回模型OpenClaw 会回退到之前硬编码的建议值,以确保新手引导仍能完成。
</Tab>
<Tab title="Local only">
在仅本地模式下OpenClaw 会从配置的 Ollama 实例发现模型。此路径适用于本地或自托管的 Ollama 服务器。
在仅本地模式下OpenClaw 会从配置的 Ollama 实例发现模型。此路径适用于本地或自托管的 Ollama 服务器。
OpenClaw 当前推荐 `gemma4` 作为本地默认模型
OpenClaw 当前建议 `gemma4` 作为本地默认值
</Tab>
</Tabs>
## 模型发现(隐式 provider
当你设置了 `OLLAMA_API_KEY`(或认证配置文件),并且**没有**定义 `models.providers.ollama` 或其他设置了 `api: "ollama"` 的自定义远程 provider 时OpenClaw 会从 `http://127.0.0.1:11434` 的本地 Ollama 实例发现模型。
当你设置了 `OLLAMA_API_KEY`(或 auth profile并且**没有**定义 `models.providers.ollama` 或其他带有 `api: "ollama"` 的自定义远程 provider 时OpenClaw 会从 `http://127.0.0.1:11434` 的本地 Ollama 实例发现模型。
| 行为 | 详情 |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 目录查询 | 查询 `/api/tags` |
| 能力检测 | 使用尽力而为的 `/api/show` 查询来读取 `contextWindow`、扩展的 `num_ctx` Modelfile 参数,以及包括视觉/工具在内的能力 |
| 视觉模型 | `/api/show` 报告具有 `vision` 能力的模型会被标记为支持图像(`input: ["text", "image"]`),因此 OpenClaw 会自动将图像注入提示词 |
| 能力检测 | 使用尽力而为的 `/api/show` 查询来读取 `contextWindow`、扩展`num_ctx` Modelfile 参数,以及包括 vision/tools 在内的能力 |
| 视觉模型 | 对于 `/api/show` 报告具备 `vision` 能力的模型,会将其标记为支持图像(`input: ["text", "image"]`),因此 OpenClaw 会自动将图像注入提示词 |
| 推理检测 | 通过模型名称启发式(`r1`、`reasoning`、`think`)标记 `reasoning` |
| Token 限制 | 将 `maxTokens` 设置为 OpenClaw 使用的默认 Ollama 最大 token 上限 |
| 成本 | 将所有成本设`0` |
| token 限制 | 将 `maxTokens` 设置为 OpenClaw 使用的默认 Ollama 最大 token 上限 |
| 成本 | 将所有成本设为 `0` |
样可以避免手动录入模型条目,同时让目录与本地 Ollama 实例保持一致。你可以在本地 `infer model run` 中使用完整引用,如 `ollama/<pulled-model>:latest`OpenClaw 会从 Ollama 的实时目录中解析这个已安装模型,而不需要手写 `models.json` 条目。
这避免手动录入模型条目,同时让目录与本地 Ollama 实例保持一致。你可以在本地 `infer model run` 中使用完整引用,如 `ollama/<pulled-model>:latest`OpenClaw 会从 Ollama 的实时目录中解析这个已安装模型,而不需要手写 `models.json` 条目。
```bash
# 查看可用模型
# 查看有哪些可用模型
ollama list
openclaw models list
```
如需进行一个只关注文本生成、避免完整智能体工具表面的精简冒烟测试,可在本地 `infer model run` 中使用完整的 Ollama 模型引用:
要进行一个范围较小的文本生成 smoke test并避免完整的智能体工具表面
请在本地 `infer model run` 中使用完整的 Ollama 模型引用:
```bash
OLLAMA_API_KEY=ollama-local \
@ -211,20 +212,22 @@ OLLAMA_API_KEY=ollama-local \
--json
```
该路径仍然使用 OpenClaw 配置的 provider、认证和原生 Ollama 传输,但不会启动聊天智能体轮次,也不会加载 MCP/工具上下文。如果这里成功,而普通智能体回复失败,请接下来排查该模型的智能体提示词/工具能力。
这个路径仍会使用 OpenClaw 已配置的 provider、auth 和原生 Ollama
传输,但它不会启动聊天智能体轮次,也不会加载 MCP/工具上下文。如果
这个命令成功,而普通智能体回复失败,请接着排查模型的智能体提示词/工具能力。
当你使用 `/model ollama/<model>` 切换会话模型时OpenClaw 会将其视为精确的用户选择。如果配置的 Ollama `baseUrl` 无法访问,下一次回复会直接因 provider 错误而失败,而不会悄悄改用其他已配置的后备模型。
当你使用 `/model ollama/<model>` 切换对话时OpenClaw 会将其视为用户的精确选择。如果已配置的 Ollama `baseUrl` 不可访问,下一条回复会因 provider 错误而失败,而不会静默地改用其他已配置的回退模型来回答
隔离的 cron 作业在启动智能体轮次之前,会额外执行一次本地安全检查。如果所选模型解析到本地、私有网络或 `.local` 的 Ollama provider`/api/tags` 无法访问OpenClaw 会将该次 cron 运行记录为 `skipped`,并在错误文本中包含所选的 `ollama/<model>`。该端点预检会缓存 5 分钟,因此多个指向同一已停止 Ollama 守护进程的 cron 作业不会都去发起失败的模型请求。
隔离的 cron 作业在启动智能体轮次前还会额外执行一次本地安全检查。如果所选模型解析到本地、私有网络或 `.local` 的 Ollama provider`/api/tags` 不可访问OpenClaw 会将该次 cron 运行记录为 `skipped`,并在错误文本中带上所选的 `ollama/<model>`。端点预检结果会缓存 5 分钟,因此多个指向同一个已停止 Ollama 守护进程的 cron 作业不会全部发起失败的模型请求。
使用以下命令对本地文本路径、原生流式路径以及针对本地 Ollama 的嵌入进行实时验证
使用以下命令对接本地 Ollama实时验证本地文本路径、原生流式传输路径和 embeddings
```bash
OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_OLLAMA=1 OPENCLAW_LIVE_OLLAMA_WEB_SEARCH=0 \
pnpm test:live -- extensions/ollama/ollama.live.test.ts
```
要添加新模型,只需使用 Ollama 拉取它:
要添加新模型,只需用 Ollama 拉取它:
```bash
ollama pull mistral
@ -233,14 +236,14 @@ ollama pull mistral
新模型会被自动发现并可立即使用。
<Note>
如果你显式设置了 `models.providers.ollama`,或配置了诸如 `models.providers.ollama-cloud` 这类带有 `api: "ollama"` 的自定义远程 provider则会跳过自动发现你必须手动定义模型。像 `http://127.0.0.2:11434` 这样的 loopback 自定义 provider 仍会被视为本地。请参阅下的显式配置部分。
如果你显式设置了 `models.providers.ollama`,或配置了带有 `api: "ollama"` 的自定义远程 provider(例如 `models.providers.ollama-cloud`,则会跳过自动发现,你必须手动定义模型。像 `http://127.0.0.2:11434` 这样的 loopback 自定义 provider 仍会被视为本地。请参阅下的显式配置部分。
</Note>
## 视觉图像描述
## 视觉图像描述
内置的 Ollama 插件将 Ollama 注册为支持图像的媒体理解 provider。这使 OpenClaw 能够通过本地或托管的 Ollama 视觉模型来路由显式图像描述请求以及已配置的图像模型默认值。
内置的 Ollama 插件将 Ollama 注册为支持图像的媒体理解 provider。这使 OpenClaw 能够通过本地或托管的 Ollama 视觉模型,路由显式的图像描述请求和已配置的图像模型默认值。
对于本地视觉功能,请拉取一个支持图像的模型:
对于本地视觉模型,请拉取一个支持图像的模型:
```bash
ollama pull qwen2.5vl:7b
@ -272,7 +275,7 @@ openclaw infer image describe \
}
```
较慢的本地视觉模型可能需要比云模型更长的图像理解超时时间。当 Ollama 在受限硬件上尝试分配完整声明的视觉上下文时,它们也可能崩溃或停止。对于只需要普通图像描述轮次的场景,请设置能力超时,并在模型条目上限制 `num_ctx`
较慢的本地视觉模型相比云模型,可能需要更长的图像理解超时时间。当 Ollama 在硬件受限的情况下尝试分配模型声明的完整视觉上下文时,这些模型也可能崩溃或停止。对于只需要普通图像描述轮次的场景,请设置能力超时,并在模型条目上限制 `num_ctx`
```json5
{
@ -301,16 +304,16 @@ openclaw infer image describe \
}
```
这个超时同时适用于入站图像理解,以及智能体在轮次中可调用的显式 `image` 工具。provider 级别的 `models.providers.ollama.timeoutSeconds` 仍然控制普通模型调用底层 Ollama HTTP 请求的保护超时。
这个超时同时适用于入站图像理解,以及智能体在轮次中可调用的显式 `image` 工具。provider 级别的 `models.providers.ollama.timeoutSeconds` 仍然控制普通模型调用底层 Ollama HTTP 请求的保护超时。
使用以下命令对本地 Ollama 的显式图像工具进行实时验证
使用以下命令对接本地 Ollama实时验证显式图像工具
```bash
OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_OLLAMA_IMAGE=1 \
pnpm test:live -- src/agents/tools/image-tool.ollama.live.test.ts
```
如果你手动定义了 `models.providers.ollama.models`,请将视觉模型标记为支持图像输入
如果你手动定义了 `models.providers.ollama.models`,请为视觉模型标记图像输入支持
```json5
{
@ -322,26 +325,26 @@ OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_OLLAMA_IMAGE=1 \
}
```
OpenClaw 会拒绝未标记为支持图像能力的模型的图像描述请求。在隐式发现模式下,当 `/api/show` 报告视觉能力时OpenClaw 会从 Ollama 读取该信息。
OpenClaw 会拒绝未标记为支持图像能力的模型的图像描述请求。使用隐式发现时,当 `/api/show` 报告视觉能力OpenClaw 会从 Ollama 读取这一信息。
## 配置
<Tabs>
<Tab title="基础(隐式发现)">
最简单的仅本地启用方式是使用环境变量:
最简单的仅本地启用方式是通过环境变量:
```bash
export OLLAMA_API_KEY="ollama-local"
```
<Tip>
如果设置了 `OLLAMA_API_KEY`,你可以在 provider 条目中省略 `apiKey`OpenClaw 会自动填充它以执行可用性检查
如果设置了 `OLLAMA_API_KEY`,你可以在 provider 条目中省略 `apiKey`OpenClaw 会在可用性检查时自动填充它。
</Tip>
</Tab>
<Tab title="显式(手动模型)">
当你需要托管云设置、Ollama 运行在其他主机/端口、想强制指定特定上下文窗口或模型列表,或者你希望完全手动定义模型时,请使用显式配置。
<Tab title="显式配置(手动模型)">
当你需要托管云设置、Ollama 运行在其他主机/端口、想强制指定特定上下文窗口或模型列表,或者完全手动定义模型时,请使用显式配置。
```json5
{
@ -379,15 +382,15 @@ OpenClaw 会拒绝未标记为支持图像能力的模型的图像描述请求
providers: {
ollama: {
apiKey: "ollama-local",
baseUrl: "http://ollama-host:11434", // 不要加 /v1 —— 使用原生 Ollama API URL
baseUrl: "http://ollama-host:11434", // 不要使用 /v1 —— 请使用原生 Ollama API URL
api: "ollama", // 显式设置以确保原生工具调用行为
timeoutSeconds: 300, // 可选:给冷启动的本地模型更长的连接和流式输时间
timeoutSeconds: 300, // 可选:给冷启动的本地模型更长的连接和流式输时间
models: [
{
id: "qwen3:32b",
name: "qwen3:32b",
params: {
keep_alive: "15m", // 可选:在轮次之间保持模型加载
keep_alive: "15m", // 可选:在轮次之间保持模型加载
},
},
],
@ -398,7 +401,7 @@ OpenClaw 会拒绝未标记为支持图像能力的模型的图像描述请求
```
<Warning>
不要在 URL 中添加 `/v1`。`/v1` 路径使用 OpenAI 兼容模式,其中工具调用并不可靠。请使用不带路径后缀的基础 Ollama URL。
不要在 URL 中添加 `/v1`。`/v1` 路径使用 OpenAI 兼容模式,而该模式下工具调用并不可靠。请使用不带路径后缀的基础 Ollama URL。
</Warning>
</Tab>
@ -406,11 +409,11 @@ OpenClaw 会拒绝未标记为支持图像能力的模型的图像描述请求
## 常见配方
将这些作为起点,并模型 ID 替换为 `ollama list``openclaw models list --provider ollama`显示的精确名称。
将这些作为起点,并模型 ID 替换为 `ollama list``openclaw models list --provider ollama` 中的精确名称。
<AccordionGroup>
<Accordion title="带自动发现的本地模型">
当 Ollama 与 Gateway 网关 运行在同一台机器上,并且你希望 OpenClaw 自动发现已安装模型时,请使用方式。
当 Ollama 与 Gateway 网关运行在同一台机器上,并且你希望 OpenClaw 自动发现已安装模型时,请使用这个方式。
```bash
ollama serve
@ -462,12 +465,12 @@ OpenClaw 会拒绝未标记为支持图像能力的模型的图像描述请求
}
```
`contextWindow` 是 OpenClaw 侧的上下文预算。`params.num_ctx` 会随请求发送给 Ollama。当你的硬件无法运行模型声明的完整上下文时让两者保持一致。
`contextWindow` 是 OpenClaw 侧的上下文预算。`params.num_ctx` 会随请求发送给 Ollama。当你的硬件无法运行模型声明的完整上下文时保持两者一致。
</Accordion>
<Accordion title="仅 Ollama Cloud">
当你不运行本地守护进程,并希望直接使用托管的 Ollama 模型时,请使用此方式。
当你不运行本地守护进程,并且想直接使用托管的 Ollama 模型时,请使用这个方式。
```bash
export OLLAMA_API_KEY="your-ollama-api-key"
@ -505,7 +508,7 @@ OpenClaw 会拒绝未标记为支持图像能力的模型的图像描述请求
</Accordion>
<Accordion title="通过已登录守护进程同时使用云端和本地">
当本地或局域网 Ollama 守护进程已通过 `ollama signin` 登录,并且应同时提供本地模型和 `:cloud` 模型时,请使用方式。
当本地或局域网 Ollama 守护进程已通过 `ollama signin` 登录,并且应同时提供本地模型和 `:cloud` 模型时,请使用这个方式。
```bash
ollama signin
@ -542,7 +545,7 @@ OpenClaw 会拒绝未标记为支持图像能力的模型的图像描述请求
</Accordion>
<Accordion title="多个 Ollama 主机">
当你拥有多个 Ollama 服务器时,请使用自定义 provider ID。每个 provider 都有自己的主机、模型、证、超时和模型引用。
当你拥有多个 Ollama 服务器时,请使用自定义 provider ID。每个 provider 都有自己的主机、模型、证、超时和模型引用。
```json5
{
@ -577,12 +580,12 @@ OpenClaw 会拒绝未标记为支持图像能力的模型的图像描述请求
}
```
当 OpenClaw 发送请求时,活动 provider 前缀会被移除,因此 `ollama-large/qwen3.5:27b` 到达 Ollama 时会变成 `qwen3.5:27b`
当 OpenClaw 发送请求时,会去掉活动 provider 前缀,因此 `ollama-large/qwen3.5:27b` 到达 Ollama 时会变成 `qwen3.5:27b`
</Accordion>
<Accordion title="精简本地模型配置">
有些本地模型可以回答简单提示,但在完整智能体工具表面下表现不佳。开始时应先限制工具和上下文,再考虑更改全局运行时设置。
某些本地模型可以回答简单提示,但难以应对完整的智能体工具表面。开始时,先限制工具和上下文,再考虑修改全局运行时设置。
```json5
{
@ -616,8 +619,8 @@ OpenClaw 会拒绝未标记为支持图像能力的模型的图像描述请求
}
```
仅当模型或服务器在工具 schema 上稳定失败时,才使用 `compat.supportsTools: false`。它会以降低智能体能力为代价来换取稳定性。
`localModelLean` 会从智能体表面移除浏览器、cron 和消息工具,但不会改变 Ollama 的运行时上下文或 thinking 模式。对于会循环或把响应预算消耗在隐藏推理上的小型 Qwen 风格 thinking 模型,请将它与显式 `params.num_ctx``params.thinking: false` 搭配使用。
仅当模型或服务器在工具 schema 上稳定失败时,才使用 `compat.supportsTools: false`。它是以牺牲智能体能力来换取稳定性。
`localModelLean` 会从智能体表面移除浏览器、cron 和消息工具,但不会改变 Ollama 的运行时上下文或 thinking 模式。对于会循环输出或把回复预算耗在隐藏推理上的小型 Qwen 风格 thinking 模型,请将它与显式 `params.num_ctx``params.thinking: false` 搭配使用。
</Accordion>
</AccordionGroup>
@ -639,9 +642,11 @@ OpenClaw 会拒绝未标记为支持图像能力的模型的图像描述请求
}
```
也支持自定义 Ollama provider ID。当模型引用使用活动 provider 前缀时,例如 `ollama-spark/qwen3:32b`OpenClaw 在调用 Ollama 前只会移除该前缀,因此服务器接收到的是 `qwen3:32b`
也支持自定义 Ollama provider id。当模型引用使用活动
provider 前缀时,例如 `ollama-spark/qwen3:32b`OpenClaw 只会在调用 Ollama 前移除该
前缀,因此服务器接收到的是 `qwen3:32b`
对于较慢的本地模型,优先考虑按 provider 范围调整请求,而不是提高整个智能体运行时超时:
对于较慢的本地模型,优先考虑按 provider 范围进行请求调优,而不是提高整个智能体运行时超时:
```json5
{
@ -662,25 +667,28 @@ OpenClaw 会拒绝未标记为支持图像能力的模型的图像描述请求
}
```
`timeoutSeconds` 适用于模型 HTTP 请求包括连接建立、headers、body 流式传输以及整个受保护获取的中止。`params.keep_alive` 会作为顶层 `keep_alive` 转发给原生 `/api/chat` 请求中的 Ollama当首轮加载时间是瓶颈时请按模型设置它。
`timeoutSeconds` 适用于模型 HTTP 请求,包括连接建立、
响应头、响应体流式传输,以及整个受保护 fetch 的中止。`params.keep_alive`
会作为顶层 `keep_alive` 转发给原生 `/api/chat` 的 Ollama 请求;
当首轮加载时间是瓶颈时,请按模型进行设置。
### 快速验证
```bash
# 机器可见的 Ollama 守护进程
# 对这台机器可见的 Ollama 守护进程
curl http://127.0.0.1:11434/api/tags
# OpenClaw 模型目录和当前选中的模型
# OpenClaw 目录和已选模型
openclaw models list --provider ollama
openclaw models status
# 直接模型冒烟测试
# 直接模型 smoke test
openclaw infer model run \
--model ollama/gemma4 \
--prompt "Reply with exactly: ok"
```
对于远程主机,请将 `127.0.0.1` 替换为 `baseUrl` 中使用的主机。如果 `curl` 可用但 OpenClaw 不可用,请检查 Gateway 网关 是否运行在不同的机器、容器或服务账户下。
对于远程主机,请将 `127.0.0.1` 替换为 `baseUrl` 中使用的主机。如果 `curl` 可用但 OpenClaw 不可用,请检查 Gateway 网关是否运行在另一台机器、容器或服务账户下。
## Ollama Web 搜索
@ -688,11 +696,11 @@ OpenClaw 支持 **Ollama Web 搜索**,作为内置的 `web_search` provider。
| 属性 | 详情 |
| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 主机 | 使用你配置的 Ollama 主机(设置了 `models.providers.ollama.baseUrl` 时使用该值,否则使用 `http://127.0.0.1:11434``https://ollama.com` 直接使用托管 API |
| 认证 | 对已登录的本地 Ollama 主机无需密钥;对于直接通过 `https://ollama.com` 进行搜索或受认证保护的主机,则需要 `OLLAMA_API_KEY` 或已配置的 provider 认证 |
| 要求 | 本地/自托管主机必须正在运行并通过 `ollama signin` 登录;直接使用托管搜索需要 `baseUrl: "https://ollama.com"` 加上真实的 Ollama API key |
| 主机 | 使用你配置的 Ollama 主机(如果设置了 `models.providers.ollama.baseUrl`,则使用它,否则使用 `http://127.0.0.1:11434``https://ollama.com` 直接使用托管 API |
| 凭证 | 对已登录的本地 Ollama 主机无需密钥;对于直接使用 `https://ollama.com` 的搜索或受保护主机,使用 `OLLAMA_API_KEY` 或已配置的 provider 凭证 |
| 要求 | 本地/自托管主机必须正在运行并通过 `ollama signin` 登录;直接使用托管搜索需要 `baseUrl: "https://ollama.com"` 外加真实的 Ollama API 密钥 |
`openclaw onboard``openclaw configure --section web` 期间选择 **Ollama Web 搜索**,或设置:
`openclaw onboard``openclaw configure --section web` 期间选择 **Ollama Web 搜索**,或设置:
```json5
{
@ -706,7 +714,7 @@ OpenClaw 支持 **Ollama Web 搜索**,作为内置的 `web_search` provider。
}
```
如需通过 Ollama Cloud 直接使用托管搜索:
通过 Ollama Cloud 直接使用托管搜索:
```json5
{
@ -731,7 +739,7 @@ OpenClaw 支持 **Ollama Web 搜索**,作为内置的 `web_search` provider。
对于已登录的本地守护进程OpenClaw 使用该守护进程的 `/api/experimental/web_search` 代理。对于 `https://ollama.com`,它会直接调用托管的 `/api/web_search` 端点。
<Note>
完整设置和行为详情,请参阅 [Ollama Web 搜索](/zh-CN/tools/ollama-search)。
完整的设置和行为细节,请参阅 [Ollama Web 搜索](/zh-CN/tools/ollama-search)。
</Note>
## 高级配置
@ -739,10 +747,10 @@ OpenClaw 支持 **Ollama Web 搜索**,作为内置的 `web_search` provider。
<AccordionGroup>
<Accordion title="旧版 OpenAI 兼容模式">
<Warning>
**在 OpenAI 兼容模式下,工具调用并不可靠。** 仅当你需要通过代理使用 OpenAI 格式,且不依赖原生工具调用行为时,才使用此模式。
**在 OpenAI 兼容模式下,工具调用并不可靠。** 仅当你需要为代理使用 OpenAI 格式,并且不依赖原生工具调用行为时,才使用此模式。
</Warning>
如果你需要改用 OpenAI 兼容端点(例如位于仅支持 OpenAI 格式的代理之后),请显式设置 `api: "openai-completions"`
如果你必须改用 OpenAI 兼容端点(例如,在只支持 OpenAI 格式的代理之后),请显式设置 `api: "openai-completions"`
```json5
{
@ -760,9 +768,9 @@ OpenClaw 支持 **Ollama Web 搜索**,作为内置的 `web_search` provider。
}
```
此模式下,可能无法同时支持流式传输和工具调用。你可能需要在模型配置中使用 `params: { streaming: false }` 关闭流式传输。
该模式下,可能不支持同时进行流式传输和工具调用。你可能需要在模型配置中使用 `params: { streaming: false }` 关闭流式传输。
当 Ollama 与 `api: "openai-completions"` 一起使用时OpenClaw 默认会注入 `options.num_ctx`,这样 Ollama 就不会静默回退到 4096 的上下文窗口。如果你的代理/上游会拒绝未知的 `options` 字段,请关闭此行为:
当 Ollama 与 `api: "openai-completions"` 一起使用时OpenClaw 默认会注入 `options.num_ctx`,这样 Ollama 就不会静默回退到 4096 的上下文窗口。如果你的代理/上游会拒绝未知的 `options` 字段,请禁用此行为:
```json5
{
@ -785,9 +793,9 @@ OpenClaw 支持 **Ollama Web 搜索**,作为内置的 `web_search` provider。
<Accordion title="上下文窗口">
对于自动发现的模型OpenClaw 会在可用时使用 Ollama 报告的上下文窗口,包括来自自定义 Modelfile 的更大 `PARAMETER num_ctx` 值。否则,它会回退到 OpenClaw 使用的默认 Ollama 上下文窗口。
你可以为该 Ollama provider 下的每个模型设置 provider 级别的默认 `contextWindow`、`contextTokens` 和 `maxTokens`并在需要时按模型覆盖它们。`contextWindow` 是 OpenClaw 的提示词和压缩预算。原生 Ollama 请求默认不会设置 `options.num_ctx`,除非你显式配置 `params.num_ctx`,这样 Ollama 就可以应用自己的模型、`OLLAMA_CONTEXT_LENGTH` 或基于 VRAM 的默认值。要在不重建 Modelfile 的情况下限制或强制 Ollama 的单请求运行时上下文,请设置 `params.num_ctx`无效、零、负数和非有限值都会被忽略。OpenAI 兼容的 Ollama 适配器仍会默认配置的 `params.num_ctx``contextWindow` 注入 `options.num_ctx`;如果你的上游拒绝 `options`可通过 `injectNumCtxForOpenAICompat: false` 关闭
你可以为该 Ollama provider 下的每个模型设置 provider 级别的默认 `contextWindow`、`contextTokens` 和 `maxTokens`然后在需要时按模型覆盖。`contextWindow` 是 OpenClaw 的提示词和压缩预算。原生 Ollama 请求不会设置 `options.num_ctx`,除非你显式配置 `params.num_ctx`,这样 Ollama 就可以应用自己的模型、`OLLAMA_CONTEXT_LENGTH` 或基于 VRAM 的默认值。要在不重建 Modelfile 的情况下限制或强制指定 Ollama 每次请求的运行时上下文,请设置 `params.num_ctx`无效、零、负数和非有限值都会被忽略。OpenAI 兼容的 Ollama 适配器仍会默认根据已配置的 `params.num_ctx``contextWindow` 注入 `options.num_ctx`;如果你的上游拒绝 `options`请使用 `injectNumCtxForOpenAICompat: false` 禁用
原生 Ollama 模型条目也接受 `params` 下常见的 Ollama 运行时选项,包括 `temperature`、`top_p`、`top_k`、`min_p`、`num_predict`、`stop`、`repeat_penalty`、`num_batch`、`num_thread` 和 `use_mmap`。OpenClaw 只会转发 Ollama 请求键,因此像 `streaming` 这样的 OpenClaw 运行时参数不会泄露给 Ollama。使用 `params.think``params.thinking` 发送顶层 Ollama `think`;对 Qwen 风格的 thinking 模型,`false` 会禁用 API 级别的 thinking。
原生 Ollama 模型条目也接受 `params` 下常见的 Ollama 运行时选项,包括 `temperature`、`top_p`、`top_k`、`min_p`、`num_predict`、`stop`、`repeat_penalty`、`num_batch`、`num_thread` 和 `use_mmap`。OpenClaw 只会转发 Ollama 请求键,因此像 `streaming` 这样的 OpenClaw 运行时参数不会泄露给 Ollama。使用 `params.think``params.thinking` 发送顶层 Ollama `think`;对 Qwen 风格的 thinking 模型,`false` 会禁用 API 级 thinking。
```json5
{
@ -814,12 +822,12 @@ OpenClaw 支持 **Ollama Web 搜索**,作为内置的 `web_search` provider。
}
```
每个模型的 `agents.defaults.models["ollama/<model>"].params.num_ctx` 也同样有效。如果两者都已配置,则显式的 provider 模型条目优先于智能体默认值。
按模型设置的 `agents.defaults.models["ollama/<model>"].params.num_ctx` 也可以生效。如果两者都配置了,显式的 provider 模型条目优先于智能体默认值。
</Accordion>
<Accordion title="Thinking 控制">
对于原生 Ollama 模型OpenClaw 会按 Ollama 期望的方式转发 thinking 控制:使用顶层 `think`,而不是 `options.think`
对于原生 Ollama 模型OpenClaw 会按 Ollama 期望的方式转发 thinking 控制:使用顶层 `think`,而不是 `options.think`
```bash
openclaw agent --model ollama/gemma4 --thinking off
@ -842,12 +850,12 @@ OpenClaw 支持 **Ollama Web 搜索**,作为内置的 `web_search` provider。
}
```
每个模型`params.think``params.thinking` 可以为特定已配置模型禁用或强制启用 Ollama API thinking。运行时命令如 `/think off` 仍然会应用到当前运行。
按模型设置`params.think``params.thinking` 可以为特定已配置模型禁用或强制启用 Ollama API thinking。`/think off` 这样的运行时命令仍会作用于当前运行。
</Accordion>
<Accordion title="推理模型">
OpenClaw 默认将名称中包含 `deepseek-r1`、`reasoning` 或 `think` 的模型视为具备推理能力
OpenClaw 默认将名称中包含 `deepseek-r1`、`reasoning` 或 `think` 的模型视为支持推理的模型
```bash
ollama pull deepseek-r1:32b
@ -858,23 +866,23 @@ OpenClaw 支持 **Ollama Web 搜索**,作为内置的 `web_search` provider。
</Accordion>
<Accordion title="模型成本">
Ollama 是免费的并且在本地运行,因此所有模型成本都设置为 $0。这同时适用于自动发现的模型和手动定义的模型。
Ollama 是免费的并且在本地运行,因此所有模型成本都设置为 $0。这同时适用于自动发现和手动定义的模型。
</Accordion>
<Accordion title="Memory 嵌入">
<Accordion title="Memory embeddings">
内置的 Ollama 插件为
[memory search](/zh-CN/concepts/memory) 注册了一个 Memory 嵌入 provider。它使用已配置的 Ollama base URL
和 API key,调用 Ollama 当前的 `/api/embed` 端点,并在可能时将多个
Memory 块批量合并为一次 `input` 请求
[memory search](/zh-CN/concepts/memory) 注册了一个 memory embedding provider。它使用已配置的 Ollama base URL
和 API 密钥,调用 Ollama 当前的 `/api/embed` 端点,并在可能时
将多个 memory 块批量合并到一个 `input` 请求中
| 属性 | 值 |
| ------------- | ------------------- |
| 默认模型 | `nomic-embed-text` |
| 自动拉取 | 是 —— 如果嵌入模型在本地不存在,会自动拉取 |
| 自动拉取 | 是 —— 如果 embedding 模型在本地不存在,会自动拉取 |
查询时嵌入会对需要或建议此前缀的模型使用检索前缀,包括 `nomic-embed-text`、`qwen3-embedding` 和 `mxbai-embed-large`。Memory 文档批次保持原始格式,因此现有索引不需要进行格式迁移。
查询时 embeddings 会对需要或建议此前缀的模型使用检索前缀,包括 `nomic-embed-text`、`qwen3-embedding` 和 `mxbai-embed-large`。Memory 文档批次保持原始格式,因此现有索引不需要进行格式迁移。
要将 Ollama 选为 memory search 的嵌入 provider
要将 Ollama 选为 memory search 的 embedding provider
```json5
{
@ -883,7 +891,7 @@ OpenClaw 支持 **Ollama Web 搜索**,作为内置的 `web_search` provider。
memorySearch: {
provider: "ollama",
remote: {
// Ollama 的默认值。如果较大的主机上重建索引太慢,可提高此值
// Ollama 的默认值。如果在更大的主机上重建索引过慢,可以调高
nonBatchConcurrency: 1,
},
},
@ -892,7 +900,7 @@ OpenClaw 支持 **Ollama Web 搜索**,作为内置的 `web_search` provider。
}
```
对于远程嵌入主机,请将认证限定在该主机范围内
对于远程 embedding 主机,请将凭证作用域限制在该主机上
```json5
{
@ -915,12 +923,12 @@ OpenClaw 支持 **Ollama Web 搜索**,作为内置的 `web_search` provider。
</Accordion>
<Accordion title="流式传输配置">
OpenClaw 的 Ollama 集成默认使用**原生 Ollama API**`/api/chat`),它完全支持同时进行流式传输和工具调用。不需要特殊配置。
OpenClaw 的 Ollama 集成默认使用 **原生 Ollama API**`/api/chat`),它完全支持同时进行流式传输和工具调用。不需要额外配置。
对于原生 `/api/chat` 请求OpenClaw 会直接将 thinking 控制转发给 Ollama`/think off` 和 `openclaw agent --thinking off` 会发送顶层 `think: false`,而 `/think low|medium|high` 会发送对应的顶层 `think` 强度字符串。`/think max` 会映射为 Ollama 最高的原生强度,即 `think: "high"`
对于原生 `/api/chat` 请求OpenClaw 会直接将 thinking 控制转发给 Ollama`/think off` 和 `openclaw agent --thinking off` 会发送顶层 `think: false`,而 `/think low|medium|high` 会发送对应的顶层 `think` 强度字符串。`/think max` 会映射到 Ollama 的最高原生强度,即 `think: "high"`
<Tip>
如果你需要使用 OpenAI 兼容端点,请参阅上方“旧版 OpenAI 兼容模式”部分。在该模式下,流式传输和工具调用可能无法同时工作。
如果你需要使用 OpenAI 兼容端点,请参阅上方“旧版 OpenAI 兼容模式”部分。在该模式下,流式传输和工具调用可能无法同时工作。
</Tip>
</Accordion>
@ -930,15 +938,15 @@ OpenClaw 支持 **Ollama Web 搜索**,作为内置的 `web_search` provider。
<AccordionGroup>
<Accordion title="WSL2 崩溃循环(反复重启)">
在带有 NVIDIA/CUDA 的 WSL2 上,官方 Ollama Linux 安装程序会创建一个 `ollama.service` systemd 单元,并设置 `Restart=always`。如果该服务在 WSL2 启动期间自动启动并加载 GPU 支持的模型Ollama 可能会在模型加载时锁定主机内存。Hyper-V 的内存回收并不总能回收这些被锁定的页面,因此 Windows 可能会终止 WSL2 VMsystemd 又会再次启动 Ollama于是循环重复发生。
在带有 NVIDIA/CUDA 的 WSL2 上,官方 Ollama Linux 安装程序会创建一个 `ollama.service` systemd 单元,并设置 `Restart=always`。如果该服务在 WSL2 启动时自动启动并加载 GPU 支持的模型Ollama 在模型加载期间可能会锁定主机内存。Hyper-V 的内存回收并不总能回收这些被锁定的页面,因此 Windows 可能会终止 WSL2 VMsystemd 又再次启动 Ollama于是循环反复发生。
常见证据:
- 从 Windows 侧看到 WSL2 反复重启或被终止
- WSL2 启动后不久,`app.slice` 或 `ollama.service` 的 CPU 占用很高
- Windows 侧反复出现 WSL2 重启或终止
- WSL2 启动后不久,`app.slice` 或 `ollama.service` 出现高 CPU 占用
- 来自 systemd 的 SIGTERM而不是 Linux OOM-killer 事件
当 OpenClaw 检测到 WSL2、启用了 `Restart=always``ollama.service`,并且检测到可见的 CUDA 标记时,会记录一条启动警告。
当 OpenClaw 检测到 WSL2、启用了 `Restart=always``ollama.service` 以及可见的 CUDA 标记时,会记录一条启动警告。
缓解方法:
@ -953,25 +961,25 @@ OpenClaw 支持 **Ollama Web 搜索**,作为内置的 `web_search` provider。
autoMemoryReclaim=disabled
```
在 Ollama 服务环境中设置更短的 keep-alive或仅在需要时手动启动 Ollama
在 Ollama 服务环境中设置更短的 keep-alive仅在需要时手动启动 Ollama
```bash
export OLLAMA_KEEP_ALIVE=5m
ollama serve
```
参见 [ollama/ollama#11317](https://github.com/ollama/ollama/issues/11317)。
请参阅 [ollama/ollama#11317](https://github.com/ollama/ollama/issues/11317)。
</Accordion>
<Accordion title="未检测到 Ollama">
请确保 Ollama 正在运行,并且你已设置 `OLLAMA_API_KEY`(或认证配置文件),同时**没有**定义显式的 `models.providers.ollama` 条目:
请确认 Ollama 正在运行,并且你已设置 `OLLAMA_API_KEY`(或 auth profile同时你**没有**定义显式的 `models.providers.ollama` 条目:
```bash
ollama serve
```
验证 API 可访问:
验证 API 是否可访问:
```bash
curl http://localhost:11434/api/tags
@ -980,10 +988,10 @@ OpenClaw 支持 **Ollama Web 搜索**,作为内置的 `web_search` provider。
</Accordion>
<Accordion title="没有可用模型">
如果你的模型未列出,请在本地拉取该模型,或在 `models.providers.ollama` 中显式定义它。
如果列表中没有你的模型,请在本地拉取该模型,或`models.providers.ollama` 中显式定义它。
```bash
ollama list # 查看已安装内容
ollama list # 查看已安装内容
ollama pull gemma4
ollama pull gpt-oss:20b
ollama pull llama3.3 # 或其他模型
@ -1005,7 +1013,7 @@ OpenClaw 支持 **Ollama Web 搜索**,作为内置的 `web_search` provider。
</Accordion>
<Accordion title="远程主机可通过 curl 访问,但 OpenClaw 不行">
在运行 Gateway 网关 的同一台机器和同一运行时中进行验证:
从运行 Gateway 网关的同一台机器和同一运行时环境中进行验证:
```bash
openclaw gateway status --deep
@ -1014,17 +1022,17 @@ OpenClaw 支持 **Ollama Web 搜索**,作为内置的 `web_search` provider。
常见原因:
- `baseUrl` 指向 `localhost`,但 Gateway 网关 运行在 Docker 中或另一台主机上。
- `baseUrl` 指向 `localhost`,但 Gateway 网关运行在 Docker 中或另一台主机上。
- URL 使用了 `/v1`,这会选择 OpenAI 兼容行为,而不是原生 Ollama。
- 远程主机在 Ollama 需要调整防火墙或局域网绑定设置。
- 模型存在于你笔记本电脑上的守护进程中,但不远程守护进程中。
- 远程主机在 Ollama 需要调整防火墙或局域网绑定设置。
- 模型存在于你笔记本电脑上的守护进程中,但不在远程守护进程中。
</Accordion>
<Accordion title="模型将工具 JSON 作为文本输出">
这通常意味着 provider 正在使用 OpenAI 兼容模式,或模型无法处理工具 schema。
这通常意味着 provider 正在使用 OpenAI 兼容模式,或模型无法处理工具 schema。
优先使用原生 Ollama 模式:
优先使用原生 Ollama 模式:
```json5
{
@ -1039,12 +1047,12 @@ OpenClaw 支持 **Ollama Web 搜索**,作为内置的 `web_search` provider。
}
```
如果较小的本地模型在工具 schema 上仍然失败,请在该模型条目上设置 `compat.supportsTools: false`,然后重新测试。
如果小型本地模型在工具 schema 上仍然失败,请在该模型条目中设置 `compat.supportsTools: false`,然后重新测试。
</Accordion>
<Accordion title="冷启动本地模型超时">
大型本地模型在开始流式输之前,首次加载可能需要较长时间。请将超时限制在 Ollama provider 范围内,并可选择要求 Ollama 在轮次之间保持模型已加载:
<Accordion title="冷启动本地模型超时">
大型本地模型在开始流式输之前,首次加载可能需要较长时间。请将超时限制在 Ollama provider 范围内,并可选择要求 Ollama 在轮次之间保持模型已加载:
```json5
{
@ -1065,12 +1073,12 @@ OpenClaw 支持 **Ollama Web 搜索**,作为内置的 `web_search` provider。
}
```
如果主机本身接受连接的速度较慢,`timeoutSeconds` 也会延长 provider 的受保护 Undici 连接超时。
如果主机本身接受连接的速度较慢,`timeoutSeconds` 也会延长 provider 的受保护 Undici 连接超时。
</Accordion>
<Accordion title="大上下文模型太慢或耗尽内存">
许多 Ollama 模型声明的上下文大小,超过了你的硬件可以舒适运行的范围。原生 Ollama 会使用它自己的运行时上下文默认值,除非你设置 `params.num_ctx`。当你希望获得可预测的首个 token 延迟时,请同时限制 OpenClaw 的预算和 Ollama 的请求上下文:
<Accordion title="大上下文模型太慢或内存不足">
许多 Ollama 模型声明的上下文长度,大于你的硬件能够舒适运行的范围。原生 Ollama 会使用它自己的运行时上下文默认值,除非你设置 `params.num_ctx`。当你想获得可预测的首 token 延迟时,请同时限制 OpenClaw 的预算和 Ollama 的请求上下文:
```json5
{
@ -1104,14 +1112,14 @@ OpenClaw 支持 **Ollama Web 搜索**,作为内置的 `web_search` provider。
## 相关内容
<CardGroup cols={2}>
<Card title="模型 provider" href="/zh-CN/concepts/model-providers" icon="layers">
所有 provider、模型引用和故障转移行为的概览。
<Card title="模型提供商" href="/zh-CN/concepts/model-providers" icon="layers">
所有 provider、模型引用和故障切换行为的概览。
</Card>
<Card title="模型选择" href="/zh-CN/concepts/models" icon="brain">
如何选择和配置模型。
</Card>
<Card title="Ollama Web 搜索" href="/zh-CN/tools/ollama-search" icon="magnifying-glass">
由 Ollama 驱动的 Web 搜索的完整设置和行为详情
由 Ollama 驱动的 Web 搜索的完整设置和行为细节
</Card>
<Card title="配置" href="/zh-CN/gateway/configuration" icon="gear">
完整的配置参考。

View File

@ -1,26 +1,26 @@
---
read_when:
- 你想配置 Memory 搜索提供商或嵌入模型
- 你想配置内存搜索提供商或嵌入模型
- 你想设置 QMD 后端
- 你想调优混合搜索、MMR 或时间衰减
- 你想启用多模态 Memory 索引
- 你想调整混合搜索、MMR 或时间衰减参数
- 你想启用多模态内存索引
sidebarTitle: Memory config
summary: 关于内存搜索、嵌入提供商、QMD、混合搜索和多模态索引的所有配置
title: Memory 配置参考
summary: 内存搜索、嵌入提供商、QMD、混合搜索和多模态索引的所有配置项
title: 内存配置参考
x-i18n:
generated_at: "2026-04-28T00:33:55Z"
generated_at: "2026-04-28T02:18:31Z"
model: gpt-5.4
provider: openai
source_hash: ae4993c3b6579be3086997bbd0938e81ce52cfb3b8964674630ab52e59cb1528
source_hash: 6dda6c28de377afaef6fdd951ff8e9f678c75cf969a1242e6f7a16e86c4a1137
source_path: reference/memory-config.md
workflow: 15
---
本页列出了 OpenClaw Memory 搜索的所有配置选项。概念性概览请参阅
此页面列出了 OpenClaw 内存搜索的所有配置项。有关概念性概览,请参见
<CardGroup cols={2}>
<Card title="Memory 概览" href="/zh-CN/concepts/memory">
Memory 的工作方式。
<Card title="内存概览" href="/zh-CN/concepts/memory">
内存的工作方式。
</Card>
<Card title="内置引擎" href="/zh-CN/concepts/memory-builtin">
默认的 SQLite 后端。
@ -28,37 +28,37 @@ x-i18n:
<Card title="QMD 引擎" href="/zh-CN/concepts/memory-qmd">
本地优先的 sidecar。
</Card>
<Card title="Memory 搜索" href="/zh-CN/concepts/memory-search">
<Card title="内存搜索" href="/zh-CN/concepts/memory-search">
搜索流水线与调优。
</Card>
<Card title="活跃 Memory" href="/zh-CN/concepts/active-memory">
用于交互式会话的 Memory 子智能体。
<Card title="活动内存" href="/zh-CN/concepts/active-memory">
用于交互式会话的内存子智能体。
</Card>
</CardGroup>
除非另有说明,所有 Memory 搜索设置都位于 `openclaw.json` `agents.defaults.memorySearch` 下。
除非另有说明,所有内存搜索设置都位于 `openclaw.json``agents.defaults.memorySearch` 下。
<Note>
如果你在寻找**活跃 Memory**功能开关和子智能体配置,它位于 `plugins.entries.active-memory` 下,而不是 `memorySearch`
如果你要查找 **活动内存**功能开关和子智能体配置,它位于 `plugins.entries.active-memory` 下,而不是 `memorySearch`
跃 Memory 使用双门控模型:
动内存采用双门控模型:
1. 插件必须已启用,并且目标指向当前智能体 id
2. 请求必须是符合条件的交互式持久聊天会话
有关激活模型、插件自有配置、对话持久化和安全发布模式,请参阅 [Active Memory](/zh-CN/concepts/active-memory)。
有关激活模型、插件自有配置、转录持久化以及安全发布模式,请参见 [活动内存](/zh-CN/concepts/active-memory)。
</Note>
---
## 提供商选择
| Key | Type | Default | Description |
| ---------- | --------- | ---------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `provider` | `string` | auto-detected | 嵌入适配器 id`bedrock`、`deepinfra`、`gemini`、`github-copilot`、`local`、`mistral`、`ollama`、`openai`、`voyage` |
| `model` | `string` | provider default | 嵌入模型名称 |
| `fallback` | `string` | `"none"` | 当主适配器失败时使用的回退适配器 id |
| `enabled` | `boolean` | `true` | 启用或禁用 Memory 搜索 |
| Key | Type | Default | Description |
| ---------- | --------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `provider` | `string` | 自动检测 | 嵌入适配器 ID例如 `bedrock`、`deepinfra`、`gemini`、`github-copilot`、`local`、`mistral`、`ollama`、`openai` 或 `voyage`;也可以是已配置的 `models.providers.<id>`,其 `api` 指向这些适配器之一 |
| `model` | `string` | 提供商默认值 | 嵌入模型名称 |
| `fallback` | `string` | `"none"` | 当主提供商失败时使用的回退适配器 ID |
| `enabled` | `boolean` | `true` | 启用或禁用内存搜索 |
### 自动检测顺序
@ -66,10 +66,10 @@ x-i18n:
<Steps>
<Step title="local">
如果配置 `memorySearch.local.modelPath` 且文件存在,则选择它。
如果配置 `memorySearch.local.modelPath` 且文件存在,则选择它。
</Step>
<Step title="github-copilot">
如果可以解析到 GitHub Copilot token环境变量或认证配置文件),则选择它。
如果可以解析到 GitHub Copilot token环境变量或 auth profile),则选择它。
</Step>
<Step title="openai">
如果可以解析到 OpenAI key则选择它。
@ -87,36 +87,63 @@ x-i18n:
如果可以解析到 DeepInfra key则选择它。
</Step>
<Step title="bedrock">
如果 AWS SDK 凭证链可解析实例角色、访问密钥、profile、SSO、web identity 或共享配置),则选择它。
如果 AWS SDK 凭证链可解析成功实例角色、访问密钥、profile、SSO、web identity 或共享配置),则选择它。
</Step>
</Steps>
支持 `ollama`,但不会自动检测(需要显式设置)。
支持 `ollama`,但不会自动检测(请显式设置)。
### 自定义提供商 ID
`memorySearch.provider` 可以指向自定义的 `models.providers.<id>` 条目。OpenClaw 会解析该提供商的 `api` 所有者作为嵌入适配器,同时保留自定义提供商 ID用于端点、认证和模型前缀处理。这使多 GPU 或多主机部署可以将内存嵌入专用于某个特定本地端点:
```json5
{
models: {
providers: {
"ollama-5080": {
api: "ollama",
baseUrl: "http://gpu-box.local:11435",
apiKey: "ollama-local",
models: [{ id: "qwen3-embedding:0.6b" }],
},
},
},
agents: {
defaults: {
memorySearch: {
provider: "ollama-5080",
model: "qwen3-embedding:0.6b",
},
},
},
}
```
### API key 解析
远程嵌入需要 API key。Bedrock 则使用 AWS SDK 默认凭证链实例角色、SSO、访问密钥
远程嵌入需要 API key。Bedrock 则改为使用 AWS SDK 默认凭证链实例角色、SSO、访问密钥
| Provider | Env var | Config key |
| -------------- | -------------------------------------------------- | ----------------------------------- |
| Bedrock | AWS credential chain | 不需要 API key |
| Bedrock | AWS 凭证链 | 不需要 API key |
| DeepInfra | `DEEPINFRA_API_KEY` | `models.providers.deepinfra.apiKey` |
| Gemini | `GEMINI_API_KEY` | `models.providers.google.apiKey` |
| GitHub Copilot | `COPILOT_GITHUB_TOKEN`, `GH_TOKEN`, `GITHUB_TOKEN` | 通过设备登录的认证配置文件 |
| GitHub Copilot | `COPILOT_GITHUB_TOKEN`, `GH_TOKEN`, `GITHUB_TOKEN` | 通过设备登录的 auth profile |
| Mistral | `MISTRAL_API_KEY` | `models.providers.mistral.apiKey` |
| Ollama | `OLLAMA_API_KEY`(占位符) | -- |
| OpenAI | `OPENAI_API_KEY` | `models.providers.openai.apiKey` |
| Voyage | `VOYAGE_API_KEY` | `models.providers.voyage.apiKey` |
<Note>
Codex OAuth 仅覆盖 chat/completions不能满足 embedding 请求。
Codex OAuth 仅覆盖 chat/completions满足嵌入请求。
</Note>
---
## 远程端点配置
用于自定义 OpenAI 兼容端点或覆盖提供商默认值:
于自定义 OpenAI 兼容端点或覆盖提供商默认值:
<ParamField path="remote.baseUrl" type="string">
自定义 API 基础 URL。
@ -125,7 +152,7 @@ Codex OAuth 仅覆盖 chat/completions不能满足 embedding 请求。
覆盖 API key。
</ParamField>
<ParamField path="remote.headers" type="object">
额外的 HTTP headers与提供商默认值合并)。
额外的 HTTP headers与提供商默认值合并
</ParamField>
```json5
@ -147,28 +174,28 @@ Codex OAuth 仅覆盖 chat/completions不能满足 embedding 请求。
---
## 提供商专配置
## 提供商专配置
<AccordionGroup>
<Accordion title="Gemini">
| Key | Type | Default | Description |
| ---------------------- | -------- | ---------------------- | ------------------------------------------ |
| `model` | `string` | `gemini-embedding-001` | 也支持 `gemini-embedding-2-preview` |
| `outputDimensionality` | `number` | `3072` | 对于 Embedding 2 768、1536 或 3072 |
| Key | Type | Default | Description |
| ---------------------- | -------- | ---------------------- | ----------------------------------------- |
| `model` | `string` | `gemini-embedding-001` | 也支持 `gemini-embedding-2-preview` |
| `outputDimensionality` | `number` | `3072` | 对于 Embedding 2 768、1536 或 3072 |
<Warning>
更改模型或 `outputDimensionality` 会触发自动全量重索引。
更改模型或 `outputDimensionality` 会触发自动全量重索引。
</Warning>
</Accordion>
<Accordion title="OpenAI 兼容输入类型">
OpenAI 兼容的 embedding 端点可以选择使用提供商特定的 `input_type` 请求字段。这对于需要为查询嵌入和文档嵌入使用不同标签的非对称嵌入模型非常有用
OpenAI 兼容嵌入端点可以选择启用提供商专属的 `input_type` 请求字段。这对于非对称嵌入模型很有用,因为这类模型要求查询嵌入和文档嵌入使用不同标签
| Key | Type | Default | Description |
| ------------------- | -------- | ------- | ------------------------------------------------------- |
| `inputType` | `string` | unset | 查询嵌入和文档嵌入共享的 `input_type` |
| `queryInputType` | `string` | unset | 查询时的 `input_type`;会覆盖 `inputType` |
| `documentInputType` | `string` | unset | 索引/文档用的 `input_type`;会覆盖 `inputType` |
| Key | Type | Default | Description |
| ------------------- | -------- | ------- | -------------------------------------------- |
| `inputType` | `string` | 未设置 | 查询嵌入与文档嵌入共用的 `input_type` |
| `queryInputType` | `string` | 未设置 | 查询时的 `input_type`;覆盖 `inputType` |
| `documentInputType` | `string` | 未设置 | 索引/文档时的 `input_type`覆盖 `inputType` |
```json5
{
@ -189,11 +216,11 @@ Codex OAuth 仅覆盖 chat/completions不能满足 embedding 请求。
}
```
更改这些值会影响提供商批量索引的 embedding 缓存标识;如果上游模型对这些标签有不同处理,应在更改后执行一次 Memory 重新索引。
更改这些值会影响提供商批量索引的嵌入缓存标识;如果上游模型会区别对待这些标签,则之后应执行一次内存重建索引。
</Accordion>
<Accordion title="Bedrock">
Bedrock 使用 AWS SDK 默认凭证链——不需要 API key。如果 OpenClaw 在具有 Bedrock 权限实例角色的 EC2 上运行,只需设置 provider 和 model
Bedrock 使用 AWS SDK 默认凭证链——不需要 API key。如果 OpenClaw 在带有 Bedrock 权限实例角色的 EC2 上运行,只需设置提供商和模型
```json5
{
@ -208,20 +235,20 @@ Codex OAuth 仅覆盖 chat/completions不能满足 embedding 请求。
}
```
| Key | Type | Default | Description |
| ---------------------- | -------- | ------------------------------ | ------------------------------- |
| `model` | `string` | `amazon.titan-embed-text-v2:0` | 任意 Bedrock embedding 模型 id |
| `outputDimensionality` | `number` | model default | 对于 Titan V2可选 256、512 或 1024 |
| Key | Type | Default | Description |
| ---------------------- | -------- | ------------------------------ | ------------------------------ |
| `model` | `string` | `amazon.titan-embed-text-v2:0` | 任意 Bedrock 嵌入模型 ID |
| `outputDimensionality` | `number` | 模型默认值 | 对于 Titan V2256、512 或 1024 |
**支持的模型**包含家族检测和默认维度):
**支持的模型**含模型族检测和默认维度):
| Model ID | Provider | Default Dims | Configurable Dims |
| ------------------------------------------ | ---------- | ------------ | -------------------- |
| `amazon.titan-embed-text-v2:0` | Amazon | 1024 | 256、512、1024 |
| `amazon.titan-embed-text-v2:0` | Amazon | 1024 | 256, 512, 1024 |
| `amazon.titan-embed-text-v1` | Amazon | 1536 | -- |
| `amazon.titan-embed-g1-text-02` | Amazon | 1536 | -- |
| `amazon.titan-embed-image-v1` | Amazon | 1024 | -- |
| `amazon.nova-2-multimodal-embeddings-v1:0` | Amazon | 1024 | 256、384、1024、3072 |
| `amazon.nova-2-multimodal-embeddings-v1:0` | Amazon | 1024 | 256, 384, 1024, 3072 |
| `cohere.embed-english-v3` | Cohere | 1024 | -- |
| `cohere.embed-multilingual-v3` | Cohere | 1024 | -- |
| `cohere.embed-v4:0` | Cohere | 1536 | 256-1536 |
@ -235,10 +262,10 @@ Codex OAuth 仅覆盖 chat/completions不能满足 embedding 请求。
1. 环境变量(`AWS_ACCESS_KEY_ID` + `AWS_SECRET_ACCESS_KEY`
2. SSO token 缓存
3. Web identity token 凭证
4. 共享凭证配置文件
4. 共享凭证配置文件
5. ECS 或 EC2 元数据凭证
区域会从 `AWS_REGION`、`AWS_DEFAULT_REGION`、`amazon-bedrock` 提供商的 `baseUrl` 中解析,或默认使用 `us-east-1`
区域会从 `AWS_REGION`、`AWS_DEFAULT_REGION`、`amazon-bedrock` 提供商的 `baseUrl` 中解析,或默认使用 `us-east-1`
**IAM 权限:** IAM 角色或用户需要:
@ -250,7 +277,7 @@ Codex OAuth 仅覆盖 chat/completions不能满足 embedding 请求。
}
```
了实现最小权限,请将 `InvokeModel` 限定到具体模型:
遵循最小权限原则,可将 `InvokeModel` 限定到特定模型:
```
arn:aws:bedrock:*::foundation-model/amazon.titan-embed-text-v2:0
@ -258,22 +285,22 @@ Codex OAuth 仅覆盖 chat/completions不能满足 embedding 请求。
</Accordion>
<Accordion title="本地GGUF + node-llama-cpp">
| Key | Type | Default | Description |
| --------------------- | ------------------ | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `local.modelPath` | `string` | auto-downloaded | GGUF 模型文件路径 |
| `local.modelCacheDir` | `string` | node-llama-cpp default | 已下载模型的缓存目录 |
| `local.contextSize` | `number \| "auto"` | `4096` | 嵌入上下文的上下文窗口大小。4096 可覆盖典型分块128512 token同时控制非权重 VRAM 占用。在资源受限的宿主机上,可降到 10242048。`"auto"` 会使用模型训练时的最大值——不建议用于 8B 及以上模型Qwen3-Embedding-8B40 960 token → 约 32 GB VRAM而在 4096 时约为 8.8 GB。 |
| Key | Type | Default | Description |
| --------------------- | ------------------ | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `local.modelPath` | `string` | 自动下载 | GGUF 模型文件路径 |
| `local.modelCacheDir` | `string` | node-llama-cpp 默认值 | 已下载模型的缓存目录 |
| `local.contextSize` | `number \| "auto"` | `4096` | 嵌入上下文的上下文窗口大小。4096 可覆盖典型分块128512 token同时限制非权重 VRAM 占用。在受限主机上可降到 10242048。`"auto"` 使用模型训练时的最大值——不建议用于 8B+ 模型Qwen3-Embedding-8B40 960 token → 约 32 GB VRAM而在 4096 时约为 8.8 GB。 |
默认模型:`embeddinggemma-300m-qat-Q8_0.gguf`(约 0.6 GB自动下载)。需要原生构建:`pnpm approve-builds`,然后执行 `pnpm rebuild node-llama-cpp`
默认模型:`embeddinggemma-300m-qat-Q8_0.gguf`(约 0.6 GB自动下载。需要原生构建`pnpm approve-builds`,然后执行 `pnpm rebuild node-llama-cpp`
使用独立 CLI 验证 Gateway 网关所使用的同一 provider 路径:
使用独立 CLI 验证 Gateway 网关 所使用的同一提供商路径:
```bash
openclaw memory status --deep --agent main
openclaw memory index --force --agent main
```
如果 `provider``auto`,只有当 `local.modelPath` 指向一个已存在的本地文件时,才会选择 `local`。`hf:` 和 HTTP(S) 模型引用仍然可以在显式设置 `provider: "local"`使用,但在模型尚未落盘可用之前,它们不会让 `auto` 优先选择 local。
如果 `provider``auto`,只有当 `local.modelPath` 指向现有本地文件时才会选择 `local`。`hf:` 和 HTTP(S) 模型引用在显式设置 `provider: "local"`仍可使用,但在模型尚未出现在磁盘上之前,它们不会让 `auto` 优先选择 local。
</Accordion>
</AccordionGroup>
@ -281,9 +308,9 @@ Codex OAuth 仅覆盖 chat/completions不能满足 embedding 请求。
### 内联嵌入超时
<ParamField path="sync.embeddingBatchTimeoutSeconds" type="number">
覆盖 Memory 索引期间内联嵌入批次的超时时间。
覆盖内存索引期间内联嵌入批次的超时时间。
未设置时将使用 provider 默认值:对于 `local`、`ollama` 和 `lmstudio` 等本地/自托管 provider 为 600 秒,对于托管 provider 为 120 秒。当本地 CPU 受限的嵌入批次运行正常但较慢时,请增大该值。
未设置时使用提供商默认值:对于 `local`、`ollama` 和 `lmstudio` 这类本地/自托管提供商为 600 秒,对于托管提供商为 120 秒。当本地 CPU 密集型嵌入批次运行正常但速度较慢时,请增大该值。
</ParamField>
---
@ -292,27 +319,27 @@ Codex OAuth 仅覆盖 chat/completions不能满足 embedding 请求。
全部位于 `memorySearch.query.hybrid` 下:
| Key | Type | Default | Description |
| --------------------- | --------- | ------- | ---------------------------------- |
| `enabled` | `boolean` | `true` | 启用混合 BM25 + 向量搜索 |
| `vectorWeight` | `number` | `0.7` | 向量分数权重0-1 |
| `textWeight` | `number` | `0.3` | BM25 分数权重0-1 |
| `candidateMultiplier` | `number` | `4` | 候选池大小倍率 |
| Key | Type | Default | Description |
| --------------------- | --------- | ------- | ---------------------------- |
| `enabled` | `boolean` | `true` | 启用 BM25 + 向量混合搜索 |
| `vectorWeight` | `number` | `0.7` | 向量分数权重0-1 |
| `textWeight` | `number` | `0.3` | BM25 分数权重0-1 |
| `candidateMultiplier` | `number` | `4` | 候选池大小乘数 |
<Tabs>
<Tab title="MMR多样性">
| Key | Type | Default | Description |
| ------------- | --------- | ------- | ------------------------------------ |
| `mmr.enabled` | `boolean` | `false` | 启用 MMR 重排序 |
| Key | Type | Default | Description |
| ------------- | --------- | ------- | ------------------------------ |
| `mmr.enabled` | `boolean` | `false` | 启用 MMR 重排序 |
| `mmr.lambda` | `number` | `0.7` | 0 = 最大多样性1 = 最大相关性 |
</Tab>
<Tab title="时间衰减(时效性)">
| Key | Type | Default | Description |
| ---------------------------- | --------- | ------- | ------------------------- |
| `temporalDecay.enabled` | `boolean` | `false` | 启用时效性加权 |
| `temporalDecay.halfLifeDays` | `number` | `30` | 分数每 N 天减半 |
| Key | Type | Default | Description |
| ---------------------------- | --------- | ------- | -------------------- |
| `temporalDecay.enabled` | `boolean` | `false` | 启用时效性加权 |
| `temporalDecay.halfLifeDays` | `number` | `30` | 分数每 N 天减半 |
常青文件(`MEMORY.md`、`memory/` 中不带日期的文件)永不衰减。
常青文件(`MEMORY.md`、`memory/` 中无日期的文件)永远不会衰减。
</Tab>
</Tabs>
@ -340,11 +367,11 @@ Codex OAuth 仅覆盖 chat/completions不能满足 embedding 请求。
---
## 额外 Memory 路径
## 额外内存路径
| Key | Type | Description |
| ------------ | ---------- | ---------------------------------------- |
| `extraPaths` | `string[]` | 要索引的额外目录或文件 |
| Key | Type | Description |
| ------------ | ---------- | -------------------------- |
| `extraPaths` | `string[]` | 要索引的额外目录或文件路径 |
```json5
{
@ -358,24 +385,24 @@ Codex OAuth 仅覆盖 chat/completions不能满足 embedding 请求。
}
```
路径可以是绝对路径,也可以是相对于工作区的路径。目录会递归扫描其中的 `.md` 文件。符号链接处理取决于当前后端:内置引擎会忽略符号链接,而 QMD 会遵循底层 QMD 扫描器的行为。
路径可以是绝对路径,也可以是相对于工作区的路径。目录会递归扫描其中的 `.md` 文件。符号链接处理方式取决于当前后端:内置引擎会忽略符号链接,而 QMD 会遵循底层 QMD 扫描器的行为。
对于按智能体作用域划分的跨智能体对话检索,请使用 `agents.list[].memorySearch.qmd.extraCollections`,而不是 `memory.qmd.paths`。这些额外集合沿用相同的 `{ path, name, pattern? }` 结构,但会按智能体进行合并,并且当路径指向当前工作区之外时,可以保留显式共享名称。如果同一个解析路径同时出现在 `memory.qmd.paths``memorySearch.qmd.extraCollections`QMD 会保留第一项并跳过重复项。
对于按智能体作用域的跨智能体转录搜索,请使用 `agents.list[].memorySearch.qmd.extraCollections`,而不是 `memory.qmd.paths`。这些额外集合使用相同的 `{ path, name, pattern? }` 结构,但会按智能体合并,并且当路径指向当前工作区之外时,可以保留显式共享名称。如果同一个解析路径同时出现在 `memory.qmd.paths``memorySearch.qmd.extraCollections`QMD 会保留第一项并跳过重复项。
---
## 多模态 MemoryGemini
## 多模态内存Gemini
使用 Gemini Embedding 2同时为 Markdown、图像和音频建立索引:
使用 Gemini Embedding 2将图像和音频与 Markdown 一起建立索引:
| Key | Type | Default | Description |
| ------------------------- | ---------- | ---------- | -------------------------------------- |
| `multimodal.enabled` | `boolean` | `false` | 启用多模态索引 |
| Key | Type | Default | Description |
| ------------------------- | ---------- | ---------- | -------------------- |
| `multimodal.enabled` | `boolean` | `false` | 启用多模态索引 |
| `multimodal.modalities` | `string[]` | -- | `["image"]`、`["audio"]` 或 `["all"]` |
| `multimodal.maxFileBytes` | `number` | `10000000` | 建立索引时允许的最大文件大小 |
| `multimodal.maxFileBytes` | `number` | `10000000` | 建立索引的最大文件大小 |
<Note>
仅适用于 `extraPaths` 中的文件。默认 Memory 根路径仍然只支持 Markdown。需要 `gemini-embedding-2-preview`。`fallback` 必须为 `"none"`
仅适用于 `extraPaths` 中的文件。默认内存根目录仍然只支持 Markdown。需要 `gemini-embedding-2-preview`。`fallback` 必须为 `"none"`
</Note>
支持的格式:`.jpg`、`.jpeg`、`.png`、`.webp`、`.gif`、`.heic`、`.heif`(图像);`.mp3`、`.wav`、`.ogg`、`.opus`、`.m4a`、`.aac`、`.flac`(音频)。
@ -384,57 +411,57 @@ Codex OAuth 仅覆盖 chat/completions不能满足 embedding 请求。
## 嵌入缓存
| Key | Type | Default | Description |
| ------------------ | --------- | ------- | -------------------------------- |
| `cache.enabled` | `boolean` | `false` | 在 SQLite 中缓存分块嵌入 |
| `cache.maxEntries` | `number` | `50000` | 最大缓存嵌入数量 |
| Key | Type | Default | Description |
| ------------------ | --------- | ------- | ------------------------------ |
| `cache.enabled` | `boolean` | `false` | 在 SQLite 中缓存分块嵌入 |
| `cache.maxEntries` | `number` | `50000` | 最大缓存嵌入条目数 |
可防止在重新索引或更新对话记录时,对未变化的文本重复生成嵌入。
可防止在重建索引或更新转录时,对未更改文本重复执行嵌入。
---
## 批量索引
| Key | Type | Default | Description |
| ----------------------------- | --------- | ------- | -------------------------- |
| `remote.nonBatchConcurrency` | `number` | `4` | 并行内联嵌入 |
| `remote.batch.enabled` | `boolean` | `false` | 启用批量嵌入 API |
| `remote.batch.concurrency` | `number` | `2` | 并行批处理任务数 |
| `remote.batch.wait` | `boolean` | `true` | 等待批处理完成 |
| `remote.batch.pollIntervalMs` | `number` | -- | 轮询间隔 |
| `remote.batch.timeoutMinutes` | `number` | -- | 批处理超时 |
| Key | Type | Default | Description |
| ----------------------------- | --------- | ------- | -------------------- |
| `remote.nonBatchConcurrency` | `number` | `4` | 并行内联嵌入 |
| `remote.batch.enabled` | `boolean` | `false` | 启用批量嵌入 API |
| `remote.batch.concurrency` | `number` | `2` | 并行批处理任务数 |
| `remote.batch.wait` | `boolean` | `true` | 等待批处理完成 |
| `remote.batch.pollIntervalMs` | `number` | -- | 轮询间隔 |
| `remote.batch.timeoutMinutes` | `number` | -- | 批处理超时时间 |
适用于 `openai`、`gemini` 和 `voyage`。对于大规模回填OpenAI 的批处理通常最快且成本最低。
适用于 `openai`、`gemini` 和 `voyage`。对于大型历史回填OpenAI 批处理通常最快且成本最低。
`remote.nonBatchConcurrency` 控制内联嵌入调用,这些调用用于本地/自托管 provider以及未启用 provider 批量 API 时的托管 provider。为了避免压垮较小的本地主机Ollama 在非批量索引时默认值为 `1`;在更大的机器上,你设置更高值。
`remote.nonBatchConcurrency` 控制内联嵌入调用,供本地/自托管提供商使用,以及在提供商批量 API 未启用时供托管提供商使用。Ollama 在非批量索引时默认值为 `1`,以避免压垮较小的本地主机;在更大的机器上可设置更高值。
这与 `sync.embeddingBatchTimeoutSeconds` 不同,后者控制内联嵌入调用的超时时间。
这与 `sync.embeddingBatchTimeoutSeconds` 是分开的,后者控制内联嵌入调用的超时时间。
---
## 会话 Memory 搜索(实验性)
## 会话内存搜索(实验性)
对会话对话记录建立索引,并通过 `memory_search` 暴露
为会话转录建立索引,并通过 `memory_search` 提供结果
| Key | Type | Default | Description |
| ----------------------------- | ---------- | ------------ | --------------------------------------- |
| `experimental.sessionMemory` | `boolean` | `false` | 启用会话索引 |
| `sources` | `string[]` | `["memory"]` | 添加 `"sessions"` 以包含对话记录 |
| `sync.sessions.deltaBytes` | `number` | `100000` | 触发重新索引的字节阈值 |
| `sync.sessions.deltaMessages` | `number` | `50` | 触发重新索引的消息阈值 |
| Key | Type | Default | Description |
| ----------------------------- | ---------- | ------------ | ------------------------------------- |
| `experimental.sessionMemory` | `boolean` | `false` | 启用会话索引 |
| `sources` | `string[]` | `["memory"]` | 添加 `"sessions"` 以包含转录 |
| `sync.sessions.deltaBytes` | `number` | `100000` | 触发重建索引的字节阈值 |
| `sync.sessions.deltaMessages` | `number` | `50` | 触发重建索引的消息阈值 |
<Warning>
会话索引需要显式启用,并且异步运行。结果可能会略有滞后。会话日志存储在磁盘上,因此请将文件系统访问视为信任边界。
会话索引需要显式启用,并以异步方式运行。结果可能会略有陈旧。会话日志存储在磁盘上,因此请将文件系统访问视为信任边界。
</Warning>
---
## SQLite 向量加速sqlite-vec
| Key | Type | Default | Description |
| ---------------------------- | --------- | ------- | --------------------------------- |
| `store.vector.enabled` | `boolean` | `true` | 使用 sqlite-vec 执行向量查询 |
| `store.vector.extensionPath` | `string` | bundled | 覆盖 sqlite-vec 路径 |
| Key | Type | Default | Description |
| ---------------------------- | --------- | ------- | ------------------------------- |
| `store.vector.enabled` | `boolean` | `true` | 使用 sqlite-vec 执行向量查询 |
| `store.vector.extensionPath` | `string` | bundled | 覆盖 sqlite-vec 路径 |
当 sqlite-vec 不可用时OpenClaw 会自动回退到进程内余弦相似度计算。
@ -442,10 +469,10 @@ Codex OAuth 仅覆盖 chat/completions不能满足 embedding 请求。
## 索引存储
| Key | Type | Default | Description |
| --------------------- | -------- | ------------------------------------- | ------------------------------------------- |
| `store.path` | `string` | `~/.openclaw/memory/{agentId}.sqlite` | 索引位置(支持 `{agentId}` token |
| `store.fts.tokenizer` | `string` | `unicode61` | FTS5 分词器(`unicode61` 或 `trigram` |
| Key | Type | Default | Description |
| --------------------- | -------- | ------------------------------------- | ----------------------------------------- |
| `store.path` | `string` | `~/.openclaw/memory/{agentId}.sqlite` | 索引位置(支持 `{agentId}` token |
| `store.fts.tokenizer` | `string` | `unicode61` | FTS5 分词器(`unicode61` 或 `trigram` |
---
@ -453,47 +480,47 @@ Codex OAuth 仅覆盖 chat/completions不能满足 embedding 请求。
设置 `memory.backend = "qmd"` 以启用。所有 QMD 设置都位于 `memory.qmd` 下:
| Key | Type | Default | Description |
| ------------------------ | --------- | -------- | ------------------------------------------------------------------------------------- |
| `command` | `string` | `qmd` | QMD 可执行文件路径;当服务的 `PATH` 与你的 shell 不同时,请设置绝对路径 |
| `searchMode` | `string` | `search` | 搜索命令:`search`、`vsearch`、`query` |
| `includeDefaultMemory` | `boolean` | `true` | 自动索引 `MEMORY.md` + `memory/**/*.md` |
| `paths[]` | `array` | -- | 额外路径:`{ name, path, pattern? }` |
| `sessions.enabled` | `boolean` | `false` | 索引会话对话记录 |
| `sessions.retentionDays` | `number` | -- | 对话记录保留时间 |
| `sessions.exportDir` | `string` | -- | 导出目录 |
| Key | Type | Default | Description |
| ------------------------ | --------- | -------- | ----------------------------------------------------------------------------------- |
| `command` | `string` | `qmd` | QMD 可执行文件路径;当服务的 `PATH` 与你的 shell 不同时,请设置绝对路径 |
| `searchMode` | `string` | `search` | 搜索命令:`search`、`vsearch`、`query` |
| `includeDefaultMemory` | `boolean` | `true` | 自动索引 `MEMORY.md` + `memory/**/*.md` |
| `paths[]` | `array` | -- | 额外路径:`{ name, path, pattern? }` |
| `sessions.enabled` | `boolean` | `false` | 为会话转录建立索引 |
| `sessions.retentionDays` | `number` | -- | 转录保留时长 |
| `sessions.exportDir` | `string` | -- | 导出目录 |
`searchMode: "search"` 仅支持词法/BM25 搜索。对于该模式OpenClaw 不会运行语义向量就绪性探测,也不会执行 QMD 嵌入维护,包括在 `memory status --deep` 期间;`vsearch` 和 `query` 仍然要求 QMD 向量就绪和嵌入可用。
`searchMode: "search"` 仅支持词法/BM25 搜索。对于该模式OpenClaw 不会运行语义向量就绪性探测,也不会执行 QMD 嵌入维护,包括在 `memory status --deep` 期间;`vsearch` 和 `query` 仍然要求 QMD 向量就绪和嵌入可用。
OpenClaw 优先使用当前的 QMD collection 和 MCP query 结构,但也会在需要时尝试兼容的 collection pattern 标志以及旧版 MCP 工具名称,以保持对旧版 QMD 发布的兼容性。当 QMD 宣告支持多个 collection 过滤器时,来自同一来源的 collection 会通过单个 QMD 进程进行搜索;较旧的 QMD 版本则保留按 collection 分别处理的兼容路径。同一来源意味着持久 Memory collection 会被分组在一起,而会话对话记录 collection 会保持为单独一组,从而使来源多样化仍然保留这两种输入。
OpenClaw 优先使用当前的 QMD collection 和 MCP 查询结构,但也会通过在需要时尝试兼容的 collection pattern flags 和较旧的 MCP 工具名称,来保持对旧版 QMD 发布的兼容。当 QMD 宣布支持多个 collection 过滤器时,同源 collection 会通过单个 QMD 进程进行搜索;较旧的 QMD 构建则继续使用按 collection 分开的兼容路径。同源意味着持久内存 collection 会被归为一组,而会话转录 collection 仍会保留为单独一组,以便来源多样化仍然同时包含两种输入。
<Note>
QMD 模型覆盖设置保留在 QMD 侧,而不是 OpenClaw 配置中。如果你需要全局覆盖 QMD 的模型,请在 Gateway 网关运行时环境中设置环境变量,例如 `QMD_EMBED_MODEL`、`QMD_RERANK_MODEL` 和 `QMD_GENERATE_MODEL`
QMD 模型覆盖保留在 QMD 侧,而不是 OpenClaw 配置中。如果你需要全局覆盖 QMD 的模型,请在 Gateway 网关 运行时环境中设置环境变量,例如 `QMD_EMBED_MODEL`、`QMD_RERANK_MODEL` 和 `QMD_GENERATE_MODEL`
</Note>
<AccordionGroup>
<Accordion title="更新计划">
| Key | Type | Default | Description |
| ------------------------- | --------- | ------- | ------------------------------------- |
| `update.interval` | `string` | `5m` | 刷新间隔 |
| `update.debounceMs` | `number` | `15000` | 文件变更防抖 |
| `update.onBoot` | `boolean` | `true` | 启动时刷新 |
| `update.waitForBootSync` | `boolean` | `false` | 启动时阻塞直到刷新完成 |
| `update.embedInterval` | `string` | -- | 单独的嵌入执行频率 |
| `update.commandTimeoutMs` | `number` | -- | QMD 命令超时时间 |
| `update.updateTimeoutMs` | `number` | -- | QMD 更新操作超时时间 |
| `update.embedTimeoutMs` | `number` | -- | QMD 嵌入操作超时时间 |
| Key | Type | Default | Description |
| ------------------------- | --------- | ------- | --------------------------- |
| `update.interval` | `string` | `5m` | 刷新间隔 |
| `update.debounceMs` | `number` | `15000` | 文件变更防抖 |
| `update.onBoot` | `boolean` | `true` | 启动时刷新 |
| `update.waitForBootSync` | `boolean` | `false` | 启动时阻塞直到刷新完成 |
| `update.embedInterval` | `string` | -- | 单独的嵌入更新频率 |
| `update.commandTimeoutMs` | `number` | -- | QMD 命令超时时间 |
| `update.updateTimeoutMs` | `number` | -- | QMD 更新操作超时时间 |
| `update.embedTimeoutMs` | `number` | -- | QMD 嵌入操作超时时间 |
</Accordion>
<Accordion title="限制">
| Key | Type | Default | Description |
| ------------------------- | -------- | ------- | -------------------------- |
| `limits.maxResults` | `number` | `6` | 最大搜索结果数 |
| `limits.maxSnippetChars` | `number` | -- | 限制摘录长度 |
| `limits.maxInjectedChars` | `number` | -- | 限制注入的总字符数 |
| `limits.timeoutMs` | `number` | `4000` | 搜索超时时间 |
| Key | Type | Default | Description |
| ------------------------- | -------- | ------- | -------------------- |
| `limits.maxResults` | `number` | `6` | 最大搜索结果数 |
| `limits.maxSnippetChars` | `number` | -- | 限制摘要长度 |
| `limits.maxInjectedChars` | `number` | -- | 限制注入字符 |
| `limits.timeoutMs` | `number` | `4000` | 搜索超时时间 |
</Accordion>
<Accordion title="范围">
控制哪些会话可以接收 QMD 搜索结果。schema 与 [`session.sendPolicy`](/zh-CN/gateway/config-agents#session) 相同:
<Accordion title="作用范围">
控制哪些会话可以接收 QMD 搜索结果。使用与 [`session.sendPolicy`](/zh-CN/gateway/config-agents#session) 相同的 schema
```json5
{
@ -508,19 +535,19 @@ QMD 模型覆盖设置保留在 QMD 侧,而不是 OpenClaw 配置中。如果
}
```
已发布的默认配置允许私信和渠道会话,同时仍然拒绝群组
已发布的默认设置允许 direct 和 channel 会话,同时仍然拒绝 group
默认仅限私信。`match.keyPrefix` 匹配标准化后的会话键;`match.rawKeyPrefix` 匹配原始键,包括 `agent:<id>:`
默认仅限私信。`match.keyPrefix` 匹配规范化后的会话键;`match.rawKeyPrefix` 匹配包含 `agent:<id>:` 的原始键
</Accordion>
<Accordion title="引用">
`memory.citations` 适用于所有后端:
| Value | Behavior |
| ---------------- | --------------------------------------------------- |
| `auto` (default) | 在摘录中包含 `Source: <path#line>` 页脚 |
| `on` | 始终包含页脚 |
| `off` | 省略页脚(路径仍会在内部传递给智能体) |
| Value | Behavior |
| ---------------- | --------------------------------------------- |
| `auto`(默认) | 在摘要中包含 `Source: <path#line>` 页脚 |
| `on` | 始终包含页脚 |
| `off` | 省略页脚(路径仍会在内部传递给智能体) |
</Accordion>
</AccordionGroup>
@ -552,17 +579,17 @@ QMD 模型覆盖设置保留在 QMD 侧,而不是 OpenClaw 配置中。如果
Dreaming 配置位于 `plugins.entries.memory-core.config.dreaming` 下,而不是 `agents.defaults.memorySearch` 下。
Dreaming 以一次计划任务扫描运行,并将内部的 light/deep/REM 阶段作为实现细节处理
Dreaming 作为一次计划中的完整扫描运行,并将内部的 light/deep/REM 阶段作为实现细节来使用
关于概念行为和斜杠命令,请参阅 [Dreaming](/zh-CN/concepts/dreaming)。
有关概念行为和斜杠命令,请参见 [Dreaming](/zh-CN/concepts/dreaming)。
### 用户设置
| Key | Type | Default | Description |
| ----------- | --------- | ------------- | ------------------------------------------------- |
| `enabled` | `boolean` | `false` | 完全启用或禁用 Dreaming |
| `frequency` | `string` | `0 3 * * *` | 可选的完整 Dreaming 扫描 cron 频率 |
| `model` | `string` | default model | 可选的 Dream Diary 子智能体模型覆盖 |
| Key | Type | Default | Description |
| ----------- | --------- | ------------- | ------------------------------------ |
| `enabled` | `boolean` | `false` | 完全启用或禁用 Dreaming |
| `frequency` | `string` | `0 3 * * *` | 完整 Dreaming 扫描的可选 cron 频率 |
| `model` | `string` | 默认模型 | 可选的 Dream Diary 子智能体模型覆盖 |
### 示例
@ -591,12 +618,12 @@ Dreaming 以一次计划任务扫描运行,并将内部的 light/deep/REM 阶
<Note>
- Dreaming 会将机器状态写入 `memory/.dreams/`
- Dreaming 会将人类可读的叙事输出写入 `DREAMS.md`(或现有的 `dreams.md`)。
- `dreaming.model` 使用现有插件子智能体信任门控;启用前请先设置 `plugins.entries.memory-core.subagent.allowModelOverride: true`
- `dreaming.model` 使用现有插件子智能体信任门控;启用它之请先设置 `plugins.entries.memory-core.subagent.allowModelOverride: true`
- light/deep/REM 阶段策略和阈值属于内部行为,不是面向用户的配置。
</Note>
## 相关内容
- [配置参考](/zh-CN/gateway/configuration-reference)
- [Memory 概览](/zh-CN/concepts/memory)
- [Memory 搜索](/zh-CN/concepts/memory-search)
- [内存概览](/zh-CN/concepts/memory)
- [内存搜索](/zh-CN/concepts/memory-search)