给 Coding Agent 的上下文文件,应该写项目事实

0阅读8分钟

上下文文件要解决的问题

2026 年初,一篇 arXiv 论文(arXiv:2602.11988)给出了一个反直觉的结论:给 Agent 提供 AGENTS.md 等仓库级上下文文件,平均将推理成本提高了 20% 以上,但并未普遍提升任务成功率。Martin Fowler 在 Context Engineering for Coding Agents 中把问题说得更精确——上下文工程的目标是找到最小的高信号 token 集合,最大化期望输出的概率

问题出在信噪比太低

我见过太多团队第一次写上下文文件,写的是「写高质量代码」「保持简洁」「注意安全」这类口号。Agent 的训练数据里有数十万个项目,它早就知道这些原则。这些信息的信息熵接近零——不携带任何新知识,却挤占了有限的上下文窗口,把 Agent 对项目规则的注意力稀释了。

上下文文件要做的事用一句话说:用项目特有的事实,替换 Agent 的通用猜测

所谓「项目特有事实」,是 Agent 凭通用训练数据猜不到的东西——你的目录结构、你的封装层路径、你的测试放哪里、你的环境变量怎么读。判别标准很简单:Agent 凭通用知识能不能推断出来? 能推断出来,写了就是噪声;推断不出来但项目需要,漏写就是隐患。

我在实际项目中反复见到这种信息缺失导致的事故:Agent 直接读 process.env 跳过项目的强类型校验封装,测试文件放在源码目录下导致 CI 采集不到覆盖率,API 请求绕过统一的鉴权和重试层。Agent 不够聪明吗?不是——它在几万个项目上学到的最常见做法,恰好与你的项目规范冲突。

根因只有一个:没有人告诉它这个项目的规矩

为什么上下文会变成噪声

那篇 arXiv 论文的数据已经表明,粗制滥造的上下文文件不仅无用,反而增加成本。拆开来看有三个层面。

信噪比:通用原则的信息熵为零

关键是「精」,不是「多」。

上下文文件写了 50 条「写高质量代码」之类的规则时,Agent 需要额外计算来过滤噪声——这些 token 信息熵接近零,不携带新知识,却消耗了上下文窗口容量,把 Agent 对项目特有规则的注意力稀释了。

认知负荷理论的映射

认知负荷类型人类开发者Coding Agent对应上下文问题
内在负荷理解业务逻辑理解任务需求和代码结构无法避免
外在负荷查找散落各处的约定从噪声规则中提取有用信息低质量上下文文件的主要危害
相关负荷构建心智模型理解项目架构和边界高质量上下文文件应该做的

口号式规则制造的就是外在负荷。Sourcegraph 的研究(Context Engineering: A Practical Guide)发现,Agent 在一个 K8s 百万行 monorepo 中 grep 出 4000 个结果后,上下文窗口被无关文件占满,根本没看到根因文件

「中间迷失」效应

Liu et al.(2023)的 "Lost in the Middle" 研究表明,LLM 对开头和结尾的信息关注度最高,中间的信息最容易被忽略。这意味着:

  • 最重要的项目约束放在文件开头
  • 次要信息放在文件结尾
  • 避免在中间塞入大量低优先级内容

Buildcamp 的 CLAUDE.md 终极指南 建议根上下文文件控制在 300 行以内,部分团队压缩到 60 行以内。LLM 能可靠遵循的指令总数约 150–200 条,系统提示词就消耗约 50 条。指令越多,每条被遵循的概率越低。

低价值 vs 高价值上下文

判别标准只有一条——Agent 凭通用训练数据能不能推断出来? 能,写了等于噪声;不能,漏写就是隐患。

低价值上下文(Agent 已知)高价值上下文(项目特有)为什么
写高质量代码TypeScript 严格模式,Biome 单引号无分号「高质量」是空话,linter 配置才是约束
保持简洁单文件不超过 500 行,超出需询问用户Agent 不知道你的「简洁」阈值
注意测试测试放 apps/tests/,不放进 apps/src/测试目录位置因项目而异
保持项目结构apps/ 是主应用,packages/ui/ 是共享组件目录结构是最容易踩坑的信息
使用环境变量不直接读 process.env,走 apps/src/config/env/Agent 不知道你有强类型封装
写好函数页面文件只做路由装配,UI 放 _components/文件职责划分是硬约束
注意安全API 请求走 apps/src/api/module,内含鉴权和重试Agent 不知道你封装了统一请求层
使用 REST 规范locale 列表放 apps/src/i18n/locales.tsAgent 凭通用 Next.js 经验一定会做错

