为什么 AI 需要“自己动起来”?
你是否遇到过这样的场景:让 AI 协助撰写一份方案,它给出初稿,读起来通顺,但细看总有不足——某个论点未展开、逻辑跳跃、语气不当。你反馈,它修改,但改完又出现新问题。反复沟通后,你发现自己在不断手动“操控”AI,而非让它自主完成工作。
AI 能解决问题,但要让它真正交付标准结果,还需要一个关键结构。 正如 Borish Cherny 所说:“我现在不给 Claude 写提示词了,那些 Loop 替我写”。Peter Steinberger 也指出:“你不应该再给编程 Agent 写提示词了,应该设计 Loop 来提示你的 Agent”。
提示词写得再好,也只是为一次性调用打补丁。真正该做的,是设计一个让 Agent 自己运转起来的循环,这个循环就是 Loop。 行业对此展开了广泛讨论,AlphaSignal 的系统梳理文章《Loop Engineering: Do You Actually Need to Put Your Agent in a Loop?》给出了核心判断:Loop 并非万能,但在当前阶段,它是让 Agent 真正可用的唯一工程路径。
文章还指出一个关键信号:没有 Loop 的 Agent,本质上只是一个更昂贵的搜索引擎。
为什么不能只靠单次调用?
用一个具体场景来说明:你让 AI 帮你写一篇工作汇报。
- 单次 LLM 调用:你说一遍需求,AI 生成一篇。内容通顺,但结构不符合团队格式,某些数据缺失。你再补充,它重新生成——一问一答,每次全量重写,上一轮的反馈它可能记不住。
- 脚本:你预先写好流程:读取本周日报 → 调用模型 → 输出文档。只要数据格式对、模板符合预期,就能实现。但如果 AI 发现某个项目数据缺失,需要去另一个文件里补全,脚本却无法应对——它只按写好的路径走,超出预期的情况就卡住。
- Loop Agent:你告诉 AI「帮我写本周工作汇报」。它自己读日报、进度表、会议记录,发现某个项目数据不完整,主动去查关联文件,补全数据后按你们团队的模板组织内容,写完还自己对照模板检查格式——这套流程它会自己判断要不要做、按什么顺序做、遇到新情况怎么处理。

