第18章 长时程任务的上下文工程
本章来源:综合自 Hello-Agents 第九章(GSSC流水线与长时程上下文策略)、Practical Guide to Context Engineering(会话存储与上下文持久化)
核心论点:长时程任务——大型代码库迁移、跨数小时的系统性研究、多阶段项目开发——将上下文管理的所有挑战推向极端。单纯增大上下文窗口无法解决问题,需要专门的工程手段:压缩整合实现上下文的"接力",结构化笔记实现信息的"外化",子代理架构实现注意力的"分治",JIT 检索实现上下文的"按需加载"。本章将这些技术整合为一个完整的长时程上下文工程方法论。
18.1 核心问题:当任务超越上下文窗口
第17章解决的是"上下文如何崩溃",本章要解决的是一个更根本的问题:"当任务的时间跨度远超上下文窗口的承载能力时,如何维持连贯性、目标导向和信息完整性?"
一个典型的长时程场景:智能体需要对一个大型代码库进行框架迁移。这可能涉及数百个文件的修改、数十次工具调用、多轮测试-修复循环。即使使用 1M token 的上下文窗口,在任务进行到中途时,早期的关键决策和上下文已经被新的工具输出和对话历史淹没。
长时程任务面临三个结构性挑战:
上下文溢出:任务产生的信息总量超过了上下文窗口的容量。这不是"窗口不够大"的问题——即使窗口无限大,第17章已经证明过长的上下文本身就会导致性能退化。
目标漂移:随着上下文不断累积,模型对初始目标的"记忆"逐渐被稀释。系统提示中的指令可能在数千条消息之后被有效"遗忘",导致智能体偏离原始任务轨道。
信息碎片化:关键信息散落在对话历史的各个位置——某个架构决策在第5轮对话中做出,某个依赖约束在第30轮中发现,某个阻塞问题在第50轮中解决。这些信息之间的关联关系无法通过简单的上下文截断来保持。
应对这些挑战的核心思想是:将上下文从"一次性消耗品"转变为"可管理的工程资产",通过主动的信息生命周期管理,在有限的注意力预算内维持任务的长期连贯性。
18.2 设计空间:长时程上下文管理的三大范式
面向长时程任务的上下文工程,在实践中收敛为三个核心范式。它们不是互斥的替代方案,而是互补的策略层次。
18.2.1 压缩整合(Compaction)——上下文的"接力赛"
核心思想:当对话接近上下文上限时,对其进行高保真总结,并用该摘要重启一个新的上下文窗口。
压缩整合将长时程任务的执行转化为一场"接力赛":每一段上下文窗口就是一棒,接力棒(摘要)在每次交接时必须携带足够的信息,确保下一棒的"选手"(新窗口中的模型)能无缝接续。
适用场景:需要长对话连续性的任务。例如,与用户进行长时间的需求讨论和迭代开发,每一轮对话都建立在之前的基础上。
关键设计决策:
压缩的调参应遵循"召回优先"原则——先确保不遗漏关键信息(高召回),再优化剔除冗余内容(高精确度)。一种安全的"轻触式"压缩是:仅清理深历史中的工具调用与结果,保留所有自然语言交互。这与第17章介绍的工具消息裁剪策略一脉相承。
新窗口的初始上下文应包含:压缩摘要 + 最近的少量高相关工件(如最近访问的文件、未解决的错误信息)。这种"摘要 + 近期缓存"的组合,在信息保留和上下文清洁之间取得了平衡。
18.2.2 结构化笔记(Structured Note-taking)——信息的"外化存储"
核心思想:智能体以固定频率将关键信息写入上下文之外的持久化存储,在后续阶段按需拉回。
如果说压缩整合是在上下文内部进行信息管理,那么结构化笔记则是在上下文外部建立信息枢纽。它以极低的上下文开销(仅需在上下文中保留"有一个笔记系统"的提示和少量引用)维持持久状态与依赖关系。
适用场景:有里程碑或阶段性成果的迭代式开发与研究。例如,代码库重构的每个阶段可以用一个笔记记录完成状态、发现的问题和下一步计划。
实践模式:维护 TODO 列表、项目 NOTES.md、关键结论/依赖/阻塞项的索引。这些外化的记录可以跨数十次工具调用与多轮上下文重置仍保持进度与一致性。在非编码场景中同样有效——例如长期策略性任务、游戏/仿真中的目标管理与统计计数。
18.2.3 子代理架构(Sub-agent Architectures)——注意力的"分治法"
核心思想:由主代理负责高层规划与综合,多个专长子代理在"干净的上下文窗口"中各自深挖,最后仅回传凝练摘要。
子代理架构是上下文隔离策略在长时程场景中的自然延伸。核心价值是实现关注点分离:庞杂的搜索上下文留在子代理内部,主代理的上下文窗口始终保持清洁,专注于整合与推理。
适用场景:复杂研究与分析任务,能从并行探索中获益。例如,需要同时调研多个技术方案的可行性时,每个方案分配一个子代理独立评估,主代理汇总评估结果做最终决策。
方法取舍的经验法则:
| 范式 | 最适合 | 核心优势 |
|---|---|---|
| 压缩整合 | 长对话连续性任务 | 上下文的"接力",保持对话流 |
| 结构化笔记 | 里程碑式迭代开发 | 信息"外化",跨窗口持久化 |
| 子代理架构 | 复杂并行探索任务 | 注意力"分治",保持主窗口清洁 |
18.3 架构解析一:GSSC 流水线
GSSC(Gather-Select-Structure-Compress)是 Hello-Agents 框架提出的上下文构建流水线,将上下文管理过程分解为四个清晰的阶段。它不是一个"压缩算法",而是一个完整的上下文生命周期管理框架。

