告别"做到一半就停":Hermes 的 max_turns 默认改为无限

你有没有遇到过这种情况:让 Hermes 跑一个真正的大任务——比如重构整个仓库、批量整理几千个文件、把一条数据管道从头搭到尾——它干得正起劲,突然就停下来了。不是报错,不是问你问题,就是“到此为止”了。任务完成了一半,剩下的活儿晾在那儿。
这不是玄学,而是 Hermes 以前默认的一个硬性上限:每一轮对话(turn)里,agent 最多只能调用 500 次工具。500 次听起来很多,但一个稍微复杂点的任务——查资料、读代码、改文件、跑测试、修 bug、再跑测试——很快就用完了。更难受的是它停得悄无声息,你回头看对话才发现它半途而废。
这个默认值现在已经改掉了:从 v0.20.4 之后的主线版本起,agent.max_turns 默认改为无限。本文讲清楚这个改动是什么、为什么改、以及你如果想给任务设置上限该怎么做。
先弄清楚:max_turns 到底是什么
max_turns(也叫 max iterations)限制的是 agent 在一个回合里调用工具的次数,不是对话轮数。你可以这样理解:你发一句话,Hermes 开始干活,它每读一个文件、每敲一条命令、每调一次 API,都算一次迭代。max_turns: 500 的意思就是:这个回合里它最多干 500 次活儿,干完必须停下来把控制权交还给你。
在旧版本里,这个默认值是 500。对于大部分日常问答,500 绰绰有余;但对于那些需要“读一遍代码库 → 改几十个文件 → 跑测试 → 修问题 → 再跑”的长任务,500 就是个看不见的天花板。任务干到一半撞上上限,剩下的步骤只能留到下一轮你手动让它继续。
还有更糟的:如果你在配置文件里写 max_turns: none 想表示“不限制”,旧版本会直接抛 TypeError 崩溃(issue #82813),或者被静默忽略——连“没用”都算客气,有时候直接让 cron 任务和 gateway 崩掉。
新默认:不设限,除非你自己要限
这个改动(PR #90708)把默认行为整个翻转了:
| 写法 | 之前 | 现在 |
|---|---|---|
| 不写(默认) | 上限 500 | 无限 |
max_turns: none |
TypeError 崩溃 | 无限 |
max_turns: null / unlimited / inf / infinity / 0 / -1 |
崩溃或被忽略 | 无限 |
max_turns: 200 |
上限 200 | 上限 200(不变) |
也就是说:默认情况下任务会一路干到完成,不会再有那个让你抓狂的静默截断。所有表示“无限”的写法(none、null、unlimited、infinite、infinity、inf、∞、0、-1,大小写和空格都不敏感)现在都是合法的一等公民,统一由一个 resolve_turn_limit() 函数归一化处理。你随便写哪种,效果都一样,而且不会再崩。
如果你确实想给某些任务设个上限,写正整数就行,行为完全没变。
想限制的话,怎么配
无限是默认,但“无限”不一定适合所有场景——比如你跑的是个一小时一次的 cron 任务,你希望它最多干多少活就收手,避免意外烧 token。设置上限有三种方式,按优先级从低到高:
1. 配置文件(config.yaml)
agent:
max_turns: 200 # 每回合最多 200 次工具调用
2. CLI 命令
hermes config set agent.max_turns 200
3. 环境变量
export HERMES_MAX_ITERATIONS=200
hermes chat
这三个都会走同一个 resolve_turn_limit() 解析器,所以无论从哪里设,行为都一致。
别混淆:goals.max_turns 还是 20
注意不要把这个改动和另一个配置项搞混:goals.max_turns 保持不变,默认仍是 20。
agent.max_turns 管的是普通对话回合,而 goals.max_turns 管的是 goal 模式(你给 Hermes 一个长期目标,让它自己持续推进直到完成)里“自动继续”的次数上限。goal 模式有独立的预算保护——防止目标太模糊时无限烧钱,跑满 20 次自动暂停、问你 resume 还是 clear。这次改动特意没动它,两个字段各管各的。
所以如果你的目标是“让长任务别半途而废”,用无限默认(什么都不用配);如果目标是“给自动推进加个刹车”,调 goals.max_turns。
无限了,还要注意什么
默认无限之后,有两件事值得你心里有数:
- 成本意识:任务会跑完,意味着它会持续调用模型 API。如果你在意花费,与其靠
max_turns截断,不如用更精确的工具——比如agent.run_budget_seconds(按秒计的时间预算,到 80% 会提醒一次),或 gateway 的空闲超时(agent长时间无动作才停)。这些是“优雅刹车”,比“干到一半硬停”体验好得多。 - cron 与 gateway 都受益:因为 cron 调度器和 gateway 的读配置逻辑也统一改成了同一个解析器,以前在 cron 配置里写
none会崩的问题也一并修掉了。长 cron 任务现在能一次跑完。
小结
agent.max_turns 从“默认 500”变成“默认无限”,是 Hermes 对长任务体验的一次务实修正:想跑完的任务就让它跑完,想限制的人照样可以限制。这个改动目前在 main 分支上(v0.20.4 之后合并),等下一个正式版本发布后,hermes update 一下就能用上。
如果你想深入理解 Hermes 的回合机制和上下文处理,可以看看我们之前的错误处理与恢复机制详解,或者长任务配置指南——里面有不少避免任务卡死的实用配置。