Francis
Francis
发布于 2026-07-12 / 12 阅读
0
0

第2篇——上下文工程

#AI

上下文窗口就那么大,放什么、不放什么,直接决定 Agent 跑不跑得起来。这本书讲的就是这件事:怎么把对的信息,在对的时间,塞进窗口里。

目录

第1章 上下文的诅咒

提示工程不够用了。这一章从 Context Rot 讲起,说清楚上下文越长,模型越容易犯的四种错。

第2章 三大手段:卸载、压缩、隔离

别再往提示词里硬塞。能往外丢的丢出去,能压短的压短,能隔开的隔开。每种手段的边界和代价都讲明白。

第3章 动态上下文实战

看 Cursor 怎么处理上下文,再比较 RAG 和 Agentic Search 到底差在哪、各自什么时候该上场。

第4章 Menlo 踩过的坑

KV 缓存为什么是绕不开的成本,以及"把文件系统当上下文"如何改变了整个架构思路。

第5章 长跑型 Agent 的上下文管理

压缩、串行接力、环境隔离,三种让 Agent 撑过长时间任务的具体办法。

上下文的诅咒

本章是 Hermes Engineering 系列第 2 模块的第 1 章。

AI 的任务已经从单次问答变成了持续项目。但有个反直觉的现象:上下文越多,模型反而越容易失焦。这就是上下文的诅咒,它从不报错,只是慢慢变糊。

从提示工程到上下文工程

提示工程到上下文工程,不是换了个词,是换了个活法。

早年的提示工程,目标很窄:写好一条提示,让模型在一次调用里给出想要的答案。它是战术,琢磨的是那一瞬间的措辞,作用范围也就是那一次调用。提示写得好,模型能聪明一下;调用结束,聪明也就结束了。

Agent 出现之后,事情变了。AI 能自己规划、调工具、跑多轮任务,性质从一次性问答变成了持续项目。这时候它要的不再是一条提示,而是完整的信息视野:系统指令、可用工具、历史对话、从外部检索来的知识,全都得在上下文里就位。

所以上下文工程不只是在写提示,它更像一门架构活。你要动态地、持续地帮 Agent 打理它的整个上下文状态。说白了,我们这批人正在从调提示词的,变成搭系统的。

Context Rot:上下文腐烂

模型越来越强,上下文窗口也越开越大,那为什么不直接把所有信息都塞进去?

因为所有大模型都绕不开一个硬约束:上下文腐烂(Context Rot)。上下文里的信息越多,模型精确回忆、做长距离推理的能力就越往下掉,而且掉得很平滑,你不容易察觉。

一句话:上下文越长越杂,模型越容易走神。

两个底层原因

第一,架构本身的局限。主流大模型都跑在 Transformer 上,每个 Token 都要和上下文里所有其他 Token 产生关联,关系数量是 N² 量级。上下文长度翻一倍,要处理的关系数差不多翻四倍。人的注意力也这样,信息越多,摊到每件事上的精力就越少。

第二,训练数据的偏差。模型预训练时读过的文本绝大多数是中短篇,它很会处理短序列,但长文本的经验少得可怜。

上下文腐烂最阴的地方在于它是结构性的:不会一下子崩,而是慢慢退化。模型不会冒出一句"我不行了",它只是开始答非所问、漏掉重点、逻辑漂走。

最危险的就在这里:它不报错,只是变糊。

四种失效模式

上下文腐烂是底层状态,落到具体任务上,会表现出四种失效模式:

上下文污染(Contamination):一次幻觉或者错误信息混进了上下文,后面还被当成事实接着用。一旦有毒数据进入 Agent 的认知循环,后面整条决策链都可能被带歪。

上下文干扰(Interference):上下文里信息太多,把模型的预训练知识盖住了。大量低价值的即时信息淹没了它本来的知识信号,让它在噪声里迷失,做出违背常识的判断。

上下文混淆(Confusion):多余的、不相关的语境干扰了最终回答。模型注意力被摊薄,抓不住核心逻辑,还会把两个不相干的概念乱连到一起。

