Agent Loop 深度解析:理解、规划、行动、观察与纠错

0 阅读13分钟

一、引言

AI Agent 的关键能力来自一个持续运行的反馈循环:系统先理解任务和约束,再选择下一步行动;如果行动需要外部能力,就调用工具并读取环境返回的结果;如果结果不符合预期,就修正计划或操作;直到任务完成、达到停止条件,或者需要把决策权交还给用户。

本文将这个过程抽象为六个阶段:

输入理解 → 任务规划 → 工具执行 → 结果观察 → 错误修正 → 最终响应
               ↑                         |
               +-------------------------+

这个六阶段模型不一定对应六次模型调用,一个模型响应可能同时完成输入理解、局部规划和工具选择;一个框架节点也可能把观察与纠错合并。这里划分的是逻辑职责,而不是固定的代码模块。

它是一种工程抽象,不是行业统一标准。它的价值在于提供共同语言:无论系统采用 OpenAI Agents SDK、LangGraph、Google ADK,还是自研 Runtime,都可以用同一组问题分析其执行链路。

二、输入理解:把自然语言转成可执行任务

用户输入通常只描述期望,没有完整描述执行条件。例如:

帮我分析线上支付失败的原因,并给出修复建议。

Agent 在执行前至少需要提取以下信息:

Task
├── Goal:定位支付失败原因并提出修复建议
├── Scope:线上支付链路
├── Constraints:不能直接修改生产环境
├── Required evidence:日志、指标、发布记录、错误栈
├── Completion criteria:原因有证据支持,建议能对应原因
└── Missing information:时间范围、服务名称、环境权限

1.输入理解不是关键词分类

可靠的输入理解至少包含四个维度:

维度需要识别的内容识别错误的后果
目标用户最终希望得到什么完成了步骤,却没有完成任务
对象操作哪个文件、服务或数据集工具作用于错误对象
约束权限、时间、格式和安全边界产生越权或不可逆操作
完成标准什么证据可以说明任务完成Agent 过早停止或持续循环

2.事实与假设需要分开

可以把 Agent 初始状态表示为:

State = {
  observations: 已知事实,
  assumptions: 当前假设,
  constraints: 操作边界,
  open_questions: 尚未解决的问题,
  artifacts: 已获取的外部结果
}

“支付失败发生在数据库层”在读取错误栈之前只能算假设。如果 Agent 把假设当作事实,后续规划会沿错误方向持续展开。

3.歧义处理也是一种行动

遇到关键信息缺失时,Agent 有三个选择:

低风险、可撤销      -> 采用显式假设后继续
可通过只读工具获得  -> 调用工具补充信息
高风险或不可推断    -> 请求用户澄清或批准

请求澄清并不意味着 Agent 失败。对于删除数据、发送消息、部署生产环境等高影响操作,把控制权交还给用户是正确的运行时决策。

三、任务规划:规划的是下一步,不一定是完整路线

任务规划容易被理解成“一开始生成一份完整步骤列表”。这种做法只适合环境稳定、路径可预测的任务。

真实环境会持续暴露新信息。Agent 更适合使用滚动规划:

初始目标
   |
   v
规划当前最合理的一步
   |
   v
执行并获取新信息
   |
   v
更新状态和剩余任务
   |
   +----> 规划下一步

1.三种常见规划粒度

  • 反应式规划:每轮只确定下一步。
观察日志为空
    -> 检查日志时间范围
发现时区错误
    -> 修正查询参数
发现数据库超时
    -> 查询数据库指标

优点是能适应环境变化,缺点是容易短视或重复探索。

  • 分层规划:先生成里程碑,再动态选择每个里程碑内的行动。
目标:定位支付失败
├── 1. 确认故障窗口
├── 2. 定位异常服务
├── 3. 验证候选原因
└── 4. 形成修复建议

分层规划兼顾方向稳定和局部灵活性,适合多数工程 Agent。

  • 固定工作流:由程序预先定义执行路径。
输入分类 -> 参数校验 -> 查询数据库 -> 生成报告

它的行为容易测试,适合步骤明确的业务流程。路径已知时应优先考虑 workflow;无法预知步骤、需要模型动态决策时才使用 agent。

2.好计划需要包含验证动作

弱计划只描述“做什么”:

1. 搜索代码
2. 修改代码
3. 返回结果

可验证计划同时描述“如何知道做对了”:

1. 搜索错误码的定义和调用路径
   验证:找到错误码的产生位置和传播链路

2. 根据失败条件修改最小范围代码
   验证:变更只影响目标分支

3. 运行相关测试
   验证:原失败用例通过,相关回归用例未失败

缺少验证步骤时,Agent 很容易把“工具调用成功”误判为“任务成功”。

四、工具执行:模型提出调用,运行时负责落地

模型通常不会直接执行外部操作。它生成结构化的工具调用请求,由 Runtime 校验并分派。

LLM 输出
{
  "tool": "search_logs",
  "arguments": {
    "service": "payment-api",
    "start_time": "2026-10-26T09:00:00+08:00",
    "query": "status:error"
  }
}
        |
        v
