Skip to content

第 3 章:从一次请求看懂 Agent 的闭环

本章目标:不再静态拆部件,而是沿着一次真实任务执行过程,理解 Agent 如何把“目标、状态、动作、反馈”串成闭环。
本章对应总纲:docs/ebook-outline.md 中“第 3 章正文写作提纲(2026-03-31 归档)”。


3.1 为什么必须看“过程”,而不只看“能力清单”

上一章我们把 Agent 拆成了模型、工具、状态、规划、执行循环五个部件。

但只知道部件名字还不够。因为很多系统的问题,根本不出在“有没有这些部件”,而出在:

  • 它们是怎么串起来的
  • 信息是怎么流动的
  • 错误是在哪一轮被发现的
  • 系统为什么会继续、回退、停下,或者问人

所以这一章不再讲“Agent 有哪些零件”,而是讲:

当一个真实请求进入系统后,这个系统到底怎么运转?

只有把过程走一遍,你才会真正明白为什么 Agent 的本质是闭环,而不是“更长的回答”。


3.2 从一句用户请求开始:目标是怎么被建立的

假设用户说:

请帮我修复这个 TypeScript 报错。

表面看,这是一句很普通的话。但对一个 Agent 来说,第一件事不是立刻开始写代码,而是建立任务语义。

系统通常要先回答几件事:

  • 用户真正目标是什么?
  • 这是解释型请求,还是执行型请求?
  • 需要读哪些上下文才知道怎么下手?
  • 当前是否有足够信息直接行动?

这一步的关键,不是“理解文字”,而是把文字转成可推进的目标状态。

3.2.1 一个好系统不会把模糊目标直接拿去执行

“修复这个报错”本身其实信息不完整。

至少还缺:

  • 报错在哪个文件
  • 报错信息是什么
  • 是类型设计问题,还是调用点问题
  • 用户是要建议,还是要直接修改代码

所以一个靠谱的 Agent 往往会先做目标澄清。澄清不一定非要问用户,也可能通过读取环境补全。

这就是为什么读取文件、搜索代码、检查错误信息,往往会出现在真正行动之前。


3.3 第一轮:感知当前环境,而不是凭空猜

3.3.1 闭环的起点一定是感知

Agent 的第一轮动作通常不是“修”,而是“看”。

因为如果系统对当前环境没有认知,任何后续动作都只是撞大运。

在修 TypeScript 错误这个例子里,感知阶段可能包括:

  • 读取报错文件
  • 查看错误行附近代码
  • 搜索相关类型定义
  • 找调用链
  • 读取测试或构建脚本
  • 查看当前变更范围

这一步回答的问题是:

现在到底发生了什么?

3.3.2 为什么感知必须依赖真实环境

普通问答系统最容易犯的毛病,就是拿“常见情况”代替“当前情况”。

比如它会说:

  • 这可能是类型不匹配
  • 可以加类型断言
  • 可以把参数改成可选

这些都不一定错,但它们不基于当前代码状态。

Agent 不一样。它必须优先读取现实,而不是优先输出经验。

这也是为什么一个真正的 coding agent 总要不断读代码、查符号、看报错、跑检查。它不是啰嗦,它是在接地。


3.4 第二轮:基于当前状态做局部判断

当系统已经看到环境后,下一步才轮到判断。

在这个阶段,模型通常会做几类事:

  • 压缩和整理刚读到的信息
  • 识别最可能的错误源头
  • 判断下一步最有价值的动作
  • 决定是继续搜,还是直接改

3.4.1 判断不是终局真理,而是当前最优动作选择

这是很多人容易误解的地方。

Agent 并不需要在一开始就“想明白全部问题”。它更常做的是:

在当前信息条件下,选出最合理的下一步。

比如:

  • 如果报错点已经很明确,就直接改
  • 如果类型定义不清楚,就继续跳转定义
  • 如果影响范围可能很大,就先找引用
  • 如果风险高,就先确认边界

这是一种局部最优推进,不是一次性全知推理。

3.4.2 为什么这一步不能被误解成“想好了再做”

因为真实工程不是考试。

很多问题只有你动手以后,反馈才会暴露更多信息。所以好的 Agent 不会在原地空想太久,而是会在“先想一点”和“赶紧验证”之间找平衡。

