chore(i18n): refresh zh-CN translations

This commit is contained in:
openclaw-docs-i18n[bot] 2026-04-27 08:34:01 +00:00
parent 3c8e63e070
commit 01088d8536
4 changed files with 466 additions and 623 deletions

View File

@ -1,52 +1,52 @@
---
read_when:
- 诊断证配置文件轮换、冷却机制或模型回退行为
- 更新证配置文件或模型的回退规则
- 诊断证配置文件轮换、冷却机制或模型回退行为
- 更新证配置文件或模型的回退规则
- 了解会话模型覆盖如何与回退重试交互
sidebarTitle: Model failover
summary: OpenClaw 如何轮换认证配置文件,以及如何在不同模型之间进行回退
summary: OpenClaw 如何轮换凭证配置文件并在不同模型之间回退
title: 模型回退
x-i18n:
generated_at: "2026-04-27T08:25:10Z"
generated_at: "2026-04-27T08:31:22Z"
model: gpt-5.4
provider: openai
source_hash: b652e0bfb30aa698f0badbd341e615eb110254ca08abb1896189e95b0f9d4c61
source_hash: 7b6fd539fddce6f7dfee9bf04076026b09fb1b84c5c170578bca9643e0105bd4
source_path: concepts/model-failover.md
workflow: 15
---
OpenClaw 分两个阶段处理失败:
1. 当前提供商内的**认证配置文件轮换**。
2. 回退到 `agents.defaults.model.fallbacks` 中的下一个**模型回退**。
1. 当前提供商内的**凭证配置文件轮换**
2. **模型回退**`agents.defaults.model.fallbacks` 中的下一个模型
本文档解释运行时规则以及支撑这些规则的数据。
## 运行时流程
对于一次普通文本运行OpenClaw 会按以下顺序评估候选项:
对于普通文本运行OpenClaw 会按以下顺序评估候选项:
<Steps>
<Step title="解析会话状态">
解析当前激活的会话模型和认证配置文件偏好。带有 `modelOverrideSource: "auto"` 的会话覆盖来自先前的一次回退,因此下一次运行会先清除它,再重试已配置的主模型;由用户选择的覆盖会保持粘性
解析当前激活的会话模型和凭证配置文件偏好
</Step>
<Step title="构建候选链">
从当前选中的会话模型开始,按顺序加入 `agents.defaults.model.fallbacks`,构建模型候选链;如果本次运行是从某个覆盖开始,则最后再加上已配置的主模型
从当前选中的会话模型构建模型候选链,然后按顺序加入 `agents.defaults.model.fallbacks`,如果本次运行起始于某个覆盖项,则最终以已配置的主模型结尾
</Step>
<Step title="尝试当前提供商">
使用认证配置文件轮换 / 冷却规则尝试当前提供商。
使用凭证配置文件轮换/冷却规则尝试当前提供商。
</Step>
<Step title="在值得回退的错误上进">
如果该提供商因值得回退的错误而耗尽,则移动到下一个模型候选项。
<Step title="在值得回退的错误上进">
如果该提供商因值得回退的错误而耗尽,则移动到下一个模型候选项。
</Step>
<Step title="持久化回退覆盖">
在重试开始前持久化选中的回退覆盖,这样其他会话读取方能看到运行器即将使用的相同提供商 / 模型。持久化的模型覆盖会标记为 `modelOverrideSource: "auto"`
在重试开始前持久化所选的回退覆盖,这样其他会话读取方就会看到运行器即将使用的相同提供商/模型。持久化的模型覆盖会标记为 `modelOverrideSource: "auto"`
</Step>
<Step title="在失败时进行窄范围回滚">
如果回退候选项失败,仅在这些字段仍与该失败候选项匹配时,回滚由回退拥有的会话覆盖字段。
<Step title="在失败时进行精确回滚">
如果回退候选项失败,仅回滚由回退拥有的会话覆盖字段,前提是这些字段仍与该失败候选项匹配
</Step>
<Step title="若已耗尽则抛出 FallbackSummaryError">
如果每个候选项都失败,则抛出一个 `FallbackSummaryError`,其中包含每次尝试的详细信息,以及已知时的最早冷却到期时间。
<Step title="耗尽时抛出 FallbackSummaryError">
如果每个候选项都失败,则抛出一个 `FallbackSummaryError`,其中包含每次尝试的详细信息,以及已知情况下最早的冷却到期时间。
</Step>
</Steps>
@ -54,108 +54,108 @@ OpenClaw 分两个阶段处理失败:
- `providerOverride`
- `modelOverride`
- `modelOverrideSource`
- `authProfileOverride`
- `authProfileOverrideSource`
- `authProfileOverrideCompactionCount`
样可以防止一次失败的回退重试覆盖更新得更晚、且与之无关的会话变更,例如在该尝试运行期间发生的手动 `/model` 更改或会话轮换更新。
可以防止失败的回退重试覆盖较新的无关会话变更,例如尝试运行期间发生的手动 `/model` 更改或会话轮换更新。
## 凭证存储(密钥 + OAuth
OpenClaw 对 API 密钥和 OAuth 令牌都使用**证配置文件**。
OpenClaw 对 API 密钥和 OAuth 令牌都使用**证配置文件**。
- 密钥凭证存放`~/.openclaw/agents/<agentId>/agent/auth-profiles.json`(旧路径:`~/.openclaw/agent/auth-profiles.json`)。
- 运行时认证路由状态存放`~/.openclaw/agents/<agentId>/agent/auth-state.json`
- 配置 `auth.profiles` / `auth.order` **仅包含元数据和路由**(不含密钥)。
- 旧版仅导入用 OAuth 文件:`~/.openclaw/credentials/oauth.json`(首次使用时导入到 `auth-profiles.json`)。
- 密钥保存`~/.openclaw/agents/<agentId>/agent/auth-profiles.json`(旧路径:`~/.openclaw/agent/auth-profiles.json`)。
- 运行时凭证路由状态保存`~/.openclaw/agents/<agentId>/agent/auth-state.json`
- 配置 `auth.profiles` / `auth.order` **仅用于元数据 + 路由**(不包含密钥)。
- 旧版仅导入用 OAuth 文件:`~/.openclaw/credentials/oauth.json`(首次使用时导入到 `auth-profiles.json`)。
更多细节: [OAuth](/zh-CN/concepts/oauth)
凭证类型:
- `type: "api_key"``{ provider, key }`
- `type: "oauth"``{ provider, access, refresh, expires, email? }`(某些提供商还包含 `projectId` / `enterpriseUrl`
- `type: "oauth"``{ provider, access, refresh, expires, email? }`(某些提供商还会带 `projectId`/`enterpriseUrl`
## 配置文件 ID
OAuth 登录会创建不同的配置文件,以便多个账共存。
OAuth 登录会创建不同的配置文件,以便多个账户可以共存。
- 默认:当没有可用邮箱时使用 `provider:default`
- 带邮箱的 OAuth`provider:<email>`(例如 `google-antigravity:user@gmail.com`
- 默认:当没有可用邮箱时使用 `provider:default`
- 带邮箱的 OAuth`provider:<email>`(例如 `google-antigravity:user@gmail.com`
配置文件存放在 `~/.openclaw/agents/<agentId>/agent/auth-profiles.json``profiles` 下。
配置文件位于 `~/.openclaw/agents/<agentId>/agent/auth-profiles.json``profiles` 下。
## 轮换顺序
当一个提供商有多个配置文件时OpenClaw 会按下方式选择顺序:
当一个提供商有多个配置文件时OpenClaw 会按下方式选择顺序:
<Steps>
<Step title="显式配置">
`auth.order[provider]`(如果已设置)。
</Step>
<Step title="已配置的配置文件">
按提供商筛选后的 `auth.profiles`
按提供商过滤后的 `auth.profiles`
</Step>
<Step title="已存储的配置文件">
`auth-profiles.json` 中该提供商对应的条目。
`auth-profiles.json`属于该提供商的条目。
</Step>
</Steps>
如果配置显式顺序OpenClaw 会使用轮询顺序:
如果没有配置显式顺序OpenClaw 会使用轮询顺序:
- **主键:**配置文件类型(**OAuth 优先于 API 密钥**
- **次键:**`usageStats.lastUsed`(越早越先,同一类型内排序)。
- **处于冷却 / 禁用状态的配置文件** 会被移到末尾,并按最早到期时间排序
- **主排序键:**配置文件类型(**OAuth 优先于 API 密钥**
- **次排序键:**`usageStats.lastUsed`(同一类型内最久未使用优先)
- **处于冷却/已禁用的配置文件** 会被移到末尾,并按最早到期时间排序
### 会话粘性(对缓存友好
### 会话粘性(有利于缓存
OpenClaw 会**为每个会话固定所选的认证配置文件**,以保持提供商缓存处于热状态。它**不会**在每次请求时都轮换。固定的配置文件会一直复用,直到
OpenClaw 会**按会话固定所选的凭证配置文件**,以保持提供商缓存处于热状态。它**不会**在每次请求时轮换。固定的配置文件会被重复使用,直到发生以下情况之一
- 会话被重置(`/new` / `/reset`
- 一次压缩完成(压缩计数递增)
- 该配置文件处于冷却 / 禁用状态
- 该配置文件处于冷却/已禁用状态
通过 `/model …@<profileId>` 进行手动选择会为该会话设置一个**用户覆盖**,在新会话开始前不会自动轮换。
通过 `/model …@<profileId>` 手动选择会为该会话设置一个**用户覆盖**,在新会话开始前不会自动轮换。
<Note>
自动固定的配置文件(由会话路由器选中)被视为一种**偏好**:它们会先被尝试,但在遇到速率限制 / 超时时OpenClaw 可能会轮换到另一个配置文件。用户固定的配置文件会锁定在该配置文件上;如果它失败且已配置模型回退OpenClaw 会移动到下一个模型,而不是切换配置文件。
自动固定的配置文件(由会话路由器选择)被视为一种**偏好**:它们会先被尝试,但 OpenClaw 可能会在遇到限流/超时时轮换到其他配置文件。用户固定的配置文件会保持锁定在该配置文件;如果它失败,并且已配置模型回退OpenClaw 会移动到下一个模型,而不是切换配置文件。
</Note>
### 为什么 OAuth 可能“看起来丢失了”
如果同一个提供商同时有一个 OAuth 配置文件和一个 API 密钥配置文件,那么在未固定时,轮询可能会在不同消息之间于二者之间切换。要强制使用单个配置文件:
如果你为同一个提供商同时有一个 OAuth 配置文件和一个 API 密钥配置文件,那么轮询可能会在不同消息之间切换它们,除非已固定。要强制使用单个配置文件:
- 使用 `auth.order[provider] = ["provider:profileId"]` 进行固定,或
- 通过 `/model …` 配合配置文件覆盖进行每会话覆盖(当你的 UI / 聊天界面支持时)。
- 通过 `auth.order[provider] = ["provider:profileId"]` 固定,或
- 使用 `/model …` 加上配置文件覆盖进行按会话覆盖(在你的 UI / 聊天界面支持时)。
## 冷却
当某个配置文件因认证 / 速率限制错误失败时(或因看起来像速率限制的超时而失败OpenClaw 会将其标记为冷却中,并移动到下一个配置文件。
当某个配置文件因凭证/限流错误失败时(或者因看起来像限流的超时而失败OpenClaw 会将其标记为冷却中,并移动到下一个配置文件。
<AccordionGroup>
<Accordion title="哪些情况会落入速率限制 / 超时桶">
该速率限制分类比单纯的 `429` 更广:还包括提供商消息,例如 `Too many concurrent requests`、`ThrottlingException`、`concurrency limit reached`、`workers_ai ... quota limit exceeded`、`throttled`、`resource exhausted`,以及周期性使用窗口限制,例如 `weekly/monthly limit reached`
<Accordion title="哪些情况会进入限流 / 超时桶">
这个限流桶比单纯的 `429` 更宽:它还包括提供商消息,例如 `Too many concurrent requests`、`ThrottlingException`、`concurrency limit reached`、`workers_ai ... quota limit exceeded`、`throttled`、`resource exhausted`,以及诸如 `weekly/monthly limit reached` 之类的周期性使用窗口限制
格式 / 无效请求错误(例如 Cloud Code Assist 工具调用 ID 验失败会被视为值得回退并使用相同的冷却机制。OpenAI 兼容的 stop-reason 错误,例如 `Unhandled stop reason: error`、`stop reason: error` 和 `reason: error`,会被归类为超时 / 回退信号。
格式/无效请求错误(例如 Cloud Code Assist 工具调用 ID 验失败会被视为值得回退并使用相同的冷却机制。OpenAI 兼容的停止原因错误,例如 `Unhandled stop reason: error`、`stop reason: error` 和 `reason: error`,会被归类为超时/回退信号。
错误来源匹配已知瞬时模式时,通用服务器文本也可能落入该超时分类。例如,纯文本的 pi-ai 流包装器消息 `An unknown error occurred` 会被视为所有提供商都值得回退,因为 pi-ai 会在提供商流以 `stopReason: "aborted"``stopReason: "error"` 结束且没有具体细节时发出该消息。带有瞬时服务器文本的 JSON `api_error` 负载,例如 `internal server error`、`unknown error, 520`、`upstream error` 或 `backend error`,也会被视为值得回退的超时。
当来源匹配已知瞬时模式时,通用服务器文本也可能进入这个超时桶。例如,裸露的 pi-ai stream-wrapper 消息 `An unknown error occurred` 会被视为所有提供商都值得回退,因为 pi-ai 会在提供商流以 `stopReason: "aborted"``stopReason: "error"` 结束且没有具体细节时发出该消息。带有瞬时服务器文本的 JSON `api_error` 负载,例如 `internal server error`、`unknown error, 520`、`upstream error` 或 `backend error`,也会被视为值得回退的超时。
OpenRouter 特有的通用上游文本,例如单独`Provider returned error`,只有在提供商上下文确实是 OpenRouter 时才会被视为超时。通用的内部回退文本,例如 `LLM request failed with an unknown error.`则保持保守,不会单独触发回退。
OpenRouter 特有的通用上游文本,例如裸露`Provider returned error`,只有在提供商上下文确实是 OpenRouter 时才会被视为超时。`LLM request failed with an unknown error.` 这样的通用内部回退文本则保持保守,不会单独触发回退。
</Accordion>
<Accordion title="SDK retry-after 上限">
某些提供商 SDK 否则可能会在把控制权交还给 OpenClaw 之前,先休眠一个很长的 `Retry-After` 时间窗口。对于基于 Stainless 的 SDK例如 Anthropic 和 OpenAIOpenClaw 默认会将 SDK 内部的 `retry-after-ms` / `retry-after` 等待上限限制为 60 秒,并立即暴露更长的可重试响应,以便运行此回退路径。可使用 `OPENCLAW_SDK_RETRY_MAX_WAIT_SECONDS` 调整或禁用该上限;参见 [重试行为](/zh-CN/concepts/retry)。
某些提供商 SDK 否则可能会在将控制权交还给 OpenClaw 之前,因较长的 `Retry-After` 窗口而休眠很久。对于基于 Stainless 的 SDK例如 Anthropic 和 OpenAIOpenClaw 默认会将 SDK 内部的 `retry-after-ms` / `retry-after` 等待时间上限设为 60 秒,并立即暴露更长的可重试响应,以便这个回退路径能够运行。你可以使用 `OPENCLAW_SDK_RETRY_MAX_WAIT_SECONDS` 调整或禁用这个上限;参见 [Retry behavior](/zh-CN/concepts/retry)。
</Accordion>
<Accordion title="按模型划分的冷却">
速率限制冷却也可以按模型划分:
- 当已知失败的模型 ID 时OpenClaw 会为速率限制失败记录 `cooldownModel`
- 如果冷却范围限定在另一个模型上,那么同一提供商上的兄弟模型仍然可以尝试。
- 账单 / 禁用窗口仍会在跨模型范围内阻止整个配置文件。
<Accordion title="模型作用域冷却">
限流冷却也可以限定在模型作用域:
- 当已知失败模型 ID 时OpenClaw 会为限流失败记录 `cooldownModel`
- 当冷却限定在不同模型时,同一提供商上的兄弟模型仍然可以被尝试
- 计费/禁用窗口仍会跨模型阻止整个配置文件
</Accordion>
</AccordionGroup>
冷却用指数退避:
冷却使用指数退避:
- 1 分钟
- 5 分钟
@ -176,14 +176,14 @@ OpenClaw 会**为每个会话固定所选的认证配置文件**,以保持提
}
```
## 账单禁用
## 计费禁用
账单 / 额度失败(例如 “insufficient credits” / “credit balance too low”会被视为值得回退但它们通常不是瞬时问题。OpenClaw 不会设置短时冷却,而是会将该配置文件标记为**已禁用**(采用更长的退避),然后轮换到下一个配置文件 / 提供商。
计费/额度失败(例如“insufficient credits” / “credit balance too low”会被视为值得回退但它们通常不是瞬时性的。OpenClaw 不会使用短冷却,而是将该配置文件标记为**已禁用**(带有更长的退避时间),然后轮换到下一个配置文件/提供商。
<Note>
并非每个看起来像账单问题的响应都是 `402`,也并非每个 HTTP `402` 都会落到这里。即使提供商返回的是 `401``403`OpenClaw 也会把明确的账单文本保留在账单分类中,但提供商特定匹配器仍然只作用于拥有它们的提供商(例如 OpenRouter 的 `403 Key limit exceeded`)。
并非每个看起来像计费的响应都是 `402`,也并非每个 HTTP `402` 都会落入这里。即使某个提供商返回的是 `401``403`OpenClaw 仍会将明确的计费文本保留在计费通道中,但提供商特定的匹配器仍会限定在拥有它们的提供商内(例如 OpenRouter 的 `403 Key limit exceeded`)。
与此同时,临时性的 `402` 使用窗口以及组织 / 工作区支出限制错误,如果消息看起来可重试(例如 `weekly usage limit exhausted`、`daily limit reached, resets tomorrow` 或 `organization spending limit exceeded`,则会被归类为 `rate_limit`。这些情况会走短时冷却 / 回退路径,而不是长期账单禁用路径。
同时,当消息看起来可重试时,临时性的 `402` 使用窗口和组织/工作区支出限制错误会被归类为 `rate_limit`(例如 `weekly usage limit exhausted`、`daily limit reached, resets tomorrow` 或 `organization spending limit exceeded`。这些情况会保留在短冷却/回退路径中,而不是长时间的计费禁用路径。
</Note>
状态存储在 `auth-state.json` 中:
@ -201,122 +201,122 @@ OpenClaw 会**为每个会话固定所选的认证配置文件**,以保持提
默认值:
- 账单退避从**5 小时**开始,每次账单失败后翻倍,并在 **24 小时**封顶。
- 如果某个配置文件 **24 小时**内没有再次失败,退避计数器会重置(可配置)
- 过载重试在模型回退前允许进行 **1 次同提供商认证配置文件轮换**
- 过载重试默认使用 **0 毫秒**退避
- 计费退避从 **5 小时**开始,每次计费失败翻倍,并在 **24 小时**封顶
- 如果某个配置文件 **24 小时**内没有失败,退避计数器会重置(可配置)
- 过载重试允许在模型回退前进行 **1 次同提供商配置文件轮换**
- 过载重试默认使用 **0 毫秒**退避
## 模型回退
如果某个提供商的所有配置文件都失败OpenClaw 会移动到 `agents.defaults.model.fallbacks` 中的下一个模型。这适用于已耗尽配置文件轮换的认证失败、速率限制和超时(其他错误不会推进回退)。
如果某个提供商的所有配置文件都失败OpenClaw 会移动到 `agents.defaults.model.fallbacks` 中的下一个模型。这适用于已耗尽配置文件轮换的凭证失败、限流和超时(其他错误不会推进回退)。
与账单冷却相比过载和速率限制错误会以更积极的方式处理。默认情况下OpenClaw 允许一次同提供商认证配置文件重试,然后不等待,直接切换到下一个已配置的模型回退。像 `ModelNotReadyException` 这样的提供商繁忙信号会落入该过载分类。可以通过 `auth.cooldowns.overloadedProfileRotations`、`auth.cooldowns.overloadedBackoffMs` 和 `auth.cooldowns.rateLimitedProfileRotations` 来调
过载和限流错误比计费冷却处理得更激进。默认情况下OpenClaw 允许进行一次同提供商凭证配置文件重试,然后立即切换到下一个已配置的模型回退而不等待。像 `ModelNotReadyException` 这样的提供商繁忙信号会落入这个过载桶。你可以通过 `auth.cooldowns.overloadedProfileRotations`、`auth.cooldowns.overloadedBackoffMs` 和 `auth.cooldowns.rateLimitedProfileRotations` 来调节这一行为
当一次运行以模型覆盖开始时(钩子或 CLI在尝试完所有已配置回退后回退仍会以 `agents.defaults.model.primary` 结束。
当一次运行以模型覆盖开始时(钩子或 CLI在尝试完所有已配置回退后回退仍会以 `agents.defaults.model.primary` 结束。
### 候选链规则
OpenClaw 会根据当前请求的 `provider/model` 和已配置回退构建候选列表。
OpenClaw 会根据当前请求的 `provider/model` 以及已配置回退来构建候选列表。
<AccordionGroup>
<Accordion title="规则">
- 请求的模型始终排在第一位。
- 显式配置的回退会去重,但不会按模型 allowlist 过滤。它们被视为操作员的显式意图。
- 如果当前运行已经处于同一提供商系列中的某个已配置回退上OpenClaw 会继续使用完整的已配置链。
- 如果当前运行使用的提供商与配置中的不同,且当前模型并不属于已配置的回退链,那么 OpenClaw 不会追加来自其他提供商的无关已配置回退。
- 当运行从某个覆盖开始时,已配置的主模型会附加到链末尾,以便当前面的候选项耗尽后,链可以重新回到正常默认值。
- 显式配置的回退会去重,但不会被模型允许列表过滤。它们会被视为显式的运维意图。
- 如果当前运行已经处于同一提供商中的某个已配置回退上OpenClaw 会继续使用完整的已配置链。
- 如果当前运行使用的是与配置不同的提供商,并且该当前模型还不是已配置回退链的一部分,OpenClaw 不会追加来自其他提供商的无关已配置回退。
- 当运行起始于某个覆盖项时,已配置主模型会被追加到末尾,以便在更早的候选项耗尽后,候选链能够重新稳定回到正常默认值。
</Accordion>
</AccordionGroup>
### 哪些错误会推进回退
<Tabs>
<Tab title="会继续推进的情况">
- 证失败
- 速率限制和冷却耗尽
- 过载 / 提供商繁忙错误
- 形态上属于超时的回退错误
- 账单禁用
- `LiveSessionModelSwitchError`,它会被规范化为回退路径,这样过时的持久化模型就不会形成外层重试循环
- 在仍有剩余候选项时,其他无法识别的错误
<Tab title="以下情况会继续">
- 证失败
- 限流以及冷却耗尽
- 过载/提供商繁忙错误
- 呈现超时特征的回退错误
- 计费禁用
- `LiveSessionModelSwitchError`,它会被标准化到回退路径中,这样过期的已持久化模型就不会形成外层重试循环
- 当仍有剩余候选项时,其他未识别错误
</Tab>
<Tab title="不会继续推进的情况">
- 不属于超时 / 回退形态的显式中止
- 应保留在压缩 / 重试逻辑内部处理的上下文溢出错误(例如 `request_too_large`、`INVALID_ARGUMENT: input exceeds the maximum number of tokens`、`input token count exceeds the maximum number of input tokens`、`The input is too long for the model``ollama error: context length exceeded`
- 当没有候选项剩余时的最终未知错误
<Tab title="以下情况不会继续">
- 不属于超时/回退特征的显式中止
- 应保留在压缩/重试逻辑内部的上下文溢出错误(例如 `request_too_large`、`INVALID_ARGUMENT: input exceeds the maximum number of tokens`、`input token count exceeds the maximum number of input tokens`、`The input is too long for the model` `ollama error: context length exceeded`
- 当没有剩余候选项时的最终未知错误
</Tab>
</Tabs>
### 冷却跳过与探测行为
当某个提供商的每个认证配置文件都已处于冷却中时OpenClaw 不会自动永久跳过该提供商。它会按每个候选项分别决定:
当某个提供商的所有凭证配置文件都已处于冷却中时OpenClaw 不会永远自动跳过该提供商。它会按每个候选项分别做出决定:
<AccordionGroup>
<Accordion title="按候选项决策">
- 持久性认证失败会立即跳过整个提供商。
- 账单禁用通常会被跳过,但主候选项仍可能在节流条件下被探测,以便无需重启也能恢复。
- 主候选项可能会在接近冷却到期时被探测,并按每个提供商进行节流。
- 即使处于冷却中,同一提供商下的回退兄弟项在失败看起来是瞬时问题时(`rate_limit`、`overloaded` 或未知),仍然可以尝试。当速率限制是按模型划分,而某个兄弟模型可能仍可立即恢复时,这一点尤其重要。
- 瞬时冷却探测在每次回退运行中,每个提供商最多只允许一次,因此单个提供商不会拖慢跨提供商回退。
- 持续性的凭证失败会立即跳过整个提供商。
- 计费禁用通常会被跳过,但主候选项仍然可能在节流条件下被探测,以便无需重启也能恢复。
- 主候选项可能会在接近冷却到期时被探测,并带有按提供商划分的节流。
- 即使存在冷却,同一提供商中的回退兄弟模型仍可能在失败看起来是瞬时性的情况下被尝试(`rate_limit`、`overloaded` 或未知)。当限流限定在模型作用域,而兄弟模型可能仍可立即恢复时,这一点尤其重要。
- 瞬时冷却探测在每次回退运行中每个提供商最多只允许一次,这样单个提供商就不会拖慢跨提供商回退。
</Accordion>
</AccordionGroup>
## 会话覆盖与实时模型切换
会话模型变更是共享状态。当前运行器、`/model` 命令、压缩 / 会话更新以及实时会话协调,都会读取或写入同一个会话条目的不同部分。
会话模型变更属于共享状态。活动运行器、`/model` 命令、压缩/会话更新以及实时会话协调,都会读取或写入同一个会话条目的部分内容
这意味着回退重试必须与实时模型切换进行协调:
这意味着回退重试必须与实时模型切换协调:
- 只有明确由用户触发的模型更改才会标记待处理的实时切换。这包括 `/model`、`session_status(model=...)` 和 `sessions.patch`
- 系统驱动的模型更,例如回退轮换、心跳覆盖或压缩,不会自行标记待处理的实时切换。
- 在回退重试开始前,回复运行器会将选的回退覆盖字段持久化到会话条目中。
- 在下一次运行时,自动回退覆盖会在模型选择之前被清除,以便重新尝试已配置的主模型。如果它仍不健康,回退循环会为这次新尝试记录一个新的自动覆盖
- 用户模型覆盖(`modelOverrideSource: "user"`)以及没有来源字段的旧版覆盖,会在多轮之间持续存在
- 实时会话协调会优先采用持久化的会话覆盖,而不是过时的运行时模型字段。
- 如果某个实时切换错误指向当前回退链中更靠后的候选项OpenClaw 会直接跳转到该选中的模型,而不是先遍历无关候选项。
- 如果回退尝试失败,运行器只会回滚它自己写入的覆盖字段,而且仅在这些字段仍与该失败候选项匹配时才会这样做
- 只有显式的用户驱动模型变更才会标记待处理的实时切换。这包括 `/model`、`session_status(model=...)` 和 `sessions.patch`
- 系统驱动的模型更,例如回退轮换、心跳覆盖或压缩,本身不会标记待处理的实时切换。
- 在回退重试开始前,回复运行器会将选的回退覆盖字段持久化到会话条目中。
- 自动回退覆盖会在后续轮次中保持选中,因此 OpenClaw 不会在每条消息上都探测一个已知不可用的主模型。`/new`、`/reset` 和 `sessions.reset` 会清除自动来源的覆盖,并将会话恢复到已配置的默认值
- `/status` 会显示所选模型;当回退状态不同,还会显示当前激活的回退模型和原因
- 实时会话协调会优先使用已持久化的会话覆盖,而不是过期的运行时模型字段。
- 如果实时切换错误指向当前回退链中更靠后的候选项OpenClaw 会直接跳转到该选模型,而不是先遍历无关候选项。
- 如果回退尝试失败,运行器只会回滚它写入的覆盖字段,并且仅当这些字段仍与该失败候选项匹配时才会回滚
这可以防止经典竞态:
<Steps>
<Step title="主模型失败">
选中的主模型失败。
当前选中的主模型失败。
</Step>
<Step title="在内存中选中回退项">
在内存中选回退候选项。
<Step title="在内存中选定回退">
在内存中选回退候选项。
</Step>
<Step title="会话存储仍指向旧主模型">
<Step title="会话存储仍显示旧主模型">
会话存储仍反映旧的主模型。
</Step>
<Step title="实时协调读取过状态">
实时会话协调读取到过时的会话状态。
<Step title="实时协调读取过状态">
实时会话协调读取过期的会话状态。
</Step>
<Step title="重试被拉回">
在回退尝试开始前,重试被拉回到旧模型。
</Step>
</Steps>
持久化的回退覆盖弥合了这个窗口,而窄范围回滚则能保持更新得更晚的手动或运行时会话变更不被破坏
已持久化的回退覆盖关闭了这个窗口,而精确回滚则能保持较新的手动或运行时会话变更不受影响
## 可观测性与失败摘要
`runWithModelFallback(...)` 会记录每次尝试的详细信息,用于日志和面向用户的冷却消息:
- 尝试的提供商 / 模型
- 尝试的提供商/模型
- 原因(`rate_limit`、`overloaded`、`billing`、`auth`、`model_not_found` 以及类似的回退原因)
- 可选的状态 / 代码
- 可选的状态/代码
- 人类可读的错误摘要
当每个候选项都失败时OpenClaw 会抛出 `FallbackSummaryError`。外层回复运行器可以用它构建更具体的消息,例如“所有模型当前都受到临时速率限制”,并在已知时包含最早的冷却到期时间。
当每个候选项都失败时OpenClaw 会抛出 `FallbackSummaryError`。外层回复运行器可以用它构建更具体的消息,例如“所有模型当前都被临时限流”,并在已知时包含最早的冷却到期时间。
该冷却摘要具有模型感知能力:
- 与已尝试提供商 / 模型链无关的按模型划分速率限制会被忽略
- 如果剩余阻塞是匹配的按模型划分速率限制OpenClaw 会报告仍然阻止该模型的最后一个匹配到期时间
- 与已尝试提供商/模型链无关的模型作用域限流会被忽略
- 如果剩余阻塞是与之匹配的模型作用域限流OpenClaw 会报告仍阻止该模型的最后一个匹配到期时间
## 相关配置
参见 [Gateway 网关配置](/zh-CN/gateway/configuration)
有关以下内容,请参见 [Gateway 配置](/zh-CN/gateway/configuration)
- `auth.profiles` / `auth.order`
- `auth.cooldowns.billingBackoffHours` / `auth.cooldowns.billingBackoffHoursByProvider`
@ -326,4 +326,4 @@ OpenClaw 会根据当前请求的 `provider/model` 和已配置回退构建候
- `agents.defaults.model.primary` / `agents.defaults.model.fallbacks`
- `agents.defaults.imageModel` 路由
参见 [Models](/zh-CN/concepts/models) 了解更广泛的模型选择与回退概览
有关更广泛的模型选择和回退概览,请参见 [Models](/zh-CN/concepts/models)。

View File

@ -1,26 +1,26 @@
---
read_when:
- 你想从你自己的 GPU 机提供模型服务
- 你正在连接 LM Studio 或兼容 OpenAI 的代理
- 你想从你自己的 GPU 机提供模型服务
- 你正在配置 LM Studio 或兼容 OpenAI 的代理
- 你需要最安全的本地模型使用指南
summary: 在本地 LLM 上运行 OpenClawLM Studio、vLLM、LiteLLM、自定义 OpenAI 端点)
title: 本地模型
x-i18n:
generated_at: "2026-04-27T08:18:16Z"
generated_at: "2026-04-27T08:31:19Z"
model: gpt-5.4
provider: openai
source_hash: d6d44f451e14e74f49b8fb23c7c890c8a13a76c56ef82e5d271cfbb7d90f7c81
source_hash: 0e2733bd1d6f9e57f0b0fb888d28beebff321d12684a6ea670bee327d2ced8dc
source_path: gateway/local-models.md
workflow: 15
---
本地部署是可行的,但 OpenClaw 需要大上下文窗口 + 强大的提示注入防御能力。小显卡会截断上下文并削弱安全性。建议尽量提高配置:**≥2 台满配 Mac Studio 或同等级 GPU 主机(约 3 万美元以上)**。单张 **24 GB** GPU 只适合较轻量的提示,且延迟更高。请使用**你能运行的最大 / 完整尺寸模型变体**激进量化或“small”检查点会提高提示注入风险参见 [Security](/zh-CN/gateway/security))。
本地部署是可行的,但 OpenClaw 需要大上下文窗口以及对提示注入的强防护。小显存显卡会截断上下文,并削弱安全性。目标应尽可能高:**≥ 2 台拉满配置的 Mac Studio 或同等级 GPU 设备(约 3 万美元以上)**。单张 **24 GB** GPU 只适用于较轻的提示,且延迟更高。请使用**你能运行的最大 / 完整尺寸模型变体**激进量化或“small”检查点会提高提示注入风险参见 [Security](/zh-CN/gateway/security))。
如果你想要最低摩擦的本地部署方式,请从 [LM Studio](/zh-CN/providers/lmstudio) 或 [Ollama](/zh-CN/providers/ollama) 开始,并运行 `openclaw onboard`。本页是面向更高端本地技术栈和自定义兼容 OpenAI 的本地服务器的主观推荐指南。
如果你想要最低摩擦的本地配置,请从 [LM Studio](/zh-CN/providers/lmstudio) 或 [Ollama](/zh-CN/providers/ollama) `openclaw onboard` 开始。本页是面向更高端本地堆栈和自定义兼容 OpenAI 的本地服务器的倾向性指南。
## 推荐LM Studio + 大型本地模型Responses API
这是当前最好的本地技术栈。在 LM Studio 中加载一个大型模型(例如完整尺寸的 Qwen、DeepSeek 或 Llama 构建),启用本地服务器(默认 `http://127.0.0.1:1234`),并使用 Responses API 将推理内容与最终文本分离。
当前最佳的本地方案。在 LM Studio 中加载一个大型模型(例如完整尺寸的 Qwen、DeepSeek 或 Llama 构建),启用本地服务器(默认 `http://127.0.0.1:1234`),并使用 Responses API 以将推理过程与最终文本分离。
```json5
{
@ -57,18 +57,18 @@ x-i18n:
}
```
**设置清单**
**设置检查清单**
- 安装 LM Studio[https://lmstudio.ai](https://lmstudio.ai)
- 在 LM Studio 中,下载**可用的最大模型构建**(避免 “small”/重度量化变体),启动服务器,并确认 `http://127.0.0.1:1234/v1/models` 能列出该模型。
- 在 LM Studio 中,下载**可用的最大模型构建**(避免使用 “small”/重度量化变体),启动服务器,并确认 `http://127.0.0.1:1234/v1/models` 能列出该模型。
- 将 `my-local-model` 替换为 LM Studio 中显示的实际模型 ID。
- 保持模型已加载;冷加载会增加启动延迟。
- 保持模型已加载;冷启动加载会增加启动延迟。
- 如果你的 LM Studio 构建不同,请调整 `contextWindow`/`maxTokens`。
- 对于 WhatsApp请坚持使用 Responses API这样只会发送最终文本。
- 对于 WhatsApp请坚持使用 Responses API以便只发送最终文本。
即使在运行本地模型时,也保留托管模型配置;使用 `models.mode: "merge"`,这样回退模型仍然可用。
即使在运行本地模型时,也保留托管模型配置;使用 `models.mode: "merge"`,这样回退模型仍然可用。
### 混合配置:托管模型为主模型,本地模型作为回退
### 混合配置:托管模型为主,本地模型回退
```json5
{
@ -109,18 +109,18 @@ x-i18n:
}
```
### 本地优先,同时保留托管安全网
### 本地优先,托管模型兜底
交换主模型与回退模型的顺序;保留相同的 provider 配置块和 `models.mode: "merge"`,这样当本地主机不可用时,你仍然可以回退到 Sonnet 或 Opus。
交换主模型与回退模型的顺序;保留相同的 provider 配置块和 `models.mode: "merge"`,这样当本地机器宕机时,你仍可回退到 Sonnet 或 Opus。
### 区域托管 / 数据路由
- 托管的 MiniMax/Kimi/GLM 变体也可通过 OpenRouter 的区域固定端点提供(例如美国托管)。你可以在那里选择区域变体,将流量限制在你指定的司法辖区内,同时仍然使用 `models.mode: "merge"` 来保留 Anthropic/OpenAI 回退。
- 纯本地仍然是隐私最强的方案;当你需要提供商功能但又希望控制数据流向时,区域托管路由是折中方案。
- 托管的 MiniMax/Kimi/GLM 变体也可通过 OpenRouter 的区域固定端点提供(例如美国托管)。在那里选择区域变体,以便将流量保留在你选择的司法辖区内,同时仍可使用 `models.mode: "merge"` 来启用 Anthropic/OpenAI 回退。
- 纯本地仍是隐私性最强的路径;当你需要提供商功能但又希望控制数据流向时,托管区域路由是折中方案。
## 其他兼容 OpenAI 的本地代理
如果 vLLM、LiteLLM、OAI-proxy 或自定义网关暴露的是 OpenAI 风格的 `/v1` 端点,它们都可以工作。将上面的 provider 配置块替换为你的端点和模型 ID
vLLM、LiteLLM、OAI-proxy 或自定义 Gateway 网关 只要暴露 OpenAI 风格的 `/v1` 端点即可使用。将上面的 provider 配置块替换为你的端点和模型 ID
```json5
{
@ -150,34 +150,32 @@ x-i18n:
```
保留 `models.mode: "merge"`,这样托管模型仍可作为回退使用。
对于较慢的本地或远程模型服务器,请优先使用 `models.providers.<id>.timeoutSeconds`,再考虑提高 `agents.defaults.timeoutSeconds`。provider 超时仅适用于模型 HTTP 请求包括连接、响应头、body 流式传输,以及整个受保护获取流程的中止控制
对于缓慢的本地或远程模型服务器,请在提高 `agents.defaults.timeoutSeconds` 之前先使用 `models.providers.<id>.timeoutSeconds`。提供商超时仅适用于模型 HTTP 请求,包括连接、响应头、正文流式传输,以及整个受保护获取的中止时间
关于本地 / 代理 `/v1` 后端的行为说明:
- OpenClaw 将这些视为代理风格的兼容 OpenAI 路由,而不是原生 OpenAI 端点
- 仅适用于原生 OpenAI 的请求整形不会在这里生效:没有 `service_tier`,没有 Responses `store`,没有 OpenAI 推理兼容负载整形,也没有提示缓存提示
- 隐藏的 OpenClaw 归因请求头(`originator`、`version`、`User-Agent`)不会注入到这些自定义代理 URL 中
- 原生 OpenAI 专用的请求整形不适用于这里:没有 `service_tier`,没有 Responses `store`,没有 OpenAI 推理兼容负载整形,也没有提示缓存提示
- 隐藏的 OpenClaw 归因头(`originator`、`version`、`User-Agent`)不会注入到这些自定义代理 URL 中
对更严格的兼容 OpenAI 后端的兼容性说明:
- 某些服务器在 Chat Completions 中只接受字符串类型`messages[].content`,不接受结构化内容片段数组。对于这些端点,请设置 `models.providers.<provider>.models[].compat.requiresStringContent: true`
- 某些本地模型会以文本形式输出独立的方括号工具请求,例如 `[tool_name]`,后接 JSON 和 `[END_TOOL_REQUEST]`。只有当该名称与当前轮次已注册工具完全匹配时OpenClaw 才会将其提升为真正的工具调用;否则,该块会被视为不受支持的文本,并从用户可见回复中隐藏。
- 如果某个模型输出看起来像工具调用的 JSON、XML 或 ReAct 风格文本,但 provider 并未输出结构化调用OpenClaw 会将其保留为文本,并记录一条警告日志,其中包含运行 ID、provider/模型、检测到的模式,以及可用时的工具名称。应将这视为 provider/模型的工具调用不兼容问题,而不是工具已成功运行。
- 某些更小或更严格的本地后端在处理 OpenClaw 完整的智能体运行时提示形状时并不稳定,尤其是在包含工具 schema 时。如果后端能够处理很小的直接 `/v1/chat/completions` 调用,但在正常的 OpenClaw 智能体轮次中失败,请先尝试设置 `agents.defaults.experimental.localModelLean: true`,以移除`browser`、`cron` 和 `message` 这样的重量级默认工具;这是一个实验性标志,不是稳定的默认模式设置。参见 [Experimental Features](/zh-CN/concepts/experimental-features)。如果这样仍然失败,再尝试 `models.providers.<provider>.models[].compat.supportsTools: false`
- 如果后端仍然只在更大的 OpenClaw 运行中失败,剩余问题通常是上游模型/服务器容量不足或后端 bug,而不是 OpenClaw 的传输层问题。
- 某些服务器在 Chat Completions 中只接受字符串形式`messages[].content`,不接受结构化内容片段数组。对于这些端点,请设置 `models.providers.<provider>.models[].compat.requiresStringContent: true`
- 某些本地模型会以文本形式输出独立的方括号工具请求,例如 `[tool_name]`,后跟 JSON 和 `[END_TOOL_REQUEST]`。只有当名称与该轮次中已注册工具完全匹配时OpenClaw 才会将其提升为真实工具调用;否则该块会被视为不受支持的文本,并从用户可见回复中隐藏。
- 如果模型输出看起来像工具调用的 JSON、XML 或 ReAct 风格文本,但提供商并未输出结构化调用OpenClaw 会将其保留为文本,并记录一条警告,其中包含运行 ID、provider/模型、检测到的模式以及可用时的工具名称。请将这视为 provider/模型的工具调用不兼容问题,而不是一次已完成的工具运行。
- 某些更小或更严格的本地后端在处理 OpenClaw 完整的 Agent Runtimes 提示结构时不稳定,尤其是在包含工具 schema 时。如果该后端可用于极小的直接 `/v1/chat/completions` 调用,但在正常的 OpenClaw 智能体轮次中失败,请先尝试 `agents.defaults.experimental.localModelLean: true`,以移除诸如 `browser`、`cron` 和 `message` 之类的重量级默认工具;这是实验性标志,不是稳定的默认模式设置。参见 [Experimental Features](/zh-CN/concepts/experimental-features)。如果仍然失败,再尝试 `models.providers.<provider>.models[].compat.supportsTools: false`
- 如果后端仍然只在较大的 OpenClaw 运行中失败,剩余问题通常是上游模型/服务器容量不足或后端缺陷,而不是 OpenClaw 的传输层问题。
## 故障排除
- Gateway 网关能访问代理吗?`curl http://127.0.0.1:1234/v1/models`
- Gateway 网关 能否连到代理?`curl http://127.0.0.1:1234/v1/models`。
- LM Studio 模型未加载?重新加载;冷启动是常见的“卡住”原因。
- 当检测到的上下文窗口低于 **32k**OpenClaw 会发出警告;低于 **16k** 时会阻止运行。如果你触发了该预检,请提高服务器/模型的上下文限制,或选择更大的模型。
- 上下文错误?降低 `contextWindow` 或提高你的服务器限制。
- 兼容 OpenAI 的服务器返回 `messages[].content ... expected a string`
在该模型条目上添加 `compat.requiresStringContent: true`
- 直接的小型 `/v1/chat/completions` 调用可用,但 `openclaw infer model run`
在 Gemma 或其他本地模型上失败?先用
`compat.supportsTools: false` 禁用工具 schema然后重新测试。如果服务器仍然只在更大的 OpenClaw 提示上崩溃,应将其视为上游服务器/模型的限制。
- 安全性:本地模型会跳过提供商侧过滤;请保持智能体范围收窄并启用压缩,以限制提示注入的影响范围。
- 本地服务器显示 `terminated`、`ECONNRESET`或在轮次中途关闭流OpenClaw 会在诊断中记录低基数的 `model.call.error.failureKind`,以及 OpenClaw 进程的 RSS/堆快照。对于 LM Studio/Ollama 内存压力问题,请将该时间戳与服务器日志或 macOS 崩溃 / jetsam 日志进行比对,以确认模型服务器是否被系统杀死。
- 当检测到的上下文窗口低于 **32k**OpenClaw 会发出警告;低于 **16k** 时会阻止运行。如果你触发了这个预检,请提高服务器/模型的上下文限制,或选择更大的模型。
- 上下文报错?降低 `contextWindow` 或提高你的服务器限制。
- 兼容 OpenAI 的服务器返回 `messages[].content ... expected a string`?在该模型条目上添加 `compat.requiresStringContent: true`
- 直接的小型 `/v1/chat/completions` 调用可以工作,但 `openclaw infer model run` 在 Gemma 或其他本地模型上失败?先用 `compat.supportsTools: false` 禁用工具 schema然后重新测试。如果服务器仍然只在较大的 OpenClaw 提示上崩溃,请将其视为上游服务器/模型限制。
- 安全性:本地模型会跳过提供商侧过滤;请将智能体范围保持收敛,并开启压缩,以限制提示注入的影响半径。
## 相关内容

View File

@ -1,33 +1,27 @@
---
read_when:
- 你想将 OpenClaw 模型使用情况、消息流或会话指标发送到 OpenTelemetry 收集器
- 你想将 OpenClaw 模型使用情况、消息流或会话指标发送到 OpenTelemetry 收集器
- 你正在将追踪、指标或日志接入 Grafana、Datadog、Honeycomb、New Relic、Tempo 或其他 OTLP 后端
- 你需要确切的指标名称、span 名称或属性结构来构建仪表板或告警
summary: 通过 diagnostics-otel 插件OTLP/HTTP将 OpenClaw 诊断数据导出到任意 OpenTelemetry 收集器
title: OpenTelemetry 导出
x-i18n:
generated_at: "2026-04-26T21:16:58Z"
generated_at: "2026-04-27T08:31:25Z"
model: gpt-5.4
provider: openai
source_hash: 1ad923fff12ff89766999370fe39a75c1aa5f386ce4641fde1c385b24439cc1b
source_hash: e9d06589d281223ebb57e76f6f19441d30c138b9f7b0636198ab7bae5fad3c8a
source_path: gateway/opentelemetry.md
workflow: 15
---
OpenClaw 通过内置的 `diagnostics-otel` 插件导出诊断数据,
使用 **OTLP/HTTPprotobuf**。任何接受 OTLP/HTTP 的收集器或后端
都可以直接使用,无需修改代码。关于本地文件日志及其读取方式,请参见
[日志记录](/zh-CN/logging)。
OpenClaw 通过内置的 `diagnostics-otel` 插件使用 **OTLP/HTTPprotobuf** 导出诊断数据。任何接受 OTLP/HTTP 的收集器或后端都可以直接使用,无需修改代码。有关本地文件日志及其读取方式,请参阅[日志记录](/zh-CN/logging)。
## 工作原理
## 它是如何协同工作的
- **诊断事件** 是由 Gateway 网关和内置插件发出的结构化进程内记录,
用于模型运行、消息流、会话、队列和 exec。
- **`diagnostics-otel` 插件** 订阅这些事件,并通过 OTLP/HTTP 将它们导出为
OpenTelemetry **指标**、**追踪** 和 **日志**
- **提供商调用** 会从 OpenClaw 可信的模型调用 span 上下文中接收一个 W3C `traceparent`
请求头,前提是提供商传输层接受自定义请求头。插件发出的追踪上下文不会被传播。
- 只有在诊断功能和插件都启用时,导出器才会附加,因此默认情况下进程内开销几乎为零。
- **诊断事件**是由 Gateway 网关和内置插件发出的结构化进程内记录,用于模型运行、消息流、会话、队列和 exec。
- **`diagnostics-otel` 插件**订阅这些事件,并通过 OTLP/HTTP 将其导出为 OpenTelemetry **指标**、**追踪**和**日志**。
- 当提供商传输支持自定义请求头时,**提供商调用**会从 OpenClaw 受信任的模型调用 span 上下文接收 W3C `traceparent` 请求头。插件发出的追踪上下文不会传播。
- 只有当诊断功能面和该插件都启用时,导出器才会附加,因此默认情况下进程内开销几乎为零。
## 快速开始
@ -70,12 +64,11 @@ openclaw plugins enable diagnostics-otel
| 信号 | 包含内容 |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| **指标** | 用于 token 使用量、成本、运行时长、消息流、队列通道、会话状态、exec 和内存压力的计数器与直方图。 |
| **追踪** | 用于模型使用、模型调用、harness 生命周期、工具执行、exec、webhook/消息处理、上下文组装和工具循环的 span。 |
| **日志** | 当启用 `diagnostics.otel.logs` 时,通过 OTLP 导出的结构化 `logging.file` 记录。 |
| **指标** | 用于令牌使用量、成本、运行时长、消息流、队列通道、会话状态、exec 和内存压力的计数器与直方图。 |
| **追踪** | 用于模型使用情况、模型调用、harness 生命周期、工具执行、exec、webhook/消息处理、上下文组装和工具循环的 span。 |
| **日志** | 当启用 `diagnostics.otel.logs` 时,通过 OTLP 导出的结构化 `logging.file` 记录。 |
你可以分别切换 `traces`、`metrics` 和 `logs`。当
`diagnostics.otel.enabled` 为 true 时,这三项默认都会开启。
你可以独立切换 `traces`、`metrics` 和 `logs`。当 `diagnostics.otel.enabled` 为 true 时,这三者默认都开启。
## 配置参考
@ -89,14 +82,14 @@ openclaw plugins enable diagnostics-otel
tracesEndpoint: "http://otel-collector:4318/v1/traces",
metricsEndpoint: "http://otel-collector:4318/v1/metrics",
logsEndpoint: "http://otel-collector:4318/v1/logs",
protocol: "http/protobuf", // grpc 会被忽略
protocol: "http/protobuf", // grpc is ignored
serviceName: "openclaw-gateway",
headers: { "x-collector-token": "..." },
traces: true,
metrics: true,
logs: true,
sampleRate: 0.2, // 根 span 采样器,范围 0.0..1.0
flushIntervalMs: 60000, // 指标导出间隔(最小 1000ms
sampleRate: 0.2, // root-span sampler, 0.0..1.0
flushIntervalMs: 60000, // metric export interval (min 1000ms)
captureContent: {
enabled: false,
inputMessages: false,
@ -114,49 +107,36 @@ openclaw plugins enable diagnostics-otel
| 变量 | 用途 |
| ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `OTEL_EXPORTER_OTLP_ENDPOINT` | 覆盖 `diagnostics.otel.endpoint`。如果该值已包含 `/v1/traces`、`/v1/metrics` 或 `/v1/logs`,则按原样使用。 |
| `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` / `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` / `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` | 当对应的 `diagnostics.otel.*Endpoint` 配置键未设置时,用作各信号专属端点覆盖。信号专属配置优先于信号专属环境变量,后者优先于共享端点。 |
| `OTEL_SERVICE_NAME` | 覆盖 `diagnostics.otel.serviceName`。 |
| `OTEL_EXPORTER_OTLP_PROTOCOL` | 覆盖线协议(当前仅 `http/protobuf` 会生效)。 |
| `OTEL_SEMCONV_STABILITY_OPT_IN` | 设置为 `gen_ai_latest_experimental` 时,会发出最新的实验性 GenAI span 属性`gen_ai.provider.name`,而不是旧版的 `gen_ai.system`。无论如何GenAI 指标始终使用有界、低基数的语义属性。 |
| `OPENCLAW_OTEL_PRELOADED` | 当另一个预加载器或宿主进程已经注册了全局 OpenTelemetry SDK 时,设置为 `1`。此时插件会跳过自己的 NodeSDK 生命周期,但仍会连接诊断监听器并遵循 `traces`/`metrics`/`logs`。 |
| `OTEL_EXPORTER_OTLP_ENDPOINT` | 覆盖 `diagnostics.otel.endpoint`。如果该值已包含 `/v1/traces`、`/v1/metrics` 或 `/v1/logs`,则按原样使用。 |
| `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` / `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` / `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` | 当对应的 `diagnostics.otel.*Endpoint` 配置键未设置时,使用对应信号的端点覆盖。信号专用配置优先于信号专用环境变量,后者优先于共享端点。 |
| `OTEL_SERVICE_NAME` | 覆盖 `diagnostics.otel.serviceName`。 |
| `OTEL_EXPORTER_OTLP_PROTOCOL` | 覆盖传输协议(目前仅 `http/protobuf` 会生效)。 |
| `OTEL_SEMCONV_STABILITY_OPT_IN` | 设置为 `gen_ai_latest_experimental` 时,会发出最新的实验性 GenAI span 属性 `gen_ai.provider.name`,而不是旧版的 `gen_ai.system`。无论如何GenAI 指标始终使用有界、低基数的语义属性。 |
| `OPENCLAW_OTEL_PRELOADED` | 当其他预加载项或宿主进程已经注册了全局 OpenTelemetry SDK 时,将其设为 `1`。这样插件会跳过自身的 NodeSDK 生命周期,但仍会连接诊断监听器并遵循 `traces`/`metrics`/`logs`。 |
## 隐私与内容采集
默认**不会**导出原始模型/工具内容。span 携带的是有界标识符
(渠道、提供商、模型、错误类别、仅哈希的请求 ID并且绝不会包含提示词文本、
响应文本、工具输入、工具输出或会话键。
默认**不会**导出原始模型/工具内容。span 携带的是有界标识符(渠道、提供商、模型、错误类别、仅哈希的请求 id绝不会包含提示词文本、响应文本、工具输入、工具输出或会话键。
发往外部的模型请求可能包含一个 W3C `traceparent` 请求头。该请求头仅基于
当前模型调用的 OpenClaw 自有诊断追踪上下文生成。已有的调用方提供的 `traceparent`
请求头会被替换,因此插件或自定义提供商选项无法伪造跨服务追踪祖先关系。
出站模型请求可能包含 W3C `traceparent` 请求头。该请求头仅根据 OpenClaw 自有的活动模型调用诊断追踪上下文生成。现有的调用方提供的 `traceparent` 请求头会被替换,因此插件或自定义提供商选项无法伪造跨服务追踪祖先关系。
仅当你的收集器和保留策略已获准处理提示词、响应、工具或系统提示词文本时,
才将 `diagnostics.otel.captureContent.*` 设为 `true`。每个子键都需要单独显式启用:
仅当你的收集器和保留策略已获准存储提示词、响应、工具或系统提示文本时,才将 `diagnostics.otel.captureContent.*` 设为 `true`。每个子键都需要单独显式启用:
- `inputMessages` 用户提示内容。
- `outputMessages` 模型响应内容。
- `toolInputs` 工具参数负载。
- `toolOutputs` 工具结果负载。
- `systemPrompt` 组装后的 system/developer 提示词。
- `inputMessages` — 用户提示内容。
- `outputMessages` — 模型响应内容。
- `toolInputs` — 工具参数负载。
- `toolOutputs` — 工具结果负载。
- `systemPrompt` — 组装后的 system/developer 提示词。
当任一子键启用时,模型和工具 span 会仅针对该类内容附加有界、已脱敏的
`openclaw.content.*` 属性。
当任一子键启用时,模型和工具 span 会仅为该类内容附加有界、已脱敏的 `openclaw.content.*` 属性。
## 采样与刷新
- **追踪:** `diagnostics.otel.sampleRate`(仅根 span`0.0` 表示全部丢弃,
`1.0` 表示全部保留)。
- **追踪:** `diagnostics.otel.sampleRate`(仅根 span`0.0` 表示全部丢弃,`1.0` 表示全部保留)。
- **指标:** `diagnostics.otel.flushIntervalMs`(最小值为 `1000`)。
- **日志:** OTLP 日志遵循 `logging.level`(文件日志级别)。它们使用的是
诊断日志记录脱敏路径,而不是控制台格式化。对于高流量安装,建议优先使用
OTLP 收集器采样/过滤,而不是本地采样。
- **文件日志关联:** 当日志调用携带有效的诊断追踪上下文时JSONL 文件日志会在顶层包含
`traceId`、`spanId`、`parentSpanId` 和 `traceFlags`,这使日志处理器能够将本地日志行与
已导出的 span 关联起来。
- **请求关联:** Gateway 网关 HTTP 请求和 WebSocket 帧会创建一个内部请求追踪作用域。
该作用域内的日志和诊断事件默认会继承请求追踪,而智能体运行和模型调用 span
则作为其子级创建,因此提供商 `traceparent` 请求头会保持在同一条追踪上。
- **日志:** OTLP 日志遵循 `logging.level`(文件日志级别)。它们使用诊断日志记录脱敏路径,而不是控制台格式化。对于高流量部署,建议优先使用 OTLP 收集器采样/过滤,而不是本地采样。
- **文件日志关联:** 当日志调用携带有效的诊断追踪上下文时JSONL 文件日志会包含顶层的 `traceId`、`spanId`、`parentSpanId` 和 `traceFlags`,这样日志处理器就能将本地日志行与导出的 span 关联起来。
- **请求关联:** Gateway 网关 HTTP 请求和 WebSocket 帧会创建内部请求追踪作用域。该作用域内的日志和诊断事件默认继承该请求追踪,而 智能体 运行和模型调用 span 会作为其子级创建,因此提供商 `traceparent` 请求头会保留在同一条追踪中。
## 导出的指标
@ -168,10 +148,10 @@ openclaw plugins enable diagnostics-otel
- `openclaw.context.tokens`(直方图,属性:`openclaw.context`、`openclaw.channel`、`openclaw.provider`、`openclaw.model`
- `gen_ai.client.token.usage`直方图GenAI 语义约定指标,属性:`gen_ai.token.type` = `input`/`output`、`gen_ai.provider.name`、`gen_ai.operation.name`、`gen_ai.request.model`
- `gen_ai.client.operation.duration`直方图单位为秒GenAI 语义约定指标,属性:`gen_ai.provider.name`、`gen_ai.operation.name`、`gen_ai.request.model`,以及可选的 `error.type`
- `openclaw.model_call.duration_ms`(直方图,属性:`openclaw.provider`、`openclaw.model`、`openclaw.api`、`openclaw.transport`
- `openclaw.model_call.duration_ms`(直方图,属性:`openclaw.provider`、`openclaw.model`、`openclaw.api`、`openclaw.transport`,以及在分类错误下的 `openclaw.errorCategory``openclaw.failureKind`
- `openclaw.model_call.request_bytes`(直方图,最终模型请求负载的 UTF-8 字节大小;不包含原始负载内容)
- `openclaw.model_call.response_bytes`(直方图,流式模型响应事件的 UTF-8 字节大小;不包含原始响应内容)
- `openclaw.model_call.time_to_first_byte_ms`(直方图,首个流式响应事件到达前的耗时)
- `openclaw.model_call.time_to_first_byte_ms`(直方图,第一个流式响应事件之前的耗时)
### 消息流
@ -184,7 +164,7 @@ openclaw plugins enable diagnostics-otel
- `openclaw.message.delivery.started`(计数器,属性:`openclaw.channel`、`openclaw.delivery.kind`
- `openclaw.message.delivery.duration_ms`(直方图,属性:`openclaw.channel`、`openclaw.delivery.kind`、`openclaw.outcome`、`openclaw.errorCategory`
### 队列会话
### 队列会话
- `openclaw.queue.lane.enqueue`(计数器,属性:`openclaw.lane`
- `openclaw.queue.lane.dequeue`(计数器,属性:`openclaw.lane`
@ -197,13 +177,13 @@ openclaw plugins enable diagnostics-otel
### Harness 生命周期
- `openclaw.harness.duration_ms`(直方图,属性:`openclaw.harness.id`、`openclaw.harness.plugin`、`openclaw.outcome`,以及出错时`openclaw.harness.phase`
- `openclaw.harness.duration_ms`(直方图,属性:`openclaw.harness.id`、`openclaw.harness.plugin`、`openclaw.outcome`,以及错误情况下`openclaw.harness.phase`
### Exec
- `openclaw.exec.duration_ms`(直方图,属性:`openclaw.exec.target`、`openclaw.exec.mode`、`openclaw.outcome`、`openclaw.failureKind`
### 诊断内部指标(内存与工具循环)
### 诊断内部机制(内存和工具循环)
- `openclaw.memory.heap_used_bytes`(直方图,属性:`openclaw.memory.kind`
- `openclaw.memory.rss_bytes`(直方图)
@ -216,19 +196,20 @@ openclaw plugins enable diagnostics-otel
- `openclaw.model.usage`
- `openclaw.channel`、`openclaw.provider`、`openclaw.model`
- `openclaw.tokens.*`input/output/cache_read/cache_write/total
- 默认使用 `gen_ai.system`,或者在选择启用最新 GenAI 语义约定时使用 `gen_ai.provider.name`
- 默认使用 `gen_ai.system`,或者在启用最新 GenAI 语义约定时使用 `gen_ai.provider.name`
- `gen_ai.request.model`、`gen_ai.operation.name`、`gen_ai.usage.*`
- `openclaw.run`
- `openclaw.outcome`、`openclaw.channel`、`openclaw.provider`、`openclaw.model`、`openclaw.errorCategory`
- `openclaw.model.call`
- 默认使用 `gen_ai.system`,或者在选择启用最新 GenAI 语义约定时使用 `gen_ai.provider.name`
- 默认使用 `gen_ai.system`,或者在启用最新 GenAI 语义约定时使用 `gen_ai.provider.name`
- `gen_ai.request.model`、`gen_ai.operation.name`、`openclaw.provider`、`openclaw.model`、`openclaw.api`、`openclaw.transport`
- 出错时包含 `openclaw.errorCategory` 和可选的 `openclaw.failureKind`
- `openclaw.model_call.request_bytes`、`openclaw.model_call.response_bytes`、`openclaw.model_call.time_to_first_byte_ms`
- `openclaw.provider.request_id_hash`(上游提供商请求 ID 的有界 SHA 哈希;不会导出原始 ID
- `openclaw.provider.request_id_hash`(上游提供商请求 id 的有界 SHA 哈希;不会导出原始 id
- `openclaw.harness.run`
- `openclaw.harness.id`、`openclaw.harness.plugin`、`openclaw.outcome`、`openclaw.provider`、`openclaw.model`、`openclaw.channel`
- 完成时:`openclaw.harness.result_classification`、`openclaw.harness.yield_detected`、`openclaw.harness.items.started`、`openclaw.harness.items.completed`、`openclaw.harness.items.active`
- 出错时:`openclaw.harness.phase`、`openclaw.errorCategory`,以及可选的 `openclaw.harness.cleanup_failed`
- 出错时:`openclaw.harness.phase`、`openclaw.errorCategory`可选的 `openclaw.harness.cleanup_failed`
- `openclaw.tool.execution`
- `gen_ai.tool.name`、`openclaw.toolName`、`openclaw.errorCategory`、`openclaw.tool.params.*`
- `openclaw.exec`
@ -244,24 +225,21 @@ openclaw plugins enable diagnostics-otel
- `openclaw.session.stuck`
- `openclaw.state`、`openclaw.ageMs`、`openclaw.queueDepth`
- `openclaw.context.assembled`
- `openclaw.prompt.size`、`openclaw.history.size`、`openclaw.context.tokens`、`openclaw.errorCategory`(不包含 prompt、history、response 或 session-key 内容)
- `openclaw.prompt.size`、`openclaw.history.size`、`openclaw.context.tokens`、`openclaw.errorCategory`(不包含提示词、历史记录、响应或会话键内容)
- `openclaw.tool.loop`
- `openclaw.toolName`、`openclaw.outcome`、`openclaw.iterations`、`openclaw.errorCategory`(不包含循环消息、参数或工具输出)
- `openclaw.memory.pressure`
- `openclaw.memory.level`、`openclaw.memory.heap_used_bytes`、`openclaw.memory.rss_bytes`
当显式启用内容采集时,模型和工具 span 还可以包含你所选择启用的特定内容类别对应的有界、已脱敏 `openclaw.content.*` 属性。
当显式启用内容采集时,模型和工具 span 还可以包含你所选择的特定内容类别对应的有界、已脱敏 `openclaw.content.*` 属性。
## 诊断事件目录
以下事件支撑上面的指标和 span。插件也可以直接订阅这些事件而无需 OTLP 导出。
下列事件构成了上面的指标和 span。插件也可以直接订阅这些事件而无需通过 OTLP 导出。
**模型使用情况**
- `model.usage` —— token、成本、时长、上下文、提供商/模型/渠道、
会话 ID。`usage` 是提供商/轮次级别的成本与遥测统计;
`context.used` 是当前 prompt/上下文快照,当涉及缓存输入或工具循环调用时,
它可能小于提供商的 `usage.total`
- `model.usage` — 令牌、成本、持续时间、上下文、提供商/模型/渠道、会话 id。`usage` 是提供商/轮次级别的成本和遥测记账;`context.used` 是当前的提示词/上下文快照,当涉及缓存输入或工具循环调用时,它可能低于提供商的 `usage.total`
**消息流**
@ -269,29 +247,22 @@ openclaw plugins enable diagnostics-otel
- `message.queued` / `message.processed`
- `message.delivery.started` / `message.delivery.completed` / `message.delivery.error`
**队列会话**
**队列会话**
- `queue.lane.enqueue` / `queue.lane.dequeue`
- `session.state` / `session.stuck`
- `run.attempt`
- `diagnostic.heartbeat`聚合计数器webhooks/queue/session
- `diagnostic.heartbeat`聚合计数器webhooks/队列/会话
**Harness 生命周期**
- `harness.run.started` / `harness.run.completed` / `harness.run.error`
智能体 harness 的逐次运行生命周期。包括 `harnessId`、可选的
`pluginId`、provider/model/channel以及 run id。完成事件会新增
`durationMs`、`outcome`、可选的 `resultClassification`、`yieldDetected`
以及 `itemLifecycle` 计数。错误事件会新增 `phase`
`prepare`/`start`/`send`/`resolve`/`cleanup`)、`errorCategory`,以及
可选的 `cleanupFailed`
- `harness.run.started` / `harness.run.completed` / `harness.run.error` — 智能体 harness 的逐次运行生命周期。包含 `harnessId`、可选的 `pluginId`、提供商/模型/渠道以及运行 id。完成事件会附加 `durationMs`、`outcome`、可选的 `resultClassification`、`yieldDetected` 和 `itemLifecycle` 计数。错误事件会附加 `phase``prepare`/`start`/`send`/`resolve`/`cleanup`)、`errorCategory` 和可选的 `cleanupFailed`
**Exec**
- `exec.process.completed` —— 最终结果、时长、目标、模式、退出
码和失败类型。不包含命令文本和工作目录。
- `exec.process.completed` — 最终结果、持续时间、目标、模式、退出码和失败类型。不包含命令文本和工作目录。
## 不使用导出器
## 没有导出器时
你可以在不运行 `diagnostics-otel` 的情况下,仍然让诊断事件可供插件或自定义接收端使用:
@ -301,9 +272,7 @@ openclaw plugins enable diagnostics-otel
}
```
如果你想要定向调试输出,而不提升 `logging.level`,可以使用诊断
标记。标记不区分大小写,并支持通配符(例如 `telegram.*`
`*`
如果你想获得定向调试输出而不提高 `logging.level`,请使用诊断标记。标记不区分大小写,并支持通配符(例如 `telegram.*``*`
```json5
{
@ -317,8 +286,7 @@ openclaw plugins enable diagnostics-otel
OPENCLAW_DIAGNOSTICS=telegram.http,telegram.payload openclaw gateway
```
标记输出会写入标准日志文件(`logging.file`),并仍然会被
`logging.redactSensitive` 脱敏。完整指南:
标记输出会写入标准日志文件(`logging.file`),并且仍会被 `logging.redactSensitive` 脱敏。完整指南:
[诊断标记](/zh-CN/diagnostics/flags)。
## 禁用
@ -329,13 +297,13 @@ OPENCLAW_DIAGNOSTICS=telegram.http,telegram.payload openclaw gateway
}
```
你也可以不`diagnostics-otel` 放入 `plugins.allow`,或者运行
你也可以不`diagnostics-otel` 加入 `plugins.allow`,或者运行
`openclaw plugins disable diagnostics-otel`
## 相关内容
- [日志记录](/zh-CN/logging) — 文件日志、控制台输出、CLI 尾随查看,以及 Control UI 的 Logs 标签页
- [Gateway 网关日志记录内部机制](/zh-CN/gateway/logging) — WS 日志样式、子系统前缀和控制台捕获
- [日志记录](/zh-CN/logging) — 文件日志、控制台输出、CLI tail 查看,以及 Control UI 的日志标签页
- [Gateway 网关日志内部机制](/zh-CN/gateway/logging) — WS 日志样式、子系统前缀和控制台捕获
- [诊断标记](/zh-CN/diagnostics/flags) — 定向调试日志标记
- [诊断导出](/zh-CN/gateway/diagnostics) — 面向运维的支持包导出工具(与 OTEL 导出分开)
- [诊断导出](/zh-CN/gateway/diagnostics) — 面向运维人员的支持包工具(与 OTEL 导出分开)
- [配置参考](/zh-CN/gateway/configuration-reference#diagnostics) — 完整的 `diagnostics.*` 字段参考

View File

@ -1,21 +1,21 @@
---
read_when:
- 你正在构建一个 OpenClaw 插件】【。
- 你需要发布一个插件配置 schema或调试插件验证错误】【。
- 你正在构建一个 OpenClaw 插件
- 你需要发布一个插件配置 schema或调试插件验证错误
summary: 插件清单 + JSON schema 要求(严格配置验证)
title: 插件清单
x-i18n:
generated_at: "2026-04-27T08:00:40Z"
generated_at: "2026-04-27T08:31:19Z"
model: gpt-5.4
provider: openai
source_hash: 9d6e1da1cc57f6ba89ef511b01636439dd34f0b847a306b96271ccf9c2b878d4
source_hash: 5b3ffcdfcf09b4480d0cec007d645daebdaeb86a051a233dec192f555359162a
source_path: plugins/manifest.md
workflow: 15
---
此页面仅适用于**原生 OpenClaw 插件清单**。
关于兼容的 bundle 布局,请参 [Plugin bundles](/zh-CN/plugins/bundles)。
关于兼容的 bundle 布局,请参 [Plugin bundles](/zh-CN/plugins/bundles)。
兼容的 bundle 格式使用不同的清单文件:
@ -23,31 +23,31 @@ x-i18n:
- Claude bundle`.claude-plugin/plugin.json`,或不带清单的默认 Claude 组件布局
- Cursor bundle`.cursor-plugin/plugin.json`
OpenClaw 也会自动检测这些 bundle 布局,但它们不会根据此处描述的 `openclaw.plugin.json` schema 进行验证。
OpenClaw 也会自动检测这些 bundle 布局,但不会按照此处描述的 `openclaw.plugin.json` schema 对它们进行验证。
对于兼容 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 使用此清单在**不执行插件代码**的情况下验证配置。缺失或无效的清单会被视为插件错误,并阻止配置验证。
请参阅完整的插件系统指南:[Plugins](/zh-CN/tools/plugin)。
关于原生能力模型和当前外部兼容性指导,请参见
请参阅完整的插件系统指南:[插件](/zh-CN/tools/plugin)。
关于原生能力模型和当前的外部兼容性指引,请参阅
[能力模型](/zh-CN/plugins/architecture#public-capability-model)。
## 这个文件的作用
## 文件的作用
`openclaw.plugin.json` 是 OpenClaw 在**加载你的插件代码之前**读取的元数据。下面的所有内容都必须足够轻量,以便在不启动插件运行时的情况下进行检查。
**将它用于:**
**用于:**
- 插件标识、配置验证和配置 UI 提示
- 认证、新手引导和设置元数据(别名、自动启用、提供商环境变量、认证选项)
- 控制平面界面的激活提示
- 简写模型族归属
- 凭证、onboarding 和设置元数据别名、自动启用、provider 环境变量、凭证选项)
- control-plane 界面的激活提示
- 简写模型族归属
- 静态能力归属快照(`contracts`
- 共享 `openclaw qa` 主机检查的 QA 运行器元数据
- 合并到目录和验证界面中的渠道专用配置元数据
- 共享 `openclaw qa` 主机检查的 QA 运行器元数据
- 合并到 catalog 和验证界面中的渠道专用配置元数据
**不要将它用于:** 注册运行时行为、声明代码入口点或 npm 安装元数据。这些属于你的插件代码和 `package.json`
**不要用于:**注册运行时行为、声明代码入口点或 npm 安装元数据。这些应放在你的插件代码和 `package.json`
## 最小示例
@ -129,69 +129,67 @@ OpenClaw 也会自动检测这些 bundle 布局,但它们不会根据此处描
| 字段 | 必填 | 类型 | 含义 |
| ------------------------------------ | -------- | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id` | 是 | `string` | 规范插件 id。这是在 `plugins.entries.<id>` 中使用的 id。 |
| `id` | 是 | `string` | 规范插件 id。这是在 `plugins.entries.<id>` 中使用的 id。 |
| `configSchema` | 是 | `object` | 此插件配置的内联 JSON Schema。 |
| `enabledByDefault` | 否 | `true` | 将内置插件标记为默认启用。省略此项,或设置为任何非 `true` 的值,以使该插件默认禁用。 |
| `legacyPluginIds` | 否 | `string[]` | 会规范化为此规范插件 id 的旧版 id。 |
| `autoEnableWhenConfiguredProviders` | 否 | `string[]` | 当认证、配置或模型引用提到这些提供商 id 时,应自动启用此插件。 |
| `kind` | 否 | `"memory"` \| `"context-engine"` | 声明一个由 `plugins.slots.*` 使用的互斥插件种类。 |
| `channels` | 否 | `string[]` | 由此插件拥有的渠道 id。用于发现和配置验证。 |
| `providers` | 否 | `string[]` | 由此插件拥有的提供商 id。 |
| `providerDiscoveryEntry` | 否 | `string` | 轻量级 provider 发现模块路径,相对于插件根目录,用于可在不激活完整插件运行时的情况下加载的、限定于清单范围内的 provider 目录元数据。 |
| `modelSupport` | 否 | `object` | 由清单拥有的简写模型族元数据,用于在运行时之前自动加载插件。 |
| `modelCatalog` | 否 | `object` | 适用于由此插件拥有的提供商的声明式模型目录元数据。这是未来只读列表、新手引导、模型选择器、别名和抑制功能在不加载插件运行时情况下的控制平面契约。 |
| `providerEndpoints` | 否 | `object[]` | 由清单拥有的端点 host / `baseUrl` 元数据,用于核心在 provider 运行时加载前必须分类的 provider 路由。 |
| `cliBackends` | 否 | `string[]` | 由此插件拥有的 CLI 推理后端 id。用于根据显式配置引用在启动时自动激活。 |
| `syntheticAuthRefs` | 否 | `string[]` | provider 或 CLI 后端引用;在运行时加载前的冷启动模型发现期间,应探测其由插件拥有的合成认证钩子。 |
| `nonSecretAuthMarkers` | 否 | `string[]` | 由内置插件拥有的占位 API 密钥值表示非密钥的本地、OAuth 或环境凭证状态。 |
| `commandAliases` | 否 | `object[]` | 由此插件拥有的命令名称;在运行时加载前,这些命令应产生具备插件感知的配置和 CLI 诊断信息。 |
| `providerAuthEnvVars` | 否 | `Record<string, string[]>` | 已弃用的兼容性环境变量元数据,用于 provider 认证 / Status 查询。对于新插件,优先使用 `setup.providers[].envVars`OpenClaw 在弃用窗口期内仍会读取此项。 |
| `providerAuthAliases` | 否 | `Record<string, string>` | 应复用另一个 provider id 进行认证查询的 provider id例如共享基础 provider API 密钥和 auth profile 的编码 provider。 |
| `channelEnvVars` | 否 | `Record<string, string[]>` | OpenClaw 可在不加载插件代码的情况下检查的轻量级渠道环境变量元数据。将其用于通用启动 / 配置辅助工具应可见的、由环境变量驱动的渠道设置或认证界面。 |
| `providerAuthChoices` | 否 | `object[]` | 适用于新手引导选择器、首选 provider 解析和简单 CLI 标志接线的轻量级认证选项元数据。 |
| `activation` | 否 | `object` | 适用于由 provider、命令、渠道、路由和能力触发加载的轻量级激活规划器元数据。仅为元数据实际行为仍由插件运行时负责。 |
| `setup` | 否 | `object` | 可供发现和设置界面在不加载插件运行时情况下检查的轻量级设置 / 新手引导描述符。 |
| `qaRunners` | 否 | `object[]` | 共享 `openclaw qa` 主机在插件运行时加载前使用的轻量级 QA 运行器描述符。 |
| `contracts` | 否 | `object` | 外部认证钩子、语音、实时转写、实时语音、媒体理解、图像生成、音乐生成、视频生成、网页抓取、Ollama Web 搜索 和工具归属的静态内置能力快照。 |
| `mediaUnderstandingProviderMetadata` | 否 | `Record<string, object>` | 适用于在 `contracts.mediaUnderstandingProviders` 中声明的 provider id 的轻量级媒体理解默认值。 |
| `channelConfigs` | 否 | `Record<string, object>` | 由清单拥有的渠道配置元数据,在运行时加载前合并到发现和验证界面中。 |
| `enabledByDefault` | 否 | `true` | 将内置插件标记为默认启用。省略此字段,或将其设置为任何非 `true` 的值,则插件默认保持禁用。 |
| `legacyPluginIds` | 否 | `string[]` | 会规范化为此标准插件 id 的旧版 id。 |
| `autoEnableWhenConfiguredProviders` | 否 | `string[]` | 当凭证、配置或模型引用提到这些 provider id 时,应自动启用此插件。 |
| `kind` | 否 | `"memory"` \| `"context-engine"` | 声明一个由 `plugins.slots.*` 使用的排他性插件种类。 |
| `channels` | 否 | `string[]` | 由此插件拥有的渠道 id。用于设备发现和配置验证。 |
| `providers` | 否 | `string[]` | 由此插件拥有的 provider id。 |
| `providerDiscoveryEntry` | 否 | `string` | 轻量级 provider 发现模块路径,相对于插件根目录,用于可在不激活完整插件运行时的情况下加载的、限定于清单范围内的 provider catalog 元数据。 |
| `modelSupport` | 否 | `object` | 由清单拥有的简写模型家族元数据,用于在运行时之前自动加载插件。 |
| `modelCatalog` | 否 | `object` | 由此插件拥有的 providers 的声明式模型 catalog 元数据。这是未来只读列表、新手引导、模型选择器、别名和抑制功能的 control-plane 契约,无需加载插件运行时。 |
| `modelPricing` | 否 | `object` | provider 自有的外部定价查询策略。用它可让本地 / 自托管 provider 退出远程定价 catalog或将 provider 引用映射到 OpenRouter / LiteLLM catalog id而无需在核心中硬编码 provider id。 |
| `providerEndpoints` | 否 | `object[]` | 由清单拥有的 endpoint host / `baseUrl` 元数据,用于核心在 provider 运行时加载前必须分类的 provider 路由。 |
| `cliBackends` | 否 | `string[]` | 由此插件拥有的 CLI 推理后端 id。用于基于显式配置引用的启动时自动激活。 |
| `syntheticAuthRefs` | 否 | `string[]` | provider 或 CLI 后端引用;在运行时加载之前的冷启动模型发现期间,应探测其由插件拥有的 synthetic auth hook。 |
| `nonSecretAuthMarkers` | 否 | `string[]` | 由内置插件拥有的占位 API key 值表示非密钥的本地、OAuth 或环境凭证状态。 |
| `commandAliases` | 否 | `object[]` | 由此插件拥有的命令名称,应在运行时加载前生成具备插件感知能力的配置和 CLI 诊断信息。 |
| `providerAuthEnvVars` | 否 | `Record<string, string[]>` | 已弃用的兼容性环境变量元数据,用于 provider 凭证 / Status 查询。新插件请优先使用 `setup.providers[].envVars`在弃用过渡期内OpenClaw 仍会读取此字段。 |
| `providerAuthAliases` | 否 | `Record<string, string>` | 应复用另一个 provider id 进行凭证查询的 provider id例如与基础 provider 共享 API key 和凭证配置文件的编码 provider。 |
| `channelEnvVars` | 否 | `Record<string, string[]>` | OpenClaw 可在不加载插件代码的情况下检查的轻量级渠道环境变量元数据。将其用于由环境变量驱动的渠道设置或凭证界面,以便通用的启动 / 配置辅助工具可以识别。 |
| `providerAuthChoices` | 否 | `object[]` | 轻量级的凭证选项元数据,用于 onboarding 选择器、首选 provider 解析和简单的 CLI 标志绑定。 |
| `activation` | 否 | `object` | 轻量级的激活规划器元数据,用于基于 provider、命令、渠道、路由和能力触发的加载。仅为元数据实际行为仍由插件运行时负责。 |
| `setup` | 否 | `object` | 轻量级的设置 / onboarding 描述符,供设备发现和设置界面在不加载插件运行时的情况下检查。 |
| `qaRunners` | 否 | `object[]` | 轻量级 QA 运行器描述符,供共享 `openclaw qa` 主机在插件运行时加载前使用。 |
| `contracts` | 否 | `object` | 静态内置能力快照,用于 external auth hooks、speech、实时转录、实时语音、媒体理解、图像生成、音乐生成、视频生成、web-fetch、网络搜索和工具归属。 |
| `mediaUnderstandingProviderMetadata` | 否 | `Record<string, object>` | 为 `contracts.mediaUnderstandingProviders` 中声明的 provider id 提供的轻量级媒体理解默认值。 |
| `channelConfigs` | 否 | `Record<string, object>` | 由清单拥有的渠道配置元数据,在运行时加载前合并到设备发现和验证界面中。 |
| `skills` | 否 | `string[]` | 要加载的 Skills 目录,相对于插件根目录。 |
| `name` | 否 | `string` | 人类可读的插件名称。 |
| `description` | 否 | `string` | 显示在插件界面中的简短摘要。 |
| `description` | 否 | `string` | 在插件界面中显示的简短摘要。 |
| `version` | 否 | `string` | 信息性插件版本。 |
| `uiHints` | 否 | `Record<string, object>` | 配置字段的 UI 标签、占位符和敏感性提示。 |
## `providerAuthChoices` 参考
每个 `providerAuthChoices` 条目描述一个新手引导或认证选项。
每个 `providerAuthChoices` 条目描述一个 onboarding 或凭证选项。
OpenClaw 会在 provider 运行时加载前读取它。
provider 设置列表会使用这些清单选项、由描述符派生的设置选项,
以及安装目录元数据,而无需加载 provider 运行时。
provider 设置列表会使用这些清单选项、从描述符派生的设置选项以及安装 catalog 元数据,而无需加载 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应该将用户重定向到这个替代选项。 |
| `method` | 是 | `string` | 要分派到的证方法 id。 |
| `choiceId` | 是 | `string` | onboarding 和 CLI 流程使用的稳定凭证选项 id。 |
| `choiceLabel` | 否 | `string` | 面向用户的标签。如省略OpenClaw 会回退到 `choiceId`。 |
| `choiceHint` | 否 | `string` | 选择器中的简短助文本。 |
| `assistantPriority` | 否 | `number` | 在由 assistant 驱动的交互式选择器中,值越小排序越靠前。 |
| `assistantVisibility` | 否 | `"visible"` \| `"manual-only"` | 在 assistant 选择器中隐藏此选项,但仍允许手动 CLI 选择。 |
| `deprecatedChoiceIds` | 否 | `string[]` | 应将用户重定向到此替代选项的旧版选项 id。 |
| `groupId` | 否 | `string` | 用于对相关选项分组的可选分组 id。 |
| `groupLabel` | 否 | `string` | 该分组面向用户标签。 |
| `groupHint` | 否 | `string` | 该分组的简短助文本。 |
| `optionKey` | 否 | `string` | 用于简单单标志证流程的内部选项键。 |
| `groupLabel` | 否 | `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">` | 此选项应出现在哪些 onboarding 界面中。如省略,默认值为 `["text-inference"]`。 |
## `commandAliases` 参考
当插件拥有一个运行时命令名称,而用户可能误将其放入 `plugins.allow`
或尝试将其作为根 CLI 命令运行时,请使用 `commandAliases`。OpenClaw
使用这些元数据来提供诊断,而无需导入插件运行时代码。
当插件拥有一个运行时命令名,而用户可能错误地将它放入 `plugins.allow` 中,或尝试将它作为根 CLI 命令运行时,请使用 `commandAliases`。OpenClaw 使用这些元数据提供诊断,而无需导入插件运行时代码。
```json
{
@ -209,33 +207,18 @@ provider 设置列表会使用这些清单选项、由描述符派生的设置
| ------------ | -------- | ----------------- | ----------------------------------------------------------------------- |
| `name` | 是 | `string` | 属于此插件的命令名称。 |
| `kind` | 否 | `"runtime-slash"` | 将该别名标记为聊天斜杠命令,而不是根 CLI 命令。 |
| `cliCommand` | 否 | `string` | 若存在,用于建议 CLI 操作的相关根 CLI 命令。 |
| `cliCommand` | 否 | `string` | 若存在,可建议用于 CLI 操作的相关根 CLI 命令。 |
## `activation` 参考
当插件可以以低成本声明哪些控制平面事件
应将其包含在激活 / 加载计划中时,请使用 `activation`
当插件能够以低成本声明哪些 control-plane 事件应将其纳入激活 / 加载计划时,请使用 `activation`
此块是规划器元数据,而不是生命周期 API。它不会注册
运行时行为,不会替代 `register(...)`,也不保证
插件代码已执行。激活规划器使用这些字段来
缩小候选插件范围,然后才回退到现有的清单归属
元数据,例如 `providers`、`channels`、`commandAliases`、`setup.providers`、
`contracts.tools` 和 hooks。
此块是规划器元数据,不是生命周期 API。它不会注册运行时行为不会替代 `register(...)`,也不保证插件代码已经执行。激活规划器使用这些字段在回退到现有清单归属元数据(如 `providers`、`channels`、`commandAliases`、`setup.providers`、`contracts.tools` 和 hooks之前先缩小候选插件范围。
优先使用已经能够描述归属关系的最窄元数据。能用
`providers`、`channels`、`commandAliases`、setup 描述符或 `contracts`
表达关系时,就使用这些字段。对于无法由这些归属字段表示的额外规划器
提示,再使用 `activation`
对于 `claude-cli`、`codex-cli` 或 `google-gemini-cli` 这类 CLI 运行时别名,
请使用顶层 `cliBackends``activation.onAgentHarnesses` 仅适用于
那些尚无归属字段的嵌入式 Agent harness id。
优先使用已经能够描述归属关系的最窄元数据。当这些字段可以表达该关系时,请使用 `providers`、`channels`、`commandAliases`、setup 描述符或 `contracts`。对于这些归属字段无法表示的额外规划提示,再使用 `activation`
对于诸如 `claude-cli`、`codex-cli` 或 `google-gemini-cli` 之类的 CLI 运行时别名,请使用顶层 `cliBackends``activation.onAgentHarnesses` 仅用于那些尚无归属字段的嵌入式 agent harness id。
此块仅为元数据。它不会注册运行时行为,也不会
替代 `register(...)`、`setupEntry` 或其他运行时 / 插件入口点。
当前使用方会在更广泛的插件加载之前将其作为缩小范围的提示,因此
缺少激活元数据通常只会带来性能成本;
只要旧版清单归属回退仍然存在,就不应影响正确性。
此块仅为元数据。它不会注册运行时行为,也不会替代 `register(...)`、`setupEntry` 或其他运行时 / 插件入口点。当前使用方会在更广泛的插件加载之前,将其作为缩小范围的提示,因此缺失激活元数据通常只会带来性能成本;在旧版清单归属回退仍存在的情况下,它不应改变正确性。
```json
{
@ -251,39 +234,29 @@ provider 设置列表会使用这些清单选项、由描述符派生的设置
| 字段 | 必填 | 类型 | 含义 |
| ------------------ | -------- | ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `onProviders` | 否 | `string[]` | 应将此插件包含在激活 / 加载计划中的 provider id。 |
| `onAgentHarnesses` | 否 | `string[]` | 应将此插件包含在激活 / 加载计划中的嵌入式 Agent harness 运行时 id。对于 CLI 后端别名,请使用顶层 `cliBackends`。 |
| `onCommands` | 否 | `string[]` | 应将此插件包含在激活 / 加载计划中的命令 id。 |
| `onChannels` | 否 | `string[]` | 应将此插件包含在激活 / 加载计划中的渠道 id。 |
| `onRoutes` | 否 | `string[]` | 应将此插件包含在激活 / 加载计划中的路由类型。 |
| `onCapabilities` | 否 | `Array<"provider" \| "channel" \| "tool" \| "hook">` | 用于控制平面激活规划的宽泛能力提示。可以的话,优先使用更窄的字段。 |
| `onProviders` | 否 | `string[]` | 应将此插件纳入激活 / 加载计划的 provider id。 |
| `onAgentHarnesses` | 否 | `string[]` | 应将此插件纳入激活 / 加载计划的嵌入式 Agent harness 运行时 id。对于 CLI 后端别名,请使用顶层 `cliBackends`。 |
| `onCommands` | 否 | `string[]` | 应将此插件纳入激活 / 加载计划的命令 id。 |
| `onChannels` | 否 | `string[]` | 应将此插件纳入激活 / 加载计划的渠道 id。 |
| `onRoutes` | 否 | `string[]` | 应将此插件纳入激活 / 加载计划的路由种类。 |
| `onCapabilities` | 否 | `Array<"provider" \| "channel" \| "tool" \| "hook">` | control-plane 激活规划中使用的宽泛能力提示。可能时优先使用更窄的字段。 |
当前在线使用方:
- 命令触发的 CLI 规划会回退到旧版
- 命令触发的 CLI 规划会回退到旧版
`commandAliases[].cliCommand``commandAliases[].name`
- 智能体运行时启动规划对嵌入式 harness 使用 `activation.onAgentHarnesses`
对 CLI 运行时别名使用顶层 `cliBackends[]`
- 由渠道触发的设置 / 渠道规划在缺少显式渠道激活元数据时,
会回退到旧版 `channels[]`
- agent 运行时启动规划对嵌入式 harness 使用 `activation.onAgentHarnesses`,对 CLI 运行时别名使用顶层 `cliBackends[]`
- 渠道触发的 setup / 渠道规划在缺少显式渠道激活元数据时,会回退到旧版 `channels[]`
归属
- provider 触发的 setup / 运行时规划在缺少显式 provider
激活元数据时,会回退到旧版 `providers[]` 和顶层 `cliBackends[]`
归属
- 由 provider 触发的设置 / 运行时规划在缺少显式 provider
激活元数据时,会回退到旧版
`providers[]` 和顶层 `cliBackends[]` 归属
规划器诊断可以区分显式激活提示和清单
归属回退。例如,`activation-command-hint` 表示
匹配了 `activation.onCommands`,而 `manifest-command-alias` 表示
规划器改用了 `commandAliases` 归属。这些原因标签
用于宿主诊断和测试;插件作者应继续声明最能描述
归属关系的元数据。
规划器诊断可以区分显式激活提示和清单归属回退。例如,`activation-command-hint` 表示匹配了 `activation.onCommands`,而 `manifest-command-alias` 表示规划器改用了 `commandAliases` 归属。这些原因标签用于主机诊断和测试;插件作者应继续声明最能描述归属关系的元数据。
## `qaRunners` 参考
当插件在共享的 `openclaw qa` 根命令下贡献一个或多个传输运行器时,
请使用 `qaRunners`。请保持这些元数据轻量且静态;
实际的 CLI 注册仍由插件运行时通过一个轻量级
`runtime-api.ts` 接口负责,该接口导出 `qaRunnerCliRegistrations`
当插件在共享 `openclaw qa` 根命令下贡献一个或多个传输运行器时,请使用 `qaRunners`。请保持这些元数据轻量且静态;实际的 CLI 注册仍由插件运行时通过导出 `qaRunnerCliRegistrations` 的轻量级 `runtime-api.ts` 界面负责。
```json
{
@ -298,13 +271,12 @@ provider 设置列表会使用这些清单选项、由描述符派生的设置
| 字段 | 必填 | 类型 | 含义 |
| ------------- | -------- | -------- | ------------------------------------------------------------------ |
| `commandName` | 是 | `string` | 挂载在 `openclaw qa` 下的子命令,例如 `matrix`。 |
| `description` | 否 | `string` | 当共享宿主需要一个桩命令时使用的回退帮助文本。 |
| `commandName` | 是 | `string` | 挂载在 `openclaw qa` 下的子命令,例如 `matrix`。 |
| `description` | 否 | `string` | 当共享主机需要一个 stub 命令时使用的回退帮助文本。 |
## `setup` 参考
当设置和新手引导界面需要在运行时加载前获取由插件拥有的轻量级元数据时,
请使用 `setup`
当设置和 onboarding 界面在运行时加载前需要轻量级的、由插件拥有的元数据时,请使用 `setup`
```json
{
@ -323,65 +295,40 @@ provider 设置列表会使用这些清单选项、由描述符派生的设置
}
```
顶层 `cliBackends` 仍然有效,并继续描述 CLI 推理
后端。`setup.cliBackends` 是面向
应保持仅元数据化的控制平面 / 设置流程的、设置专用描述符界面。
顶层 `cliBackends` 仍然有效,并继续描述 CLI 推理后端。`setup.cliBackends` 是面向 control-plane / 设置流程的、特定于设置的描述符界面,应保持为纯元数据。
存在 `setup.providers``setup.cliBackends` 时,它们是
设置发现中优先使用的描述符优先查询界面。如果该描述符仅用于
缩小候选插件范围,而设置仍需要更丰富的设置期运行时钩子,
请将 `requiresRuntime` 设为 `true`,并保留 `setup-api`
作为回退执行路径。
存在时,`setup.providers` 和 `setup.cliBackends` 是设置发现时首选的 descriptor-first 查询界面。如果描述符仅缩小候选插件范围,而设置仍需要更丰富的设置时运行时 hooks请将 `requiresRuntime` 设为 `true`,并保留 `setup-api` 作为回退执行路径。
OpenClaw 还会将 `setup.providers[].envVars` 包含在通用 provider 认证和
环境变量查询中。`providerAuthEnvVars` 在弃用窗口期内仍通过兼容适配器
继续受支持,但仍在使用它的非内置插件
会收到清单诊断。新插件应将设置 / Status 环境变量元数据
放在 `setup.providers[].envVars` 上。
OpenClaw 还会将 `setup.providers[].envVars` 纳入通用 provider 凭证和环境变量查询中。`providerAuthEnvVars` 在弃用过渡期内仍通过兼容适配器受支持,但仍使用它的非内置插件会收到清单诊断。新插件应将设置 / Status 环境变量元数据放在 `setup.providers[].envVars` 上。
在没有 setup 入口时,或者当
`setup.requiresRuntime: false` 声明设置运行时不必要时OpenClaw 也可以从 `setup.providers[].authMethods`
派生出简单的设置选项。对于自定义标签、CLI 标志、新手引导范围
和助手元数据,显式的 `providerAuthChoices` 条目仍然是首选。
当没有 setup 条目,或者 `setup.requiresRuntime: false` 表示无需设置运行时时OpenClaw 也可以根据 `setup.providers[].authMethods` 推导简单的设置选项。显式的 `providerAuthChoices` 条目仍然更适合自定义标签、CLI 标志、onboarding 范围和 assistant 元数据。
仅当这些描述符已足以满足
设置界面时,才将 `requiresRuntime: false`。OpenClaw 将显式的 `false` 视为仅描述符契约,
并且不会为设置查询执行 `setup-api``openclaw.setupEntry`。如果
一个仅描述符插件仍然提供了其中某个设置运行时入口,
OpenClaw 会报告一条附加诊断,并继续忽略它。省略
`requiresRuntime` 会保留旧版回退行为,因此现有那些在未设置该标志的情况下添加了
描述符的插件不会失效。
仅当这些描述符已足以满足设置界面需求时,才将 `requiresRuntime` 设为 `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` 注册了一个提供商或 CLI 后端,
但清单描述符没有声明它,或者某个描述符没有匹配的运行时
注册,设置注册表诊断就会报告描述符漂移。
这些诊断是附加性的,不会拒绝旧版插件。
当设置运行时确实执行时,如果 `setup-api` 注册了清单描述符未声明的 provider 或 CLI 后端,或者某个描述符没有对应的运行时注册,设置注册表诊断会报告描述符漂移。这些诊断是附加性的,不会拒绝旧版插件。
### `setup.providers` 参考
| 字段 | 必填 | 类型 | 含义 |
| ------------- | -------- | ---------- | ------------------------------------------------------------------------------------ |
| `id` | 是 | `string` | 在设置或新手引导期间暴露的 provider id。请保持规范化 id 在全局范围内唯一。 |
| `authMethods` | 否 | `string[]` | 此 provider 在不加载完整运行时的情况下支持的设置 / 证方法 id。 |
| `id` | 是 | `string` | 在设置或 onboarding 期间公开的 provider id。保持规范化 id 在全局范围内唯一。 |
| `authMethods` | 否 | `string[]` | 此 provider 在不加载完整运行时的情况下支持的设置 / 证方法 id。 |
| `envVars` | 否 | `string[]` | 通用设置 / Status 界面可在插件运行时加载前检查的环境变量。 |
### `setup` 字段
| 字段 | 必填 | 类型 | 含义 |
| ------------------ | -------- | ---------- | --------------------------------------------------------------------------------------------------- |
| `providers` | 否 | `object[]` | 在设置和新手引导期间暴露的 provider 设置描述符。 |
| `cliBackends` | 否 | `string[]` | 用于描述符优先设置查询的设置期后端 id。请保持规范化 id 在全局范围内唯一。 |
| `providers` | 否 | `object[]` | 在设置和 onboarding 期间公开的 provider 设置描述符。 |
| `cliBackends` | 否 | `string[]` | 用于 descriptor-first 设置查询的设置时后端 id。保持规范化 id 在全局范围内唯一。 |
| `configMigrations` | 否 | `string[]` | 由此插件的设置界面拥有的配置迁移 id。 |
| `requiresRuntime` | 否 | `boolean` | 描述符查询后,设置是否仍需要执行 `setup-api`。 |
| `requiresRuntime` | 否 | `boolean` | 描述符查询后,设置是否仍需要执行 `setup-api`。 |
## `uiHints` 参考
`uiHints`一个从配置字段名映射到小型渲染提示的映射表。
`uiHints` 是从配置字段名映射到小型渲染提示的映射表。
```json
{
@ -401,16 +348,15 @@ OpenClaw 会报告一条附加诊断,并继续忽略它。省略
| 字段 | 类型 | 含义 |
| ------------- | ---------- | --------------------------------------- |
| `label` | `string` | 面向用户的字段标签。 |
| `help` | `string` | 简短助文本。 |
| `tags` | `string[]` | 可选 UI 标签。 |
| `help` | `string` | 简短助文本。 |
| `tags` | `string[]` | 可选 UI 标签。 |
| `advanced` | `boolean` | 将该字段标记为高级项。 |
| `sensitive` | `boolean` | 将该字段标记为密钥或敏感项。 |
| `placeholder` | `string` | 表单输入的占位文本。 |
## `contracts` 参考
仅当 OpenClaw 可以在不导入插件运行时的情况下读取静态能力归属元数据时,
才使用 `contracts`
仅将 `contracts` 用于 OpenClaw 可在不导入插件运行时的情况下读取的静态能力归属元数据。
```json
{
@ -438,43 +384,28 @@ OpenClaw 会报告一条附加诊断,并继续忽略它。省略
| -------------------------------- | ---------- | --------------------------------------------------------------------- |
| `embeddedExtensionFactories` | `string[]` | Codex app-server 扩展工厂 id目前为 `codex-app-server`。 |
| `agentToolResultMiddleware` | `string[]` | 内置插件可为其注册工具结果中间件的运行时 id。 |
| `externalAuthProviders` | `string[]` | 其外部 auth profile 钩子由该插件拥有的 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 的 provider id。 |
| `speechProviders` | `string[]` | 插件拥有的语音 provider id。 |
| `realtimeTranscriptionProviders` | `string[]` | 此插件拥有的实时转录 provider id。 |
| `realtimeVoiceProviders` | `string[]` | 插件拥有的实时语音 provider id。 |
| `memoryEmbeddingProviders` | `string[]` | 此插件拥有的 Memory 嵌入 provider id。 |
| `mediaUnderstandingProviders` | `string[]` | 插件拥有的媒体理解 provider id。 |
| `imageGenerationProviders` | `string[]` | 插件拥有的图像生成 provider id。 |
| `videoGenerationProviders` | `string[]` | 插件拥有的视频生成 provider id。 |
| `webFetchProviders` | `string[]` | 此插件拥有的 web-fetch provider id。 |
| `webSearchProviders` | `string[]` | 此插件拥有的网络搜索 provider id。 |
| `migrationProviders` | `string[]` | 插件为 `openclaw migrate` 拥有的导入 provider id。 |
| `tools` | `string[]` | 插件为内置契约检查拥有的智能体工具名称。 |
`contracts.embeddedExtensionFactories` 被保留用于内置的、仅适用于 Codex
app-server 的扩展工厂。内置工具结果转换应
声明 `contracts.agentToolResultMiddleware`,并使用
`api.registerAgentToolResultMiddleware(...)` 进行注册。外部插件不能
注册工具结果中间件,因为该接口可以在模型看到高信任度工具输出之前
改写它。
`contracts.embeddedExtensionFactories` 为内置的、仅限 Codex app-server 的扩展工厂保留。内置工具结果转换应声明 `contracts.agentToolResultMiddleware`,并使用 `api.registerAgentToolResultMiddleware(...)` 注册。外部插件不能注册工具结果中间件,因为该接口可以在模型看到高信任工具输出之前重写它。
实现了 `resolveExternalAuthProfiles` 的 provider 插件
应声明 `contracts.externalAuthProviders`。未声明该项的插件仍会通过
已弃用的兼容性回退运行,但该回退更慢,
并将在迁移窗口结束后移除。
实现了 `resolveExternalAuthProfiles` 的 provider 插件应声明 `contracts.externalAuthProviders`。未声明的插件仍会通过已弃用的兼容性回退运行,但该回退更慢,并将在迁移窗口结束后移除。
内置 memory embedding provider 应为其暴露的每个适配器 id 声明
`contracts.memoryEmbeddingProviders`
包括诸如 `local` 之类的内置适配器。独立 CLI 路径使用这个清单
契约,在完整 Gateway 网关运行时尚未
注册 provider 之前,仅加载拥有该能力的插件。
内置 Memory 嵌入 provider 应为其公开的每个适配器 id 声明 `contracts.memoryEmbeddingProviders`,包括诸如 `local` 这样的内置适配器。独立 CLI 路径使用此清单契约,只在完整 Gateway 网关运行时注册 provider 之前加载归属插件。
## `mediaUnderstandingProviderMetadata` 参考
当某个媒体理解 provider 具有默认模型、自动认证回退优先级
或原生文档支持,并且通用核心辅助工具需要在运行时加载前获取这些信息时,
请使用 `mediaUnderstandingProviderMetadata`。其键也必须在
`contracts.mediaUnderstandingProviders` 中声明。
当媒体理解 provider 具有默认模型、自动凭证回退优先级或原生文档支持,并且通用核心辅助工具在运行时加载前需要这些信息时,请使用 `mediaUnderstandingProviderMetadata`。这些键也必须在 `contracts.mediaUnderstandingProviders` 中声明。
```json
{
@ -501,39 +432,25 @@ app-server 的扩展工厂。内置工具结果转换应
| 字段 | 类型 | 含义 |
| ---------------------- | ----------------------------------- | ---------------------------------------------------------------------------- |
| `capabilities` | `("image" \| "audio" \| "video")[]` | 该 provider 暴露的媒体能力。 |
| `defaultModels` | `Record<string, string>` | 当配置未指定模型时,按能力映射到模型的默认值。 |
| `autoPriority` | `Record<string, number>` | 用于基于凭证自动回退 provider 时,数字越小排序越靠前。 |
| `nativeDocumentInputs` | `"pdf"[]` | provider 支持的原生文档输入。 |
| `capabilities` | `("image" \| "audio" \| "video")[]` | 此 provider 公开的媒体能力。 |
| `defaultModels` | `Record<string, string>` | 当配置未指定模型时使用的能力到模型默认值映射。 |
| `autoPriority` | `Record<string, number>` | 用于自动基于凭证的 provider 回退时,数值越小排序越靠前。 |
| `nativeDocumentInputs` | `"pdf"[]` | provider 支持的原生文档输入。 |
## `channelConfigs` 参考
当某个渠道插件需要在运行时加载前获取低成本配置元数据时,
请使用 `channelConfigs`。只读的渠道设置 / Status 发现可以
在没有 setup 入口时直接使用这些元数据来处理已配置的外部渠道,
或者在 `setup.requiresRuntime: false` 声明设置运行时不必要时使用它们。
当渠道插件在运行时加载前需要轻量级配置元数据时,请使用 `channelConfigs`。在没有设置条目,或 `setup.requiresRuntime: false` 声明无需设置运行时时,只读的渠道设置 / Status 发现可直接对已配置的外部渠道使用这些元数据。
`channelConfigs` 是插件清单元数据,而不是新的顶层用户配置
区段。用户仍然在 `channels.<channel-id>` 下配置渠道实例。
OpenClaw 会读取清单元数据,以决定哪个插件拥有该已配置的
渠道,然后才执行插件运行时代码。
`channelConfigs` 是插件清单元数据,不是新的顶层用户配置部分。用户仍然在 `channels.<channel-id>` 下配置渠道实例。OpenClaw 会读取清单元数据,以便在插件运行时代码执行前判断哪个插件拥有该已配置渠道。
对于渠道插件,`configSchema` 和 `channelConfigs` 描述的是不同
路径:
对于渠道插件,`configSchema` 和 `channelConfigs` 描述的是不同路径:
- `configSchema` 用于验证 `plugins.entries.<plugin-id>.config`
- `channelConfigs.<channel-id>.schema` 用于验证 `channels.<channel-id>`
- `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` 发布相同默认值,并与其他由 package 拥有的
渠道目录元数据一起提供。
`channelConfigs.<channel-id>.commands.nativeCommandsAutoEnabled``nativeSkillsAutoEnabled` 可以为在渠道运行时加载前执行的命令配置检查声明静态 `auto` 默认值。内置渠道还可以通过 `package.json#openclaw.channel.commands` 发布相同的默认值,并与其余由包拥有的渠道 catalog 元数据一同提供。
```json
{
@ -569,18 +486,15 @@ OpenClaw 会读取清单元数据,以决定哪个插件拥有该已配置的
| 字段 | 类型 | 含义 |
| ------------- | ------------------------ | ----------------------------------------------------------------------------------------- |
| `schema` | `object` | `channels.<id>` 的 JSON Schema。每个已声明的渠道配置条目都必须提供。 |
| `uiHints` | `Record<string, object>` | 该渠道配置区段的可选 UI 标签 / 占位符 / 敏感性提示。 |
| `uiHints` | `Record<string, object>` | 该渠道配置部分的可选 UI 标签 / 占位符 / 敏感性提示。 |
| `label` | `string` | 当运行时元数据尚未就绪时,合并到选择器和检查界面中的渠道标签。 |
| `description` | `string` | 用于检查和目录界面的简短渠道描述。 |
| `description` | `string` | 用于检查和 catalog 界面的简短渠道描述。 |
| `commands` | `object` | 用于运行时前配置检查的静态原生命令和原生 Skills 自动默认值。 |
| `preferOver` | `string[]` | 在选择界面中,此渠道应优先于其之上的旧版或低优先级插件 id。 |
| `preferOver` | `string[]` | 在选择界面中,此渠道应优先于的旧版或低优先级插件 id。 |
### 替换另一个渠道插件
当你的插件是某个渠道 id 的首选拥有者,而另一个插件
也可以提供该渠道时,请使用 `preferOver`。常见情况包括:插件 id 已重命名、
独立插件取代了内置插件,或者维护中的分支为了配置兼容性
保留了相同的渠道 id。
当你的插件是某个渠道 id 的首选拥有者,而另一个插件也能提供该渠道时,请使用 `preferOver`。常见情况包括:插件 id 已重命名、独立插件取代了内置插件,或维护中的分支为了配置兼容性保留了相同的渠道 id。
```json
{
@ -601,22 +515,13 @@ OpenClaw 会读取清单元数据,以决定哪个插件拥有该已配置的
}
```
当配置了 `channels.chat`OpenClaw 会同时考虑渠道 id 和
首选插件 id。如果低优先级插件之所以被选中
只是因为它是内置的或默认启用的,
OpenClaw 会在生效运行时配置中禁用它,以便由一个插件统一拥有该渠道
及其工具。显式的用户选择仍然优先:如果用户明确启用了两个插件,
OpenClaw 会保留该选择,并报告重复渠道 / 工具诊断,
而不是静默更改用户请求的插件集合。
当配置了 `channels.chat`OpenClaw 会同时考虑渠道 id 和首选插件 id。如果较低优先级插件之所以被选中只是因为它是内置的或默认启用的OpenClaw 会在生效运行时配置中将其禁用从而由一个插件拥有该渠道及其工具。显式的用户选择仍然优先如果用户显式启用了两个插件OpenClaw 会保留该选择,并报告重复渠道 / 工具诊断,而不是静默更改请求的插件集合。
请将 `preferOver` 限定在那些确实能提供相同渠道的插件 id 上。
它不是一个通用优先级字段,也不会重命名用户配置键。
请将 `preferOver` 的范围限制在确实能提供同一渠道的插件 id 上。它不是通用优先级字段,也不会重命名用户配置键。
## `modelSupport` 参考
当 OpenClaw 应在插件运行时加载前,根据简写模型 id
`gpt-5.5``claude-sonnet-4.6` 推断你的 provider 插件时,
请使用 `modelSupport`
当 OpenClaw 应在插件运行时加载前,根据简写模型 id`gpt-5.5``claude-sonnet-4.6`)推断你的 provider 插件时,请使用 `modelSupport`
```json
{
@ -629,26 +534,21 @@ OpenClaw 会保留该选择,并报告重复渠道 / 工具诊断,
OpenClaw 按以下优先级应用:
- 显式`provider/model` 引用使用拥有该项的 `providers` 清单元数据
- 显式 `provider/model` 引用使用其所属 `providers` 清单元数据
- `modelPatterns` 优先于 `modelPrefixes`
- 如果一个非内置插件和一个内置插件都匹配,则非内置
插件优先
- 如果一个非内置插件和一个内置插件都匹配,则非内置插件胜出
- 其余歧义会被忽略,直到用户或配置指定某个 provider
字段:
| 字段 | 类型 | 含义 |
| --------------- | ---------- | ------------------------------------------------------------------------------- |
| `modelPrefixes` | `string[]` | 通过 `startsWith` 与简写模型 id 匹配的前缀。 |
| `modelPatterns` | `string[]` | 在移除 profile 后缀后,与简写模型 id 匹配的正则表达式源码。 |
| `modelPrefixes` | `string[]` | 使用 `startsWith` 对简写模型 id 进行匹配的前缀。 |
| `modelPatterns` | `string[]` | 在移除配置文件后缀后,与简写模型 id 匹配的正则表达式源码。 |
## `modelCatalog` 参考
当 OpenClaw 应在加载插件运行时之前了解 provider 模型元数据时,
请使用 `modelCatalog`。这是由清单拥有的固定目录
条目、provider 别名、抑制规则和发现模式的数据源。
运行时刷新仍属于 provider 运行时代码负责,但清单会告知核心
何时需要运行时。
当 OpenClaw 应在加载插件运行时之前了解 provider 模型元数据时,请使用 `modelCatalog`。这是固定 catalog 行、provider 别名、抑制规则和发现模式的清单自有来源。运行时刷新仍归属于 provider 运行时代码,但清单会告诉核心何时需要运行时。
```json
{
@ -701,19 +601,19 @@ OpenClaw 按以下优先级应用:
| 字段 | 类型 | 含义 |
| -------------- | -------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| `providers` | `Record<string, object>` | 由此插件拥有的 provider id 的目录条目。键也应出现在顶层 `providers` 中。 |
| `aliases` | `Record<string, object>` | 在目录或抑制规划中应解析到某个已拥有 provider 的 provider 别名。 |
| `suppressions` | `object[]` | 因特定 provider 原因而被此插件抑制的、来自其他来源的模型条目。 |
| `discovery` | `Record<string, "static" \| "refreshable" \| "runtime">` | 该 provider 目录是可从清单元数据读取、可刷新到缓存,还是需要运行时。 |
| `providers` | `Record<string, object>` | 由此插件拥有的 provider id 的 catalog 行。键也应出现在顶层 `providers` 中。 |
| `aliases` | `Record<string, object>` | 在 catalog 或抑制规划中应解析到某个所属 provider 的 provider 别名。 |
| `suppressions` | `object[]` | 出于 provider 特定原因,由此插件抑制的来自其他来源的模型行。 |
| `discovery` | `Record<string, "static" \| "refreshable" \| "runtime">` | provider catalog 是否可从清单元数据读取、可刷新到缓存,或需要运行时。 |
provider 字段:
| 字段 | 类型 | 含义 |
| --------- | ------------------------ | ----------------------------------------------------------------- |
| `baseUrl` | `string` | 此 provider 目录中模型的可选默认 base URL。 |
| `api` | `ModelApi` | 此 provider 目录中模型的可选默认 API 适配器。 |
| `headers` | `Record<string, string>` | 适用于此 provider 目录的可选静态请求头。 |
| `models` | `object[]` | 必填模型条目。没有 `id` 的条目会被忽略。 |
| `baseUrl` | `string` | 此 provider catalog 中模型的可选默认 `baseUrl`。 |
| `api` | `ModelApi` | 此 provider catalog 中模型的可选默认 API 适配器。 |
| `headers` | `Record<string, string>` | 适用于此 provider catalog 的可选静态请求头。 |
| `models` | `object[]` | 必填模型行。没有 `id` 的行会被忽略。 |
模型字段:
@ -721,143 +621,130 @@ provider 字段:
| --------------- | -------------------------------------------------------------- | --------------------------------------------------------------------------- |
| `id` | `string` | provider 本地模型 id不含 `provider/` 前缀。 |
| `name` | `string` | 可选显示名称。 |
| `api` | `ModelApi` | 可选的逐模型 API 覆盖值。 |
| `baseUrl` | `string` | 可选的逐模型 base URL 覆盖值。 |
| `headers` | `Record<string, string>` | 可选的模型静态请求头。 |
| `api` | `ModelApi` | 可选的按模型覆盖的 API。 |
| `baseUrl` | `string` | 可选的按模型覆盖的 `baseUrl`。 |
| `headers` | `Record<string, string>` | 可选的模型静态请求头。 |
| `input` | `Array<"text" \| "image" \| "document" \| "audio" \| "video">` | 该模型接受的模态。 |
| `reasoning` | `boolean` | 该模型是否暴露推理行为。 |
| `contextWindow` | `number` | provider 原生上下文窗口。 |
| `contextTokens` | `number` | 当与 `contextWindow` 不同时,可选的实际运行时上下文上限。 |
| `reasoning` | `boolean` | 该模型是否公开 reasoning 行为。 |
| `contextWindow` | `number` | 原生 provider 上下文窗口。 |
| `contextTokens` | `number` | 当与 `contextWindow` 不同时,可选的有效运行时上下文上限。 |
| `maxTokens` | `number` | 已知时的最大输出 token 数。 |
| `cost` | `object` | 可选的每百万 token 美元定价,包括可选的 `tieredPricing`。 |
| `compat` | `object` | 与 OpenClaw 模型配置兼容性匹配的可选兼容性标志。 |
| `status` | `"available"` \| `"preview"` \| `"deprecated"` \| `"disabled"` | 列表状态。仅当某条目绝不能出现时才使用 suppress。 |
| `statusReason` | `string` | 在非可用状态下显示的可选原因。 |
| `replaces` | `string[]` | 模型取代的旧 provider 本地模型 id。 |
| `replacedBy` | `string` | 已弃用条目的替代 provider 本地模型 id。 |
| `status` | `"available"` \| `"preview"` \| `"deprecated"` \| `"disabled"` | 列表状态。仅当该行完全不应出现时才使用 suppress。 |
| `statusReason` | `string` | 随非可用状态显示的可选原因。 |
| `replaces` | `string[]` | 模型取代的旧 provider 本地模型 id。 |
| `replacedBy` | `string` | 已弃用的替代 provider 本地模型 id。 |
| `tags` | `string[]` | 供选择器和过滤器使用的稳定标签。 |
不要将仅运行时数据放入 `modelCatalog`。如果某个 provider 需要账户
状态、API 请求或本地进程发现才能得知完整模型集合,
请在 `discovery` 中将该 provider 声明为 `refreshable``runtime`
不要把仅运行时数据放入 `modelCatalog`。如果某个 provider 需要账户状态、API 请求或本地进程发现才能知道完整模型集,请在 `discovery` 中将该 provider 声明为 `refreshable``runtime`
## `modelPricing` 参考
当 provider 在运行时加载前需要 control-plane 定价行为时,请使用 `modelPricing`。Gateway 网关定价缓存会读取这些元数据,而无需导入 provider 运行时代码。
```json
{
"providers": ["ollama", "openrouter"],
"modelPricing": {
"providers": {
"ollama": {
"external": false
},
"openrouter": {
"openRouter": {
"passthroughProviderModel": true
},
"liteLLM": false
}
}
}
}
```
provider 字段:
| 字段 | 类型 | 含义 |
| ------------ | ----------------- | -------------------------------------------------------------------------------------------------- |
| `external` | `boolean` | 对于绝不应获取 OpenRouter 或 LiteLLM 定价的本地 / 自托管 provider将其设为 `false`。 |
| `openRouter` | `false \| object` | OpenRouter 定价查询映射。`false` 会禁用该 provider 的 OpenRouter 查询。 |
| `liteLLM` | `false \| object` | LiteLLM 定价查询映射。`false` 会禁用该 provider 的 LiteLLM 查询。 |
来源字段:
| 字段 | 类型 | 含义 |
| -------------------------- | ------------------ | -------------------------------------------------------------------------------------------------------------------- |
| `provider` | `string` | 当外部 catalog provider id 与 OpenClaw provider id 不同时使用的外部 catalog provider id例如 `zai` provider 对应的 `z-ai`。 |
| `passthroughProviderModel` | `boolean` | 将包含斜杠的模型 id 视为嵌套的 provider/model 引用,这对 OpenRouter 之类的代理 provider 很有用。 |
| `modelIdTransforms` | `"version-dots"[]` | 额外的外部 catalog 模型 id 变体。`version-dots` 会尝试带点的版本 id例如 `claude-opus-4.6`。 |
### OpenClaw Provider Index
OpenClaw Provider Index 是由 OpenClaw 拥有的预览元数据,适用于那些
插件可能尚未安装的 provider。它不是插件清单的一部分。
插件清单仍然是已安装插件的权威来源。Provider Index 是内部回退契约,
未来可安装 provider 和安装前模型选择器界面将在未安装 provider 插件时
使用它。
OpenClaw Provider Index 是由 OpenClaw 拥有的预览元数据,用于那些插件可能尚未安装的 provider。它不是插件清单的一部分。插件清单仍然是已安装插件的权威来源。Provider Index 是内部回退契约,未来可安装 provider 和安装前模型选择器界面会在 provider 插件尚未安装时使用它。
目录权威顺序:
catalog 权威顺序:
1. 用户配置。
2. 已安装插件清单中的 `modelCatalog`
3. 通过显式刷新得到的模型目录缓存。
4. OpenClaw Provider Index 预览条目。
2. 已安装插件清单 `modelCatalog`
3. 来自显式刷新的模型 catalog 缓存。
4. OpenClaw Provider Index 预览
Provider Index 不得包含密钥、启用状态、运行时钩子
或与实际账户相关的在线模型数据。它的预览目录使用与插件清单
相同的 `modelCatalog` provider 条目结构,但应仅限于稳定显示元数据,
除非有意让 `api`
`baseUrl`、定价或兼容性标志等运行时适配器字段与已安装插件清单保持一致。
对于具有在线 `/models` 发现能力的 provider应通过显式模型目录缓存路径
写入刷新后的条目,而不是在常规列表或新手引导期间调用 provider API。
Provider Index 不得包含密钥、启用状态、运行时 hooks 或实时的账户专属模型数据。它的预览 catalog 使用与插件清单相同的 `modelCatalog` provider 行结构,但除非诸如 `api`、`baseUrl`、定价或兼容性标志等运行时适配器字段有意与已安装插件清单保持一致,否则应限制为稳定的显示元数据。具有实时 `/models` 发现能力的 provider 应通过显式模型 catalog 缓存路径写入刷新后的行,而不是在普通列表或 onboarding 过程中调用 provider API。
Provider Index 条目还可以携带适用于那些插件已移出核心
或尚未安装的 provider 的可安装插件元数据。此元数据遵循渠道目录模式:
package 名称、npm 安装规格、预期完整性以及轻量级认证选项标签
足以展示一个可安装的设置选项。一旦插件安装完成,
其清单将优先生效,而该 provider 的 Provider Index 条目会被忽略。
Provider Index 条目还可以携带适用于那些插件已移出核心或尚未安装的 provider 的可安装插件元数据。这些元数据遵循渠道 catalog 模式包名、npm 安装 spec、预期完整性以及轻量级凭证选项标签已足以显示一个可安装的设置选项。一旦插件安装完成其清单即成为权威该 provider 的 Provider Index 条目将被忽略。
旧版顶层能力键已弃用。使用 `openclaw doctor --fix`
`speechProviders`、`realtimeTranscriptionProviders`、
`realtimeVoiceProviders`、`mediaUnderstandingProviders`、
`imageGenerationProviders`、`videoGenerationProviders`、
`webFetchProviders``webSearchProviders`
移动到 `contracts` 下;常规
清单加载不再将这些顶层字段视为能力
归属。
旧版顶层能力键已弃用。请使用 `openclaw doctor --fix``speechProviders`、`realtimeTranscriptionProviders`、`realtimeVoiceProviders`、`mediaUnderstandingProviders`、`imageGenerationProviders`、`videoGenerationProviders`、`webFetchProviders` 和 `webSearchProviders` 移动到 `contracts` 下;常规清单加载不再将这些顶层字段视为能力归属。
## 清单与 package.json 的区别
## 清单与 `package.json`
这两个文件承担不同职责:
| 文件 | 用途 |
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `openclaw.plugin.json` | 在插件代码运行前必须存在的设备发现、配置验证、证选项元数据和 UI 提示 |
| `package.json` | npm 元数据、依赖安装,以及用于入口点、安装门控、设置或目录元数据的 `openclaw`块 |
| `openclaw.plugin.json` | 在插件代码运行前必须存在的设备发现、配置验证、证选项元数据和 UI 提示 |
| `package.json` | npm 元数据、依赖安装,以及用于入口点、安装门控、设置或 catalog 元数据的 `openclaw` 块 |
如果你不确定某项元数据应放在哪里,请使用以下规则:
如果你不确定某项元数据应放在哪里,请使用以下规则:
- 如果 OpenClaw 必须在加载插件代码之前知道它,就将其放在 `openclaw.plugin.json`
- 如果它与打包、入口文件或 npm 安装行为有关,就将其放在 `package.json`
- 如果 OpenClaw 必须在加载插件代码之前知道它,就放到 `openclaw.plugin.json`
- 如果它与打包、入口文件或 npm 安装行为有关,就放到 `package.json`
### 影响设备发现的 package.json 字段
### 影响设备发现的 `package.json` 字段
一些运行时前插件元数据会有意放在 `package.json`
`openclaw` 区块下,而不是 `openclaw.plugin.json` 中。
某些运行时前插件元数据有意放在 `package.json``openclaw` 块下,而不是 `openclaw.plugin.json` 中。
重要示例:
| 字段 | 含义 |
| ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `openclaw.extensions` | 声明原生插件入口点。必须保留在插件 package 目录内。 |
| `openclaw.runtimeExtensions` | 为已安装 package 声明已构建的 JavaScript 运行时入口点。必须保留在插件 package 目录内。 |
| `openclaw.setupEntry` | 在新手引导、延迟渠道启动和只读渠道 Status / SecretRef 设备发现期间使用的轻量级仅设置入口点。必须保留在插件 package 目录内。 |
| `openclaw.runtimeSetupEntry` | 为已安装 package 声明已构建的 JavaScript 设置入口点。必须保留在插件 package 目录内。 |
| `openclaw.channel` | 轻量级渠道目录元数据,例如标签、文档路径、别名和选择说明文本。 |
| `openclaw.channel.commands` | 在渠道运行时加载前,由配置、审计和命令列表界面使用的静态原生命令和原生 Skills 自动默认元数据。 |
| `openclaw.channel.configuredState` | 轻量级 configured-state 检查器元数据,可在不加载完整渠道运行时的情况下回答“是否已存在仅环境变量设置?”。 |
| `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.extensions` | 声明原生插件入口点。必须保留在插件目录内。 |
| `openclaw.runtimeExtensions` | 为已安装包声明已构建的 JavaScript 运行时入口点。必须保留在插件包目录内。 |
| `openclaw.setupEntry` | 在 onboarding、延迟渠道启动以及只读渠道 Status / SecretRef 发现期间使用的轻量级仅设置入口点。必须保留在插件包目录内。 |
| `openclaw.runtimeSetupEntry` | 声明已安装包的已构建 JavaScript 设置入口点。必须保留在插件包目录内。 |
| `openclaw.channel` | 轻量级渠道 catalog 元数据,例如标签、文档路径、别名和选择文案。 |
| `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` | 允许在启动期间,完整渠道插件之前先加载仅设置的渠道界面。 |
清单元数据决定了在运行时加载前,
哪些 provider / channel / setup 选项会出现在新手引导中。`package.json#openclaw.install` 则告诉
新手引导,当用户选择其中某个选项时,
应如何获取或启用该插件。不要将安装提示移到 `openclaw.plugin.json` 中。
清单元数据决定了在运行时加载前,哪些 provider / 渠道 / 设置选项会出现在 onboarding 中。`package.json#openclaw.install` 则告诉 onboarding当用户选择这些选项之一时如何获取或启用该插件。不要将安装提示移到 `openclaw.plugin.json` 中。
`openclaw.install.minHostVersion` 会在安装和清单
注册表加载期间强制执行。无效值会被拒绝;较新但有效的值会在旧宿主上跳过该
插件。
`openclaw.install.minHostVersion` 会在安装期间和清单注册表加载期间强制执行。无效值会被拒绝;在较旧主机上,较新但有效的值会跳过该插件。
精确的 npm 版本固定已经存在于 `npmSpec` 中,例如
`"npmSpec": "@wecom/wecom-openclaw-plugin@1.2.3"`。官方外部目录
条目应将精确 spec 与 `expectedIntegrity` 配对,这样如果获取到的 npm 制品
不再匹配固定版本,更新流程就会失败即关闭。
出于兼容性考虑,交互式新手引导仍会提供受信任注册表的 npm spec
包括裸 package 名称和 dist-tag。目录诊断可以
区分精确、浮动、带完整性固定、缺少完整性、package 名称不匹配
以及无效默认选项来源。它们还会在
存在 `expectedIntegrity` 但没有可用于固定它的有效 npm 来源时发出警告。
当存在 `expectedIntegrity` 时,
安装 / 更新流程会强制校验它;省略时,注册表解析结果
会被记录下来,但不带完整性固定。
精确的 npm 版本固定已存在于 `npmSpec` 中,例如 `"npmSpec": "@wecom/wecom-openclaw-plugin@1.2.3"`。官方外部 catalog 条目应将精确 spec 与 `expectedIntegrity` 搭配使用,以便当获取的 npm 工件不再匹配固定版本时,更新流程以封闭失败方式终止。出于兼容性考虑,交互式 onboarding 仍会提供受信任注册表的 npm spec包括裸包名和 dist-tag。catalog 诊断可以区分精确、浮动、完整性固定、缺少完整性、包名不匹配以及无效默认选项来源。它们还会在存在 `expectedIntegrity` 但没有可供固定的有效 npm 来源时发出警告。当存在 `expectedIntegrity` 时,安装 / 更新流程会强制执行它;省略时,将记录注册表解析结果,但不会附带完整性固定。
当 Status、渠道列表
或 SecretRef 扫描需要在不加载完整运行时的情况下识别已配置账户时,渠道插件应提供 `openclaw.setupEntry`
该设置入口点应暴露渠道元数据以及适用于设置场景的配置、
Status 和密钥适配器请将网络客户端、Gateway 网关监听器
和传输运行时保留在主扩展入口点中。
当 Status、渠道列表或 SecretRef 扫描需要在不加载完整运行时的情况下识别已配置账户时,渠道插件应提供 `openclaw.setupEntry`。该设置入口应公开渠道元数据以及适用于设置场景的配置、状态和密钥适配器请将网络客户端、gateway 监听器和传输运行时保留在主扩展入口点中。
运行时入口点字段不会覆盖针对源代码
入口点字段的 package 边界检查。例如,`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` 是一个微型检查器
模块的 package 元数据:
`openclaw.channel.persistedAuthState` 是用于一个极小检查器模块的包元数据:
```json
{
@ -873,13 +760,9 @@ Status 和密钥适配器请将网络客户端、Gateway 网关监听器
}
```
当设置、Doctor 或 configured-state 流程需要在完整渠道插件加载前进行一个
低成本的是否已认证探测时,请使用它。目标导出应是一个仅
读取持久化状态的小函数;不要通过完整的
渠道运行时 barrel 转发它。
当设置、Doctor 或已配置状态流程需要在完整渠道插件加载前进行一个廉价的“是 / 否”凭证探测时,请使用它。目标导出应是一个只读取持久化状态的小函数;不要通过完整渠道运行时 barrel 暴露它。
`openclaw.channel.configuredState` 采用相同结构,用于低成本的仅环境变量
configured 检查:
`openclaw.channel.configuredState` 对于廉价的仅环境变量已配置检查采用相同结构:
```json
{
@ -895,57 +778,51 @@ configured 检查:
}
```
当某个渠道可以通过环境变量或其他微型
非运行时输入来回答 configured-state 时,请使用它。如果检查需要完整配置解析或真实
渠道运行时,请将该逻辑保留在插件 `config.hasConfiguredState`
钩子中。
当渠道可以仅凭环境变量或其他极小的非运行时输入回答已配置状态时,请使用它。如果检查需要完整配置解析或真实渠道运行时,请将该逻辑保留在插件 `config.hasConfiguredState` hook 中。
## 设备发现优先级(重复插件 id
OpenClaw 会从多个根目录发现插件(内置、全局安装、工作区、显式配置选择的路径)。如果两个发现结果共享相同的 `id`,则只保留**优先级最高**的清单;优先级较低的重复项会被丢弃,而不是与其一起加载。
OpenClaw 会从多个根位置发现插件(内置、全局安装、工作区、显式配置选择的路径)。如果两个发现结果共享同一个 `id`,则只保留**优先级最高**的清单;较低优先级的重复项会被丢弃,而不是与其一起加载。
优先级从高到低:
1. **由配置选择** —— 在 `plugins.entries.<id>` 中显式固定的路径
2. **内置** —— 随 OpenClaw 一起提供的插件
1. **配置选定** —— 在 `plugins.entries.<id>` 中显式固定的路径
2. **内置** —— 随 OpenClaw 一起发布的插件
3. **全局安装** —— 安装到全局 OpenClaw 插件根目录中的插件
4. **工作区** —— 相对于当前工作区发现的插件
影响:
- 位于工作区中的某个内置插件分支或过期副本不会遮蔽内置构建。
- 如果你确实要用本地插件覆盖内置插件,请通过 `plugins.entries.<id>` 固定它,让它凭优先级获胜,而不是依赖工作区发现。
- 被丢弃的重复项会记录到日志中,以便 Doctor 和启动诊断指出被舍弃的副本。
- 放在工作区中的某个内置插件分支或旧副本,不会覆盖内置构建。
- 若要真正用本地插件覆盖内置插件,请通过 `plugins.entries.<id>` 固定它,使其凭借优先级获胜,而不是依赖工作区发现。
- 被丢弃的重复项会被记录日志,这样 Doctor 和启动诊断就可以指向被舍弃的副本。
## JSON Schema 要求
- **每个插件都必须提供一个 JSON Schema**,即使它不接受任何配置。
- 可以接受空 schema例如 `{ "type": "object", "additionalProperties": false }`)。
- Schema 会在配置读写时验证,而不是在运行时验证。
- schema 会在配置读写时验证,而不是在运行时验证。
## 验证行为
- 未知的 `channels.*` 键是**错误**,除非该渠道 id 已由
某个插件清单声明。
- 未知的 `channels.*` 键是**错误**,除非该渠道 id 由某个插件清单声明。
- `plugins.entries.<id>`、`plugins.allow`、`plugins.deny` 和 `plugins.slots.*`
必须引用**可发现的**插件 id。未知 id 是**错误**。
- 如果某个插件已安装,但其清单或 schema 损坏或缺失,
验证会失败Doctor 会报告该插件错误。
- 如果插件配置存在,但插件已**禁用**,则配置会被保留,并且
Doctor + 日志中会显示一条**警告**。
必须引用**可发现的**插件 id。未知 id 属于**错误**。
- 如果某个插件已安装,但其清单或 schema 损坏或缺失验证会失败Doctor 会报告该插件错误。
- 如果插件配置存在,但插件被**禁用**,配置会被保留,并且 Doctor + 日志中会显示一条**警告**。
有关完整 `plugins.*` schema请参见 [配置参考](/zh-CN/gateway/configuration)。
完整的 `plugins.*` schema 请参阅[配置参考](/zh-CN/gateway/configuration)。
## 注意事项
## 说明
- 对于原生 OpenClaw 插件,清单是**必需的**,包括从本地文件系统加载的插件。运行时仍会单独加载插件模块;清单仅用于设备发现 + 验证。
- 原生清单使用 JSON5 解析,因此支持注释、尾随逗号和未加引号的键,只要最终值仍然是一个对象即可。
- 清单加载器只会读取已文档化的清单字段。避免使用自定义顶层键。
- 当插件不需要它们时,可以省略 `channels`、`providers`、`cliBackends` 和 `skills`
- `providerDiscoveryEntry` 必须保持轻量,不应导入宽泛的运行时代码;应将其用于静态 provider 目录元数据或窄范围发现描述符,而不是请求时执行。
- 互斥插件种类通过 `plugins.slots.*` 选择:`kind: "memory"` 通过 `plugins.slots.memory` 选择`kind: "context-engine"` 通过 `plugins.slots.contextEngine` 选择(默认值为 `legacy`)。
- 环境变量元数据(`setup.providers[].envVars`、已弃用的 `providerAuthEnvVars` 以及 `channelEnvVars`)仅是声明式信息。Status、审计、cron 投递验证和其他只读界面在将某个环境变量视为已配置之前,仍会应用插件信任和效激活策略。
- 关于需要 provider 代码的运行时向导元数据,请参见 [Provider 运行时钩子](/zh-CN/plugins/architecture-internals#provider-runtime-hooks)。
- 清单对**原生 OpenClaw 插件**是**必需的**,包括本地文件系统加载。运行时仍会单独加载插件模块;清单仅用于设备发现 + 验证。
- 原生清单使用 JSON5 解析,因此接受注释、尾随逗号和未加引号的键,只要最终值仍然是一个对象即可。
- 清单加载器只会读取文档中记录的清单字段。请避免使用自定义顶层键。
- 当插件不需要它们时,`channels`、`providers`、`cliBackends` 和 `skills` 都可以省略
- `providerDiscoveryEntry` 必须保持轻量,不应导入大范围运行时代码;请将其用于静态 provider catalog 元数据或狭义发现描述符,而不是请求时执行。
- 排他性插件种类通过 `plugins.slots.*` 选择:`kind: "memory"` 通过 `plugins.slots.memory``kind: "context-engine"` 通过 `plugins.slots.contextEngine`(默认 `legacy`)。
- 环境变量元数据(`setup.providers[].envVars`、已弃用的 `providerAuthEnvVars` `channelEnvVars`)仅具声明性。Status、审计、cron 投递验证和其他只读界面在将环境变量视为已配置之前,仍会应用插件信任和效激活策略。
- 关于需要 provider 代码的运行时向导元数据,请参阅[provider 运行时钩子](/zh-CN/plugins/architecture-internals#provider-runtime-hooks)。
- 如果你的插件依赖原生模块,请记录构建步骤以及任何包管理器允许列表要求(例如 pnpm `allow-build-scripts` + `pnpm rebuild <package>`)。
## 相关内容