Agent 设计模式
上下文的三板斧
当任务跨越多个上下文窗口,每个新窗口都会失忆。生产环境中已验证三种策略来应对这个根本挑战,让 Agent 能在长任务中保持连贯和高效。
根本挑战
长任务的失忆问题
一个复杂的编程任务可能需要 Agent 执行数十步操作,产生数万 Token 的对话历史。当上下文窗口快满时,系统面临两难选择:
Option A:开启新窗口,但新窗口什么都不记得,Agent 会重复已做过的工作。
Option B:继续在旧窗口工作,但随着 Token 增多,模型的注意力被稀释,表现下降。
这不是理论问题。Claude Code、Cursor、Devin 这些产品每天都在解决这个问题。
Option A:开启新窗口,但新窗口什么都不记得,Agent 会重复已做过的工作。
Option B:继续在旧窗口工作,但随着 Token 增多,模型的注意力被稀释,表现下降。
这不是理论问题。Claude Code、Cursor、Devin 这些产品每天都在解决这个问题。
策略一
1
Compaction
上下文压缩
当对话快要触达上下文窗口上限时,用一次 LLM 调用对已有对话做摘要:保留关键信息,丢弃冗余细节,然后在压缩后的上下文上继续工作。
- 关键决策:选择什么保留、什么丢弃。这是一个信息论问题:并非所有 Token 都等价,有些信息丢了就无法恢复。
- 低风险操作:清理旧的 tool call 结果(比如文件列表、搜索输出),这些通常不影响后续推理。
- 高风险操作:丢弃架构决策的推理过程、未解决的 bug 描述,这些如果丢了,Agent 会重蹈覆辙。
- Claude Code 的实践:保留架构决策和未解决的 bug 信息,丢弃冗余的文件内容输出和已完成任务的中间步骤。
实践 Tip
压缩时让 LLM 生成的摘要应该是结构化的,自由文本很难快速定位信息。例如:「已完成:[列表] | 未完成:[列表] | 关键决策:[列表] | 已知问题:[列表]」,这样后续推理可以快速找到需要的信息。
策略二
2
Structured Note-taking
结构化笔记
Agent 在执行过程中主动将关键信息写到外部文件,而不仅仅依赖对话历史。当上下文重置(新窗口)后,从笔记文件读回这些信息来恢复记忆。
- 核心思想:把短期记忆(上下文窗口)外化为长期记忆(文件系统),实现跨窗口的信息延续。
- Claude Code 的实践:维护 TODO list 文件,每完成一步就更新,这样即使上下文被压缩或重置,打开 TODO 就知道进度。
- Claude 打宝可梦的案例:Agent 维护一个游戏笔记文件,记录地图位置、已获道具、下一步计划。每次新对话开始时先读这个笔记,实现记忆传递。
- 关键设计:笔记格式要固定且结构化,不能是自由散文,否则读回来时还要额外 Token 来理解笔记内容。
对比 Compaction
Compaction 是压缩旧信息继续用,Note-taking 是把信息存到外面以后取用。前者适合连续工作场景,后者适合可能被中断或需要跨 session 延续的场景。两者可以组合使用。
策略三
3
Sub-agent Architecture
子 Agent 架构
主 Agent 把需要深入探索的子任务委派给子 Agent。子 Agent 在自己独立的上下文窗口中工作(可能消耗数万 Token),最终只返回一个精炼的摘要(1000-2000 Token)给主 Agent。
- 核心价值:关注点分离 + 上下文隔离。子 Agent 的工作草稿不会污染主 Agent 的上下文。
- Token 经济:一个子 Agent 可能在内部消耗 30,000 Token 来读代码、分析依赖、做推理,但只向上报告 1,500 Token 的结论。主 Agent 的上下文保持精简。
- 并行优势:多个子 Agent 可以同时工作,各自探索不同方向,最后由主 Agent 整合。这比单一 Agent 串行探索快得多。
- 真实应用:Cursor 的 background agent、Claude Code 的 Task tool,都是子 Agent 架构的体现。
类比
想象一个 CEO(主 Agent)让 3 个部门经理(子 Agent)分别调研竞品、分析市场、评估技术。每个经理可能花了一周(大量 Token),但汇报给 CEO 的只是一页 PPT(精炼摘要)。CEO 的认知带宽始终保持在战略层面。
JIT Context vs 预加载
预加载(Preloading)
在对话开始时就把信息塞进上下文
- CLAUDE.md / Rules 文件直接载入
- 用户偏好、项目配置
- 高频使用的上下文信息
- 优点:即时可用,无需额外调用
- 缺点:每次都占 Token,不管用不用得到
JIT(Just-In-Time 按需获取)
只在需要时才检索信息到上下文
- 用 glob/grep 按需搜索文件
- 用 RAG 检索相关文档
- 调用 API 获取实时数据
- 优点:上下文保持精简,只含当前需要的
- 缺点:多一次工具调用的延迟
最佳实践:混合策略
高频信息预加载(项目约定、核心规则、用户偏好)+ 长尾信息按需获取(具体文件内容、API 文档、历史记录)。
类比浏览器缓存策略:热数据放内存缓存(预加载),冷数据放磁盘或网络获取(JIT)。目标是让上下文的命中率最大化:大多数推理所需的信息已经在窗口里,偶尔需要的才动态获取。
类比浏览器缓存策略:热数据放内存缓存(预加载),冷数据放磁盘或网络获取(JIT)。目标是让上下文的命中率最大化:大多数推理所需的信息已经在窗口里,偶尔需要的才动态获取。
三种策略对比
| 策略 | 核心思想 | 适用场景 | 代表产品 |
|---|---|---|---|
| Compaction | 压缩旧上下文,保留关键信息继续 | 连续长对话,不会被中断 | Claude Code auto-compact |
| Note-taking | 主动写笔记到外部,跨窗口读回 | 可能中断、需跨 session 延续 | Claude Code TODO、Cursor Rules |
| Sub-agent | 子 Agent 深入探索,只回传摘要 | 需要深度探索但不想污染主上下文 | Cursor Task、Claude Code spawn |
长任务的本质挑战是有限的注意力窗口 vs 无限增长的信息量。压缩、笔记、子 Agent 三板斧,分别解决三个问题:在窗口内保持精简、跨窗口传递记忆、隔离深度探索的噪声。三者组合使用,才能让 Agent 在复杂长任务中保持高效。