这就是实用主义。


3.5 第三轮:执行动作,真正改变系统状态

3.5.1 动作是闭环的转折点

到这一步,系统才从“理解问题”进入“推进任务”。

在修错误的例子里,动作可能是:

  • 编辑类型定义
  • 修改调用点
  • 补充返回值约束
  • 删除错误的断言
  • 调整泛型参数

一旦动作发生,系统状态就真的变了。文件被改了,仓库被改了,环境被推进了。

这就是 Agent 和纯建议系统之间最现实的差别。

3.5.2 为什么动作必须受边界约束

一个系统能行动,不代表它应该乱动。

动作层必须受到至少三种约束:

  • 能力边界:它到底能调哪些工具
  • 权限边界:哪些操作需要确认
  • 任务边界:用户让它修错,不代表它可以顺手重构半个项目

Claude Code 这类系统之所以适合作为样本,就是因为它把这些边界写得很明:

  • 风险操作要确认
  • 能用专用工具就别滥用 shell
  • 不要超范围改动
  • 不要顺手做一堆“改进”

这很重要。没有边界的 Agent,不是强,是危险。


3.6 第四轮:读取反馈,判断刚才那一步有没有真的生效

3.6.1 没有反馈,动作就只是碰运气

真正把 Agent 和 workflow 拉开差距的,不只是它会执行,而是它执行完会看结果。

比如代码改完后,系统通常不会凭感觉宣布成功,而会继续:

  • 运行类型检查
  • 重新查看错误输出
  • 检查是否引入新错误
  • 对照原目标判断是否已经完成

这一步的核心问题是:

刚才那一步,真的把问题推进了吗?

3.6.2 反馈为什么是下一轮决策的输入

如果检查通过,说明当前路径可能是对的。

如果检查失败,系统就会获得新信息:

  • 原假设错了
  • 只修了一半
  • 改动影响了别的地方
  • 当前修法引入了新类型冲突

这些信息不会被浪费,而会直接变成下一轮判断输入。

于是闭环开始形成:

  • 先动作
  • 再看反馈
  • 再调整路径

这不是“失败了再说”,而是系统设计里的基本回路。


3.7 第五轮:更新状态,并决定继续、回退、停机还是求助

当反馈回来以后,Agent 不只是看到结果,还要更新自己的状态视图。

它需要知道:

  • 这个问题现在是否已解决
  • 哪条路径已经证伪
  • 哪些中间结论值得保留
  • 当前任务是否进入新阶段

然后它要做一个比“成功/失败”更细的决策。

3.7.1 四种典型去向

一个成熟的 Agent,在每轮反馈后通常会进入四种去向之一:

  1. 继续当前路径
    说明方向对,只需要再补一刀。

  2. 回退并换路
    说明刚才的判断有问题,得重新定位原因。

  3. 停机并交付
    说明目标已经满足,可以结束任务。

  4. 请求人类输入
    说明现在缺的是决策授权、业务判断或额外信息,不该乱猜。

3.7.2 人类介入不是失败,而是闭环的一部分

很多人误以为真正的 Agent 应该“全自动到底”。这很幼稚。

现实世界里,很多任务天然需要 human-in-the-loop:

  • 删除重要文件前要确认
  • 改 API 行为前要确认兼容性
  • 多种合理实现之间可能需要用户拍板
  • 权限不足时必须请人介入

所以“问人”不是破坏闭环,而是闭环的一种合法分支。

好系统知道什么时候该自主,什么时候该停下来问。


3.8 用一个简化流程图看懂完整闭环

现在可以把前面的过程压缩成一个最小运行模型:

  1. 用户提出目标
  2. 系统感知当前环境
  3. 模型判断下一步动作
  4. 工具执行动作
  5. 系统读取反馈
  6. 更新状态
  7. 判断:继续 / 回退 / 结束 / 求助
  8. 如果未结束,回到第 2 步

你会发现,这个结构并不玄学。它甚至很朴素。

Agent 的神秘感,很多时候只是因为大家平时只看到了“模型输出”,没有看到后面的这条运行链。


3.9 为什么很多系统看起来像 Agent,却经常不是