18.3.1 Gather:多源信息汇集
第一阶段从多个来源汇集候选信息,每个信息单元被封装为一个 ContextPacket:
@dataclass
class ContextPacket:
content: str # 信息内容
timestamp: datetime # 时间戳
token_count: int # Token 数量
relevance_score: float = 0.5 # 相关性分数 (0.0-1.0)
metadata: Optional[Dict] = None # 可选元数据Gather 阶段按以下顺序从多个来源收集候选信息:
- 系统指令:标记为最高优先级(relevance_score = 1.0),始终保留
- 记忆系统:通过 MemoryTool 检索与当前查询相关的记忆
- RAG 系统:通过 RAG 工具检索相关知识
- 对话历史:保留最近 N 条消息(默认 5 条)
- 自定义信息包:任何外部注入的上下文(如 NoteTool 的笔记)
关键设计决策是容错机制:每个外部数据源的调用都被 try-except 包裹,确保单个源的失败不会影响整体流程。这在长时程任务中尤其重要——当某个外部服务暂时不可用时,智能体仍能基于其他来源的信息继续工作。
18.3.2 Select:智能信息选择
第二阶段是整个流水线的核心,通过相关性和新近性的加权评分来选择最有价值的信息。
评分机制:
其中默认权重为 ContextConfig 配置。
相关性计算:基础实现使用 Jaccard 相似度(关键词重叠),生产环境中替换为向量相似度。
新近性计算:使用指数衰减模型,24 小时内保持高分,之后逐渐衰减:
选择算法:贪心策略——按综合分数从高到低填充,直到达到 Token 上限。系统指令不参与排序,始终优先占用预算。低于 min_relevance 阈值的信息被直接过滤。
18.3.3 Structure:结构化输出
第三阶段将选中的信息组织为固定骨架的模板:
[Role & Policies] ← 系统指令
[Task] ← 当前用户查询
[Evidence] ← RAG 检索结果
[Context] ← 对话历史 + 记忆
[Output] ← 输出格式要求这种分区设计的工程价值在于:(1) 可调试性——问题定位时可以快速识别哪个区域的信息有问题;(2) 稳定性——固定的结构让模型形成稳定的"阅读习惯",减少因上下文格式变化带来的行为波动;(3) 可度量性——A/B 测试和评估可以精确到分区级别。
18.3.4 Compress:兜底压缩
第四阶段是安全网——当结构化后的上下文仍然超过 Token 预算时,执行分区级别的截断压缩。保持结构完整性是核心原则:压缩从后面的分区开始,每个分区至少保留 50 tokens,截断处标记 [... 内容已压缩 ...] 以告知模型信息不完整。
在生产环境中,这一阶段可以升级为 LLM 摘要压缩(如第17章介绍的 Claude Code 或 Gemini CLI 方案),但简单截断作为兜底策略已经足够有效。
18.3.5 配置管理
GSSC 流水线的行为通过 ContextConfig 统一配置:
@dataclass
class ContextConfig:
max_tokens: int = 3000 # 最大 Token 数
reserve_ratio: float = 0.2 # 为系统指令预留的比例
min_relevance: float = 0.1 # 最低相关性阈值
enable_compression: bool = True
recency_weight: float = 0.3 # 新近性权重
relevance_weight: float = 0.7 # 相关性权重reserve_ratio 参数确保系统指令始终有足够空间,不会被其他信息挤占。这是一个容易被忽视但至关重要的设计:如果系统指令被截断,智能体的行为约束就会失效,在长时程任务中尤其危险。
18.4 架构解析二:JIT 上下文检索
工程实践正在从"推理前一次性检索"逐步过渡到"及时(Just-in-time, JIT)上下文"。这是长时程任务中上下文管理的另一个关键架构。

