
上个月我把一个内部用的任务管理系统从零重写了一遍全程几乎没有手动打开编辑器去敲业务代码靠的是一份 400 行左右的规格文档加上 Codex 在终端里来回跑。说句实话最早我也觉得让 AI 写全栈项目是玄学但真正把规格驱动开发Spec-Driven Development, SDD这套方法跑顺之后效率提升是实打实的。这篇文章就把我的完整思路、Spec 写法、Codex 实操流程和踩过的坑整理出来。这篇文章适合准备用 AI 提效的全栈开发者、技术负责人以及想从用 AI 写脚本升级到用 AI 做完整项目的独立开发者。你不需要有很深的前端或后端功底但至少要知道 REST API、数据库、React 和 FastAPI 大概是什么。我会用一个具体的团队任务看板项目做例子从安装 Codex 开始到前端联调结束完整拆一遍。1. 为什么先写规格再让 AI 写代码能成事1.1 传统全栈开发的效率瓶颈做过全栈项目的人都有体会最耗时间的往往不是代码本身而是需求传递过程中的信息损耗。产品口述一个想法你理解成 A后端理解成 B前端理解成 C等前后端联调的时候发现接口对不上又回头改。这个来回沟通的成本在小团队里尤其明显。以前我们处理这个问题靠的是需求文档加接口文档但大部分团队的需求文档写得极其抽象基本都是用户可以登录系统、实现任务的增删改查。这种描述对人有模糊的指引作用人脑能脑补出很多上下文但落到代码层面每个人脑补的内容都不一样。AI 编程工具出现之后很多人觉得问题解决了直接跟 ChatGPT 说帮我做一个任务管理系统结果生成的代码看起来像模像样但跑起来全是问题没有权限控制、数据库设计不合理、接口没做异常处理、前端页面样式错位。原因很简单——模型不是产品经理它不会替你把需求边界、数据结构、交互细节全部补齐。你给它的输入越模糊它给你的输出就越随机。1.2 规格驱动开发让需求变成可执行的工程契约规格驱动开发的核心思想是把需求升级为规格也就是把一句模糊的话拆成一个可以被验证的工程契约。规格里包含功能描述、数据模型、接口契约、页面路由、交互流程、验收标准。它比需求文档更接近代码但比代码更接近业务。打个比方你跟施工队说我要一栋楼施工队只能凭经验给你发挥。但如果你给出一份施工图上面标了层高、房间数量、承重墙位置、水电管线走向施工队就能按图施工。Spec 就是这张施工图。人看施工图能干活AI 看施工图也能干活而且 AI 比人更需要施工图。这里有个很重要的点AI 模型本质上是按指令生成的概率引擎你给它清晰的指令它能在指令约束下做得很漂亮你给它含糊的需求它就会把训练数据里出现频率最高的方案拿过来用。规格驱动开发的价值就是让 AI 从自由发挥变成按图施工。1.3 Codex 在全栈链路里的定位Codex 是 OpenAI 推出的 AI 编程智能体它不是一个简单的代码补全插件而是以 Agent 的方式在终端里运行。你给它一个任务它能读取项目目录下的文件、创建新文件、修改已有代码、执行命令行工具、安装依赖、运行测试然后根据测试结果自我修正。这和 Copilot 那种你在编辑器里写代码它给你补全下一行的模式完全不一样。Copilot 是辅助驾驶Codex 更像一个能听懂指令的初级工程师你告诉它实现这个模块、跑一下测试、修掉报错它会自己迭代。更关键的是Codex 在做全栈任务时能跨文件操作它知道改了后端接口之后前端对应的请求代码也要跟着改这是普通代码补全工具做不到的。所以我的定位很简单Spec 是蓝图Codex 是施工队我是监理。我不需要亲手搬每一块砖但我要确保图纸没问题并且验收每一道工序。2. 写一份能被 Codex 执行的 Spec关键在哪儿2.1 Spec 该包含哪些模块很多人写 Spec 的时候容易走极端要么就写三句话要么直接写几千字的需求说明书。我的经验是一份面向 Codex 的 Spec 至少应该包含八个模块项目目标与范围、技术栈、数据模型、API 契约、页面与路由、交互流程、验收标准、非功能性要求。项目目标与范围用来约束 AI 别跑偏。比如这个项目的目标是做一个团队内部使用的任务看板不包含团队管理功能AI 就不会自作主张加一套用户角色权限系统进去。技术栈是硬约束前后端各用什么框架、数据库用什么、ORM 用什么必须写死。数据模型和 API 契约是 Spec 的核心它们直接决定了前后端能不能对上。我习惯在 Spec 里把每个实体的字段、类型、约束都写清楚再把每个接口的路径、方法、请求参数、响应结构、错误码列出来。页面与路由则是给前端部分的指令告诉 Codex 需要实现哪几个页面、每个页面大概长什么样、路由怎么映射。交互流程描述的是用户在页面上做了某件事之后系统应该怎么响应比如用户点击新建任务按钮后弹出表单提交成功后新任务出现在待处理列顶部。这看起来像需求文档但它能有效防止 AI 把新建任务做成一个独立页面而你要的其实只是一个弹窗。2.2 把验收标准写成 Codex 可以自检的条目验收标准是整个 Spec 里最有价值的部分因为它能把做完了从主观判断变成客观验证。大多数 AI 编程工具跑偏不是因为它能力不行而是因为你觉得自己说清楚了但模型其实不知道什么算完成。好的验收标准不是按钮要好看或者页面要流畅而是具体的、可执行的断言。举个例子与其写任务状态可以修改不如写向 POST /api/tasks 发送一个合法的 JSON 请求返回状态码 201且响应体包含一个 id 字段。使用未登录状态访问 /dashboard系统跳转到 /login 页面。在浏览器中拖拽一个任务卡片到已完成列重新刷新页面该任务依然停留在已完成列。这些验收标准可以直接交给 Codex 去执行——它可以运行接口测试、写 pytest 用例、启动前端做基本冒烟测试。当 Codex 说做完了的时候你可以直接用验收标准去检验它而不是靠肉眼判断页面能不能打开。2.3 Spec 的粒度与边界Spec 粒度太粗AI 的自由发挥空间过大结果不可控粒度太细写 Spec 的时间比写代码还长失去提效意义。我踩过几次坑之后总结的规律是核心业务闭环写细边缘功能写粗。一个项目的核心闭环就是那些没有它产品就不成立的链路比如任务看板里的创建任务、查看任务、修改状态、登录校验。这部分的数据模型、接口、交互必须完整写清楚每个字段都不能含糊。而像关于我们页面、404 页面、头像上传这种边缘功能一句话带过就行AI 发挥空间大反而可能给你惊喜。另外不要把 Spec 写成一次性文档。我会把 Spec 当作活文档和代码一起提交到仓库里。Codex 每完成一个阶段我就把已经实现的细节从待办挪到已完成同时把联调中发现的新需求补进待办。这样 Spec 会随着项目演进越来越准确后面的 AI 任务也会越来越顺手。3. 实操流程我用 Codex 从零生成一个团队任务看板3.1 环境准备安装 Codex 并完成身份验证先交代一下我的实验环境一台 macOS 设备安装了 Node.js 20 和 npm。Codex 官方推荐通过 npm 全局安装命令很简单npm install -g openai/codex安装完成之后用codex --version验证一下是否成功。如果之前装过老版本记得先npm update -g openai/codex因为 Codex 迭代很快旧版本可能不支持最新的模型参数。接下来是身份验证。Codex 支持 ChatGPT 账号登录也支持 API 凭证方式具体用哪种取决于你想用哪个模型。运行codex login会弹出浏览器授权页面扫码或者登录账号之后终端里会显示鉴权成功。如果你用的是 API 凭证则通过环境变量设置密钥例如在 shell 配置文件中写入export OPENAI_API_KEY你的密钥。这里提醒一下新人Codex 在真正执行任务时需要 CLI 能够访问到模型服务。如果你所在的网络环境无法直接连通服务请先自行解决基础连通性问题再继续使用。国内也有一些模型服务商提供了兼容的接口可以通过 Codex 的模型配置项接入具体参考官方文档这里不展开。3.2 先写一份能落地的最小规格安装完 Codex别急着让它写代码先写规格。我管这叫最小可用规格——一份能支撑第一个可运行版本的文件。拿团队任务看板来说我的 spec.md 长这样# 项目团队任务看板 ## 技术栈 - 后端Python FastAPI SQLite SQLAlchemy - 前端React Vite Tailwind CSS - 认证JWT ## 数据模型 Task: id: int, 主键, 自增 title: str, 必填, 最大 200 字符 status: str, 枚举(PENDING/DOING/DONE), 默认 PENDING owner: str, 必填 created_at: datetime, 默认当前时间 ## API 契约 POST /api/auth/login 请求体: { username, password } 响应: { token } 校验: 用户名与密码正确时返回 JWT GET /api/tasks 请求头: Authorization: Bearer token 响应: Task[] 校验: 未携带 token 返回 401 POST /api/tasks 请求头: Authorization: Bearer token 请求体: { title, owner, status? } 响应: Task 校验: title 为空返回 422 PATCH /api/tasks/{id} 请求头: Authorization: Bearer token 请求体: { status } 响应: Task 校验: 只能修改 PENDING 为 DOING/DONE ## 页面与路由 /login 登录页提交表单后保存 token 并跳转 /dashboard /dashboard 看板页按 status 分为三列展示任务卡片 ## 交互流程 1. 未登录访问 /dashboard前端拦截并跳转 /login 2. 新建任务点击按钮弹出表单提交后刷新当前列 3. 修改状态卡片上提供下拉选择框选择后立即调用 PATCH 接口 ## 非功能性要求 - 前后端分别提供统一错误提示 - 密码在数据库中存储时要用哈希这份 Spec 大概 40 行信息密度很高。Codex 拿到它之后理论上不需要再问任何问题就能把项目骨架搭出来。这也是我反复强调规格优先的原因——你在 Spec 上花的每一分钟都是在帮 AI 减少一次瞎猜。3.3 分阶段让 Codex 生成后端代码Spec 写完之后进入目录把 spec.md 放进去然后开始给 Codex 下达第一个任务。我的习惯是分阶段执行先后端再前端绝不让它在一次任务里同时生成两个端否则上下文一长前后端很容易出现契约对不上的情况。第一个任务命令大致长这样codex 阅读 spec.md使用 FastAPI 实现后端全部接口。要求创建虚拟环境、编写数据模型、实现 JWT 认证、实现三个 API 端点、编写 pytest 测试覆盖 Spec 中的验收标准、运行测试直到全部通过。Codex 的执行过程是这样的先读取 spec.md然后扫描当前目录下的文件结构接着就开始创建后端目录、安装依赖、写代码、写测试、运行测试。中间如果出现依赖版本冲突或者测试失败它通常会自动修复实在修不了会停下来向你提问。这里我要强调一个很多人忽略的点不要一次性把全部需求塞给 Codex。比如实现后端、实现前端、再启动服务做联调这种大而全的任务Codex 虽然也能硬着头皮做但越到后面越容易顾此失彼。我倾向于一个阶段只让它做一个完整的功能块做完了验收验收通过再进入下一个阶段。就像带初级工程师一样你不可能让他一天把所有事都干完还得保证质量。3.4 再让 Codex 生成前端并完成联调后端跑通测试之后我给 Codex 的第二个任务是前端codex 阅读 spec.md 和已存在的 backend 目录使用 React Vite Tailwind CSS 实现前端。要求创建前端项目、实现登录页、实现看板页、封装 API 客户端、处理 token 存储、配置路由守卫运行构建命令确保无类型错误。注意这里我让 Codex 阅读已存在的 backend 目录这是一个关键技巧。前端代码需要知道后端返回的确切数据格式与其让 Codex 去猜不如直接让它去读后端代码。Codex 作为 Agent 有这个能力它能把后端的数据模型和接口响应结构提取出来生成的前端接口调用代码会更准确。前后端都生成完之后通常需要联调。我把联调也当成一个独立任务交给 Codex命令大概是启动后端服务启动前端开发服务器使用 curl 模拟登录并调用任务接口确认 CORS 配置正确修复发现的问题。 Codex 会实际去跑命令、看日志、改代码整个过程我就是在旁边看着它每改完一轮我就在浏览器里手动点一点。联调中最容易出问题的就是 CORS 和 token 存储位置。Codex 生成的 FastAPI 后端默认可能没有配置 CORS 中间件而 Vite 开发服务器默认跑在 5173 端口后端跑在 8000 端口跨域请求直接被浏览器拦截。遇到这种问题只要把报错信息贴给 Codex它一般能自己加上 CORSMiddleware 并配置允许的源。4. 用 Codex 和 Spec 时最容易踩的五个坑4.1 Spec 写得模糊AI 就会自由发挥很多第一次尝试规格驱动开发的人Spec 写得太像需求文档。比如任务状态可以修改这句话至少有三种实现方式下拉选择框、拖拽卡片、点击状态循环切换。你如果不写清楚AI 大概率会选一个它认为最合理的但大概率不是你想要的。后来我的规矩是凡是涉及交互方式的描述一律在 Spec 里明确写死。你想要下拉选择框就直接写卡片上提供下拉选择框选择后立即调用 PATCH 接口不带任何歧义。如果某个需求你自己都没想清楚那就先别写进 Spec因为你都没想清楚的事AI 更想不清楚。Spec 驱动的第一原则就是你自己脑子里的图越清晰AI 手里的活越靠谱。4.2 上下文太长Codex 干到一半失忆Codex 虽然能处理很长的上下文但它仍然有窗口上限。当你把整个项目源码、Spec、依赖清单、历史对话一股脑塞给它的时候它就会出现类似codex ran out of room in the models context的报错。这个报错的意思是上下文窗口满了模型已经没有余力再接受新的输入。解决这个问题核心思路是拆。不要把整个项目当成一个任务而是把项目拆成若干个可以独立验收的子任务。子任务之间通过代码仓库本身建立联系Codex 在子任务开始时只需要重新读取关键文件不需要把所有历史对话都带着。另外留意项目中是否有大量不必要的文件被 Codex 扫描比如 node_modules、编译产物、日志文件把它们加进 ignore 列表能有效减少上下文占用。4.3 模型选择与账号限制Codex 默认会使用 OpenAI 的某个模型但并不是所有账号都能用所有模型。用 ChatGPT 订阅账号登录时如果指定的模型不在账号可用范围内会看到类似the gpt-5.6-sol model is not supported when using Codex with a ChatGPT account的报错。遇到这个报错第一件事是确认你登录的是哪类账号ChatGPT 订阅和 API 账号能用的模型范围是不一样的。第二件事是查看 Codex 的配置看它当前指定的模型名是不是一个默认值你可以把模型改成一个当前账号支持的版本。Codex 也支持通过环境变量指定第三方兼容模型服务如果你用的是国内模型服务商提供的兼容接口按官方文档配置模型地址和模型名即可。这不算什么高端操作但能解决很多人为什么我跑不起来的困惑。4.4 依赖版本解析错误Codex 在生成项目的过程中会自动安装依赖但它生成的依赖版本约束偶尔会出问题。比如你在 Spec 里写Python 版本 2.7或者模型自动生成了不规范的版本号pip 在解析时就会抛出Invalid version spec: 2.7这类错误。这类问题的根源往往是版本约束格式不对比如把2.7写成了2.7或者把1.0,2.0写成了别的非法表达式。我的建议是重要依赖在 Spec 里直接锁定版本比如写FastAPI0.115.0、SQLAlchemy2.0.30不给 AI 自由发挥的空间。另外很多 Python 开发者提到 spec 会联想到 PyInstaller 的 .spec 打包脚本那个 spec 是构建配置和需求规格文档完全不是一回事注意别混在一起讨论。4.5 网络连接与模型服务不可用Codex 在执行任务时依赖云端模型服务如果网络环境不稳定或者本机防火墙拦截了 Codex 的请求就会表现为长时间没有响应甚至直接报连接错误。这种问题通常和代码本身无关先检查基础网络连通性、防火墙规则、模型服务的可用状态。我自己的排查顺序一般是先 ping 一下服务域名看网络通不通再确认是不是当前网络环境限制了外部服务的访问接着看 Codex 有没有输出更详细的日志。如果是临时性网络抖动重试一次就好如果是服务商那边的问题可以去状态页看看有没有公告。记住这类问题不要盲目去改项目代码先定位是哪一层的故障否则很容易在错误的方向上浪费大量时间。5. 规格驱动开发的人机协作心得5.1 我踩过几次坑之后的习惯现在我做 AI 全栈开发流程已经非常固定先是写 Spec然后分阶段让 Codex 干活每干完一个阶段我都要做一次验收验收不过就把问题回填到 Spec 里再让它继续改。有一个细节很值得分享我从不让 Codex 直接改 Spec哪怕它觉得自己发现了 Spec 里的问题。原因很简单Spec 是需求方的意图表达需求不该被实现方随意修改。Codex 如果觉得某个接口设计不合理它可以提出来但改不改由我决定。这样能避免一个很可怕的情况——AI 为了实现方便悄悄把需求改成了它擅长的样子。5.2 什么项目适合用这套方法规格驱动开发加 Codex 的组合最适合的是 CRUD 为主的中小型全栈应用包括内部管理后台、MVP、原型验证、自动化工具。这类项目业务逻辑清晰、技术栈通用、验收标准容易量化正是 Codex 最擅长的领域。不太适合的场景我也要如实说强实时、高并发、复杂算法、历史遗留大仓改造这些场景目前还不适合完全交给 AI。Codex 在理解全局架构和性能瓶颈方面还达不到资深工程师的水平。越是涉及资金、人身安全、强合规的领域人工审查越是不能少。AI 是提效工具不是免责声明。5.3 后续还可以怎么扩展这套流程跑通之后可以往几个方向扩展。一是把 Spec 和 CI/CD 集成代码生成后自动跑测试和静态检查质量门禁前置。二是用 Spec 驱动多人协作的接口联调把 Spec 作为前后端唯一的沟通契约减少开会扯皮。三是沉淀自己的 Spec 模板库把常见业务类型的数据模型、接口模式、页面结构固化成模板下次做类似项目时直接套。如果你有团队还可以试试把 Spec 的评审纳入开发流程让前端、后端、测试都参与 Spec 评审而不是评审代码。毕竟代码是速朽的而规格是整个项目的地基。地基稳了谁来写代码都差不到哪里去。最后再分享一个小技巧每次让 Codex 完成一个阶段后我都会问一句这一阶段你遇到了哪些问题做了什么假设。这个动作看起来很简单但经常能挖出很多隐藏信息——原来它默认了用户名是手机号原来它假设任务不能删除。这些假设如果不及时暴露出来后面就是一个个隐性 bug。规格驱动开发不是把需求写细就完事了它应该是你与 AI 持续对话、持续校准的一个循环。