Agent、Harness、Loop 到底怎么分?一条运行链看清楚
把 Agent、Harness、Loop 放在一起,经常看到的是这样一张图:Agent 干活,Harness 管 Agent,Loop 再管 Harness。
可一对照 OpenAI 和 Anthropic 的说法,这张图就对不上了。
OpenAI 介绍 Codex 时,把 Harness 说成提供核心 Agent Loop 和执行逻辑的系统。Anthropic 讲 Managed Agents 更直接:Harness 本身就是一段循环,负责调用模型、路由工具。按这个说法,Loop 就在 Harness 里面。
可聊到 Loop Engineering,Loop 又跑到一次 Agent run 外面去了。它把定时触发、验证、重试、人工接管,甚至上线后的 Badcase 都接了进来。这个 Loop,确实比一次 Harness 运行更大。
两种说法并不冲突,因为三个词说的不是同一件事:Agent 是围绕目标判断和行动的执行主体;Harness 托住这次执行;Loop 则看结果,再决定下一步。系统里,通常按一次具体的 Agent run 来记录、限权和恢复。
拿一个修测试的任务跑一遍,会更直观。
先跑一遍
任务很常见:修复一个失败的端到端测试,通过验证后提交代码。
task T42
│ 触发
▼
Agent run R1
┌────────────── Harness ──────────────┐
│ 组装上下文 → 调用模型 → 路由工具 │
│ ↑ ↓ │
│ 记录事件 ← 执行结果 ← Sandbox │
└─────────────────────────────────────┘
│ 结束
▼
candidate C1 → verifier → evidence E1
│
通过 ───────┴────── 未通过 / 未知
│ │
交付 更新 T42,启动 R2
或转人工

