当前位置: 首页 > news >正文

从写Prompt到设计Loop:真正让Agent干完活的,是一个会自我纠错的闭环

写出一个完美的Prompt,只能换来一次漂亮的回答;要让Agent稳定地干完一件多步骤的活,你真正需要设计的,是一个能持续执行、检查结果、处理错误、并且知道何时停止的Loop。这篇文章从一个常见的翻车场景讲起,拆解Agent Loop的核心组件和停止条件,最后给出一个测试通过、可以直接跑起来的最小Python工程。

01 | 先看一个熟悉的翻车现场

不少人第一次搭Agent,走的都是同一条路:花一个下午打磨出一段几百字的 Prompt,角色、目标、约束、输出格式一应俱全,然后把它丢给模型,期待它自己分析 issue、改代码、跑测试、提交结果。

第一轮输出往往确实惊艳。问题出在第三轮、第五轮之后。我自己搭执行框架(harness)时反复见过这些场景:跑着跑着,模型开始改一个和 bug 毫无关系的文件,原始目标早被冲出了上下文;工具报错了,它不看错误信息,若无其事地编一个"执行成功"继续往下走;同一个文件连读四遍;测试还红着,它已宣布"任务圆满完成"。而最要命的是——整个系统里没有任何一处代码回答过一个问题:这件事什么时候算结束?

每次翻车,第一反应都是回去改Prompt:加一句"不要重复操作",加一句"必须确认测试通过"。改完好两天,然后在另一个地方以新的姿势翻车。折腾几轮你会意识到,这不是Prompt的问题。

Agent的可靠性,不取决于Prompt写得多精致,而取决于执行它的Loop 怎么设计。Prompt决定模型"懂不懂"这个任务;Loop决定这个任务最后"成不成"。

02 | Prompt 解决什么,Loop 解决什么

先把概念摆清楚。一次模型调用,本质上是个无状态的纯函数:文本进,文本出,调用结束,什么都不记得。而一个真正的任务是有状态的过程:做一步,世界变了,要看一眼结果,再决定下一步。这两者之间的鸿沟,就是Loop要填的。

把一个Agent系统拆开,大致是这几层东西:

  • Prompt:定义角色、任务、约束和输出要求,是模型理解任务的入口;
  • Context(上下文):为"当前这一步"提供必要信息——文件内容、上一轮的报错、已经试过什么;
  • Tools(工具):让模型的输出能真正作用于外部世界,而不只是说说;
  • State(状态):记录任务从开始到现在的完整轨迹;
  • Loop(循环):决定模型什么时候思考、什么时候行动、什么时候验证、什么时候重试、什么时候停;
  • Guardrails(护栏):轮数上限、预算上限、权限边界这些保命机制。

可以粗略写成一个公式:Agent = Model + Prompt + Context + Tools + State + Loop + Guardrails。需要说明,这是我做工程时用的抽象,不是学术定义——业界至今对"什么是 Agent"没有统一说法,Anthropic 在《Building Effective Agents》里就专门区分过预编排的workflow和模型自主决定流程的agent。但不管哪条路线,有一点是共通的:模型只负责"提议下一步",真正把一个个提议串成持续执行的,是Loop。

换句话说,新的核心技能不再是写出一条完美的 Prompt,而是搭出那个替你写下一条Prompt的系统

03 | 解剖一个完整的 Agent Loop

一个能用的Loop,每一圈大致要走完这几个阶段:读取目标和当前状态;观察环境(目录里有什么、上一步发生了什么);规划下一步;选择并调用工具;把工具结果原原本本记下来;验证结果是否符合预期;然后做决策——继续、重试、换路、求助,还是停止;最后输出结论并保存整条执行轨迹。

听起来像是把while True套在模型调用外面就完事了,但魔鬼全在两个细节里。

第一个细节是上下文由状态生成,而不是由人手打。很多人所谓的"Agent",其实是自己坐在对话框前,一轮一轮把报错复制粘贴给模型——那不是 Loop,那是你在当Loop。正确的做法是维护一个显式状态对象,每轮的 Prompt都从状态里渲染出来:目标、已执行的动作、每次的观察结果。状态变了,Prompt自然跟着变,人不需要参与。

第二个细节是失败信息是资产,不是垃圾。工具执行的结果——diff、标准输出、报错栈——必须全部捕获并回写进状态,因为这一轮的失败,恰恰是下一轮最有价值的上下文。模型看到"密码校验对空字符串返回了true"这条具体报错,远比看到一句干巴巴的"上次失败了,请重试"有用得多。闭环就是在"结果回写状态、状态生成下一条Prompt"这一步形成的。

所以一个好的Loop不是裸奔的死循环,而是一个带状态转换、资源预算和完成条件的受控执行系统

04 | 最难设计的不是"继续",而是"何时停止"

让循环转起来很容易,让它在正确的时机停下来才是真功夫。一个没有出口的Loop不是系统,是一台持续烧钱的机器——尤其是挂在夜里跑的那种,你睡一觉,它跑了几百轮,账单还在涨,活没干完。

