尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

【技术教程】AI Coding原生契约开发文档教程:用 AGENTS.md 与 Codex 落地契约驱动开发

【技术教程】AI Coding原生契约开发文档教程:用 AGENTS.md 与 Codex 落地契约驱动开发 1. 为什么你的 Codex 总在“自由发挥”如果你正在用 Codex 这类 AI 编码工具做项目大概率遇到过这种场景你给了一句“帮我写个登录接口”它噼里啪啦生成了一堆代码字段命名跟你项目里已有的风格完全对不上错误码格式也自成一派甚至数据库表名都给你改了。你 Review 的时候血压升高改完一遍下次让它加个“积分商城”它又把之前定好的用户表结构给“优化”了。这不是 Codex 不行而是你给它的输入太“软”了。自然语言需求天然有歧义AI 只能靠猜。猜对了是运气猜错了是常态。契约驱动开发Contract-Driven Development要解决的就是这个问题把 PRD 里模糊的“用户能登录”变成 AI 可以直接读取、逐条执行的硬约束——字段名、接口路径、错误码、目录结构全部写死在文档里。Codex 只负责在契约框架内填充实现人负责定义边界和验收。这套方法特别适合两类人一是用 Codex 做快速原型但苦于代码越写越乱的独立开发者二是团队里想把 PRD 转成可执行契约、让 AI 输出可追溯可回归的工程团队。核心载体就是AGENTS.md——它不是普通的说明文档而是 Codex 每次启动都要读取的“操作手册”和“行为契约”。下面我从零开始把 AGENTS.md 的骨架、Codex 的配置片段、契约校验命令以及从 PRD 到契约文件的完整验证动作一步步拆给你看。2. 前置准备TaoToken 接入与 Codex 环境在写 AGENTS.md 之前得先让 Codex 能稳定跑起来。我实测下来用 TaoToken 做模型接入层比较省心它兼容 OpenAI 风格的接口Codex 配置里改个 base_url 就能用不用折腾网络层。2.1 获取 API Key打开 TaoToken 控制台进入 API Keys 页面创建一个新 Key。建议按项目维度创建比如codex-contract-demo方便后续排查用量。创建后立即复制保存页面刷新后就不再完整显示。注意API Key 只存到环境变量或本地.env文件不要硬编码进 AGENTS.md 或提交到 Git。2.2 配置 Codex 的模型端点Codex 的配置文件通常在~/.codex/config.tomlLinux/macOS或%USERPROFILE%\.codex\config.tomlWindows。把模型提供方指向 TaoToken 的 API 地址# ~/.codex/config.toml model gpt-4o model_provider taotoken [model_providers.taotoken] name TaoToken base_url https://taotoken.net/api env_key TAOTOKEN_API_KEY wire_api chat然后在 shell 里导出环境变量export TAOTOKEN_API_KEYsk-你的KeyWindows PowerShell 用$env:TAOTOKEN_API_KEYsk-你的Key。配置完成后Codex 的所有请求都会走 TaoToken 的 API 端点模型对话和代码生成共用同一个 Key。2.3 验证连通性先跑一个最小请求确认链路通curl https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -H Content-Type: application/json \ -d { model: gpt-4o, messages: [{role: user, content: 回复 OK}] }返回 JSON 里choices[0].message.content包含 “OK” 就说明接入正常。这一步别跳过后面 Codex 报错时你能快速判断是契约问题还是接入问题。3. AGENTS.md 契约骨架让 Codex 有据可依AGENTS.md 放在项目根目录Codex 每次会话启动时会自动读取。它的作用不是“介绍项目”而是“约束行为”。我踩过的坑是一开始把 AGENTS.md 写成 README 风格结果 Codex 该犯的错一个没少。后来改成“规则 契约 禁止项”三段式效果立竿见影。3.1 完整 AGENTS.md 骨架# AGENTS.md — 契约驱动开发操作手册 ## 一、项目身份 - 项目名contract-demo - 技术栈Node.js 20 TypeScript 5 Prisma PostgreSQL - 包管理器pnpm禁止使用 npm/yarn - 代码风格ESLint Prettier缩进 2 空格单引号 ## 二、契约文件优先级 当以下文件存在冲突时按此顺序取最新 1. /docs/ARCHITECTURE.md接口与数据模型契约 2. /docs/PRD.md需求与验收标准 3. /docs/TASK_PLAN.md任务拆解 4. 本文件 AGENTS.md行为规则 ## 三、硬性规则 - 规则 1收到修改指令时先检查 /changes 下是否有对应 CR-*.md。若无不得修改任何代码必须反问“请先创建变更申请单”。 - 规则 2每次生成代码后对比 /reviews/REVIEW_RECORD.md 中的典型错误自检命中则修正后再输出。 - 规则 3所有数据库字段名使用 snake_caseAPI 响应字段使用 camelCase转换在 service 层完成。 - 规则 4日期一律存 UTC禁止在数据库层做时区转换。 ## 四、禁止行为 - 禁止引入 ARCHITECTURE.md 未定义的第三方依赖 - 禁止修改 /docs 下任何契约文件只能人改 - 禁止在 controller 层直接操作数据库 - 禁止使用 any 类型未知类型用 unknown 类型守卫 ## 五、常用命令 - 安装依赖pnpm install - 生成 Prisma Clientpnpm prisma generate - 迁移pnpm prisma migrate dev --name name - 测试pnpm vitest run - 契约校验pnpm contract:check ## 六、身份指令 你只负责实现我是架构师。任何逻辑冲突以 /docs 下最新文档为准 若文档冲突停止编码并向我提问。这份骨架的关键在于“规则 1”和“规则 2”——它们把变更纪律和审查反哺写进了 Codex 的每次会话上下文。Codex 不会“记住”上一次对话但每次启动都会读 AGENTS.md所以规则必须写在这里而不是写在聊天记录里。3.2 配套的契约文件最小集AGENTS.md 是行为契约还需要数据契约和任务契约配合。在/docs下建三个文件!-- /docs/ARCHITECTURE.md 片段 -- ## 用户表 users | 字段 | 类型 | 约束 | |------|------|------| | id | uuid | PK, default gen_random_uuid() | | email | varchar(255) | unique, not null | | password_hash | varchar(255) | not null | | created_at | timestamptz | default now() | ## 接口 POST /api/v1/auth/login 请求{ email: string, password: string } 响应 200{ token: string, expiresIn: number } 响应 401{ code: AUTH_FAILED, message: string }!-- /docs/TASK_PLAN.md 片段 -- - [ ] Task 1.1 初始化 Prisma schema建 users 表 - [ ] Task 1.2 实现 POST /api/v1/auth/login - [ ] Task 1.3 编写登录接口的 vitest 用例Codex 提示词模板可以这样写根据 /docs/ARCHITECTURE.md 中 users 表定义和 POST /api/v1/auth/login 接口契约 以及 /docs/TASK_PLAN.md 的 Task 1.2实现登录逻辑。 严格遵循 AGENTS.md 的字段命名和分层规则无需额外解释。4. 契约校验从 PRD 到可执行验证文档写完了怎么保证 Codex 生成的代码真的符合契约靠人眼 Review 太慢得让校验自动化。核心思路是把 ARCHITECTURE.md 里的接口定义转成机器可读的 OpenAPI 片段再用脚本比对实际路由和响应结构。4.1 契约校验脚本在项目里建scripts/contract-check.tsimport { readFileSync } from fs; import { parse } from yaml; import { z } from zod; // 从 ARCHITECTURE.md 提取的契约实际项目可用 openapi.yaml const LoginResponse z.object({ token: z.string(), expiresIn: z.number(), }); const LoginError z.object({ code: z.literal(AUTH_FAILED), message: z.string(), }); async function checkLoginContract(baseUrl: string) { // 正常路径 const okRes await fetch(${baseUrl}/api/v1/auth/login, { method: POST, headers: { Content-Type: application/json }, body: JSON.stringify({ email: testexample.com, password: correct }), }); const okJson await okRes.json(); LoginResponse.parse(okJson); console.log([PASS] 登录成功响应符合契约); // 错误路径 const failRes await fetch(${baseUrl}/api/v1/auth/login, { method: POST, headers: { Content-Type: application/json }, body: JSON.stringify({ email: testexample.com, password: wrong }), }); const failJson await failRes.json(); LoginError.parse(failJson); console.log([PASS] 登录失败响应符合契约); } checkLoginContract(http://localhost:3000).catch((e) { console.error([FAIL] 契约校验不通过:, e.message); process.exit(1); });在package.json里加一行{ scripts: { contract:check: tsx scripts/contract-check.ts } }这样 AGENTS.md 里写的pnpm contract:check就真正可执行了。Codex 生成代码后你跑一次校验不符合契约直接打回不用逐行看。4.2 从 PRD 到契约文件的验证动作PRD 里的用户故事是“作为用户我希望能用邮箱密码登录以便访问个人中心”。转成契约的步骤第一步在 ARCHITECTURE.md 里把“登录”拆成接口路径、请求字段、响应字段、错误码。第二步在 TASK_PLAN.md 里拆成可独立执行的任务单元。第三步把验收标准写成 zod schema 或 OpenAPI 片段放进校验脚本。第四步让 Codex 按契约实现跑pnpm contract:check验证。如果校验失败把失败信息贴回给 Codex并附上 AGENTS.md 的规则 2 让它自检。实测下来两轮之内基本能收敛。5. 本篇常见错排查5.1 Codex 不读 AGENTS.md 怎么办先确认文件在项目根目录且文件名大小写正确AGENTS.md不是agents.md。Codex 只在会话启动时读取一次如果你在会话中途改了 AGENTS.md需要重启会话。另外检查config.toml里有没有设置project_doc_max_bytes如果项目文档总大小超过这个值AGENTS.md 可能被截断。默认值通常够用但如果你在/docs下堆了太多文件建议精简或调大。5.2 契约校验报字段类型不匹配最常见的是数据库返回created_at是 Date 对象JSON 序列化后变成 ISO 字符串但契约里写的是number时间戳。统一在 ARCHITECTURE.md 里约定所有时间字段对外一律 ISO 8601 字符串。另一个坑是expiresIn单位不统一契约写秒代码返回毫秒。这类问题在契约里写清楚单位校验脚本就能拦住。5.3 Codex 绕过 CR 直接改代码说明 AGENTS.md 的规则 1 没被严格执行。检查两点一是规则 1 是否在 AGENTS.md 的“硬性规则”章节靠前位置二是你的提示词里有没有明确说“先检查 /changes”。如果 Codex 仍然直接改可以在提示词末尾追加“若 /changes 下无对应 CR 文件只输出提醒不输出代码。” 把这条也写进 AGENTS.md 的规则 1 里双保险。5.4 接入层报 401 或超时先跑第 2.3 节的 curl 命令确认 Key 有效。如果 curl 通但 Codex 不通检查config.toml里env_key的名字和实际环境变量名是否一致。TaoToken 的 API 地址是https://taotoken.net/api注意不要多加/v1后缀导致路径重复。如果遇到超时检查本地网络环境是否能正常访问该域名必要时在 Codex 配置里加request_timeout_ms 60000。6. 把契约变成 Codex 的肌肉记忆这套方法跑通之后你会发现 Codex 的输出质量跟“有没有契约”强相关。没有 AGENTS.md 的时候它像一个聪明但没规矩的实习生有了 AGENTS.md 和配套的 ARCHITECTURE.md、TASK_PLAN.md它更像一个按图施工的工程队。变更走 CR 申请单审查记录进 REVIEW_RECORD.md契约校验用pnpm contract:check卡住回归——整条链路是可追溯的。如果你还没配好 Codex 的接入层可以先到 TaoToken 的 API Keys 页面创建一个 Key再对照第 2 节的配置片段把config.toml改好。模型对话和代码生成共用同一个端点调试起来比较顺手。长期做编码和 Agent 任务的话Coding Plan 的额度模型比按次调用更划算适合把契约驱动开发变成日常流程。接入文档里有完整的参数说明和示例遇到配置问题可以直接对照排查。
返回列表