Claude Code Agent Loop 研究系列(04)—— stop_reason 的 7 种含义
内容提要
Claude Code Agent Loop 研究中,stop_reason 有7种含义,但循环结束不依赖它,而是检查内容是否有tool_use块。max_tokens和context超限触发自动恢复重试,refusal直接结束,pause_turn未处理。maxTurns是硬保险,Stop hook可阻断结束。真正结束需过三关:无tool_use、非恢复类型、hook不阻拦。
延伸解读
stop_reason 并非循环结束的可靠信号
文章指出,Claude Code 判断一轮是否结束,不是依据 stop_reason 字段,而是检查 assistant 消息内容中是否存在 tool_use 块。源码注释明确说明 stop_reason 为 tool_use 时可能没有实际的 tool_use 块,反之亦然。因此,stop_reason 主要用于向用户展示错误信息,而非作为循环分派的依据。
错误处理哲学:恢复而非终止
Claude Code 对 max_tokens 和 context 超限等错误,不是直接终止,而是触发自动恢复流程:上调 token 上限、注入继续消息、压缩上下文后重试。这体现了其设计哲学:能自动恢复的错误尽量恢复,只有无法挽救的错误才抛给用户。这种机制减少了人工干预,但也可能增加循环次数。
maxTurns 与 Stop hook:双重保险防死循环
为防止无限循环,Claude Code 设置了 maxTurns 硬保险,累计调用次数超限即强制退出。此外,Stop hook 可在循环即将结束时返回 block,强制再跑一轮,用于确保测试或未提交改动等条件满足。真正结束需同时满足无 tool_use、非恢复类型、Stop hook 不阻拦三个条件。
Q&A
Claude Code 中 stop_reason 有哪几种?
Anthropic API 的响应中 stop_reason 共有 7 种:end_turn、tool_use、max_tokens、stop_sequence、refusal、pause_turn、model_context_window_exceeded。
Claude Code 如何判断一轮循环是否结束?
Claude Code 不依赖 stop_reason 判断循环结束,而是检查 assistant 消息内容中是否有 tool_use 块。如果有 tool_use 块则继续执行工具,否则结束循环。
当 stop_reason 为 max_tokens 时,Claude Code 会如何处理?
当 stop_reason 为 max_tokens 时,Claude Code 会触发 max_output_tokens 恢复流程:先尝试上调 max_tokens 上限并重试;如果仍触顶,则注入一条 [Output token limit hit, continue] 消息让模型继续;最多重试 3 次,若仍失败则抛给用户。
Claude Code 对 refusal 和 pause_turn 分别如何处理?
对于 refusal,Claude Code 会生成错误消息并结束循环,不进行重试,因为重试无意义。对于 pause_turn,Claude Code 完全没有处理,源码中找不到相关分支,这是一个空白,未来接入长思考模型时可能需要补充。
Claude Code 如何防止无限循环?
Claude Code 通过 maxTurns 硬保险防止无限循环:在一次 loop 内累计 LLM 调用次数超过 maxTurns 时,强制退出循环,并追加 [max_turns_reached] 系统消息,返回 error_max_turns 错误。
Stop hook 在循环结束中起什么作用?
Stop hook 挂在循环打算结束的时刻,如果它返回 decision: block,则循环不能结束,必须再跑一轮。这用于强制模型处理未完成的任务,比如测试未跑或未提交的改动。
Claude Code 中一次真正的循环结束需要满足哪些条件?
一次真正的循环结束需要满足三个条件:内容中没有 tool_use 块;stop_reason 不是需要恢复的类型(如 max_tokens、context_window_exceeded);Stop hook 不阻拦。