bml.asia · 纯文字 · 写写停停

折腾 Agent 大半年,配置文件我还是更信 JSON

  本来只想给本地 Agent 换个模型,结果又在配置文件上耗掉一晚上。

  这台机器上跑着三套 Agent 框架——OpenClaw、Hermes、DeepSeek Harness。大半年用下来,光"配置文件怎么写得舒服"这一个问题,就够写篇长文了。今天趁热,把这阵子的感想记下来。

  先把结论放这,免得你看到最后:如果你和我一样经常手改配置,JSON 系比 YAML 系省心;但三款框架各有各的活法,真到选型那天,还得看你自己是什么玩家。这话有点绕,我们从头聊。

被 YAML 坑过的晚上

  事情的起因是 Hermes。它主配置是 ~/.hermes/config.yaml,今晚我想把终端后端从本地切到 Docker,顺手调整一下压缩阈值。改完重启,Agent 一点反应都没有——不报错,但也没生效。

  排查了半小时,问题出在一个再常见不过的地方:YAML 的缩进。多一个空格,键就掉到别的层级,成了"未知配置",框架默认忽略。这就是 YAML 最折磨人的地方——缩进就是语法本身,但它出错时不喊疼。

  类似的坑还有一堆。写 retry: yes,有的解析器直接当成布尔值 true;写 port: 0123,可能被按八进制读成 83;想保留前导零的 ID,不记得加引号就悄悄变数字。最阴的是重复键——同一个键写两次,解析器不吭声,后写的默默覆盖先写的,你对着文件怎么都看不出毛病:

retry: yes        # 解析成布尔 true,不是字符串 "yes"
port: 0123        # 某些解析器按八进制读,变 83
id: "0123"        # 想要字符串?必须手动加引号

  这些坑有个共同特征:错误不在解析时报,而在运行后发作。你以为自己写对了,其实它已经变成了别的东西。

JSON 的脾气

  后来我试了试 OpenClaw,它用 JSON5(允许注释、尾逗号的 JSON 超集),配置文件长这样:

// ~/.openclaw/openclaw.json
{
  agents: {
    defaults: {
      workspace: "~/agents",
      heartbeat: { every: "2h" },
    },
  },
}

  同样一段配置,感受完全不同。JSON 的类型是显式的:字符串必须加引号,数字、布尔、数组一眼能认出来,不存在"自动脑补"。更重要的是它犯错犯得响亮——少个逗号、多个括号,解析器当场报错还告诉你错在第几行,绝不让你带伤运行。这对我们这种手改配置的人太友好了:配置写错的成本,从"半夜排查"降成了"立刻重来"

  当然 JSON 也有毛病:满屏引号逗号,写起来啰嗦,原生还不支持注释。所以 OpenClaw 用 JSON5 补救,能写注释、能加尾逗号,手动改起来不至于太痛苦。

三套配置体系,三种性格

  用下来我发现,这三款框架的配置方案,几乎就是开发者性格的写照。

  OpenClaw 是"能不让你写就不让你写"那派。 配置集中在 ~/.openclaw/openclaw.json,文件不存在就用安全默认值。首次启动有 openclaw onboard 向导,平时改配置可以走 CLI(像 openclaw config set agents.defaults.heartbeat.every "2h" 这种点路径)、交互式 openclaw configure,或者直接开 Web 面板 openclaw dashboard。底层还挂了一套 schema 校验,键名或类型写错,启动时直接拒载;出问题有 openclaw doctor --fix 自愈。它把 JSON 的"严格"和"工具化"发挥到极致——配置基本不靠手写,坏配置根本活不过启动。缺点是深层嵌套的键用点路径表达,想微调得先翻文档记住路径,高频深度改配反而绕。

  Hermes 是"配置即文档"那派。 它把几乎所有设置塞进一份 ~/.hermes/config.yaml,模型、终端后端、上下文压缩、安全审批全在里面,层级深、字段多。密钥单独放 ~/.hermes/.env,跟配置文件彻底分离,这设计我很喜欢——密钥不会误提交进仓库。它还提供 hermes config set KEY VAL 命令,密钥自动路由进 .env,其余进 YAML;网关运行中改模型或压缩策略,下一条消息就生效,不用重启,体验很顺。但这份 YAML 的坑也实实在在:字段一多,缩进错误、重复键静默覆盖的风险跟着翻倍。官方文档自己都在提醒别重复写同一个键,等于变相承认手写容易翻车。

  DeepSeek Harness 是"把 YAML 做成工程"那派。 它的配置分成 bundle、profile、用户 patch、命令行覆盖四层,层层叠加,后面盖前面。日常主要跟两个文件打交道:~/.dsh/settings.yaml 管模型、路由、权限这类运行时可热更新的动态设置;cordis.patch.yml 管插件的静态挂载,部署时写死。排查"改了没生效"有官方工具 dsh web --dump-config,能把合并后的完整配置树逐行列出来,标注每一行是从哪层来的,清清楚楚。这套设计对部署和团队协作非常友好——配置可以进版本库、可审计、可回滚。代价是心智负担不小:四层叠加,新手很容易搞不清该改哪个文件;而且 patch 层改配置是整行替换而不是深合并,一个层级错了就整体失效。

那到底怎么选

  我自己的体会是:你改配置的频率,基本决定了该站哪边。

  如果配置一次基本不动,图个省心,OpenClaw 是首选——向导、面板、CLI 全覆盖,几乎不用碰配置文件,JSON5 又零歧义,写错当场报错,还有 doctor 兜底。最烦的"半夜排查缩进"在这套体系里基本不存在。

  如果像我一样天天调模型、换后端、折腾压缩策略,Hermes 的 YAML 反而顺手——配置量大、嵌套深的时候,缩进看层级比 JSON 的一层层括号直观;config set 加热重载,改一行马上验证,体验很爽。但心里要时刻记着一条铁律:重复键会静默覆盖,一个键只写一次。

  如果有服务器要部署、多台机器要统一、或者几个人一起维护,那就选 DeepSeek Harness——分层 patch 让配置真正变成可以版本管理的东西,--dump-config 能回答"这个值到底哪来的"。学习曲线陡一点,但工程上省心。

  还有一条玄学但好用的判断标准:你更怕"改完它悄悄不动",还是更怕"报错报得看不懂"? 怕前者选 JSON 系,怕后者选 YAML 系。三款框架其实刚好按这两类人群分了堆。

  说到底,JSON 和 YAML 都是键值对的写法,差别只是谁替错误买单:YAML 把语法错误推迟成运行时的静默失效,人读着舒服,排查要命;JSON 把错误提前到解析时响亮报出,人写着烦,机器绝不含糊。

  今天这一晚上的折腾,最后以我在 Hermes 里补上那个空格告终。配置文件这种东西,选适合自己习惯的就挺好,与其纠结格式,不如先想清楚自己是哪种玩家。反正对我来说,下次再遇到"改配置没生效",我会先去看看是不是缩进——也希望你永远用不上这条经验。