上下文冲突(Conflict):上下文不同部分互相矛盾。系统提示说"保持简洁",历史对话里却是一堆冗长例子,模型左右为难,行为变得混乱或者犹豫不决。

Context Rot(上下文腐烂)
├─ 上下文污染:幻觉渗入被当事实 → 决策链条被污染
├─ 上下文干扰:低价值信息淹没常识 → 违背常识的判断
├─ 上下文混淆:注意力稀释,错误关联 → 核心逻辑丢失
└─ 上下文冲突:矛盾信息导致行为混乱 → 模型犹豫混乱
最终:系统输出质量下降

图解:Context Rot 是病因,四种失效模式是并发症。模型不报错,只是慢慢变糊。

因果关系

打个比方。上下文腐烂是病根,四种失效模式是并发症。一个精神饱满的司机,烂路也能开过去;一个疲劳的司机,同样的烂路出事概率高得多。

腐烂带来的注意力稀释和信噪比下降,会直接引发干扰和混淆。模型在腐烂状态下推理能力本来就弱,更容易产生幻觉,等于自己往上下文里投毒。更麻烦的是,腐烂还会遮住模型的眼睛:相隔很远的两条矛盾信息,可能已经超出了它有效的注意力范围,它根本发现不了冲突。

任务进化:单次问答 → 持续项目
    ↓
Agent 运行依赖动态上下文
    ↓
Transformer 结构:上下文越多,性能越容易腐烂
    ↓
上下文工程成为高可靠 Agent 的必修课

图解:任务复杂度的进化撞上了 Transformer 的物理墙。不主动设计上下文,腐烂就会吞噬 Agent 的判断力。

把整条逻辑串起来:任务变复杂,Agent 跑起来依赖动态上下文,而 Transformer 结构决定了上下文越多越容易腐烂,于是上下文工程成了高可靠 Agent 的必修课。

所以真正的出路不是等一个无限大的内存,而是自己上手当上下文架构师,用工程方法主动设计上下文,让模型一直保持清醒和聚焦。

常见错误

错误做法

正确做法

为什么

把所有信息塞进上下文,觉得"窗口够大就行"

主动设计上下文,只注入下一步决策需要的信息

Context Rot 是结构性的:Transformer 的 N² 约束加上训练数据偏差,上下文越长性能越差,而且不报错

一次幻觉混进上下文后继续当事实用

保留错误信息但做好标记和隔离,让 Agent 从失败里学

上下文污染一旦进入认知循环,后面整条决策链都会被带歪

上下文里塞满工具返回的原始日志

用子 Agent 过滤噪声,只回传 50-200 Token 的关键信息

上下文干扰:大量低价值信息淹没模型的预训练知识,让它在噪声里做出违背常识的判断

系统提示要求简洁,历史对话却是一堆冗长例子

保持指令风格一致,矛盾信息必须清掉

上下文冲突让模型左右为难,不同部分的矛盾指令会导致行为混乱或犹豫

无关的上下文也留着"以防万一"

只保留和当前任务相关的语境

上下文混淆:注意力被摊薄,模型把两个不相干的概念错连,核心逻辑丢失

三大支柱

本章是 Hermes Engineering 系列第 2 模块的第 2 章。

业内做 Agent 的头部团队,不约而同地收敛到同一套架构:一个极简的原子函数调用层,加上一个庞大的、可供探索的外部文件系统和脚本库。这不是谁的拍脑袋设计,而是整个行业为了兼顾"能力要无限扩展"和"上下文窗口就那么大"这两个死对头,一步步演化出来的解法。

核心矛盾

Agent 说白了就是个在循环里调工具的大语言模型。这个简单的循环一旦碰到长任务,就会炸出一个大问题:上下文爆炸。Menlo 提过一个典型任务平均要调 50 次工具,Anthropic 也佐证过,生产级 Agent 的对话轮次能拉到几百轮。

