OpenClaw Model Manager:让我不用再手改模型路由 JSON 的 GUI

发布日期
2026年7月11日
作者
Jacob Lloyd —— 项目完成后,在 AI 协助下撰写
阅读时长
约 9 分钟阅读

简单来说: 一个免费的桌面应用,给我家里的 AI 系统配上了一块像样的控制面板,取代了原来那种有风险的手改配置文件方式。它能显示每个助手正在用哪个 AI「大脑」,点一下就能切换,而且拒绝保存任何会把系统弄坏的内容。它的诞生原因很简单:曾经有一次打错一个字,就悄无声息地让一个助手掉线了。

我曾经在 JSON 文件里把一个模型 ID 打错了字,结果用这个模型的智能体就这么悄无声息地哑火了。没报错,没崩溃。它就那么坐在那儿,对着一个根本不存在的模型自说自话,而我却在别处满世界找一个"更有意思"的 bug。这个应用,就是我给自己定下的"绝不再犯"。

TL;DR

  • 这是什么:一个 GTK4/libadwaita 桌面应用,用来编辑 openclaw.json——这份配置决定了我 OpenClaw 系统里每个智能体、子智能体和 cron 任务该和哪个 LLM 对话。
  • 费用:免费,MIT 协议,源码在下面的 zip 里。
  • 需要什么:装了 GTK4 + libadwaita + PyGObject 的 Linux(包管理器一行命令搞定)、Python 3.11 以上,还有一套 OpenClaw 安装——没有的话,用自带的示例配置从零开始也行。
  • 最终得到什么:一屏看全所有智能体模型的仪表盘、既不会写坏文件也不会指派死模型的保存机制,以及一个点一下就能把 Claude Code CLI 路由到免费本地模型、便宜的 DeepSeek,或者真金白银计费的 Anthropic 的开关。

最终得到什么

先看截图。这些截图来自一个沙盒环境,跑的是用完即弃的 HOME 目录里的一份假配置。应用是真的,数据是假的,里面没有我的任何密钥。

OpenClaw Model Manager 主窗口,显示 Model Usage 模型清单、Connectivity and Routing 连接与路由状态面板,以及按颜色区分的 API/本地默认配置
主窗口:所有智能体的模型一屏看全,外加每个供应商的实时连接状态。

主窗口回答的问题,以前得靠 grep JSON 才能搞清楚:哪个模型跑在哪里,又要花多少钱?每个智能体、整套系统的默认值、子智能体的覆盖设置、cron 任务,甚至连相邻的一个邮件智能体用的模型也在内。每一条都带一个颜色标签:Local(这台机器)、Remote(第二台机器),或者 Cloud(会出现在账单上的那种)。

Set Models for All Agents 批量应用面板,以及带模式选择器的 Coding Helper 区块,还有一条提示——这台机器上 Cloud 模式没有可用密钥的实时警告
把一个模型批量应用到所有智能体,或者挑选 Coding Helper 的后端。选的模式实际上跑不起来时,应用会发出警告。
Model Catalog 视图,列出每个模型的费用、上下文长度和是否支持推理,还有 Add LM Studio Model 和 Add Anthropic Model 按钮
模型目录:每个模型的费用、上下文长度、是否支持推理,还有一个能问 LM Studio 实际加载了什么模型的发现按钮。

为什么会做这个

OpenClaw 是我在家里跑的多智能体系统:好几个 AI 智能体,各自指向一个模型,有的本地免费,有的云端计费。所有路由都集中在一个文件里,~/.openclaw/openclaw.json:模型目录、每个智能体的主/备选分配、供应商配置,还有网关自己的鉴权令牌。手改这个文件,老是在两个地方栽跟头。

第一,写错的模型 ID 会悄无声息地失败。有一次某个陈旧的默认值就把一个智能体指向了 vllm/google/gemma-4-31b-qat——这个模型供应商压根没提供过。格式不对的保存更糟:一处改错,整个网关就崩溃循环。

第二,在不同后端之间切换 Claude Code CLI,靠的是看不见的环境变量手术。OpenClaw 会为编码任务拉起 Claude Code,而这些请求发去哪里、账单算在谁头上,是由网关 systemd unit 上的 ANTHROPIC_* 环境变量决定的。在免费本地、便宜的 DeepSeek 和真正的 Anthropic 之间来回切换,以前每次都得手写一个 systemd drop-in。这种事,正是我晚上 11 点最容易搞错的类型。

保存流程

我需要能信得过的,是点下 Save 之后到底发生了什么。按顺序如下:

有两个步骤扛着大梁。校验会拒绝任何供应商未公布过的模型 ID,这让开头那种打错字的 bug 从"要靠自己留神检查"变成"结构上根本不可能发生"。而原子写入的存在,是因为 openclaw.json 里存着网关的鉴权令牌,必须一直保持 chmod 600:临时文件在写入任何内容之前就先获得原文件的权限,然后 fsync,再重命名覆盖原文件。哪怕保存到一半崩溃,旧文件也丝毫无损。

一次糟糕的保存,离撤销只差一次 rename,而且你留着的是五代历史,不是一代。

Coding Helper 的 drop-in

切换 Claude Code CLI 的路由是单独一条流程,因为它完全不碰 openclaw.json。它写的是一个 systemd drop-in,在网关拉起 Claude Code 之前先覆盖它的环境变量。