R1 是一次实际运行。Agent 读取任务、检查仓库、修改代码、执行测试。Harness 把上下文、模型、工具和执行环境接起来,同时记下这次运行发生了什么。
R1 里跑测试,是为了让 Agent 知道接下来怎么改。图中的 verifier 会在干净环境里再跑一遍,决定 C1 能不能往后走。两边可能用的是同一条测试命令,分量却不一样:前一次帮助 Agent 工作,后一次才产生验收证据。
测试结果回来后,通过就生成验收证据,失败就继续修改。要是预算用完、环境异常,或者结果根本看不明白,当前 run 先停下来,再由外层决定恢复、重试还是交给人处理。
这条链里已经有两个 Loop:
- run 里面,模型发起工具调用,Harness 执行后把结果送回模型;
- run 外面,验证器检查候选结果,任务系统再决定要不要启动下一次 run。
前一个 Loop 通常以秒、分钟计,后一个可能跑上几小时甚至几天。名字都叫 Loop,看的状态、手里的权限、停下来的条件却完全不同。
|
概念 |
在这条链里是什么 |
它回答的问题 |
|
Agent / Agent run |
Agent 在 |
这次由谁判断、谁行动 |
|
Harness |
承载 |
这次执行怎么安全、稳定地跑 |
|
Loop |
结果回来后的反馈关系 |
接下来继续、停止、重试还是转人工 |
Agent:这次谁来做
Agent 这个词很宽。有人用它指模型加工具,有人用它指完整产品,也有人把团队里的自动化角色叫 Agent。
落到运行架构里,Agent run 往往比单说 Agent 更准确:系统给出一个目标,Agent 实际跑了一次。这次执行能被观察,也能被终止。
一份完整的 run 记录,至少能回答几件事:
- 目标和输入是什么;
- 使用哪份上下文,能调用哪些工具;
- 预算、超时和权限到哪里;
- 动过哪些外部状态;
- 为什么结束,留下了什么结果。
模型负责判断下一步,工具把判断变成动作,环境接住动作带来的变化。代码写进了哪个 worktree,浏览器点了什么,数据库里到底有没有多出一条记录,这些都发生在模型之外。
“Agent = LLM + Harness”用来快速理解没问题,真要划系统边界就不够了。它只说了大概有哪些东西,没有说状态归谁、故障后怎么回来,也没有说谁有权确认任务完成。
Harness:这次怎么跑
我更愿意把 Harness 理解成 Agent 的运行时。一次 run 需要的能力由它接起来,不能越过的边界也由它守住。
常见职责包括:
- 选择并压缩上下文;
- 调用模型,解析模型输出;
- 路由工具,校验参数和权限;
- 管理 Sandbox、工作区和凭据边界;
- 控制预算、超时、并发和取消;
- 记录事件,处理异常与恢复。
实现时,Harness 不一定就是一个服务。桌面客户端、云端调度、Sandbox 和仓库脚本,都可能分走一部分工作。无论最后拆成几个进程,边界都落在四件事上:模型能看见什么,动作能碰到哪里,事件怎么留下来,这次运行什么时候结束。
OpenAI 拆解 Codex Agent Loop 时,主链路很朴素:用户输入送给模型;模型返回工具调用,Harness 执行工具并追加结果;模型再次推理;直到返回最终消息。一次对话轮次里,可能已经经历多轮模型调用和工具执行。
Anthropic 的 Managed Agents 又把 session、harness、sandbox 分开:session 保存不断追加的事件,harness 负责模型调用和工具路由,sandbox 把动作落到环境里。Harness 进程坏了,就按 session 恢复;Sandbox 坏了,就重建执行环境。两类故障没必要绑在一起。
Loop:下一步怎么走
Loop 说的是反馈怎么回来:先做一步,看看结果,再决定下一步。
这段逻辑可以写在 Harness 的事件循环里,也可以放进任务调度器、工作流引擎、CI 系统或产品后台。它该放在哪儿,要看两件事:它读哪份状态,又能发起什么动作。
在 R1 内,Loop 读的是 session 事件。测试报错后,模型看日志、改代码、再跑测试。它能继续调用工具,却未必有权合并代码或把业务任务标成完成。
到了 T42 这一层,Loop 读的是工作项、候选版本和验收证据。它可以结束 R1,等 CI 返回后再启动 R2。读的东西变了,权限也变了。
再往外,线上 Badcase 进入评测集,推动 Harness、提示、工具或模型配置调整。这个 Loop 改的是系统版本,眼前这次任务早就结束了。
Loop 到底在 Harness 里面还是外面,要看说的是哪一次反馈。把所有反馈都塞进最外层的一个大盒子,图是整齐了,恢复和验收的边界反而没了。
三种节奏
同一套 Agent 系统里,往往同时跑着三种节奏。
|
Loop |
正在处理什么 |
主要状态 |
停止依据 |
|
运行 Loop |
模型决策、工具执行、结果回传 |
上下文、session 事件、预算 |
模型停止、超时、取消或 Harness 规则 |
|
任务 Loop |
候选持久化、外部验证、再次执行 |
工作项、run、候选、验收记录 |
验收通过、确定阻塞或人工接管 |
|
演进 Loop |
Badcase 归因、评测、灰度、发布 |
数据集、配置、基线、版本 |
发布门禁与线上结果 |
运行 Loop 以秒和分钟计,任务 Loop 可能跨小时和天,演进 Loop 往往要跨版本。它们会互相触发,但不能共用一个含糊的 done。
R1 停止,只说明这次运行结束。C1 测试通过,说明某个候选满足当前技术检查。代码是否已合并、部署是否完成、真实流量是否生效,还要看后面的状态。
停下不等于做完
这类系统里,最容易说早了的一个词就是“完成”。
MODEL_STOPPED
↓
RUN_COMPLETED
↓
CANDIDATE_PERSISTED
↓
VERIFIED
↓
DELIVERED
↓
EFFECTIVE