Runtime 校验
├── 工具是否存在
├── 参数是否符合 Schema
├── 当前身份是否有权限
├── 是否需要人工批准
└── 是否达到调用预算
        |
        v
工具适配器
        |
        v
日志平台 / 数据库 / 浏览器 / Shell / 内部 API

1.工具接口是 Agent 的行动空间

对 Agent 来说,工具名称、描述和参数 Schema 共同定义了它可以采取哪些行动。下面两个接口实际能力相近,但对模型的可用性不同:

//第一种
run(command: string)

//第二种
search_logs(
    service: string,
    start_time: datetime,
    end_time: datetime,
    query: string
)

后者明确表达了参数边界,运行时也能进行结构化校验。工具接口也称为 Agent-Computer Interface,其工具文档与测试会直接影响 Agent 表现。

2.工具错误需要机器可读

只有一段模糊文本:

Error: operation failed

模型很难决定下一步。结构化错误更有利于恢复:

{
  "status": "error",
  "code": "TIME_RANGE_TOO_LARGE",
  "message": "单次查询最多支持 24 小时",
  "retryable": true,
  "suggestion": "缩小时间范围或拆分查询"
}

其中最关键的是:

  • code :稳定的错误分类;
  • retryable :是否值得重试;
  • suggestion :允许怎样调整;
  • details :供诊断使用的原始信息;
  • side_effect :失败前是否已经产生部分副作用。

3.有副作用的工具需要不同控制

工具可以按风险分层:

L0 纯计算:格式转换、数学计算
L1 只读访问:搜索、读取文件、查询日志
L2 可撤销写入:创建草稿、修改工作区文件
L3 外部副作用:发消息、创建工单、调用付费服务
L4 高影响操作:删除数据、生产部署、资金操作

风险越高,越需要参数约束、幂等键、权限隔离、审批和审计记录。Agent 的智能水平不能替代这些系统控制。

五、结果观察:工具返回值还不是结论

ReAct 的核心贡献之一,是让模型交错地产生推理和行动,并将环境观察用于后续决策。在工程实现中,“观察”是把工具原始返回转成可以更新 Agent 状态的信息。

工具原始结果
   |
   v
语法检查:返回格式是否完整
   |
   v
语义检查:结果是否回答当前子问题
   |
   v
状态更新:新增了哪些事实和证据
   |
   v
进度判断:目标是否更接近完成

假设日志工具返回了 200 条记录。Agent 不应只记录“查询成功”,而应提取:

Observation
├── 事实:09:31 后失败率由 0.2% 升至 18.4%
├── 事实:错误集中为 DB_CONNECTION_TIMEOUT
├── 关联:09:28 有数据库配置变更
├── 缺口:尚未证明配置变更导致连接超时
└── 下一验证:对照连接池指标和变更内容

工具成功描述的是调用状态,任务成功描述的是目标状态。两者必须分开。

另外,观察信息需要进入共享状态。LangGraph 把 state 描述为所有节点都能访问的共享记忆,用来保存跨步骤仍需保留的信息;其图节点读取状态并返回状态更新,这种设计可以防止执行逻辑依赖零散字符串拼接。

一个实用状态结构可以包含:

AgentState
├── user_goal
├── constraints
├── plan
├── observations[]
├── tool_calls[]
├── verified_facts[]
├── hypotheses[]
├── unresolved_questions[]
├── retry_budget
└── status

状态不应无限增长。长任务需要摘要、裁剪或外部存储,否则上下文成本会持续增加,旧信息也可能干扰当前判断。

六、错误修正:从失败中获得可用信号

Agent 的错误修正可以分成四层。

  • 调用级错误:包括参数缺失、类型错误、超时、限流和权限不足,这类错误通常不需要重新规划整个任务。
参数错误      -> 修正参数后重试
临时超时      -> 有上限地退避重试
权限不足      -> 请求授权或更换只读路径
工具不存在    -> 选择可用工具
  • 结果级错误:工具正常返回,但结果不可用,这要求 Agent 检查结果语义,而不是只看 HTTP 状态码或进程退出码。
搜索结果为空
测试命令退出码为 0,但没有运行任何测试
网页请求成功,但内容是登录页
数据库查询成功,但使用了错误时间范围
  • 计划级错误:连续几个步骤都没有减少不确定性,说明当前路线可能错误,有效修正需要改变假设、工具、查询范围或任务分解。如果 Agent 使用相同参数机械重试,它只是在消耗预算。
假设 H1
  |
  +-> 查询 A:无证据
  |
  +-> 查询 B:无证据
  |
  +-> 查询 C:仍无证据
  |
  v
放弃或降低 H1 优先级,生成 H2/H3
  • 目标级错误:Agent 发现原目标无法在当前条件下完成,例如:用户要求访问未授权系统、数据源缺失而无法得出确定结论、两个约束互相冲突、执行风险超过允许范围等,此时正确行为是停止,说明证据、缺口与可选路径,而不是编造结果。

反思并不等于重新训练模型,错误修正可以发生在推理时状态和记忆层,通过语言形式的反馈,让 Agent 总结错误并把反思文本保存在情景记忆中,以影响后续尝试,而不需要更新模型权重。

