Agent 设计模式 | Lance
作者:Lance Martin | 日期:2026年1月9日
2025 年以 Meta 以超过 20 亿美元收购 Manus,以及 Claude Code 达到 10 亿美元年化收入规模而告终。在这里,我将基于我最喜欢的一些博客、论文和文章,探讨这些以及其他流行 agent 中的一些常见设计模式。
我们正在逐渐接近能够长期运行的自治 agent。@METR_Evals 报告称,agent 的任务长度每 7 个月就会翻一倍。但其中一个挑战在于:随着上下文变长,模型的表现会变差。@trychroma 报告了“上下文腐烂”,@dbreunig 概述了各种失败模式,而 Anthropic 在这里对此进行了说明:
上下文必须被视为一种具有递减边际收益的有限资源。就像人类有限的工作记忆一样,LLM 也有一个“注意力预算”。每增加一个 token,都会消耗这部分预算。
基于这一点,@karpathy 阐述了上下文工程的必要性:
上下文工程是一门精细的艺术与科学,其目标是在上下文窗口中填入恰到好处的信息,以支撑下一步行动。
高效的 agent 设计在很大程度上可以归结为上下文管理。下面我们来探索一些来自我最喜欢的博客、论文和文章中的常见思想。
赋予 Agent 一台计算机
@barry_zyj 和 @ErikSchluntz 将 agent 定义为由 LLM 自主引导其行动的系统。在过去一年中已经变得非常清晰的一点是:agent 会从对一台计算机的访问中显著受益,这为它们提供了诸如文件系统和 shell 这样的原语。
文件系统为 agent 提供了持久化上下文。shell 允许 agent 运行内置工具、CLI、提供的脚本,或者它们自己编写的代码。
我们已经在许多流行的 agent 中看到了这一点。Claude Code 作为一个“生活在你的电脑上”的 agent 脱颖而出。Manus 使用的是一台虚拟计算机。而这两者在根本上都使用工具来控制计算机,正如 @rauchg 所总结的那样:
编码 agent 的基本抽象是 CLI……这源于 agent 需要访问操作系统层这一事实。将 Claude Code 理解为“面向操作系统的 AI”会更加准确。
多层级动作空间
Agent 通过调用工具来执行动作。为 agent 提供工具变得越来越容易(例如通过 model context protocol)。但是,这也会带来问题:
随着 MCP 使用规模的扩大,工具定义会挤占上下文窗口,而中间工具结果还会消耗额外的 token。
工具定义通常会被直接加载进上下文。以 GitHub MCP 服务器为例,它拥有 35 个工具,其工具定义大约有 2.6 万个 token。如果工具数量更多,且功能存在重叠,还可能会让模型产生困惑。
许多通用型 agent 实际上只使用了数量出人意料地少的工具。@bcherny 提到,Claude Code 使用的大约只有十几个工具。@peakji 表示 Manus 使用的工具少于 20 个。Amp Code 的 @beyang 也谈到,他们是如何精心裁剪动作空间,只保留少数几个工具的。
那么,agent 如何在限制工具数量的同时仍然执行广泛的动作呢?答案是将动作从工具调用层下推到计算机层。@peakji 将 Manus 的动作空间解释为一种层级结构:agent 使用少量原子工具(例如 bash 工具)来在虚拟计算机上执行操作。bash 工具可以调用 shell 工具、CLI,或者直接编写并执行代码来完成任务。
CodeAct 论文展示了 agent 可以通过编写并执行代码来串联大量动作。Anthropic 在这里对此进行了说明,并强调了 token 节省方面的优势,因为 agent 不需要处理每一步的中间工具结果。@trq212 展示了一些使用 Claude 的实际示例。
渐进式披露
Agent 需要知道有哪些动作是可用的。一种做法是将动作放在工具调用层,并在一开始就将工具定义加载进上下文。
但我们已经看到了一种趋势:为了更好地进行上下文管理,开始采用渐进式披露。这是一种设计模式,即只在一开始展示最核心的信息,而在需要时才逐步揭示更多细节。
在工具调用层,一些 agent 会对工具定义进行索引,并按需检索工具,甚至可能使用搜索工具来封装这一过程。
对于 shell 工具或已安装的 CLI,@peakji 表示 Manus 只是在 agent 指令中提供一份可用工具列表。然后,agent 会在需要时通过 bash 工具调用 --help(或类似方式)来了解某个工具的具体用法。
MCP 服务器也可以从工具调用层下推到计算机层,从而实现渐进式披露。Cursor Agent 会将 MCP 工具描述同步到一个文件夹中,向 agent 提供一个简短的工具列表,并允许 agent 仅在任务需要时才读取完整描述。Anthropic 和 Cloudflare 都讨论了类似的 MCP 管理思路。
Anthropic 的 skills 标准也使用了渐进式披露。@barry_zyj 和 @MaheshMurag 在一次演讲中对此进行了说明:skills 是包含 SKILL.md 文件的文件夹。每个文件的 YAML frontmatter 会被加载进 agent 指令中,使 agent 能够自行决定是否需要读取完整的 SKILL.md 内容。
卸载上下文
通过计算机,另一件可以做的事情是将上下文从 agent 的上下文窗口卸载到文件系统中。Manus 会将旧的工具结果写入文件,只有在卸载带来的收益开始递减时才进行总结。
Cursor Agent 也会将工具结果和 agent 轨迹卸载到文件系统中,使 agent 在需要时可以再将其读回上下文。
这两种做法都有助于应对一种合理的担忧:上下文压缩(也就是总结)可能会导致有用信息的丢失。
将上下文卸载到文件系统中还可以用于引导长期运行的 agent。一些 agent 会将计划写入文件,并周期性地读回上下文,以强化目标,或者验证其工作结果。
缓存上下文
Agent 通常将上下文管理为一系列消息列表。每次行动产生的上下文都会被追加到这个列表中。@irl_danB 曾提出一个有趣的观点:
Agent 使用线性的聊天历史。而软件工程师的心理模型更像是一个调用栈:任务被压入,完成后再弹出。
考虑通过移除或添加上下文块来改变会话历史是很有意思的。但在设计上下文变更方式时,有一个重要的现实因素:如果没有 prompt caching,agent 的成本可能会高到无法接受,而 prompt caching 允许 agent 从某个提示前缀处恢复执行。
Manus 将“缓存命中率”称为生产级 agent 最重要的指标,并指出:使用支持缓存的高容量(高单 token 成本)模型,可能反而比不支持缓存的低价模型更便宜。@trq212 也指出,如果没有缓存,像 Claude Code 这样的编码 agent 在成本上是不可行的。
隔离上下文
许多 agent 会将任务委派给拥有隔离上下文窗口、工具或指令的子 agent。一个明确的使用场景是可并行化的任务。@bcherny 提到,Claude Code 团队在代码审查中使用子 agent,分别独立检查不同类型的问题。类似的 map-reduce 模式也可用于更新 lint 规则或数据库迁移等任务。
长期运行的 agent 也会使用上下文隔离。@GeoffreyHuntley 提出了“Ralph Wiggum”这一概念,即一个反复运行 agent,直到计划被满足的循环。对于长期任务而言,往往不可能将全部内容放入单个 agent 的上下文窗口中。上下文存储在文件中,而 agent 之间可以通过 git 历史来传递进度。
Anthropic 描述了一种 Ralph 循环的实现方式:由一个初始化 agent 来建立环境(例如计划文件、追踪文件),然后由子 agent 从计划文件中分别处理各个任务。@bcherny 也提到,Claude Code 使用 stop hooks 在每一轮 Ralph 循环之后验证工作结果。
演化上下文
围绕 agent 的持续学习已经引起了大量关注。我们希望 agent 能像人类一样从经验中学习并不断改进。一些研究表明,agent 在实际部署中失败的原因之一在于其无法适应或学习。
@Letta_AI 讨论了“token 空间中的持续学习”,即通过更新 agent 的上下文,而不是模型权重,来实现学习。各种方法的共同点在于:回顾过去的 agent 轨迹或会话,并据此更新上下文。
这种模式可以应用于任务特定的提示。GEPA 的做法是:收集 agent 轨迹,对其进行评分,反思失败原因,并提出多种任务特定的提示变体用于后续测试。
这一模式也可以应用于开放式记忆学习。我曾在 Claude Code 上测试过类似的想法:将会话蒸馏为日记条目,在多个日记之间进行反思,并用其更新 CLAUDE.md。
这同样可以应用于 skills。@Letta_AI 给出了一个示例:通过反思轨迹来提炼可复用的流程,并将其作为新技能保存到文件系统中。
未来方向
一些模式已经逐渐清晰:赋予 agent 一台计算机,并将动作从工具调用层下推到计算机层;使用文件系统来卸载上下文并实现渐进式披露;使用子 agent 来隔离上下文;随着时间推移演化上下文以学习记忆或技能;通过缓存来节省成本和延迟。
未来一年中,还有许多开放性挑战值得关注。
学习型上下文管理
上下文管理可以包括手工设计的压缩提示、子 agent 的生成、上下文卸载时机与内容的选择,以及如何随着时间演化上下文以实现学习。苦涩的教训表明,计算能力或模型规模往往会超越这些手工方法。
递归语言模型的研究表明,LLM 可能学会自行进行上下文管理。agent 框架中大量的提示或支架,可能最终会被模型本身吸收。
这在记忆方面尤为有趣。这与“睡眠时计算”的工作有一定关联,该研究表明 agent 可以在离线状态下思考自身上下文。可以想象,agent 自动反思过去会话,并据此更新自身记忆或技能;或者直接反思自身长期积累的记忆,以便更好地整合并为未来任务做准备,就像人类一样。
多 Agent 协同
随着 agent 承担更大规模的任务,我们很可能会看到大量 agent 并发协作。当前的 agent 在共享上下文方面仍然存在困难:每个动作都隐含决策,而并行 agent 在缺乏彼此工作可见性的情况下,容易做出相互冲突的决策。
像 Gas Town 这样的多 agent 项目非常有趣:它使用一个多 agent 协调器,通过 git 进行工作追踪,设置一个对整个工作区具有完整上下文的“市长”agent,并通过合并队列和角色分工来协调数十个并发的 Claude Code 实例。
长期运行 Agent 的抽象
长期运行的 agent 需要新的基础设施:对 agent 行为的可观测性、人工审查的钩子,以及在出现问题时的优雅降级。当前的模式仍然较为粗糙。Claude Code 使用 stop hooks 在每次迭代后验证工作,Ralph 循环通过 git 历史追踪进度。但目前还没有针对 agent 可观测性、通用调试接口或人类参与监控的标准模式。随着 agent 运行时间变长,我们可能需要新的抽象来管理它们。
https://rlancemartin.github.io/2026/01/09/agent_design/
如果觉得内容不错,欢迎你点一下「在看」,或是将文章分享给其他有需要的人^^
相关好文推荐:
递归语言模型(Recursive Language Models) | Alex Zhang
重新构想 LLM 记忆:将上下文作为训练数据,使模型能够在测试时学习 | Nvidia
引入嵌套学习(Nested Learning):一种用于持续学习的全新机器学习范式
理解 LSTM 网络 | Ilya Sutskever’s Top 30 Reading List
循环神经网络不合理的有效性 | Ilya Sutskever’s Top 30 Reading List
复杂动力学第一定律 | Ilya Sutskever’s Top 30 Reading List
赋权于民:大语言模型如何逆转技术扩散的范式 | karpathy
“通用智能根本不存在”?Yann LeCun 与 Demis Hassabis 正面开撕

0条留言