ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

OpenClaw Agent四层嵌套循环架构:从动作到目标的自纠偏控制体系

OpenClaw Agent四层嵌套循环架构:从动作到目标的自纠偏控制体系

最近我在梳理 OpenClaw Agent 的自主控制链路时,把整体架构彻底改成了四层嵌套循环。这套架构的核心思想,是用“动作、步骤、规划、目标”四个不同尺度的循环,把 Agent 从一次性的线性流水线,变成一台能自我纠偏的复杂系统。它主要解决长任务执行中的目标漂移、行为退化和死循环问题,也兼顾了需要人随时介入的准生产场景。如果你正在做 Agent 编排、任务规划、机器人控制,或者只是对“如何让智能体不跑偏”这件事感兴趣,这篇内容应该能给你一个可以直接落地的框架认知。

长任务的失控,往往不是单点故障,而是没有一个完整的“兜底”体系。OpenClaw Agent 的四层嵌套循环,本质上就是把兜底的责任分散到四个层次,每一层只管好自己那一尺度的风险,同时把处理不了的问题向上抛。下面我尽量讲清楚设计思路、参数配置、实现细节,以及我实测中踩过的一堆坑。

1. 为什么要把 Agent 设计成四层嵌套循环

1.1 从一次性流水线到自省式循环

如果你接触过早期的 Agent 方案,大概率对这种模式很熟悉:接收用户指令,拆解成步骤,按顺序执行,最后返回结果。整个链路像一个串行的流水线,动作执行完就认为任务完成,没有验证、没有回滚、没有纠偏。我自己的实测感受是,这种模式在任务步骤少于五步、环境相对可控时勉强能用,但只要任务一长,或者中途环境出了一点意外,整条链路就很容易崩掉。

之前我在一个模拟项目X里测试过一个长任务:让 Agent 从一堆杂乱数据中整理出报表,结果它在第九步读取文件时遇到了格式问题,然后就没有然后了——没有重试,没有换一种方式解析,更没有回头检查自己的计划是否合理,直接返回了一个失败结果。问题不在模型能力,而在于架构里根本没有“反馈回路”。这就是我下决心引入嵌套循环的起点:Agent 需要一层一层地自省,每一层都要有能力把执行状态拉回正轨。

四层嵌套循环,恰好对应四种不同尺度的“反馈”:

  • 第一层盯着单个动作是否完成;
  • 第二层盯着本步骤预期的结果是否达成;
  • 第三层盯着整体计划是否还可行;
  • 第四层盯着“我们最初到底要干什么”。

听起来像层层汇报的管理层级,但它远比顺序执行稳健,原因稍后细说。

1.2 四个层次各自负责什么

为了后面讨论方便,先给四层命名:L1 动作循环、L2 步骤循环、L3 规划循环、L4 目标循环。每一层有独立的输入、判定逻辑和退出条件,也可以理解为四个独立状态机叠加在一起。

  • L1 动作循环:最内层,负责一次具体动作的尝试与重试。比如调用一个工具、生成一段文本、执行一次数据库查询。它关心的是“这次动作到底成功了没有”。
  • L2 步骤循环:负责把当前计划中的一个步骤完整跑完。它需要汇总 L1 的结果,判断这一步的预期产出是否达成,以及是否要继续下一步。
  • L3 规划循环:负责检查整个计划是否仍可行。如果 L2 发现某个步骤反复失败,就会把信息抛给 L3,L3 再决定是调整步骤顺序、替换执行策略,还是重新生成一份计划。
  • L4 目标循环:最外层,负责在若干轮规划后回头审视原始目标。环境可能变了、用户需求可能变了,甚至连“成功”的定义都需要重新确认,这就是 L4 出手的时候。

我见过一些更简化的方案只做两层循环:动作循环套目标循环。实际跑下来会发现一个很尴尬的问题——内层动作失败后,外层不知道是换个动作继续,还是直接改目标;目标变更后,内层又在按旧计划逐动作执行。中间的“规划”尺度缺失,整个系统依然会乱。

1.3 为什么必须是“嵌套”,而不是“顺序平铺”

谈到四层循环时,有人会问:我按顺序把四个循环依次跑一遍不就行了?比如先跑动作,再跑步骤,再检查计划,最后审视目标。听起来没啥问题,但实际上一旦拆成顺序执行,每一层就会丢失对“持续反馈”的感知。