因为它们往往只覆盖了这条链的前几步:

  • 理解请求
  • 生成解释
  • 给出建议

但没有真正把:

  • 动作
  • 反馈
  • 状态更新
  • 继续迭代

串起来。

于是用户会产生错觉:

  • 它说得很像会做事
  • 它也能列步骤
  • 它还能解释每一步为什么

但这仍然不等于它真的在推进任务。

一句难听但准确的话是:

很多系统不是在执行任务,只是在模仿执行任务时该说的话。

真正的分水岭,不在它能不能把步骤讲出来,而在它有没有把步骤跑起来。


3.10 用 Claude Code 看一个现实中的闭环样本

这一套逻辑,放到当前项目里看就很直观。

Claude Code 这类环境里,一个典型任务往往会经过:

  • 用户给出目标
  • 系统先读相关文件和上下文
  • 搜索定义、引用和约束
  • 必要时补足上下文
  • 编辑文件
  • 运行测试或检查
  • 根据结果继续修正
  • 在风险操作前请求确认
  • 完成后停止

表面上看,这像一串朴素动作;但如果对照当前仓库,你会发现它背后其实有几条很硬的闭环设计规则。

先看 plugins/README.md:16plugins/README.md:19code-reviewfeature-devpr-review-toolkit 这些插件都不是一次性吐出结论,而是把分析、审查、架构、复核拆成多段执行角色。这说明当前项目默认的不是“一次想完”,而是:先做一轮动作,再根据回来的信息继续推进。

再看 examples/settings/settings-strict.json:1,它把 Bash 放进 ask,把 WebSearch / WebFetch 放进 deny。这不是权限配置的小细节,而是在告诉你闭环里有几种分叉必须被显式建模:

  • 可以直接继续的路径
  • 必须停下来确认的路径
  • 当前运行根本不允许走的路径

也就是说,一个成熟闭环不是只有“做完再看结果”这么简单,它还要把继续、停机、求助、禁止都纳入同一运行结构里。

如果再把 plugins/README.md:48 的标准目录结构一起看,你会更容易看清设计思路:

  • commands/ 负责给任务建立入口
  • agents/ 负责承载独立执行角色
  • hooks/ 负责在生命周期节点插手
  • .mcp.json 负责接外部能力

这几层合起来,才让“闭环”变成可运行的系统,而不是脑子里的流程图。

所以当前项目真正值得学的,不是某个提示词写法,而是它怎么把闭环压成几条可重复使用的规则:

  • 先读现实,再做判断,别拿经验代替当前状态
  • 动作之后一定要接反馈,别把“我觉得应该好了”当完成
  • 继续、回退、停机、求助都要显式存在,别把异常路径留给运气
  • 风险边界要进入闭环本身,而不是等出事了再补一个安全说明

这条链说明它不是“增强聊天”,而是“受控执行系统”。


3.11 一个系统什么时候才算“真的在推进任务”

判断标准其实可以非常简单。

如果一个系统面对任务时:

  • 会先读当前状态
  • 能选择并执行动作
  • 会检查动作结果
  • 会根据结果继续调整
  • 在完成、失败或需要授权时才停下

那它就在推进任务。

反过来,如果它只是:

  • 输出建议
  • 列一个计划
  • 说“你可以这样做”
  • 然后把剩下的全留给人

那它更像顾问,而不是 Agent。

顾问也有价值,但别叫错名字。


3.12 本章小结

这一章真正想让你看到的,不是某个酷炫功能,而是一条朴素但决定性的运行链。

你现在应该记住六件事:

  1. 理解 Agent,不能只看能力清单,必须看任务是如何被推进的。
  2. 一次请求进入系统后,第一步通常是感知环境,而不是直接输出答案。
  3. 判断的目标不是一次想明白全部,而是选出当前最合理的下一步。
  4. 动作之后必须读取反馈,否则系统只是碰运气。
  5. 反馈会更新状态,并决定继续、回退、停机还是请求人类介入。
  6. 真正的 Agent,不是更会描述任务,而是真的把这条闭环跑起来。

下一章我们进入更底层的问题:模型在这个闭环里到底承担什么责任,又有哪些事情是再强的模型也不该替系统结构背锅的。