Agent上下文窗口即RAM:引入分页机制
将操作系统LRU分页思想应用于Agent上下文管理,15%缺页率下零信息丢失,告别硬截断。
将操作系统LRU分页思想应用于Agent上下文管理,15%缺页率下零信息丢失,告别硬截断。
把上下文窗口当作稀缺缓存来用:把工作集保留在内存里,把冷数据驱逐到存储层,等出现缺页中断时再调回来。局部性越好,缺页率越低,信息永不丢失。
TL;DR:长时间运行的 Agent 会不断往上下文窗口里堆工具返回结果和笔记,但注意力是一个固定预算——稀释它,准确率和成本都会下降。硬性限制窗口大小并丢弃最旧的内容,会丢失 Agent 后面需要的信息。操作系统用请求分页解决了这个问题:只把工作集保留在内存里,把冷数据驱逐到后备存储,需要时再调回来。Agent 会话有很强的局部性,所以缺页率可以保持很低,而且不会丢失任何信息。在一个可运行的 Go 演示中,"保留一切"会膨胀到窗口预算的 7.6 倍,而 LRU 分页的窗口可以保持在预算内,缺页率 15%,信息零丢失。
思维模型:你的笔记本运行的应用程序需要的内存远大于它实际拥有的 RAM,但你从未察觉,因为操作系统把正在使用的页面保留在 RAM 里,其余的安静地停放在磁盘上——一旦你触碰它们就立即取回来。Agent 的上下文窗口就是那块 RAM。
上下文窗口不是内存——它是一个缓存,而且是一个很小的缓存。Agent 做的一切都会往里面添加内容:工具返回 30k tokens、文档被粘贴进来、每一步都留下笔记。它填满时会发生两件坏事。首先是注意力税:Transformer 的注意力是一个固定预算,已发表的测量数据显示,随着这个预算被分散到更多 tokens 上,准确率从约 95% 下滑到 60–70%。其次是成本和延迟随窗口内的 tokens 数量增长,每一步都是如此。
naive 的修复方案——限制窗口大小并丢弃最旧的内容——是用一个失败换取另一个失败。一旦后面的步骤引用了你丢弃的东西,它就没了:Agent 会静默地重新计算它(再次支付工具调用费用),或者更糟——产生幻觉。
操作系统从 1960 年代起就在运行地址空间远大于物理 RAM 的程序,使用的是请求分页和 Denning 的工作集模型。它到 Agent 的映射是直接的:
只把工作集保留在内存里。当窗口满了、新内容进来时,把最近最少使用的项驱逐到存储层(不是丢弃到虚空里)。当后面的步骤引用了一个已被驱逐的项时,这就是一次缺页中断——把它调回内存。没有任何东西被销毁,只是被移到了一个成本更低的层级。
驱逐以腾出空间和缺页中断时调回的逻辑就是整个模式的核心:
for _, item := range stream {
if el, resident := pos[item]; resident {
lru.MoveToFront(el) // hit: already in the window
continue
}
faults++ // miss: page it back in from the store
evictToFit(item) // make room by evicting LRU residents (to the store)
tokens += size[item]
pos[item] = lru.PushFront(item)
}
func evictToFit(incoming int) {
for tokens+size[incoming] > budgetTokens && lru.Len() > 0 {
victim := lru.Back().Value.(int)
lru.Remove(lru.Back())
delete(pos, victim)
tokens -= size[victim] // evicted to the backing store, not destroyed
}
}
Context Demand Paging — the context window is a cache, not infinite memory
1500-step session, 60 distinct items, 8000-token window budget.
keep everything resident 60,728 tokens (7.6× the window — attention tax + cost blowup)
demand paging (LRU) 7,997 tokens (stays within budget)
page faults 226 (15% of references — the rest hit the working set)
information lost 0 (faults page back in from the store — nothing destroyed)
把所有内容保留在内存里会达到窗口预算的 7.6 倍——这正是这个预算本来要防止的注意力税。请求分页把窗口维持在预算范围内,而且因为 Agent 持续访问同一个工作集,只有 15% 的引用会未命中——每次都是一次廉价的从存储层重新读取,绝不会丢失信息。
现实检验:7.6 倍和 15% 缺页率来自上面的局部性模型——是方向性数据,不是基准测试,你的缺页率完全取决于你工作负载的局部性。独立成立的是它所针对的注意力税(已发表的论文显示,随着窗口填满,长上下文准确率从约 95% 下滑到 60–70%),以及发展的方向:2026 年的 Neural Paging 将这个问题形式化,并学习驱逐策略,而不是使用这里展示的朴素 LRU。
随着 Agent 从单一回答转向长时域工作——数小时的编码、多文档研究、跨越多次上下文重置的会话——上下文管理不再是一个事后想法,而成为系统问题。这个领域正在快速收敛到操作系统类比:2026 年的 Neural Paging 将"上下文分页问题"形式化,并提出了一个作为神经 MMU 的可学习页面控制器,而从业者的 write-ups 描述了上下文卸载、即时上下文和带可测量缺页率的请求分页工作集。可迁移的工程理念:不要再把窗口当作你填充的内存,而是开始把它当作你管理的缓存——常驻工作集、廉价的后备存储、故障驱动的恢复、按效用驱逐。
这是分页机制,不是真实的 Agent:"items"是带有 token 大小的整数,访问流是一个局部性模型,存储层被认为是廉价且无损的。真实系统需要搞定两个难点——驱逐什么(对 Agent 来说按最近使用 evict 的纯 LRU 很弱;应该按引用/工作集固定,因为规划阶段读取的文件在整个会话期间都保持相关)和常驻句柄说什么(模型无法操作的指针比载荷本身更糟糕)。从把大型工具结果卸载到摘要+句柄后面开始,只在步骤需要时才分页调回。
go run . # standard library only
Neural Paging: Learning Context Management Policies for Turing-Complete Agents (arXiv 2603.02228) — formalizes the Context Paging Problem and a differentiable page controller acting as a "neural MMU."
Peter J. Denning — The Working Set Model for Program Behavior (1968) — why pinning the active working set beats evicting by recency.
Engineering write-ups
Context offloading: 3 patterns for AI agents — note-taking, sub-agent delegation, just-in-time retrieval; the attention-budget framing.
Demand paging for the AI context window — the OS mapping, fault rates, and "pin by reference, not recency."
Just-in-Time Context for AI Agents — keep the window full of pointers, load heavy content only when needed.
Context Offloading for AI Agents: writing tool results to disk — deferring the retrieval decision from write-time to read-time.