我习惯用一个生活化类比:你带一个实习生做一个跨月的项目。如果只在每周五审查一次进度,那平日里的具体动作跑偏了谁发现?反过来,如果你每分钟都去审实习生填的表格,你把自己累死,他也没有发挥空间。正确的管理方式是:每天追踪具体动作,每周确认阶段性产出,按月讨论计划是否需要调整,到项目里程碑时再回来核对最终目标。四层循环嵌套的意义也是如此——所有尺度的反馈必须并行存在,随时能响应,而不是等到某一层跑完才轮到下一层。

嵌套的另一个原因是状态共享。L1 的失败记录会直接影响 L3 的判断;L3 的规划调整会带出新的动作需求;L4 的目标修正会反向重置 L2 的步进顺序。这些都是实时发生的,不是顺序执行的批次任务。这套机制就是让 Agent 在任何时刻都能回答三个问题:当前动作是否有效,当前步骤是否符合预期,当前计划是否还值得坚持。

2. 整体状态设计与数据流机制

2.1 每层循环的职责边界与退出条件

四层循环最忌讳的是层与层之间职责不清。如果 L1 失败后直接冲去找 L4 改目标,中间规划层就形同虚设。我在最初设计时,给每一层都规定了明确的输入、职责和退出条件,并且把“退出”视为一层重要的设计维度。

层级关注尺度输入来源核心职责退出条件
L1 动作循环单次工具调用或原子动作L2 下发的具体动作指令重试动作直到成功或判定不可执行动作成功、超过重试上限、或外部中断
L2 步骤循环计划中的单个步骤L3 下发的步骤序列汇总 L1 结果并验证步骤预期产出步骤达成、步骤失败上报、计划被 L3 取消
L3 规划循环当前整份计划L4 下发的目标描述判断计划可行性,必要时修订计划可执行、重规划次数上限、目标更新
L4 目标循环整个任务周期任务原始描述 + 各层状态摘要确认目标是否仍然有效目标达成、请求人工确认、任务被终止

这张表是我设计架构时贴在屏幕前的。每写一段代码前都会看一眼:当前这个判断到底属于哪个尺度,应该交给哪一层处理。看似简单,实际上能避免大量逻辑混乱。

2.2 层间数据流:只传摘要,不传全量日志

嵌套循环很容易踩的一个坑,就是上下文爆炸。最内层的每次动作尝试都会产生大量日志,如果这些全量日志都往上一层层传,很快模型上下文就不够用了。

我在设计层间数据接口时,定了一条硬性规则:内层往外层传递时,只传“状态摘要 + 关键异常”。L1 往 L2 传的是动作是否成功、失败原因分类、尝试次数。L2 往 L3 传的是步骤是否达成、实际产出与预期的偏差、以及阻碍步骤推进的核心障碍。L3 往 L4 传的是计划修订次数、修订原因、当前计划相对原始目标的风险指数。反过来,外层向内层下发指令时,也要把指令裁剪成当前层能理解的粒度,而不是把完整目标描述直接砸给 L1。

举个例子,L4 修正后的目标可能是“不要追求完整自动化,先确保数据不丢”,这个信息传到 L3 后会变成“把校验前置,放宽重试条件”,传到 L2 变成“对每个输出文件做一次完整性检查”,传到 L1 就变成“写文件后立即读取并比对长度”。每一层只消化与自身尺度相关的部分,剩下的交给上层或下层。

2.3 失败状态如何在四层间流转

四层循环里,失败不是终点,而是流转的起点。我设计了一个失败状态登记表:每个失败动作都会被记录成结构化信息,包括失败类型、尝试次数、可恢复性判断、建议的上报层级。这样 L2 在判断“步骤是否失败”时,看的就不是一条孤立日志,而是完整的失败原因分布。

我之前遇到过一种情况:Agent 在某个步骤里反复调用同一个外部服务失败,但因为每次失败的具体原因不同,模型判断为“可重试”,于是在 L1 里无限重试。最后加上重试上限和失败原因归类之后,才在换取另一种方式时救回来。失败流转的关键,是让 L1 知道自己解决不了时要往 L2 抛,L2 解决不了要往 L3 抛,而不是在同一层里做无意义的打转。