这意味着模型每走一步,都得背着前面所有轮次的工具结果。成本和时间先不提,最要命的是上下文会腐烂。

所以核心矛盾就在这:Agent 任务天生会产出海量上下文,可模型在海量上下文下偏偏越来越不行。

上下文工程干的事,就是用刚好够下一步用的正确信息,把窗口填满。它拆下来是三根支柱:

核心矛盾:任务产生巨量上下文,但模型性能随上下文增加而下降

├─ 卸载 Offloading:文件系统即上下文 / 分层行动空间 / 渐进式披露
├─ 缩减 Reduction:可逆压缩·指针替代 / 不可逆摘要·最后手段
└─ 隔离 Isolation:通信模式·低成本 / 共享上下文·全视野

底座:极简原子函数层 + 庞大外部文件系统

图解:三大支柱的共同目标,是让模型在每一步只看它需要的东西。多一点是噪音,少一点是盲区。

支柱

核心思想

卸载 Offloading

把上下文从 LLM 窗口挪到外部存储,需要时再拣回来

缩减 Reduction

每步传给模型的东西,能小就小

隔离 Isolation

不同的独立任务,各用各的上下文窗口

支柱一:卸载

卸载这件事,已经从"卸数据"走到了"卸工具"。

先说卸数据。给 Agent 一个文件系统,它就能在长任务里把信息存下来、以后想起来。Anthropic 的多 Agent 研究里,Agent 会把计划写进文件,干完子任务再读回来,确保没跑偏。Claude Code 的 .claude.md 也是这个思路,让 Agent 在多次调用之间把用户偏好持久存住。

再说卸工具,也就是分层行动空间。要是把 100 个工具全塞进 Prompt,模型会犯晕,Prompt 也会胀爆。Menlo 的解法是把函数调用层压到极简,只留少数原子工具(bash 加文件操作),其余动作全部卸载成文件系统里的脚本。

你看几个顶级 Agent 的原生工具数都少得可怜:Claude Code 大概 12 个,Menlo 不到 20 个,Deep Agents 只有 11 个。

再往前走一步,是渐进式披露。连脚本都不用一上来全告诉模型。Agent 启动时只加载每个 Skill 的标题,真要用了才把完整内容读进来。它靠 bash 工具在自己那堆脚本目录里翻,找到说明书自己看。

三层行动空间

Menlo 把行动空间由内到外分了三层。

第一层是函数调用,也就是原子操作。这是唯一一层直接跟模型打交道,只有极少数固定不变的原子函数。它拿灵活性换了可靠性和性能,模式安全、缓存友好。

第二层是沙盒里的现成程序,走命令行。Agent 通过 execute_shell 跑预装好的工具。模型被教着去自己发现、自己学:引导提示告诉它工具目录在哪,它主动 ls 看有什么,再跑 --help 学用法。这一层适合那种能等一下的复杂离线任务。

第三层是包和 API,也就是写代码。最开放,能力也最强。Agent 自己写 Python 脚本去调任意 API。什么时候才走到这层?只有前两层的现成工具都搞不定时,它才会做出"我得写代码了"这个决定。

站在模型的角度看,它根本不知道有三层。它最后要做的,无非是调第一层那几个原子函数。接口简洁、缓存友好、设计正交。

唯一的接口(模型视角)
├─ 第一层 函数调用:少数原子操作(极简固定、模式安全)
├─ 第二层 沙盒使用程序:execute_shell 跑预装工具(按需发现、自主学习)
└─ 第三层 包和 API:Agent 写 Python 脚本(能力缺口时才触发)
特性:第一层可靠+缓存友好,第二层灵活+可扩展,第三层开放+最强能力

图解:三层行动空间对模型完全透明。它只看到几个原子函数,但靠这几个就能撬动整个工具世界。

支柱二:缩减

先说压缩,它是可逆的。工具结果放旧了,就把完整内容挪到文件里,在历史消息中换成指向那个文件的指针。以后 Agent 还能 100% 把原始信息捞回来。

