Skip to main content

Loop Agent 和 React Agent 都是循环完成任务,本质区别在哪?

· 8 min read

两种 agent 表面都"循环",但决定"什么时候退出循环"的主体完全不同——这才是它们真正的分野。

  1. 决策主体:ReAct 退出由 LLM 自己判断,Loop 退出由外部规则验证。
  2. 适用场景:ReAct 适合查天气这类 3 步内 完成的轻量任务,Loop 适合老代码升级这类需要客观验证的工程任务。
  3. 工程难点:Loop 每轮会清上下文重建 prompt,反馈机制与状态持久化是真正的门槛。
  4. 真实案例Claude Code 是 ReAct 框架 + Loop 思维的混合体——LLM 驱动主循环,但把判官能力下放给 Bash 工具的 exit code。
  5. 思想定位:Loop Agent 不是新模型,是承认 LLM 会幻觉出错,结合软件工程验证与 AI 生成能力的务实架构。

一、循环的"决策权"在谁手里

最容易被忽略的事实:ReAct 和 Loop 的循环结构几乎一样,差异在「退出条件由谁判定」

  • ReAct:模型自言自语"我觉得任务完成了"就退出。判定权在 LLM 手里。
  • Loop:LLM 觉得完成不算——必须编译通过、测试通过。判定权在外部规则手里。

这一字之差,决定了两种 agent 各自的"主场"和工程难度。

二、ReAct Agent 主场:轻量信息查询

任务:「查一下北京的天气,决定要不要带伞」。

ReAct 三步搞定:

  1. Think:用户问天气,需要调用天气工具。
  2. Act:调用 get_weather(city="北京")
  3. Observe:返回「晴,28°C」 → Think:天气好,不带伞 → 退出。

这种任务完全不需要外层循环,几次迭代就结束。硬套 Loop 反而是杀鸡用牛刀——外层循环要等「验证通过」退出,可这条任务没有客观验证条件,硬造一个反而多余。

三、Loop Agent 主场:客观验证型工程任务

任务:把一个 JDK 8 老项目升级到 JDK 21。

让 ReAct 一次性跑,会发生什么?模型自信改完几个文件,prompt 里说「升级完毕」,但实际编译报错。这一步模型自己是意识不到的——它只能看到自己改了什么,看不到编译器的真实反馈。

Loop Agent 的处理方式:

  1. 第一轮:Agent 改一波文件,自评「完成」。
  2. 外层验证:触发 mvn compile客观失败
  3. 反馈重写:把最新编译报错日志拼成新 prompt,丢回给 Agent。
  4. 循环往复:直到 mvn compile && mvn test 都通过,外层循环才真正退出。

精髓不在循环,而在退出条件。循环谁都能写,判定循环是否应该退出的客观条件才是工程难点。

四、Loop Agent 的三大工程门槛

内层的 Agent 只是"不知疲倦的程序",外层循环才是"铁面无私的判官"。把外层循环写出来不难,难的是下面三件事

1. 上下文交接

ReAct 上下文会一直累积,模型能看到全部历史。Loop 通常会在每轮之间清空旧记忆,重建 prompt——只保留「任务描述 + 最新错误 + 已修改文件」。

重建不好会出问题:上一轮的修复思路、已尝试过的方案全部丢失,模型可能反复掉进同一个坑。

2. 反馈机制

「错误日志怎么写进 prompt」是个细致活。

  • 整段堆进去?上下文爆掉。
  • 截前 50 行?关键错误被截掉。
  • 丢给 LLM 让它「总结错误」?又多一层不稳定性。

需要按错误类型(编译错误、测试失败、超时)设计不同的 prompt 模板。

3. 状态持久化

中间产物放哪?部分修改的文件要不要回滚?多轮迭代后工作区是脏的,下一轮 Agent 是在脏工作区上继续改,还是先 git stash 一份?

没设计好,就会出现「改 A 报错 B」的死循环——A 修了 B 又炸,B 修了 A 又炸。

五、真实案例:Claude Code 是 ReAct 还是 Loop?

最有意思的对照实验是 Claude Code——Anthropic 官方的 CLI agent,每天被用来改真实代码库。它的执行流把两种 agent 的特征都体现出来了。

架构上是 ReAct

Claude Code 的主循环就是教科书式的 ReAct:

while (!shouldStop) {
response = await api.messages.create({ messages, tools, system })
if (response.stop_reason === 'end_turn') break
for (const block of response.content) {
if (block.type === 'tool_use') {
result = await executeTool(block.name, block.input)
messages.push({ role: 'user', content: [{ type: 'tool_result', ... }] })
}
}
}

LLM 在循环里决定调什么工具、调用顺序、什么时候结束。判定权在 LLM 手里——这是 ReAct 的核心特征。

但骨子里是 Loop 思维

如果 Claude Code 是纯 ReAct,改完代码直接说"改完了"就完事。实际上不是。

模型被强引导去主动调用 mvn compilepytestnpm test 这类命令,把退出条件客观化

  • "改完文件 → 跑测试" 是工具调用循环,模型自己驱动。
  • "测试通过没" 是工具返回值(exit code 0 / 1),不是模型自评。
  • "失败 → 看错误日志 → 改 → 再跑" 是反馈重写。

判定权名义上还在 LLM,但模型把"是否完成"外包给了 exit code——这正是 Loop Agent 的精髓。

执行流程

外层的"判官"位置,Claude Code 没有硬编码在 while 循环外,而是通过工具能力下放给模型——Bash 工具就是万能判官,模型想跑什么验证就调什么。

其他扩展点

  • max_turns 熔断:防止模型陷入死循环。
  • 用户中断:按 Esc 随时打断当前执行。
  • HooksPreToolUse 可以拦截危险命令(删库、force push),PostToolUse 可以追加 context(lint 报错自动塞进下一轮 prompt)。
  • 子 Agent:Task 工具派生一个全新的 Claude Code 实例,自带独立 context——这就是嵌套的 Loop Agent

结论

Claude Code 不是一个标准的 Loop Agent(没有显式的「执行-验证-重试」编排),也不是一个纯 ReAct Agent(把验证外包给了 exit code)。它是一个ReAct 框架 + Loop 思维的混合体:

  • 框架上 LLM 当判官(ReAct)。
  • 工具上把判官能力下放给 Bash(Loop)。
  • 控制上 hooks + max_turns + 用户中断兜底(生产级工程化)。

如果你想理解"Loop Agent 的思想在主流 agent 里怎么落地",看 Claude Code 源码比看任何 workflow 引擎都直观。

六、思想定位:AI + 软件工程的握手

Loop Agent 不是什么高深莫测的新型大模型,它是一种极其务实的架构思想

  • 承认 LLM 会幻觉、会出错、上下文有限。
  • 把传统软件工程的客观验证(编译、测试、断言)和 AI 的生成能力握在一起
  • 落地形态可以是显式 workflow 引擎(结构化任务),也可以是 Claude Code 这类 agent runtime(开放式任务)——核心都是在可控性上叠加 AI 的灵活性

回头看,ReAct 本身也是一种 workflow。它是 LLM 自己当判官的极简 workflow,Loop 则是把判定权交给外部规则的强化版。

很多人低估了 workflow——觉得「不过是 if-else 编排」。但只有把可控性和灵活性结合起来,AI 应用才能从 demo 走到生产。Loop Agent 的价值,就是把这件事讲清楚了。

References

  1. Loop Agent和ReactAgent都是循环完成任务,有什么区别? —— 徐庶说技术, 哔哩哔哩, 2026-05-26
  2. Claude Code Overview —— Anthropic 官方文档