Claude Code 代理循环的三大阶段(从收集上下文到验证结果的闭环反馈)

把 Claude Code 的工作引擎拆开看,整套 agentic loop 由”收集上下文—采取行动—验证结果”三个阶段构成,并且会反复迭代直到任务完成或被用户打断。三个阶段并非线性流水线,而是一条”工具结果驱动下一轮决策”的反馈链,理解这条闭环结构是判断 Claude 在长任务里为什么会突然跑偏、又为什么能自我修正的关键。Anthropic 公开文档把这套机制列为 Claude Agent SDK 的核心设计模式。

(项目背景:在排查一个分布式链路里偶发的 502 时,一开始把任务写成”修一下 502″,模型只能给到泛泛的猜测。拆成”先读上游网关日志 → 改重试策略 → 跑压测验证”三步后,循环才真正被激活,几轮之内定位到根因。)

一、三阶段总览

“收集上下文—采取行动—验证结果”是 Claude Code 文档原话,三个阶段随时可被用户中断并重新引导。

阶段 模型在做什么 典型工具 输出
收集上下文 理解当前项目状态与任务边界 Read、Grep、Glob、Bash 文件树、符号表、运行日志
采取行动 决定下一步动作并执行 Edit、Write、Bash 文件修改、命令执行
验证结果 评估动作是否达成目标 Bash、Read 测试输出、类型检查结果

三个阶段并不按固定顺序切分,而是按工具结果在上下文窗口里实时拼接。一次”问代码库”任务可能只走第一个阶段;一次 bug 修复会在三个阶段之间反复横跳几十次;一次大规模重构则会把第三个阶段拉得很长。

二、收集上下文:循环的起点

Claude 拿到任务后并不立即行动,而是先调用工具建立”项目地图”。这一步会读 CLAUDE.md、auto memory、项目目录树、Git 状态,以及与任务直接相关的源文件。官方文档明确指出,工具返回的每一个结果都会进入上下文窗口,成为下一轮决策的依据。

// 收集上下文的典型工具组合
1. Bash  ->  git status -sb            // 看未提交变更
2. Read  ->  src/services/auth.ts     // 读目标文件
3. Grep  ->  'TODO' src/              // 搜索遗留标记
4. Read  ->  package.json             // 确认依赖与脚本

这一步决定了后续行动的方向。在小问题上 Claude 也许只读一两个文件就够;在跨服务改动中,它会把上下游几十个文件全读一遍,再决定哪一段需要改。

2.1 上下文窗口的可见反馈

每条工具调用的输入输出都会占用上下文窗口。窗口快满时,Claude Code 会自动 compact(压缩)历史消息,把靠前的内容替换成摘要。用户也可以手动 /compact 提前腾空间。理解这一机制能解释”为什么模型突然忘了开头交代的命名约定”——它们被压缩掉了。

上下文窗口组成(近似比例)
+----------------------------+
| 系统提示 + CLAUDE.md       |
| 当前任务与最近工具结果     |
| 历史消息(可被压缩)       |
+----------------------------+

三、采取行动:闭环里的”做”

在第二步里,Claude 根据上一阶段的信息选定一个工具,执行,再把结果放回上下文窗口。关键约束是:一次循环只发生一个动作,不存在”先把整个计划写完再依次执行”。

工具 类别 典型用途
Read 文件操作 读文件拿正文
Edit / Write 文件操作 改写、创建
Bash 执行 跑测试、构建、git 命令
Grep / Glob 搜索 全局文本或文件名匹配
WebFetch 网络 抓取外部文档
Task 编排 派生 subagent 并行处理

工具选择由模型根据上文推断,没有预编程的”先 A 后 B”流程。这种”自由选择工具”是 agent 与传统 chat 的分水岭——后者只能一次性输出文本,前者能反复操作真实环境。

3.1 行动的反馈粒度

工具结果以原始字节流的形式回到上下文,包括 Read 出来的整段文件、Bash 输出的全部 stdout/stderr、类型错误的完整堆栈。结果越详细,下一轮决策越准;反之,如果某个工具只回传”成功”两个字符,模型就缺少可修正的依据。

# 反例:把命令写成只输出状态
git pull && echo "ok"
# 正例:保留 stderr 便于诊断
git pull 2>&1

四、验证结果:闭环里的”测”

行动之后必须验证。验证的常见手段是跑测试、检查类型、读取命令输出,对比预期与实际。验证失败时,模型不会停下,而是把失败信息重新送进上下文,进入下一轮循环。

闭环反馈的一个完整例子
[用户] 修复 src/auth.ts 的 null 报错
[模型] Read src/auth.ts                  -> 上下文
[模型] Edit 增补 null 判断              -> 行动
[模型] Bash 跑 npm test                  -> 验证
[结果] 用例 #7 失败
[模型] Read 测试输出片段                 -> 上下文
[模型] Edit 修正判断条件                 -> 行动
[模型] Bash 重跑 npm test                -> 验证
[结果] 全部通过,循环结束

4.1 验证失败的自动回退

验证不通过不会抛错退出,而是把”我刚才尝试过什么、错在哪里”沉淀到上下文,下一轮循环继续修正。这意味着只要给得出”完成信号”(比如”测试全部通过”),Claude 就能自己跑到结束;如果任务本身没有清晰的验收点,循环很可能在原地打转。

4.2 用户随时可以打断

循环再长,用户随时可介入。Esc 键停止当前动作,追加上下文或换方向即可;/rewind 可以回退到之前的检查点并尝试新方案。这种”人在回路”的设计把 agent 的自主性收敛在可控范围内。

五、闭环设计给使用者的启示

把这三个阶段想清楚,能直接优化提问方式。

  1. 任务要带可观察的完成信号(”测试全绿””构建无错误””接口 200″);
  2. 命令保留 stderr,工具结果越详细模型越准;
  3. 上下文窗口快满时主动 /compact 或 /clear;
  4. 长链路任务用 subagent 并行处理,避免主上下文被噪声淹没;
  5. 同一问题被纠正超过两次时,清空上下文用更具体的 prompt 重启。

把任务描述和工具结果都设计成”可被循环消化”的形态,Claude 才能在三个阶段之间稳定地穿梭到底。

常见问题(FAQ)

Q1:为什么 Claude 有时反复做同样的尝试?

通常是因为工具结果没回传到上下文,或完成信号太模糊,循环没有可收敛的判定点。

Q2:如何让循环更快结束?

给出明确的完成条件(”测试通过””文件存在””接口返回 X”),避免开放式指令。

Q3:subagent 在循环里扮演什么角色?

subagent 在独立上下文窗口里执行子任务,把摘要回传主循环,是减少主上下文噪声的常用手段。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 qiqicto@qq.com 举报,一经查实,本站将立刻删除。
赞 (0)
赵其鑫的头像赵其鑫管理团队

相关推荐

返回顶部