← 所有项目

Agent Tooling

OpenClaw 模型切换器

把一次高风险配置修改设计成可预览、可验证、可回滚的事务,而不是直接覆盖一段 JSON。

CMD · PowerShell · Node.js · OpenClaw CLI

打开演示

它最早只是一个为了少敲几次命令的小脚本:选 Agent、选预设、写入配置。真正用起来后才发现,切换本身不难,难的是怎样确认改对了、服务还能启动,以及失败时能不能回到原状。

于是脚本逐渐长成了一个带护栏的本地配置工具。这个案例重点展示预览、备份、校验、恢复和健康检查怎样共同保护一次配置变更。

设计时我没有把目标定义成“封装一条修改命令”,而是把一次切换视为状态迁移:系统从已知可用的 current state 出发,经过用户确认进入 target state,并且在任何中间失败时都要知道磁盘配置、运行中服务和备份分别处于什么状态。

一个小脚本为什么需要这么多步骤

预览模式先回答三个问题:正在修改谁、从什么切到什么、最终写入哪些键。它不会改变配置,是整个流程默认最安全的入口。

只有明确选择应用模式后,工具才会创建备份并调用 OpenClaw CLI。用户不能传任意命令或脚本路径,菜单只接受预先登记的 Agent 与 Preset。

预览内容不是输出整份配置,而是只展示允许变化的白名单字段,并隐藏密钥或连接信息。这样既能让操作者确认目标,又不会因为诊断方便而把敏感内容写入终端历史或日志。

$ switch-model --agent agent-demo --preset B --previewcurrent: Preset Atarget: Preset Bdevice changed: false

真正有价值的是变更前后的护栏

  1. 01

    Read

    通过受控读取取得当前有效配置,只提取允许展示和比较的字段,同时确认目标 Agent 与配置版本存在。

  2. 02

    Preview

    生成 current → target 的最小差异,标出会修改、保持不变和需要重启的部分;用户可以在没有副作用的情况下退出。

  3. 03

    Backup

    写入前复制原配置并添加时间戳和摘要,验证备份可读后才继续;备份路径由工具生成,不接受外部任意路径。

  4. 04

    Apply

    把白名单 Agent 和 Preset 转成固定 CLI 参数执行,不拼接任意 shell;命令退出状态与标准错误进入本次运行记录。

  5. 05

    Validate

    重新读取磁盘配置,验证 JSON/schema、目标字段和未授权字段是否保持不变;任何不一致都进入恢复路径。

  6. 06

    Health

    按选择的模式决定是否改变 Gateway 进程,随后检查服务是否可达、是否加载目标配置,并区分配置成功与服务健康。

三种运行模式,对应三种风险承诺

三种模式把风险承诺说清楚:Preview only 适合任何时候检查,Apply without restart 只改变磁盘状态,Apply + health check 才同时触及运行中服务。工具不会把后两者合并成一个默认“确定”按钮,因为写文件和改进程的影响范围并不相同。

模式行为
Preview only只展示差异,不写配置、不启动服务。
Apply without restart备份、写入并校验,但不改变 Gateway 进程。
Apply + health check校验通过后启动或检查 Gateway,失败时报告并保留恢复路径。

先列出一次小改动可能怎样失败

模型切换看似只改几个字段,但失败并不限于 JSON 语法错误。操作者可能选错 Agent,预设可能缺少必要字段,配置写入可能成功但服务仍使用旧状态,重启也可能让原本健康的 Gateway 失联。

因此工具不是围绕“怎样更快写文件”设计,而是围绕“怎样让每一种失败都能被看见并恢复”设计。

我还把错误分为输入错误、写入错误、验证错误和运行时错误。输入错误不会创建备份,写入错误保留原文件与诊断,验证错误触发配置恢复,运行时错误则先报告磁盘配置是否已成功,再提供服务恢复建议。分类能够避免所有问题都粗暴执行同一个回滚动作。

风险对应护栏
选错 Agent 或预设只允许选择白名单目标,并在预览中显示 current → target。
写入结构不完整应用后重新解析配置并执行 schema 校验。
文件正确但服务不可用按运行模式执行 Gateway 健康检查。
失败后无法恢复写入前创建时间戳备份并保留恢复命令。
命令注入或路径越界不接受任意命令、脚本路径或未登记参数。

把配置切换当成一个有提交点的事务