压缩不等于摘要。压缩是把内容无损地外移,用个轻指针顶替;摘要是有损、不可逆的,只有在压缩实在省不下多少时才当最后手段用。

执行上讲究顺序:先反复压缩,等压缩收益变小了,再上摘要。做摘要之前,先把完整上下文卸到日志文件里买份保险。压缩只压旧的 50%,最新的几个完整工具调用留着当 Few-shot 示例,帮模型校准行为。摘要必须基于完整版本,不能拿已经压过的东西再压。

再定一个浅腐烂阈值,大概 128K 到 200K Token,到这个数优先压缩,快触顶了才开摘要。

支柱三:隔离

隔离有两种搞法。

一种是通过通信。主 Agent 给子 Agent 丢一句简短指令,子 Agent 在一个干干净净的隔离上下文里把活干完,只把最终结果递回来。成本低、延迟低、KV 缓存也友好,适合那种能切得清清楚楚的简单任务。

另一种是通过共享上下文。子 Agent 被允许看主 Agent 的完整历史,但换一套新的 System Prompt 来行动。好处是带着完整视野能啃复杂任务,代价是 KV 缓存彻底失效,全价预填充成本得照付。

业界共识

说到底,所有顶级的生产级 Agent 都收敛到了同一套打过实战的架构:极简的原子函数调用层,加上庞大的、能自己探索的文件系统和脚本库。上下文工程也就此从零散技巧,变成了一套系统化的设计思路。

动态上下文与实战

本章是 Hermes Engineering 系列第 2 模块的第 3 章。

上下文的设计思路正在从"一次性塞满"转向"按需发现"。模型当 Agent 的能力越来越强,这时候反而该少给点细节,让 Agent 自己按需去拣相关的上下文。

静态上下文:AI 的出厂设置

静态上下文是智能体在启动前就备好的:它是谁、能干什么、该怎么干。AI 的出厂配置由三大核心组件构成:

系统提示是 AI 的灵魂,定下模型的身份、职责和处事方式。关键是粒度要合适:太细,写成伪代码一样的 if-else 硬编码,模型就僵了;太虚,一句"请像专家一样思考",输出就开始飘。做法是用结构化分层加迭代优化,先丢一个最小版本测,再针对性补。

工具是 AI 的手和眼,负责跟外部世界打交道。但工具的定义本身也算上下文:每个工具的名字、描述、输入输出说明,都在占模型的注意力预算。所以原则是最小可行工具集,只留能完成任务的那最小一组。连人类工程师自己都拿不准该用哪个工具时,就别指望 AI 能选对。

示例是告诉模型你希望它怎么想、怎么答。它不是让模型背答案,而是教一种思考方式。示例堆太多,上下文就胀了。好的示例不追求覆盖所有情况,而是亮出一种思考模式,价值在代表性,不在数量。

动态发现:Cursor 的五大实践

Cursor 团队有个判断:当下模型的能力、成本、可靠性都还受约束,最稳的路线是选更简单、更可控、也更好演化的原语,拿来当外部系统的底座。

实践一:工具响应转文件

Agent 跑一个数据库迁移脚本,终端吐出 5000 行日志。传统做法是截断到 2000 字符,可关键报错偏偏可能藏在被截掉的那截里。Cursor 不这么干:把输出完整写进文件,不塞进上下文,只跟 Agent 说"结果在这儿"。再配一个 Tail 工具从末尾开始探,末尾信息够用就收手,不够再往里展开。先探后展开,直到信息刚好够用。

实践二:摘要时引用对话历史

对话太长必须摘要时,原始完整对话被转存成文本文件。Agent 脑子里只留简短摘要,但手里攥着历史文件的路径。一旦发现摘要里的信息不够,就停下来去搜历史文件,把具体细节精准捞回来。这就像开卷考试,脑子里只记重点脉络,细节随时能翻书查。

实践三:Skills 按需加载

