工程化 / Loop Engineering
1. 从和智能体对话到设计运行循环
原文备份 · 第 3 / 13 篇 · 查看极客时间原知识库 ↗
本篇目录 · 22 节
预计阅读与练习时间:30~40 分钟
本篇目标:分清 Agent 内部的工具调用循环与 Loop Engineering 管理的多次运行,判断一个任务应该由人处理、交给一次 Agent 运行,还是设计成一个有边界的循环。
你大概做过这样的事:把任务交给编码 Agent,等它修改、测试、修错,再根据结果补一句提示。第二天又来一个相似任务,于是重复同样的交接和检查。
如果这些任务足够多,很容易产生一个诱人的想法:写个定时器,不断调用 Agent,失败就再试,直到成功。
问题也从这里开始。它怎样知道自己真的有进展?重启后从哪里继续?同一个错误出现三次时,是继续消耗 Token,还是停下来?测试被 Agent 改弱之后,“全部通过”还可信吗?遇到需要产品判断或高风险权限的任务,又由谁接手?
Loop Engineering 关心的不是怎样让循环转起来,而是怎样让它在正确的时候继续,在不该继续的时候结束。
一、先承认:这是一个正在形成的术语
Loop Engineering 还不是一套已经定型的行业标准。IBM 在 2026 年 7 月发布的介绍中,把它描述为设计迭代式 Agent 工作流的实践:系统围绕目标反复行动、观察和调整,而不是每一步都等待人重新提示。IBM 概念说明
一项 2026 年的探索性研究则梳理了当时的公开实践,发现较稳定的共同元素包括:触发 Agent 运行、机器可检查的停止条件、持久状态、独立验证者、Token 或时间预算,以及明确的人类升级点。作者也强调,这一领域仍缺少充分的实证研究,不能把流行说法直接当成成熟结论。探索性研究
因此,这套教程不会把某个脚本或某家产品包装成“标准答案”。我们采用一个够具体、也方便检验的工作定义:
Loop Engineering,是对多次 Agent 运行之间的触发、任务选择、状态传递、结果验证、预算、重试、隔离、停止和人工升级进行工程化设计。
这一定义里最重要的词不是“循环”,而是“多次运行之间”。
二、先分清四个容易混在一起的层次
同一个 Agent 工作过程里,往往同时存在 Prompt、Context、Harness 和 Loop。它们会配合,但解决的问题不同。
| 层次 | 主要问题 | 例子 |
|---|---|---|
| Prompt Engineering | 这一轮怎样把目标说清楚 | “修复搜索为空的问题,不要改数据文件” |
| Context Engineering | 当前决策前应该让模型看到什么 | 选择相关代码、错误日志和产品规则 |
| Harness Engineering | 一次运行怎样行动、观察并验证 | 文件工具、终端、浏览器、测试、权限与仓库说明 |
| Loop Engineering | 多次运行怎样接力、恢复并结束 | 触发器、任务队列、持久状态、预算、重试和升级 |
可以把 Harness 想成一名 Agent 上班时使用的工作台,把 Loop 想成安排多次轮班的调度与控制系统。工作台不好用,增加轮班次数只会更快地产生混乱;只有单次运行已经能理解项目、使用工具和读取验证结果,外部循环才有可靠基础。
这也是为什么本教程的 Issue Garden 不从一个空仓库开始。课程会提供一份具备基础说明、测试、诊断和权限边界的 ShelfCare 快照。没有学过 Harness Engineering 也能直接开始,但我们不会假设一个完全没有验证能力的项目适合自动循环。
三、“Agent 自己反复调用工具”还不是本教程的 Loop
现代编码 Agent 在一次任务里,本来就会多次调用模型和工具。OpenAI 当前的 Agent Runner 文档把一次 SDK run 视为一个应用层 turn:Runner 调用模型,执行工具或处理交接,再把结果送回模型,直到得到最终输出、需要审批或遇到其他真实停止点。OpenAI Agent Runner 文档
一次运行内部可能是这样:
模型规划
-> 读取文件
-> 模型决定修改
-> 写文件
-> 模型决定测试
-> 运行测试
-> 模型观察结果并修复
-> 返回最终回答
虽然这里也在循环,但它仍属于一次 Agent 运行:共享同一段会话状态,由 Agent 的 Runner 决定何时结束。
本教程要搭的是它外面的控制循环:
触发器发现任务
-> 外部 Runner 选择一个任务
-> 启动一次 Agent 运行
-> 收集退出码、Diff 和报告
-> 独立运行验证器
-> 保存本轮状态
-> 决定完成、再试、换策略、等人或停止
-> 必要时再启动下一次 Agent 运行
这两层不要混为一谈。Agent 内部工具调用次数很多,不代表它已经具备跨进程恢复、全局预算、任务去重和人工升级;外部 Runner 能重复启动 Agent,也不代表单次运行里的工具、上下文和验证已经设计好。
后面的课程统一使用两个术语:
- 一次运行(run):从外部 Runner 启动 Agent,到它返回或中止;
- 一轮(round):外部循环围绕一个任务完成“启动运行、收集结果、独立验证、保存状态和作出下一步决定”的完整过程。
一个任务可以经历多轮,每轮内部又可能包含许多次模型与工具交互。
四、最小可用循环必须包含什么
把 Loop Engineering 压缩到最小,至少要回答六个问题。
1. 目标:这一轮究竟要改变什么
“继续改进项目”不是目标。一个可循环处理的任务应该足够小,并且有稳定标识,例如:
issue-001:修复搜索框输入全角空格时无法匹配书名的问题
稳定 ID 用来去重和恢复;明确范围用来防止 Agent 把一次维护任务扩展成整库重写。
2. 动作:本轮允许 Agent 做什么
动作不仅是“调用模型”。还包括允许读取哪些文件、能否写代码、可以运行哪些命令、是否能访问网络,以及结果是否允许提交或发布。
Issue Garden 默认只允许修改本地实验副本、运行项目已有检查和查看 Git Diff。它不会自动合并、部署或访问真实外部服务。
3. 观察:怎样知道这一轮发生了什么
至少要保留:Agent 退出状态、修改文件、验证输出、耗时和本轮报告。只有最终一句“已完成”,无法支持下一轮判断。
4. 验证:谁来判断结果是否满足目标
Agent 可以自查,但不能把它的自述当成唯一证据。循环需要在 Agent 运行结束后,由外部 Runner 执行受保护的测试、规则检查和 Diff 审查。
5. 调整:失败后为什么值得再来一轮
重试应该有新的信息或新的策略,例如补充缺失日志、缩小任务,或用干净上下文重新开始。如果输入、上下文和做法都不变,只是再次发送同一句提示词,那不叫纠偏,只是在碰运气。
6. 停止:什么时候不再启动下一轮
至少要包括:任务验证通过、达到最大轮次、耗尽时间或费用预算、连续出现相同失败、缺少必要信息、触发权限边界,以及人主动取消。
把它们连起来,才是一条完整控制链:
目标 -> 动作 -> 观察 -> 验证 -> 调整 -> 继续或停止
其中“人工处理”不是循环失败,而是一种正常终态。工程化系统的可靠性,常常体现在它知道什么时候不应该继续自动做。
五、为什么 while true 不够
下面这段伪代码确实会重复调用 Agent:
while True:
result = run_agent("继续修复项目,直到测试通过")
if tests_pass():
break
它没有回答几个关键问题:
- 进程重启后,之前尝试了什么;
tests_pass()检查的是可信基线,还是 Agent 刚刚改弱的测试;- Agent 连续三次犯同一个错误时如何停止;
- 一轮修改了 80 个文件时是否仍可接受;
- 测试本身不稳定时,怎样区分环境错误与逻辑错误;
- 任务需要产品判断或额外权限时,由谁接手;
- 两个 Runner 同时拿到同一任务时,怎样防止重复修改;
- 已经成功的副作用会不会在重试中执行第二次。
真正的工程工作大多发生在循环体之外:契约、状态、验证、锁、预算、审批和恢复。循环语法只负责重复。
同样,给上面代码加一个 max_retries = 5 也只解决了“最多转几次”,没有解决每次为什么值得转、结果是否可信,以及停止后留下什么证据。
六、哪些任务值得循环化
一个任务满足下面四个条件时,才更像合适的 Loop 候选:
- 会重复出现。 不是只发生一次的临时工作;
- 每轮可以缩小。 能拆成短小、相对独立的任务;
- 结果可以验证。 有测试、规则、结构化检查或清楚的人工审核点;
- 失败可以控制。 修改可隔离、可恢复,不会一次错误就产生不可逆后果。
少一个条件,不代表绝对不能自动化,但需要更强的人类控制。例如“每天整理低风险依赖更新”很适合形成循环;“自动决定并执行生产数据库删除”即便反复出现,也不该因为频率高就交给无人值守 Agent。
可以用这个简化判断顺序:
任务是否重复?
否 -> 人或一次 Agent 运行通常足够
是
↓
能否拆成有明确结束条件的小任务?
否 -> 先重写任务,不要急着循环
是
↓
是否有独立验证和可控失败面?
否 -> 先补 Harness 与审核点
是 -> 值得设计一个有预算的 Loop
七、先做一次任务分类练习
暂时不要写代码。先为下面六个场景选择“人处理”“一次 Agent 运行”或“工程化 Loop”。最好先自己判断,再看后面的解释。
| 场景 | 你的选择 |
|---|---|
| 把一个函数改名,并修复所有引用 | |
| 每晚扫描本地任务队列,处理一个有测试的小缺陷 | |
| 决定是否删除生产环境中的过期客户数据 | |
| 第一次为个人网站重写首页文案 | |
| 每周检查依赖更新,测试通过后生成待审核分支 | |
| 需求只有“让产品更好用”,没有验收标准 |
一种合理答案是:
- 函数改名和首次文案任务通常交给一次 Agent 运行,人最终检查即可;
- 每晚处理小缺陷、每周准备依赖更新具备重复、小范围和可验证特征,适合 Loop;
- 删除生产客户数据需要高风险业务与合规判断,应由人控制,Agent 最多提供清单和建议;
- “让产品更好用”连一个可执行任务都还不是,应该先由人澄清目标,而不是让循环不断自行发明工作。
这里没有按任务名字机械分类。“依赖更新”也可能涉及破坏性迁移,“文案修改”也可能形成大量低风险、可审阅的重复任务。真正决定方案的是边界、验证和失败代价。
八、贯穿项目 Issue Garden 怎样工作
后面的课程使用 Issue Garden:给 ShelfCare 增加一个本地维护循环。ShelfCare 是个人藏书管理小应用,已经具备基础项目说明、检查命令和权限边界;Issue Garden 则负责组织多次 Agent 运行。
最终结构大致如下:
本地任务队列
-> 触发器发现待处理任务
-> Runner 获取锁并选择一项
-> 读取 loop.yaml 和持久状态
-> Agent 适配器启动一次运行
-> 外部验证器检查测试、Diff 和任务契约
-> 事件日志与状态文件记录证据
-> 决策器输出:
completed / retry / needs_input / blocked / stopped
为了让每位读者都能先验证控制逻辑,课程最初使用一个确定性的模拟 Agent。它不会真的写复杂代码,却能稳定重现“成功”“信息不足”和“越过权限”三种路径。单轮 Runner 跑通后,再把适配器换成你已经安装的命令行 Agent。
这不是回避真实 Agent。恰恰相反:如果循环只有连接某个在线模型时才能测试,我们就很难知道错误来自 Agent、网络,还是控制逻辑。先把 Loop 自身变成可重复验证的程序,再接入不确定的执行者,排错会简单得多。
最终综合实战会提供三类任务:
- 测试可以明确验证的小缺陷,循环应完成并产出候选修改;
- 缺少关键信息的模糊需求,循环应停止并请求补充;
- 超出权限边界的任务,循环应拒绝继续并说明触发了哪条规则。
结果只进入本地待审核区,不自动合并到 main,更不会部署。
九、写下你的第一张 Loop 候选卡
现在选一个你真的会重复处理的任务,先写成一张候选卡。可以放在课程笔记中,不需要提交到任何项目。
# Loop 候选卡
- 任务名称:
- 触发方式:手动 / 定时 / 事件
- 输入从哪里来:
- 每轮最多处理什么:
- 可以自动执行的动作:
- 必须人工批准的动作:
- 独立验证方式:
- 成功条件:
- 立即停止条件:
- 最大轮次或时间:
- 失败后怎样恢复:
- 为什么它比一次 Agent 运行更合适:
用 Issue Garden 填写时,关键条目可以是:
任务名称:本地小缺陷维护
触发方式:先手动,后续再增加定时或文件事件
输入:tasks/inbox/ 中一条结构化任务
每轮范围:只处理一个任务,不超过约定修改文件数
自动动作:读取仓库、修改实验分支、运行本地验证
人工批准:外部网络、扩大权限、合并、发布、破坏性命令
独立验证:任务验收 + npm run check + Diff 规则
成功条件:所有受保护验证通过并生成候选结果
停止条件:预算耗尽、相同失败重复、信息不足、越权或人工取消
检查你的候选卡。如果“独立验证方式”只能写成“让 Agent 自己判断”,或者“立即停止条件”完全为空,就先不要实现循环。下一篇会把这些文字升级成机器可读取、启动前就能检查的契约。
常见误解
已经有定时任务,算不算 Loop Engineering
定时器只回答“何时启动”。如果每次启动后不读取持久状态、不验证结果,也没有预算、停止和人工升级,它只是重复执行器。触发机制是 Loop 的一部分,不是全部。
Agent 自己会测试和修错,还需要外部 Loop 吗
一次任务能在一个运行中完成,就不需要为了概念完整再包一层 Loop。外部循环适合跨运行、跨时间或跨任务的工作,并负责单次 Agent 不适合拥有的全局状态和控制权。
只要设置最大重试次数就安全了吗
不是。最大轮次能限制一种资源消耗,却不能防止错误副作用、弱化测试、重复处理、读取敏感信息或多个任务相互覆盖。后面的课程会分别处理这些边界。
没有做过 Harness Engineering 能继续吗
可以。课程会提供具备基本 Harness 的项目快照。你仍然需要理解一个原则:Loop 会放大单次运行的能力,也会放大单次运行的缺陷。若验证、权限和运行入口本身不可靠,应该先修 Harness,而不是增加重试。
所有任务最终都应该自动闭环吗
不应该。产品判断、合规审批、高风险外部操作和目标本身不清楚的任务,都应该保留人类决策。一个能明确输出 needs_input 或 blocked 的循环,比假装什么都能自动解决的循环更可靠。
本篇留下了什么
到这里,你应该能画出两层循环:一次 Agent 运行内部的模型—工具循环,以及外部 Runner 管理多次运行的控制循环。你也有了一张 Loop 候选卡,里面至少写清任务、验证、预算和停止条件。
下一篇,我们会把 Issue Garden 的这些边界写进 loop.yaml。在第一次调用 Agent 之前,Runner 就应该能拒绝缺少验证器、没有预算或不存在停止条件的配置——先让循环拥有契约,再让它开始转动。