🔁 Agent 循环理论 ★
把上一章的"单次工具调用"升级为"思考-行动-观察"的多步循环——这是 LangChain、LangGraph、OpenCode 三套源码共同的骨架。本章的图会在后面每一章反复出现,请务必吃透。
本章目标
- 掌握 ReAct 范式(Thought → Action → Observation 循环)
- 理解 Agent 循环的状态机三阶段模型(Plan / Execute / Update)
- 能画出 Agent 循环核心图,并说出"停止条件"如何决定循环退出
- 建立三大框架的映射关系:LangChain AgentExecutor、LangGraph 图、OpenCode runLoop 都是同一个循环的不同实现
从"单次"到"循环"
上一章我们看到一次工具调用的完整往返:模型输出 tool_calls → 执行 → 回传结果 → 模型再输出。Agent 循环就是把这个往返不断重复,直到模型认为任务完成、不再调用工具为止。
关键问题来了:谁来决定"继续"还是"停止"? 答案是——LLM 自己。这就是 F1 章说的"控制权反转"。判断逻辑只有两种结果:
- 继续(Action):模型还想调用某个工具 → 循环再来一轮。
- 停止(Finish):模型不再调工具,直接给出最终回答 → 循环结束。
Action(继续) / Finish(停止) —— 这正是 LangChain 源码里 AgentAction 和 AgentFinish 两个类的语义(LC7 精读)。整个 Agent 循环就是在这两个状态之间反复判断。
ReAct 范式:思考 + 行动
Agent 该怎么"决定下一步"?最经典、至今最常用的范式叫 ReAct(Reason + Act,2022 年论文提出)。它的核心是让 LLM 在每一步都显式地"思考"一下,再决定行动:
用文字还原一次完整的 ReAct 跑动
假设用户问:"北京和上海哪个更热?" 一个 ReAct Agent 的内部过程:
用户: 北京和上海哪个更热?
【第 1 轮】
Thought: 我需要分别查两个城市的气温才能比较。先查北京。
Action: search_weather(location="北京")
Observation: {"temp": 25, "weather": "晴"}
【第 2 轮】
Thought: 北京 25 度。现在查上海。
Action: search_weather(location="上海")
Observation: {"temp": 30, "weather": "多云"}
【第 3 轮】
Thought: 北京 25 度,上海 30 度,上海更热。信息齐全,可以回答了。
Finish: 上海更热,30 度,北京 25 度。
早期 ReAct 用文字把 Thought/Action/Observation 拼成一段文本喂给模型(解析"Action: xxx"这种格式)。现代实现(LangChain 的 create_tool_calling_agent、LangGraph 的 create_react_agent)直接用模型原生的工具调用能力,Thought 隐藏在模型内部,Action 体现为结构化的 tool_calls。但循环骨架完全一样。
状态机三阶段模型
换一个更工程化的视角看,每一轮循环(一个 "step")内部其实经历三个阶段。这个三阶段模型是理解 LangGraph 的 Pregel 引擎(LG5)和 OpenCode runLoop(OC2)的关键:
三阶段在三大框架中的对应
同一个三阶段模型,不同框架用不同名字实现,但本质一致。这张表是本教程最重要的"对照表"之一,建议截图保存:
| 阶段 | LangChain AgentExecutor | LangGraph Pregel 引擎 | OpenCode runLoop |
|---|---|---|---|
| ① Plan 规划 | 组装 prompt + 历史 | prepare_next_tasks_algo.py:371 |
读取消息、组装 system prompt |
| ② Execute 执行 | 调 LLM,解析出 Action/Finish | PregelRunner 并发跑节点_runner.py:135 |
handle.process() 调 LLMprocessor.ts:625 |
| ③ Update 更新 | 执行工具、追加历史 | apply_writes 写通道_algo.py:232 |
处理 tool_calls、判断 continue/stop |
| 停止条件 | 返回 AgentFinish |
无任务可执行 / 到达 END | assistant 无 tool_calls → break |
表里的源码行号现在看不懂完全正常。这一章的目的,是让你脑子里先装下"所有 Agent 框架都在实现同一个三阶段循环"这个认知。等学完后面三大框架的源码,再回来看这张表,会有豁然开朗的感觉——这正是 OC6 概念对照表要做的事。
停止条件:循环何时结束
循环不能无限跑下去。Agent 必须有明确的停止条件,常见有四种:
| 停止条件 | 含义 | 框架体现 |
|---|---|---|
| 自然完成 | LLM 主动停止调工具,给出最终回答 | LangChain AgentFinish;OpenCode assistant 无 tool_calls |
| 步数上限 | 防止无限循环,强制最多 N 步 | max_iterations;OpenCode agent.steps |
| 到达终点节点 | 图的执行流到 END 节点 | LangGraph END(constants.py:28) |
| 人工/中断 | 被外部中断(人在回路、取消) | LangGraph interrupt;OpenCode 取消信号 |
当 LLM 反复用相同参数调用同一个工具却得不到进展,就会陷入死循环。生产级 Agent 必须检测并打断它——OpenCode 在 processor.ts 里专门有 doom_loop 检测(连续 3 个相同工具调用就触发权限询问,见 processor.ts:354)。这是工业级 Agent 才会考虑的细节,OC4 会讲。
一张图统合三大框架
把前面所有概念收束成一张"大图"。这就是本教程后续所有章节要反复回到的总参照系:
三大框架如何实现这个循环
同一个循环,三种工程实现路线。这是本教程的核心叙事线:
LangChain 路线
用 AgentExecutor 编排:一个 while 循环,每轮调 LLM,解析出 AgentAction/AgentFinish,执行工具。最直接,但状态管理较简单。
LangGraph 路线
把循环建模成图:节点是处理函数,边是控制流(含条件边实现"调工具 vs 完成"的判断)。状态显式流转,可中断、可恢复、可并行。
OpenCode 路线
生产级 TypeScript 实现:runLoop 的 while(true) 显式循环,配合流式处理器、权限系统、上下文压缩。最贴近真实产品。
现在你脑子里已经有了同一个循环的三种视角。后面的学习就是逐层填充细节:
- LangChain 阶段:先掌握循环里每个"零件"(消息、提示、模型、工具)长什么样。
- LangGraph 阶段:把零件升级成有状态的图,学会中断、恢复、并行。
- OpenCode 阶段:看生产产品如何把这些零件打磨成可靠系统。
小结
- Agent 循环 = ReAct 范式(Thought → Action → Observation)的不断重复,直到 Finish。
- 每一步内部经历 Plan → Execute → Update 三阶段——这是理解 Pregel 引擎和 OpenCode runLoop 的钥匙。
- 停止条件四类:自然完成 / 步数上限 / 到达终点 / 中断;死循环需主动检测。
- 三大框架(LangChain / LangGraph / OpenCode)实现的是同一个循环,只是工程路线不同。
恭喜!你现在有了完整的理论锚点。接下来进入 第二阶段 · LangChain 系统,从最基础的"消息"开始,逐个零件拆解。第一站:LC1 · 消息体系——看看 LangChain 如何封装 system/user/assistant/tool 这四种角色。