Agent 越自主,停止条件越重要
我们常用“能连续做多少步”衡量 Agent 的能力:自己拆任务、搜索资料、调用工具、检查结果,再决定下一步。步数越多,看起来越接近自主。
但行动空间扩大,错误半径也会扩大。错误目标会被持续执行,工具拒绝会被反复重试,局部优化会消耗越来越多成本,用户取消后系统仍可能继续产生动作。
自主性不是少设规则。恰恰相反,Agent 越能自己推进,越需要明确什么时候必须停。
Loop 不是重复,是带证据的下一轮
一个健康循环,每一轮都应该形成可观察变化:新增了证据、减少了未决项、通过了一项检查,或者明确排除了一个方向。如果下一轮只是换一种说法、重复搜索同一资料、再次调用已被拒绝的工具,它没有进展,只是在消耗预算。
因此,每轮开始前要有小合同:当前目标、允许动作、预期产物、检查方法、剩余预算和停止条件。轮次结束后,系统用同一组事实判断继续还是停止。
“模型认为还可以优化”不能成为继续运行的充分理由。
六类停止条件缺一不可
完成:产物和所有硬验证已经齐全,再运行只会制造变化。
需要输入:缺少只能由指定用户或角色提供的信息,继续猜测会改变路径。
需要审批:动作已经明确,但权限或风险 Gate 尚未满足。
无进展:连续轮次没有新增证据,候选动作开始重复或振荡。
预算耗尽:时间、调用、轮次或成本达到事先上限。
不可恢复失败:输入损坏、权限明确拒绝,或关键依赖长期不可用。
这六类状态表达的是不同业务语义。需要输入可以在补齐后恢复,权限拒绝不能自动绕过,预算耗尽需要新的授权,不可恢复失败则应结束当前任务。把它们都写成 failed,会让恢复机制失去依据。
停止条件要有优先级
同一时刻可能命中多个条件。用户已经取消,同时预算也耗尽;权限被撤回,同时外部工具仍在返回结果。如果系统没有优先级,页面和后台可能作出互相冲突的决定。
通常,取消、权限和安全拒绝应先阻止新动作;随后处理结果未知和在途副作用;输入、审批和预算决定是否允许未来恢复;只有产物与硬验证全部通过,才能进入完成。
具体顺序取决于业务,但必须在执行前确定。停止不能由模型临场选择一个最方便的解释。
用户需要看到停在哪里,而不是只看到停了
每个停止状态都应带一个用户去向。
需要输入时,列出缺什么、为什么需要、补充入口和期限;需要审批时,展示动作影响、审批角色和有效期;无进展时,说明已经尝试的路径、仍缺的证据和接管建议;预算耗尽时,交付已完成部分、剩余缺口以及追加预算会换来什么。
用户取消后,页面还要区分“已停止新动作”和“已经发生的现实结果”。取消一个等待界面,不等于撤销已经发出的消息或写入。系统应对在途动作查询、对账,并在结果出现时通知用户。
可解释的停止,让用户重新获得控制权。
Hook 负责守门,不替 Agent 作业务决定
停止条件需要落到系统控制,而不是只写在 Prompt。工具调用前可以检查权限、对象版本、任务状态和预算;调用后记录回执、更新状态并运行验证;取消事件到达时阻止后续写入。
这些 Hook 适合执行确定性门,但不应变成第二个隐藏 Agent。它们判断“当前是否允许做”,业务 Owner 和任务合同决定“为什么允许”。
把关键 Gate 放在动作发生之前,审计才能阻止错误;只在事后留下完整日志,无法撤回已经发生的副作用。
警惕四种假进展
第一种是表达变化:答案换了措辞,证据没有增加。第二种是局部指标改善:格式更好,却破坏了事实或权限。第三种是动作完成:工具返回成功,但现实结果没有读回。第四种是等待被误写成循环:外部事件尚未到达,系统却不断空转查询。
识别假进展,需要明确进展指标和首次偏离。每轮 Trace 至少记录任务版本、观察、候选动作、工具结果、验证、预算变化和状态迁移。复盘时从错误向前找第一处不符合预期,而不是只看最后一句答案。
停止不是削弱自主,而是定义自主
一个永不停止的 Agent 并不更聪明,只是没有边界。真正的自主是:在允许范围内自行选择下一步,在证据不足、风险升高或目标完成时,准确地把控制权交还给系统或人。
停止条件让 Loop 从无限尝试变成受控探索,也让成本、权限和责任有了可执行的边界。Agent 越自主,这套边界越不能依赖一句“请谨慎行事”。