上下文工程原则
我们要讨论的原则有:
- 共享上下文
- 行动自带隐含决策
为何思考这些原则?
HTML 在 1993 年问世。2013 年,Facebook 向世界发布了 React。现在是 2025 年,React(及其后代)主宰了开发者构建网站和应用的方式。为什么?因为 React 不只是代码脚手架,它是一种哲学。使用 React,你接受以响应式与模块化模式来搭建应用——如今大家视为标准,但当年对早期 web 开发者并非显而易见。
在 LLM 和 AI 代理时代,我们还像在摆弄原生 HTML 与 CSS,琢磨如何拼成好的体验。除了最基础的东西,尚无单一代理构建方式成为标准。
有些库(例如 OpenAI 的 github.com/openai/swar… 和微软的 github.com/microsoft/a…)在我看来反而在推动错误的代理构建方式——多代理架构,下面我会解释原因。
如果你刚接触代理构建,有不少资源教你搭建基础脚手架 [1] [2]。但要构建严肃的生产级应用,故事就不同了。
长时运行代理的构建理论
先聊可靠性。让代理长时间运行并保持连贯对话时,必须采取某些措施以控制错误的连锁放大。否则不注意,很快就崩。可靠性的核心是上下文工程。
上下文工程
2025 年的模型已经非常聪明。但即便最聪明的人,没有被告知任务上下文也无法有效工作。“提示词工程”一词用于描述为 LLM 聊天机器人编写理想任务格式的努力。“上下文工程”是下一层,它要在动态系统中自动完成这件事,更微妙,也是 AI 代理工程师的头号工作。
举个常见代理类型的例子。这个代理:
- 把工作拆成多部分
- 启动子代理处理这些部分
- 最后合并结果
这种架构很诱人,尤其在有多个并行组件的任务领域。但它非常脆弱,关键的失效点是:
假设你的任务是“做个 Flappy Bird 克隆”。被拆成子任务 1“做一个带绿色管道和碰撞盒的移动背景”和子任务 2“做一只能上下移动的小鸟”。
结果子代理 1 弄错了子任务,做了一个看起来像超级马里奥的背景。子代理 2 做了只鸟,但不像游戏素材、动作也不似 Flappy Bird。最终代理只能去拼这两个误解的产物。
这似乎是编故事,但真实任务往往有多层细节,都可能被误传。你可能会想:简单解决方案是把原始任务上下文也复制给子代理,这样就不会误解子任务。但别忘了,生产系统里的对话多半是多轮的,代理可能需要一些工具调用来决定如何拆分任务,任何细节都有可能影响任务的理解。
原则 1
共享上下文,且要共享完整的代理轨迹,而不只是单条消息
再看一版代理,这次确保每个代理都有前面代理的上下文。
很遗憾,问题还没完。这次给代理相同的 Flappy Bird 任务,你可能得到风格完全不一致的鸟和背景。子代理 1 和子代理 2 看不到彼此的工作,结果彼此不一致。
子代理 1 和子代理 2 的行动基于彼此冲突、且事先未规定的假设。
原则 2
行动自带隐含决策,冲突的决策会带来糟糕结果
我认为原则 1 与 2 至关重要,几乎不值得违反;默认应否定任何不遵守它们的代理架构。你可能觉得这很约束,但事实上仍有很大空间可探索。
遵循这些原则最简单的方式,就是用单线程的线性代理:
这里上下文是连续的。但在超大任务、子任务过多时,可能会遇到上下文窗口溢出。
说实话,简单架构已经能应付很远,但如果你需要真正长时任务并愿意投入精力,可以做得更好。解决方法有很多,下面只介绍一种:
在这里,我们引入一个新 LLM,用来把行动与对话历史压缩成关键细节、事件与决策。这很难做对。需要投入时间找出哪些信息关键,并构建擅长这件事的系统。根据领域,你甚至可以考虑微调小模型(在 Cognition 我们确实这么做过)。
收益是让代理在更长上下文中仍有效。不过最终仍会有极限。对于好奇的读者,欢迎思考如何管理任意长的上下文,这是个挺深的兔子洞!
应用这些原则
如果你是代理构建者,要确保代理的每个行动都基于系统其他部分所有相关决策的上下文。理想情况下,每个行动都能看到所有其他行动。但受限于上下文窗口与实际取舍,未必总能做到,你需要决定为达成目标可靠性愿意承受多少复杂度。
当你思考如何架构代理以避免冲突决策时,下面一些真实案例值得参考:
Claude Code 子代理
截至 2025 年 6 月,Claude Code 会派生子任务。但它从不与子任务代理并行工作,子任务代理通常只负责回答问题,而不是写代码。为什么?子任务代理缺少主代理的上下文,无法做超出回答明确问题之外的事。如果同时运行多个并行子代理,它们可能给出相互冲突的回复,导致我们前面看到的可靠性问题。此处引入子代理的好处是:子代理的探索工作无需保留在主代理历史中,从而在耗尽上下文前拥有更长的轨迹。Claude Code 的设计者刻意采取了简单方法。
编辑-应用模型
2024 年,很多模型在编辑代码上表现很差。于是编码代理、IDE、应用构建器等(包括 Devin)常用“编辑-应用模型”。核心思想是:与其让大模型输出格式正确的 diff,不如让小模型根据一份 Markdown 形式的变更说明重写整份文件更可靠。所以,构建者让大模型输出 Markdown 代码修改说明,再把说明喂给小模型去真正改文件。但这些系统仍然容易出错,小模型常因说明的细微歧义误解大模型指令,做出错误修改。如今,编辑决策与应用往往在单个模型的一次行动中完成。
多代理
如果真想从系统中榨取并行性,你可能希望让决策者彼此“对话”并解决分歧。
这也是我们人类(理想情况下)会做的事。如果工程师 A 的代码与工程师 B 的合并冲突,正确流程是沟通差异并达成共识。但当下的代理还不能以比单代理更高的可靠性进行这种长上下文的主动对话。人类能高效地把最重要的知识传递给彼此,但这种效率需要不小的智能。
自 ChatGPT 发布不久,人们就开始探索让多个代理相互协作来完成目标 [3][4]。我对代理协作的长期可能性乐观,但显然在 2025 年,多代理协作只会带来脆弱系统。决策被过度分散,上下文也无法在代理间充分共享。目前我没看到有人专注解决跨代理上下文传递这个难题。我个人认为,随着单线程代理在与人类沟通上变得更好,这个问题会自然而然得到解决。那一天到来时,将解锁更大规模的并行与效率。
迈向更通用的理论
这些关于上下文工程的观察只是未来可能成为构建代理标准原则的起点。还有许多未提到的挑战与技巧。在 Cognition,我们把代理构建视为关键前沿;围绕这些反复实践得到的原则来构建内部工具与框架,以落实这些想法。当然我们的理论不一定完美,随着领域演进我们也期待变化,因此需要保持弹性与谦逊。