一、引子:你的 AI 编程助手,真的"认识"你的项目吗?
用 Codex 写过几天代码的人应该都有这个感觉:刚开始用的时候特别惊艳——一句话就能生成一个函数、一个组件,甚至整个文件。但用着用着就发现一个尴尬的问题——你让它"按项目的风格写个新接口",它写出来的东西看着不像你的项目。
为什么?因为 Codex 默认只知道你当前打开的这一个文件。它不知道你的项目用什么目录结构、有没有统一的错误处理规范、API 响应格式长什么样、数据库用的是 ORM 还是裸查询。就像一个新入职的工程师,你只给他看了今天要改的那一行代码,然后指望他把整个服务重构好——这是不可能的。
AGENTS.md 就是解决这个问题的。
Codex 会读取项目根目录下的 AGENTS.md 文件,把它当作"这个项目的全局说明书"。你写在里面的规则、约定、架构信息,会影响到 Codex 的每一次代码生成和修改。
二、AGENTS.md 是什么?和 CLAUDE.md 有什么区别?
很多从 Claude Code 转过来的朋友会问:AGENTS.md 不就是 Claude Code 的 CLAUDE.md 吗?
是,也不是。
| 特性 | AGENTS.md (Codex) | CLAUDE.md (Claude Code) |
|---|---|---|
| 加载方式 | 每次对话自动加载 | 每次对话自动加载 |
| 优先级规则 | 支持 override 层级覆盖 | 不支持 override |
| 文件位置 | 项目根目录 | 项目根目录或 .claude/ |
| 支持 AGENTS.md 继承 | ✅ 子目录可覆盖父目录 | ❌ |
| 多文件规则管理 | ✅ 支持 import 拆分 | ❌ 单文件 |
| Markdown 格式 | ✅ 完整 MD 解析 | ✅ 完整 MD 解析 |
AGENTS.md 最大的优势是 层级覆盖。你可以有一个项目级的 AGENTS.md 定义全局规则,然后在 src/ 目录下放一个 src/AGENTS.md 只覆盖前端的规则,在 src/api/ 目录下再放一个只覆盖 API 层的规则。Codex 在操作某个文件时,会自动合并所有相关的 AGENTS.md。
三、AGENTS.md 怎么写?从零开始
3.1 基础结构
一个最简的 AGENTS.md 长这样:
# 项目名称
## 技术栈
- 前端:React 18 + TypeScript + Vite
- 后端:Node.js + Express + Prisma ORM
- 数据库:PostgreSQL 15
## 代码规范
- 使用函数组件 + Hooks,禁止 Class 组件
- API 响应统一格式:{ code: number, data: T, message: string }
- 错误处理使用 try-catch,禁止在业务代码中直接 throw string
- 数据库查询统一走 Prisma Service 层
就是这么简单。写清楚"这个项目是谁、它怎么做事",Codex 就能做得更好。
3.2 进阶:用好代码块和示例
Codex 对代码块的识别非常好。与其用文字描述"API 响应格式",不如直接给一个例子:
// ✅ 正确的响应格式
interface ApiResponse<T> {
code: number; // 0=成功, 其他=错误码
data: T;
message: string; // 中文描述,前端直接展示
}
// ❌ 禁止的写法
{ success: true, result: null, err: "" }
关键经验:给正例 + 反例,效果远好于只给规范文字。Codex 在大模型层面已经理解代码模式,给它对比示例比写十行约束描述更有效。
四、实战:从简单到完整
场景 1:小型个人项目(50 行以内)
# my-utils
一个轻量级工具函数库。
## 约束
- 纯函数,无副作用
- 使用 TypeScript 严格模式
- 每个函数必须有 JSDoc 注释
- 单元测试覆盖率 > 90%
场景 2:中型团队项目(10-50 个模块)
这时候需要更详细的架构说明:
# ecommerce-platform
## 项目结构
src/ ├── modules/ # 业务模块(按领域拆分) │ ├── product/ │ ├── order/ │ └── user/ ├── shared/ # 共享工具和类型 └── infrastructure/ # 基础设施(DB、缓存、消息队列)
## 开发规则
1. 新功能先写类型定义,再写实现
2. Controller 层只做参数校验和路由,业务逻辑放在 Service 层
3. 所有配置项从环境变量读取,禁止硬编码
4. Git commit 使用 Conventional Commits 格式
## 数据库规范
- 禁止在循环中执行 SQL 查询(N+1 问题)
- 复杂查询使用 Prisma 的 include/select 做预加载
- 所有表必须有 created_at 和 updated_at 字段
场景 3:大型多模块项目(50+ 模块)
这时候建议用 import 拆分:
# main-app
## 引入子规则
> 以下文件会被自动合并
- [Frontend 规则](./frontend/AGENTS.md)
- [API 规范](./api/AGENTS.md)
- [测试要求](./tests/AGENTS.md)
然后每个子目录维护自己的 AGENTS.md。这样不同层级的开发者只需要关注自己那层的规则。
五、5 个让 AGENTS.md 更好用的技巧
5.1 用"禁止"取代"避免"
| ❌ 模糊表达 | ✅ 精确表达 |
|---|---|
| "尽量避免使用 any" | "禁止使用 explicit any,使用 unknown 替代" |
| "代码尽量简洁" | "单个函数不超过 50 行,超过需拆分" |
| "注意错误处理" | "每个 API 路由必须有 try-catch + 统一错误响应" |
5.2 给出具体例子
Codex 是一个代码模型,它理解例子比理解规则好得多。每一条规范如果能配上代码示例,效果提升 3 倍以上。
5.3 定期更新 AGENTS.md
项目在演进,AGENTS.md 也得跟着更新。建议每次做架构决策或引入新工具时,同步更新 AGENTS.md。过时的规则比没有规则更糟糕——Codex 会按照过期规则生成错误的代码。
5.4 不要太长,但要够用
2000 行的 AGENTS.md 确实存在(掘金热门文就有同事写了 2000 行),但大多数项目 50-200 行就够了。太长反而让 Codex 在推理时注意力分散。浓缩出项目真正的关键约束才是核心能力。
5.5 测试你的 AGENTS.md
写完之后怎么知道它有没有效?很简单——开一个新对话,让它"用中文描述这个项目的架构和开发规范"。如果 AGENTS.md 写得好,它应该能准确说出你的技术栈、目录结构和关键约束。
六、常见陷阱
- 只写技术栈不写约束:列了一堆技术名但没说明怎么用,相当于没写
- 规则过于抽象:"高质量代码""最佳实践"这种词对 Codex 没有意义
- 忽略反例:只告诉它要怎么做,没告诉它不要怎么做
- 文件放在错误位置:AGENTS.md 必须放在项目根目录或子目录根,不能随便放
- 和 CLAUDE.md 冲突:如果同时使用 Claude Code 和 Codex,确保两个文件规则一致
七、总结
AGENTS.md 的本质不是什么神秘技术——它就是用 Codex 能理解的方式,告诉它你的项目长什么样。写好了,Codex 就不再是"一个什么都不知道的随机代码生成器",而是"一个熟悉你项目的结对编程伙伴"。
如果你还没写过 AGENTS.md,今天就可以在项目根目录创建一个,写 10 行技术栈和约束,你就会发现 Codex 的输出质量有明显提升。
关注我,后续会继续写 Codex 的进阶技巧——多 Agent 协作、自定义工具的 AGENTS.md 配置、以及与 CI/CD 的结合方案。
八、实际对比:有 AGENTS.md 和没有的区别
为了让你更直观地感受 AGENTS.md 的作用,我用一个真实场景对比:
场景:让 Codex 在 Express 项目中新增一个用户查询接口。
没有 AGENTS.md 时
Codex 可能会写出这样的代码:
router.get('/user', async (req, res) => {
const user = await db.query('SELECT * FROM users WHERE id = ?', [req.query.id]);
res.json(user);
});
看起来没问题?但在这个项目里,它有 3 个问题:SQL 裸查询(应该走 Prisma Service)、没有错误处理、响应格式不对。
有 AGENTS.md 时
如果 AGENTS.md 写清楚了规则,Codex 会生成:
import { userService } from '@/services/user.service';
import { success, fail } from '@/utils/response';
router.get('/user', async (req: Request, res: Response) => {
try {
const user = await userService.findById(req.query.id as string);
res.json(success(user));
} catch (err) {
res.json(fail(1001, (err as Error).message));
}
});
这就是 AGENTS.md 的价值——不是让 Codex 写更多代码,而是让它写对的代码。
附:一张 AGENTS.md 自检清单,写完后逐一确认:
| 检查项 | 说明 |
|---|---|
| 技术栈清单 | 框架、语言、数据库、构建工具 |
| 目录结构说明 | 核心目录的用途,方便 Codex 理解文件组织 |
| 代码规范示例 | 正例 + 反例,每种至少一个 |
| 错误处理策略 | 统一格式还是业务异常?全局捕获还是逐层处理? |
| 数据流说明 | API 请求怎么进来的,数据怎么流转 |
| 命名约定 | 文件命名、变量命名、组件命名规则 |
| 测试要求 | 用什么框架、覆盖率要求、测试位置 |
把这 7 项写进 AGENTS.md,你的 Codex 体验会有质的提升。