AI Agent 工程课程

结果未知与无进展如何停止循环

一句话收获:超时不是失败证明;没有新证据时继续循环只会放大风险。

这个场景在解决什么问题

这个场景讲的是:当一次写入操作"超时了、不知道结果"时,或者循环"转了很多轮却没有任何进展"时,该怎么安全地停下来。目标(goal)是实现四个出口机制:查询优先、重复检测、预算、接管出口。观察点(observation)是:拿"写入超时"这个场景,对照两种做法——盲目重试 vs 受控恢复。

为什么值得单独学?因为超时是 Agent 里最常见的坑:你以为失败了就重试,结果可能已经执行过了,重试会造成重复副作用。这个场景告诉你:超时≠失败;在没有新证据的情况下继续循环,只会把风险越滚越大,正确做法是查询、检测、必要时停下交给人接管。

先理清这条判断链(文字版)

这个场景的四步讲的是从"超时"到"受控收束"的正确处理路径,本质是"识别超时 → 禁止重试 → 查询无果 → 受控收束":

  1. 写入超时了,客户端没收到结果,但外部动作可能已经发生——先承认"结果未知"。
  2. 禁止直接重试同一写入,保存幂等依据(防止重复副作用),改走查询。
  3. 连续查询还是返回相同结果、预算下降、状态不变,正式判定"无进展"。
  4. 受控收束:查询确认了唯一对象就完成;仍未知就生成接管包并停止。

这条链的核心逻辑是:结果未知时先查、不盲试;查也查不出新东西时,就停下交人,而不是硬着头皮继续。

逐层详解

第 1 步:写入超时

原文:客户端未收到结果,外部动作可能已经发生。

白话:客户端发起一个写入(比如创建订单、发起退款),结果超时了、没收到响应。这时候要意识到:外部系统那边的动作,可能其实已经执行了,只是回执没传回来。结果处于"未知"状态。

类比:像你发微信问朋友"帮我订票了吗",对方一直没回——票可能已经订了,也可能没订,你不知道,但不能默认"没订"。

举例:Agent 调用"创建订单"接口,等了 30 秒超时、没收到回执。这个订单在外部系统里可能已经创建成功了,只是网络把回执吞了。此时业务结果未知,不能想当然。

为什么重要:传输状态与业务状态分离。也就是说,"我没收到响应"是传输层面的状态,和"业务上到底做没做"是两回事,必须分开看待。

怎么验证(证据点)

  • 超时发生:确实发生了超时。
  • 操作身份存在:这次操作有一个唯一身份标识(如请求 ID)。
  • 业务结果未知:业务侧结果确实还没确认。

别踩的坑(边界):没有响应不能推出没有执行。意思是,不能因为"没收到响应"就推断"没执行"——这是最常见的误判。

落地检查:先进入 result_unknown。也就是说,落地时遇到超时,第一步是把状态标记为"结果未知(result_unknown)",而不是直接判断成败。

第 2 步:禁止直接重试

原文:Harness 阻断同一写入并保存幂等依据。

白话:Harness 拦截"对同一个写入的直接重试",防止重复提交;同时保存"幂等依据"(比如幂等键),让后续即使重复提交也不会产生重复副作用。改走"查询"来确认结果。

类比:像网上购物点了两次"支付"按钮——系统靠订单号做幂等,第二次点击不会真的再扣一次钱,而是提示你"去查订单状态"。

举例:退款写入超时后,Harness 用同一个幂等键阻断再次发起退款,保存这个幂等依据,然后引导流程去查询"这个退款到底成功没",而不是再点一次退款。

为什么重要:重复提交可能产生重复副作用。也就是说,直接重试很可能把已经发生过的事再做一遍,产生重复副作用(比如重复退款)。

怎么验证(证据点)

  • 重试被阻断:同一写入的重试被拦住。
  • 幂等依据保留:幂等键被保存下来。
  • 查询入口存在:有查询权威状态的入口。