一、什么是 Loop?
一句话:Loop 是让 AI Agent 不断“推理——行动——观察”直到任务完成的控制结构。
上下文:模型每次推理时能看到的全部信息,相当于它的工作记事本。每一轮的行动结果都会追加进去,供下一轮推理使用。本文后面提到“上下文”均指此。
类比到软件工程:Loop = 控制流(for / while / 递归),把模型的单次调用变成可迭代、可重试、可收敛的执行引擎。
脚本和 Loop 的根本差别,其实是决策权在谁手里。脚本执行确定的指令序列,Loop 让模型在每一步自主推理下一步应该做什么。这就是“智能”的真正价值。
最小实现只有 5 行:
while True:
response = llm.call(context)
if response.is_final_answer:
return response.content
context.append(execute_tool(response.tool_call))
二、Loop 的三个基本元素
Loop 的本质决定了,要让 Agent 自主完成任务,它必须能“想清楚下一步”(Reason)、“真的去做”(Act)、“知道做完了什么”(Observe)。少任何一个,循环就转不起来。
2.1 推理(Reason)
每一轮循环开始时,模型会读取当前的全部上下文,做出一个判断:下一步该做什么?
结果只有两种:
- 任务已完成 → 生成最终结果,退出循环
- 任务尚未完成 → 选择一个工具,进入下一步行动
这一步的决策权完全在模型侧。Loop 框架的职责是触发推理、接收输出,不介入模型的判断过程。
2.2 行动(Act)
推理完成后,Loop 框架执行模型选定的工具。工具类型没有限制:
2.3 观察(Observe)
工具执行完毕后,结果会写回上下文,供下一轮推理使用。这里有一个关键原则:工具出错了,错误信息也要原文写回去,不能悄悄忽略。
想象你派了一个实习生去打印文件。他回来跟你说“打印机卡纸了”,你可以让他换一台机器,或者先发邮件代替——你能做出判断,是因为你知道出了什么问题。但如果他回来什么都不说,你以为文件打好了,继续安排下一步,开会的时候才发现手里什么都没有——这时候损失比卡纸本身大得多。
模型也是一样。看不到错误,它只能假设“一切正常”往下走。只有把真实结果——包括失败信息——反馈给它,它才能决定:重试、换方案,还是直接告诉你“这条路走不通”。
try:
result = tools[tool_name](**args)
except Exception as e:
result = f"Tool error: {e}" # ✅ 错误原文给模型,让它决定怎么处理
context.append({"role": "tool", "content": str(result)})
小提示: 在 Observe 阶段,务必确保错误信息原文保留。不要使用 try-except 中的 pass 语句,否则模型会误以为操作成功,导致后续决策错误。
三、Loop 的五大问题
虽然 Loop 听起来像是 Agent 已经实现了自主交付,但这其中还蕴藏着两个风险:Loop 有可能会让 Token 账单爆炸,以及盲目接受 Loop 的输出。要让 Loop 在生产环境里运转起来,实现成本可控、结果可验证,设计一个良好的 Loop 需要解决这五个绕不开的问题:
问题一:何时停止?
想象你给一个员工安排了一个任务,但没有告诉他“完成后来汇报”——他可能会一直反复检查、反复修改,停不下来。Loop 也一样,你必须给它一个明确的“可以停了”的退出信号。
退出信号通常来自四个地方:
- 模型自报完成(final_answer)
- max_steps:执行的最大步数上限
- 时间超时
- 人工干预
不要只靠模型自报完成来停。 max_steps 就像给任务定个 deadline,到了就停,不管做完没做完,先交结果再说。
问题二:上下文爆炸
每跑一轮,工具的返回结果就追加一次进上下文。任务跑到几十步,窗口很快就装不下了。
类比一下:你用一张 A4 纸记录整个项目过程,每做一步就往上抄一段记录。纸就这么大,写满了就没法再推进了。处理方式只有三种:
- 只留最近几步(滚动窗口)
- 把之前的记录压缩成一段摘要
- 只保留重要节点,把过程细节扔掉
经验是,保留“任务目标 + 关键中间结果 + 最近 3-5 轮”通常够用。
小提示: 实现上下文压缩时,可以设计一个 compress_if_needed 函数,它根据上下文长度决定是否触发压缩,例如当 token 数超过 80% 窗口大小时,自动将历史记录摘要化。
问题三:工具调用失败怎么处理
这个原则前面已经讲过:工具出错了,错误信息要原文写回上下文,不能忽略掉。 这里只看代码层面怎么实现:
# 不要这样
try:
result = execute(tool)
except:
pass # ❌ 吞掉了,模型不知道
except Exception as e:
result = f"Error: {e}" # ✅ 告诉模型,让它推理
context.append(result)
问题四:需要等待外部事件
有些任务会卡在等资源上——等人工审批,等后台任务跑完,等外部接口回来。这时候 Loop 不会傻傻地空转,也不会直接挂掉。它会把当前进展存下来,先挂起,等到信号来了,再从原来的地方接着继续,一步都不会丢。
简单来说,就像手机来电话时自动暂停音乐,挂断后继续播——Loop 的挂起和恢复,就是这么回事。
问题五:任务规模过大
当任务复杂到一个 Loop 跑不完,就拆。
想象一个大型装修项目:装修公司不会承包所有工种,而是把水电、木工、油漆分给不同的分包商同时推进,最后验收汇总。主 Loop 做的是同样的事——把任务拆成互相独立的子任务,分给子 Agent 并行跑,最后收结果。
能并行的绝不串行——整体耗时取决于最慢那个子任务,不是所有子任务加起来。
四、Loop 完整状态机
把上面五个问题综合起来,一个完整的 Loop 本质上是一个状态机——任务在不同状态之间流转,每个状态有明确的进入条件和出口。

五、Loop 与相关概念的关系
Loop 在 Agent 架构中的位置
了解完 Loop 的整体结构,现在我们来从下往上看看 Loop 在整体架构里处于哪一层,能帮助判断遇到的问题该在哪里解决。Model 相当于 Agent 的大脑,只在 Loop 触发时被调用一次,负责推理决策。Loop 其实是一个控制结构,是让 Agent 真正“动起来”的引擎。 而前段时间广泛提及的 Harness 则是它的生产级外壳,保证 Loop 在生产环境里跑得稳、跑得安全。