按我的经验,停止条件至少要覆盖这几类:目标已通过验证(正常出口);达到最大迭代轮数;达到最大工具调用次数;超出时间或 Token 预算;连续多轮没有有效进展;同类错误反复出现;即将执行高风险操作;以及信息不足、必须人工介入。前面是刹车,后面是方向盘,缺哪个都不行。

这里面有一条值得单独拎出来:"模型自称完成"和"系统证明完成"是两回事。模型非常乐意宣布胜利——它说"测试已全部通过"的时候,测试可能压根没跑过。所以"完成"的判定权必须交给模型之外的东西:跑一遍真实的测试、校验输出是否符合schema、检查目标文件是否真的存在且非空。模型的"我做完了"只是一个申请,验证器点头才算数。

另一条容易被忽略的是重复动作检测。模型卡住时的典型表现,就是用一模一样的参数反复调用同一个工具。一个简单有效的做法:对最近几轮的(工具名,参数)做指纹比对,连续重复先注入一条警告提醒它换思路,再重复就直接熔断、升级人工。成本很低,但能拦住大部分"原地打转烧Token"的事故。

05 | 从 Demo Loop 到生产 Loop

一个演示级的Loop三件套就能跑:模型调用、工具调用、最大轮数。发朋友圈够用了。但要放进真实业务,清单会长很多:显式状态对象、结构化动作输出、工具权限控制、超时、重试与退避、幂等设计、日志与可观测性、checkpoint、错误分类、成本预算、人工审批、最终验证器,以及可恢复的失败状态——挂掉之后能从断点继续,而不是从头再来。

看到这串清单先别慌,没有人第一天就把它们全堆上去。更现实的路径是:从最小闭环开始,根据真实出现的失败模式逐步加复杂度。跑出重复动作,就加指纹检测;账单超预期,就加成本预算;出现误删文件,就收紧权限、加审批。每个机制都应该对应一次真实的疼,而不是凭想象预防。

人工审批的边界倒值得一开始就划清楚:不可逆的操作必须停下来问人。删除文件、转账、推生产环境,这类动作错一次就没有撤销键。我的做法很朴素——要么不给Agent这个工具,要么在执行前插一道确认。自动化每提高一档,对验证、权限和可观测性的要求就跟着提高一档,这笔账躲不掉。

06 | The Full Loop in Code:一个最小可运行的 Agent Loop

道理讲完,上代码。我写了一个最小但完整的工程,文末附录给出全部文件,可以直接拼起来运行:

minimal-agent-loop/ ├── main.py # 入口:接收任务、注册验证器、打印执行摘要 ├── agent.py # Loop 核心:上下文构建 / 决策 / 执行 / 验证 / 熔断 ├── tools.py # 沙箱工具集:目录、读写文件、存在性检查、受限计算 ├── models.py # Pydantic 数据模型:Action / StepRecord / AgentState ├── test_loop_offline.py # 离线自检脚本,无需 API Key ├── requirements.txt ├── .env.example └── README.md

几个设计决策说明一下。模型每轮只允许返回一个JSON动作{"thought": ..., "tool": ..., "args": ...},用Pydantic校验,解析失败会带着错误信息重试,而不是让脏输出流进系统。工具全部是沙箱内的安全本地工具——读写指定目录的文本文件、列目录、检查文件、做四则运算——刻意没有提供任意 Shell 执行,路径也做了越界检查。模型调用走OpenAI兼容接口,API Key、Base URL、模型名全部通过环境变量配置,接任何兼容服务都行。

Loop主干的核心逻辑长这样(完整版见附录的 agent.py):

def run(self) -> AgentState: hint = "" for turn in range(1, self.max_turns + 1): # 护栏:最大轮数 action = self._next_action(hint) # 模型基于状态提出下一步 hint = "" if action.tool == "ask_human": # 出口一:升级人工 self.state.status = RunStatus.HUMAN_REQUIRED break if action.tool == "finish": # 出口二:自称完成 ok, msg = self.validator(self.state) # 但要系统验证说了算 if ok: self.state.status = RunStatus.SUCCESS break continue # 验证不过?证据缺口喂回去,接着干 repeats = self._repeat_count(action) # 重复动作检测 if repeats >= self.max_repeats: self.state.status = RunStatus.HUMAN_REQUIRED # 熔断 break if repeats >= 1: hint = "你在重复同一个动作,换个思路或求助。" ok, observation = run_tool(action.tool, action.args) # 执行并捕获一切 self.state.steps.append( # 结果回写状态 StepRecord(turn=turn, action=action, # → 闭环在这里形成 observation=observation, ok=ok)) else: self.state.status = RunStatus.FAILED # 出口三:轮数耗尽 return self.state

短短几十行,但前面讲的东西都在:三种终态各有出口;"完成"必须过验证器;重复动作先警告再熔断;每一轮的观察结果都回写状态,成为下一轮 Prompt 的一部分。

07 | 跑一遍:从 notes.txt 到 summary.md

