你的 Agent 并不自主:你就是它的循环

它写你读,它说"搞定了"你验。这三层不是三件工具,是台阶:harness 给手脚,循环给能失败的检查,图给形状和闸门。

分享
你的 Agent 并不自主:你就是它的循环

你并不是在"使用"你的 Agent。

你就是它的循环。

它写,你读。它说"搞定了",你验。它弄坏了什么,你解释坏在哪,然后你再敲一遍。

这三个动作一直重复,说明系统本该干的三件事没人干:

  • 给模型一个能干活的地方;
  • 告诉它到底对不对;
  • 决定下一步发生什么。

这三件事有名字:Harness、Loop、Graph。

大多数文章把它们并排摆在架子上当三件工具,这恰好是它们看起来费解的原因。它们不是菜单,是梯子。 上面一层之所以存在,是因为下面那一层会以某种特定、可预测的方式坏掉。

下面七个等级,每一级只讲三件事:加了什么、修了什么、以及把你推到下一级的那次具体失败。一个例子贯穿全文:来了一张 bug 报告,Agent 要修好它并开 PR。

一、30 秒地图

层 回答的问题 落在什么上
Harness Agent 能做什么 环境
Loop 什么才是真的 证据
Graph 接下来发生什么 授权

以及你要爬的这七级:

层 名字 一句话
0 聊天 所有事都是你
1 Harness:手 它能动手
2 Harness:记忆 它能接着干
3 循环:检查 它能当着你的面错
4 循环:反馈 它能从错里爬出来
5 图:形状 工作有了对的形态
6 图:闸门 错误留在一个小格子里
7 学习 同一个错误不再回来

二、Level 0 聊天:系统里唯一没干脏活的部件是模型

你把 bug 报告贴进去。模型给一个修法。你复制到编辑器,跑测试,把报错贴回去,再问一遍。

看谁在干什么:

岗位 谁 具体在做什么
Harness 你 你的手替它跑代码
Loop 你 你的眼睛判断有没有成
Graph 你 你的脑子决定下一步

模型是这个系统里唯一不干脏活的部分——它是一个非常聪明的函数,而你是围着它的整个程序。

一次性提问,这没问题。任何要做第二次的事,这是灾难。

坏在哪:你。 三个岗位同时压在同一个人身上,你就是瓶颈。

三、Level 1 Harness:给它一双手

第一个修法太明显了:让 Agent 碰得到世界。shell、文件读写、一个测试运行器、git,任务需要时再加浏览器。

我见过最干净的 harness 定义是这个:把模型从你的架构图里删掉,图上还剩下的东西全部是 harness。

现在 Agent 自己读仓库、改文件、跑测试,不用再复制粘贴。

但注意 harness 到底是什么。它不是"更多工具"。每加一个工具,就多一个模型可以选错的空格。十个窄的、有文档的工具,胜过四十个互相重叠的。 给它能完成这件活的最小环境。

坏在哪:它动得了手,但没有记忆也没有围墙。

四十分钟后,上下文里塞满了测试日志。压缩一次,Agent 忘了哪个修法已经试过,于是又试一遍。而它对所有东西都有写权限,包括那个它绝不该碰的配置文件。

四、Level 2 Harness:记忆与围墙

缺的是两样东西:活得过上下文窗口的状态,和不依赖模型表现的界限。

记忆活在模型外面:

PROGRESS.md
  goal       fix #482: login redirect loop
  tried      reorder auth middleware  ->  still red
  known      only happens when the session cookie is expired
  next       inspect auth/refresh.py
  never      touch migrations/

再加上用 git 提交当检查点,以及产物按引用传递——而不是把整段记录再贴一遍。

上下文窗口是内存,harness 是硬盘。模型会忘,文件不会。

围墙是所有"模型错了也照样成立"的东西:最小权限、隔离的 worktree 或沙箱、命令白名单、硬性的 token 与时间预算(这条线上已经有人在生产系统里做:沙箱里根本不存凭证)。

围墙不是指令。"请不要动 migration"是一个愿望。Agent 没有那个权限,才是墙。