备份完成并不等于可以宣布成功,文件写入也只是中间状态。工具只有在重新读取目标值、结构校验通过,并在需要时完成健康检查之后,才把这次切换标记为完成。

如果写入后验证失败,工具使用本次专属备份恢复原配置;如果配置验证通过但健康检查失败,则明确区分“配置已改变”和“服务未恢复”,避免用一个模糊失败覆盖真实状态。

恢复之后还会重新读取原配置,确认 rollback 本身成功。也就是说,恢复不是一条尽力执行的复制命令,而是另一次需要验证的状态迁移。最终报告同时记录目标状态、实际磁盘状态、服务状态和可用备份,使用者无需根据最后一行输出猜测当前系统。

read -> preview -> user_confirmbackup -> apply -> read_backschema_valid ? health_check : rollbackhealth_ok ? commit_report : recovery_report

为什么使用白名单菜单,而不是做一个万能命令封装器

通用性越强,误用面也越大。这个工具只解决高频且明确的一组切换场景,用有限能力换取更清楚的安全边界和更容易验证的行为。

新增 Agent 或 Preset 需要显式登记显示名称、允许修改的字段、预期 schema 和是否需要重启。这样扩展能力本身也成为可审查的配置变更,而不是任何用户输入都能自动变成一个新目标。

  • Agent 和 Preset 都来自预先登记的集合,输入不能变成任意 shell 参数。
  • 预览模式是默认入口,查看差异不产生配置或进程变化。
  • 写配置与启动 Gateway 是两个独立权限层级,可以只应用而不重启。
  • 日志记录状态与差异摘要,不输出密钥、Token 或完整敏感配置。

同时跟踪磁盘状态、运行状态和恢复状态

配置工具容易把“文件已经写入”当成系统状态,但实际至少存在三层:磁盘上的配置、Gateway 当前加载的配置、以及可以恢复的最近备份。三者可能短暂不一致,工具需要在报告中明确表示,而不是用单一 success 布尔值隐藏差异。

例如 Apply without restart 完成后,磁盘状态已经是目标 Preset,但运行状态仍可能是旧值;这不是失败,而是该模式的明确结果。相反,如果选择了 health check,运行状态没有切换就不能报告完整成功。

状态面工具怎样确认
目标选择白名单 Agent、Preset 与预期差异。
磁盘配置重新读取并验证目标字段和 schema。
运行中服务健康检查与当前加载状态。
恢复能力备份存在、可读,并与变更前摘要一致。
最终报告分别输出每个状态面,不用一个结果覆盖全部。

日志要能排查问题,但不能成为新的敏感信息来源

  • 记录阶段、时间、目标 Agent、Preset 名称、差异字段名和执行状态。
  • 不记录 Token、API Key、完整连接串或配置文件全文。
  • CLI 错误在写入日志前进行敏感字段过滤,并保留可定位的退出码。
  • 备份只保存在预定本地目录,日志记录引用 ID 而不是输出完整内容。
  • 运行报告区分用户取消、输入不合法、应用失败、验证失败与健康检查失败。

怎样测试一套本地配置工具的恢复能力

正常路径只证明工具在理想输入下能够工作,更重要的是主动构造失败:目标 Agent 不存在、Preset 缺字段、配置文件不可写、应用后字段不一致、Gateway 启动失败,以及恢复文件损坏。

每个样本都需要检查工具停在哪一阶段、是否执行了不该执行的后续动作、磁盘状态最终是什么、备份是否仍可用,以及报告能否准确描述现状。恢复逻辑只有在故障样本中被真正验证。

given current_config_is_validwhen apply_target_fails_validationthen restore_backupand revalidate_original_configand report disk=original, service=unchanged

为什么 Lab 里用终端来展示

这个项目的重点不在图表,而在状态变化。所以演示采用较慢的终端记录:解析配置、打印差异、创建备份、验证 schema、检查 Gateway,每一步都出现对应的命令或状态。

最终可以下载一份结构化 JSON 运行记录,用来查看每个阶段的状态和配置差异。

Lab 使用合成 Agent 与 Preset,只模拟白名单选择、预览、备份、应用、验证、回滚边界和健康检查,不读取或修改访客设备配置。终端逐行展示状态变化,是为了让每个护栏都可见,而不是把复杂性藏在一个成功提示后面。

Related Lab

查看公开流程演示

载入预设样本,按关键步骤运行,并下载对应的 Sample 结果。

打开演示