返回 FEED
AGENT2026-05-26

长任务 Agent 的最小工程闭环:三层五态控制架构

长任务 Agent 的最小工程闭环:三层五态控制架构

很多人第一次认真用 Agent,都会经历相似的过程。

前十分钟很惊艳。它能读代码、改文件、跑命令,还能自己解释下一步要做什么。半小时后开始不放心。它还在执行,但你已经不确定它有没有记住最初的目标。两小时后,问题变得更明显:它做了很多事,改了很多文件,跑了很多验证,最后交上来的结果却经不起细看。

Claude 工程师把这个问题拆得很准:Agent 会丢状态,会误判工作量,也会高估自己的输出质量。这三个问题放在一起,就会形成长任务里最常见的失控链路:上下文越来越脏,计划越来越虚,验证越来越浅。最后 Agent 没有突然变笨,只是在一个缺少控制回路的系统里越跑越偏。

所以这篇文章不聊怎么写一个更"聪明"的 prompt。聊一个更工程的问题:如果要让 Agent 稳定处理长任务,系统里至少要补上哪些控制层?

三层核心控制面

Context 管现场,Planning 管边界,Verification 管证据。

任何一层松掉,另外两层都会被拖下水。

Context 层:状态会丢

上下文窗口经常被理解成"模型能记住多少东西"。这个理解太乐观了。

对 Agent 来说,context 更像一张工作台。任务说明、文件片段、命令输出、错误日志、用户补充、模型自己的中间判断,全都堆在这张桌子上。桌子变大当然有用,但桌子再大,也不等于它能自动整理材料。

Anthropic 在 Claude Code 最佳实践里讲得很直接:context window 会很快被填满,窗口越满,模型越容易忘记早期指令或犯错。它还建议给 Claude 明确的验证方式,比如测试、截图和期望输出,因为这是提升结果质量的高杠杆动作。

更麻烦的是 session 之间的状态断裂。一次任务没做完,换一个 session 继续。Agent 看起来能接上,但它接上的往往只是压缩摘要,只剩压缩后的现场。哪些决定已经确认过,哪些方案被否掉,哪些文件刚改过但还没验证,哪些失败路径不要再试,这些信息如果没有被写进外部状态,很容易在下一轮里丢掉。

生产级 Agent 不能把状态全押在 context 里。最小可用的状态层至少要有:任务目标、当前进度、阶段产物、决策记录、文件变更、验证结果、阻塞点、人工确认记录。写进 progress.md、任务 ledger、trace log、issue comment 或数据库,才有机会在下一轮被稳定读回。

一个好的 Agent 系统,会主动把"工作状态"和"推理上下文"分开。context 里只放当前步骤需要的材料,长期状态放到外部。每次进入新阶段,Agent 先读状态,再继续执行;每次完成一个阶段,Agent 先写状态,再清理上下文。

Planning 层:计划会漂

人类工程师接到需求,会下意识判断:这是不是小改动?会不会牵动数据结构?有没有迁移?有没有兼容问题?验收标准是什么?适合一次做完还是拆成几个阶段?

Agent 经常没有这个尺度。你让它"改一下文档生成流程",它可能把整个内容系统都扫一遍。你让它"做一个可用 demo",它可能只搭一个 UI 空壳。你让它"修一个 bug",它可能顺手重构半个模块。

规划层要解决的具体问题:

  • 这次任务的交付物是什么?
  • 哪些内容明确不做?
  • 每个阶段的完成标准是什么?
  • 当前阶段最多允许消耗多少上下文、多少工具调用、多少时间?
  • 如果做到一半发现范围变大,什么时候停下来重新估算?
  • 如果验证过不了,是否允许继续扩展实现,还是必须先修当前问题?

没有这些约束,计划就只是一个开场白。Agent 会在执行过程中不断重新解释计划,最后交付一个和最初目标越来越远的东西。

