chore(i18n): refresh zh-CN translations
This commit is contained in:
parent
a7a1d8bec3
commit
721674af09
@ -1,21 +1,21 @@
|
||||
---
|
||||
read_when:
|
||||
- 安排后台作业或唤醒任务
|
||||
- 调度后台任务或唤醒操作
|
||||
- 将外部触发器(webhook、Gmail)接入 OpenClaw
|
||||
- 为计划任务决定使用心跳还是 cron
|
||||
sidebarTitle: Scheduled tasks
|
||||
summary: Gateway 网关调度器的计划任务、webhook 和 Gmail PubSub 触发器
|
||||
title: 计划任务
|
||||
x-i18n:
|
||||
generated_at: "2026-04-27T08:44:47Z"
|
||||
generated_at: "2026-04-27T20:43:29Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: a8764103e2d6a9b35b3112e3e95c9570d196c03ed86f4fcdcf4536049a05ac6d
|
||||
source_hash: f61e85e3f4f334d611397e2d27e508ee7b20e342ccb52b8995b73555f2e6434b
|
||||
source_path: automation/cron-jobs.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
Cron 是 Gateway 网关的内置调度器。它会持久化作业,在正确的时间唤醒智能体,并可将输出回传到聊天渠道或 webhook 端点。
|
||||
Cron 是 Gateway 网关的内置调度器。它会持久化任务,在正确的时间唤醒智能体,并且可以将输出回传到聊天渠道或 webhook 端点。
|
||||
|
||||
## 快速开始
|
||||
|
||||
@ -23,15 +23,15 @@ Cron 是 Gateway 网关的内置调度器。它会持久化作业,在正确的
|
||||
<Step title="添加一次性提醒">
|
||||
```bash
|
||||
openclaw cron add \
|
||||
--name "提醒" \
|
||||
--name "Reminder" \
|
||||
--at "2026-02-01T16:00:00Z" \
|
||||
--session main \
|
||||
--system-event "提醒:检查 cron 文档草稿" \
|
||||
--system-event "Reminder: check the cron docs draft" \
|
||||
--wake now \
|
||||
--delete-after-run
|
||||
```
|
||||
</Step>
|
||||
<Step title="检查你的作业">
|
||||
<Step title="检查你的任务">
|
||||
```bash
|
||||
openclaw cron list
|
||||
openclaw cron show <job-id>
|
||||
@ -46,130 +46,130 @@ Cron 是 Gateway 网关的内置调度器。它会持久化作业,在正确的
|
||||
|
||||
## cron 的工作方式
|
||||
|
||||
- Cron 运行在 **Gateway 网关** 进程**内部**(不在模型内部)。
|
||||
- 作业定义会持久化到 `~/.openclaw/cron/jobs.json`,因此重启不会丢失计划。
|
||||
- 运行时执行状态会持久化到相邻的 `~/.openclaw/cron/jobs-state.json`。如果你在 git 中跟踪 cron 定义,请跟踪 `jobs.json` 并将 `jobs-state.json` 加入 gitignore。
|
||||
- 拆分后,较旧版本的 OpenClaw 仍可读取 `jobs.json`,但可能会将作业视为全新作业,因为运行时字段现在位于 `jobs-state.json` 中。
|
||||
- 当 Gateway 网关运行中或停止时编辑 `jobs.json`,OpenClaw 会将变更后的计划字段与待处理运行时槽位元数据进行比较,并清除过期的 `nextRunAtMs` 值。纯格式调整或仅键顺序重写会保留待处理槽位。
|
||||
- Cron 运行在 **Gateway 网关进程内部**(而不是在模型内部)。
|
||||
- 任务定义持久保存在 `~/.openclaw/cron/jobs.json`,因此重启不会丢失调度计划。
|
||||
- 运行时执行状态保存在旁边的 `~/.openclaw/cron/jobs-state.json` 中。如果你用 git 跟踪 cron 定义,请跟踪 `jobs.json`,并将 `jobs-state.json` 加入 `gitignore`。
|
||||
- 在拆分之后,旧版 OpenClaw 仍可读取 `jobs.json`,但可能会将任务视为全新任务,因为运行时字段现在位于 `jobs-state.json` 中。
|
||||
- 当 Gateway 网关运行中或停止时编辑了 `jobs.json`,OpenClaw 会将变更后的调度字段与待处理的运行时槽位元数据进行比较,并清除过期的 `nextRunAtMs` 值。仅格式调整或仅键顺序重写会保留待处理槽位。
|
||||
- 所有 cron 执行都会创建[后台任务](/zh-CN/automation/tasks)记录。
|
||||
- 一次性作业(`--at`)默认会在成功后自动删除。
|
||||
- 独立 cron 运行会尽力在运行完成时关闭其 `cron:<jobId>` 会话所跟踪的浏览器标签页 / 进程,这样分离的浏览器自动化就不会留下孤儿进程。
|
||||
- 独立 cron 运行还会防止过期的确认回复。如果第一个结果只是中间状态更新(如 “on it”、“pulling everything together” 及类似提示),并且没有任何后代子智能体运行仍负责最终答案,OpenClaw 会再提示一次以获取实际结果,然后再投递。
|
||||
- 独立 cron 运行会优先使用嵌入式运行中的结构化执行拒绝元数据,然后再回退到已知的最终摘要 / 输出标记,例如 `SYSTEM_RUN_DENIED` 和 `INVALID_REQUEST`,这样被阻止的命令就不会被报告为绿色成功运行。
|
||||
- 独立 cron 运行还会将运行级别的智能体失败视为作业错误,即使没有生成任何回复负载也是如此,因此模型 / 提供商失败会增加错误计数并触发失败通知,而不是将该作业清除为成功。
|
||||
- 一次性任务(`--at`)默认会在成功后自动删除。
|
||||
- 独立 cron 运行会尽力在运行完成后关闭其 `cron:<jobId>` 会话所跟踪的浏览器标签页/进程,这样分离的浏览器自动化就不会留下孤儿进程。
|
||||
- 独立 cron 运行还会防止陈旧的确认回复。如果第一个结果只是临时状态更新(如 `on it`、`pulling everything together` 以及类似提示),并且没有任何后代子智能体运行仍负责最终答案,OpenClaw 会在投递前再次提示一次以获取实际结果。
|
||||
- 独立 cron 运行会优先使用来自嵌入式运行的结构化执行拒绝元数据,然后再回退到已知的最终摘要/输出标记,如 `SYSTEM_RUN_DENIED` 和 `INVALID_REQUEST`,这样被阻止的命令就不会被报告为一次绿色运行。
|
||||
- 独立 cron 运行还会将运行级别的智能体失败视为任务错误,即使没有产生任何回复负载也是如此,因此模型/提供商失败会增加错误计数并触发失败通知,而不是将任务标记为成功。
|
||||
|
||||
<a id="maintenance"></a>
|
||||
|
||||
<Note>
|
||||
cron 的任务对账优先由运行时负责,其次才依赖持久化历史:只要 cron 运行时仍在跟踪该作业为运行中,活动 cron 任务就会保持存活,即使仍存在旧的子会话行记录也是如此。一旦运行时不再拥有该作业,且 5 分钟宽限期到期,维护检查会针对匹配的 `cron:<jobId>:<startedAt>` 运行,检查已持久化的运行日志和作业状态。如果该持久化历史显示为终态结果,任务账本就会据此完成;否则,由 Gateway 网关拥有的维护流程可将任务标记为 `lost`。离线 CLI 审计可以从持久化历史中恢复,但它不会把自己空的进程内活动作业集视作 Gateway 网关拥有的 cron 运行已消失的证据。
|
||||
cron 的任务对账首先由运行时负责,其次才依赖持久历史:只要 cron 运行时仍将某个任务跟踪为正在运行,该活跃 cron 任务就会保持存活,即使仍存在一条旧的子会话记录。一旦运行时不再拥有该任务,并且 5 分钟宽限期到期,维护检查就会检查与对应 `cron:<jobId>:<startedAt>` 运行相匹配的持久运行日志和任务状态。如果该持久历史显示终态结果,任务账本就会据此完成;否则,由 Gateway 网关拥有的维护流程可以将任务标记为 `lost`。离线 CLI 审计可以根据持久历史恢复,但不会将其自身为空的进程内活跃任务集视为 Gateway 网关拥有的 cron 运行已经消失的证据。
|
||||
</Note>
|
||||
|
||||
## 计划类型
|
||||
## 调度类型
|
||||
|
||||
| 类型 | CLI 标志 | 描述 |
|
||||
| ------- | --------- | ------------------------------------------------ |
|
||||
| `at` | `--at` | 一次性时间戳(ISO 8601 或类似 `20m` 的相对时间) |
|
||||
| `every` | `--every` | 固定间隔 |
|
||||
| `cron` | `--cron` | 5 字段或 6 字段的 cron 表达式,可选 `--tz` |
|
||||
| 类型 | CLI 标志 | 说明 |
|
||||
| ------- | -------- | --------------------------------------------------- |
|
||||
| `at` | `--at` | 一次性时间戳(ISO 8601 或类似 `20m` 的相对时间) |
|
||||
| `every` | `--every`| 固定间隔 |
|
||||
| `cron` | `--cron` | 5 字段或 6 字段的 cron 表达式,可选 `--tz` |
|
||||
|
||||
不带时区的时间戳会按 UTC 处理。添加 `--tz America/New_York` 以按本地挂钟时间进行调度。
|
||||
不带时区的时间戳会被视为 UTC。添加 `--tz America/New_York` 可按本地墙上时钟时间调度。
|
||||
|
||||
循环的整点表达式会自动错开最多 5 分钟,以减少负载尖峰。使用 `--exact` 可强制精确定时,或使用 `--stagger 30s` 指定明确的错开窗口。
|
||||
重复的整点表达式会自动错开,最长可达 5 分钟,以减少负载尖峰。使用 `--exact` 可强制精确时间,或使用 `--stagger 30s` 指定显式错开窗口。
|
||||
|
||||
### 每月日期与星期几使用 OR 逻辑
|
||||
### day-of-month 和 day-of-week 使用 OR 逻辑
|
||||
|
||||
Cron 表达式由 [croner](https://github.com/Hexagon/croner) 解析。当“每月第几天”和“星期几”字段都不是通配符时,croner 会在**任一**字段匹配时触发,而不是两个字段都匹配才触发。这是标准的 Vixie cron 行为。
|
||||
Cron 表达式由 [croner](https://github.com/Hexagon/croner) 解析。当 `day-of-month` 和 `day-of-week` 字段都不是通配符时,croner 会在**任一**字段匹配时触发——而不是两个都匹配时。这是标准的 Vixie cron 行为。
|
||||
|
||||
```
|
||||
# 预期:“15 日上午 9 点,但仅当这一天是周一”
|
||||
# 实际:“每月 15 日上午 9 点,以及每个周一上午 9 点”
|
||||
# Intended: "9 AM on the 15th, only if it's a Monday"
|
||||
# Actual: "9 AM on every 15th, AND 9 AM on every Monday"
|
||||
0 9 15 * 1
|
||||
```
|
||||
|
||||
这样每月会触发约 5–6 次,而不是 0–1 次。OpenClaw 在这里使用 Croner 默认的 OR 行为。若要同时要求两个条件,请使用 Croner 的 `+` 星期几修饰符(`0 9 15 * +1`),或在一个字段上设定计划,并在作业的提示词或命令中对另一个条件进行保护判断。
|
||||
这会每月触发约 5–6 次,而不是每月 0–1 次。OpenClaw 在这里使用 Croner 默认的 OR 行为。若要同时要求两个条件,请使用 Croner 的 `+` weekday 修饰符(`0 9 15 * +1`),或者只按一个字段调度,并在你的任务提示或命令中对另一个字段做保护判断。
|
||||
|
||||
## 执行样式
|
||||
|
||||
| 样式 | `--session` 值 | 运行位置 | 最适合 |
|
||||
| -------------- | ------------------ | ------------------------ | ----------------------------- |
|
||||
| 主会话 | `main` | 下一个心跳回合 | 提醒、系统事件 |
|
||||
| 独立 | `isolated` | 专用 `cron:<jobId>` | 报告、后台杂务 |
|
||||
| 当前会话 | `current` | 在创建时绑定 | 感知上下文的循环工作 |
|
||||
| 自定义会话 | `session:custom-id`| 持久化命名会话 | 基于历史逐步构建的工作流 |
|
||||
| 样式 | `--session` 值 | 运行位置 | 最适合 |
|
||||
| -------------- | ------------------- | ------------------------ | ------------------------------ |
|
||||
| 主会话 | `main` | 下一个心跳回合 | 提醒、系统事件 |
|
||||
| 独立 | `isolated` | 专用 `cron:<jobId>` | 报告、后台杂项任务 |
|
||||
| 当前会话 | `current` | 在创建时绑定 | 依赖上下文的重复工作 |
|
||||
| 自定义会话 | `session:custom-id` | 持久化命名会话 | 基于历史逐步构建的工作流 |
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="主会话 vs 独立 vs 自定义">
|
||||
**主会话**作业会排入一个系统事件,并可选择唤醒心跳(`--wake now` 或 `--wake next-heartbeat`)。这些系统事件不会延长目标会话的每日 / 空闲重置新鲜度。**独立**作业会使用一个全新的会话运行一个专用智能体回合。**自定义会话**(`session:xxx`)会在多次运行间保留上下文,可支持例如基于先前摘要构建的每日站会等工作流。
|
||||
<Accordion title="主会话、独立和自定义的区别">
|
||||
**主会话**任务会将一个系统事件加入队列,并可选择唤醒心跳(`--wake now` 或 `--wake next-heartbeat`)。这些系统事件不会延长目标会话的每日/空闲重置新鲜度。**独立**任务会以全新会话运行一次专用的智能体回合。**自定义会话**(`session:xxx`)会在多次运行之间保留上下文,从而支持诸如每日站会这类建立在先前摘要之上的工作流。
|
||||
</Accordion>
|
||||
<Accordion title="独立作业中的“全新会话”是什么意思">
|
||||
对独立作业来说,“全新会话”表示每次运行都使用新的 transcript / session id。OpenClaw 可能会携带安全偏好,例如 thinking / fast / verbose 设置、标签以及用户显式选择的模型 / 认证覆盖,但不会从旧的 cron 行继承环境式会话上下文:渠道 / 群组路由、发送或排队策略、提权、来源,或 ACP 运行时绑定。如果某个循环作业应当有意地建立在同一对话上下文上,请使用 `current` 或 `session:<id>`。
|
||||
<Accordion title="独立任务中的“全新会话”是什么意思">
|
||||
对于独立任务,“全新会话”意味着每次运行都会有一个新的 transcript/session id。OpenClaw 可能会保留安全的偏好设置,例如 thinking/fast/verbose 设置、标签以及用户显式选择的模型/凭证覆盖,但不会继承旧 cron 记录中的环境会话上下文:渠道/群组路由、发送或排队策略、提权、来源或 ACP 运行时绑定。当重复任务应当有意建立在相同会话上下文之上时,请使用 `current` 或 `session:<id>`。
|
||||
</Accordion>
|
||||
<Accordion title="运行时清理">
|
||||
对独立作业来说,运行时拆除现在包括对该 cron 会话进行尽力而为的浏览器清理。清理失败会被忽略,因此实际 cron 结果仍然优先。
|
||||
对于独立任务,运行时拆除现在包括尽力清理该 cron 会话的浏览器。清理失败会被忽略,因此真正的 cron 结果仍然优先。
|
||||
|
||||
独立 cron 运行现在还会通过共享运行时清理路径,释放为该作业创建的任何内置 MCP 运行时实例。这与主会话和自定义会话的 MCP 客户端销毁方式保持一致,因此独立 cron 作业不会在多次运行间泄漏 stdio 子进程或长期存在的 MCP 连接。
|
||||
独立 cron 运行还会通过共享的运行时清理路径,释放为该任务创建的所有内置 MCP 运行时实例。这与主会话和自定义会话的 MCP 客户端销毁方式一致,因此独立 cron 任务不会在多次运行之间泄漏 stdio 子进程或长期存在的 MCP 连接。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="子智能体与 Discord 投递">
|
||||
当独立 cron 运行编排子智能体时,投递也会优先使用最终的后代输出,而不是陈旧的父级中间文本。如果后代仍在运行,OpenClaw 会抑制该部分父级更新,而不是将其对外宣布。
|
||||
<Accordion title="子智能体和 Discord 投递">
|
||||
当独立 cron 运行编排子智能体时,投递也会优先使用最终后代输出,而不是陈旧的父级临时文本。如果后代仍在运行,OpenClaw 会抑制该部分父级更新,而不是播报它。
|
||||
|
||||
对于仅文本的 Discord announce 目标,OpenClaw 只会发送一次规范化的最终 assistant 文本,而不会同时重放流式 / 中间文本负载和最终答案。媒体和结构化 Discord 负载仍会作为独立负载投递,以免附件和组件丢失。
|
||||
对于仅文本的 Discord 通知目标,OpenClaw 会只发送一次规范化的最终 assistant 文本,而不是同时重放流式/中间文本负载和最终答案。媒体和结构化 Discord 负载仍会作为单独负载投递,以避免丢失附件和组件。
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
### 独立作业的负载选项
|
||||
### 独立任务的负载选项
|
||||
|
||||
<ParamField path="--message" type="string" required>
|
||||
提示文本(独立模式必需)。
|
||||
提示文本(独立任务必需)。
|
||||
</ParamField>
|
||||
<ParamField path="--model" type="string">
|
||||
模型覆盖;使用为该作业所选且允许的模型。
|
||||
模型覆盖;使用为该任务选择的允许模型。
|
||||
</ParamField>
|
||||
<ParamField path="--thinking" type="string">
|
||||
Thinking 级别覆盖。
|
||||
thinking 级别覆盖。
|
||||
</ParamField>
|
||||
<ParamField path="--light-context" type="boolean">
|
||||
跳过工作区引导文件注入。
|
||||
</ParamField>
|
||||
<ParamField path="--tools" type="string">
|
||||
限制作业可使用的工具,例如 `--tools exec,read`。
|
||||
限制任务可使用的工具,例如 `--tools exec,read`。
|
||||
</ParamField>
|
||||
|
||||
`--model` 会使用该作业所选且允许的模型。如果请求的模型不被允许,cron 会记录一条警告,并回退到该作业的智能体 / 默认模型选择。已配置的回退链仍然适用,但如果只是普通的模型覆盖且没有显式的按作业回退列表,则不会再将智能体主模型作为隐藏的额外重试目标附加进去。
|
||||
`--model` 会使用为该任务选择的允许模型。如果请求的模型不被允许,cron 会记录一条警告,并回退到该任务的智能体/默认模型选择。已配置的回退链仍然适用,但仅有普通模型覆盖且没有显式的按任务回退列表时,不再把智能体主模型作为隐藏的额外重试目标附加进去。
|
||||
|
||||
独立作业的模型选择优先级如下:
|
||||
独立任务的模型选择优先级如下:
|
||||
|
||||
1. Gmail hook 模型覆盖(当该运行来自 Gmail 且该覆盖被允许时)
|
||||
2. 按作业负载中的 `model`
|
||||
1. Gmail hook 模型覆盖(当运行来自 Gmail 且该覆盖被允许时)
|
||||
2. 按任务负载中的 `model`
|
||||
3. 用户选择并存储的 cron 会话模型覆盖
|
||||
4. 智能体 / 默认模型选择
|
||||
4. 智能体/默认模型选择
|
||||
|
||||
Fast 模式也会跟随已解析的实时选择。如果选中的模型配置包含 `params.fastMode`,独立 cron 默认会使用它。无论方向如何,已存储会话中的 `fastMode` 覆盖仍优先于配置。
|
||||
Fast 模式也会遵循解析后的实时选择。如果选中的模型配置带有 `params.fastMode`,独立 cron 默认会使用它。已存储会话中的 `fastMode` 覆盖在任意方向上都仍然优先生效。
|
||||
|
||||
如果独立运行遇到实时模型切换交接,cron 会使用切换后的提供商 / 模型重试,并在重试前为当前运行持久化该实时选择。如果切换还携带新的认证配置文件,cron 也会为当前运行持久化该认证配置文件覆盖。重试次数是有界的:初次尝试之后再加 2 次切换重试后,cron 会中止,而不是无限循环。
|
||||
如果独立运行遇到实时模型切换交接,cron 会使用切换后的提供商/模型重试,并在重试前为当前运行持久化该实时选择。当该切换还携带新的认证配置文件时,cron 也会为当前运行持久化该认证配置文件覆盖。重试次数是有上限的:在初始尝试加上 2 次切换重试之后,cron 会中止,而不是无限循环。
|
||||
|
||||
## 投递与输出
|
||||
|
||||
| 模式 | 行为 |
|
||||
| ---------- | --------------------------------------------------------------------- |
|
||||
| `announce` | 如果智能体未发送,则回退将最终文本投递到目标 |
|
||||
| `webhook` | 将完成事件负载以 POST 方式发送到 URL |
|
||||
| `none` | 运行器不执行回退投递 |
|
||||
| 模式 | 结果说明 |
|
||||
| ---------- | --------------------------------------------------------------- |
|
||||
| `announce` | 如果智能体未发送,则回退投递最终文本到目标 |
|
||||
| `webhook` | 向某个 URL POST 已完成事件负载 |
|
||||
| `none` | 不进行运行器回退投递 |
|
||||
|
||||
使用 `--announce --channel telegram --to "-1001234567890"` 可投递到渠道。对于 Telegram forum topic,请使用 `-1001234567890:topic:123`。Slack / Discord / Mattermost 目标应使用显式前缀(`channel:<id>`、`user:<id>`)。Matrix 房间 ID 区分大小写;请使用精确的房间 ID,或使用来自 Matrix 的 `room:!room:server` 形式。
|
||||
使用 `--announce --channel telegram --to "-1001234567890"` 可投递到渠道。对于 Telegram 论坛主题,使用 `-1001234567890:topic:123`;直接 RPC/配置调用方也可以将 `delivery.threadId` 作为字符串或数字传入。Slack/Discord/Mattermost 目标应使用显式前缀(`channel:<id>`、`user:<id>`)。Matrix 房间 ID 区分大小写;请使用精确的房间 ID,或使用 Matrix 中的 `room:!room:server` 形式。
|
||||
|
||||
对于独立作业,聊天投递是共享的。如果存在聊天路由,即使作业使用 `--no-deliver`,智能体仍可使用 `message` 工具。如果智能体发送到了已配置 / 当前目标,OpenClaw 会跳过回退 announce。否则,`announce`、`webhook` 和 `none` 只控制在智能体回合结束后,运行器如何处理最终回复。
|
||||
对于独立任务,聊天投递是共享的。如果聊天路由可用,即使任务使用了 `--no-deliver`,智能体仍然可以使用 `message` 工具。如果智能体发送到了已配置/当前目标,OpenClaw 会跳过回退通知。否则,`announce`、`webhook` 和 `none` 仅控制运行器在智能体回合结束后如何处理最终回复。
|
||||
|
||||
当智能体从活跃聊天中创建独立提醒时,OpenClaw 会为回退 announce 路由存储保留的实时投递目标。内部会话键可能是小写;当当前聊天上下文可用时,不会依据这些键重建提供商投递目标。
|
||||
当智能体从活跃聊天中创建独立提醒时,OpenClaw 会为回退通知路由保存保留的实时投递目标。内部会话键可能为小写;当当前聊天上下文可用时,不会根据这些键重建提供商投递目标。
|
||||
|
||||
失败通知遵循独立的目标路径:
|
||||
失败通知遵循单独的目标路径:
|
||||
|
||||
- `cron.failureDestination` 设置失败通知的全局默认值。
|
||||
- `job.delivery.failureDestination` 可按作业覆盖它。
|
||||
- 如果两者都未设置,且该作业已经通过 `announce` 投递,失败通知现在会回退到该主 announce 目标。
|
||||
- `delivery.failureDestination` 仅在 `sessionTarget="isolated"` 作业中受支持,除非主投递模式为 `webhook`。
|
||||
- `failureAlert.includeSkipped: true` 可让某个作业或全局 cron 告警策略选择加入重复的跳过运行告警。跳过运行会维护独立的连续跳过计数,因此不会影响执行错误退避。
|
||||
- `cron.failureDestination` 为失败通知设置全局默认值。
|
||||
- `job.delivery.failureDestination` 按任务覆盖该值。
|
||||
- 如果两者都未设置,而该任务已经通过 `announce` 进行投递,失败通知现在会回退到该主通知目标。
|
||||
- `delivery.failureDestination` 仅在 `sessionTarget="isolated"` 的任务上受支持,除非主投递模式是 `webhook`。
|
||||
- `failureAlert.includeSkipped: true` 可让任务或全局 cron 告警策略选择加入重复的跳过运行告警。跳过运行会保留单独的连续跳过计数,因此不会影响执行错误退避。
|
||||
|
||||
## CLI 示例
|
||||
|
||||
@ -184,7 +184,7 @@ Fast 模式也会跟随已解析的实时选择。如果选中的模型配置包
|
||||
--wake now
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="循环独立作业">
|
||||
<Tab title="重复的独立任务">
|
||||
```bash
|
||||
openclaw cron add \
|
||||
--name "Morning brief" \
|
||||
@ -197,7 +197,7 @@ Fast 模式也会跟随已解析的实时选择。如果选中的模型配置包
|
||||
--to "channel:C1234567890"
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="模型和 Thinking 覆盖">
|
||||
<Tab title="模型和 thinking 覆盖">
|
||||
```bash
|
||||
openclaw cron add \
|
||||
--name "Deep analysis" \
|
||||
@ -212,9 +212,9 @@ Fast 模式也会跟随已解析的实时选择。如果选中的模型配置包
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Webhook
|
||||
## webhook
|
||||
|
||||
Gateway 网关可以暴露 HTTP webhook 端点以供外部触发器使用。在配置中启用:
|
||||
Gateway 网关可以暴露 HTTP webhook 端点来接收外部触发器。在配置中启用:
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -226,18 +226,18 @@ Gateway 网关可以暴露 HTTP webhook 端点以供外部触发器使用。在
|
||||
}
|
||||
```
|
||||
|
||||
### 身份验证
|
||||
### 认证
|
||||
|
||||
每个请求都必须通过请求头包含 hook token:
|
||||
每个请求都必须通过请求头携带 hook token:
|
||||
|
||||
- `Authorization: Bearer <token>`(推荐)
|
||||
- `x-openclaw-token: <token>`
|
||||
|
||||
不接受查询字符串 token。
|
||||
不接受查询字符串中的 token。
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="POST /hooks/wake">
|
||||
为主会话排入一个系统事件:
|
||||
为主会话将一个系统事件加入队列:
|
||||
|
||||
```bash
|
||||
curl -X POST http://127.0.0.1:18789/hooks/wake \
|
||||
@ -247,7 +247,7 @@ Gateway 网关可以暴露 HTTP webhook 端点以供外部触发器使用。在
|
||||
```
|
||||
|
||||
<ParamField path="text" type="string" required>
|
||||
事件描述。
|
||||
事件说明。
|
||||
</ParamField>
|
||||
<ParamField path="mode" type="string" default="now">
|
||||
`now` 或 `next-heartbeat`。
|
||||
@ -267,20 +267,20 @@ Gateway 网关可以暴露 HTTP webhook 端点以供外部触发器使用。在
|
||||
字段:`message`(必填)、`name`、`agentId`、`wakeMode`、`deliver`、`channel`、`to`、`model`、`thinking`、`timeoutSeconds`。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="映射 hooks(POST /hooks/<name>)">
|
||||
<Accordion title="映射 hook(POST /hooks/<name>)">
|
||||
自定义 hook 名称通过配置中的 `hooks.mappings` 解析。映射可以使用模板或代码转换,将任意负载转换为 `wake` 或 `agent` 动作。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
<Warning>
|
||||
将 hook 端点放在 loopback、tailnet 或受信任的反向代理之后。
|
||||
请将 hook 端点放在 loopback、tailnet 或受信任的反向代理之后。
|
||||
|
||||
- 使用专用 hook token;不要复用 gateway 身份验证 token。
|
||||
- 将 `hooks.path` 保持为专用子路径;`/` 会被拒绝。
|
||||
- 设置 `hooks.allowedAgentIds` 以限制显式 `agentId` 路由。
|
||||
- 除非你确实需要由调用方选择会话,否则请保持 `hooks.allowRequestSessionKey=false`。
|
||||
- 如果你启用了 `hooks.allowRequestSessionKey`,也请设置 `hooks.allowedSessionKeyPrefixes` 来约束允许的会话键形态。
|
||||
- 默认情况下,hook 负载会被安全边界包裹。
|
||||
- 使用专用的 hook token;不要复用 gateway 认证 token。
|
||||
- 将 `hooks.path` 保持在专用子路径下;`/` 会被拒绝。
|
||||
- 设置 `hooks.allowedAgentIds` 以限制显式的 `agentId` 路由。
|
||||
- 除非你需要调用方自行选择会话,否则请保持 `hooks.allowRequestSessionKey=false`。
|
||||
- 如果你启用了 `hooks.allowRequestSessionKey`,也请设置 `hooks.allowedSessionKeyPrefixes`,以约束允许的会话键形状。
|
||||
- 默认情况下,hook 负载会被安全边界包装。
|
||||
</Warning>
|
||||
|
||||
## Gmail PubSub 集成
|
||||
@ -288,7 +288,7 @@ Gateway 网关可以暴露 HTTP webhook 端点以供外部触发器使用。在
|
||||
通过 Google PubSub 将 Gmail 收件箱触发器接入 OpenClaw。
|
||||
|
||||
<Note>
|
||||
**前置条件:**`gcloud` CLI、`gog`(gogcli)、已启用 OpenClaw hooks,以及用于公共 HTTPS 端点的 Tailscale。
|
||||
**前提条件:** `gcloud` CLI、`gog`(gogcli)、已启用 OpenClaw hooks,以及用于公共 HTTPS 端点的 Tailscale。
|
||||
</Note>
|
||||
|
||||
### 向导设置(推荐)
|
||||
@ -307,7 +307,7 @@ openclaw webhooks gmail setup --account openclaw@gmail.com
|
||||
|
||||
<Steps>
|
||||
<Step title="选择 GCP 项目">
|
||||
选择由 `gog` 所使用 OAuth 客户端所属的 GCP 项目:
|
||||
选择拥有 `gog` 所用 OAuth 客户端的 GCP 项目:
|
||||
|
||||
```bash
|
||||
gcloud auth login
|
||||
@ -347,19 +347,19 @@ openclaw webhooks gmail setup --account openclaw@gmail.com
|
||||
}
|
||||
```
|
||||
|
||||
## 管理作业
|
||||
## 管理任务
|
||||
|
||||
```bash
|
||||
# 列出所有作业
|
||||
# 列出所有任务
|
||||
openclaw cron list
|
||||
|
||||
# 显示一个作业,包括解析后的投递路由
|
||||
# 显示一个任务,包括解析后的投递路由
|
||||
openclaw cron show <jobId>
|
||||
|
||||
# 编辑作业
|
||||
# 编辑任务
|
||||
openclaw cron edit <jobId> --message "Updated prompt" --model "opus"
|
||||
|
||||
# 立即强制运行作业
|
||||
# 立即强制运行任务
|
||||
openclaw cron run <jobId>
|
||||
|
||||
# 仅在到期时运行
|
||||
@ -368,7 +368,7 @@ openclaw cron run <jobId> --due
|
||||
# 查看运行历史
|
||||
openclaw cron runs --id <jobId> --limit 50
|
||||
|
||||
# 删除作业
|
||||
# 删除任务
|
||||
openclaw cron remove <jobId>
|
||||
|
||||
# 智能体选择(多智能体设置)
|
||||
@ -379,10 +379,10 @@ openclaw cron edit <jobId> --clear-agent
|
||||
<Note>
|
||||
模型覆盖说明:
|
||||
|
||||
- `openclaw cron add|edit --model ...` 会更改作业的已选模型。
|
||||
- 如果该模型被允许,确切的 provider / model 会传递给独立智能体运行。
|
||||
- 如果不被允许,cron 会发出警告并回退到该作业的智能体 / 默认模型选择。
|
||||
- 已配置的回退链仍然适用,但纯 `--model` 覆盖如果没有显式的按作业回退列表,将不再悄悄回退到智能体主模型作为额外重试目标。
|
||||
- `openclaw cron add|edit --model ...` 会更改任务的选定模型。
|
||||
- 如果模型被允许,确切的该 provider/模型会传递到独立智能体运行。
|
||||
- 如果不被允许,cron 会发出警告并回退到任务的智能体/默认模型选择。
|
||||
- 已配置的回退链仍然适用,但仅使用普通 `--model` 覆盖且没有显式的按任务回退列表时,不会再静默回落到智能体主模型作为额外的重试目标。
|
||||
</Note>
|
||||
|
||||
## 配置
|
||||
@ -405,19 +405,19 @@ openclaw cron edit <jobId> --clear-agent
|
||||
}
|
||||
```
|
||||
|
||||
`maxConcurrentRuns` 同时限制计划中的 cron 分发和独立智能体回合执行。独立 cron 智能体回合在内部使用队列专用的 `cron-nested` 执行通道,因此提高该值可让独立的 cron LLM 运行并行推进,而不是只启动它们的外层 cron 包装器。共享的非 cron `nested` 通道不会因该设置而扩展。
|
||||
`maxConcurrentRuns` 同时限制计划中的 cron 分发和独立智能体回合执行。独立 cron 智能体回合在内部使用队列专用的 `cron-nested` 执行通道,因此提高此值可以让相互独立的 cron LLM 运行并行推进,而不是只启动它们的外层 cron 包装器。共享的非 cron `nested` 通道不会因该设置而扩宽。
|
||||
|
||||
运行时状态 sidecar 由 `cron.store` 派生:像 `~/clawd/cron/jobs.json` 这样的 `.json` 存储会使用 `~/clawd/cron/jobs-state.json`,而没有 `.json` 后缀的存储路径则会追加 `-state.json`。
|
||||
运行时状态 sidecar 由 `cron.store` 派生:像 `~/clawd/cron/jobs.json` 这样的 `.json` 存储会使用 `~/clawd/cron/jobs-state.json`,而不带 `.json` 后缀的存储路径则会追加 `-state.json`。
|
||||
|
||||
如果你手动编辑 `jobs.json`,请不要将 `jobs-state.json` 纳入源代码控制。OpenClaw 使用该 sidecar 来保存待处理槽位、活动标记、最近一次运行元数据,以及计划标识;该标识可让调度器判断外部编辑的作业何时需要新的 `nextRunAtMs`。
|
||||
如果你手动编辑 `jobs.json`,请不要将 `jobs-state.json` 纳入源代码管理。OpenClaw 使用该 sidecar 保存待处理槽位、活跃标记、最近运行元数据,以及用于告诉调度器何时需要为外部编辑过的任务生成新的 `nextRunAtMs` 的调度标识。
|
||||
|
||||
禁用 cron:`cron.enabled: false` 或 `OPENCLAW_SKIP_CRON=1`。
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="重试行为">
|
||||
**一次性重试**:瞬时错误(限流、过载、网络、服务器错误)最多重试 3 次,并使用指数退避。永久性错误会立即禁用。
|
||||
**一次性重试**:瞬时错误(限流、过载、网络、服务器错误)最多重试 3 次,并采用指数退避。永久性错误会立即禁用。
|
||||
|
||||
**循环重试**:重试之间使用指数退避(30 秒到 60 分钟)。下一次成功运行后会重置退避。
|
||||
**重复任务重试**:重试之间采用指数退避(30 秒到 60 分钟)。在下一次成功运行后,退避会重置。
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="维护">
|
||||
@ -443,27 +443,27 @@ openclaw doctor
|
||||
<AccordionGroup>
|
||||
<Accordion title="Cron 未触发">
|
||||
- 检查 `cron.enabled` 和 `OPENCLAW_SKIP_CRON` 环境变量。
|
||||
- 确认 Gateway 网关在持续运行。
|
||||
- 对于 `cron` 计划,检查时区(`--tz`)与主机时区是否一致。
|
||||
- 运行输出中的 `reason: not-due` 表示手动运行是通过 `openclaw cron run <jobId> --due` 检查的,而该作业当时尚未到期。
|
||||
- 确认 Gateway 网关持续运行。
|
||||
- 对于 `cron` 调度,请核对时区(`--tz`)与主机时区是否一致。
|
||||
- 运行输出中的 `reason: not-due` 表示你使用 `openclaw cron run <jobId> --due` 检查了手动运行,但该任务尚未到期。
|
||||
</Accordion>
|
||||
<Accordion title="Cron 已触发但没有投递">
|
||||
- 投递模式 `none` 表示不应期望运行器执行回退发送。当聊天路由可用时,智能体仍可直接使用 `message` 工具发送。
|
||||
- 缺少 / 无效的投递目标(`channel` / `to`)意味着出站投递已被跳过。
|
||||
- 对于 Matrix,复制的或旧版作业如果使用小写的 `delivery.to` 房间 ID,可能会失败,因为 Matrix 房间 ID 区分大小写。请将作业编辑为来自 Matrix 的精确 `!room:server` 或 `room:!room:server` 值。
|
||||
- 渠道身份验证错误(`unauthorized`、`Forbidden`)表示投递被凭证阻止。
|
||||
- 如果独立运行只返回静默 token(`NO_REPLY` / `no_reply`),OpenClaw 会抑制直接出站投递,也会抑制回退排队摘要路径,因此不会向聊天回发任何内容。
|
||||
- 如果智能体本应自行向用户发消息,请检查该作业是否有可用路由(`channel: "last"` 且有先前聊天,或显式的渠道 / 目标)。
|
||||
- 投递模式为 `none` 表示不应期望有运行器回退发送。如果聊天路由可用,智能体仍可使用 `message` 工具直接发送。
|
||||
- 投递目标缺失/无效(`channel`/`to`)表示已跳过出站发送。
|
||||
- 对于 Matrix,复制或旧版任务中被小写化的 `delivery.to` 房间 ID 可能失败,因为 Matrix 房间 ID 区分大小写。请将任务编辑为 Matrix 中准确的 `!room:server` 或 `room:!room:server` 值。
|
||||
- 渠道认证错误(`unauthorized`、`Forbidden`)表示投递因凭证问题被阻止。
|
||||
- 如果独立运行只返回静默 token(`NO_REPLY` / `no_reply`),OpenClaw 会抑制直接出站投递,也会抑制回退的排队摘要路径,因此不会向聊天回发任何内容。
|
||||
- 如果应该由智能体自行向用户发消息,请检查任务是否有可用路由(`channel: "last"` 且有先前聊天,或显式渠道/目标)。
|
||||
</Accordion>
|
||||
<Accordion title="Cron 或心跳似乎阻止了 /new 样式轮转">
|
||||
- 每日和空闲重置新鲜度并不基于 `updatedAt`;参见[会话管理](/zh-CN/concepts/session#session-lifecycle)。
|
||||
- Cron 唤醒、心跳运行、exec 通知和 gateway 记账可能会更新会话行以用于路由 / 状态,但它们不会延长 `sessionStartedAt` 或 `lastInteractionAt`。
|
||||
- 对于这些字段出现前创建的旧版行,只要 transcript JSONL 会话头文件仍可用,OpenClaw 就能从中恢复 `sessionStartedAt`。对于没有 `lastInteractionAt` 的旧版空闲行,会使用恢复出的启动时间作为空闲基线。
|
||||
<Accordion title="Cron 或 heartbeat 看起来阻止了 /new-style rollover">
|
||||
- 每日和空闲重置新鲜度不是基于 `updatedAt`;参见[会话管理](/zh-CN/concepts/session#session-lifecycle)。
|
||||
- Cron 唤醒、heartbeat 运行、exec 通知和 gateway 账务处理可能会更新会话行以用于路由/状态,但不会延长 `sessionStartedAt` 或 `lastInteractionAt`。
|
||||
- 对于这些字段出现之前创建的旧记录,只要文件仍可用,OpenClaw 就可以从 transcript JSONL 会话头中恢复 `sessionStartedAt`。缺少 `lastInteractionAt` 的旧版空闲记录会使用该恢复出的开始时间作为其空闲基线。
|
||||
</Accordion>
|
||||
<Accordion title="时区注意事项">
|
||||
- 不带 `--tz` 的 cron 使用 gateway 主机时区。
|
||||
- 不带时区的 `at` 计划按 UTC 处理。
|
||||
- 心跳 `activeHours` 使用已配置的时区解析。
|
||||
- 不带 `--tz` 的 cron 会使用 gateway 主机时区。
|
||||
- 不带时区的 `at` 调度会被视为 UTC。
|
||||
- heartbeat `activeHours` 使用已配置的时区解析。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
@ -471,5 +471,5 @@ openclaw doctor
|
||||
|
||||
- [自动化与任务](/zh-CN/automation) — 所有自动化机制概览
|
||||
- [后台任务](/zh-CN/automation/tasks) — cron 执行的任务账本
|
||||
- [Heartbeat](/zh-CN/gateway/heartbeat) — 周期性主会话回合
|
||||
- [Heartbeat](/zh-CN/gateway/heartbeat) — 周期性的主会话回合
|
||||
- [时区](/zh-CN/concepts/timezone) — 时区配置
|
||||
|
||||
@ -1,29 +1,33 @@
|
||||
---
|
||||
read_when:
|
||||
- 你正在构建一个新的模型提供商插件
|
||||
- 你想为 OpenClaw 添加一个与 OpenAI 兼容的代理或自定义 LLM
|
||||
- 你想为 OpenClaw 添加一个兼容 OpenAI 的代理或自定义 LLM
|
||||
- 你需要了解提供商认证、目录和运行时钩子
|
||||
sidebarTitle: Provider plugins
|
||||
summary: 为 OpenClaw 构建模型提供商插件的分步指南
|
||||
title: 构建提供商插件
|
||||
x-i18n:
|
||||
generated_at: "2026-04-27T09:55:47Z"
|
||||
generated_at: "2026-04-27T20:43:28Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 4cd037c179a28ede6da91976cc886d062265e6223081da8bd19641fc20ccfedb
|
||||
source_hash: 9a4f0d0bed655ccda7ce2731270999d46d83f29b89d5e8ba80832992161eb993
|
||||
source_path: plugins/sdk-provider-plugins.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
本指南将带你逐步构建一个提供商插件,用于向 OpenClaw 添加模型提供商(LLM)。完成后,你将拥有一个包含模型目录、API 密钥认证和动态模型解析的提供商。
|
||||
本指南将带你逐步构建一个提供商插件,为 OpenClaw 添加一个模型提供商
|
||||
(LLM)。完成后,你将拥有一个包含模型目录、API 密钥认证和动态模型解析功能的提供商。
|
||||
|
||||
<Info>
|
||||
如果你以前从未构建过任何 OpenClaw 插件,请先阅读
|
||||
如果你之前没有构建过任何 OpenClaw 插件,请先阅读
|
||||
[入门指南](/zh-CN/plugins/building-plugins),了解基础包结构和清单设置。
|
||||
</Info>
|
||||
|
||||
<Tip>
|
||||
提供商插件会将模型添加到 OpenClaw 的常规推理循环中。如果模型必须通过一个原生智能体守护进程运行,并且该守护进程负责线程、压缩或工具事件,请将该提供商与一个 [agent harness](/zh-CN/plugins/sdk-agent-harness) 搭配使用,而不是把守护进程协议细节放进核心中。
|
||||
提供商插件会将模型添加到 OpenClaw 的常规推理循环中。如果该模型
|
||||
必须通过一个拥有线程、压缩或工具事件的原生智能体守护进程运行,
|
||||
请将该提供商与一个 [agent harness](/zh-CN/plugins/sdk-agent-harness) 搭配使用,
|
||||
而不是把守护进程协议细节放进核心中。
|
||||
</Tip>
|
||||
|
||||
## 演练
|
||||
@ -55,7 +59,7 @@ x-i18n:
|
||||
{
|
||||
"id": "acme-ai",
|
||||
"name": "Acme AI",
|
||||
"description": "Acme AI 模型提供商",
|
||||
"description": "Acme AI model provider",
|
||||
"providers": ["acme-ai"],
|
||||
"modelSupport": {
|
||||
"modelPrefixes": ["acme-"]
|
||||
@ -71,12 +75,12 @@ x-i18n:
|
||||
"provider": "acme-ai",
|
||||
"method": "api-key",
|
||||
"choiceId": "acme-ai-api-key",
|
||||
"choiceLabel": "Acme AI API 密钥",
|
||||
"choiceLabel": "Acme AI API key",
|
||||
"groupId": "acme-ai",
|
||||
"groupLabel": "Acme AI",
|
||||
"cliFlag": "--acme-ai-api-key",
|
||||
"cliOption": "--acme-ai-api-key <key>",
|
||||
"cliDescription": "Acme AI API 密钥"
|
||||
"cliDescription": "Acme AI API key"
|
||||
}
|
||||
],
|
||||
"configSchema": {
|
||||
@ -87,7 +91,12 @@ x-i18n:
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
该清单声明了 `providerAuthEnvVars`,这样 OpenClaw 无需加载你的插件运行时即可检测凭证。当某个提供商变体应复用另一个提供商 id 的认证时,请添加 `providerAuthAliases`。`modelSupport` 是可选的,它允许 OpenClaw 在运行时钩子存在之前,根据诸如 `acme-large` 这样的简写模型 id 自动加载你的提供商插件。如果你要在 ClawHub 上发布该提供商,那么 `package.json` 中的这些 `openclaw.compat` 和 `openclaw.build` 字段是必需的。
|
||||
清单会声明 `providerAuthEnvVars`,这样 OpenClaw 无需加载你的插件运行时
|
||||
就能检测凭证。当某个提供商变体应复用另一个提供商 id 的认证时,
|
||||
添加 `providerAuthAliases`。`modelSupport` 是可选项,它允许 OpenClaw
|
||||
在运行时钩子存在之前,就根据像 `acme-large` 这样的简写模型 id
|
||||
自动加载你的提供商插件。如果你要在 ClawHub 上发布该提供商,
|
||||
则 `package.json` 中必须包含这些 `openclaw.compat` 和 `openclaw.build` 字段。
|
||||
|
||||
</Step>
|
||||
|
||||
@ -101,7 +110,7 @@ x-i18n:
|
||||
export default definePluginEntry({
|
||||
id: "acme-ai",
|
||||
name: "Acme AI",
|
||||
description: "Acme AI 模型提供商",
|
||||
description: "Acme AI model provider",
|
||||
register(api) {
|
||||
api.registerProvider({
|
||||
id: "acme-ai",
|
||||
@ -113,12 +122,12 @@ x-i18n:
|
||||
createProviderApiKeyAuthMethod({
|
||||
providerId: "acme-ai",
|
||||
methodId: "api-key",
|
||||
label: "Acme AI API 密钥",
|
||||
hint: "来自你的 Acme AI 控制台的 API 密钥",
|
||||
label: "Acme AI API key",
|
||||
hint: "API key from your Acme AI dashboard",
|
||||
optionKey: "acmeAiApiKey",
|
||||
flagName: "--acme-ai-api-key",
|
||||
envVar: "ACME_AI_API_KEY",
|
||||
promptMessage: "输入你的 Acme AI API 密钥",
|
||||
promptMessage: "Enter your Acme AI API key",
|
||||
defaultModel: "acme-ai/acme-large",
|
||||
}),
|
||||
],
|
||||
@ -163,11 +172,12 @@ x-i18n:
|
||||
});
|
||||
```
|
||||
|
||||
这样就得到了一个可工作的提供商。用户现在可以运行
|
||||
这就是一个可工作的提供商。用户现在可以运行
|
||||
`openclaw onboard --acme-ai-api-key <key>` 并选择
|
||||
`acme-ai/acme-large` 作为他们的模型。
|
||||
|
||||
如果上游提供商使用的控制令牌与 OpenClaw 不同,请添加一个小型双向文本转换,而不是替换流路径:
|
||||
如果上游提供商使用的控制标记与 OpenClaw 不同,请添加一个
|
||||
小型双向文本转换,而不是替换流路径:
|
||||
|
||||
```typescript
|
||||
api.registerTextTransforms({
|
||||
@ -184,9 +194,13 @@ x-i18n:
|
||||
});
|
||||
```
|
||||
|
||||
`input` 会在传输之前重写最终系统提示词和文本消息内容。`output` 会在 OpenClaw 解析其自身控制标记或进行渠道投递之前,重写助手文本增量和最终文本。
|
||||
`input` 会在传输前重写最终系统提示词和文本消息内容。
|
||||
`output` 会在 OpenClaw 解析其自身控制标记或进行渠道投递之前,
|
||||
重写助手文本增量和最终文本。
|
||||
|
||||
对于仅注册一个使用 API 密钥认证的文本提供商,并带有单个由目录支持的运行时的内置提供商,优先使用更精简的 `defineSingleProviderPluginEntry(...)` 辅助函数:
|
||||
对于只注册一个带 API 密钥认证的文本提供商、再加上一个由目录支持的单一运行时的内置提供商,
|
||||
优先使用更窄的
|
||||
`defineSingleProviderPluginEntry(...)` 辅助函数:
|
||||
|
||||
```typescript
|
||||
import { defineSingleProviderPluginEntry } from "openclaw/plugin-sdk/provider-entry";
|
||||
@ -194,19 +208,19 @@ x-i18n:
|
||||
export default defineSingleProviderPluginEntry({
|
||||
id: "acme-ai",
|
||||
name: "Acme AI",
|
||||
description: "Acme AI 模型提供商",
|
||||
description: "Acme AI model provider",
|
||||
provider: {
|
||||
label: "Acme AI",
|
||||
docsPath: "/providers/acme-ai",
|
||||
auth: [
|
||||
{
|
||||
methodId: "api-key",
|
||||
label: "Acme AI API 密钥",
|
||||
hint: "来自你的 Acme AI 控制台的 API 密钥",
|
||||
label: "Acme AI API key",
|
||||
hint: "API key from your Acme AI dashboard",
|
||||
optionKey: "acmeAiApiKey",
|
||||
flagName: "--acme-ai-api-key",
|
||||
envVar: "ACME_AI_API_KEY",
|
||||
promptMessage: "输入你的 Acme AI API 密钥",
|
||||
promptMessage: "Enter your Acme AI API key",
|
||||
defaultModel: "acme-ai/acme-large",
|
||||
},
|
||||
],
|
||||
@ -226,20 +240,32 @@ x-i18n:
|
||||
});
|
||||
```
|
||||
|
||||
`buildProvider` 是 OpenClaw 可以解析真实提供商认证时使用的实时目录路径。它可以执行提供商特定的发现逻辑。仅在需要显示离线条目且这些条目可以在认证配置完成前安全展示时,才使用 `buildStaticProvider`;它不能要求凭证,也不能发起网络请求。OpenClaw 的 `models list --all` 显示当前仅对内置提供商插件执行静态目录,并且使用空配置、空环境以及无 agent/workspace 路径的上下文。
|
||||
`buildProvider` 是 OpenClaw 可以解析真实提供商认证时所使用的实时目录路径。
|
||||
它可以执行提供商特定的发现逻辑。`buildStaticProvider` 仅用于
|
||||
在认证尚未配置前也可安全显示的离线条目;它不得要求凭证,也不得发起网络请求。
|
||||
OpenClaw 的 `models list --all` 显示当前仅对内置提供商插件执行静态目录,
|
||||
且执行环境为空配置、空环境变量,并且没有智能体 / 工作区路径。
|
||||
|
||||
如果你的认证流程还需要在新手引导期间修补 `models.providers.*`、别名以及智能体默认模型,请使用 `openclaw/plugin-sdk/provider-onboard` 中的预设辅助函数。最精简的辅助函数是
|
||||
如果你的认证流程还需要在新手引导期间修补 `models.providers.*`、
|
||||
别名以及智能体默认模型,请使用
|
||||
`openclaw/plugin-sdk/provider-onboard` 中的预设辅助函数。最窄的辅助函数有
|
||||
`createDefaultModelPresetAppliers(...)`、
|
||||
`createDefaultModelsPresetAppliers(...)` 和
|
||||
`createModelCatalogPresetAppliers(...)`。
|
||||
|
||||
当某个提供商的原生端点在常规 `openai-completions` 传输上支持流式 usage 块时,请优先使用 `openclaw/plugin-sdk/provider-catalog-shared` 中的共享目录辅助函数,而不要硬编码提供商 id 检查。`supportsNativeStreamingUsageCompat(...)` 和
|
||||
`applyProviderNativeStreamingUsageCompat(...)` 会根据端点能力映射检测支持情况,因此即使插件使用的是自定义提供商 id,原生 Moonshot/DashScope 风格端点也仍然可以选择启用。
|
||||
当某个提供商的原生端点在常规 `openai-completions` 传输上支持流式用量块时,
|
||||
优先使用 `openclaw/plugin-sdk/provider-catalog-shared` 中的共享目录辅助函数,
|
||||
而不要硬编码提供商 id 检查。
|
||||
`supportsNativeStreamingUsageCompat(...)` 和
|
||||
`applyProviderNativeStreamingUsageCompat(...)` 会根据端点能力映射检测支持情况,
|
||||
因此即使插件使用的是自定义提供商 id,原生 Moonshot / DashScope 风格的端点
|
||||
仍然可以选择启用。
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="添加动态模型解析">
|
||||
如果你的提供商接受任意模型 id(例如代理或路由器),请添加 `resolveDynamicModel`:
|
||||
如果你的提供商接受任意模型 ID(例如代理或路由器),
|
||||
添加 `resolveDynamicModel`:
|
||||
|
||||
```typescript
|
||||
api.registerProvider({
|
||||
@ -260,14 +286,17 @@ x-i18n:
|
||||
});
|
||||
```
|
||||
|
||||
如果解析需要网络调用,请使用 `prepareDynamicModel` 进行异步预热 —— 完成后会再次运行 `resolveDynamicModel`。
|
||||
如果解析过程需要网络调用,请使用 `prepareDynamicModel` 进行异步预热——
|
||||
在它完成后,`resolveDynamicModel` 会再次运行。
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="按需添加运行时钩子">
|
||||
大多数提供商只需要 `catalog` + `resolveDynamicModel`。随着你的提供商需求增加,再逐步添加钩子。
|
||||
大多数提供商只需要 `catalog` + `resolveDynamicModel`。请根据你的提供商需求
|
||||
逐步添加钩子。
|
||||
|
||||
共享辅助构建器现在已经覆盖了最常见的重放/工具兼容系列,因此插件通常不需要逐个手动接线每个钩子:
|
||||
共享辅助构建器现在已覆盖最常见的重放 / 工具兼容系列,
|
||||
因此插件通常不需要手动逐个接线每个钩子:
|
||||
|
||||
```typescript
|
||||
import { buildProviderReplayFamilyHooks } from "openclaw/plugin-sdk/provider-model-shared";
|
||||
@ -287,43 +316,43 @@ x-i18n:
|
||||
});
|
||||
```
|
||||
|
||||
当前可用的重放系列如下:
|
||||
当前可用的重放系列:
|
||||
|
||||
| 系列 | 它接入的内容 | 内置示例 |
|
||||
| 系列 | 它会接入的内容 | 内置示例 |
|
||||
| --- | --- | --- |
|
||||
| `openai-compatible` | 用于与 OpenAI 兼容传输的共享 OpenAI 风格重放策略,包括工具调用 id 清理、assistant-first 顺序修复,以及在传输需要时的通用 Gemini 轮次校验 | `moonshot`, `ollama`, `xai`, `zai` |
|
||||
| `anthropic-by-model` | 按 `modelId` 选择的 Claude 感知型重放策略,因此 Anthropic 消息传输仅会在解析后的模型实际是 Claude id 时应用 Claude 特定的 thinking 块清理 | `amazon-bedrock`, `anthropic-vertex` |
|
||||
| `google-gemini` | 原生 Gemini 重放策略,加上引导重放清理和带标签的 reasoning 输出模式 | `google`, `google-gemini-cli` |
|
||||
| `passthrough-gemini` | 用于通过与 OpenAI 兼容的代理传输运行的 Gemini 模型的 Gemini thought-signature 清理;不会启用原生 Gemini 重放校验或引导重写 | `openrouter`, `kilocode`, `opencode`, `opencode-go` |
|
||||
| `hybrid-anthropic-openai` | 适用于在单个插件中混合 Anthropic 消息和与 OpenAI 兼容模型界面的提供商的混合策略;可选的仅限 Claude 的 thinking 块丢弃仍然只作用于 Anthropic 一侧 | `minimax` |
|
||||
| `openai-compatible` | 面向兼容 OpenAI 传输的共享 OpenAI 风格重放策略,包括工具调用 id 清理、assistant 优先顺序修复,以及传输需要时的通用 Gemini 轮次校验 | `moonshot`, `ollama`, `xai`, `zai` |
|
||||
| `anthropic-by-model` | 按 `modelId` 选择的 Claude 感知重放策略,因此只有在解析出的模型确实是 Claude id 时,Anthropic 消息传输才会获得 Claude 特有的 thinking block 清理 | `amazon-bedrock`, `anthropic-vertex` |
|
||||
| `google-gemini` | 原生 Gemini 重放策略,加上引导重放清理和带标签的推理输出模式 | `google`, `google-gemini-cli` |
|
||||
| `passthrough-gemini` | 面向通过兼容 OpenAI 的代理传输运行的 Gemini 模型的 Gemini thought signature 清理;不会启用原生 Gemini 重放校验或引导重写 | `openrouter`, `kilocode`, `opencode`, `opencode-go` |
|
||||
| `hybrid-anthropic-openai` | 适用于在一个插件中混合 Anthropic 消息和兼容 OpenAI 模型表面的提供商的混合策略;可选的仅 Claude thinking block 丢弃仍然局限在 Anthropic 一侧 | `minimax` |
|
||||
|
||||
当前可用的流系列:
|
||||
当前可用的流式系列:
|
||||
|
||||
| 系列 | 它接入的内容 | 内置示例 |
|
||||
| 系列 | 它会接入的内容 | 内置示例 |
|
||||
| --- | --- | --- |
|
||||
| `google-thinking` | 共享流路径上的 Gemini thinking 负载标准化 | `google`, `google-gemini-cli` |
|
||||
| `kilocode-thinking` | 共享代理流路径上的 Kilo reasoning 包装器,其中 `kilo/auto` 和不受支持的代理 reasoning id 会跳过注入的 thinking | `kilocode` |
|
||||
| `moonshot-thinking` | 根据配置和 `/think` 级别进行的 Moonshot 二进制原生 thinking 负载映射 | `moonshot` |
|
||||
| `kilocode-thinking` | 共享代理流路径上的 Kilo 推理包装器,其中 `kilo/auto` 和不受支持的代理推理 id 会跳过注入的 thinking | `kilocode` |
|
||||
| `moonshot-thinking` | 根据配置和 `/think` 级别对 Moonshot 二进制原生 thinking 负载进行映射 | `moonshot` |
|
||||
| `minimax-fast-mode` | 共享流路径上的 MiniMax 快速模式模型重写 | `minimax`, `minimax-portal` |
|
||||
| `openai-responses-defaults` | 共享的原生 OpenAI/Codex Responses 包装器:归因头、`/fast`/`serviceTier`、文本详细程度、原生 Codex 网络搜索、reasoning 兼容负载整形以及 Responses 上下文管理 | `openai`, `openai-codex` |
|
||||
| `openrouter-thinking` | 用于代理路由的 OpenRouter reasoning 包装器,集中处理不支持模型/`auto` 的跳过逻辑 | `openrouter` |
|
||||
| `tool-stream-default-on` | 为像 Z.AI 这样希望默认启用工具流式传输、除非显式禁用的提供商提供默认开启的 `tool_stream` 包装器 | `zai` |
|
||||
| `openai-responses-defaults` | 共享的原生 OpenAI/Codex Responses 包装器:归因标头、`/fast`/`serviceTier`、文本详细度、原生 Codex web search、推理兼容负载整形,以及 Responses 上下文管理 | `openai`, `openai-codex` |
|
||||
| `openrouter-thinking` | 面向代理路由的 OpenRouter 推理包装器,集中处理不受支持模型 / `auto` 的跳过逻辑 | `openrouter` |
|
||||
| `tool-stream-default-on` | 面向像 Z.AI 这样除非明确禁用否则希望启用工具流式传输的提供商的默认开启 `tool_stream` 包装器 | `zai` |
|
||||
|
||||
<Accordion title="为系列构建器提供支持的 SDK 接缝">
|
||||
每个系列构建器都由同一包导出的更底层公共辅助函数组合而成,当某个提供商需要偏离常见模式时,你可以直接使用它们:
|
||||
每个系列构建器都由同一包中导出的更底层公共辅助函数组成;当某个提供商需要偏离通用模式时,你可以使用它们:
|
||||
|
||||
- `openclaw/plugin-sdk/provider-model-shared` — `ProviderReplayFamily`、`buildProviderReplayFamilyHooks(...)` 以及原始重放构建器(`buildOpenAICompatibleReplayPolicy`、`buildAnthropicReplayPolicyForModel`、`buildGoogleGeminiReplayPolicy`、`buildHybridAnthropicOrOpenAIReplayPolicy`)。还导出 Gemini 重放辅助函数(`sanitizeGoogleGeminiReplayHistory`、`resolveTaggedReasoningOutputMode`)以及端点/模型辅助函数(`resolveProviderEndpoint`、`normalizeProviderId`、`normalizeGooglePreviewModelId`、`normalizeNativeXaiModelId`)。
|
||||
- `openclaw/plugin-sdk/provider-stream` — `ProviderStreamFamily`、`buildProviderStreamFamilyHooks(...)`、`composeProviderStreamWrappers(...)`,以及共享的 OpenAI/Codex 包装器(`createOpenAIAttributionHeadersWrapper`、`createOpenAIFastModeWrapper`、`createOpenAIServiceTierWrapper`、`createOpenAIResponsesContextManagementWrapper`、`createCodexNativeWebSearchWrapper`)、DeepSeek V4 的 OpenAI-compatible 包装器(`createDeepSeekV4OpenAICompatibleThinkingWrapper`),以及共享的代理/提供商包装器(`createOpenRouterWrapper`、`createToolStreamWrapper`、`createMinimaxFastModeWrapper`)。
|
||||
- `openclaw/plugin-sdk/provider-tools` — `ProviderToolCompatFamily`、`buildProviderToolCompatFamilyHooks("gemini")`、底层 Gemini schema 辅助函数(`normalizeGeminiToolSchemas`、`inspectGeminiToolSchemas`),以及 xAI 兼容辅助函数(`resolveXaiModelCompatPatch()`、`applyXaiModelCompat(model)`)。内置的 xAI 插件会将这些与 `normalizeResolvedModel` + `contributeResolvedModelCompat` 配合使用,以确保 xAI 规则仍由该提供商自行管理。
|
||||
- `openclaw/plugin-sdk/provider-model-shared` — `ProviderReplayFamily`、`buildProviderReplayFamilyHooks(...)`,以及原始重放构建器(`buildOpenAICompatibleReplayPolicy`、`buildAnthropicReplayPolicyForModel`、`buildGoogleGeminiReplayPolicy`、`buildHybridAnthropicOrOpenAIReplayPolicy`)。还导出 Gemini 重放辅助函数(`sanitizeGoogleGeminiReplayHistory`、`resolveTaggedReasoningOutputMode`)以及端点 / 模型辅助函数(`resolveProviderEndpoint`、`normalizeProviderId`、`normalizeGooglePreviewModelId`、`normalizeNativeXaiModelId`)。
|
||||
- `openclaw/plugin-sdk/provider-stream` — `ProviderStreamFamily`、`buildProviderStreamFamilyHooks(...)`、`composeProviderStreamWrappers(...)`,以及共享的 OpenAI/Codex 包装器(`createOpenAIAttributionHeadersWrapper`、`createOpenAIFastModeWrapper`、`createOpenAIServiceTierWrapper`、`createOpenAIResponsesContextManagementWrapper`、`createCodexNativeWebSearchWrapper`)、DeepSeek V4 兼容 OpenAI 的包装器(`createDeepSeekV4OpenAICompatibleThinkingWrapper`)、Anthropic Messages thinking 预填充清理(`createAnthropicThinkingPrefillPayloadWrapper`),以及共享的代理 / 提供商包装器(`createOpenRouterWrapper`、`createToolStreamWrapper`、`createMinimaxFastModeWrapper`)。
|
||||
- `openclaw/plugin-sdk/provider-tools` — `ProviderToolCompatFamily`、`buildProviderToolCompatFamilyHooks("gemini")`、底层 Gemini schema 辅助函数(`normalizeGeminiToolSchemas`、`inspectGeminiToolSchemas`),以及 xAI 兼容辅助函数(`resolveXaiModelCompatPatch()`、`applyXaiModelCompat(model)`)。内置的 xAI 插件结合 `normalizeResolvedModel` 与 `contributeResolvedModelCompat` 使用这些函数,以便让 xAI 规则继续由该提供商负责。
|
||||
|
||||
有些流辅助函数会有意保留在提供商本地。`@openclaw/anthropic-provider` 将 `wrapAnthropicProviderStream`、`resolveAnthropicBetas`、`resolveAnthropicFastMode`、`resolveAnthropicServiceTier` 以及更底层的 Anthropic 包装器构建器保留在它自己的公共 `api.ts` / `contract-api.ts` 接缝中,因为它们编码了 Claude OAuth beta 处理和 `context1m` 门控。xAI 插件同样会将原生 xAI Responses 整形保留在它自己的 `wrapStreamFn` 中(`/fast` 别名、默认 `tool_stream`、不受支持的严格工具清理、xAI 特定的 reasoning 负载移除)。
|
||||
有些流式辅助函数会有意保留为提供商本地实现。`@openclaw/anthropic-provider` 将 `wrapAnthropicProviderStream`、`resolveAnthropicBetas`、`resolveAnthropicFastMode`、`resolveAnthropicServiceTier`,以及更底层的 Anthropic 包装器构建器保留在其公共 `api.ts` / `contract-api.ts` 接缝中,因为它们编码了 Claude OAuth beta 处理和 `context1m` 门控。xAI 插件同样将原生 xAI Responses 整形保留在自己的 `wrapStreamFn` 中(`/fast` 别名、默认 `tool_stream`、不受支持的 strict-tool 清理,以及 xAI 特定的推理负载移除)。
|
||||
|
||||
同样的包根模式也支撑着 `@openclaw/openai-provider`(提供商构建器、默认模型辅助函数、realtime 提供商构建器)和 `@openclaw/openrouter-provider`(提供商构建器以及新手引导/配置辅助函数)。
|
||||
同样的包根模式也支撑 `@openclaw/openai-provider`(提供商构建器、默认模型辅助函数、实时提供商构建器)和 `@openclaw/openrouter-provider`(提供商构建器以及新手引导 / 配置辅助函数)。
|
||||
</Accordion>
|
||||
|
||||
<Tabs>
|
||||
<Tab title="令牌交换">
|
||||
对于那些在每次推理调用前都需要进行令牌交换的提供商:
|
||||
对于需要在每次推理调用前进行令牌交换的提供商:
|
||||
|
||||
```typescript
|
||||
prepareRuntimeAuth: async (ctx) => {
|
||||
@ -336,8 +365,8 @@ x-i18n:
|
||||
},
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="自定义请求头">
|
||||
对于那些需要自定义请求头或请求体修改的提供商:
|
||||
<Tab title="自定义标头">
|
||||
对于需要自定义请求标头或请求体修改的提供商:
|
||||
|
||||
```typescript
|
||||
// wrapStreamFn returns a StreamFn derived from ctx.streamFn
|
||||
@ -354,8 +383,8 @@ x-i18n:
|
||||
},
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="原生传输身份">
|
||||
对于那些需要在通用 HTTP 或 WebSocket 传输上附加原生请求/会话请求头或元数据的提供商:
|
||||
<Tab title="原生传输标识">
|
||||
对于需要在通用 HTTP 或 WebSocket 传输上添加原生请求 / 会话标头或元数据的提供商:
|
||||
|
||||
```typescript
|
||||
resolveTransportTurnState: (ctx) => ({
|
||||
@ -376,7 +405,7 @@ x-i18n:
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="用量和计费">
|
||||
对于那些公开用量/计费数据的提供商:
|
||||
对于公开用量 / 计费数据的提供商:
|
||||
|
||||
```typescript
|
||||
resolveUsageAuth: async (ctx) => {
|
||||
@ -391,73 +420,73 @@ x-i18n:
|
||||
</Tabs>
|
||||
|
||||
<Accordion title="所有可用的提供商钩子">
|
||||
OpenClaw 按以下顺序调用钩子。大多数提供商只会使用其中 2–3 个:
|
||||
OpenClaw 会按以下顺序调用钩子。大多数提供商只会使用其中 2–3 个:
|
||||
|
||||
| # | 钩子 | 适用场景 |
|
||||
| # | 钩子 | 何时使用 |
|
||||
| --- | --- | --- |
|
||||
| 1 | `catalog` | 模型目录或基础 URL 默认值 |
|
||||
| 2 | `applyConfigDefaults` | 在配置具体化期间应用由提供商管理的全局默认值 |
|
||||
| 3 | `normalizeModelId` | 在查找前清理旧版/预览模型 id 别名 |
|
||||
| 4 | `normalizeTransport` | 在通用模型组装前清理提供商系列的 `api` / `baseUrl` |
|
||||
| 1 | `catalog` | 模型目录或 base URL 默认值 |
|
||||
| 2 | `applyConfigDefaults` | 配置物化期间由提供商负责的全局默认值 |
|
||||
| 3 | `normalizeModelId` | 查找前清理旧版 / 预览模型 id 别名 |
|
||||
| 4 | `normalizeTransport` | 通用模型组装前清理提供商系列的 `api` / `baseUrl` |
|
||||
| 5 | `normalizeConfig` | 标准化 `models.providers.<id>` 配置 |
|
||||
| 6 | `applyNativeStreamingUsageCompat` | 对配置提供商应用原生流式 usage 兼容重写 |
|
||||
| 7 | `resolveConfigApiKey` | 由提供商管理的环境标记认证解析 |
|
||||
| 8 | `resolveSyntheticAuth` | 本地/自托管或由配置支持的合成认证 |
|
||||
| 9 | `shouldDeferSyntheticProfileAuth` | 将合成的已存储 profile 占位符置于环境/配置认证之后 |
|
||||
| 10 | `resolveDynamicModel` | 接受任意上游模型 id |
|
||||
| 11 | `prepareDynamicModel` | 在解析前异步获取元数据 |
|
||||
| 12 | `normalizeResolvedModel` | 在进入运行器前重写传输参数 |
|
||||
| 13 | `contributeResolvedModelCompat` | 为运行在另一种兼容传输后的厂商模型提供兼容标记 |
|
||||
| 14 | `capabilities` | 旧版静态能力包;仅用于兼容性 |
|
||||
| 15 | `normalizeToolSchemas` | 在注册前清理由提供商管理的工具 schema |
|
||||
| 16 | `inspectToolSchemas` | 由提供商管理的工具 schema 诊断 |
|
||||
| 17 | `resolveReasoningOutputMode` | 带标签与原生 reasoning 输出契约 |
|
||||
| 6 | `applyNativeStreamingUsageCompat` | 面向配置提供商的原生流式用量兼容重写 |
|
||||
| 7 | `resolveConfigApiKey` | 由提供商负责的环境变量标记认证解析 |
|
||||
| 8 | `resolveSyntheticAuth` | 本地 / 自托管或由配置支持的合成认证 |
|
||||
| 9 | `shouldDeferSyntheticProfileAuth` | 在环境变量 / 配置认证之后降低合成存储配置文件占位符的优先级 |
|
||||
| 10 | `resolveDynamicModel` | 接受任意上游模型 ID |
|
||||
| 11 | `prepareDynamicModel` | 解析前异步获取元数据 |
|
||||
| 12 | `normalizeResolvedModel` | 运行器之前的传输重写 |
|
||||
| 13 | `contributeResolvedModelCompat` | 针对运行在其他兼容传输后的厂商模型提供兼容标志 |
|
||||
| 14 | `capabilities` | 旧版静态能力包;仅用于兼容 |
|
||||
| 15 | `normalizeToolSchemas` | 注册前由提供商负责的工具 schema 清理 |
|
||||
| 16 | `inspectToolSchemas` | 由提供商负责的工具 schema 诊断 |
|
||||
| 17 | `resolveReasoningOutputMode` | 带标签与原生推理输出契约 |
|
||||
| 18 | `prepareExtraParams` | 默认请求参数 |
|
||||
| 19 | `createStreamFn` | 完全自定义的 StreamFn 传输 |
|
||||
| 20 | `wrapStreamFn` | 常规流路径上的自定义请求头/请求体包装器 |
|
||||
| 21 | `resolveTransportTurnState` | 原生逐轮请求头/元数据 |
|
||||
| 22 | `resolveWebSocketSessionPolicy` | 原生 WS 会话请求头/冷却策略 |
|
||||
| 20 | `wrapStreamFn` | 常规流路径上的自定义标头 / 请求体包装器 |
|
||||
| 21 | `resolveTransportTurnState` | 原生逐轮标头 / 元数据 |
|
||||
| 22 | `resolveWebSocketSessionPolicy` | 原生 WS 会话标头 / 冷却时间 |
|
||||
| 23 | `formatApiKey` | 自定义运行时令牌形态 |
|
||||
| 24 | `refreshOAuth` | 自定义 OAuth 刷新 |
|
||||
| 25 | `buildAuthDoctorHint` | 认证修复指导 |
|
||||
| 26 | `matchesContextOverflowError` | 由提供商管理的上下文溢出检测 |
|
||||
| 27 | `classifyFailoverReason` | 由提供商管理的限流/过载分类 |
|
||||
| 25 | `buildAuthDoctorHint` | 认证修复指引 |
|
||||
| 26 | `matchesContextOverflowError` | 由提供商负责的上下文溢出检测 |
|
||||
| 27 | `classifyFailoverReason` | 由提供商负责的限流 / 过载分类 |
|
||||
| 28 | `isCacheTtlEligible` | 提示词缓存 TTL 门控 |
|
||||
| 29 | `buildMissingAuthMessage` | 自定义缺失认证提示 |
|
||||
| 30 | `suppressBuiltInModel` | 隐藏过时的上游条目 |
|
||||
| 31 | `augmentModelCatalog` | 合成的前向兼容条目 |
|
||||
| 32 | `resolveThinkingProfile` | 特定模型的 `/think` 选项集 |
|
||||
| 33 | `isBinaryThinking` | 二进制 thinking 开/关兼容性 |
|
||||
| 34 | `supportsXHighThinking` | `xhigh` reasoning 支持兼容性 |
|
||||
| 33 | `isBinaryThinking` | 二元 thinking 开 / 关兼容性 |
|
||||
| 34 | `supportsXHighThinking` | `xhigh` 推理支持兼容性 |
|
||||
| 35 | `resolveDefaultThinkingLevel` | 默认 `/think` 策略兼容性 |
|
||||
| 36 | `isModernModelRef` | live/smoke 模型匹配 |
|
||||
| 37 | `prepareRuntimeAuth` | 在推理前进行令牌交换 |
|
||||
| 36 | `isModernModelRef` | 实时 / 冒烟模型匹配 |
|
||||
| 37 | `prepareRuntimeAuth` | 推理前的令牌交换 |
|
||||
| 38 | `resolveUsageAuth` | 自定义用量凭证解析 |
|
||||
| 39 | `fetchUsageSnapshot` | 自定义用量端点 |
|
||||
| 40 | `createEmbeddingProvider` | 由提供商管理、用于 memory/search 的嵌入适配器 |
|
||||
| 41 | `buildReplayPolicy` | 自定义转录重放/压缩策略 |
|
||||
| 42 | `sanitizeReplayHistory` | 在通用清理后应用提供商特定的重放重写 |
|
||||
| 43 | `validateReplayTurns` | 在嵌入式运行器之前进行严格的重放轮次校验 |
|
||||
| 40 | `createEmbeddingProvider` | 面向 memory / search 的提供商自有嵌入适配器 |
|
||||
| 41 | `buildReplayPolicy` | 自定义转录重放 / 压缩策略 |
|
||||
| 42 | `sanitizeReplayHistory` | 通用清理后由提供商负责的重放重写 |
|
||||
| 43 | `validateReplayTurns` | 嵌入式运行器前的严格重放轮次校验 |
|
||||
| 44 | `onModelSelected` | 选择模型后的回调(例如遥测) |
|
||||
|
||||
运行时回退说明:
|
||||
|
||||
- `normalizeConfig` 会先检查匹配的提供商,然后再检查其他具备钩子能力的提供商插件,直到有一个真正修改了配置为止。如果没有任何提供商钩子重写受支持的 Google 系列配置项,内置的 Google 配置标准化器仍会生效。
|
||||
- `resolveConfigApiKey` 在暴露该钩子时会使用提供商钩子。内置的 `amazon-bedrock` 路径在这里也有一个内建的 AWS 环境标记解析器,尽管 Bedrock 运行时认证本身仍使用 AWS SDK 默认链。
|
||||
- `resolveSystemPromptContribution` 允许提供商为某个模型系列注入具备缓存感知能力的系统提示词指导。当某个行为属于单一提供商/模型系列,并且应保留稳定/动态缓存拆分时,优先使用它,而不是 `before_prompt_build`。
|
||||
- `normalizeConfig` 会先检查匹配的提供商,然后再检查其他具备钩子能力的提供商插件,直到某个插件实际修改了配置。如果没有任何提供商钩子重写受支持的 Google 系列配置项,则仍会应用内置的 Google 配置标准化器。
|
||||
- `resolveConfigApiKey` 在公开提供商钩子时会使用该钩子。内置的 `amazon-bedrock` 路径在这里也有一个内建的 AWS 环境变量标记解析器,尽管 Bedrock 运行时认证本身仍然使用 AWS SDK 默认链。
|
||||
- `resolveSystemPromptContribution` 允许提供商为某个模型系列注入具备缓存感知能力的系统提示词指导。当该行为属于某个提供商 / 模型系列,并且应保留稳定 / 动态缓存拆分时,应优先使用它,而不是 `before_prompt_build`。
|
||||
|
||||
有关详细说明和真实示例,请参见[内部机制:提供商运行时钩子](/zh-CN/plugins/architecture-internals#provider-runtime-hooks)。
|
||||
有关详细说明和真实示例,请参阅 [内部机制:Provider Runtime Hooks](/zh-CN/plugins/architecture-internals#provider-runtime-hooks)。
|
||||
</Accordion>
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="添加额外能力(可选)">
|
||||
提供商插件除了文本推理外,还可以注册语音、实时转录、实时语音、媒体理解、图像生成、视频生成、网页抓取和网页搜索。OpenClaw 将其归类为
|
||||
**hybrid-capability** 插件——这是公司级插件的推荐模式(每个供应商一个插件)。请参见
|
||||
提供商插件除了文本推理外,还可以注册语音、实时转写、实时语音、媒体理解、图像生成、视频生成、web 获取和 web 搜索。OpenClaw 将其归类为
|
||||
**混合能力** 插件——这是公司插件(每个厂商一个插件)的推荐模式。参见
|
||||
[内部机制:能力归属](/zh-CN/plugins/architecture#capability-ownership-model)。
|
||||
|
||||
在 `register(api)` 中,与你现有的
|
||||
`api.registerProvider(...)` 调用一起注册各项能力。只选择你需要的标签页:
|
||||
在 `register(api)` 中与你现有的
|
||||
`api.registerProvider(...)` 调用一起注册每种能力。只选择你需要的标签页:
|
||||
|
||||
<Tabs>
|
||||
<Tab title="语音(TTS)">
|
||||
@ -495,10 +524,12 @@ x-i18n:
|
||||
});
|
||||
```
|
||||
|
||||
对于提供商 HTTP 故障,请使用 `assertOkOrThrowProviderError(...)`,这样插件就能共享受限的错误响应体读取、JSON 错误解析以及 request-id 后缀处理。
|
||||
对于提供商 HTTP 故障,请使用 `assertOkOrThrowProviderError(...)`,
|
||||
这样插件就能共享受限的错误响应体读取、JSON 错误解析以及
|
||||
request-id 后缀。
|
||||
</Tab>
|
||||
<Tab title="实时转录">
|
||||
优先使用 `createRealtimeTranscriptionWebSocketSession(...)` —— 这个共享辅助函数会处理代理捕获、重连退避、关闭刷新、就绪握手、音频排队以及关闭事件诊断。你的插件只需要映射上游事件。
|
||||
<Tab title="实时转写">
|
||||
优先使用 `createRealtimeTranscriptionWebSocketSession(...)`——这个共享辅助函数会处理代理捕获、重连退避、关闭时刷新、就绪握手、音频排队以及关闭事件诊断。你的插件只需要映射上游事件。
|
||||
|
||||
```typescript
|
||||
api.registerRealtimeTranscriptionProvider({
|
||||
@ -536,9 +567,10 @@ x-i18n:
|
||||
});
|
||||
```
|
||||
|
||||
通过 POST multipart 音频的批量 STT 提供商应使用
|
||||
通过 multipart 音频进行 POST 的批量 STT 提供商应使用
|
||||
`openclaw/plugin-sdk/provider-http` 中的
|
||||
`buildAudioTranscriptionFormData(...)`。该辅助函数会标准化上传文件名,包括那些为了兼容转录 API 而需要使用 M4A 风格文件名的 AAC 上传。
|
||||
`buildAudioTranscriptionFormData(...)`。该辅助函数会标准化上传文件名,
|
||||
包括那些需要使用 M4A 风格文件名才能兼容转写 API 的 AAC 上传。
|
||||
</Tab>
|
||||
<Tab title="实时语音">
|
||||
```typescript
|
||||
@ -547,9 +579,8 @@ x-i18n:
|
||||
label: "Acme Realtime Voice",
|
||||
isConfigured: ({ providerConfig }) => Boolean(providerConfig.apiKey),
|
||||
createBridge: (req) => ({
|
||||
// Set this only if the provider accepts multiple tool responses for
|
||||
// one call, for example an immediate "working" response followed by
|
||||
// the final result.
|
||||
// 仅当提供商接受一次调用对应多个工具响应时才设置此项,
|
||||
// 例如先返回一个即时的“working”响应,然后再返回最终结果。
|
||||
supportsToolResultContinuation: false,
|
||||
connect: async () => {},
|
||||
sendAudio: () => {},
|
||||
@ -573,10 +604,11 @@ x-i18n:
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="图像和视频生成">
|
||||
视频能力使用**模式感知**结构:`generate`、
|
||||
视频能力使用 **模式感知** 结构:`generate`、
|
||||
`imageToVideo` 和 `videoToVideo`。像
|
||||
`maxInputImages` / `maxInputVideos` / `maxDurationSeconds` 这样的扁平聚合字段不足以清晰表达变换模式支持或禁用模式。
|
||||
音乐生成也遵循相同模式,使用显式的 `generate` /
|
||||
`maxInputImages` / `maxInputVideos` / `maxDurationSeconds` 这样的扁平汇总字段,
|
||||
不足以清晰表达转换模式支持或已禁用的模式。
|
||||
音乐生成功能也遵循相同模式,使用显式的 `generate` /
|
||||
`edit` 块。
|
||||
|
||||
```typescript
|
||||
@ -604,12 +636,12 @@ x-i18n:
|
||||
});
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="网页抓取和搜索">
|
||||
<Tab title="Web 获取和搜索">
|
||||
```typescript
|
||||
api.registerWebFetchProvider({
|
||||
id: "acme-ai-fetch",
|
||||
label: "Acme Fetch",
|
||||
hint: "通过 Acme 的渲染后端抓取页面。",
|
||||
hint: "通过 Acme 的渲染后端获取页面。",
|
||||
envVars: ["ACME_FETCH_API_KEY"],
|
||||
placeholder: "acme-...",
|
||||
signupUrl: "https://acme.example.com/fetch",
|
||||
@ -620,7 +652,7 @@ x-i18n:
|
||||
acme.apiKey = value;
|
||||
},
|
||||
createTool: () => ({
|
||||
description: "通过 Acme Fetch 抓取页面。",
|
||||
description: "通过 Acme Fetch 获取页面。",
|
||||
parameters: {},
|
||||
execute: async (args) => ({ content: [] }),
|
||||
}),
|
||||
@ -640,7 +672,7 @@ x-i18n:
|
||||
<Step title="测试">
|
||||
```typescript src/provider.test.ts
|
||||
import { describe, it, expect } from "vitest";
|
||||
// Export your provider config object from index.ts or a dedicated file
|
||||
// 从 index.ts 或专用文件中导出你的提供商配置对象
|
||||
import { acmeProvider } from "./provider.js";
|
||||
|
||||
describe("acme-ai provider", () => {
|
||||
@ -673,7 +705,7 @@ x-i18n:
|
||||
|
||||
## 发布到 ClawHub
|
||||
|
||||
提供商插件的发布方式与其他任何外部代码插件相同:
|
||||
提供商插件的发布方式与任何其他外部代码插件相同:
|
||||
|
||||
```bash
|
||||
clawhub package publish your-org/your-plugin --dry-run
|
||||
@ -688,7 +720,7 @@ clawhub package publish your-org/your-plugin
|
||||
```
|
||||
<bundled-plugin-root>/acme-ai/
|
||||
├── package.json # openclaw.providers 元数据
|
||||
├── openclaw.plugin.json # 带有提供商认证元数据的清单
|
||||
├── openclaw.plugin.json # 包含提供商认证元数据的清单
|
||||
├── index.ts # definePluginEntry + registerProvider
|
||||
└── src/
|
||||
├── provider.test.ts # 测试
|
||||
@ -697,20 +729,21 @@ clawhub package publish your-org/your-plugin
|
||||
|
||||
## 目录顺序参考
|
||||
|
||||
`catalog.order` 控制你的目录相对于内置提供商的合并时机:
|
||||
`catalog.order` 用于控制你的目录相对于内置
|
||||
提供商的合并时机:
|
||||
|
||||
| 顺序 | 时机 | 使用场景 |
|
||||
| --------- | ------------- | ----------------------------------------------- |
|
||||
| `simple` | 第一轮 | 纯 API 密钥提供商 |
|
||||
| `profile` | 在 simple 之后 | 受认证 profile 控制的提供商 |
|
||||
| `simple` | 第一轮 | 普通 API 密钥提供商 |
|
||||
| `profile` | 在 simple 之后 | 受认证配置文件控制的提供商 |
|
||||
| `paired` | 在 profile 之后 | 合成多个相关条目 |
|
||||
| `late` | 最后一轮 | 覆盖现有提供商(冲突时胜出) |
|
||||
|
||||
## 后续步骤
|
||||
|
||||
- [渠道插件](/zh-CN/plugins/sdk-channel-plugins) — 如果你的插件还提供一个渠道
|
||||
- [SDK 运行时](/zh-CN/plugins/sdk-runtime) — `api.runtime` 辅助函数(TTS、搜索、subagent)
|
||||
- [插件 SDK 概览](/zh-CN/plugins/sdk-overview) — 完整的子路径导入参考
|
||||
- [SDK 运行时](/zh-CN/plugins/sdk-runtime) — `api.runtime` 辅助函数(TTS、搜索、子智能体)
|
||||
- [SDK 概览](/zh-CN/plugins/sdk-overview) — 完整的子路径导入参考
|
||||
- [插件内部机制](/zh-CN/plugins/architecture-internals#provider-runtime-hooks) — 钩子细节和内置示例
|
||||
|
||||
## 相关内容
|
||||
|
||||
@ -1,42 +1,44 @@
|
||||
---
|
||||
read_when:
|
||||
- 你想将 Cloudflare AI Gateway 与 OpenClaw 一起使用
|
||||
- 你需要账户 ID、Gateway 网关 ID 或 API 密钥环境变量
|
||||
summary: Cloudflare AI Gateway 设置(认证 + 模型选择)
|
||||
title: Cloudflare AI Gateway 网关
|
||||
- 你需要账户 ID、Gateway 网关 ID 或 API key 环境变量
|
||||
summary: Cloudflare AI Gateway 设置(凭证 + 模型选择)
|
||||
title: Cloudflare AI Gateway
|
||||
x-i18n:
|
||||
generated_at: "2026-04-23T22:14:43Z"
|
||||
generated_at: "2026-04-27T20:43:33Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: fb10ef4bd92db88b2b3dac1773439ab2ba37916a72d1925995d74ef787fa1c8b
|
||||
source_hash: c7c567076a5b3fea0f09f44d772c0858aed2a4813f91f1cc9f87b0da39c2e5db
|
||||
source_path: providers/cloudflare-ai-gateway.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
Cloudflare AI Gateway 位于提供商 API 前方,可让你添加分析、缓存和控制。对于 Anthropic,OpenClaw 会通过你的 Gateway 端点使用 Anthropic Messages API。
|
||||
Cloudflare AI Gateway 位于提供商 API 之前,让你能够添加分析、缓存和控制功能。对于 Anthropic,OpenClaw 会通过你的 Gateway 网关端点使用 Anthropic Messages API。
|
||||
|
||||
| 属性 | 值 |
|
||||
| ------------- | ---------------------------------------------------------------------------------------- |
|
||||
| 提供商 | `cloudflare-ai-gateway` |
|
||||
| 基础 URL | `https://gateway.ai.cloudflare.com/v1/<account_id>/<gateway_id>/anthropic` |
|
||||
| Base URL | `https://gateway.ai.cloudflare.com/v1/<account_id>/<gateway_id>/anthropic` |
|
||||
| 默认模型 | `cloudflare-ai-gateway/claude-sonnet-4-6` |
|
||||
| API 密钥 | `CLOUDFLARE_AI_GATEWAY_API_KEY`(你通过 Gateway 网关发起请求时使用的提供商 API 密钥) |
|
||||
| API key | `CLOUDFLARE_AI_GATEWAY_API_KEY`(你用于通过 Gateway 网关发起请求的提供商 API key) |
|
||||
|
||||
<Note>
|
||||
对于通过 Cloudflare AI Gateway 路由的 Anthropic 模型,请使用你的 **Anthropic API 密钥** 作为提供商密钥。
|
||||
对于通过 Cloudflare AI Gateway 路由的 Anthropic 模型,请使用你的 **Anthropic API key** 作为提供商密钥。
|
||||
</Note>
|
||||
|
||||
当为 Anthropic Messages 模型启用 thinking 时,OpenClaw 会在通过 Cloudflare AI Gateway 发送负载之前,去除末尾的 assistant 预填充轮次。Anthropic 会拒绝带有扩展 thinking 的响应预填充,而普通的非 thinking 预填充仍然可用。
|
||||
|
||||
## 入门指南
|
||||
|
||||
<Steps>
|
||||
<Step title="设置提供商 API 密钥和 Gateway 网关详细信息">
|
||||
运行新手引导并选择 Cloudflare AI Gateway 认证选项:
|
||||
<Step title="设置提供商 API key 和 Gateway 网关详细信息">
|
||||
运行新手引导并选择 Cloudflare AI Gateway 凭证选项:
|
||||
|
||||
```bash
|
||||
openclaw onboard --auth-choice cloudflare-ai-gateway-api-key
|
||||
```
|
||||
|
||||
这会提示你输入账户 ID、Gateway 网关 ID 和 API 密钥。
|
||||
系统会提示你输入账户 ID、Gateway 网关 ID 和 API key。
|
||||
|
||||
</Step>
|
||||
<Step title="设置默认模型">
|
||||
@ -53,7 +55,7 @@ Cloudflare AI Gateway 位于提供商 API 前方,可让你添加分析、缓
|
||||
```
|
||||
|
||||
</Step>
|
||||
<Step title="验证模型可用">
|
||||
<Step title="验证该模型可用">
|
||||
```bash
|
||||
openclaw models list --provider cloudflare-ai-gateway
|
||||
```
|
||||
@ -76,8 +78,8 @@ openclaw onboard --non-interactive \
|
||||
## 高级配置
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="已认证的 Gateway 网关">
|
||||
如果你在 Cloudflare 中启用了 Gateway 认证,请添加 `cf-aig-authorization` 标头。这是**对你的提供商 API 密钥的额外要求**。
|
||||
<Accordion title="需要身份验证的 Gateway 网关">
|
||||
如果你在 Cloudflare 中启用了 Gateway 身份验证,请添加 `cf-aig-authorization` 标头。这是**除了**你的提供商 API key 之外的额外要求。
|
||||
|
||||
```json5
|
||||
{
|
||||
@ -94,16 +96,16 @@ openclaw onboard --non-interactive \
|
||||
```
|
||||
|
||||
<Tip>
|
||||
`cf-aig-authorization` 标头用于向 Cloudflare Gateway 网关本身进行认证,而提供商 API 密钥(例如你的 Anthropic 密钥)则用于向上游提供商进行认证。
|
||||
`cf-aig-authorization` 标头用于向 Cloudflare Gateway 本身进行身份验证,而提供商 API key(例如你的 Anthropic key)用于向上游提供商进行身份验证。
|
||||
</Tip>
|
||||
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="环境说明">
|
||||
如果 Gateway 网关以守护进程(`launchd`/`systemd`)方式运行,请确保 `CLOUDFLARE_AI_GATEWAY_API_KEY` 对该进程可用。
|
||||
如果 Gateway 网关以守护进程(launchd/systemd)方式运行,请确保 `CLOUDFLARE_AI_GATEWAY_API_KEY` 可供该进程使用。
|
||||
|
||||
<Warning>
|
||||
仅存在于 `~/.profile` 中的密钥不会帮助 `launchd`/`systemd` 守护进程,除非该环境也被导入到那里。请在 `~/.openclaw/.env` 中设置该密钥,或通过 `env.shellEnv` 设置,以确保 Gateway 网关进程可以读取它。
|
||||
如果密钥只存在于 `~/.profile` 中,那么它不会对 launchd/systemd 守护进程起作用,除非该环境也被导入到那里。请在 `~/.openclaw/.env` 中设置该密钥,或通过 `env.shellEnv` 设置,以确保 gateway 进程能够读取它。
|
||||
</Warning>
|
||||
|
||||
</Accordion>
|
||||
@ -113,7 +115,7 @@ openclaw onboard --non-interactive \
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="模型选择" href="/zh-CN/concepts/model-providers" icon="layers">
|
||||
选择提供商、模型引用和故障转移行为。
|
||||
选择提供商、模型引用和故障切换行为。
|
||||
</Card>
|
||||
<Card title="故障排除" href="/zh-CN/help/troubleshooting" icon="wrench">
|
||||
常规故障排除和常见问题。
|
||||
|
||||
@ -6,15 +6,15 @@ read_when:
|
||||
summary: 参考:提供商特定的转录清理与修复规则
|
||||
title: 转录清理规范
|
||||
x-i18n:
|
||||
generated_at: "2026-04-27T07:30:01Z"
|
||||
generated_at: "2026-04-27T20:43:29Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 2836499f6860b0d21a954355850b5a1b89abfc6887df0343a64c12a6be251d29
|
||||
source_hash: be3cef051f872ce2fa8d3e8f9db9c0a7d8a413ca2faa286582ce9bb886e92693
|
||||
source_path: reference/transcript-hygiene.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
OpenClaw 会在运行前(构建模型上下文时)对转录应用**提供商特定的修复**。其中大多数是**仅在内存中**进行的调整,用于满足严格的提供商要求。单独的会话文件修复流程也可能在加载会话之前重写已存储的 JSONL:要么丢弃格式错误的 JSONL 行,要么修复那些语法有效但已知会在提供商重放期间被拒绝的持久化轮次。发生修复时,原始文件会在会话文件旁边备份。
|
||||
OpenClaw 会在运行前(构建模型上下文时)对转录内容应用**提供商特定修复**。其中大多数是用于满足严格提供商要求的**内存中**调整。另有一个独立的会话文件修复流程,可能会在加载会话前重写已存储的 JSONL:要么丢弃格式错误的 JSONL 行,要么修复那些语法有效但已知会在提供商重放时被拒绝的持久化轮次。发生修复时,原始文件会在会话文件旁边备份。
|
||||
|
||||
范围包括:
|
||||
|
||||
@ -23,13 +23,13 @@ OpenClaw 会在运行前(构建模型上下文时)对转录应用**提供商
|
||||
- 工具调用输入验证
|
||||
- 工具结果配对修复
|
||||
- 轮次验证 / 排序
|
||||
- 思考签名清理
|
||||
- Thinking 签名清理
|
||||
- thought 签名清理
|
||||
- thinking 签名清理
|
||||
- 图像负载清理
|
||||
- 用户输入来源标记(用于跨会话路由的提示)
|
||||
- Bedrock Converse 重放时的空 assistant 错误轮次修复
|
||||
- Bedrock Converse 重放的空 assistant 错误轮次修复
|
||||
|
||||
如果你需要转录存储细节,请参阅:
|
||||
如果你需要了解转录存储细节,请参见:
|
||||
|
||||
- [会话管理深度解析](/zh-CN/reference/session-management-compaction)
|
||||
|
||||
@ -37,9 +37,9 @@ OpenClaw 会在运行前(构建模型上下文时)对转录应用**提供商
|
||||
|
||||
## 全局规则:运行时上下文不是用户转录
|
||||
|
||||
运行时 / system 上下文可以被添加到某一轮的模型提示中,但它不是最终用户编写的内容。OpenClaw 会为 Gateway 网关回复、排队的后续操作、ACP、CLI 和嵌入式 Pi 运行保留一个面向转录的独立提示正文。已存储的可见用户轮次使用该转录正文,而不是运行时增强后的提示。
|
||||
运行时 / system 上下文可以添加到某一轮的模型提示中,但它不是最终用户编写的内容。OpenClaw 会为 Gateway 网关回复、排队的后续消息、ACP、CLI 和嵌入式 Pi 运行保留一个面向转录的独立提示正文。存储的可见用户轮次使用该转录正文,而不是运行时增强后的提示。
|
||||
|
||||
对于已经持久化了运行时包装器的旧会话,Gateway 网关历史记录界面会在将消息返回给 WebChat、TUI、REST 或 SSE 客户端之前应用显示投影。
|
||||
对于已经持久化了运行时包装内容的旧会话,Gateway 网关历史记录界面会在将消息返回给 WebChat、TUI、REST 或 SSE 客户端之前应用显示投影。
|
||||
|
||||
---
|
||||
|
||||
@ -52,7 +52,7 @@ OpenClaw 会在运行前(构建模型上下文时)对转录应用**提供商
|
||||
|
||||
该策略使用 `provider`、`modelApi` 和 `modelId` 来决定应用哪些规则。
|
||||
|
||||
与转录清理分开的是:会话文件会在加载前按需修复:
|
||||
与转录清理分开的是,会话文件会在加载前按需修复:
|
||||
|
||||
- `src/agents/session-file-repair.ts` 中的 `repairSessionFileIfNeeded`
|
||||
- 从 `run/attempt.ts` 和 `compact.ts`(嵌入式运行器)调用
|
||||
@ -63,7 +63,7 @@ OpenClaw 会在运行前(构建模型上下文时)对转录应用**提供商
|
||||
|
||||
图像负载始终会被清理,以防止因大小限制而被提供商侧拒绝(对过大的 base64 图像进行缩放 / 重新压缩)。
|
||||
|
||||
这也有助于控制由图像驱动的 token 压力,适用于支持视觉能力的模型。较小的最大尺寸通常会减少 token 使用;较大的尺寸则能保留更多细节。
|
||||
这也有助于控制由图像驱动的 token 压力。较低的最大尺寸通常会减少 token 使用量;较高的尺寸则能保留更多细节。
|
||||
|
||||
实现:
|
||||
|
||||
@ -75,7 +75,7 @@ OpenClaw 会在运行前(构建模型上下文时)对转录应用**提供商
|
||||
|
||||
## 全局规则:格式错误的工具调用
|
||||
|
||||
缺少 `input` 和 `arguments` 两者的 assistant 工具调用块会在构建模型上下文之前被丢弃。这可以防止提供商因部分持久化的工具调用而拒绝请求(例如在速率限制失败之后)。
|
||||
在构建模型上下文之前,缺少 `input` 和 `arguments` 这两者的 assistant 工具调用块会被丢弃。这可以防止因部分持久化的工具调用而导致提供商拒绝(例如在速率限制失败之后)。
|
||||
|
||||
实现:
|
||||
|
||||
@ -86,14 +86,14 @@ OpenClaw 会在运行前(构建模型上下文时)对转录应用**提供商
|
||||
|
||||
## 全局规则:跨会话输入来源
|
||||
|
||||
当一个智能体通过 `sessions_send` 将提示发送到另一个会话时(包括智能体到智能体的回复 / 通知步骤),OpenClaw 会在持久化创建的用户轮次时写入:
|
||||
当一个智能体通过 `sessions_send` 向另一个会话发送提示时(包括智能体到智能体的回复 / 通知步骤),OpenClaw 会将创建的用户轮次持久化为:
|
||||
|
||||
- `message.provenance.kind = "inter_session"`
|
||||
|
||||
此元数据在追加到转录时写入,不会改变角色
|
||||
(为保持提供商兼容性,仍然是 `role: "user"`)。转录读取器可以利用这一点,避免将路由过来的内部提示当作最终用户编写的指令处理。
|
||||
该元数据会在追加到转录时写入,并且不会改变角色
|
||||
(为保证提供商兼容性,`role: "user"` 保持不变)。转录读取器可以利用这一点,避免将路由的内部提示视为最终用户编写的指令。
|
||||
|
||||
在上下文重建期间,OpenClaw 还会在内存中为这些用户轮次添加一个简短的 `[Inter-session message]` 标记作为前缀,以便模型能够将它们与外部最终用户指令区分开来。
|
||||
在重建上下文期间,OpenClaw 还会在内存中为这些用户轮次预添加一个简短的 `[Inter-session message]` 标记,以便模型将其与外部最终用户指令区分开来。
|
||||
|
||||
---
|
||||
|
||||
@ -101,53 +101,54 @@ OpenClaw 会在运行前(构建模型上下文时)对转录应用**提供商
|
||||
|
||||
**OpenAI / OpenAI Codex**
|
||||
|
||||
- 仅进行图像清理。
|
||||
- 对于 OpenAI Responses / Codex 转录,丢弃孤立的 reasoning 签名(后面没有内容块的独立 reasoning 项);在模型路由切换后丢弃可重放的 OpenAI reasoning。
|
||||
- 仅图像清理。
|
||||
- 对 OpenAI Responses / Codex 转录,丢弃孤立的 reasoning 签名(即后面没有跟随内容块的独立 reasoning 项),并在模型路由切换后丢弃可重放的 OpenAI reasoning。
|
||||
- 不进行工具调用 ID 清理。
|
||||
- 工具结果配对修复可能会移动真实匹配的输出,并为缺失的工具调用合成 Codex 风格的 `aborted` 输出。
|
||||
- 不进行轮次验证或重排序。
|
||||
- 会为缺失的 OpenAI Responses 系列工具输出合成 `aborted`,以匹配 Codex 重放规范化。
|
||||
- 不移除 thought 签名。
|
||||
- 缺失的 OpenAI Responses 系列工具输出会被合成为 `aborted`,以匹配 Codex 重放规范化。
|
||||
- 不剥离 thought 签名。
|
||||
|
||||
**OpenAI-compatible Gemma 4**
|
||||
|
||||
- 在重放前移除历史 assistant thinking / reasoning 块,这样本地 OpenAI-compatible Gemma 4 服务器就不会接收到前几轮的 reasoning 内容。
|
||||
- 当前同轮次的工具调用续接会保留附着在工具调用上的 assistant reasoning 块,直到工具结果被重放完毕。
|
||||
- 在重放前剥离历史 assistant thinking / reasoning 块,这样本地 OpenAI-compatible Gemma 4 服务器就不会收到前一轮的 reasoning 内容。
|
||||
- 当前同一轮的工具调用续接会保留附着在工具调用上的 assistant reasoning 块,直到工具结果完成重放。
|
||||
|
||||
**Google(Generative AI / Gemini CLI / Antigravity)**
|
||||
|
||||
- 工具调用 ID 清理:严格字母数字。
|
||||
- 工具结果配对修复和合成工具结果。
|
||||
- 轮次验证(Gemini 风格轮次交替)。
|
||||
- Google 轮次顺序修复(如果历史以 assistant 开始,则预置一个极小的 user 引导消息)。
|
||||
- 轮次验证(Gemini 风格的轮次交替)。
|
||||
- Google 轮次顺序修复(如果历史记录以 assistant 开始,则预添加一个极小的 user 引导消息)。
|
||||
- Antigravity Claude:规范化 thinking 签名;丢弃未签名的 thinking 块。
|
||||
|
||||
**Anthropic / Minimax(Anthropic-compatible)**
|
||||
|
||||
- 工具结果配对修复和合成工具结果。
|
||||
- 轮次验证(合并连续的 user 轮次,以满足严格交替要求)。
|
||||
- 在转换为提供商格式之前,会移除缺失、为空或仅为空白的重放签名的 thinking 块。如果这会导致 assistant 轮次为空,OpenClaw 会使用非空的省略推理文本来保持轮次结构。
|
||||
- 必须移除的旧式仅 thinking 的 assistant 轮次,会被替换为非空的省略推理文本,以避免提供商适配器丢弃该重放轮次。
|
||||
- 轮次验证(合并连续的 user 轮次以满足严格交替)。
|
||||
- 启用 thinking 时,会从发往 Anthropic Messages 负载中剥离尾部 assistant 预填充轮次,包括 Cloudflare AI Gateway 路由。
|
||||
- 缺失、为空或仅为空白的重放签名的 thinking 块会在提供商转换前被剥离。如果这会使 assistant 轮次变空,OpenClaw 会用非空的省略 reasoning 文本保持轮次结构。
|
||||
- 必须被剥离的较旧的仅 thinking assistant 轮次会被替换为非空的省略 reasoning 文本,以便提供商适配器不会丢弃该重放轮次。
|
||||
|
||||
**Amazon Bedrock(Converse API)**
|
||||
|
||||
- 在重放前,将空的 assistant 流错误轮次修复为非空的后备文本块。Bedrock Converse 会拒绝 `content: []` 的 assistant 消息,因此带有 `stopReason: "error"` 且内容为空的持久化 assistant 轮次,也会在加载前于磁盘上修复。
|
||||
- 在 Converse 重放前,会移除缺失、为空或仅为空白的重放签名的 Claude thinking 块。如果这会导致 assistant 轮次为空,OpenClaw 会使用非空的省略推理文本来保持轮次结构。
|
||||
- 必须移除的旧式仅 thinking 的 assistant 轮次,会被替换为非空的省略推理文本,以便 Converse 重放保持严格的轮次结构。
|
||||
- 重放会过滤掉 OpenClaw 投递镜像和 Gateway 网关注入的 assistant 轮次。
|
||||
- 空的 assistant 流错误轮次会在重放前修复为非空的回退文本块。Bedrock Converse 会拒绝 `content: []` 的 assistant 消息,因此,带有 `stopReason: "error"` 且内容为空的持久化 assistant 轮次也会在加载前于磁盘上修复。
|
||||
- 缺失、为空或仅为空白的重放签名的 Claude thinking 块会在 Converse 重放前被剥离。如果这会使 assistant 轮次变空,OpenClaw 会用非空的省略 reasoning 文本保持轮次结构。
|
||||
- 必须被剥离的较旧的仅 thinking assistant 轮次会被替换为非空的省略 reasoning 文本,以便 Converse 重放保持严格的轮次结构。
|
||||
- 重放会过滤 OpenClaw 投递镜像和 Gateway 网关注入的 assistant 轮次。
|
||||
- 图像清理通过全局规则应用。
|
||||
|
||||
**Mistral(包括基于 model-id 的检测)**
|
||||
**Mistral(包括基于 model id 的检测)**
|
||||
|
||||
- 工具调用 ID 清理:strict9(长度为 9 的字母数字)。
|
||||
|
||||
**OpenRouter Gemini**
|
||||
|
||||
- Thought 签名清理:移除非 base64 的 `thought_signature` 值(保留 base64)。
|
||||
- thought 签名清理:剥离非 base64 的 `thought_signature` 值(保留 base64)。
|
||||
|
||||
**其他所有情况**
|
||||
|
||||
- 仅进行图像清理。
|
||||
- 仅图像清理。
|
||||
|
||||
---
|
||||
|
||||
@ -157,15 +158,14 @@ OpenClaw 会在运行前(构建模型上下文时)对转录应用**提供商
|
||||
|
||||
- 一个 **transcript-sanitize extension** 会在每次构建上下文时运行,并且可以:
|
||||
- 修复工具使用 / 结果配对。
|
||||
- 清理工具调用 ID(包括会保留 `_` / `-` 的非严格模式)。
|
||||
- 运行器也会执行提供商特定的清理,导致工作重复。
|
||||
- 提供商策略之外还存在额外变更,包括:
|
||||
- 在持久化前从 assistant 文本中移除 `<final>` 标签。
|
||||
- 清理工具调用 ID(包括一种保留 `_` / `-` 的非严格模式)。
|
||||
- 运行器也会执行提供商特定清理,这造成了重复工作。
|
||||
- 提供商策略之外还会发生其他变更,包括:
|
||||
- 在持久化前从 assistant 文本中剥离 `<final>` 标签。
|
||||
- 丢弃空的 assistant 错误轮次。
|
||||
- 在工具调用后裁剪 assistant 内容。
|
||||
|
||||
这种复杂性导致了跨提供商回归(尤其是 `openai-responses`
|
||||
`call_id|fc_id` 配对)。2026.1.22 的清理工作移除了该扩展,将逻辑集中到运行器中,并使 OpenAI 除图像清理外变为**不触碰**。
|
||||
这种复杂性导致了跨提供商回归(尤其是 `openai-responses` 的 `call_id|fc_id` 配对)。2026.1.22 的清理工作移除了该扩展,将逻辑集中到运行器中,并使 OpenAI 除图像清理之外保持**不触碰**。
|
||||
|
||||
## 相关内容
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user