我最先在哪个真实场景里撞上这个问题
年初我在做一个自动化代码审查工具,目标是让 Agent 能根据测试失败信息自动修复代码并重新提交。最开始的方案很直接:Agent 调用一次 LLM,拿到修复建议,打补丁,跑测试。但很快发现问题——第一次生成的修复常常不对,甚至引入新 bug。
这时我才真正撞上 Loop Engineering:不是简单地“调用 LLM 拿结果”,而是需要设计一个循环——评估输出、反馈修正、再评估,直到通过或者达到终止条件。很多文章讲的是理论上的“闭环”,但我面对的是实实在在的 retry 队列、终止条件判断和状态管理。
做完之后真正改变我判断方式的几个结论
1. 循环次数不是越多越好,关键在信号质量
我一开始设了 max_retries=5,想着多试几次总能过。实际上,第 3 次之后 Agent 往往只会微调标点或换同义词,毫无实质改进。后来我把终止条件从“固定次数”改为“信号变化率”——如果连续两次的修复方案语义相似度超过 90%,就直接终止并标记为“无法自动修复”。
2. 上下文膨胀是隐形杀手
每次循环都把完整对话历史发给模型,上下文窗口很快堆满,模型开始“遗忘”最初的代码。我踩过这个坑后,改为只保留当前代码块、最近一次失败信息和前一次修复 diff。结果修复成功率反而提升了 12%。
3. 测试的可靠性决定了循环的有效性
如果测试本身有 flaky(脆弱的)因素,比如网络抖动或计时问题,循环就会在错误的信号上反复尝试。我花了两周时间把 flaky test 比率从 8% 降到 1% 以下,这才让循环真正有指导意义。

当时踩过的坑和后来怎么修正
坑 1:没有区分“可重试错误”和“不可重试错误”
一开始对所有失败都重试,包括编译错误(比如缺少 import)——这类错误重试 10 次也不会变好,只会浪费时间和 tokens。修正方法是预先定义错误分类:语法错误、缺少依赖、逻辑错误——前两类直接报错终止,只有“逻辑不够完善”才能进入循环。
坑 2:循环日志太粗,无法调试
最初只记录“retry 1: fail, retry 2: fail”,完全看不出失败原因。后来我在每个循环节点打印出:原始错误、模型输出 diff、测试输出摘要。有了这个日志,定位问题的时间从小时级降到分钟级。
坑 3:没有考虑成本上限
一个复杂的修复任务可能跑 8 次循环,花费 2 美元。对于实验阶段来说不可持续。我的修正方案是:设置 token 预算,一旦当前循环累计 tokens 超过条目的预期价值(比如这个 bug 修复的预估人工成本),就自动降级到简单 LLM 或直接挂起。

如果你也在做类似工作,最值得先照抄的一步
直接在你的修复循环入口处加上这段检查(伪代码):
def should_retry(error, history):
if error.type in UNRECOVERABLE_ERRORS:
return False
if len(history) >= 2 and similarity(history[-1], history[-2]) > 0.9:
return False
if total_tokens_used > BUDGET:
return False
return True
这三点检查覆盖了最常见的问题:错误不可修复、模型陷入原地打转、成本失控。把它放在循环最外层,能节省至少 30% 的无谓消耗。
什么时候应该继续投入,什么时候该换路线
继续投入的信号:
- 你有明确的信号(如测试通过率、实际修复率)在持续改善,即使提升缓慢。
- 你已经在循环设计中加入了上述的终止和降级逻辑,成本可控。
- 团队有精力维护测试稳定性和错误分类清单。
换路线的信号:
- 你发现大多数失败是同一类“不可重试”错误,比如依赖版本冲突或 API 变更——这时应该去修复源问题,而不是循环。
- 循环次数增加了,但修复成功率长期低于 30%。这可能意味着 LLM 本身不擅长这个任务,需要更换模型或换 prompt 策略。
- 你发现自己花了 80% 的时间在调循环参数(max_retries、temperature、top_p)而不是改善任务本身。
当我遇到这些信号时,果断暂停了自动修复循环,改为半自动方案:循环只负责生成建议,人工确认后再落地。两个月后,等模型版本升级才重新尝试全自动。
总结
Loop Engineering 不是银弹,它解决的是“有明确反馈信号、有可重试空间、成本可接受”的任务。如果在你的场景里这些条件不满足,不要硬套。但如果你正好面对这类问题,上面这些经验——尤其是终止条件设计、上下文管理、错误分类和预算控制——可以直接拿来用。
下一步,如果你想获得更系统的 Agent 工程方法论,包括上下文窗口策略、循环成本模型和错误恢复模式,可以进入我们的付费文章和课程。

暂无评论,快来发表你的见解吧