如果连续多步失败,L2 可以直接汇总给 L3。L3 收到后重新生成计划,而不是沿着原有步骤继续硬跑。若多次重规划后仍然失败,信息继续上传到 L4,由 L4 决定是调整目标还是请求人工介入。

3. 核心参数配置与实现细节

3.1 每一层该设置哪些关键参数

四层循环不是写四个 while 就完事了,真正要花心思的是给每层配置合理的参数。参数配得太松会导致系统失控,配得太太紧又会导致正常波动被误判为故障。以下是我在项目中实测用的基准值,可以当一个起点参考。

参数项所属层级建议初始值作用
MAX_ACTION_RETRIESL13单个动作最大重试次数
ACTION_TIMEOUTL18s单次动作超时阈值
MAX_STEP_RECOVERIESL22单个步骤允许的恢复性重试次数
STEP_SUCCESS_THRESHOLDL20.85步骤产出的达标判断阈值
MAX_REPLAN_ROUNDSL34单轮目标下最大重规划次数
MIN_REPLAN_INTERVALL32 step两次重规划之间的最小步数间隔
MAX_REFLECTION_ROUNDSL43整个任务周期内最大目标反思次数
GOAL_FREEZE_STEPSL410 step目标冻结期:前 N 步不允许修改目标
HUMAN_CONFIRM_THRESHOLDL40.6置信度低于该值时请求人工确认

MAX_ACTION_RETRIES 设为 3,是权衡了“偶发网络抖动”和“系统性失败”的结果。低于 3,很多本来能恢复的偶发错误会直接升级;高于 3,面对无效动作时又会浪费太多时间。L4 的 GOAL_FREEZE_STEPS 也很有用,它防止模型一开始因为信息不足就频繁改目标。前 10 步内目标被冻结,10 步之后才允许 L4 根据新信息做反思。这样反而比“随时可反思”更稳。

3.2 四层循环核心伪代码

为了让思路更具体,我把这套四层嵌套循环的核心骨架用伪代码写出来。实际项目中还要接入工具调用和观察接口,但骨架结构基本就是下面这样。

# 四层嵌套循环核心骨架 def run_agent(task_desc): plan = make_initial_plan(task_desc) global_state = init_global_state(task_desc) reflection_count = 0 # L4 目标反思循环(最外层) while not goal_satisfied(task_desc, global_state): if reflection_count >= MAX_REFLECTION_ROUNDS: request_human_confirm(global_state) break # L3 规划调整循环 for planning_round in range(MAX_REPLAN_ROUNDS): if plan_is_workable(plan, global_state): break plan = revise_plan(plan, global_state, reason="plan_invalid") else: # 重规划次数超限,上报 L4 global_state.add_issue("replan_exhausted", plan) break # L2 步骤执行循环 step_results = [] for step in plan.steps: step_ok = False # L1 原子动作执行循环(最内层) for attempt in range(MAX_ACTION_RETRIES): result = execute_action(step.action, step.args) if action_succeeded(result): step_ok = True break record_failure(step.id, attempt, result) if not is_retryable(result): break if not step_ok: mark_step_failed(step) global_state.add_issue("step_failed", step) break step_results.append(result) update_global_state(result) # 步骤失败后,交给下一轮 L3/L4 处理 if not can_proceed(global_state): global_state.reflection_count += 1 continue # 判断是否达成目标 if goal_satisfied(task_desc, global_state): break reflection_count += 1 global_state.reflection_count = reflection_count return format_result(global_state)

注意代码里的 break 都带有明确的语义:L1 的 break 是动作成功或不可重试,L2 的 break 是步骤失败,L3 的 break 是重规划次数超限,L4 的 break 是目标达成或人工介入。每一层 break 之前都有一行状态写入,确保外层能感知内层发生了什么。

3.3 防止失控的多道保险闸

四层嵌套循环最怕的就是失控,特别是“死循环”。我在实现中加了五道保险,缺一不可。

