Codex 编程完整工作流教程:Spec → Plan → Execute → Review
> 来源基础:Rick Hightower 关于 Claude Code spec-driven development 的文章总结,以及 Hermes 场景下的工程化调整。 > > 适用对象:使用 Codex / Claude Code / Hermes 这类编码 Agent 开发中等以上复杂度功能,尤其是运维自动化、监控、告警、诊断 Agent。 > > 来源限制:原文 Medium 页面在当前环境受 Cloudflare/403 阻断,本文基于已提取摘要与片段整理,不引用未验证全文细节。
1. 核心原则
不要直接让 Codex “帮我写一个系统”。
更稳的方式是把一次开发拆成四层:
1. Spec:合同
- 说明要解决什么问题、不解决什么问题、成功标准是什么。
- 说明按什么顺序改哪些文件、怎么测试、怎么回滚。
- 每次只做一个小任务,验证后再继续。
- 让另一个上下文检查是否符合 spec、是否有安全/质量问题。
2. Plan:配方
3. Execute:小步执行
4. Review:独立审查
一句话:
> Spec 决定“做什么”;Plan 决定“怎么做”;Execute 负责“小步落地”;Review 防止“自己证明自己正确”。
2. 为什么不能直接写代码
长时间 AI 编程会话常见失败模式:
- 需求越聊越散;
- 代码写了一半,但不知道哪些验收标准还没满足;
- 模型开始根据上下文里的旧讨论做隐含假设;
- 测试为了通过被错误修改;
- 运维脚本不小心引入真实副作用,例如删除、重启、写数据库、误发告警;
- 最后只能靠人肉 review 整理烂摊子。
Spec-driven workflow 的价值不是多写文档,而是提前消灭歧义。
3. 推荐目录结构
一个小型运维 Agent 项目可以这样组织:
ops-agent/
├── README.md
├── pyproject.toml
├── .env.example
├── docs/
│ ├── specs/
│ │ └── ops-agent.md
│ ├── plans/
│ │ └── ops-agent-implementation.md
│ └── reviews/
├── src/
│ └── ops_agent/
│ ├── __init__.py
│ ├── config.py
│ ├── checks.py
│ ├── collector.py
│ ├── diagnosis.py
│ ├── notifier.py
│ └── main.py
└── tests/
├── test_config.py
├── test_checks.py
├── test_diagnosis.py
└── test_notifier.py4. 阶段一:写 Spec
Spec 应该回答这些问题:
- 目标:这个 Agent 解决什么运维问题?
- 非目标:明确不做什么?
- 输入:读取哪些数据?系统指标、日志、K8s API、数据库、HTTP endpoint?
- 输出:告警、诊断报告、JSON、企业微信通知?
- 权限边界:是否只读?是否允许自动修复?
- 失败策略:采集失败、API 超时、配置错误时怎么处理?
- 验收标准:哪些测试/命令通过才算完成?
- 安全边界:禁止执行哪些操作?
Spec 示例
# Ops Agent Spec
## Goal
开发一个只读运维 Agent,用于周期性检查 Linux 主机健康状态,并在异常时生成诊断报告和企业微信告警。
## Non-goals
- 不自动重启服务。
- 不删除文件。
- 不执行修复命令。
- 不连接生产数据库。
- 不把 token 写入代码或日志。
## Requirements
- R1: 读取 CPU、内存、磁盘使用率。
- R2: 支持配置阈值。
- R3: 当指标超过阈值时生成结构化诊断结果。
- R4: 支持 dry-run 模式,只打印告警内容,不发送企业微信。
- R5: 企业微信 Webhook 从环境变量读取。
- R6: 所有外部调用必须有 timeout。
- R7: 单元测试覆盖阈值判断、配置加载、告警格式。
## Acceptance Criteria
- `pytest -q` 通过。
- `ruff check .` 通过。
- 没有硬编码 token/IP/密码。
- dry-run 模式不会发送真实 HTTP 请求。
- 配置缺失时给出明确错误,而不是 traceback 泄漏。
## Safety
- 默认只读。
- 自动修复必须作为未来单独 spec,不在本期实现。5. 阶段二:写 Plan
Plan 不是重复 Spec,而是把实现拆成可执行步骤。
每个任务都要包含:
- 文件路径;
- 改动内容;
- 测试方式;
- 完成标准;
- 回滚方式。
Plan 示例
# Ops Agent Implementation Plan
## Task 1: 项目骨架
- 创建 `src/ops_agent/` 与 `tests/`。
- 添加 `pyproject.toml`、`.env.example`、`README.md`。
- 验证:`pytest -q` 至少有 import smoke test。
## Task 2: 配置加载
- 创建 `src/ops_agent/config.py`。
- 使用 dataclass 定义阈值配置。
- Webhook 只从环境变量读取。
- 测试:`tests/test_config.py` 覆盖默认值、非法值、缺失 webhook。
## Task 3: 指标采集
- 创建 `collector.py`。
- 读取 CPU、内存、磁盘。
- 外部命令必须 timeout,不使用 `shell=True`。
- 测试:mock 采集结果。
## Task 4: 阈值判断与诊断
- 创建 `checks.py` 和 `diagnosis.py`。
- 输入指标,输出结构化诊断。
- 测试:正常、警告、严重三类场景。
## Task 5: 企业微信通知
- 创建 `notifier.py`。
- 支持 dry-run。
- 真实发送使用 timeout。
- 测试:mock HTTP,不发真实请求。
## Task 6: CLI 入口
- 创建 `main.py`。
- 支持 `--dry-run`。
- 验证:`python -m ops_agent.main --dry-run` 输出诊断 JSON。
## Final Verification
- `pytest -q`
- `ruff check .`
- 检查无硬编码密钥:搜索 `token|secret|password|webhook`。6. 阶段三:执行 Plan
执行时不要让 Codex 一次完成全部任务。
推荐节奏:
1. 只执行 Task 1; 2. 跑 Task 1 的验证; 3. review diff; 4. 再执行 Task 2; 5. 每个任务完成后更新 todo; 6. 如果实现发现需求不对,先改 Spec,再改 Plan,不要直接改代码。
给 Codex 的执行提示词可以这样写:
请只执行 plan 中的 Task 1。
不要执行后续任务。
完成后返回:
1. 修改的文件列表;
2. 运行的验证命令;
3. 命令退出码;
4. 未完成项;
5. 是否偏离 spec。7. 阶段四:独立审查
审查要分两层:
1. Spec compliance review
- 是否满足 spec?
- 是否遗漏验收标准?
- 是否做了非目标里的内容?
2. Code quality review
- 是否有安全问题?
- 是否硬编码秘密?
- 是否缺少 timeout?
- 是否错误使用
shell=True? - 测试是否真的覆盖关键行为?
审查提示词:
你是独立代码审查员。请只读审查当前 diff,不要修改文件。
审查目标:
1. 对照 docs/specs/ops-agent.md 检查实现是否符合要求。
2. 对照 docs/plans/ops-agent-implementation.md 检查是否只完成当前任务,没有越界。
3. 检查安全问题:硬编码 token、shell=True、无 timeout、真实外部请求、路径遍历。
4. 检查测试是否覆盖关键行为。
输出:
- Verdict: APPROVE / REQUEST_CHANGES / BLOCKED
- Spec gaps:
- Security issues:
- Logic issues:
- Test gaps:
- Required fixes:8. 运维 Agent 的完整 Codex 提示词
下面是一份可以直接复制给 Codex 的完整提示词。建议在一个空仓库或已有项目根目录中使用。
你是一个资深 Python 运维自动化工程师。请使用 spec-driven development 流程开发一个只读 Linux 运维健康检查 Agent。
硬性要求:
- 先写 spec,再写 plan,再执行 plan。
- 不要在没有 spec 和 plan 的情况下写业务代码。
- 默认只读,不允许自动修复。
- 禁止使用 shell=True。
- 禁止硬编码 token、密码、IP、Webhook。
- Webhook 只能从环境变量读取。
- 所有外部调用必须设置 timeout。
- 所有新增函数必须有参数和返回值类型注解。
- 新增代码必须有 pytest 单元测试。
- 真实告警发送必须可通过 --dry-run 禁用。
- 不要提交代码,除非我明确要求 commit。
项目目标:
开发一个名为 ops-agent 的 Python 运维 Agent,用于检查单台 Linux 主机健康状态,并在异常时生成结构化诊断报告。第一版只支持本机只读检查,不做自动修复。
功能范围:
1. 读取 CPU、内存、磁盘使用率。
2. 支持通过配置设置阈值。
3. 根据阈值输出 OK / WARNING / CRITICAL。
4. 生成结构化诊断报告,包含:
- hostname
- timestamp
- metrics
- triggered_checks
- severity
- summary
- suggested_manual_actions
5. 支持企业微信机器人 Webhook 通知。
6. 支持 dry-run 模式:只打印将要发送的消息,不发真实 HTTP 请求。
7. 支持 CLI:`python -m ops_agent.main --dry-run`。
非目标:
- 不自动重启服务。
- 不执行清理磁盘、kill 进程、delete 文件等修复动作。
- 不连接 Kubernetes。
- 不连接数据库。
- 不做长期 daemon/scheduler,第一版只做单次运行。
- 不引入复杂依赖,优先 Python 标准库;如确需第三方依赖,先说明原因并等待确认。
推荐目录结构:
ops-agent/
├── README.md
├── pyproject.toml
├── .env.example
├── docs/
│ ├── specs/
│ │ └── ops-agent.md
│ └── plans/
│ └── ops-agent-implementation.md
├── src/
│ └── ops_agent/
│ ├── __init__.py
│ ├── config.py
│ ├── collector.py
│ ├── checks.py
│ ├── diagnosis.py
│ ├── notifier.py
│ └── main.py
└── tests/
├── test_config.py
├── test_collector.py
├── test_checks.py
├── test_diagnosis.py
└── test_notifier.py
执行流程:
Phase 1: 写 spec
- 创建 `docs/specs/ops-agent.md`。
- 必须包含:Goal、Non-goals、Requirements、Acceptance Criteria、Safety、Validation、Rollback/Stop Conditions。
- 写完后停止,等待我确认。
Phase 2: 写 plan
- 在我确认 spec 后,创建 `docs/plans/ops-agent-implementation.md`。
- 把实现拆成 2-5 分钟粒度的小任务。
- 每个任务必须包含:目标文件、改动内容、测试、验证命令、回滚方式。
- 写完后停止,等待我确认。
Phase 3: 执行 plan
- 在我确认 plan 后,一次只执行一个任务。
- 每个任务必须先写或更新测试,再写实现。
- 每个任务完成后运行对应测试。
- 每个任务结束时返回:
1. 修改文件;
2. 运行命令;
3. 命令退出码;
4. 是否满足 spec;
5. 是否有未完成项。
- 不要跳到后续任务。
Phase 4: 最终验证
完成所有任务后运行:
- `python -m pytest -q`
- `ruff check .`(如果已配置 ruff)
- `python -m ops_agent.main --dry-run`
- 检查没有硬编码 secret/token/password/webhook。
Phase 5: 独立审查
请生成一个 review 请求,供另一个 Codex/Claude session 独立审查当前 diff。
审查重点:
- 是否符合 spec;
- 是否越过 non-goals;
- 是否有 shell=True;
- 是否有硬编码密钥;
- 是否所有外部请求有 timeout;
- dry-run 是否不会发送真实 HTTP;
- 测试是否覆盖阈值判断、诊断输出、通知 dry-run。
代码设计建议:
- `config.py`: 使用 dataclass 定义配置,例如 CPU/MEM/DISK 阈值和 webhook URL。
- `collector.py`: 定义 `SystemMetrics` dataclass,采集只读系统指标。
- `checks.py`: 输入 metrics + thresholds,输出 check result。
- `diagnosis.py`: 把 check results 聚合成诊断报告。
- `notifier.py`: 负责企业微信消息格式化和发送;dry-run 时只返回消息内容。
- `main.py`: CLI 入口,组合配置、采集、诊断、通知。
质量要求:
- 函数短小,职责单一。
- 使用 early return,减少嵌套。
- 不使用 print 作为库函数日志;CLI 层可以输出结果。
- 异常信息要可读,但不能泄漏 secret。
- 测试中 mock HTTP 请求,不发真实请求。
现在请先执行 Phase 1:只写 spec,不写实现代码。9. 独立审查提示词
当 Codex 完成实现后,把下面提示词给另一个 session:
你是独立审查员。请只读审查这个 ops-agent 项目,不要修改文件。
请读取:
- docs/specs/ops-agent.md
- docs/plans/ops-agent-implementation.md
- 当前 git diff
- src/ 和 tests/ 下相关文件
请检查:
1. 实现是否满足 spec 的每条 requirement。
2. 是否违反 non-goals,例如自动修复、真实删除、真实重启、连接 K8s/数据库。
3. 是否存在硬编码 secret/token/password/webhook。
4. 是否使用 shell=True。
5. 所有外部请求是否有 timeout。
6. dry-run 是否不会发真实 HTTP 请求。
7. 测试是否覆盖配置、阈值判断、诊断报告、通知 dry-run。
8. CLI 是否可用。
9. 是否有不必要依赖或过度工程化。
输出格式:
- Verdict: APPROVE / REQUEST_CHANGES / BLOCKED
- Blocking issues:
- Important issues:
- Minor suggestions:
- Evidence checked:
- Required next patch scope:10. 最小验收清单
开发完成前至少满足:
docs/specs/ops-agent.md存在。docs/plans/ops-agent-implementation.md存在。python -m pytest -q通过。- dry-run 不发真实请求。
- 没有硬编码密钥。
- 没有
shell=True。 - 所有 HTTP 请求有 timeout。
- 独立审查没有 blocking issue。
11. 常见失败与处理
失败 1:Codex 直接开始写代码
处理:停止它,要求先补 spec 和 plan。
失败 2:实现做了自动修复
处理:回滚该部分。自动修复必须另开 spec。
失败 3:测试 mock 了自己的纯函数
处理:只 mock 外部边界,例如 HTTP、系统命令、文件系统;不要 mock 纯判断逻辑。
失败 4:dry-run 仍然调用 Webhook
处理:这是 blocking issue。必须先写 regression test,再修复。
失败 5:Plan 太大
处理:把任务拆小。一个任务最好 2-5 分钟可完成。
12. 实战建议
- 对普通业务功能:spec 可以轻一点。
- 对运维 Agent:spec 必须写清楚安全边界。
- 对能影响生产系统的功能:默认只读,自动修复另开阶段。
- 对告警系统:先 dry-run,再真实发送。
- 对 Hermes/Agent 工作流:review 是 gate,不是形式。
最终原则:
> 让 Agent 写代码前,先让它知道边界;让 Agent 说完成前,先让另一个上下文审查证据。