所有 Skill 的全文塞进 System Prompt,会严重膨胀。Cursor 的做法是静态上下文里只留名称和描述,全文等用到了再加载。能靠 Grep 关键词搜就先用关键词,关键词不够再上语义匹配。

实践四:MCP 工具按需加载

传统做法是把所有工具说明书塞进 Prompt,100 个工具很可能吃掉 5 万 Token。Cursor 把它卸载到文件系统,初始 Prompt 只留一个极简菜单。Agent 看到菜单、意识到需要某项能力时,主动去读说明书文件。Token 消耗因此降了 46.9%。

实践五:终端会话视为文件

集成终端的所有输出,无感写入本地日志文件。用户说一句"修好它",Agent 不需要你粘贴任何上下文,自己读终端日志、grep 定位 error、分析堆栈、给出修复建议。整个过程你一次复制粘贴都不用。

RAG vs Agentic Search

用户问题

├─ RAG(推理前检索):问题向量化 → 向量数据库查找 → 拼到上下文 → 模型回答

└─ Agentic Search(即时检索):模型思考是否需要信息 → 执行 list_files

       → 观察结果 → 选择打开文件 → 信息够吗?够就停,不够继续探索

混合策略最优:启动时 RAG 预加载,运行时 Agentic Search 探索

图解:RAG 是"考试前发的复习提纲",Agentic Search 是"开卷考试现场翻书"。两者结合才是最优解。

推理前检索,也就是 RAG:问题向量化,去向量库找相似片段,拼进上下文,再交给模型。它稳、快、便宜,但信息可能过时,检索不够聪明,也没法主动探索,模型只能被动等投喂。

即时检索,也就是 Agentic Search:模型先想"我需不需要信息",要的话就调工具,执行 list_files、看返回、选文件打开、读前几行,再决定下一步。信息永远最新,只取当下要的,而且能探索。

把两者混着用通常最稳。Claude Code 启动时预加载 CLAUDE.md(这是 RAG),运行时又配了 glob、read 工具(这是 Agentic Search)。

智能探索有两个关键机制。一个是元数据:Agent 不光看内容,还能理解信息结构,文件名、目录、时间戳都是给它指方向的信号。另一个是渐进式披露:别一次把所有信息塞进去,让模型一步步发现。

行业趋势在收敛

Cursor、Minecraft、Devin,还有 Anthropic 的 Skill 机制,不同团队在不同产品形态下,各自独立收敛到了一套很像的工程思路:上下文是稀缺内存,文件系统是近乎无限的外部存储,卸载是缓解压力的基本手段,渐进式披露是默认策略。

Menlo 的教训

本章是 Hermes Engineering 系列第 2 模块的第 4 章。

这是一个真实项目的上下文工程记录:一开始要在微调和上下文工程之间做关键抉择,后面接着是 KV 缓存优化、把文件系统当上下文这些实战经验。

关键决策:微调还是上下文工程

Menlo AI 碰上了每个 AI 产品团队起步时都要纠结的问题:花几周去微调一个专属模型,还是直接基于前沿大模型,轻快地做上下文工程?

打个比方,把一位通才医生培养成专科专家,有两条路。微调是让他去专科深造:拿海量专业病例喂模型,让它专项学习,直接改内部权重。新技能被内化成一种本能,可反馈周期按周算,一旦底层模型换代,之前的投入就很不值钱。上下文工程是给他一套临床指南:不改通才本身,每次干活前发一套完美的指南。模型没真成专家,但每次任务里都表现得像那么回事。迭代快、门槛低、适应性强。

Menlo 选了上下文工程。对绝大多数想转 AI 的团队,我的建议也是默认从上下文工程起步,迭代更快、门槛更低,能很快攒出原型去验证。

KV 缓存命中率:北极星指标

Agent 在多轮循环里反复提交又长又大部分重复的上下文,直接推高了延迟和成本。Menlo 觉得,有一个指标最该盯死,就是 KV 缓存命中率,它是生产级 Agent 最重要的单一指标。