四种模式,一个下拉菜单:LM Studio(免费、本地)、通过其 Anthropic 兼容端点接入的 DeepSeek(便宜)、Anthropic Cloud(默认选项:完全没有 drop-in,什么都不覆盖),或者 Disabled——这个选项会把 CLI 指向 http://127.0.0.1:9/blocked,让每一次调用都快速失败而不是干等着。还有一个一键实时测试,会向 LM Studio 或 DeepSeek 发一个真正符合 Anthropic 格式的 ping,并报告到底是哪个模型应答了。你信的不是一个配置界面,而是一次刚刚发生过的真实请求。

让 API 密钥远离 unit 文件

DeepSeek 模式需要一个 API 密钥,而 systemd 的 unit 文件是放密钥的糟糕地方:直接写进去的东西,在磁盘上和 systemctl show 的输出里都是明文。所以这个 drop-in 里从来不含密钥本身,写的是这个:

ExecStart=/usr/bin/bash -c 'export ANTHROPIC_API_KEY="$$DEEPSEEK_API_KEY"; exec <gateway cmd>'

诀窍在 $$。在 unit 文件里,$$ 会被转义成一个字面的 $。如果不这么写,systemd 会在拼装命令行的时候自己把变量展开,真正的密钥就会出现在进程的 argv 里,ps 一下就能看到。用两个美元符号,bash 收到的就是字面意义上的 $DEEPSEEK_API_KEY,并在运行时从网关的 EnvironmentFile(~/.openclaw/gateway.systemd.env,chmod 600)里展开它。这个密钥不会出现在 unit 文件里,不会出现在 systemctl show 里,也不会出现在进程列表里——只存在于那一个进程自己的 bash 环境中。zip 包里的 examples/ 文件夹用 CHANGE_ME 占位符记录了这套写法。

安装设置

摘自 zip 里附带的 README:

# 1. Install GTK4 + libadwaita + PyGObject from your distro's packages
#    (one dnf/apt line — see README-SETUP.md for the exact package names)

# 2. Install the app and its launcher
install -Dm755 openclaw-model-manager ~/.local/bin/openclaw-model-manager
# .desktop file goes to ~/.local/share/applications/

# 3. If you don't already have an OpenClaw config:
cp examples/openclaw.json.example ~/.openclaw/openclaw.json
chmod 600 ~/.openclaw/openclaw.json
# then replace every CHANGE_ME placeholder inside it

# 4. Optional — API keys, both chmod 600, examples provided:
#    ~/.openclaw/.env
#    ~/.openclaw/gateway.systemd.env

除了 PyGObject,不需要额外的 pip 安装;其余全是 Python 3.11+ 的标准库,包括 tomllib。整个应用就是一个可执行脚本(164KB,3,570 行)、一个 .desktop 启动器、一份 README、一份 MIT 许可证,加上四份示例配置。压缩成 zip 只有 49KB。

踩过的坑

  • Cloud 模式的意思是"没有 drop-in",不代表"一定用的是我自己的 Anthropic 账户"。它什么都不覆盖,所以 unit 里原本配置好的东西会照常运行。选中的模式没有可用密钥时应用会警告,但还是要自己确认一下。
  • 这个 drop-in 会屏蔽你真正的 Anthropic 密钥,这是故意的设计。Local 模式会给网关拉起的所有东西都设上 ANTHROPIC_API_KEY=lm-studio。在我这台机器上,这曾经悄悄把我交互式的 claude CLI 别名也重新路由到了 LM Studio——Claude Code 看起来"照常在工作",答案却是本地模型给的。如果 Claude 的回答开始不对劲,先运行 systemctl --user cat openclaw-gateway.service 找找有没有 drop-in,再去怀疑模型本身。
  • openclaw update 改动了网关的 ExecStart 之后,重新选一次 DeepSeek 模式,好把新命令重新包一层。应用会从 unit 片段里读取权威的 ExecStart,并识别出自己的包装痕迹(靠的是 index.js 加上没有 $$DEEPSEEK_API_KEY 来判断),所以不会出现二次包装——但它也不会主动去修一条没被要求重新检查的命令。
  • 本地模型的安全默认值是 reasoning: true一个会输出 reasoning_content 却被配置成 reasoning: false 的模型,在网关看来就是卡住了:大约 390 秒的沉默,然后被 kill。对不做推理的模型来说,这个开关开着也无害,所以新增模型对话框默认就是开的。这个坑真的让我调试掉了不少时间。
  • 非空的 plugins.allow 是一份严格的白名单。某个插件条目上的 enabled: true 不起任何作用,除非它的 id 也在 allow 里。应用能正确读出这一点,但它刻意从不写入任何 plugins.*,所以插件行为异常时,这不是能告诉你原因的工具。
  • 网关自己也会改写 openclaw.json(身份校准、openclaw update)。应用会追踪文件的 mtime,在覆盖一次外部编辑之前发出警告,保存前的备份保留的是磁盘上实际存在过的内容。
  • 模型 ID 的格式是 provider/raw-id没有斜杠的裸 ID,会通过本地的 LM Studio 端点来解析。这不是错误,只是一个值得了解的约定——省得你去找一个根本不存在的 provider 字段。

下载

仅限个人使用免费。如果它替你省下了一下午的时间,欢迎点旁边的咖啡按钮支持一下。


← 更多工具与下载