第一道是动作级超时。每个动作执行前会启动一个定时器,到时间未返回就判定失败。没有这一步,L1 会卡在某个外部阻塞调用上完全卡死整个系统。第二道是重试上限。失败记录达到上限后,标记为不可恢复,强制跳出内层循环。第三道是重规划次数上限。如果四轮重规划都没解决计划冲突,L3 直接上抛给 L4,不再自转。第四道是全局令牌消耗。整个任务有总动作次数预算,以防某条路径反复被重试却始终推进不了。第五道是人工确认兜底。L4 在连续反思两轮后目标指数仍低于阈值时,必须向用户确认,而不是自己拍板换方向。

这五道保险听起来都是很小的逻辑,组合在一起却能显著减少“看起来在动、实际上一直在原地打转”的问题。我见过不少 Agent 项目崩溃,都不是模型不行,而是没有在架构层面设这些刹车。

4. 实测中常见的故障模式与排查实录

4.1 内层死循环,外层却完全失聪

这是最典型的问题。现象是整个任务看起来很忙碌,实际一直卡在同一个动作上反复重试。为什么外层感知不到?因为 L1 每次失败后只是把状态写进内部缓存,没有及时上报。外层看到的是“动作还在执行中”,自然一直等待。

排查思路很直接:检查失败记录有没有向上一层同步。我后来改成 L1 每失败一次就往 L2 发一条异步状态更新,并在连续失败两次后立即升级上报,而不是等重试结束才汇报。这样 L2 能提前感知风险,尽早启动恢复流程。

4.2 上下文膨胀导致动作质量断崖式下降

四层循环初始版本最大的失控来源,是各层之间无脑传完整历史。做到第十步时,L4 的上下文里已经塞了几万字的工具调用日志,模型开始忘掉原始目标,动作质量明显下降。

解决办法就是前文说的“只传摘要”。我把层间传递彻底改成结构化摘要格式,L1 传动作结论(成功/失败/耗时/异常码),L2 传步骤结论(达成/偏差/风险),L3 传计划结论(可行/修订/原因)。实测下来上下文消耗直接下降了 60%,而且越到任务后期越稳定。

4.3 目标循环过于敏感,频繁改方向

四层架构加完后,L4 的反思机制反而成了新的痛点。因为环境里每个新信号都可能触发它重新审视目标,于是 Agent 经常刚执行几步就说“我好像理解错了目标”,然后推倒重来。整个系统变得极度不稳定。

后面我加入 GOAL_FREEZE_STEPS 才真正解决这个问题。前 10 步内目标锁定,任务描述和外部反馈必须先积累到一定量,才允许 L4 启动反思。同时,目标修正必须附带“原目标描述 + 当前任务状态 + 修正理由”三条信息,这样下游的 L3 才能区分这次修正是方向性调整,还是只是权重微调。

4.4 规划循环把失败原因归错层级

还有个常见问题是 L3 在修订计划时,把“动作选型错误”和“目标描述不清”混为一谈。比如某个动作换了三种工具都失败,L3 却认为是目标问题,试图修改目标。这会导致目标和计划正在两层同时变化,系统状态变得很难追踪。

后来我加了一个失败分类器,在 L1 上报时就会打好标签:动作参数错误、动作选型错误、环境状态不匹配、目标冲突。L3 只处理前三种,最后一种直接放给 L4。这相当于在层与层之间加了一道分流闸,让失败归因更干净。

4.5 常见问题速查表

故障现象可能根因排查步骤修复手段
任务长时间未推进,动作反复执行L1 重试上限过高,失败未上报查失败登记表,看失败类型分布降低重试上限,提早上报
步骤已失败但计划继续执行L2 步骤验证逻辑缺失检查步骤预期的生成逻辑增加步骤产出校验
重规划频繁触发,计划改来改去L3 对计划可行性的判断太严格检查重规划间隔限制增加 MIN_REPLAN_INTERVAL
Agent 方向反复摇摆L4 反思频率过高查看反思触发时的上下文量延长目标冻结期
上下文越来越长,响应变慢层间全量日志传递统计各层接收到的 token 量改成结构化摘要接口

5. 如何设计评测指标,验证四层循环真实有效

5.1 评测维度:不只看完成率

判断架构改得好不好,不能只盯着“最终任务完成率”。四层循环改动后,整个系统的行为模式都变了,需要从多个维度去评估。我常用的指标有这几个:任务完成率、平均执行步数、重规划率、人工介入次数、目标偏移次数、动作重试率、以及事后满意度评分。

