Codex CLI 完全指南:第九章·提示词工程与工作流设计

写代码要用编程语言,与 AI 对话要用提示词。提示词工程(Prompt Engineering)是与 Codex 高效协作的核心技能,本章系统讲解编写高质量提示词的方法论,以及如何设计高效的 AI 辅助开发工作流。

提示词的核心原则

好的提示词 vs 差的提示词

差的提示词

帮我写个登录功能

Codex 不知道你用哪个框架、什么数据库、要不要 JWT、错误处理到什么程度——它只能猜测,结果大概率不符合预期。

好的提示词

在 Express + TypeScript 项目中添加登录 API:
1. POST /api/auth/login,接收 { email, password }
2. 使用 bcrypt 比对密码,使用 JWT 签发 token
3. 返回 { token, user: { id, email, name } }
4. 参数校验使用 zod
5. 错误处理使用项目已有的 AppError 类
6. 不要把密码返回给客户端

这遵循了提示词的 6C 原则

| 原则 | 英文 | 含义 |
|------|------|------|
| 上下文 | Context | 说明项目背景、技术栈 |
| 约束 | Constraints | 明确技术选择、格式要求 |
| 完整 | Complete | 覆盖输入、处理、输出全流程 |
| 清晰 | Clear | 用精确术语,避免歧义 |
| 具体 | Concrete | 给出具体的期望输出 |
| 检查点 | Checkpoint | 指明需要特别注意的事项 |

情境化提示

Codex 会读取你项目中的 AGENTS.md 和文件,所以提示词不需要重复项目级别的约定。利用这一点:

请像 AGENTS.md 中描述的那样,为 UserService 添加一个 changePassword 方法。
要求:
- 接收 oldPassword 和 newPassword
- 验证旧密码正确
- 使用相同的 bcrypt 策略散列新密码
- 返回更新后的用户对象(不含密码字段)

AGENTS.md 中关于密码策略、返回格式、命名约定的信息 Codex 已经知道,提示词只需聚焦业务逻辑。

高级提示词技巧

分步提示(Chain of Thought)

让 Codex 先思考再执行:

不要直接写代码。先分析以下问题,列出步骤,再逐步实现:
需求:实现一个支持分页、排序、过滤的用户列表 API

1. 先列出需要的数据模型变更
2. 再设计 API 契约(请求参数、响应格式)
3. 然后规划实现步骤
4. 最后写出代码

每个步骤完成后等我确认再继续。

角色设定

codex "你是一位安全审计专家。请审查这个认证中间件,重点关注:会话劫持、CSRF、时序攻击。按严重程度列出问题并给出修复代码。"

输出格式控制

请为 UserService 的所有公共方法生成 API 文档,格式如下:
| 方法签名 | 参数 | 返回值 | 异常 | 说明 |
|---|---|---|---|---|
| getUser(id) | id: number | User \| null | NotFoundError | 查询单个用户 |

示例驱动(Few-Shot)

cat << 'EOF' | codex
请按照以下示例的风格,为 ProductService 编写 CRUD 方法:

示例(UserService):

async findById(id: number): Promise<User | null> {
return this.repository.findOne({ where: { id, isDeleted: false } });
}

现在请为 ProductService 编写同样的 findById 方法。
EOF

迭代精炼

第一次提示词通常不完美,用迭代方式精炼:

> 创建一个订单支付流程

// 查看结果,发现缺少退款逻辑

> 在刚才的订单支付流程中补充:
   1. 退款接口 POST /api/orders/:id/refund
   2. 退款前验证订单状态为"已支付"
   3. 调用支付网关退款 API
   4. 更新订单状态为"已退款"

常见的提示词模板

代码生成

在 [文件路径] 中新增 [功能描述]:
- 输入:[参数类型和含义]
- 处理逻辑:[核心业务规则]
- 输出:[返回值结构]
- 异常情况:[需要处理的错误]
- 遵循项目现有的 [模式名称] 模式

Bug 修复

修复 [文件路径] 中的 bug:[现象描述]
- 期望行为:[应该怎样]
- 实际行为:[实际怎样]
- 复现步骤:[如何触发]
- 不要修改其他逻辑,最小化改动

代码重构

重构 [文件路径]:
- 问题诊断:[具体的问题,如函数过长、耦合高]
- 重构目标:[想要达到的结构]
- 约束:保持 API 兼容、不改变现有行为
- 分批执行,每批完成后确认

测试编写

为 [文件路径] 编写完整测试:
- 测试框架:[vitest / pytest / go test]
- 覆盖场景:
  1. 正常输入
  2. 边界值
  3. 错误输入
  4. 依赖异常(mock)
- 每个场景用 describe/it 组织
- 测试数据使用 fixture 或 setup

工作流设计

标准开发工作流

1. 需求分析
   codex "理解以下需求,列出需要修改的文件和影响范围:[需求描述]"

2. 方案评审
   codex "针对上述需求,给出 2 种实现方案,对比优劣"

3. 编码实现
   codex "按方案 1 实现,分批进行,每批完成后等我确认"

4. 测试验证
   codex "根据刚才的变更,更新相关测试,确保覆盖新逻辑"

5. 代码审查
   git diff | codex "审查这些变更"

6. 提交部署
   codex run ship

TDD 工作流

# 1. 先写测试
codex "为 calculateDiscount 函数编写测试用例"
# 2. AI 生成失败的测试
# 3. 让 Codex 实现功能
codex "实现 calculateDiscount,使测试通过"
# 4. 迭代
codex "测试通过了,现在补充边缘情况测试"

技术调研工作流

codex "我需要为 Next.js 项目选择状态管理方案。请比较:
  - Zustand
  - Jotai
  - Redux Toolkit
  从以下维度分析:学习曲线、包大小、TypeScript 支持、社区活跃度、适用场景
  基于本项目(中小型 SaaS)给出推荐。"

代码迁移工作流

codex "将 src/services/ 下所有 JavaScript 文件迁移为 TypeScript:
  1. 分析每个文件,推断类型
  2. 添加接口定义
  3. 一次迁移一个文件
  4. 每个文件迁移后运行测试确认不破坏功能"

上下文管理策略

避免 Token 溢出

Codex 一次能处理的上下文有限,需要策略性管理:

分而治之:不要一次要求分析整个项目,按模块逐个来

聚焦重点:提示词中明确"只看 src/services/ 目录"

引用文件请参考 src/types/user.ts 中的 User 接口 比把整个接口内容粘贴到提示词更好

总结续接:当对话很长时,让 Codex 总结当前进展,新对话中继续

上下文继承技巧

# 用一个临时文件保存对话上下文
codex "分析 api/auth.ts 的安全问题" > analysis.md

# 新对话中引用
codex "根据 analysis.md 发现的问题,逐一修复 api/auth.ts"

提示词的反模式

| 反模式 | 问题 | 修正 |
|--------|------|------|
| "帮我优化" | 太模糊 | "将 getUser 的数据库查询从 3 次降为 1 次" |
| 一次提 10 个需求 | AI 容易遗漏 | 拆成独立请求,逐个完成 |
| "用最好的方式" | "最好"因人而异 | "用已有的 Repository 模式" |
| 不提供错误信息 | AI 只能猜测 | "运行报错:TypeError: ..." |
| "全部重写" | 丢弃了已有设计意图 | "重构第 50-100 行,保持接口不变" |

小结

提示词工程不是玄学,而是结构化的需求表达。核心就一件事:让 Codex 不需要猜测你的意图。配合清晰的工作流设计,你就能从 AI 中得到高质量的、可预测的输出。