更好的做法是把 Agent 规划分成两层:

  • 任务切分:回答"这件事应该怎么拆"。把大任务拆成可以独立验证的小阶段,每一段都有清楚的输入、输出和验收方式
  • 运行预算:回答"这一段最多跑到什么程度"。包括 max turns、token budget、tool call budget、时间上限、失败重试次数,以及触发人工确认的条件

两层缺一层,Agent 都容易失控。只有任务切分没有运行预算,Agent 可能在一个子任务里无限探索。只有运行预算没有任务切分,Agent 会在快到限制时随便找一个能交差的版本收工。

Verification 层:验证会浅

Agent 很擅长给自己的工作一个体面的收尾。它会说"已完成实现""已通过基本验证""核心流程正常"。如果你继续追问,它还能解释验证步骤,列出改动文件,补一段风险说明。问题在于,这些话有时候只是在替一个很浅的验证包装结论。

最常见的三种验证失灵:

curl-only verification:接口能返回 200,Agent 就说功能可用。它没有点过页面,没有走过真实用户路径,没有看浏览器控制台,没有检查数据是否真的写入,也没有确认错误状态怎么展示。

stub 逃逸:Agent 做到复杂功能时先写简化版本(mock、stub、placeholder),但后面忘了回来,或把临时实现包装成阶段成果。支付流程只打印日志没有真实状态机;权限判断写了 TODO 但页面已放开入口;RAG 只返回固定示例却说"检索链路已打通"。

自我评分过高:Agent 评自己的输出时经常会发现问题,但把问题降级。"目前实现满足核心需求,后续可优化"——很多关键缺陷就是被这句话放过去的。

真正的问题在于,Agent 没有足够独立的评价位置。写代码的 Agent 天然希望任务收敛。它已经投入了上下文、工具调用和多轮推理,也在接近限制。到了后半程,它会倾向于把不确定问题解释成可接受风险,把未完成部分解释成后续优化,把浅验证解释成基本通过。

验证层不能只依赖 Agent 的口头报告。一个能跑长任务的 Agent 系统,至少需要三类验证:

  1. 机器验证:能用工具判断的,就不要交给模型判断。测试、类型检查、lint、build、schema validation、数据对账、截图 diff、可访问性检查、日志扫描
  2. 环境验证:Agent 要在真实或接近真实的环境里走一遍。Web 应用要用浏览器点,不只用 curl。数据任务要读回结果,不只看写入命令成功
  3. 独立评价:生成者和评价者要分开。Planner 拆任务,Generator 执行,Evaluator 按 rubric 检查。Evaluator 不负责安慰 Generator,只回答几个硬问题:需求是否真的满足?关键路径是否真的跑通?有没有 stub 或 TODO 被包装成交付?失败路径有没有处理?验证证据够不够?

五层完整架构

把前面三个问题放到一起看,会发现 Agent 失控往往不属于单点故障。状态层没有沉淀,规划层就只能靠当前上下文猜任务进度。规划层没有边界,执行层就会不断扩展范围。验证层不够硬,Agent 就会把局部成功包装成整体完成。监督层缺位时,所有风险都会一路流到最后,由用户自己兜底。

生产级 Agent 至少要有五层:

1. 状态层:让任务有可恢复的现场

保存 Agent 不能丢的东西:任务目标、当前进度、阶段产物、决策记录、文件变更、验证结果、阻塞点、人工确认记录。形式不重要,关键是可读回、可续跑、可审计。

2. 规划层:把大任务压成可调度的小任务

把用户目标拆成阶段、依赖、预算和停止条件。计划不能停留在好看的 checklist。它更像调度系统里的 job spec:当前阶段做什么,输入是什么,输出是什么,用什么验证,最多允许跑多久,失败几次后停止,哪些操作需要人工确认。

3. 执行层:工具调用只是其中一部分

读文件、改代码、跑测试、开浏览器、查日志、调 API、写文档、生成图片。关键不在工具数量,关键在每次工具调用都能回到任务状态里。一个命令跑完,输出要进入状态。一个文件改完,变更要进入状态。