18.4.1 从预加载到按需加载
传统的 RAG 模式是"推理前一次性检索":在模型调用之前,通过 embedding 检索一批相关文档,全部塞入上下文。JIT 上下文则采用完全不同的思路:
- 不预先加载所有相关数据
- 维护轻量化引用(文件路径、存储查询、URL 等)
- 在运行时通过工具动态加载所需数据
- 模型撰写针对性查询、缓存必要结果
这种模式更贴近人类的认知方式:我们不会死记硬背全部信息,而是用文件系统、收件箱、书签等外部索引按需提取。
18.4.2 元数据作为隐式上下文
JIT 模式的一个被低估的优势是:引用的元数据本身就在传递信息。目录层级、命名约定、时间戳等都在隐含地传达"目的与时效"。例如,tests/test_utils.py 与 src/core/test_utils.py 的语义暗示就不同——前者是测试代码,后者是核心实现。
在长时程任务中,这些元数据帮助模型构建对项目结构的"心智模型",而无需在上下文中保存完整的项目描述。
18.4.3 渐进式披露(Progressive Disclosure)
JIT 检索自然地实现了渐进式披露:每一步交互都会产生新的上下文,反过来指导下一步决策。
- 文件大小暗示复杂度
- 命名暗示用途
- 时间戳暗示相关性
智能体按层构建理解,只在工作记忆中保留"当前必要子集",并用"记笔记"的方式做补充持久化。这种模式让智能体维持聚焦,而非"被大而全拖垮"。
18.4.4 混合策略:预加载 + JIT
纯 JIT 模式的劣势是速度——运行时探索比预计算检索更慢,且需要精心设计工具和启发式来引导模型的探索方向。如果缺少引导,智能体可能误用工具、追逐死胡同或错过关键信息,造成上下文浪费。
因此,工程实践中更常见的是混合策略:
- 前置加载少量"高价值"上下文(如项目 README、约定说明、配置文件)以保证启动速度
- 运行时按需继续自主探索(提供
glob、grep、read等工具原语)
在 Claude Code 中,这种混合策略的具体实现是:预先加载 CLAUDE.md(项目约定文件),同时提供文件搜索和读取工具,让模型在需要时自行探索代码库。这绕开了过时索引和复杂语法树的沉没成本,同时确保模型在任务开始时就拥有最关键的上下文。
18.5 关键实现决策:NoteTool 与注意力锚定
18.5.1 NoteTool:结构化的外部记忆
NoteTool 是专为长时程任务设计的结构化外部记忆组件。它以 Markdown 文件为载体,头部使用 YAML 前置元数据记录关键信息,正文用于记录状态、结论、阻塞与行动项。
笔记文件格式:
---
id: note_20250119_153000_0
title: 重构项目 - 第一阶段
type: task_state
tags: [refactoring, phase1, backend]
created_at: 2025-01-19T15:30:00
updated_at: 2025-01-19T15:30:00
---
# 重构项目 - 第一阶段
## 完成情况
已完成数据模型层的重构...
## 下一步计划
1. 重构业务逻辑层
2. 解决依赖冲突问题这种设计兼顾了三个需求:机器可解析(YAML 元数据支持精确检索)、人类可读(Markdown 正文支持丰富格式化)、版本友好(纯文本格式天然支持 Git)。
笔记类型体系:
| 类型 | 用途 | 典型内容 |
|---|---|---|
| task_state | 任务状态追踪 | 当前阶段进度、完成百分比 |
| conclusion | 阶段性结论 | 关键发现、架构决策 |
| blocker | 阻塞记录 | 未解决的问题、依赖冲突 |
| action | 行动计划 | 下一步具体操作 |
| reference | 参考信息 | 重要文档链接、API 规范 |
| general | 通用笔记 | 其他需要记录的信息 |
与 ContextBuilder 的集成:NoteTool 通过 ContextPacket 机制与 GSSC 流水线无缝对接。在每轮对话前,智能体可以检索相关笔记并将其作为自定义信息包注入上下文构建过程:
# 检索相关笔记
relevant_notes = note_tool.run({
"action": "search",
"query": user_input,
"limit": 3
})
# 转换为 ContextPacket
note_packets = [ContextPacket(
content=note['content'],
timestamp=note['updated_at'],
token_count=count_tokens(note['content']),
relevance_score=0.7,
metadata={"type": "note", "note_type": note['type']}
) for note in relevant_notes]
# 注入 GSSC 流水线
context = builder.build(
user_query=user_input,
custom_packets=note_packets,
...
)18.5.2 注意力锚定:TODO 列表与目标刷新
长时程任务中最隐蔽的失败模式是目标漂移。智能体在执行了几十个步骤后,可能已经偏离了初始目标——不是因为"忘了",而是因为累积的上下文将模型的注意力引向了其他方向。
注意力锚定是对抗目标漂移的核心技术。其基本思想是:在上下文中维护一个持续更新的结构化状态(如 TODO 列表),确保模型在每一步推理时都能"看到"当前的全局目标和进度。
Claude Code 的实践提供了一个典型案例:在执行复杂任务时,系统会在上下文中反复出现更新后的 TODO 列表,每完成一个子步骤就标记为已完成,并列出下一步。这种持续刷新的结构化状态起到了"注意力锚点"的作用——无论上下文中积累了多少工具输出和中间结果,模型都能通过 TODO 列表快速回忆当前的任务进度。
Manus 采用了类似的策略:在每次行动前,系统会将当前的计划状态注入上下文,包括已完成的步骤和待执行的步骤。这确保了即使在上下文多次压缩重置之后,智能体仍然知道"我做到了哪里,接下来该做什么"。
18.5.3 ContextAwareAgent:完整的集成示例
将上述所有技术整合到一个智能体中:
class ContextAwareAgent(SimpleAgent):
def __init__(self, name, llm, **kwargs):
super().__init__(name=name, llm=llm)
self.memory_tool = MemoryTool(user_id=kwargs.get("user_id"))
self.rag_tool = RAGTool(knowledge_base_path=kwargs.get("kb_path"))
self.note_tool = NoteTool(workspace=kwargs.get("notes_dir"))
self.context_builder = ContextBuilder(
memory_tool=self.memory_tool,
rag_tool=self.rag_tool,
config=ContextConfig(max_tokens=4000)
)
self.conversation_history = []
def run(self, user_input):
# 1. 检索相关笔记,转换为 ContextPacket
note_packets = self._retrieve_note_packets(user_input)
# 2. 使用 GSSC 流水线构建优化的上下文
context = self.context_builder.build(
user_query=user_input,
conversation_history=self.conversation_history,
system_instructions=self.system_prompt,
custom_packets=note_packets
)
# 3. 调用 LLM
response = self.llm.invoke([
{"role": "system", "content": context},
{"role": "user", "content": user_input}
])
# 4. 更新对话历史
self.conversation_history.append(
Message(content=user_input, role="user")
)
self.conversation_history.append(
Message(content=response, role="assistant")
)
# 5. 将重要交互记录到记忆系统
self.memory_tool.run({
"action": "add",
"content": f"Q: {user_input}\nA: {response[:200]}...",
"memory_type": "episodic",
"importance": 0.6
})
return response这个集成展示了长时程上下文管理的完整闭环:GSSC 流水线负责每轮调用的上下文优化,NoteTool 负责跨轮次的信息持久化,MemoryTool 负责交互记忆的积累与检索。三者协作,确保智能体在任意时间点都能获得最优的上下文。
18.6 关键实现决策:压缩整合的工程细节
18.6.1 压缩时机的选择
压缩整合不应在上下文已经溢出时才触发。工程实践表明,最佳的触发时机是在达到上下文窗口的 80%-90% 时。提前触发的好处是:(1) 给压缩操作本身(尤其是 LLM 摘要)留出足够的 Token 预算;(2) 避免在紧急截断时丢失关键信息。
18.6.2 压缩的信息保留策略
无论使用哪种压缩方法,以下信息必须被保留:
- 架构决策:项目中做出的关键技术选择和理由
- 未解决的问题:当前阻塞的 bug、待确认的需求
- 文件变更记录:哪些文件被创建、修改、删除
- 用户偏好:用户明确表达的约束和偏好
- 当前计划:任务的整体计划和执行进度
这五个维度与 Gemini CLI 的 5 段式摘要高度对应,也与 Claude Code 的 9 段式摘要的核心维度一致。
18.6.3 多次压缩的退化问题
在长时程任务中,上下文可能经历多次压缩-重启循环。每次压缩都不可避免地丢失部分信息,经过多次压缩后,累积的信息损失可能导致严重的上下文退化。
应对策略:
结构化笔记作为"不可压缩"的信息锚:将最关键的信息(架构决策、阻塞问题、里程碑)写入 NoteTool,这些信息存储在上下文之外,不受压缩影响。
分层压缩:第一层使用工具消息裁剪(无信息损失的精确删除),第二层使用消息删除(有选择的物理删除),第三层才使用 LLM 摘要(语义级压缩)。通过分层,确保 LLM 摘要(信息损失最大的压缩方式)只在真正需要时才被使用。
压缩历史审计:保留最近 10 次压缩操作的详细记录,包括压缩前后的 Token 数、被移除的消息摘要、使用的压缩策略等。这些记录帮助开发者监控压缩质量,在出现异常退化时快速定位原因。
18.7 前沿动态
18.7.1 MCP 与上下文标准化
Model Context Protocol(MCP)正在推动上下文管理的标准化。MCP 定义了一套协议,让不同的工具、数据源和上下文提供者可以以统一的格式向 LLM 提供上下文。在长时程任务场景中,MCP 使得上下文的来源可以从本地文件扩展到远程服务、数据库、API 端点等,而上下文管理系统不需要为每个新来源编写适配代码。
18.7.2 从对话式到任务式的上下文管理
传统的上下文管理以"对话轮次"为基本单位——每轮对话产生一组消息,压缩以消息为单位进行。长时程任务正在推动范式转变:以"任务阶段"为基本单位进行上下文管理。
具体而言:一个长时程任务被分解为多个阶段,每个阶段完成后产生一个结构化的"阶段报告"(类似 NoteTool 的 task_state 笔记),下一阶段以阶段报告而非完整对话历史作为上下文输入。这种方式将压缩的粒度从"消息级"提升到"阶段级",大幅减少了信息损失。
18.7.3 自适应 Token 预算
静态的 max_tokens 配置在长时程任务中不够灵活。前沿实践正在探索动态调整 Token 预算的策略:简单的子任务使用较小预算以提高处理速度,复杂的子任务(如架构设计、bug 调试)使用较大预算以确保推理质量。ContextConfig 的可配置性为这种自适应策略提供了基础设施。
18.7.4 持久化上下文的安全边界
当上下文通过 NoteTool 等机制被持久化到文件系统时,一个新的安全问题出现了:持久化的上下文可能包含敏感信息(用户输入、API 密钥、内部代码),这些信息的生命周期不再受上下文窗口的约束。未来的上下文工程框架需要内建信息分类和生命周期管理机制,确保敏感信息在不再需要时被安全清除。
18.8 本章小结
本章将前两章的概念和技术整合为一个面向长时程任务的完整方法论。
三大核心范式为不同类型的长时程任务提供了策略选择:
- 压缩整合用于需要对话连续性的任务
- 结构化笔记用于里程碑式的迭代开发
- 子代理架构用于需要并行探索的复杂研究
GSSC 流水线将上下文管理过程标准化为四个阶段(Gather-Select-Structure-Compress),提供了可复用的工程模式。其中 Select 阶段的"相关性 + 新近性"加权评分和贪心选择算法是核心引擎。
JIT 上下文检索代表了从"预加载全部信息"到"按需动态加载"的范式转变,通过轻量化引用和渐进式披露,在信息充足性和上下文清洁性之间取得平衡。
NoteTool 与注意力锚定为长时程任务提供了对抗信息碎片化和目标漂移的具体工具。
⚠️ 已知局限:长时程任务中最棘手的问题是"压缩失忆"——经过多次上下文压缩后,早期的关键架构决策和约束条件可能被逐步丢失。即使使用结构化笔记作为外部锚点,智能体也可能因为笔记检索的相关性评分偏差而遗漏关键信息。在超过100步的长任务中,实践中观察到约30%的任务会出现至少一次因信息丢失导致的决策冲突。此外,JIT检索在项目结构复杂时(如超过1000个文件的代码库)的探索效率显著下降,智能体可能花费大量步数在不相关的文件中搜索。
核心结论是:长时程任务的上下文工程,本质上是一个信息生命周期管理问题。从信息的采集(Gather)、筛选(Select)、组织(Structure)、压缩(Compress),到外化存储(NoteTool)、按需检索(JIT)、跨窗口持久化——每一个环节都需要系统化的工程设计。即便模型能力持续提升,"在长交互中维持连贯性与聚焦"仍是构建强健智能体的核心挑战。
至此,本书的第六篇"上下文工程"部分完结。我们从上下文的组件解剖(第16章)出发,经过上下文失败模式和压缩技术的深度分析(第17章),最终在本章中构建了面向长时程任务的完整工程方法论。接下来的篇章将进入通信协议与多智能体系统的领域,探讨当多个智能体协作时,上下文如何在它们之间流动、同步和整合。