左列是口号,右列是事实。Agent 已经知道要写好代码,但你项目里「好」的具体定义——路径、阈值、归属——才是它需要被告知的事实。

从坏到好:上下文文件演进

案例一:某电商后台项目

第一版(口号集合,有效信息为零)

# AI 编程规则
- 写高质量的代码
- 保持良好的项目结构
- 注意代码安全
- 测试要写全面
- 代码要简洁易读
- 遵循最佳实践
- 做好错误处理
- 注意性能优化

这 8 条规则,Agent 的训练数据里全有。它不会改变 Agent 的任何行为——除了增加噪声。

第二版(加入项目事实)

# 项目事实
- Monorepo 使用 pnpm + Turborepo,Node.js 22+
- `apps/web/` 是 Next.js 16 App Router 主应用
- `packages/ui/` 是共享 UI 组件库,基于 Radix UI
 
# 代码边界
- TypeScript 严格模式;Biome 配置在根目录 biome.json
- 单文件不超过 500 行,超出需询问用户
- 页面文件只做路由装配,复杂 UI 放 `_components/`
 
# 容易出错的归属
| 归属 | 错误做法 | 正确做法 |
|------|---------|---------|
| 环境变量 | 直接读 process.env | `apps/web/src/config/env.ts`(Zod 校验)|
| API 请求 | 组件内直接 fetch | `apps/web/src/api/` 模块函数 |
| 测试文件 | 放 src/ 目录 | `apps/tests/`,镜像源码目录 |
 
# 验证命令
- `pnpm verify` 运行全量检查
- 声称完成前必须运行并确认通过

从口号到事实,行数从 8 行变成 20 行,信息量从接近零变成覆盖 4 个维度。每一行都是 Agent 猜不到的项目特有约束。

案例二:分层上下文

项目变大后,一个上下文文件可能不够。Martin Fowler 建议采用渐进式上下文——根文件放全局约定,子目录放局部规则:

.claude/rules/
  api.md          # 仅在编辑 src/api/ 时加载
  database.md     # 仅在编辑 src/db/ 时加载
  testing.md      # 仅在编辑测试文件时加载

api.md 示例:

---
paths:
  - "src/api/**/*.ts"
---
 
# API 层规则
- 所有接口使用 `createApiHandler` 包装
- 输入校验统一用 zod schema,定义在 `_schemas.ts`
- 错误响应使用 `AppError` 类(code、message、statusCode)
- 鉴权信息从 `ctx.auth` 读取,不手动解析 JWT

paths 字段让规则只在编辑匹配文件时加载。编辑 UI 组件时,Agent 不需要看到 API 层规则,上下文窗口留给相关信息。

案例三:一条规则的打磨

Agent 直接读 process.env 是高频踩坑场景。我见过团队最初只写「不要直接读 process.env」——Agent 仍然会用 process.env,因为它知道这个 Node.js API。后来改成同时给出错误做法和正确做法,Agent 才稳定走封装路径:

| 归属 | 错误做法 | 正确做法 |
|------|---------|---------|
| 环境变量 | 直接读 process.env.PAYMENT_SECRET_KEY | 从 `@/config/env` 导入 env.PAYMENT_SECRET_KEY |

教训:告诉 Agent 不要做什么不够,必须同时告诉它应该做什么,具体到 import 路径。

上下文文件维护流程

上下文文件会影响每一次 Agent 任务,过期内容会让 Agent 稳定地犯同一种错。我推荐的维护流程:

流程图画布 · 115%
Mermaid 流程图加载中...

关键节点是Agent 踩坑后的反馈循环。每次 Agent 做出让你皱眉的决策,都应该回溯上下文文件,检查是否有缺失的规则。这和事后复盘(Post-mortem)是同一个思路——目的是把教训固化为系统约束。