不过,自我反思不能代替外部验证。模型可能生成听起来合理、实际错误的批评。工程系统应优先使用测试结果、API 响应、规则校验器和人工反馈等外部信号。

七、最终响应:用证据证明任务结束

Agent 不应因为“感觉已经完成”而停止。停止条件通常来自四类信号:

┌─────────────────┬──────────────────────────────────────┐
│ 停止类型        │ 条件                                 │
├─────────────────┼──────────────────────────────────────┤
│ 成功结束        │ 完成标准满足,必要证据已获得         │
│ 受控失败        │ 关键条件缺失,继续执行无法推进       │
│ 等待用户        │ 需要澄清、授权、审批或主观判断       │
│ 预算终止        │ 达到最大轮数、时间、费用或调用上限   │
└─────────────────┴──────────────────────────────────────┘

一个可靠的最终响应通常包括:

  • 完成了什么;
  • 关键结论是什么;
  • 使用了哪些证据;
  • 哪些内容尚未确认;
  • 是否产生了外部副作用;
  • 用户接下来是否需要做决定。
结论:
支付失败由连接池上限配置错误引起。

证据:
- 09:28 发布将 max_connections 从 200 调整为 20;
- 09:31 起连接等待时间和支付失败率同步上升;
- 回滚配置后,测试环境的失败用例恢复通过。

已执行:
- 修改测试环境配置;
- 运行支付服务集成测试,42 个用例全部通过。

未执行:
- 未修改生产环境,生产回滚仍需审批。

这种响应保留了结果、证据和操作边界,比一句“问题已经修复”更适合审计。

八、把六阶段闭环写成最小 Runtime

下面的伪代码省略了模型供应商和工具协议细节,保留 Agent Runtime 的核心结构:

def run_agent(user_input, tools, limits):
    state = initialize_state(user_input)
    turns = 0

    while turns < limits.max_turns:
        turns += 1

        model_input = build_context(
            goal=state.goal,
            constraints=state.constraints,
            plan=state.plan,
            observations=state.observations,
            available_tools=tools.schemas(),
        )

        decision = call_model(model_input)

        if decision.type == "final":
            if completion_check(decision.output, state):
                return success(decision.output, state)

            state.observations.append({
                "type": "validation_error",
                "message": "最终输出尚未满足完成标准",
            })
            continue

        if decision.type == "ask_user":
            return waiting_for_user(
                question=decision.question,
                resumable_state=state,
            )

        if decision.type == "tool_call":
            validation = validate_tool_call(decision, tools, state)

            if not validation.ok:
                state.observations.append(validation.error)
                state = revise_plan(state)
                continue

            result = tools.execute(
                name=decision.tool_name,
                arguments=decision.arguments,
            )

            observation = normalize_tool_result(result)
            state.observations.append(observation)

            if observation.indicates_failure:
                state = repair_or_replan(state, observation)
            else:
                state = update_progress(state, observation)

    return stopped(
        reason="max_turns_exceeded",
        state=state,
    )

这个循环包含几个不可省略的控制点:

模型调用前:构建受控上下文
工具执行前:校验工具、参数、权限和审批
工具执行后:规范化结果并更新状态
最终回答前:检查完成条件
每轮结束后:检查预算和停止条件

真实系统还需要增加持久化、并发控制、幂等性、事件流、可观测性和人工介入机制。它们不会改变闭环本身,只会让闭环在生产环境中更可靠。

九、用统一模型分析不同 Agent 框架

统一阶段OpenAI Agents SDKLangGraphGoogle ADK
输入理解Agent instructions、input、context初始 state、nodeuser message、session
任务规划模型输出下一行动Agent node、条件边Agent/LLM 产生 event
工具执行Runner 执行 tool callsToolNode 或自定义 nodeRunner 处理 FunctionCall
结果观察工具结果追加到输入节点更新共享 stateFunctionResponse/event 写入 session
错误修正再次运行 loop、工具错误策略条件边、重试、interruptcallback、event loop
最终响应final output / RunResult到达 ENDfinal response event
控制机制max_turns、guardrails、approvalpersistence、interrupt、HITLsession、callbacks、plugins

十、分析一个 Agent 系统的七个问题

面对一个新的 Agent 框架或产品,可以沿以下顺序分析:

1. Goal
   用户目标怎样进入系统?

2. State
   哪些信息会跨步骤保存?

3. Policy
   谁决定下一步,模型、规则还是两者共同决定?

4. Action
   Agent 可以调用哪些工具,工具怎样描述?

5. Observation
   工具结果怎样返回并更新状态?

6. Recovery
   参数错误、工具失败和计划失败分别怎样处理?

7. Termination
   谁判断任务完成,最大预算是多少?

进一步可以增加两个生产问题:

8. Control
   哪些操作需要审批、隔离或人工接管?

9. Observability
   能否追踪模型输入、工具参数、结果、状态变化和停止原因?

如果一个系统只能回答 Action,却无法清楚解释 State、Recovery 和 Termination,它通常只是“支持工具调用的聊天应用”,还没有形成可靠的 Agent Runtime。