模型不再调用工具,可能只是它觉得可以回答了。Harness 正常返回,只说明这次 run 收住了。测试通过,也只对接受测试的那份候选负责。代码有没有合并、部署有没有完成、真实环境有没有生效,还得继续往后看。
Anthropic 在 Agent 评测里也特意分开了 transcript 和 outcome。Transcript 记的是一次 trial 的完整过程,outcome 看的是最后环境里真的发生了什么。Agent 说“预订成功”,数据库里不一定真有这条预订记录。同样,run 日志里写着“测试已修复”,也代替不了实际测试结果。
每一层说到自己能证明的地方,就够了。
四个标识
回到开头那条链,架构图可以换,下面四个标识最好一直带着:
task_id = T42 // 这件事
run_id = R1 // 这次执行
candidate_id = C1 // 这份结果
evidence_ref = E1 // 这份结果的验证证据
task_id 让跨 run 的目标保持稳定。run_id 隔开每次执行的上下文、预算和终止原因。candidate_id 指向代码提交、制品或业务对象。evidence_ref 说明谁在什么条件下验证了哪份候选。
这条关联链一旦断了,错配很快就会出现:R2 读到 R1 的旧结论,C2 继承 C1 的测试结果,任务系统把 Harness 的正常退出当成验收通过;等线上出了问题,又找不到当时用的是哪个模型、哪套工具和哪份配置。
再看这些状态该放在哪儿:
|
状态 |
典型内容 |
更合适的持有方 |
|
Session |
消息、模型输出、工具调用、工具结果 |
Harness / session store |
|
工作区 |
文件、代码、浏览器页面、临时数据库 |
Sandbox / worktree / 外部系统 |
|
任务 |
待处理、进行中、待验证、阻塞、完成 |
调度器或业务系统 |
|
验收 |
测试报告、部署回执、人工审批、线上观测 |
CI、grader、发布或业务系统 |
聊天上下文可以压缩,Harness 可以重启,Sandbox 也可以重建。只要任务、候选和证据没有全塞在一段随时会丢的上下文里,外层 Loop 就知道该从哪里接着跑。
Managed Agents 把 session、harness、sandbox 拆开,价值也在这里:日志、决策和执行环境可以各自恢复,不用坏一个就全部重来。
Workflow 和 Loop
有人把 Workflow 理解成固定路径,把 Loop 理解成动态探索。这个说法好记,但容易把两件事讲成对立面。
Workflow 关心状态怎么流转:有哪些节点,允许哪些分支,出错后走哪条路。Loop 关心结果回来后怎么办:继续、重试、换策略,还是停下来。
状态机里完全可以有循环和动态分支。看起来很自主的 Agent,也可能只是在同一条脆弱路径上反复试错。两者放在一起更好理解:Workflow 画出有哪些路,Loop 看完反馈,再选下一段。
到了架构设计里,最后还是两个具体问题:什么证据能让状态往前走,谁有权宣布结束。这两点没说清,流程图画得再漂亮,系统照样会提前报完成,或者一直重试下去。
外层 Loop 何时有用
Peter Steinberger 把关注点从逐轮提示 Coding Agent,推到了外层 Loop:谁来触发,状态放哪儿,结果怎么验,失败后怎么回来。
Gergely Orosz 很快补了另一面:大多数团队没有无限的 token 预算,也不是每个任务都值得一直跑。他认可的场景很具体——问题难修,但结果容易验证,比如缺陷能稳定复现,又有端到端测试兜底。
两个人的说法放在一起,边界就清楚多了。外层 Loop 想跑稳,通常得有几个条件:
- 目标能被机器或独立角色检查;
- 每次执行都会留下可恢复的状态;
- 次数、时间和成本有上限;
- 系统分得清重试、换策略和转人工;
- 单次失败不会留下无法判断、又无法撤回的副作用。
修复稳定测试、补齐静态检查、处理可回滚的迁移,通常比较适合。要是结果只能靠主观判断,或者一次调用就可能付款、群发、删除数据,外层 Loop 就得谨慎得多。
比如发布请求超时,系统没收到成功响应,也不知道远端到底有没有创建内容。这时的状态是 UNKNOWN。如果外层 Loop 只认识成功和失败,直接重试就可能重复发布。先保留操作标识,再查询远端;查不清就停下来。这往往比再启动一个 Agent 更重要。
一个 Loop 靠不靠谱,很多时候就看它怎么处理“不知道”。
长任务不等于多 Agent
任务很长,也不代表一定要上多 Agent。
一次 run 配上持久化进度、干净的工作区、明确的任务清单和外部验证,已经能处理不少跨上下文工作。Anthropic 早期的长任务实验,核心也是进度文件、Git 历史、增量推进和逐项测试。
等工作能独立切开,或者生成与评估确实需要隔离时,多 Agent 的价值才会出来。Anthropic 后来的长任务 Harness 采用 planner、generator、evaluator 分工。起作用的不是角色多,而是规划、执行和验证各自有独立的上下文与职责。
每多一个 Agent,就多一份交接、冲突、合并和验收。任务边界还没理顺时,多 Agent 只是把同一份含糊复制了几遍。
碰到长任务,我会先看两件事:单次 run 能不能留下可恢复的状态,结果能不能独立验证。至于要几个 Agent,可以晚一点再决定。
再看这条链
再看开头的 T42 → R1 → C1 → E1,三个词的关系就落到了实处。
Agent 在 R1 里判断和行动。Harness 把模型、工具和执行环境接起来,也负责约束、记录和恢复。结果一回来,Loop 决定下一步往哪儿走。
一次 run 里可以有很多轮模型与工具调用;一个任务也可以经历很多次 run;线上反馈还会开启更长的系统演进。它们没有固定的上下级关系,边界来自各自持有的状态、能触发的动作和认可的证据。
三层图适合记名字。真到系统设计里,我更关心 task_id、run_id、candidate_id 和 evidence_ref 能不能串起来:哪一次执行改了什么,哪份结果经过了什么验证,失败后从哪里继续,最后由谁让 Loop 停下来。
资料展示:
下面是我整理的AI大模型 学习资料和工具包 预览,适合收藏后按主题逐步学习






更多推荐



所有评论(0)