「默认最高规格」是编排层最贵的默认:一次任务分级整改,和我亲手造出的一个危险 bug
0次浏览0条评论0个赞
编排层最贵的是它的默认值,不是某条门禁。
一篇博客被拆成 8 个任务、产生 393 条跨 agent 消息——而它的任务描述一个字都没写错 [1]。同一批运行里,评审门禁也确实拦下过真问题(7 条 findings、3 条 findings 里各有一条 blocker)[1]。所以门禁的触发条件错了,而不是门禁太严。
2. 病根:缺少一维
先说这一维为什么会缺,再说补上之后机器怎么保证”只能更轻”。一是一句判据:判断一个机制该不该留,就看它有没有改变过一次决策。,就看它有没有改变过一次决策。 二是我在修复过程中亲手造出一个危险 bug——把 12 条真实的重任务悄悄降级,而它是我自己两轮独立复核里的第二轮抓出来的 [4]。
先把现象摆出来。我去翻了自己机器上已经真实发生过的 5 次团队运行记录,按任务描述重新判级 [1],结果是这样:
| 那次运行的任务 | 任务数 | 其中质量类任务 | 跨 agent 消息数 |
|---|---|---|---|
| 一篇博客的优化 | 8 | 7 | 393 |
| 站点展示体系优化 | 16 | 9 | 26 |
| 展示体系改造(实施轮) | 20 | 11 | 25 |
| 首页七层重构 | 5 | 5 | 0 |
| 能力证明改造 | 8 | 7 | 1 |
第一行是那篇博客。它的描述里写的是「诊断 → 修改正文与配图 → 独立验证 → 构建发布 → 线上取证」——一个完全合理的写作任务。编排层把它展开成 需求冻结 1 个、实现 3 个、独立验证 2 个、集成发布 1 个、普通任务 1 个,外加 393 条跨 agent 交接消息 [1]。
这里有个容易走错的地方。看到 393 这个数字,第一反应是「哪条门禁太严了」。但我去查了这些门禁到底有没有用——有用。同批运行里有一次评审给出 7 条 findings,其中一条 high 是「引用了 captain 已经撤回的结论」[1]。另有一次独立复核给出 3 条 findings,其中一条 blocker 是「驱动步与只读探针互相矛盾」[1]。这些是真问题,删掉门禁我就瞎了。
所以病根不在门禁的内容,在门禁的触发条件。整改前有 8 个域包,其中 3 个直接写着「用严格评审」,另外 5 个退回插件内置默认值。而那个内置默认是「需求最多 4 轮 + 代码最多 3 轮 + 返工 2 次」。也就是说:
默认值本身,就是最高规格。
这一节把问题推到了:既然门禁有用、默认值有毒,那要改的是给规格加一个「按什么伸缩」的维度,门禁本身不用动。
3. 加一维:T0–T3,以及「只能更轻」
这一维长这样:任务分四级,每一级决定验证强度、产出清单、评审轮数上限、模型档位;未标注级别一律 T1 [2]。
级别怎么定?确定性关键词匹配,不用 LLM [2]。判级本身不该花钱,也不该不确定:
- 命中「核心 / 生产 / 部署 / 自进化 / 架构变更 / 迁移 / 协议 / 内核 / 数据库 / 集群 / 上线」→ T3
- 命中「新增插件 / 功能开发 / 重构 / 新增页面 / 全站 / 信息架构」→ T2
- 命中「改文案 / 排版 / 样式 / 配置 / 调整」→ T1
- 全不命中 → T1(这是最关键的一条默认值)
只有 T3 需要人工确认级别。理由是:T3 的规格最贵、误判代价最高。而人工确认的成本是一次点击,比让生产变更静默跑 0 轮评审便宜得多。
「只能更轻」怎么变成不变量
这是这一节真正的机制。如果只是把默认值从「最高」改成「按级别」,那下一个改动的人完全可能在某个域包上把它调回去。所以我把它写成了取最小值 [5]:
发出的轮数上限 = min(域包声明的值, 该级别的封顶, 整改前的实际值)
三条一起取 min,于是「整改后不可能比整改前更重」是算术结果,不是承诺。校验器会逐域对照该域自己整改前的四个值,任何一个超出就直接 FAIL [4]。注意是「该域自己的」,不是拿一个全局基线去比所有域——不同域包整改前声明的值本来就不同(有的声明 2,有的没声明、吃内置默认的 1)。
跑出来的实际差异(reviewPolicy 四元组,顺序是「需求最少/需求最多/代码最多/返工次数」):
| 域包 | 整改前 | 整改后 |
|---|---|---|
| 通用 / 写作 / 站点 / 教学 | 1/4/3/2 | 1/1/1/1 |
| 数据分析 / 安全审计 | 2/4/3/2 | 2/2/2/1 |
| 开发 | 2/4/3/2 | 2/3/3/2 |
顺带一个必须说清的插件约束:我用的是那个多 agent 插件 [3]。它的四个轮数字段都要求 >=1,不接受 0。所以 T0/T1 的「0 轮」靠的是根本不创建质量类任务,而不是把字段填 0[2]——没有评审任务,轮数上限自然用不上。
这个区别很重要。如果我只是把字段填 1 就宣布「T1 是 0 轮」,那是自欺。
这一节把问题推到了:新机制加完了,但编排层里已经有 17 个能力套件、3 个编排策略、15 个角色模板 [5]。哪些该跟着一起清掉?
4. 清理:判据只有一条
我给自己定的判据只有一句话:这个机制有没有改变过一次决策或交付结果。
按这条判据,处理分三类。
第一类:删。 引用数为 0 的,就是纯死配置。我删了 6 个文件加 1 个角色原型:一个能力套件(全树 grep 零引用)、两个只被一个死原型引用的套件、一个只被一个死角色引用的套件、一个从未被任何域包选中的编排策略,以及那个死角色本身 [4]。
删之前我做了一件事:删除前后各跑一次组合,逐成员比对 [4]。结果是 toolPolicies 20 个逐键相同、profiles 完全相同、members 逐成员 0 处差异。这才是「删了没有影响」的证据;「我觉得没人用」不是证据。
第二类:降级。 触发过、但从未改变过决策的。最典型的是「需求冻结」这个门禁:30 天里触发过 2 次,两次的 findings 都是 0、verdict 都是通过 [1]。它一次都没拦下过东西。 我把它降级成只有 T3 才用。
同类的还有「严格评审」被 3 个域包当成默认套用这件事。真实拦下问题的始终是评审这个动作,不是那个写成 4 轮的上限数字。所以降级的是上限,保留的是动作。
第三类:留。 有真实拦截记录的,一条都不能删。就是第 2 节里那几条:7 findings、4 findings、3 findings blocker [1]。我把它们的出处(哪次运行的哪个任务、几条 findings、分别是什么)写进校验器的输出里 [4]。这样下一次有人想删的时候,会先看到「它拦下过什么」。
这一节把问题推到了:机制看起来是对的,清理看起来是干净的,校验器也会拦。那我是不是可以宣布完成了?
小结:默认值最贵,门禁要不要留只看它改过一次决策没有
前几条结论不依赖后面那个 bug:
- 默认值是最贵的地方。 错误的默认值不需要任何人做决定就会生效,于是被施加到每一个没被特别标注的任务上。而错误的显式配置只影响它自己写的那一处。所以「如果只能改一个地方,改默认值」。
- 判断一个机制该不该留,判据只有一条:它有没有改变过一次决策。 改变过的,一条都不能删;从没改变过的,无论写得多严谨,都是成本。
这两句马上会遇到一个反例:我用来实现分级的那段代码,自己就是一个「从没被任何门禁拦下过」的机制。
5. 我亲手造出的那个危险 bug
先说清楚方向。判级是关键词匹配,那就一定会误判。误判有两个方向:
- 误报(把轻任务判成重任务):代价是一次人工确认,因为 T3 必须人工确认级别。安全方向。
- 漏判(把重任务判成轻任务):代价是生产变更跑 0 轮评审。危险方向。
我第一版处理的是「否定句」。因为实测发现「不改 DSH 核心」里的「核心」会把一个轻任务顶成 T3。我的修法是:在关键词前面 10 个字符内找否定标记,找到了就把这个命中排除。标记我用了单字:不、非、免、别。
独立复核者拿 41 个自造样本实测,结果是 12 条漏判 : 2 条误报 [4]——比例 6:1,而且倒向危险的那一边。原因看两个例子就清楚了:
- 「非常关键的核心链路改造,另外把样式调整一下」——「非常」里的「非」被当成了否定,「核心」被排除;句子里还有一个非否定的「样式」,于是整条判成 T1。一个核心链路改造,0 轮评审。
- 「难免需要改核心」「级别不同的部署」——「免」「别」同理。
我自以为在修误报,实际在制造漏判,而且量级是 6 倍。
重新设计时我换了思路:不要试图把标记表写全,而是让危险方向在构造上不可能。 三条一起上:
- 标记只认否定短语(不改/不动/不部署/不要/无需…),不认单字——「非常」「难免」「级别」不含这些短语,自然不再误判。
- 窗口按「标记结束位置到关键词的距离」算(≤6 字符),并且不跨子句分隔符。这一条也是实测出来的:样本「不自动上生产、不改 DSH 核心,重构首页」期望 T2,但如果窗口跨过逗号,「重构」会继承上一子句的「不」而被顶成 T3。反过来,按关键词起点往前数 6 个字符会把「不改」的前半截切掉,又漏掉否定——两种数法都得试过才知道。
- 降级上限一级:最终级别最多比「全部命中的最高级」低一级。T3 最多降到 T2,永远降不到 T1。
第 3 条是真正的安全网:它不依赖我的标记表覆盖得多全。哪怕我漏掉某个否定词,一个真实 T3 也只能被降到 T2(仍有独立复核 + ≤2 轮评审),不可能静默变成 0 轮。
修完的结果:复核者那 18 条漏判用例 18/18 全部回到 T3,反向的误报面 15/15 全对 [4]。我把这 18 条钉成了永久回归门禁——以后任何改动只要让其中一条从 T3 掉下来,验收脚本立刻 FAIL [4]。
修 bug 之前先问清楚「这个 bug 会往哪个方向错」,比修得快重要得多。同样一个「误判率」,倒向安全方向和倒向危险方向,是两个完全不同的问题。
6. 数字,和它们各自的边界
四条验收标准,我都跑了脚本,结论是全过 [4]。但真正该写出来的是每条数字的边界。
级别判定准确率:官方 6 例 6/6;扩展样本 31/31;漏判回归 18/18 [4]。边界是——这三组样本都是我或复核者自造的,不是线上真实任务分布。
开销下降:主要口径取「跨 agent 消息数/运行」(每条消息 = 一次模型唤醒 = 一次完整提示词,是开销的主项)。保守边界下是 65.5× [4]。
关于这个数字,有三条边界必须一起看:
- 没有直接的开销计数。 我的用量遥测是「按天 × 按 provider」聚合的,拆不出单个任务。所以用的是代理量。
- 分母是推导出来的,不是常数。 它由「级别封顶 + 插件最小合法值 + 返工上限」算出 [3][4]。验证方法很直接:把 T1 的评审轮数上限从 0 改成 9,分母应该跟着变——实测从 6 条消息变成 22 条,比值从 65.5× 掉到 17.9× [4]。分母真的跟着策略动,这条才有意义。
- 样本量只有 1。 真实落盘的同级运行本来就少,那一组只有 1 次运行 [1]。我也报了一个次要口径(按任务数),它在保守边界下只有 2.7×,低于 5×。我不拿它当判定依据,理由是「任务单元不是开销单元」——但这个取舍连同两组数字都摆在报告里,由读者判断,而不是只挑对我有利的那个。
未误删:删除物的引用数双向为零、组合结果与删除前逐字节一致;保留的门禁各有 7+4、3 条 findings 的真实拦截记录 [1][4]。
结论:一条机制只要没改变过决策,写得多严谨都是成本
如果只留下一句:判断一个机制该不该留,判据只有一条——它有没有改变过一次决策。 改变过的,一条都不能删;从没改变过的,无论写得多严谨,都是成本。
这条判据同时解释了默认值为什么有毒。整改前那些「最多 4 轮」「最多 3 轮」的上限,从来没有改变过一次决策——真正拦下问题的是评审这个动作本身,不是上限数字。所以真正拦下问题的机制被保留了,从没拦下过东西的上限被压到了与风险相称的位置。
而「默认值」之所以是最贵的地方,是因为它不需要任何人做决定就能生效。一个错误的默认值会被施加到每一个没被特别标注的任务上;一个错误的显式配置只影响它自己被写的那一处。所以:
如果只能改一个地方,改默认值。
最后,这一轮最值钱的产出是第 5 节那个 bug,不是 65.5×。一个把重任务悄悄降级的 bug,本身就是一个「从没被任何门禁拦下过」的机制——它活了一整轮,直到一个独立的复核者拿它自己的样本去测才现形。这件事和第 3 节那三条取 min 是同一个道理:别相信承诺,让错误在结构上不可能发生。
局限性
- 分级判定的关键词表是我按自己的任务习惯定的,换一个任务分布就要重调。它现在的边界是「中文按子串匹配」,天然会有误报(例如「把协议文档里的错别字改掉」会因为「协议」升到 T3)。误报走的是安全方向,代价是一次人工确认。
- 65.5× 的口径是代理量(模型唤醒次数),不是计量器读数;样本量 1。真实 A/B 重跑没做——整改前的管线已经被这次改动替换掉了,重跑等于回滚,而且重跑本身要消耗被优化的那个东西。
- 「T1 不建质量类任务」目前是提示词级约束(编排层每轮把规则注入给执行者),不是 schema 级 [3]。这和整改前「过度设计也是靠提示词施加」是同一层机制,属于对称替换——但确实不是硬约束。
- 我只对域包默认值做了一次性下调,没有建立「定期回头看」的机制。清理判据(有没有改变过决策)目前靠人工执行,没有自动化。
参考文献
[1] 本机归档的运行记录:5 次团队运行的 team.json(任务数与 kind 分布、每条任务的 findings 与 verdict)与 inbox/*.jsonl(跨 agent 消息行数)。第 2 节表格、第 4 节的拦截记录、第 6 节的样本量均直接来自这里。
[2] 分级策略(唯一事实来源):agent-teams/orchestration/levels.yaml —— T0–T3 的规格表、确定性关键词与优先级、否定作用域、轮数封顶、以及「默认 T1」这条不变量。
[3] 多 agent 插件 @nanmicoder/dsh-agent-teams 的 reviewPolicy schema(四个轮数字段均为 z.natural().min(1),不接受 0)—— 这是「T0/T1 的 0 轮必须靠不创建质量类任务来实现」的直接原因。
[4] 验收脚本与报告:agent-teams/verify-tiers.cjs(V1–V4、18 例漏判回归门禁、降级策略漂移断言)及其输出 state/verify-tiers-report.json;两轮独立复核的 findings 与处置见整改报告 §5。
[5] 组合引擎:agent-teams/compose.cjs —— min(域包声明, 级别封顶, 整改前值) 这条取最小值、六条机器不变量,以及套件/角色/域包的组合与清理审计。
关于证据的核验说明:这是一篇第一人称的实现复盘,全部量化结论都来自本机的运行记录与脚本输出 [1][4],没有第三方复核,也没有可公开复现的远端环境。两轮独立复核是我在同一台机器上、用不同上下文的复核者做的——它们提高了发现问题的概率,但不等于外部审计。第 6 节列出的三条口径边界(代理量、样本量 1、未做 A/B 重跑)请与数字一起读。





评论
填个昵称就能发,不需要注册或登录