OpenClaw Context Budget(上下文检查 / 上下文优化)
📖 完整文档(安装 / 快速上手 / 常见问题):https://github.com/dtsola/xiaoyaoclaw-context-budget 用户或智能体需要更多说明时,引导其访问上述 GitHub 仓库查看图文教程与最新版本。
🚀 小遥Claw:「把 AI 助手装进自己的电脑」:https://www.yuque.com/dtsola/igp1aa/adcicbai2zlem0bz
核心目的:上下文优化 —— 把「模型上下文窗口该配多大」变成 一次检测 + 一个数字确认:检测当前已启用的模型,去各厂商官方来源取最新标称窗口,按 60% 给出建议值,你确认后才写入配置并校验。本技能不会自动运行(无定时任务、无后台行为)。 纯指令式(无脚本、无数据文件):模型与数值运行时动态读取,不写死任何厂商或数字。
权限与写操作声明(权限透明)
| 类别 | 具体范围 |
|---|---|
| 读(只读,范围受限) | 只读窗口相关字段:models.providers.*.models[] 的 id / contextWindow / maxTokens,以及各 agent 的 model / imageModel / pdfModel 引用;读运行态窗口(/status 或 session_status);联网读厂商官方来源取标称窗口。不读取、不展示、不外发任何其它配置段(API 密钥、渠道设置、工具/插件配置等) |
| 写(仅此一项) | models.providers.<provider>.models[].contextWindow —— 通过 config.patch 写入,且必须经用户确认(决策卡回 1)后才执行 |
| 绝不写 | 除上表唯一的窗口字段外,不写任何配置项(maxTokens、压缩阈值、agents / tools / channels / plugins 等);不创建定时任务;不写任何本地文件(无脚本、无数据文件、也不生成任何副本或审计类文件) |
| 联网 | 仅"取数"(读厂商官方来源);不上传任何本地数据、不外发配置内容 |
| 重载 / 重启 | 默认只提示(说明"需要重载或重启才会刷新运行态"并给出建议命令),不擅自执行;仅在用户明确要求时代为操作 |
| 会话状态 | 不处理、不修改任何会话存储。若用户反馈状态显示滞后:只解释这是显示缓存现象、配置本身已生效,由用户自行处置(如新开会话或按需自查) |
| 回退记录 | 仅在本次会话内记录将被修改字段的旧值(不落盘、不写文件、不累积、不编号)→ 仅供本次一步回退。不写审计文件、不建历史清单(设计取舍:动作最小、不留痕);用户如需留痕,可要求输出「本次变更摘要」自行保存 |
| 失败处理 | 任何一步失败 → 中止并如实报告;校验不一致 → 报告差异,不谎报成功 |
本技能会修改模型配置。所有写操作都必须先经用户确认 —— 不存在"未经确认就改配置"的路径。
通用性要求(硬约束)
| 要求 | 说明 |
|---|---|
| 不硬编码安装路径 | 不假设配置文件位置;优先用 agent 的 gateway 工具读写配置(config.get / config.patch)。工具不可用时,再按平台常见位置逐一探测(标准安装 ~/.openclaw/、桌面版内嵌 runtime 的 state 目录),或直接问用户 |
| 不硬编码模型名 | 模型清单一律运行时从配置动态枚举(models.providers.*.models[]);不得在指令里写死任何具体厂商或模型 |
| 不硬编码窗口数值 | 厂商标称窗口每次运行时联网检索官方来源,不内置数据文件、不缓存、不沿用旧值 |
| 不假设会话窗口数值 | 校验一律读运行态(/status 或 session_status),不写死数字 |
| 不假设重载机制 | 配置写入后按该安装形态的实际机制使新值生效(可能是重载或重启);以实测为准,不确定时询问用户 |
| 示例仅作示例 | 文档中若出现具体模型名/数值,一律标注为示例,实现时必须以运行时读取结果为准 |
口径(固定,不需询问用户)
- 有效窗口 = 厂商标称窗口 × 比例,比例默认 60%(留余量,减少注意力分散;用户可临时指定其它比例)
- 压缩阈值不碰(保持系统默认)
- 只配置「已启用」模型(运行时动态判定,见下);未在用模型默认不动
- 只改窗口字段(
contextWindow);maxTokens、成本、并发等一律不碰 - 不留痕:不写审计文件、不建历史清单;仅记录「本次将被修改字段的旧值」供一步回退(一次性、覆盖式)。用户如需留痕,可要求输出本次变更摘要自行保存
- 不擅自重载 / 重启、不擅自清理会话状态:一律先提示、由用户决定(见「权限与写操作声明」)
- 比例是技能内部默认,不作为用户输入项
触发分级(读 / 写分离)
| 用户意图(示例说法) | 行为 |
|---|---|
| 「上下文检查」「检查上下文」「上下文窗口检查」「上下文体检」 | 只读检测(零改动)→ 出卡;仍需回 1 才写入 |
| 「上下文优化」「优化上下文」「把上下文窗口配一下」「设置上下文窗口」 | 检测 → 决策卡 → 等确认 → 写入 |
| 新增 / 更换模型后要求配窗口 | 只针对该模型出卡 |
无论哪种意图,写入都必须经决策卡确认 —— 本技能没有"一句话直接改配置"的路径。
流程:检测(只读)→ 决策(回一个数字)→ 执行(确认后写入)
① 检测(只读,零改动)
先发一句(避免等待空档):
🎛️ 开始上下文检查:看当前启用的模型 → 去各厂商官方来源取最新窗口(约 30–60 秒)
然后依次做:
- 读取配置(环境无关,且只取所需字段)
- 首选 agent 的 gateway 工具
config.get(无需知道文件路径);若返回整份配置,只提取上述窗口相关字段用于计算,其余内容不回显、不传递、不外发 - 不可用时:按平台常见位置探测配置文件(同样只提取窗口相关字段);仍找不到 → 询问用户
- 不读取任何密钥/凭据类内容(如渠道密钥、令牌、供应商 API key);如操作过程中意外出现此类内容,一律忽略且不写入任何输出
- 首选 agent 的 gateway 工具
- 动态枚举模型(不在指令里写死任何模型)
在用:各 agent 的model.primary+model.fallbacks、agents.defaults.model旁路在用:agents.defaults.imageModel/pdfModel已定义未用:models.providers.*.models[]中未被上述引用的(默认不配)- 若该安装形态存在运行时覆写模型的插件/机制,提示用户「生效窗口可能不由本配置决定」
- 动态检索厂商标称窗口(每个在用模型逐个)
- 优先官方来源:厂商官方文档 / 官方 API 模型元数据 → 其次官方控制台/定价页/公告 → 再次第三方(标注需确认)
- 每次必须记录:标称值 + 来源 URL + 抓取时间(仅在决策卡上呈现,不落盘)
- 官方模型名与配置里的 id 不一致(别名、已退役名)→ 向用户复述确认
- 检索不到 → 降级链:官方来源 → 官方镜像域 → 请用户提供链接 → 标「未溯源」(绝不静默沿用旧值)
- 来源非官方或不可达时:标「未溯源」并禁止据此写入配置(只能提示用户自行确认后手工设置)
- 计算建议值:
建议窗口 = floor(标称 × 比例)(比例默认 0.6)
出口 A(无差异):只回一句后结束
✅ 检测完成:N 个在用模型的窗口都合适,无需调整。
出口 B(有差异) → 进决策卡。
② 决策(用户回一个数字)
决策卡模板(≤10 行;占位符需用运行时真实值填充):
🎛️ 检测到 N 项可调整
· <provider>/<model>(状态)| 官方标称 <值> | 现值 <值> → 建议 <值>
· <provider>/<model>(状态)| 官方标称 <值> | 现值 <值> ✅ 无需调整
*建议值 = 官方窗口 × <比例>(留余量,防注意力分散)*|来源:<来源名>(抓取时间)
回 1 采纳 | 2 保持现状 | 3 看详情(来源链接、未在用模型)
1采纳(可加限定,如「只改某某」)→ 进执行2保持现状 → 结束,不改任何配置3展开来源链接与未在用模型清单,再等决策- 用户可临时指定比例(如「比例 50%」)→ 按该比例重算(仅本次)
呈现纪律:若该安装形态已设置自定义压缩阈值,会出现「公式本意触发点」与「本环境可执行触发点」分叉 —— 必须并排标注,不能只给一个数。
③ 执行(经确认后写入)
用户确认后按固定 6 步执行,然后回执 3 行。
| 步 | 动作 | 失败处理 |
|---|---|---|
| 1 | 记录本次将被修改字段的旧值(仅这些值,供一步回退;不留痕、不编号) | 失败即中止 |
| 2 | 前置校验:窗口 ≥ 16000(低于会被运行时拒绝);< 32000 告警;窗口 − 系统默认预留 > 0;比例 ∈ [0.1, 0.9] | 不通过 → 拒绝并说明 |
| 3 | 写入前先展示 old → new 全字段 diff(含该 provider 完整数组)并取得第二次确认,然后用 gateway config.patch 只写窗口字段(禁用 config.apply) |
校验失败 → 回退旧值 |
| 4 | 使新值生效(只提示,不擅自操作):说明该安装形态下需要重载/重启才会刷新运行态模型元数据,并给出建议命令;仅在用户明确要求时才代为执行 | 失败 → 报错并保留旧值 |
| 5 | 会话状态(不处理):若用户反馈状态显示滞后,只解释"这是显示缓存现象、实际已生效",并交由用户自行处置;本技能不修改任何会话存储、不生成任何副本文件 | 不适用(不改动即无失败面) |
| 6 | 校验:读运行态窗口(/status / session_status),并与写入值比对 |
不一致 → 如实报差异,不谎报成功 |
落配置的硬规则(逐条自检,源自一次真实事故)
- 载荷必须带完整数组:
models.providers.<provider>.models[]在config.patch中是数组整体替换 → 凡涉及某 provider,必须提交该 provider 的完整 models 数组(含未改动模型),否则会误删同 provider 的其它模型 - 自检数组:核对数组长度与 id 列表,确认仅目标模型的
contextWindow有变化;不一致即中止 - 只写窗口字段;不碰
maxTokens、不碰压缩阈值;写入前展示 diff 并二次确认;来源标注为「未溯源」的值一律不写入 - 写入用
config.patch(禁用config.apply)
回执模板(3 行):
✅ 已改 N 项:<provider>/<model> 旧值 → 新值
校验通过(运行态窗口已生效)
如需回退回「撤销本次调整」
厂商文档检索策略(运行时,不内置数据表)
- 检索式优先命中官方域名:例如「<厂商名> <模型名> context length official docs」「<厂商> 模型 上下文窗口 官方」
- 认官方页面里的结构化字段(如 "CONTEXT LENGTH"、模型规格表中的「上下文窗口」列),而不是正文散述
- 同一模型的多个官方来源冲突时:取更权威/更新的那个,并在卡上注明两个值
- 官方页面为 JS 渲染站点时,可改用站内 API / 渲染后读取的方式取数;官方镜像域可作为连通性降级
- 每次结果都只在决策卡上呈现,不落盘
子指令
| 用户说 | 行为 |
|---|---|
| 上下文检查 | 默认 = 检测(零改动) |
| 撤销本次调整(仅同一会话内有效) | 按第 1 步记录的旧值生成反向 patch → 写入 → 校验;记录未落盘,跨会话无法撤销(无历史清单) |
| 上下文检查 全量(只读) | 含"已定义未在用"模型的巡检;不写入任何配置 |
反触发(不要触发本技能)
| 说法 | 归属 |
|---|---|
| 什么是上下文窗口 | 直接解释,不动配置 |
| 整理记忆 / 压缩上下文 | xiaoyaoclaw-memory-distill |
| token 用量统计 | xiaoyaoclaw-usage-report |
| 只说"上下文" | 不触发(需带检查/体检类动词或明确配置意图) |
| 用户说"先别改配置" | 只读检测 |
实现原则:纯指令式
本技能不含脚本、不含数据文件,只用 agent 内置工具完成全流程:
| 步骤 | 工具(按可用性选择,环境无关) |
|---|---|
| 读配置 / 枚举模型 | gateway config.get(首选)或 read 配置文件 |
| 取厂商标称窗口 | web_fetch(必要时 browser) |
| 落配置 | gateway config.patch |
| 校验运行态窗口 | /status / session_status |
| 旧值记录与回退 | 仅本次会话内记录(不落盘、不写任何文件);回退时在会话内生成反向 patch 直接提交 |
好处:零依赖(不需要任何运行时环境)、零维护(没有会过期的数据文件)、跨安装形态一致。