09.03概念更新于 2026年9月17日

Agent Loop 详解

感知、推理、行动、验证的循环,以及每一步的输入与输出。

09.03 · 课时讲解

Agent Loop 详解

模型决定下一步,运行系统执行并把结果放回上下文,直到停下。

1 / 10

一句话理解:Agent Loop 就是一个 while 循环:模型看当前信息、决定下一步动作,运行系统执行动作并把结果放回上下文,直到模型不再请求动作,或者撞上某个停止条件。

导论里的「初识 Agent Loop」建立了“观察、推理、行动、验证”的直觉。这一课把它拆到可以和工程师逐行讨论的程度:循环在代码里长什么样?每个阶段的输入和输出是什么?一条真实轨迹是怎么推进的?问题通常出在哪?

这一课之所以重要,是因为 Agent 的几乎所有问题(上下文爆炸、反复调用同一个工具、没验证就宣布完成)都发生在这个循环里。看不懂循环,就只能笼统地说“模型不够聪明”。

从一段伪代码开始

几乎所有 Agent 框架的核心,都可以简化成下面这几行:

messages = [system_prompt, user_task]

for turn in range(MAX_TURNS):
    response = call_model(messages, tools=TOOL_DEFINITIONS)  # 模型只“提议”动作
    messages.append(response)

    if not response.tool_calls:          # 不再请求任何工具
        return response.text             # 本次运行结束

    for call in response.tool_calls:
        check_permission(call)           # 运行系统:权限、审批、参数校验
        result = execute(call)           # 运行系统:真正执行
        messages.append(tool_result(call.id, result))  # 结果放回上下文

return stop_with_reason("max_turns")     # 撞上步数上限

读懂这段代码,就能纠正几个常见的错误认知:

  1. 模型本身不执行任何东西。 它只输出“我想调用 get_ticket,参数是……”,真正执行的是外面的运行系统(Harness)。权限检查、审批、超时、重试都发生在这一层,详见「什么是 Harness」。
  2. 一轮 = 一次往返。 Claude Agent SDK 文档的定义是:模型产生包含工具调用的输出,SDK 执行工具,结果自动回传给模型,这算一轮。
  3. 默认的结束条件是“模型不再调用工具”。 Claude Agent SDK 在模型给出不含工具调用的回复时结束循环;OpenAI Agents SDK 也类似,当模型输出符合预期类型的文本、并且没有工具调用时,就视为最终输出。换句话说,是否完成,默认由模型自己宣布。这正是后面「停止条件」一课要补上的缺口。
  4. 上下文只增不减。 每一轮的工具调用和结果都追加到 messages 中,二十轮之后,模型面对的是一份很长的历史记录。

把这段伪代码画成图,模型与运行系统的分工一目了然:

Agent Loop 伪代码的执行流程:模型只提议动作,运行系统负责检查、执行并把结果放回上下文 模型 只提议动作 运行系统 执行与把关 call_model 读取全部 messages 有工具调用? 返回文本 默认的结束方式 check_permission 权限 · 审批 · 校验 execute 真正执行 tool_result 追加进上下文 否 是 结果放回,进入下一轮 另有一道硬上限:轮数达到 MAX_TURNS 时,以 max_turns 为原因停止
图 1 · 一轮 = 模型提议一次 + 运行系统执行一次;默认在模型不再调用工具时结束

四个阶段的输入与输出

把一轮循环展开,可以看到四个阶段。实际运行中它们是交织在一起的,Claude Code 文档描述自己的循环是“收集上下文、采取行动、验证结果”三个阶段,并指出这些阶段会相互融合。拆开来看是为了方便设计和排查:

阶段 输入 输出 由谁完成 设计时要问
观察 Observe 任务、指令、历史消息、上一步的工具结果 模型对“现在是什么情况”的理解 运行系统组装上下文,模型阅读 该给的信息给了吗?不相关的信息是否太多?
推理 Reason 上述理解 下一步决策:调用哪个工具、传什么参数,或直接回答 模型 工具描述足够清楚吗?有没有需要遵守的顺序?
行动 Act 工具调用请求 工具执行结果或错误信息 运行系统 是否需要审批?失败时返回的错误能指导下一步吗?
验证 Verify 行动结果、预期目标 判断:继续、修正、完成,还是交给人 模型 + 程序检查 有没有客观的验证手段?验证不通过怎么办?

四个阶段连起来是一个闭环,验证决定下一轮继续、修正、完成还是交给人:

Agent Loop 的四个阶段:观察、推理、行动、验证,以及验证后的去向 ① 观察 Observe 运行系统组装上下文 ② 推理 Reason 模型决定下一步 ③ 行动 Act 运行系统执行工具 ④ 验证 Verify 模型 + 程序检查 继续 / 修正 完成 交给人 最常被省略 看到成功就收工 很多 Agent 只有 ①②③:工具返回“成功”就宣布完成,没有回头确认
图 2 · 四个阶段组成闭环,验证是最容易被省略、也最关键的一环

最容易被省略的是验证。很多 Agent 的循环实际上只有“观察 → 推理 → 行动”,模型看到工具返回“成功”就宣布完成,没有回头确认结果是否真的达到目标。「为什么必须验证」会专门讨论这个问题。

一条完整轨迹:诊断一条迟迟没处理的工单

用户输入:“工单 T-1024 为什么还没关闭?”Agent 可以使用 5 个只读工具。(下面的数字均为示例)

