Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

第三章:上下文工程 —— 让 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.mdAgent 进行模式匹配而非理解
一个 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 重新实现一个功能子集,比让它绕过不透明的第三方库的上游行为 更便宜、更可靠。

长时运行任务的上下文策略

进度持久化

当 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 挣扎时补充缺失的上下文

小结

上下文工程 Checklist

✅ 代码仓库是唯一的真相来源 ✅ 渐进式披露:精简入口 + 结构化详情 ✅ 避免大型指令文件的三大陷阱 ✅ 让 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 不走偏。