第三章:上下文工程 —— 让 Agent 看得见
上下文工程是驾驭工程中最基础也最容易被低估的支柱。它的核心命题很简单:
你不说,Agent 就不知道。
第一条铁律:代码仓库是唯一的真相来源
Agent 看不见什么
Agent 在运行时无法在上下文中访问的内容,对它来说就不存在:
| 你认为 Agent 知道的 | Agent 实际知道的 |
|---|---|
| Google Docs 里的架构设计 | ❌ 不存在 |
| Slack 里的技术讨论 | ❌ 不存在 |
| 你脑子里的设计偏好 | ❌ 不存在 |
| 代码仓库里的文件 | ✅ 真实存在 |
| Markdown 文档 | ✅ 真实存在 |
| 配置文件 | ✅ 真实存在 |
OpenAI 团队将代码仓库定位为记录系统(System of Record)——不仅记录代码本身,还记录代码背后的决策和意图 [1]。
信息边界的后果
Agent 的行为 = f(可见上下文, 模型能力)
上下文不足 → Agent 自由发挥 → 不可控
上下文充足 → Agent 精确执行 → 可预测
更危险的是,Agent 会忠实地复现代码库中已有的模式——包括不理想的模式:
# 如果代码库中有三种错误处理方式:
# 方式A: try/except + logging
# 方式B: 返回 None
# 方式C: raise CustomError
# Agent 会随机选择其中一种,而且觉得理所当然
# 结果:同一个模块中出现不一致的错误处理风格
文档结构设计
渐进式披露(Progressive Disclosure)
OpenAI 团队总结的关键设计原则:
Agent 从一个小而稳定的入口开始,被引导到下一步该去哪里查看,而不是一开始就被海量信息淹没。
┌─────────────────────────────────────────────────────┐
│ AGENTS.md (约100行) ← 内容目录,小而稳定的入口 │
│ ↓ │
│ ARCHITECTURE.md ← 顶层领域地图 │
│ ↓ │
│ docs/ │
│ ├── design-docs/ # 设计文档 │
│ │ ├── core-beliefs.md # 核心信念 │
│ │ └── ... │
│ ├── exec-plans/ # 执行计划 │
│ │ ├── active/ # 进行中 │
│ │ ├── completed/ # 已完成 │
│ │ └── tech-debt-tracker.md │
│ ├── product-specs/ # 产品规范 │
│ ├── references/ # 外部参考 │
│ ├── DESIGN.md # 架构设计 │
│ ├── QUALITY_SCORE.md # 质量评分标准 │
│ └── SECURITY.md # 安全规范 │
└─────────────────────────────────────────────────────┘
入口文件:AGENTS.md 模板
# AGENTS.md
## 项目概述
本项目是一个 [简要描述]。技术栈:[列表]。
## 快速开始
1. 关键架构:见 ARCHITECTURE.md
2. 编码规范:见 docs/CONVENTIONS.md
3. 执行计划:见 docs/exec-plans/active/
## 关键约束
- 依赖方向:Types → Config → Repo → Service → UI(见 ARCHITECTURE.md)
- 错误处理:统一使用 [方式],见 docs/ERROR_HANDLING.md
- 测试要求:每个新功能必须有对应测试
## 当前重点
- [当前活跃任务1]
- [当前活跃任务2]
## 详细索引
- 架构设计 → docs/ARCHITECTURE.md
- 产品规范 → docs/product-specs/
- 技术债务 → docs/exec-plans/tech-debt-tracker.md
避免大型指令文件的陷阱
OpenAI 团队踩过三个关键教训 [1]:
教训一:巨大的指令文件会适得其反。 上下文窗口是稀缺资源。几百行的 AGENTS.md 会挤掉 Agent 处理实际任务所需的空间。
教训二:过多指导等于没有指导。 当所有规则都标注为"重要"时,Agent 无法区分优先级,退化为模式匹配。
教训三:文档会腐烂。 庞大的规范手册会迅速变成陈旧规则的坟场。 Agent 无法判断信息是否仍然有效。
对比:
| 做法 | 效果 |
|---|---|
| 一个 500 行的 AGENTS.md | Agent 进行模式匹配而非理解 |
| 一个 100 行的入口 + 多个小文档 | Agent 渐进式获取所需信息 |
| 规则写在自然语言文档里 | Agent 形式遵守,实质忽略 |
| 规则编码为 linter/CI 规则 | Agent 被迫遵守,无例外 |
让 Agent 能看见运行时
静态的文档和代码只是上下文的一部分。运行时信息同样关键。
UI 可读性
将浏览器集成到 Agent 运行时中:
Agent 能力:
├── 启动应用实例
├── 生成 DOM 快照和截图
├── 执行导航操作
└── 验证 UI 行为
这意味着 Agent 可以:
├── 复现用户报告的 bug
├── 验证自己的修复是否有效
└── 直接推理 UI 行为
可观测性
为每个工作目录配备临时可观测性堆栈:
Agent 可用的查询能力:
├── LogQL → 查日志
│ "服务启动是否在 800ms 内完成?"
├── PromQL → 查指标
│ "P95延迟是否超过两秒?"
└── TraceQL → 查链路追踪
"关键路径中哪个环节最慢?"
这些能力的叠加带来了一个重要的结果:Agent 可以持续工作超过 6 小时(通常在人类睡觉的时间),因为它不需要人类来告诉它"这个改动到底有没有效果"。
面向 Agent 可读性选择技术栈
上下文工程还有一个常被忽视的维度:技术栈本身在塑造 Agent 的能力边界。
"枯燥"的技术更好用
OpenAI 团队倾向于选择可以"完全内化于仓库中进行推理"的依赖:
| 特性 | Agent 友好 | Agent 不友好 |
|---|---|---|
| API 稳定性 | 稳定,文档完善 | 频繁变动,文档缺乏 |
| 行为可预测 | 输入→输出确定 | 黑盒行为,副作用多 |
| 训练数据覆盖 | 常见技术,大量示例 | 冷门技术,示例稀少 |
| 可组合性 | 小工具组合 | 大框架约束 |
何时自己造轮子
一个具体的案例:OpenAI 团队没有引入通用的并发控制包,而是自己实现了一个带并发限制的 map 辅助函数:
# 自建实现 vs 第三方库
自建实现:
├── 与 OpenTelemetry 紧密集成 ✅
├── 100% 测试覆盖率 ✅
├── Agent 可检查、验证、修改每一行 ✅
└── 行为完全符合运行时预期 ✅
第三方库:
├── 需要理解上游行为 ❌
├── 不透明的内部实现 ❌
├── Agent 难以调试问题 ❌
└── 文档可能不完整 ❌
长时运行任务的上下文策略
进度持久化
当 Agent 需要跨越多个上下文窗口完成一个大型任务时,上下文工程面临一个新挑战:如何在上下文窗口之间传递进度?
Anthropic 工程团队在长时运行 Agent 实践中总结了一套方案 [3]:
进度持久化三层机制:
Layer 1: 结构化任务清单(feature_list.json)
├── 记录每个功能的完成状态
├── 支持多轮迭代(passes 字段)
└── Agent 每次启动时首先读取
Layer 2: 自然语言进度描述(claude-progress.txt)
├── 用自然语言描述当前进展
├── 记录遇到的问题和决策
└── 帮助下一个 Agent 快速理解上下文
Layer 3: 代码状态快照(git commits)
├── 每完成一个功能就提交
├── commit message 包含功能 ID
└── 提供可靠的回滚点
初始化 Agent 模式
传统方式:
├── 人类写需求文档 → 复制粘贴到 Agent 对话 → Agent 理解并执行
├── 问题:需求文档可能不适合 Agent 消化
└── 每次上下文重启都要重新理解需求
初始化 Agent 方式:
├── 人类写简要需求
├── 初始化 Agent(专用 Agent)将需求拆解为结构化功能清单
├── 编码 Agent 按清单逐项执行
└── 每次上下文重启时,直接读取清单,跳过理解阶段
初始化 Agent 的价值不仅仅是"拆解需求"。 更重要的是它充当了上下文压缩器——把模糊的人类需求, 压缩成 Agent 可以高效消费的结构化信息。
一次投入(初始化),多次回报(每个编码 Agent 都受益)。
ETH Zurich 的研究
ETH Zurich 的研究表明,AGENTS.md 的长度直接影响 Agent 的执行效率 [4]:
AGENTS.md 长度 vs Agent 效率:
< 60 行: Agent 执行效率最高,信息密度最优
60-150 行: Agent 效率略有下降,但仍可接受
150-300 行: Agent 开始进行模式匹配而非理解
> 300 行: Agent 几乎忽略大部分内容,退化为随机行为
原因分析:
├── 上下文窗口是稀缺资源
├── 过长的指令挤掉了实际任务所需的空间
├── Agent 无法区分优先级,所有规则都被"平等"对待
└── 信息过载 = 信息丢失
这进一步验证了渐进式披露的重要性:入口文件要极致精简,详细信息分散在小文档中。
实践指南
快速检查清单
✅ AGENTS.md 是否精简(< 150 行)?
✅ 所有架构决策是否在仓库中有文档?
✅ 编码规范是否可被工具强制执行(而非仅文档描述)?
✅ Agent 是否能访问运行时状态?
✅ 技术栈选择是否考虑了 Agent 可读性?
✅ 文档是否有自动化检查(交叉引用、新鲜度)?
渐进式建设路径
第 1 周:创建 AGENTS.md 入口 + ARCHITECTURE.md
第 2 周:编写核心规范文档(编码约定、错误处理)
第 3 周:集成运行时可观测性
第 4 周:建立文档自动化检查
持续:每次 Agent 挣扎时补充缺失的上下文
小结
✅ 代码仓库是唯一的真相来源 ✅ 渐进式披露:精简入口 + 结构化详情 ✅ 避免大型指令文件的三大陷阱 ✅ 让 Agent 能看见运行时状态 ✅ 选择 Agent 友好的技术栈
参考文献:
- [1] Ryan Lopopolo, "Harness engineering: leveraging Codex in an agent-first world", OpenAI, 2026
- [2] Birgitta Böckeler, "Harness Engineering", martinfowler.com, 2026
- [3] Anthropic Engineering, "Effective harnesses for long-running agents", anthropic.com, 2026
- [4] ETH Zurich, "Optimizing Agent Instructions for Software Engineering Tasks", 2026
下一章,我们将探讨架构约束——如何用确定性工具让 Agent 不走偏。