现在它能干一小时、崩溃之后接着干,并且弄不坏重要的东西。

坏在哪:它以"修好了!测试应该都过了"结账。

应该。

Harness 让 Agent 有能力。系统里没有任何东西让它正确。一个有本事但没检查的 Agent,只是更快地、更自信地错。

五、Level 3 循环:一个能失败的检查

循环是四个动作:产出、检查、纠正、重复。

所有人都在盯"重复"。唯一重要的是"检查"。没有一个真能失败的检查,"重复"就只是"重复同一个错误"。

证据不是等价的,按伪造难度排:

强度 类型 例子
最强 确定性 测试 exit 0、schema 通过、构建编译过
次之 可观测 trace:它到底是真跑了测试,还是只说跑了
再之 独立 另一个上下文、另一份提示词里的评审者
最弱 自述 "我有信心""看起来没问题""没有报错"

规则是:一个检查只和它接受的最弱那种证据一样强。 如果你的循环接受"模型说完成了",那这个循环就是自述,堆多少步都一样——这条已经被单独量过一次,同一句"搞定了"在终态和重复 20 次面前站不住。

现在,在 Agent 写第一行代码之前,先把这张单子的检查写出来:

GREEN when
  a new test reproduces #482 and FAILS on the current code
  the same test PASSES after the fix
  the full suite is green
  the diff touches only auth/

看第一行。一个在修复前就已经通过的测试,什么都证明不了。 检查必须有可能失败,而且你得亲眼看到它失败一次。

这里有个隐藏的好处:如果你写不出这个检查,说明你还没想清这个任务。 写检查就是在写规格。

坏在哪:Agent 失败、重试,然后用同样的方式失败六次。

因为"红"不是反馈,是判决。

六、Level 4 循环:能收敛的反馈

判决说的是"错了"。反馈说的是"错在这里、错成这样、而且这条路你已经走过"。

最简单的形状,是"它预期的"和"世界实际给的"之间的那个差:

FAILED      test_expired_session_redirect
EXPECTED    302 -> /login
SAW         302 -> /dashboard      (auth/refresh.py:61)
FENCE       auth/refresh.py only
DEAD ENDS   middleware reorder

EXPECTED 和 SAW 把一盏红灯变成方向。FENCE 把下一次尝试关进一个文件里。DEAD ENDS 是这个循环自己的记忆,这样第三次尝试不会悄悄变回第一次。

然后是出口。没有出口的循环不是坚持,是持续漏钱:

EXIT when
  green                          ->  done
  the same SAW comes back twice  ->  stop and escalate
  budget spent                   ->  stop and escalate

中间那条最重要。当 Agent 拿到完全相同的结果两次,它已经不在从循环里学了。更多尝试帮不上忙,因为缺的不是努力——是它看不见的某个东西,或者一个本来就被问错的问题。

循环能修工作。循环修不了问题本身。

坏在哪:一件一件地看,工作质量变得极好。

但真实工单上写的是:修登录循环,顺便查另外两个服务是不是用了同一个刷新 helper,然后更新文档。

于是 Agent 一行一件、在一个上下文里全做完:先修,再审计 billing,再审计 admin,最后写文档。admin 的审计读到 billing 的结论,于是把那些结论重复一遍。

每一步都对。整体慢、串行,而且只有一个观点。调循环怎么调都没用,因为问题不在任何一步里面,在它们之间。

七、Level 5 图:工作的形状

一个图是三样东西:

NODE    one bounded job: one input in, one output out
EDGE    a real dependency: this output feeds that input
STATE   what survives between nodes

工作流里大多数箭头不是依赖,是习惯——某个人当初想到这些步骤的先后顺序。

所以每条箭头都过一遍"早开始测试":如果 B 在 A 完成之前就开始,什么会坏?

答案如果是"什么都不会坏",这条箭头就是习惯,为它等的每一秒都是浪费。

修复还没落地就开始 billing 的审计——会坏吗?不会。

修复还没落地就开 PR——会坏吗?会。那条箭头是真的。

这张工单重画之后:

                         -> FIX auth/refresh.py ------\