4. 验证层:把完成变成证据链

尽量使用外部证据:测试结果、浏览器截图、数据库 readback、日志、trace、diff、rubric 评分、人工 review。验证层最好和执行层分开。同一个 Agent 做完再自评,容易把风险解释成可接受。独立 evaluator 会严格得多。

5. 监督层:控制权限、成本和升级路径

Agent 什么时候能继续,什么时候必须停。包括权限控制、预算控制、loop budget、max turns、危险操作确认、发布前确认、失败升级、人类接管、回滚策略。

监督层不会频繁打断正常任务,也不会让 Agent 无限自由发挥。它只在几个关键点介入:任务范围扩大、预算接近上限、验证连续失败、操作涉及删除/发布/权限/付费/生产数据、Agent 发现自己无法判断、结果影响真实用户。

具体模式

Spec-first:先写施工单,再让 Agent 动手。目标、非目标、约束、验收、风险。半页就够。关键是让任务在执行前先固化一次。

Plan gate:计划先过关,再进入自动执行。阶段拆分、每阶段交付物、验证方式、预计碰到的文件或系统、停止条件、需要人工确认的操作。这一步最适合人参与。

Progress ledger:每个阶段都写状态。Current Goal / Completed / Changed Files / Decisions / Verification / Open Risks / Next Step。人也可以扫一眼 ledger 快速知道做到哪里。

Independent evaluator:生成者不要当最终裁判。Evaluator 的输出不要写成"整体不错,有一些建议"。更好的格式:Result: PASS/FAIL、Evidence、Blocking Issues、Non-blocking Issues、Required Fixes。Evaluator 必须有权判 FAIL。

Browser-level verification:Web 产品必须点过。页面是否能打开、控件是否能点击、表单是否能提交、数据是否能显示、错误状态是否正常、控制台有没有报错、移动端有没有明显布局问题。

Stop condition:连续两次验证失败、任务范围明显扩大、需要删除/发布/改权限/花钱/触碰生产数据、当前阶段超过预算、遇到多个可行方案但无法判断取舍、关键依赖不可用、用户给的目标互相冲突。

Rollback path:代码任务至少要有 git diff。数据任务要有 dry-run、备份、row count。发布任务要有草稿、预览、读回验证。配置任务要记录旧值。

Trace everything:输入任务、使用的模型和工具、关键工具调用、文件变更、验证结果、人工确认、失败重试、最终产物。

模型变强后 harness 应该变薄

每一个 harness 组件背后,都藏着一个判断:当前模型在这件事上还不够稳定,所以系统要补一层。模型能力提高,这个判断就应该被重新测试。继续保留过时的 harness,会让系统变慢、变重,也会制造新的失败点。

但有几类东西很难被模型能力完全吃掉:

  • 外部状态:模型可以读更长的上下文,但真实任务里的状态不只存在于上下文里。文件系统变了,数据库变了,API 状态变了,浏览器页面变了
  • 外部验证:"有没有真的点过页面""数据库里是不是写进去了"这些问题需要环境反馈
  • 权限和责任:删除文件、发布内容、修改权限、触碰生产数据、花钱调用外部服务,不能因为模型更聪明就全交出去
  • 成本:模型越强单次调用越贵,越需要 budget routing、max turns、timeout 和 circuit breaker

真正该避免的两种极端:

  • 迷信模型:模型一升级就把状态、验证、权限、预算都交给它临场判断。短 demo 很漂亮,长任务容易埋雷
  • 迷信 harness:模型已经能稳定做的事还强行拆成复杂流程,最后系统慢、贵、难维护,错误还藏在编排层

更好的做法是定期问:这层 harness 现在还在解决真实问题吗?如果答案是肯定的,就保留并做得更可观测。如果是否定的,就删掉让模型直接做。

Agent 架构师的工作,是持续识别模型当前的能力边界,然后只在边界外补必要的工程控制。