LLM 处理文本时,会把对前面每个 Token 的理解缓存下来。推理引擎用前缀匹配:第一次调用时完整算一遍前缀并缓存,第二次调用发现开头一致,就直接加载缓存,只对新增内容做增量计算。

缓存命中率高,就意味着又快又便宜。输入 10000 Token,其中 9000 命中缓存,成本能从 3 美分掉到 0.57 美分,省下 81%。

KV 缓存工作机制

首次调用:完整计算前缀 Token → 缓存 KV 状态

后续调用:检测前缀是否匹配?

├─ 匹配 → 直接加载缓存,只做增量计算(成本降 81%,延迟大降)

└─ 不匹配 → 重新计算全部(成本全价,延迟高,缓存失效)

图解:KV 缓存命中率是生产级 Agent 的北极星指标。前缀一个字符变了,缓存就全废。

五大黄金法则

围绕 KV 缓存,Menlo 总结了五条:

开启与选型:选支持高效 KV 缓存的推理框架,比如 vLLM

保证会话保持:同一用户的会话路由到同一个工作进程

保持前缀稳定:Prompt 前缀里哪怕改一个字符,缓存就失效

上下文只追加:最友好的操作是在末尾追加,任何中间修改都是缓存杀手

明确标记缓存断点:手动插特殊标记,告诉引擎前缀到哪为止

F1 赛车 vs 全地形越野车

两种模式摆在这儿。F1 赛车模式:固定 Prompt 前缀,把 KV 缓存命中率拉到最高,延迟和成本都压到极致,但扩展性差。全地形越野车模式:动态选上下文,扩展性强,代价是牺牲缓存复用。选哪种,看你业务要什么。

文件系统即上下文

现在的模型上下文窗口越开越大,可在真实 Agent 场景里常常还是不够,甚至成了包袱:物理限制、性能衰减(也就是 Context Rot)、成本高。

压缩有个坑:任何不可逆的压缩都冒着语义丢失的风险。Agent 得靠着历史状态做预测,你根本没法确定哪一步的 Observation 在十步之后还关键。

Menlo 的做法是换个思路:不再靠模型上下文存所有历史,而是把文件系统本身当成 Agent 的外部长期记忆。这等于把架构从内存上下文搬到了外部语义存储。

这么干有三个好处。一是文件系统的空间几乎无限,网页、PDF、代码库天生就能往里塞。二是存进去的数据能长期留着,中间产物也能用结构化方式摆好。三是大模型不再被动等上下文喂,而是被给了工具去主动操作文件系统,"上下文"这个词的外延,从 Token 窗口扩成了 Agent 能交互、能读能写的一个持久化世界。

闪电大脑 + 无限硬盘

Transformer 模型强,但计算成本高得吓人;新兴的 SSM 架构(比如 Mamba)速度快,可长距离记忆是短板。这俩刚好能凑成一对:SSM 当闪电大脑,高效处理眼前任务;文件系统当无限硬盘,把长期记忆原样保住。某种程度上,这就是神经图灵机那个老想法在现代技术下的落地。


运行 Agent

本章是 Hermes Engineering 系列第 2 模块的第 5 章。

Agent 要连跑几百轮,上下文早晚会爆。这一章讲三件事:压缩、串行接力、环境管理。Anthropic 的思路是,在不放弃单 Agent 决策流的前提下,想办法绕开上下文窗口那道物理墙。

压缩策略

上下文一溢出,压缩就是第一道防线。但得说清楚,压缩是有损的。一段一万字的对话压成五百字摘要,细节不可能全留住。

Claude Code 里的做法是让模型自己总结历史对话的核心要点:关键决策、还没解决的问题、重要细节,再把那些冗余的工具调用结果清掉,尽量用最小的信息损耗接着干。顺序是先保召回,能留的都先留着,再慢慢提精度,把重复和无关的东西剔掉。