ISSUE #482  ->  SCOPE  ->  -> AUDIT billing -------------> MERGE -> GATE -> PR
                         -> AUDIT admin --------------/
                         -> UPDATE docs --------------/

几个选择决定这张图是真帮忙,还是只是看起来厉害:

  • 在会分开失败的地方切。 两件事如果会因为不同原因坏,就是两个节点;如果总是一起坏,就是一个。
  • 给每个 worker 自己的房间。 四个 agent 共享一个上下文不是团队,是一个 agent 戴四顶帽子——第一份写下来的意见会变成所有人的意见。
  • 问"同一个答案"的问题。 这一步如果同样输入永远给同样输出,就写成代码:合并、排序、去重、计数。模型留给那些"换个答案也可能对"的步骤。
  • 闸门放在工作离开一个节点的地方,不要放在最末端——末端每个错误都已经和别的东西混在一起了。

两层怎么咬合:循环问"这一块对不对",图问"这几块是不是对的那几块"。两个都要。 上图每个 FIX 和 AUDIT 节点内部,都在跑自己的 Level 4 循环。

坏在哪:两件新事,都很难看。

一个审计失败,整批重跑。三个好结果回来时变了——不是更好,只是不同,于是现在全都要重新检查一遍。

以及,所有过闸的东西以同样的速度移动:文档里一个错别字和认证流程的一次改动,得到完全一样的对待。

八、Level 6 图:闸门与回流

冻结已经通过的东西。

一个节点的输出过了闸就变成只读,下游任何人都不许把它重新打开。有东西失败时,只重跑失败的那个节点——带着它的反馈——冻结的结果原样不动。

每一次重跑好工作,都是又一次弄坏它的机会,而你要拿回的什么都没有。

闸门看撤销的价钱。 信心是模型给自己判卷。更好的问题是:如果这是错的,把它收回来要花多少?

档 撤销是什么 例子 怎么放行
一键撤销 回滚一个提交 文档、测试、一个函数 绿了就发
要清理 修它碰过的地方 共享 helper、schema、认证流程 绿 + trace + 第二意见
撤不回来 已经发生了 migration、删除、已经发出的邮件、花钱 人来签

最后一档身上一个分数都不挂。不是 0.95,不是 0.99。没有数字可以让模型去够,也就没有什么可争的。

前两档里,读证据要按阶梯顺序:先测试,再看 trace,再看第二意见,模型的自信排在最后。

模型给改动贴标签,代码决定这个标签解锁什么。 模型可以说"这碰到认证了";"认证"意味着一次审批还是两次,是运行之前就写在代码里的。已经有产品把这一档做成了默认行为:不可逆的动作仍然停下来等人点头。

只在撤销不存在的地方花你的注意力。你是这张图里最贵、最慢的节点。 把自己放在错误收不回来的位置,别的地方都不用放。在我们的例子里:文档改动自己上线,认证修复等一次 PR 审批,审计只要不打架你就不用读。

坏在哪:它跑通了。

然后下一周,同一类 bug 来了。Agent 做出同样的第一次错误尝试,烧掉同样的两次重试,落在同一个修复上。系统很快,但跨运行没有记忆。你在付钱让它把同一课学两遍。

九、Level 7 系统逐层学习

走到这一步的人,大多加一条回到规划器的反馈边就停了。

但每一次失败都归属于某一层,而一个教训只有落在拥有它的那一层上才留得住:

失败 教训变成 层
Agent 看不到生产日志 一个只读的日志工具 HARNESS
把上周试死的路子又试一次 never 清单里的一条 HARNESS(记忆)
没有复现测试就说"修好了" 一条新增的必过检查 LOOP
billing 和 admin 的审计撞在一起 一条新的拆分规则 GRAPH

教训放错层,就变成建议。"注意不要重复劳动"写在提示词里是一个希望;写在拆图规则里才是结构。

而且教训是约束,不是记录。你不把上周的日志喂进下周的运行,你喂那些日志教会你的那一条规则。

Level 7 的测试很简单:同一类失败,不会让你付两次钱。

