K1.1.1 Task 1.1

stop_reason 才是唯一靠谱的循环控制

Agentic 循环有且只有一个可靠的控制机制:stop_reason。其他所有方式——检查文本内容、迭代次数上限、解析自然语言——要么是反模式,要么只能当安全网。搞错这个会导致无限循环、提前终止,或者两者兼得。

驱动循环的两个状态

  • stop_reason: "tool_use" → 模型要执行工具。继续循环:执行请求的工具,追加结果,发下一个 API 请求。
  • stop_reason: "end_turn" → 模型结束了。终止循环:把最终响应返回给用户。

这就是核心控制流。模型决定什么时候继续(通过请求工具)和什么时候停止(通过结束轮次)。循环的职责是尊重这些信号。

文本内容陷阱

最常见的反模式:检查响应是否包含文本内容,然后把它当作完成信号。这行不通,因为文本 block 和 tool_use block 可以共存在同一条响应里。模型经常在工具调用旁边附带解释性文字——“我现在去查一下账单记录……”后面跟着一个 tool_use block。一发现有文本就终止,会在任务做到一半时把 agent 杀掉。

反过来也不行:如果你用文本的存在来继续循环,那它永远不会停,因为每个响应(包括最终摘要)都包含文本。

迭代上限:安全网,不是主控制

把硬性迭代上限当作主要终止机制是反模式。生产数据告诉你会怎样:上限设 20,需要 25+ 次工具调用的复杂任务被不完整地终止了。某个客服系统 7% 的提前终止率意味着真实的客户问题没被解决。

迭代上限的正确角色:一个宽松的安全网(比如 100),用来捕获真正的无限循环,但不干扰正常操作。正常的终止来自 stop_reason: "end_turn"

处理全部六种 stop_reason 值

生产系统会遇到不只 tool_useend_turn

stop_reason含义动作
tool_use模型要执行工具继续循环,执行工具
end_turn模型自然完成正常终止
max_tokens响应被截断终止并警告截断
pause_turn轮次在工作中暂停在后续请求中恢复
refusal策略违规终止并报策略告警
stop_sequence命中了 stop sequence正常终止

每种都需要区别处理。把所有非 tool_use 值都当 end_turn 处理会悄悄丢掉截断警告、忽略可恢复的暂停、隐藏策略违规。按类型分别处理能捕获这三类问题。

CI 双约束模式

CI 流水线面临两个对立的要求:agent 必须完整执行(提前终止会漏掉 bug)且必须遵守墙钟超时(CI 任务不能无限跑下去)。方案是:用 stop_reason 做主控制,加一个墙钟超时做硬性兜底。大多数运行在时间限制内通过 end_turn 正常完成。超时触发时,agent 优雅终止并输出部分发现,而不是被硬杀。


一句话总结:stop_reason 作为唯一的循环控制(tool_use = 继续,end_turn = 停止),区别处理全部六种值,迭代上限只做宽松的安全网——绝不做主控制。