其中“目标偏移次数”是很有观察价值的指标。单循环方案经常表现为:任务完成了,但最后交付的东西跟用户最初想要的已经偏离了很远。四层方案加入 L4 之后,目标偏移次数明显下降,代价是平均执行步数会略有上升——因为它刻意停下来检查自己的方向。

5.2 用场景集做回归测试

我维护了一个低成本评测场景集,包含三类典型任务:第一类是信息整理类,目标描述清晰,但数据源零散,容易中途出错;第二类是工具调用链类,单步动作频繁失败,需要不断重试或换工具;第三类是目标模糊类,初始描述只有一句话,需要 Agent 在飞行中逐渐明确需求。每次调整四层循环参数时,我都拿这三个场景跑一遍对比。

具体的评测方法,是把同一批任务分别用单循环、双循环、四层嵌套三种方案各跑若干次,记录下数据和失败原因。不需要多复杂,只要场景稳定,结果可靠就行。

5.3 一套可参考的实测对比结果

下面这组数据来自我参与维护的某评测平台上的手工对比测试,任务集包含 30 个中等复杂度的真实任务。数据不一定普适,但能说明四层嵌套带来的变化趋势:完成率明显上升,人工介入次数下降,但执行步数略有增加。

方案任务完成率平均执行步数人工介入次数目标偏移次数
单循环方案43%18.27月半
双循环方案61%21.54中
四层嵌套方案78%24.12少

数据本身不重要,重要的是背后的结构:四层循环通过增加可控步数,换取了对任务方向和计划质量的持续校验。如果你在跑自己的对比测试,不妨把步骤完成比例和失败分布也单独拿出来看,往往能发现架构中更隐蔽的问题。

6. 再往下走,一些值得记住的经验

6.1 三个我反复提醒自己的细节

第一个细节,完成一次动作后不要立刻判定步骤成功,一定要先验证这一步的产物是否符合步骤预期。省略这个校验,四层循环的 L2 就形同虚设。第二个细节,失败信息要带标签,不能只带文本描述。只有标签化,才能让 L3 和 L4 准确判断该不该介入。第三个细节,人工确认不能没有,但也不能太频繁。最好设计成基于置信度的阈值策略,让系统在自己能兜住的时候尽量自己兜。

这三个细节都不是什么高深技术,但我在实践中发现,很多人做完四层循环后觉得效果不好,追根溯源都能归结到这几个基础点上。

6.2 从三层升级到四层时,最需要改的不是代码

如果你已经有一套三层循环(动作、步骤、目标),想升级到四层,最需要改的不是代码,而是思维方式。三层结构里,目标和计划是揉在一起的,修改目标就等于修改计划。四层结构里,两者完全分离:L3 只优化计划,L4 才决定目标。这个分离会让中间层的逻辑变复杂,但好处是目标变化时,L3 可以先旧计划做评估,再决定是修改还是推翻,而不是直接带着目标就上。

我实际升级时,第一个动作是给 L3 增加了一个“计划状态缓冲”:无论是否要改目标,都多准备一版非目标变更的修订方案。这个小改动让我免去了很多因目标抖动导致的计划任务被同步打乱。

6.3 多 Agent 协作场景下的循环扩展

四层嵌套循环的最后一问:多 Agent 协作时怎么办?我的做法是把每个子 Agent 视为一个完整的四层循环实例,而协作调度器本身再做一层外层循环,用于判断子 Agent 之间是否有冲突、任务拆分是否合理、以及整体目标是否被某个子 Agent 带偏。这相当于一个“五层”结构,每层边界更清晰,代价是协调成本更高。

如果只是主 Agent 对子 Agent 发送任务后就不管输出,很容易出现子任务各自都完成了、整体目标却被拆碎的问题。在调度器这一层也需要一个类似于 L4 的反思机制,定期对照全局目标,检查任务拆分的有效性,提高全局一致性的保障能力。

我自己在实际操作中最深的体会是:四层嵌套循环不是一套拿来就能跑死的代码模板,它更像是一种关于控制粒度的思维方式。你可以在完整框架里跑,也可以只挑其中一两层先接入。最终目标都是让 Agent 在每个尺度上都保持对状态变化的敏感度——动作不对时能换,步骤不对时能停,计划不对时能改,目标不对时能停下来问人。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进