Context Engineering:为什么 Agent 会越聊越笨
Context Engineering:为什么 Agent 会越聊越笨
wwxdsg用 Agent 做短任务时,它常常让人产生一种错觉:只要把聊天记录留得足够长,它就会越来越了解项目。
真正做过几轮迭代后,体验通常恰好相反。
它会带着已经被推翻的架构继续推理;明明上一轮刚确认的风险边界,几轮之后又被忽略;工具调用和日志越堆越多,最后连当前到底在修什么都开始模糊。
这不是因为 Agent “失忆”了,而是因为我们把上下文当成了一个越大越好的仓库。
我更愿意把 Context Engineering 理解为:在每一次推理前,主动决定什么信息值得占用 Agent 此刻有限的注意力。
它不是给模型塞更多资料,而是不断做选择、压缩、更新、淘汰和恢复。
一、聊天记录不是项目状态
下面是一种很危险、也很常见的工作方式:
历史聊天记录 |
看起来信息很完整,实际却把三种性质不同的东西混在了一起:
- 已确认的事实;
- 仍待验证的假设;
- 已经失效的历史过程。
Agent 在这里的难题不是“缺少知识”,而是“在噪声和冲突里找不到此刻最重要的事实”。
因此,长任务不能只依赖聊天记录。聊天记录适合回看过程;项目状态应该被压缩成一个能被下一次会话直接接手的持久化产物。
一个合格的状态文件,至少要让新 Agent 很快回答五个问题:
- 最终目标是什么?
- 当前完成到哪里?
- 哪些决定已经有证据,不应轻易推翻?
- 哪些验证已经通过或失败?
- 下一步最小、最合理的动作是什么?
如果这五个问题只能靠翻几千行聊天记录回答,项目就还没有真正拥有可恢复状态。
二、上下文不是一个整体,而是五层信息
为了避免“所有东西都叫上下文”,我会先把它们拆成五层。
| 层级 | 它解决的问题 | 典型内容 | 管理方式 |
|---|---|---|---|
| 稳定规则 | 默认怎样工作 | 安全边界、代码约定、审批规则 | 短、稳定、长期保留 |
| 当前任务状态 | 这次到底在做什么 | 目标、进度、假设、下一步 | 高频更新,始终保持最新 |
| 检索知识 | 现场需要了解什么 | 相关代码、文档、ADR、历史 issue | 按需加载,不全量灌入 |
| 工具上下文 | 现在能做什么 | 少量候选工具、参数、返回结构 | 只暴露相关工具 |
| 执行反馈 | 下一步该怎样调整 | 测试、日志、trace、失败结果 | 优先保留能改变决策的证据 |
这张表不是为了增加目录,而是为了让信息有不同的生命周期。
例如,“生产环境发布必须先确认”是稳定规则;“当前正在排查评论接口 429”是任务状态;一份过期的 Nginx 日志可能只是执行反馈,确认根因后不该永久留在主要上下文中。
当它们被当成同一类信息时,旧结论就会和新决定争夺注意力。
三、三个最实用的 Context Engineering 动作
1. 先写状态,再开始下一轮工作
长任务不怕中断,怕的是中断后只能重新猜。
对跨会话、跨天或可能交给另一个 Agent 的任务,我建议维护一个很短的 progress.md。它不是工作日报,更不是把思考过程全部复制进去。
# Objective |
这个例子没有记录每一次命令,也没有把完整配置贴进去。它只保留了下一轮决策真正需要的事实、证据和未决项。
2. 让文档按需展开,而不是让根规则无限长
AGENTS.md、README 或项目级说明很容易越写越大。最后它看似什么都有,实际上没有人能快速分辨哪条和当前任务有关。
更稳的结构是渐进式披露:
AGENTS.md |
根入口只负责让 Agent 不走错门:项目目标、标准命令、禁止事项和文档地图。细节应该放到需要它的目录或 Skill 中。
这和人进入陌生项目的过程很像。没有人会在写一个表单时先读完整部署史;Agent 也不应该被迫这么做。
3. 主动标记过期信息,而不是默默追加新结论
项目在演进时,最容易伤害 Agent 判断的不是“没有文档”,而是同时存在两份看起来都合理、但已经互相矛盾的文档。
因此每当架构、部署或流程发生变化,除了写下新事实,还应该注明旧事实已经失效。
## Recently superseded |
这段信息的价值很高:它不只告诉 Agent 现在是什么,还告诉它不要再沿用哪个旧模型。
四、一个完整例子:同一件事,为什么第二次会做得更好
假设你让 Agent “把博客的技术文章发布流程整理一下”。
第一次,它看了几份文档,写出了一套流程。但它没有区分草稿和发布,没有记录敏感信息边界,也不知道构建成功后是否还需要人工确认。
如果你只是继续在聊天里纠正它,下一次换会话,这些教训又会消失。
更好的做法是把被验证的结论归位:
| 发现 | 应放的位置 | 原因 |
|---|---|---|
| 文章源码目录 | 项目记忆 / AGENTS.md |
是稳定入口事实 |
| 草稿不允许直接发布 | 协作规则 | 会影响默认行为 |
| 发布前必须通过敏感信息扫描 | 发布 Skill / 脚本 | 可被机器验证 |
| 本次文章缺少封面 | 当前任务状态 | 只影响当前工作单元 |
| 某次构建报错的完整日志 | 任务记录 | 只有定位时才需要 |
下次 Agent 接手时,它不必“记住上一次聊天”。它只要读取对应的稳定规则、当前状态和发布 Skill,就能在较小的上下文里做出更好的决定。
这也是为什么我不把“记忆更多”视为目标。真正有用的是:信息该留下时能留下,该退出时也能退出。
五、常见反模式
反模式一:把所有聊天历史都保留给下一轮
历史中可能有正确的过程,也可能有过期假设、错误尝试和临时情绪。保留全部,并不等于恢复得更准确。
替代做法:每个工作单元结束时写一段状态摘要,并把验证结果和决策放到可追溯的位置。
反模式二:用很长的系统提示代替项目文档
系统提示适合稳定、少量、跨任务的规则;它不适合承载频繁变化的部署事实、当前进度和完整历史。
替代做法:稳定原则放在根规则;变化事实放在项目记忆或状态文件;具体流程放入按需加载的 Skill。
反模式三:摘要只写“做了什么”
“已修改三个文件,完成限流”无法让下一位协作者判断是否应该继续、回滚还是验证。
替代做法:每条状态都尽量附带“为什么这样做、证据是什么、下一步是什么”。
六、可以直接复制的状态恢复模板
如果你正在做任何会跨越多轮的任务,可以从下面的最小版本开始:
# Objective |
写完后做一次五分钟检查:一个完全不了解任务的人,能否只读这份文件就知道下一步要做什么、为什么还不能宣布完成?如果不能,它就还只是记录,而不是恢复点。
七、从今天开始的推荐做法
- 给每个超过半小时、可能中断的 Agent 任务创建一个状态文件。
- 把根规则控制在“入口、边界、命令、文档地图”四类内容内。
- 每次项目形态发生变化时,写新事实,也标记被淘汰的旧结论。
- 不要用“聊天记录很长”作为长期协作可靠的证据。
下一篇会继续讨论一个自然的问题:当某种工作已经反复发生时,我们不该每次都临时拼 Prompt。它应该被做成一个可复用、可验证、能持续迭代的 Skill。
AI 实现摘要
- 要解决的问题:减少长会话和长期任务中的上下文噪声、过期结论与交接丢失,使 Agent 能从持久化状态恢复工作。
- 适用版本与前置条件:适用于支持读取项目文档的 AI Agent;建议项目具备版本控制与可执行验证命令。
- 输入、输出与验收标准:输入是跨轮或跨会话任务;输出为项目根规则、按需文档与
progress.md等状态产物。新会话应能据此回答目标、进度、决策、验证和下一步。 - 文件改动清单:可新增
docs/agent/progress.md、docs/agent/project-memory.md,并在根AGENTS.md增加文档地图;按项目实际路径调整。 - 完整命令:无通用命令。使用项目已有的测试、构建和日志查询命令记录验证证据。
- 测试步骤与预期结果:中断一个真实任务后,在新会话只提供状态文件和必要规则;预期 Agent 不重复已完成工作,并能提出与“Next action”一致的后续动作。
- 常见错误、回滚方法与安全边界:状态文件不应写入密钥、个人数据或完整敏感日志。未经验证的猜测必须标注为假设,不要提升为长期事实或全局规则。