十、你在第几层

从上往下找第一个对得上的症状,那就是你的下一层。不是再下一层。

症状 缺的层
你在聊天窗口和终端之间复制粘贴 1 Harness:手
Agent 反复试它已经试过的路子 2 Harness:记忆
"完成了"这句话不作数,你得自己看 3 循环:检查
重试在同一个错误上烧预算 4 循环:反馈
每一步都对,整体却慢 5 图:形状
一处失败就全体返工,事事都要你 6 图:闸门
同样的错误每周都出现一次 7 学习

十一、怎么往上爬

不能跳级。 十个没有检查的 agent 不是十倍产出,是十倍清理。一个完美的循环如果没有 harness,就没有地方跑它的测试。

但设计要从中间开始。 动手之前,先在纸上写 Level 3 的那个检查。如果你说得出"绿"是什么意思,你就知道 harness 需要哪些工具来证明它,也就知道图该把闸门放在哪里。

如果你说不出"绿"是什么意思,哪一层都救不了你。

你也不需要爬到顶。 大多数任务在 Level 4 就结束了。只有当这一层的失败比你建下一层更贵的时候,才继续往上。

十二、简短版

Harness 让 agent 有能力,循环让它诚实,图让它有条理,学习让它比昨天好。

少一层,那个缺口就由你来补。

目标从来不是一个不需要你的 agent。而是一个只在正确的位置需要你一次的系统。

十三、我们的整理:明天就能改的三件事

原文的框架好用,但它是一张地图,不是一份施工图。把它的判据落回我们自己的工单,其实只剩三样东西——而且都在 bug 发生之前。

第一,三个岗位各留一件物证。

岗位 该有的东西 大多数团队现在有什么 判据
Harness 一份进度文件(目标/试过/已知/下一步/绝不碰)+ 只读日志入口 一段塞满日志的对话 崩溃之后能接着干,不用重读历史
Loop 一条能红、而且你亲眼见过它红的检查 "跑一下看看" 修复前红,修复后绿
Graph 一张冻结清单 + 三档闸门 全靠最后那一次总评审 单点失败只重跑那一点

第二,把"反馈"翻译成四个字段。 这四个字段可以直接抄进任务卡,不依赖任何框架:

  • EXPECTED:我以为会发生什么(具体到状态码、行号、字段值)。
  • SAW:实际发生了什么(贴原文,不要总结)。
  • FENCE:这一轮只许动哪个文件。
  • DEAD ENDS:这轮之后,哪条路不要再走。

第三,三条比原文更硬的判据。

  1. 写不出"绿"的定义,就别开工。 这是唯一一条能挡住后面所有层的规则。
  2. 同一个 SAW 回来两次就停手。 第二次相同结果是"模型看不见某个信息"的信号,不是"再努力一点"的信号。
  3. 人只在不可撤销的地方出现。 其余位置放人,等于把最贵的节点浪费在最便宜的判断上。

四条边界,我们替原文打折的地方。

  • 这篇文章没有任何样本、基准或现场数据。七个层级是一个人的经验框架,不是测量结果。它的价值在"症状 → 缺哪层"那张对照表,不在"7"这个数字。
  • 作者在文末给自建频道导流。框架本身不受影响,但别把文中的判据当成行业标准——它是设计意见,不是规范。
  • "不能跳级"当经验法则用没问题。工程上更准确的说法是:可以少建一层,不能少理解一层。两个人的团队在 Level 1 上直接加闸门,比按顺序补齐三层更现实。
  • 原文的层级图和几张对照表都是纯文本画的,我们按语义重画成中文表,没有增删条目;ASCII 工单图原样保留。

相关阅读


来源:@m4lkxx《Harness, Loops, Graphs: What Each Layer Fixes and What It Breaks》,2026-10-25,原文(X 长文,需登录)。图由我们按原文语义重画为中文表格,ASCII 图保留原样。

本文由汇智网 · Software 2.0 编译整理,转载请注明出处。

这是「Agent / MCP」专题的一部分。完整地图见:Agent / MCP / 自动化完全指南