生产 Agent 必须有人工接管开关
很多团队做 Agent 上线方案时,会把注意力放在模型选型、工具调用、知识库和 prompt 上。
这些都重要,但如果这个 Agent 会读真实工单、改订单状态、发客户消息、调设备接口,真正该提前设计的是另一件事:
一旦它开始偏,谁能接管,接管后系统怎么停住。
生产环境里最危险的不是 Agent 回答错一句话,而是它在错误路径上继续执行了三步、五步,然后没人知道应该从哪里切断。
接管开关不是“人工兜底”四个字
很多设计文档里会写“异常时转人工”。这句话太粗。
真正可执行的人工接管,至少要回答五个问题:
- 什么情况触发接管?
- 接管后 Agent 停哪些动作?
- 当前上下文怎么交给人?
- 人处理完以后怎么恢复?
- 接管过程有没有审计记录?
如果这些问题没有落到系统状态和操作按钮上,所谓“人工兜底”通常只是一个口号。
哪些信号应该触发接管
我一般会把触发条件分成三类。
第一类是模型不确定。
比如证据不足、工具返回冲突、检索结果互相矛盾、模型自评置信度低。这类场景不一定有故障,但继续自动执行会把一个不确定判断变成真实副作用。
第二类是业务风险升高。
比如涉及退款、删除、停机、修改配置、通知客户、触发设备指令、进入金融或合规流程。这些动作即使模型判断正确,也应该有更高的确认门槛。
第三类是系统异常。
比如工具超时、幂等键冲突、连续重试失败、外部接口返回状态不一致、审计日志写入失败。这里不能只让 Agent 再试一次,因为它可能已经处在半成功状态。
一个简化的规则可以长这样:
typeTakeoverReason=|"low_confidence"|"conflicting_evidence"|"high_risk_action"|"tool_timeout"|"state_mismatch"|"audit_log_failed";typeTakeoverDecision={shouldTakeover:boolean;reason?:TakeoverReason;pauseWrites:boolean;pauseExternalMessages:boolean;requireSupervisor:boolean;};functiondecideTakeover(ctx:{confidence:number;evidenceConflict:boolean;actionRisk:"read"|"draft"|"write"|"external";toolFailures:number;stateMismatch:boolean;auditWritable:boolean;}):TakeoverDecision{if(!ctx.auditWritable){return{shouldTakeover:true,reason:"audit_log_failed",pauseWrites:true,pauseExternalMessages:true,requireSupervisor:true,};}if(ctx.stateMismatch){return{shouldTakeover:true,reason:"state_mismatch",pauseWrites:true,pauseExternalMessages:true,requireSupervisor:true,};}if(ctx.actionRisk==="write"||ctx.actionRisk==="external"){return{shouldTakeover:true,reason:"high_risk_action",pauseWrites:true,pauseExternalMessages:ctx.actionRisk==="external",requireSupervisor:true,};}if(ctx.confidence<0.72||ctx.evidenceConflict||ctx.toolFailures>=2){return{shouldTakeover:true,reason:ctx.evidenceConflict?"conflicting_evidence":"low_confidence",pauseWrites:true,pauseExternalMessages:true,requireSupervisor:false,};}return{shouldTakeover:false,pauseWrites:false,pauseExternalMessages:false,requireSupervisor:false,};}重点不是这段代码本身,而是接管条件必须能被系统判断、记录和复盘。
接管后应该暂停什么
人工接管不是把整个系统都关掉。
更合理的做法是按动作风险分层暂停:
- 只读查询:通常可以继续运行;
- 内部草稿:可以继续生成,但标记为待复核;
- 写操作:暂停;
- 外部消息:暂停;
- 设备、资金、订单状态类动作:必须人工确认后再恢复。
这样系统不会因为一个高风险动作而完全失明。人接管时仍然可以让 Agent 查日志、查工单、整理上下文,但不能让它继续改外部状态。
可以把运行状态建模成这样:
上下文打包比按钮更重要
只做一个“暂停 Agent”按钮还不够。
真正让人能接住的,是接管瞬间的上下文包:
- 当前任务目标;
- 已经调用过哪些工具;
- 每个工具的入参和返回摘要;
- Agent 做出的关键判断;
- 尚未执行的下一步动作;
- 触发接管的具体原因;
- 相关工单、客户、设备或订单链接;
- 推荐的人类处理选项。
否则接管人只能重新问一遍发生了什么,响应时间会被拉长。
一个接管事件最少应该这样记录:
{"taskId":"task_20260701_1033","agentRunId":"run_8f21","takeoverReason":"state_mismatch","pausedActions":["write_tools","external_messages"],"lastToolCall":{"name":"update_ticket_status","idempotencyKey":"ticket_9172_to_pending_customer","result":"timeout"},"evidence":["ticket status readback still open","customer notification not sent","audit log written"],"recommendedHumanAction":"check ticket status in CRM before retrying"}这类记录后续还能进入评估集:哪些接管是真风险,哪些是误触发,哪些规则要放宽或收紧。
恢复也要有边界
很多事故不是发生在暂停时,而是发生在恢复时。
人处理完以后,不应该简单点击“恢复全部自动化”。更稳的方式是恢复具体能力:
- 只恢复该任务;
- 只恢复只读工具;
- 只恢复某个低风险写工具;
- 只允许在当前工单继续;
- 高风险动作继续保留人工确认。
也就是说,恢复动作本身也应该是一次权限变更。
上线前可以用这张表自查
| 检查项 | 通过标准 |
|---|---|
| 接管触发条件 | 至少覆盖低置信度、证据冲突、高风险动作、工具异常、状态不一致 |
| 暂停范围 | 能区分只读、草稿、写操作、外部消息 |
| 上下文包 | 人接手时能看到目标、证据、工具调用、下一步建议 |
| 审计记录 | 每次接管都有原因、时间、任务 ID、处理人和恢复动作 |
| 恢复机制 | 支持按任务、按工具、按风险等级恢复 |
| 复盘入口 | 接管事件能进入样本库,支持后续调规则 |
结论
生产 Agent 不应该只有“运行”和“停止”两种状态。
更可控的设计是:低风险动作继续跑,高风险动作能暂停,人接管时有上下文,恢复时有边界,所有过程都能审计。
这样 Agent 即使判断错,也不会一路错下去。对生产系统来说,这比把 prompt 再打磨一轮更重要。