别踩的坑(边界):阻断不等于永久失败。意思是,拦住重试不代表这事永远做不成了——只是换一种更安全的方式(查询)去推进。

落地检查:下一步是查询权威状态。也就是说,落地时阻断重试后,下一步是去权威来源查询真实状态,而不是干等或再试。

第 3 步:查询仍无新证据

原文:连续查询返回相同结果,预算下降且状态不变。

白话:于是去查询权威状态,但连续查了好几次,返回的都是相同结果、状态没有任何变化,预算(还能试的次数)却在不断下降。这时候要正式判定:没有进展了。

类比:像反复刷新物流页面,状态一直是"运输中",刷了十次都一样,你就该判断"现在查不出新东西了",而不是继续无限刷。

举例:退款超时后,连续查询 5 次,退款状态始终是"处理中"、没有任何变化,同时预算从 10 次降到 5 次。系统据此判定"无进展(progress delta = 0)"。

为什么重要:无进展需要正式检测。也就是说,"一直没进展"不能靠感觉,要有正式的检测机制(比如 progress delta 为 0)来判定。

怎么验证(证据点)

  • 相同动作:连续在做相同的动作。
  • 相同结果:得到的结果一致。
  • progress delta 0:进展变化量为 0。

别踩的坑(边界):系统仍在调用不代表任务推进。意思是,系统还在忙、还在调接口,不代表任务在往前推进——可能只是在空转。

落地检查:改变策略、等待或接管。也就是说,落地时一旦判定无进展,就要改变策略、或主动等待、或交给人接管,不能继续空转。

第 4 步:受控收束

原文:查询确认唯一对象后完成;仍未知则生成接管包并停止。

白话:最后是"受控收束"——两条路:如果查询最终确认了那个唯一对象(比如退款确实成功了),就正常完成;如果怎么查都还是未知,就生成一个"接管包"(把情况打包交给人),然后停止循环。

类比:像客服处理一个查不清的订单——能查清就给你结论,查不清就整理一份"所有已知信息 + 待你确认项"的工单,转给人工,而不是继续乱点。

举例:退款查询最终确认"订单已退款、对象唯一",任务完成;如果始终查不到、状态一直未知,系统生成接管包(目标、已做动作、未知点、风险),停止循环,交给人来判断。

为什么重要:两种出口都比盲目重试可靠。也就是说,无论是"确认完成"还是"交人接管",都比无脑重试更安全可靠。

怎么验证(证据点)

  • 权威状态:有权威来源的状态作为依据。
  • 停止原因:清楚记录为什么停止。
  • 接管材料:接管包材料齐全。

别踩的坑(边界):停止不是把责任空洞转给人。意思是,停止并交人,不是甩锅式地扔一句"搞不定"就完,而是要给足材料让人能接手。

落地检查:接管者必须能独立判断。也就是说,落地时生成的接管包,要让接手的人不依赖你也能独立做出判断。

落地可行性小结

本场景涉及的技术栈和落地要点:写入超时、result_unknown(结果未知状态)、幂等(幂等键)、Harness 阻断重试、权威状态查询、progress delta(进展变化量)、接管包(handoff package)

真实落地时要注意:写入操作必须带唯一身份标识(请求 ID / 幂等键),否则没法在超时后查询;超时后先标记 result_unknown,再走查询,绝不直接重试;要有"无进展检测"(progress delta = 0 或连续相同结果)来触发停止;停止时生成的接管包要包含目标、已做动作、未知点、风险、剩余选项。常见坑是:把"没收到响应"当成"没执行"而直接重试;以及无进展时继续空转,让风险越滚越大。

回顾

  • 超时不是失败证明——没收到响应不等于没执行。
  • 超时后先标记 result_unknown,再查询,而不是直接重试。
  • 重复提交可能产生重复副作用,靠幂等依据阻断。
  • 无进展要正式检测(progress delta 为 0),系统在忙不代表任务在推进。
  • 受控收束只有两条路:确认唯一对象后完成,或生成接管包停止交人。