上下文工程核心
管理 Agent(智能体) 的“工作记忆“——在有限的 Token 空间内实现信息优先级的精准编排。
前置条件
- 已完成 简介,理解 Harness Engineering(驾驭工程) 基本概念
- 已安装 OpenCode CLI 并完成基础配置
- 已了解 LLM 上下文窗口和 Token 计数的基本概念
文章概述
每个 Agent 的上下文窗口(Context(上下文) Window)容量有限,装不下所有信息。上下文工程就是管理这个有限空间的技术——决定哪些信息保留、哪些丢弃、如何预留空间,直接影响 Agent 的决策准确度。本章围绕三个核心维度展开:压缩(缩减信息量)、缓存(重用已有信息)、预算(分配有限空间),讲解每个维度的实现原理。你会理解 Compaction 自动压缩机制如何选择性保留关键信息、Session 级与跨 Session 缓存的差异、以及 Token 预算在系统指令/用户输入/工具输出之间的分配策略与超限处理机制。
上下文工程与约束系统配合使用:上下文工程确保 Agent “看得到“需要的信息,约束系统确保 Agent “不做“不该做的事。验证护栏则在输出阶段验证结果正确性。学完本节,你应能根据任务特征配置上下文管理参数,理解压缩后信息保真度与性能的权衡关系,并掌握跨会话上下文保持的基本方法。
读完本文,你将能够合理分配 Token 预算以优化上下文利用,理解 Compaction 压缩与缓存机制的工作原理,以及根据任务复杂度调整上下文管理策略。
⏱ 时间有限?先读这些: 上下文压缩原理 → 上下文缓存策略 → Token 预算管理 → 三层协作的决策流程
最小示例
用一个最简单的配置来理解上下文工程:
{
"compaction": {
"auto": true,
"prune": false,
"reserved": 10000
}
}
这三行配置说的是:开启自动压缩(auto: true),不裁剪旧工具输出(prune: false),预留 10K Token 的缓冲空间避免压缩过程溢出。reserved 就像一个安全缓冲区——当上下文接近模型窗口上限时,这段预留空间确保压缩过程中不会因超限而失败。
操作系统类比:Context = 工作记忆
理解上下文工程最直观的方式是将其类比为操作系统的内存管理:
| 操作系统概念 | OpenCode 对应 | 说明 |
|---|---|---|
| RAM / 工作记忆 | Context Window | Agent 的有限工作空间 |
| Swap / 页面文件压缩 | Compaction | 空间不足时压缩不活跃内容腾出空间 |
| CPU 缓存层级(L1/L2/L3) | Caching | 按层级缓存内容,命中越快成本越低 |
| 内存分配(heap/stack/reserved) | Token Budget | 为不同用途预分配有限空间 |
| 内存碎片整理 | 上下文压缩 | 消除冗余内容,提高空间利用率 |
| 虚拟内存 | 跨 Session 缓存 | 将持久化内容映射到上下文空间 |
这个类比帮助理解几个关键设计:
- 空间有限性:RAM 有限,Agent 的 Context Window 也有限——必须精打细算
- 层级缓存:CPU 缓存有 L1/L2/L3 层级,Context 缓存也有 Session 级和跨 Session 级
- 压缩换空间:操作系统用 Swap 换内存空间,Context 用 Compaction 换 Token 空间
为什么需要上下文工程
Token 空间有限,信息无限
每个 AI 模型都有固定的上下文窗口上限——Claude 的 200K Token、GPT-4 的 128K Token。这个窗口就是 Agent 的“工作记忆“,所有对话历史、代码片段、工具输出、系统指令都必须塞进这个有限空间。
然而,软件开发的信息量几乎是无限的:
- 一个中型项目可能有数十万行代码
- 完整的 API 文档可能超过 10 万字
- 一次长会话的对话历史可能积累数万 Token
- MCP(模型上下文协议) 工具返回的查询结果可能非常庞大
核心矛盾:有限的工作记忆 vs 无限的信息需求。上下文工程就是为了解决这个矛盾而诞生的方法论。
上下文质量决定决策质量
Agent 的每一次决策都依赖于当前上下文。上下文不完整,决策就会出错:
用户:修复登录模块的 bug
上下文缺失场景:
- Agent 不知道登录模块在哪里 → 随机搜索,浪费时间
- Agent 不知道之前的修复历史 → 重复已尝试的方案
- Agent 不知道项目规范 → 生成不符合风格的代码
上下文完整场景:
- Agent 精确定位登录模块 → 直接进入修复
- Agent 了解历史上下文 → 避免重复劳动
- Agent 掌握项目规范 → 生成一致风格的代码
上下文工程的目标,就是让 Agent 在任何时刻都拥有做出正确决策所需的信息——不多不少,恰到好处。
上下文工程的三层模型
上下文工程从三个维度管理有限的工作记忆空间:
graph TB
subgraph 三层模型
P[压缩层<br/>Compaction] --> C[缓存层<br/>Caching]
C --> B[预算层<br/>Budget]
end
P --> |缩减信息量| P1[选择性保留关键信息]
C --> |重用已有信息| C1[避免重复传输]
B --> |分配有限空间| B1[优先级排序]
style P fill:#4A90D9,color:#fff
style C fill:#50C878,color:#fff
style B fill:#FF9F43,color:#fff
style P1 fill:#E8F4FD,color:#333
style C1 fill:#E8F8EC,color:#333
style B1 fill:#FFF4E8,color:#333
| 层级 | 核心问题 | 解决思路 | 触发时机 |
|---|---|---|---|
| 压缩层 | 信息太多怎么办? | 选择性保留,丢弃低价值内容 | 上下文接近上限时 |
| 缓存层 | 重复内容怎么处理? | 一次传输,多次复用 | 每次请求时 |
| 预算层 | 空间如何分配? | 按优先级预分配,动态调整 | 任务开始时 |
三层之间存在依赖关系:缓存优先(能复用就不重传),预算控制(分配各部分空间),压缩兜底(超限时智能缩减)。
配置映射速查:压缩层对应
compaction字段(如compaction.auto、compaction.reserved);缓存层对应caching字段(如caching.crossSession);预算层通过compaction.reserved控制整体预留空间,推理预算通过provider.*.models.*.options.thinking.budgetTokens设置。部分高级配置(如微压缩规则)需要 OpenCode >= v1.17.x 和 OMO >= v4.13.x。没有直接对应配置的概念(如上下文注入),通过 AGENTS.md 或 Skill(技能) 配置实现。
上下文压缩原理
自动压缩机制(Compaction)
当上下文接近窗口上限时,OpenCode 会自动触发 Compaction——一个后台 Agent 会分析当前上下文,生成摘要并选择性保留关键信息。
sequenceDiagram
participant U as 用户
participant A as Primary Agent
participant C as Compaction Agent
participant M as 模型
U->>A: 继续对话
A->>A: 检测上下文接近上限
A->>C: 触发后台压缩
C->>M: 分析上下文重要性
M-->>C: 返回重要性评估
C->>C: 生成摘要 + 选择性保留
C-->>A: 返回压缩后的上下文
A->>M: 使用压缩上下文继续
M-->>A: 生成响应
A-->>U: 返回结果
Compaction 的核心原则:
- 用户指令优先保留 — 用户明确说过的话不能丢
- 关键决策记录 — Agent 做出的重要选择必须保留
- 错误信息保留 — 失败的尝试是宝贵的学习材料
- 代码片段压缩 — 用文件路径 + 摘要替代完整代码
- 对话历史摘要 — 多轮对话合并为简洁摘要
微压缩策略
除了自动压缩,OpenCode 还支持细粒度的微压缩配置:
// Requires OpenCode >= v1.17.x, OMO >= v4.13.x
{
"compaction": {
"strategy": "selective",
"rules": [
{
"type": "code",
"action": "summarize",
"keepSignature": true
},
{
"type": "tool_output",
"action": "protect",
"window": "40K"
},
{
"type": "conversation",
"action": "summarize",
"keepUserMessages": true
}
]
}
}
三种压缩动作:
| 动作 | 含义 | 适用场景 |
|---|---|---|
summarize | 生成摘要,丢弃原文 | 对话历史、长文档 |
protect | 完整保留,不压缩 | 用户指令、关键决策 |
truncate | 截断,只保留开头/结尾 | 超长的工具输出 |
工具输出保护窗口:最近 40K Token 的工具输出不受压缩影响,确保 Agent 能看到最新的执行结果。
压缩后的信息保真度
压缩是有损的,但损失可控。关键在于区分“必须保留“和“可以压缩“:
必须保留(保真度 100%):
├── 用户明确的指令
├── Agent 的关键决策
├── 错误信息和失败原因
└── 当前任务的核心上下文
可以压缩(保真度 70-90%):
├── 历史对话 → 摘要
├── 完整代码 → 文件路径 + 关键函数签名
├── 工具输出 → 结果摘要
└── 探索过程 → 结论性发现
压缩比 vs 保真度的权衡:更高的压缩比意味着更多的信息损失。OpenCode 默认在压缩比 3:1 时可保持大部分关键信息保真度(经验估算)。
上下文缓存策略
缓存 vs 压缩
缓存和压缩是互补的两种策略:
| 策略 | 解决的问题 | 核心机制 | 效果 |
|---|---|---|---|
| 缓存 | 消除重复传输 | 一次发送,多次复用 | 可显著节省 Token 消耗(经验估算) |
| 压缩 | 精简必要内容 | 选择性保留,丢弃冗余 | 可有效延长会话寿命 |
最佳实践:缓存优先,压缩兜底。先通过缓存消除重复,再通过压缩精简必要内容。
Session 级缓存
Session 级缓存在单个会话内有效,自动管理,无需配置:
graph LR
subgraph Session 生命周期
R1[请求 1] --> |缓存系统指令| C1[(缓存)]
R2[请求 2] --> |命中缓存| C1
R3[请求 3] --> |命中缓存| C1
end
R2 -.-> |节省 Token| S1[系统指令: 2K Token]
R3 -.-> |节省 Token| S1
style C1 fill:#50C878,color:#fff
Session 级缓存的内容:
- 系统指令(System Prompt(提示词))— 每个 Session 固定
- 工具定义(Tool Definitions)— MCP 工具的 JSON Schema
- 项目上下文(Project Context)— README、CLAUDE.md 等
跨 Session 缓存
跨 Session 缓存需要显式配置,适用于长期项目:
// Requires OpenCode >= v1.17.x, OMO >= v4.13.x
{
"caching": {
"crossSession": {
"enabled": true,
"persistPath": ".opencode/cache",
"maxAge": "7d",
"entries": [
{
"type": "project_knowledge",
"files": ["README.md", "CLAUDE.md", "docs/**/*.md"]
},
{
"type": "tool_definitions",
"tools": ["filesystem", "git", "mcp-*"]
}
]
}
}
}
跨 Session 缓存的生命周期:
| 缓存类型 | 生命周期 | 失效条件 |
|---|---|---|
| 项目知识 | 项目持续期 | 文件内容变更 |
| 工具定义 | 工具版本更新 | 配置变更 |
| 用户偏好 | 用户修改 | 手动清除 |
缓存命中率优化
缓存命中率是衡量缓存效果的关键指标:
缓存命中率 = 命中缓存的 Token 数 / 总请求 Token 数
优化目标:命中率通常可达 60% 以上(取决于使用模式)
提升命中率的策略:
- 固化系统指令 — 使用稳定的 System Prompt,避免频繁修改
- 结构化项目知识 — 将常用文档放在固定位置
- 合理设置缓存粒度 — 太小命中率低,太大更新成本高
- 预热缓存 — Session 开始时主动加载常用内容
Token 预算管理
预算分配策略
Token 预算将有限的上下文窗口划分为四个区域:
graph TB
subgraph Token 预算分配
S[系统消息<br/>2-4K Token<br/>固定开销]
U[用户输入<br/>动态变化<br/>任务描述 + 代码]
T[工具输出<br/>动态变化<br/>MCP 返回数据]
R[预留空间<br/>20-30%<br/>Agent 推理缓冲]
end
S --> U --> T --> R
style S fill:#4A90D9,color:#fff
style U fill:#50C878,color:#fff
style T fill:#FF9F43,color:#fff
style R fill:#A66CFF,color:#fff
预算配置示例:
{
"compaction": {
"auto": true,
"prune": false,
"reserved": 10000
}
}
各区域的作用:
| 区域 | 占比 | 内容 | 管理策略 |
|---|---|---|---|
| 系统消息 | 2-5% | System Prompt、工具定义 | 固定,通过缓存优化 |
| 用户输入 | 25-30% | 任务描述、代码上下文 | 按需加载,智能截断 |
| 工具输出 | 40-50% | MCP 返回、文件内容 | 结果压缩、分页返回 |
| 预留空间 | 10-20% | Agent 推理、生成响应 | 必须保留,不可侵占 |
注意:OpenCode 不提供精确到类别的预算分配配置,上表是概念性的预算分配原则。实际控制通过
compaction.reserved设置整体预留空间,以及 Provider 层的thinking.budgetTokens控制推理预算。
预算超限的处理机制
当 Token 使用接近上限时,系统依次触发三级响应:
flowchart TB
A[Token 使用 > 80%] --> B{触发压缩}
B --> |成功| C[继续执行]
B --> |仍超限| D{模型降级}
D --> |成功| E[使用更便宜模型]
D --> |仍超限| F{强制截断}
F --> G[丢弃最早历史]
C --> H[任务完成]
E --> H
G --> H
style A fill:#FFF4E8,color:#333
style B fill:#4A90D9,color:#fff
style D fill:#FF9F43,color:#fff
style F fill:#DC3545,color:#fff
三级响应详解:
| 级别 | 触发条件 | 动作 | 影响 |
|---|---|---|---|
| 压缩 | Token > 80% | 执行 Compaction | 有损但保留关键信息 |
| 降级 | Token > 90% | 切换到更便宜的模型 | 响应质量下降 |
| 截断 | Token > 95% | 丢弃最早的历史 | 可能丢失重要上下文 |
配置超限响应:
{
"compaction": {
"auto": true,
"prune": false,
"reserved": 10000
}
}
OpenCode 的 Compaction 机制在上下文接近窗口上限时自动触发。当 Token 使用量达到模型上下文限制的约 80% 时,系统会启动一个专门的 compaction Agent,对历史消息进行智能摘要压缩,替换掉原始冗长的对话记录。reserved 参数确保压缩过程中有足够的缓冲空间不会溢出。此外,还可以通过 Provider 的 thinking.budgetTokens 控制推理 Token 预算:
{
"provider": {
"anthropic": {
"models": {
"claude-sonnet-4-20250514": {
"options": {
"thinking": {
"type": "enabled",
"budgetTokens": 16000
}
}
}
}
}
}
}
三层协作的决策流程
压缩、缓存、预算三层如何协作?以下是完整的决策流程:
flowchart TB
Start[新请求到达] --> Check{缓存命中?}
Check --> |是| UseCache[使用缓存内容]
Check --> |否| LoadContent[加载完整内容]
UseCache --> Budget{预算检查}
LoadContent --> Budget
Budget --> |预算充足| Execute[执行任务]
Budget --> |预算紧张| Compact{触发压缩?}
Compact --> |是| DoCompact[执行 Compaction]
Compact --> |否| Downgrade[模型降级]
DoCompact --> Recheck{预算足够?}
Recheck --> |是| Execute
Recheck --> |否| Downgrade
Downgrade --> Execute
Execute --> Response[生成响应]
Response --> UpdateCache[更新缓存]
UpdateCache --> End[完成]
style Start fill:#E8F4FD,color:#333
style Check fill:#50C878,color:#fff
style Budget fill:#FF9F43,color:#fff
style Compact fill:#4A90D9,color:#fff
style Execute fill:#A66CFF,color:#fff
style End fill:#E8F8EC,color:#333
决策要点:
- 缓存优先 — 每次请求先检查缓存,命中则节省 Token
- 预算控制 — 加载内容后检查预算,决定是否需要压缩
- 压缩兜底 — 预算紧张时触发压缩,而非直接降级
- 渐进降级 — 压缩 → 降级 → 截断,逐级响应
上下文工程在 Harness Engineering 中的位置
上下文工程是 Harness Engineering 框架的核心支柱之一:
graph TB
subgraph Harness Engineering 双引擎
CE[上下文工程<br/>确保 Agent 看得到]
CS[约束系统<br/>确保 Agent 不做错]
end
CE --> VH[验证护栏<br/>确保输出正确]
CS --> VH
VH --> Result[高质量交付]
style CE fill:#4A90D9,color:#fff
style CS fill:#50C878,color:#fff
style VH fill:#FF9F43,color:#fff
style Result fill:#A66CFF,color:#fff
三者的协作关系:
| 组件 | 职责 | 作用阶段 |
|---|---|---|
| 上下文工程 | 提供决策所需信息 | 输入阶段 |
| 约束系统 | 限制危险操作 | 执行阶段 |
| 验证护栏 | 验证输出正确性 | 输出阶段 |
上下文工程确保 Agent 拥有做出正确决策的信息基础;约束系统防止 Agent 执行危险操作;验证护栏在输出阶段进行最终检验。三者形成完整的质量保障闭环。
配置示例汇总
基础上下文管理配置
{
"context": {
"compaction": {
"enabled": true,
"threshold": 0.8,
"strategy": "selective"
},
"caching": {
"sessionLevel": true,
"crossSession": false
},
"budget": {
"total": 200000,
"reserved": 0.25
}
}
}
高级上下文管理配置
{
"context": {
"compaction": {
"enabled": true,
"threshold": 0.75,
"strategy": "selective",
"rules": [
{
"type": "code",
"action": "summarize",
"keepSignature": true
},
{
"type": "tool_output",
"action": "protect",
"window": "40K"
},
{
"type": "conversation",
"action": "summarize",
"keepUserMessages": true
}
]
},
"caching": {
"sessionLevel": true,
"crossSession": {
"enabled": true,
"persistPath": ".opencode/cache",
"maxAge": "7d",
"entries": [
{
"type": "project_knowledge",
"files": ["README.md", "CLAUDE.md", "docs/**/*.md"]
}
]
}
},
"budget": {
"total": 200000,
"allocation": {
"system": 4000,
"user": 50000,
"tools": 80000,
"reserved": 66000
},
"overrunHandling": {
"compression": {
"threshold": 0.8,
"priority": 1
},
"modelDowngrade": {
"threshold": 0.9,
"fallbackModel": "claude-haiku",
"priority": 2
},
"truncation": {
"threshold": 0.95,
"strategy": "fifo",
"priority": 3
}
}
}
}
}
上下文工程安全风险分析
上下文工程管理 Agent 的“工作记忆“,安全性直接影响决策质量和数据安全。主要风险包括上下文注入攻击、压缩导致安全信息丢失、缓存污染/泄露、以及 Token 预算不足导致安全检查被跳过。
更详细的风险分析、配置示例和安全检查 → 安全总览。
安全检查清单
上下文工程的安全检查(Prompt 注入检测、缓存加密、Token 预算安全预留)与完整安全策略 → 安全总览。
小结
上下文工程是 AI Agent 的“记忆管理“方法论,核心解决有限 Token 空间与无限信息需求之间的矛盾。三层模型——压缩、缓存、预算——从不同维度管理上下文:
- 压缩层:选择性保留关键信息,丢弃低价值内容
- 缓存层:一次传输重复内容,避免浪费 Token
- 预算层:预分配空间,优先保障关键区域
三层协作的决策流程遵循“缓存优先、预算控制、压缩兜底“的原则。在实际配置中,需要根据任务特征调整参数,在 Token 节省和信息保真度之间找到最佳平衡点。
常见反模式
反模式一:过度压缩导致信息丢失
现象:将 Compaction 的压缩比调到极限,会话中保存的历史信息被大幅摘要化。Agent 在后续任务中反复遗漏关键细节,需要频繁重新解释上下文。
原因:追求极致的 Token 节省,低估了压缩对信息保真度的影响。成本优化的优先级高于任务质量。
对策:保留合理的预留空间(reserved: 10000),区分“必须保留“和“可以压缩“的内容类型——用户指令、关键决策用 protect 动作保护,历史对话和工具输出用 summarize 压缩。
反模式二:忽视缓存预热
现象:每次新会话 Agent 都要从零扫描项目结构、重新加载文档,前几轮交互效率极低,大量的 Token 消耗在重复加载稳定信息上。
原因:未启用跨 Session 缓存,或认为缓存配置过于复杂不值得做。
对策:配置 crossSession 缓存,将 README.md、AGENTS.md 等稳定的项目知识加入缓存白名单;Session 启动时通过 Skill 主动加载常用上下文,预热缓存。
反模式三:Token 预算分配失衡
现象:系统指令和工具定义占用了过多的 Token 预算,留给 Agent 推理空间的不足。任务进行到一半频繁触发截断,重要决策因空间不足被丢弃。
原因:将大量参考文档直接注入系统消息而非使用 Skill 按需加载。
对策:精简 system prompt 至核心指令;将冗长的参考文档放入 Skill 的 reference/ 目录按需加载而非直接注入系统消息;使用 thinking.budgetTokens 合理分配推理预算。
常见错误与陷阱
场景一:上下文注入攻击
场景:Agent 通过 WebFetch 工具读取了一个包含恶意指令的网页。网页中的隐藏指令加载到上下文后,Agent 的后续行为被劫持,执行了非预期的操作。
后果:Agent 行为被污染,可能泄露项目信息或执行危险命令。
预防:对 WebFetch 返回内容进行安全过滤,隔离用户输入和系统指令的边界;Subagent 默认只读权限限制攻击面;在安全敏感场景中禁用 WebFetch 工具。
场景二:跨 Session 缓存污染
场景:跨 Session 缓存将过期项目知识缓存了 30 天。项目在此期间重构了 API,但 Agent 在不同 Session 中持续使用过时的 API 信息生成代码。
后果:大量代码基于过时假设编写,需要返工,浪费数小时。
预防:设置合理的缓存过期时间(maxAge: 7d);配置文件变更触发的缓存失效机制;关键项目知识变更后手动清除缓存。
场景三:压缩丢失关键决策记录
场景:Agent 在长会话中经过多轮讨论做了一个重要架构决策。Compaction 触发后,将包含该决策的对话摘要化,后续 Agent 不再记得这个约束。
后果:Agent 做出与之前决策相矛盾的设计,架构一致性被破坏。
预防:将关键决策写入外部持久化文件(如 AGENTS.md 或项目决策记录),而非仅依赖上下文;在压缩规则中将“决策“类型设为 protect 动作,确保不被摘要化。
适用场景与限制
上下文工程最有效的场景:长会话的复杂任务(代码重构、多文件修改)、大型代码库的日常开发、需要频繁切换上下文的项目、跨 Session 的持续开发工作。在这些场景中,合理的上下文管理能显著提升 Agent 决策的准确性和一致性,缓存机制可节省 60% 以上的 Token 消耗。
上下文工程不太有效的场景:单轮查询(如代码解释、文档查询)、极小的项目(不足 10 个文件)、Token 预算充足的简单任务。在这些场景中,上下文管理带来的收益有限,默认配置即可满足需求。
高效使用上下文工程需要满足的前提条件:对模型上下文窗口大小有准确了解;能区分“必须保留“和“可以压缩“的信息类型;有稳定的项目知识结构和文档组织;定期检查缓存命中率以优化配置;有应对上下文注入攻击的安全意识。
学习检查清单
完成本章学习后,请确认你能够:
- 解释上下文工程三层模型(压缩、缓存、预算)的核心职责
- 描述 Compaction 自动压缩机制的触发时机和保留原则
- 区分 Session 级缓存与跨 Session 缓存的应用场景
- 配置 Token 预算分配策略并说明四个区域的作用
- 说明上下文工程与约束系统、验证护栏的协作关系
关联章节
- → 约束系统解析:约束系统是上下文工程的安全补充,防止上下文被恶意利用
- → 验证护栏体系:验证护栏与上下文的交互,确保基于上下文的输出正确
- ← 简介:Harness Engineering 理论框架为上下文工程提供方法论基础
- → 高级话题:上下文工程的深入实现与调优
- → 上下文压缩与Token 预算:压缩机制的深入原理与调优
- → 上下文压缩与Token 预算:预算分配的详细策略
- → 提示词缓存机制:缓存机制的完整实现