常见踩坑点

踩坑点后果正确做法
规则互相矛盾Agent 随机选择,行为不稳定全局只保留一个权威来源
/init 自动生成充斥通用原则,噪声大于信号逐行手写,每条经过思考
过期命令残留Agent 运行错误命令技术栈变更后全文搜索检查
规则太抽象Agent 无法执行,等于没写具体到路径、阈值、反例
文件超过 500 行中间信息被忽略控制 300 行以内,用 scoped 规则分担
只说「不要」Agent 不知道替代方案同时给出正确做法
复制网上模板引入无关规则每条必须验证是否适用

上下文文件 vs 提示词 vs Hooks

维度上下文文件提示词Hooks / Linter
时效长期稳定,跨任务复用一次性,针对当前任务自动化,每次触发
内容项目事实、边界、命令目标、约束、验收标准可执行的检查规则
可靠性Agent 可能忽略Agent 可能忽略强制执行,无法绕过
适用场景项目级约定、架构边界任务描述、临时约束格式、命名等可自动检查的规则

一个关键认知:上下文文件里的规则本质上是「请求」,不是「约束」。Agent 可能忽略它。2026 年的最佳实践是每条规则都配有自动化执行层——上下文文件告诉 Agent 应该怎么做,Hooks 和 Linter 确保即使 Agent 没遵守也会被纠正。

// .claude/settings.json
{
  "hooks": {
    "stop": [{
      "command": "pnpm lint:fix && pnpm format",
      "description": "Agent 完成后自动修复格式和 lint"
    }]
  }
}

规则放在上下文文件,执行交给自动化——比纯靠 Agent 自律可靠得多。

可直接复用的模板

# 项目事实
- <包管理器> + <构建工具>;<运行时版本>
- <主应用目录> 是 <框架> <版本> <路由模式>主应用
- 常用命令:<dev>、<verify>、<lint>、<typecheck>
 
# 代码边界
- <语言><严格模式>;<Linter> 配置在 <路径>
- 单文件不超过 <N> 行,超出需询问用户
- 页面文件只做路由装配;复杂 UI 放到 <路径>
 
# 容易出错的归属
| 归属 | 错误做法 | 正确做法 |
|------|---------|---------|
| <易错项1> | <错误选择> | <正确路径> |
 
# 验证与交付
- 声称完成前,必须运行 <验证命令> 并确认通过

尖括号是需要替换为项目事实的位置。不要保留任何模板默认值——通用占位符只会增加噪声。

检查清单

写之前

  • 扫描 package.json,确认技术栈、包管理器、命令
  • 画出目录结构树,标注每个目录的职责
  • 列出最近 3 次 Code Review 中 Agent 或新人犯过的错误
  • 确认项目是否有统一封装层(API 请求、环境变量、鉴权等)

写的时候

  • 每条规则都问:Agent 凭通用知识能不能推断出来?
  • 能用路径说明的不用抽象描述
  • 能给出反例的给出反例(错误做法 → 正确做法)
  • 根文件控制在 300 行以内
  • 最重要的约束放在文件开头

写之后

  • 用一条新任务测试 Agent 是否遵循规则
  • 配置至少一条 Hook 自动执行最关键的规则
  • 设置日历提醒,每个迭代结束后检查文件是否过期

写在最后

我花了不少时间和 Agent 打交道之后才意识到:上下文文件是让 AI 编程从「聪明猜测」变成「受约束地推进」的基础设施。

2026 年的研究已经表明:更多的上下文不等于更好的结果。arXiv 论文证明粗制滥造的上下文文件增加 20% 成本,Martin Fowler 提出信噪比原则,Sourcegraph 展示精确检索比暴力搜索快 50 倍。

按本文原则重写上下文文件后,Agent 在环境变量访问、测试目录归属等高频场景的错误率显著下降。花两个小时把上下文从口号换成项目事实,回报是后续每次 Agent 任务都不再重复踩同样的坑。

下次写上下文文件时,先问自己:

这条规则是 Agent 已经知道的通用原则,还是我们项目特有的边界?

前者,删掉。后者,写具体到路径和反例。


参考资料

评论 0

0 / 1000