【magic context介绍帖】为什么说magic context是值得研究的上下文工程和记忆实践
上下文工程(context engineering)一直是 coding agent 的重要组成部分,也是其中的重要问题。要想理解 magic context,或者解释为什么 magic context 是值得研究的上下文工程和记忆实践,必须先理解上下文工程所面对的究竟是什么问题。
Context engineering 问题可以被分解为两个限制:
- 输入容量限制
- 缓存限制
对于 1,输入容量限制,某种意义上可以把它理解为 context rot 造成的有效容量限制。
也即,即使模型声明支持很大的上下文窗口,输入不断增长之后,模型对其中信息的处理能力也可能下降。为了让模型能够有效理解和处理当前任务,输入不能无限制地累积所有历史信息,而必须被控制在一个可用范围内。
因此,模型每次请求能够接收、并且能够有效利用的输入实际上是有上限的。而一个持续工作的 Agent 会不断产生信息,这就意味着,Context Engineering 必须不断对输入进行某种更新,否则输入最终会超过模型能够有效处理的范围。
对于 2,缓存限制,实际是一种软限制。
对于使用前缀缓存的模型提供商,缓存复用依赖输入前缀保持一致。前缀中的内容如果发生变化,后面的缓存通常也无法继续复用,这会造成成本的成倍上升。
因此,缓存限制并不是说输入不能变化,而是它的变化应该尽可能保证缓存复用。
在 1 的要求下,输入容量必然要求输入进行某种更新,而在 2 的要求下,这种更新应该尽可能不造成 cache miss。
这两个限制放在一起,就已经在一定程度上暗示了上下文应当采取怎样的布局:
输入的前半部分,应该尽可能是稳定、不经常变化的内容;输入的后半部分,则可以放入近期产生或者经常变化的内容。
但是随着工作的继续,后半部分也会不断增长。它虽然不会立即破坏前面的缓存,却最终仍然会遇到输入容量限制。于是系统又会重新面临问题 1。
这就意味着一个循环应该存在,也就是
初始->m[0] (稳定基线 baseline) + m[1] (变化增量 delta)
普通更新->m[0] + 新m[1]
基线重建->新m[0] + 空m[1]到这里,m[0]-m[1] 解决的还只是当前 session 中,上下文如何在输入容量限制和缓存限制之间持续运行的问题。
但是,coding agent 在工作过程中产生的信息并不都只对当前 session 有效,为了增强后续 session,让他们不要从 0 开始,我们需要
从当前工作中提取具有长期价值的信息并将其转换为更稳定、更适合复用的表示。
很多 workflow 都提出过对应的解法。
比如,GenericAgent 是将已经验证过的执行路径提炼为 skill,供之后的相似任务直接复用;Trellis 则偏向积累规范、任务状态和团队共享的工作知识。
magic context 有类似的机制,不过它的切入点从 agent 自己为自己整理经验,变成了由 context engine 负责整理。
这个设计很符合直觉:
- agent 自己本身就可能存在 compact 后遗忘等问题,由 context engine 派发的某个专门的 subagent(magic context 中叫 historian)来整理上下文很顺理成章。
- 整理 context 过程和提取记忆过程在本质上是类似的,因此整理历史的过程中提取候选记忆很合理。
因此当 context 到达限制的时候,historian 就会出来整理一下 context,顺便提出一些 facts 作为 project memory 的候选。
然后再将 facts 进行后续的去重合并等操作(dreamer 机制),将 facts 提升为 memory。
到这里你可能会发现一种架构上的类似性:
m[0] + m[1] -> 新 m[0] memory + facts-> 新 memory
这种相似性让 magic context 的 memory 部分也保持了 m[0]-m[1] 统一机制,于是我们之前的
初始->m[0] (稳定基线 baseline) + m[1] (变化增量 delta)
普通更新->m[0] + 新m[1]
基线重建->新m[0] + 空m[1]又可以描述 memory 过程,只不过基线重建现在变成了 dream 机制。