Loop vs CoT vs ReAct
这几个概念经常被混在一起,但它们解决的是不同层面的问题:
- CoT(思维链):管模型怎么想,是一种推理策略。
- ReAct:管模型怎么表达,是一种推理与行动结合的框架。
- Loop:管任务怎么推进,是控制执行的循环结构。
- Harness:管系统怎么跑稳,是生产环境的保障层。
一句话来解释:CoT 管模型怎么想,ReAct 管模型怎么表达,Loop 管任务怎么推进,Harness 管系统怎么跑稳。
常见问题: Loop 和脚本有什么区别?
答案: 脚本执行确定的指令序列,无法应对预期外的情况。而 Loop 让模型在每一步自主推理下一步应该做什么,拥有决策权,能根据环境反馈动态调整。
六、Agent 工程全景
Loop engineering 只是 Agent 工程体系里的一层。
把整个体系铺开来看,你会发现每一层在传统软件工程里都有对应的概念。这张全景图最大的价值,是帮你判断遇到的问题该在哪一层解决,而不是什么问题都往提示词上怼。

七、Loop 完整实现代码
下面分享一个基于以上原理在实践中探索出来的最小完整 Loop 骨架。
def agent_loop(goal: str, max_steps: int = 30) -> str:
context = [{"role": "user", "content": goal}]
for step in range(max_steps):
# 推理
response = llm.call(context)
context.append({"role": "assistant", "content": response})
# 退出条件
if response.type == "final_answer":
return response.content
# 人工审批(高危操作)
if response.tool_call.requires_approval:
approved = request_human_approval(response.tool_call)
if not approved:
context.append({"role": "tool", "content": "Action rejected by user."})
continue # 模型收到拒绝信号,自己决定换方案
# 行动
try:
result = tools[response.tool_call.name](**response.tool_call.args)
except Exception as e:
result = f"Tool error: {e}" # 错误原文给模型
# 观察:结果写回
context.append({"role": "tool", "content": str(result)})
# 防止 context 爆炸(实现见第三节问题二)
context = compress_if_needed(context)
return "Max steps reached."
小提示: 此代码中的 compress_if_needed 函数需要根据实际上下文窗口大小实现。例如,当 token 数超过 80% 窗口大小时,调用一个摘要函数来压缩历史记录。
八、实战案例:用 文心快码 Comate 完成文生图提示词自动化构建
背景
遇到的问题:为地图场景文生图任务批量构建 Prompt,规则约束有几十条(时段、道具、环境全都有限制),人工逐条处理慢,而且容易出错、难以保持一致。
怎么解决:在文心快码里自定义配置一个 Loop Agent,让这个 Agent 自己跑完「规则理解 → Prompt 生成 → QC 验证 → 失败分析 → 规则修正」这整个流程,中间不需要人介入。
Loop 流程

失败处理子循环
以上主流程中的「QC 失败→修复→重试」节点,实际展开是这个子循环:

实战截图(Comate 执行过程)
Step 1-2:Comate 生成 zhoubian_eval_other.jsonl,调用 DeepSeek 批量生成 Prompt(1015/1015)
Step 3:Background Task 完成,Comate 自动触发 QC 质检脚本
Step 4:QC 完成,1007 pass / 8 fail,Comate 主动读取失败条目分析原因
Step 5:失败原因分类,Comate 自主给出修复建议,判断是否继续收敛
失败分析(Comate 自主推理产出)

效果对比
引入 Loop 前,整个流程需要在 8 个节点上主动操作,中间每一步都要等上一步完成才能继续,还得保持上下文连贯(上次改了什么、改完效果怎样)。引入 Loop 之后,只需要做两件事:
- 开始说清楚任务目标和验收标准(pass ≥ 99%)
- 最后看结果,决定要不要接受剩余 8 条失败
中间的“生成 → QC → 分析失败 → 修规则 → 重跑”这个循环,Comate 自己运营,遇到失败不会停,会先搞清楚为什么失败,再决定怎么修。
用一张表格,就能感受到引入 Loop 前后的效果对比:

结语
Loop 的核心价值:让 AI 在推理与行动之间建立闭环,使模型能够感知环境、纠正错误、持续迭代,直到真正完成任务。
推理完了要能行动,行动完了要能看结果,看完结果要能决定下一步——这个闭环跑通了,AI 才从“回答问题的工具”变成“能干活的搭档”。