还有一招更持久:结构化笔记。Agent 干活的间隙定期写笔记,把关键内容存到上下文之外的记忆系统里。Claude Code 会维护一个 notes.md,记下任务目标、没干完的事、依赖关系。哪怕上下文窗口整个被清空,AI 也能从笔记里把思路捡回来。

压缩与摘要的精细管理

Menlo 把缩减操作拆成两类,界限划得很死。压缩是可逆、无损的外部化:用轻量指针替掉原始信息,比如拿文件路径代替文件内容、拿 URL 代替网页 HTML。摘要则是有损、不可逆的,只有压缩实在省不下多少时才当最后手段。

有个铁律叫"先卸载再摘要":做摘要之前,先把完整上下文写进日志文件,给这个不可逆操作买份保险。

具体怎么执行?先定一个浅腐烂阈值,大概 128K 到 200K Token,触到这个数就优先压缩,等压缩收益变小了再上摘要。只压旧的 50%,最新的完整工具调用留着当 Few-shot 示例。原因很实在:模型是个强力模仿者,你给它看的要是全是残缺格式,它就以为那是对的。摘要必须基于完整版本,最后几个完整的"行动-观察"对要留着,当作让任务不断线的锚点。

串行接力:Anthropic 的方案

单 Agent 决策是统一的,可上下文窗口就那么大。要求从"写个函数"涨到"开发复杂 Web 应用"时,成千上万行代码分分钟撑爆窗口。多 Agent 并行容易互相打架,单 Agent 串行又不够用。

Anthropic 的解法有点巧:还是一个 Agent,但分两个阶段跑。

第一个是初始化 Agent,只活在项目第一天。它不写业务代码,只搭架子:配服务器环境、建进度打卡表、初始化 Git 仓库,让后面的工作有据可查,把那些藏在脑子里的隐性知识变成白纸黑字的文档。

第二个是编码 Agent,真正干活的那个,在之后成百上千次会话里执行,但被套了严格约束,走增量循环:每次"醒来"领一个任务,写完测试,然后提交。

整章绕不开的一个概念叫 Clean State(干净状态):不管你这一班干了多少,交接前必须保证代码能跑通、文档已更新,达到能合进主分支的标准。烂摊子不能留给下一班,编译报错的代码更不行。

串行接力:一个 Agent,两个阶段

[阶段一] 初始化 Agent(仅项目第一天)
  初始化仓库 → 创建进度表 + 环境脚本 → 输出初始化文档

[阶段二] 编码 Agent(成百上千次会话,loop)
  读取功能清单 → 领取 passes=false 的任务 → 实现功能 + 写测试
  → 提交代码 → 更新功能清单 → Clean State 合并

外部依赖:文件 / 日志、Git 仓库

图解:Clean State 是跨会话接力的生命线。任何一班 Agent 都不能把烂摊子留给下一班。

外部记忆系统

内部记忆靠不住,那就把记忆挪到模型脑子外面,靠文件和日志去了解项目,而不是靠上下文窗口。

问题

解决方案

失忆

持久化日志和 Git 历史

信息不足导致瞎猜

结构化功能清单(JSON 格式)

贪多嚼不烂

一次只做一个功能,清单驱动

盲目自信

默认失败原则,做完测试才允许改成 true

烂尾文件污染

Clean State + Git 回滚

启动序列

对 Agent 来说,每一次会话都像重新开始,得赶紧把项目理解捡回来。标准动作就六步:定位(pwd 确认目录)、回忆(读进度记录和 Git 历史)、领任务(读功能清单找没过的条目)、复原(init.sh 启动环境)、验证(确认基础功能正常)、开工。

功能清单用 JSON 而不是 Markdown,图的就是结构硬:Agent 改起来不容易把格式搞坏。Prompt 里也锁死,只允许它改 passes 字段,测试描述一个字不能动。

端到端测试走 Puppeteer:Agent 拉起开发环境,模拟用户操作,靠截图验证前端界面。光看后端数据库多了一条记录就宣布成功是不够的,得亲眼确认侧边栏变了、输入框清空了这些细节。


评论