轮次 模型的判断(推理) 行动 结果(下一轮的观察)
1 先确认工单基本状态 get_ticket("T-1024") 用户投诉“已付款未发货”,分类“发货延迟”,状态“待处理”,创建于 9 月 3 日
2 工单已挂两周仍未处理,同时查关联订单和支付记录(两者互不依赖,可以并行) get_order("T-1024")、get_payment("T-1024") 订单:9 月 3 日已付款,未出库;支付:9 月 3 日回调失败
3 回调失败可能不是个例,查同一支付渠道近期的其他订单是否也失败 search_orders(channel="C", status="payment_callback_failed") 9 月 1 日以后有 37 单回调失败
4 验证推断:这个渠道在 9 月 1 日之前的订单是否正常? search_orders(channel="C", date_before="09-01", status="payment_callback_failed") 0 单
5 证据充分,不再调用工具,给出结论 —— 输出:原因是渠道 C 在 9 月 1 日配置变更后支付回调未同步,影响 37 单;建议由支付团队核对渠道 C 的回调配置,附上各轮查询结果作为证据

把这五轮画在时间线上,可以看清哪一轮在并行、哪一轮是模型临时决定、哪一轮在验证:

工单 T-1024 的五轮轨迹:并行查询、临时决定、找反例验证与给出结论 第 1 轮 get_ticket 先确认基本状态 已付款未发货 观察现状 第 2 轮 get_order get_payment 回调失败 并行查询 第 3 轮 search_orders 查同渠道订单 37 单回调失败 临时决定 第 4 轮 search_orders 9 月 1 日之前 0 单 找反例验证 第 5 轮 不再调用工具 输出结论 原因 + 证据 给出结论
图 3 · 每一轮的结果都是下一轮的观察;第 3 轮是 Agent 与 Workflow 的分水岭

值得注意的地方:

  • 第 2 轮是并行调用。 两个查询互不依赖,模型在同一轮发出。Claude Agent SDK 文档提到,只读工具可以并发执行,修改状态的工具则按顺序执行。
  • 第 3 轮是 Agent 与 Workflow 的分水岭。 “去查同一渠道的其他订单”这一步,不在任何预设流程里,是模型根据第 2 轮的结果临时决定的。
  • 第 4 轮是验证。 模型没有在第 3 轮看到 37 单就急于下结论,而是主动找反例来排除“回调系统整体故障”的可能。好的指令和 Skill 应该鼓励这种行为。

同样的结构也出现在 Coding Agent 中:运行测试发现失败 → 读相关文件 → 修改代码 → 再运行测试确认通过 → 输出总结。区别只是工具换成了终端和文件编辑器。

循环中容易出问题的地方

问题 表现 应对方向
上下文膨胀 几十轮后,一个大文件或一大段日志挤占了大部分上下文,模型开始忽略早期的指令 工具返回精简结果、清理旧的工具输出、压缩历史、用子 Agent 隔离,见「长任务的上下文管理」
工具错误无法指导下一步 工具只返回“500 Internal Error”,模型反复用同样的参数重试 返回可行动的错误信息,如“工单号格式应为 T- 加四位数字”,见「工具设计原则」
缺少验证 工具返回“提交成功”就宣布完成,实际没有生效 行动后读回确认,或运行程序化检查
空转与循环 同样的工具、同样的参数调用了五次 设置步数和预算上限,检测重复调用,见「停止条件」
过早结束 证据不足就给出结论 在指令或 Skill 中写明完成标准,由程序检查结论是否引用了证据
人无法介入 发现方向错了,只能等它跑完 支持随时中断和插话。Claude Code 允许用户在任何时候打断并调整方向

常见误区

  • “Agent Loop 就是模型自己在不停地跑。” 循环是运行系统写的代码,模型只负责每一轮的决策。权限、预算、审批、日志都在模型之外。
  • “模型说完成了,任务就完成了。” 默认的结束条件只是“模型不再调用工具”,这并不等于任务真的完成。
  • “循环跑得越久,结果越好。” 步数增加意味着上下文变长、错误累积、成本上升。Anthropic 在讨论 Agent 时专门提醒了成本升高和错误累积的风险。

设计要点

  • 能画出你的 Agent 每一轮的上下文组成:指令、Skill、历史、工具结果各占多少。
  • 每个工具在失败时都返回模型可以据此行动的错误信息。
  • 写动作之后都有读回或程序化验证。
  • 可以并行的只读查询,允许在同一轮发出。
  • 循环有步数上限、预算上限,以及明确的停止原因记录。
  • 完整轨迹(每一轮的输入、决策、动作、结果)都被记录下来,这是排查问题和做评测的基础,见「结果评估与轨迹评估」。

练习

标注一条真实轨迹(约 45 分钟):

  1. 用 Claude Code 或任何能展示工具调用过程的 Agent 完成一个小任务,比如“找出这个项目里所有没有单元测试的函数”。
  2. 把轨迹逐轮抄成上面那样的表格:模型的判断、行动、结果。
  3. 给每一轮标注它主要属于观察、推理、行动还是验证。
  4. 找出:哪一轮可以并行但没有并行?哪一步缺少验证?有没有重复或无效的调用?如果要把轮数减少三分之一,你会改指令、改工具,还是改上下文?

延伸阅读

下一步

循环的骨架是固定的,但“每一轮怎么想”有不同的范式。下一课「ReAct、Plan-and-Execute 与 Reflection」介绍三种经典做法。

试试:上下文、MCP、沙箱、Prompt 注入、外链