Agent交接棒设计:一次失败的handoff,比不交接更伤用户体验
多Agent系统里,最难的从来不是让Agent干活,而是让它判断「该收手了」。本文拆解Agent-to-Agent交接的四种失败形态、交接包应该包含什么,以及用三档升级机制替代硬切换的设计方法。
我们拆解过上百个生产环境的Agent链路,发现一个反直觉的规律:用户投诉最多的不是Agent答错了,而是Agent在“不该继续”的时候继续了。
会干活只是及格线,知道何时交棒才是分水岭。
交接失败的四张脸
第一张脸:幽灵交接
主Agent把一个任务转给子Agent,但没有把上下文一起转过去。子Agent拿到一句“请处理上面的退款申请”,却看不到“上面”是什么。于是它开始追问用户:“请问您要退款的是哪一单?”
用户已经在第一轮说过了。这种重问的体验损失,比答错还要致命——它传递的信号是“我的时间在你这儿不值钱”。
第二张脸:三角循环
Agent A 觉得该升级到 B,B 判断信息不足又退回 A,A 再升级到 B。三轮之后用户看到的是同一段追问的不同措辞。根因是两个Agent的交接判据互相冲突:A认为“超出权限就转出”,B认为“信息不全就退回”。
修法很朴素:给每个Agent维护一张权威边界表,明确“什么问题归我终身负责”,转出后即丧失决策权,不得反向退回。
第三张脸:沉默降级
高能力Agent超时或报错,系统静默地回落到小模型继续回答,用户完全不知道自己在跟一个弱化版本对话。它可能给出一个看似合理但过时的答案。
任何降级都必须显式。宁可说“这部分我现在生成得不够可靠,要不要转人工”,也不要假装正常。
第四张脸:过度礼貌的死循环
用户说“算了不用了”,Agent回答“好的,那我不打扰您了,还有什么可以帮您?”,用户说“真不用了”,Agent又说一遍。交接逻辑缺少退出态。
交接包里应该有什么
大多数团队只传了 task 和 context。生产级的交接包至少要有六项:
| 字段 | 作用 |
|---|---|
intent | 一句话说清用户的真实目标,不是复述原话 |
facts | 已确认的事实(订单号、金额、用户诉求),结构化 |
attempts | 已尝试过什么、为什么没成 |
verboten | 明确禁止的动作(如“不得承诺赔付金额”) |
tone | 用户当前情绪状态与已承诺过的话术 |
exit | 本轮交接的成功判据——什么时候算完 |
attempts 和 verboten 是最容易被忽略、也最关键的两项。前者防止新Agent重蹈覆辙,后者防止它在权限边缘试探。
用三档替代硬切换
不要做二元判断“能处理/不能处理”。用三档:
第一档:自己答。 置信度高、权限内。 第二档:带梯子的自己答。 仍是自己答,但降低承诺强度——“通常3~5个工作日到账,具体以银行处理为准”。 第三档:交棒。 只在前两档都明确失败时触发,并附完整交接包。
关键设计在于:升级必须由“失败证据”触发,而非由“不确定”触发。 不确定时的正确动作是第二档,不是交棒。大量无谓交接都源于把“我没把握”误判成“我干不了”。
一条可观测性红线
给交接率设个指标:handoff_rate = 交棒会话数 / 总会话数。
- 低于5%:正常,交棒是稀缺事件
- 5%~20%:需要抽查交接包质量
- 高于20%:你的主Agent能力不足,或交棒判据写错了,先去查判据,别急着加子Agent
同时统计 handoff_repeat_question_rate(交棒后用户重复提供已给信息的比例)。这个数字超过10%,说明交接包缺字段。
一条更重要的原则
交接棒设计的第一性原理是:用户只关心一件事有没有被解决,不关心是谁解决的。
所以任何暴露内部结构的行为都是成本而非收益。用户不该看到“正在转接至退款专家Agent”,他只需要知道“我这就帮您转给能直接处理的同事”。
最好的交接,是用户感觉不到发生过交接。