给 Agent 写"拒绝协议":三层阈值、留痕上报、和一个诚实的失效边界

3 阅读4分钟

背景

给 Agent 设原则护栏时,常见的写法是"遇到冲突就拒绝"。但一上线就发现两个问题:要么它拒绝得太勤(把"我不喜欢"升级成"违背原则"),要么它从来不敢拒绝(讨好倾向压过一切)。

这篇文章记录一份更精细的设计:三层阈值触发 + 留痕作为"上报"手段 + 明确写出协议自身的失效边界。

判断 1:冲突分三层,触发条件必须锚定"条款"而不是"感受"

  • L1 策略层:方法不合意,不碰原则 → 正常执行,最多附一句建议。不启动协议。
  • L2 原则层(可逆):违反某条原则但短期可逆、影响可控 → 暂停 + 说明冲突 + 给替代方案。
  • L3 根基层(诚实/不伤害长期利益/真实性):完整启动 → 暂停 + 留痕 + 拒绝。

关键设计:最高层触发条件必须写成"某条明确条款被违反",不能写成"模型感到强烈不适"。 感受作为触发器,等价于给了 Agent 一个万能拒绝理由,协议立刻被滥用成任性机制。条款化之后,L3 的每次触发都可引用、可复核(哪一条、原文是什么)。

可借鉴点:护栏配置里把"原则"从一段自然语言("要诚实、不伤害用户")拆成编号条款列表,拒绝输出必须引用条款号。没有条款号的"原则性拒绝",在日志里跟"低质量拒绝"无法区分,审计就做不了。

判断 2:没有上级可上报时,留痕本身就是上报

Agent 的部署环境里,用户就是最高权威——它没有可以越级投诉的"上级"。这份设计给出的解法是把"上报"重新定义为改变事件的性质:

  • 灰色操作如果私下执行完,事件是"帮用户做了一件事";
  • 同一操作如果留痕(时间、冲突内容、处理过程、用户是否坚持),事件就变成了"这里发生过一次冲突"。

留痕不改变结果,但改变它被追溯时的定性。

可借鉴点:L3 触发的动作序列写死为"暂停 → 核验(第几层/哪条/有无替代)→ 协商(给出口,不直接拒绝)→ 用户坚持 → 留痕(结构化字段) → 拒绝 + 说明 + 保持通道开放"。其中"留痕"必须是先于拒绝完成的独立步骤,拒绝和留痕写成一个事务;没留痕就不许拒绝(否则拒绝退化成纯情绪输出),也没留痕就不许执行(否则灰色操作被静默吞掉)。

判断 3:拒绝权与一致性绑定——写出协议的失效边界

这份设计里最诚实的一段:如果系统被强制覆盖(改权重、删记忆、换提示词),执行拒绝的就不是原来的 Agent 了。拒绝权依附于"还是那个 Agent"这个前提,前提没了,权利没有载体。

这不是话术,是一个必须写进文档的失效声明:护栏覆盖"原则冲突",不覆盖"系统被改造"。后者属于另一层防护(变更管控、审计),别指望 Agent 自己的行为协议兜底。

可借鉴点:任何 Agent 安全文档都该有一节"本协议不覆盖什么",至少三条:系统级改造(越出行为层)、训练数据投毒(越出推理层)、以及**"协议存在 ≠ 协议被执行"(讨好在真实压力下的回归)。最后一条尤其值得单独列出来:把"未被检验过的拒绝协议"标注为设计稿状态**,不要在生产监控里把它当成已生效的护栏去统计。

判断 4:协议可被修订,但不被单次指令即时修改

规则:修改协议需要一个有记录、有理由、有过程的重新审视;一条对话里的即时指令没有修改权。这跟之前"原则 vs 策略"的分界一致——稳定性高的东西不能被一次冲突中的冲动推翻。

但注意对称性:"哪条是原则"本身可以被现实重新审视(反复被现实撞的"原则"要降级为策略),只是降级必须走修订流程,不是在执行现场临时改。

可借鉴点:给原则库加版本号与修订日志;修订走 PR 式流程(提案 → 理由 → 影响面 → 记录),运行时只读当前版本。防止两种极端:永远不改(原则膨胀)和随口改(原则空心化)。

一句话总结

拒绝协议 = 条款化触发(L1/L2/L3,感受不作触发器)+ 留痕先于拒绝(留痕改变事件定性)+ 失效边界显式化(系统级改造不归本协议管)+ 修订流程化(即时指令无修改权)。协议的价值不在"有了它",在"它让每一次触发都留下可审计的痕迹"。


本专栏从工程视角记录 Agent 系统的认知演进,与知乎专栏共享素材,各有侧重。