拿一个具体任务过一遍:"读取工作目录中的notes.txt,提炼三条核心结论写入summary.md,并确认文件已成功生成",同时用--expect-file summary.md注册完成验证器。

第1轮,状态里只有目标,模型选择list_dir观察目录,看到notes.txt 存在。第2轮,它调用read_file拿到笔记原文,内容进入状态。第3轮,它生成摘要并write_file写入summary.md。第4轮,它主动调用file_exists确认产出——因为系统提示里写明了"宣布完成前先验证产出"。第 5 轮,它发起finish,系统验证器检查summary.md 确实存在且非空,状态置为SUCCESS,循环结束。全程没有人打过一个字,每一轮的Prompt都是状态自动生成的。这条五轮的路径,在工程自带的离线自检脚本里是可以复现验证的。

更有意思的是异常分支。notes.txt不存在?read_file返回"文件不存在"这条观察,模型下一轮可以重新找相近文件,或调用ask_human问人,而不是硬编一份摘要。写入失败?错误信息回写状态,带着具体原因重试。反复读同一个文件?指纹检测先警告,再犯就熔断成HUMAN_REQUIRED。轮数耗尽?FAILED收场,但完整轨迹都留着,排查不抓瞎。至于删除、覆盖重要文件这类动作——这个最小工程的答案是干脆不提供对应工具;生产环境里,则应该换成审批流。

08 | 几条可以带走的工程原则

最后不复述细节了,留几条我自己反复验证过的判断:

Prompt决定Agent如何理解任务,Loop决定Agent如何完成任务。模型负责提出下一步,系统负责限制、记录和验证这一步。每一次动作都应该产生可观察的状态变化——观察不到,就等于没发生。每一个"完成"都应该对应可以检查的证据,模型的自我评价不算证据。每一种失败都应该有明确的出口:重试、回退、熔断或升级人工,唯独不能是悬在那里。自动化程度越高,验证、权限和可观测性就必须越强,这三样是自动化的地基而不是装修。

真正可靠的Agent,从来不是那个每一步都判断正确的模型,而是那个即使模型判断错了,也能被及时发现、纠正、并安全停下来的闭环。

http://www.jsqmd.com/news/1033294/

相关文章:

  • 普通汽车如何蜕变智能座驾:开源驾驶辅助系统完全指南
  • OBS Studio深度故障排查:从崩溃根源到专业修复的进阶指南
  • 2026 年旅游行业季节性仿域名钓鱼攻击机理与防控研究
  • 2026国产AI+PLM代表有哪些?推荐一个比较好用的支持AI功能的PLM系统?
  • 3分钟掌握Obsidian Border主题:打造你的个性化知识管理空间
  • 2026年中清远液态光学产品直销工厂综合实力分析 - 品牌鉴赏官2026
  • 免费USB启动盘制作神器Rufus:3分钟搞定Windows系统安装
  • 088、PCIE ASPM状态:L0s、L1、L2/L3——一次链路唤醒失败的排查手记
  • Windows Defender高效禁用终极指南:no-defender专业解决方案深度解析
  • 房颤手术治疗费用与医保支付分析——基于安徽省政策及临床数据
  • XL2247:433/315MHz 带编码的无线发射 SoC 芯片,批量3毛出头
  • 深度技术解析:Moonlight-Switch跨平台游戏串流配置优化指南
  • 高性能地理空间索引系统:H3-Py Python绑定架构深度解析
  • 医用超声图像模拟系统:界面详细设计代码详解
  • 【网工入门-eNSP模拟-11】nat网络地址转换
  • 2026年6月口碑好的井口装置测试实力厂家找哪家,自增强/等静压设备/超高压液压系统方案,井口装置测试供应商推荐分析 - 品牌推荐师
  • 选材总踩坑?了解17-4PH棒材与锻件的优质国产厂家清单 - 品牌2026
  • SVN 常用命令详解
  • kkFileView:企业级文件在线预览技术方案,实现跨格式文档统一访问与管理
  • Jemeter
  • 基于FME的等高线赋值正确性检查
  • 2026年杭州GEO优化重磅盘点!国内头部生成式引擎优化服务商权威实力排名与选型全解析 - 936品牌测评网
  • Windows启动失败修复指南:手动重建BCD与引导项解决“无法修复”问题
  • okbiye AI PPT 生成器实测解析:四步零门槛打造答辩汇报幻灯片,告别熬夜排版难题
  • 2026 年 6 月最新!浙江 GEO 优化公司哪家靠谱?2026 本地服务商实力对比全解析 - 936品牌测评网
  • 2026年6月最新!杭州本地GEO优化推荐:这几家做生成式引擎优化更专业 - 936品牌测评网
  • 做德国出口生意必看风险提示汇总
  • 如何让AI Agent真正接管批量IT运维?贝锐向日葵企业CLI解析
  • 2026年当下,江苏地区值得关注的徐州爵士舞艺术中心深度解析 - 品牌鉴赏官2026
  • 2026年近期重庆GEO平台哪个好?与选型指南 - 品牌鉴赏官2026