把 Codex Review 做成一项服务
AI 写代码越来越常见之后,AI 做代码 Review 几乎是顺理成章的下一步。
但真正跑起来之后会发现,问题并不是“模型能不能看懂 diff”。模型当然能看,尤其是对边界条件、异常处理、测试缺口、接口兼容性、明显的逻辑错误,它的第一轮筛查很有价值。真正麻烦的是另一件事:怎样把 AI Review 变成一条稳定、可控、成本可预期的工程流程。
如果每次都让一个通用 Agent 临场决定怎么拉代码、怎么读 PR、怎么评论、怎么 approve,刚开始会显得很灵活,过一阵子就会变成另一种不确定性来源。
这篇文章记录一次把 Codex Review 从“能跑”改造成“一项服务”的过程。
先看别人怎么做
GitHub 上已经有不少 AI Review 的实践。比较典型的是 Google 的 run-gemini-cli GitHub Action。它可以在 GitHub 工作流中调用 Gemini CLI,对 PR 做 Review、Issue Triage,也可以通过 PR 评论里的指令手动触发。
这种形态很自然:开发者提 PR,Action 读取 diff 和仓库上下文,生成 Review 评论,需要时给出修改建议。对使用者来说,它就像一个住在 GitHub 里的代码审查助手。
这类方案的优点很清楚:
- 入口在 GitHub,符合开发者习惯。
- 自动触发和手动触发都比较自然。
- Review 结果直接留在 PR 里,便于后续讨论。
- 不需要自己维护太多基础设施。
但它也有一个现实问题:外部服务的策略、额度和成本不是自己能完全控制的。今天可用的免费额度,明天可能变成限量试用;今天适合个人项目的定价,放到团队持续使用时可能就要重新估算。
所以,如果 Code Review 已经成为团队日常流程的一部分,就不能只把它当成一个外部工具调用。它需要变成内部可控的服务。
目标不是“把 Gemini 换成 Codex”
一开始很容易把需求理解成:原来用 Gemini Review,现在换成 Codex Review。
这其实只说对了一半。
模型只是其中一个环节。真正要建设的是一套 Review 工作流:
- 什么时候触发 Review。
- 谁可以触发。
- Review 哪个 PR。
- 是否默认 approve。
- 评论写在哪里。
- 失败时如何反馈。
- 历史记录在哪里查。
- 成本如何统计。
- 同一个 PR 重复 Review 时怎么处理。
- 不同仓库是否可以用不同规则。
这些问题都不能交给模型每次自由发挥。模型应该负责“读代码和发现问题”,而不是负责“组织整条工程流程”。
因此目标变成了:用 Codex 负责代码理解,用确定性的服务负责流程编排。
第一版:开发机定时扫 PR
最早的版本很直接:找一台开发机,安装 Codex 和 GitHub CLI,写一个定时任务,每分钟扫描一次目标仓库里 open 状态的 PR。
如果发现某个 PR 还没有 approve,就自动触发 Codex Review,把结果评论回 GitHub。
这版最大的优点是快。
不用改 GitHub,不用做 Web 页面,不用做飞书交互。PR 打开以后,后台迟早会扫到。对开发者来说,像是多了一个自动工作的审查员。
但跑了一段时间,问题也很明显。
第一,token 消耗不可控。
定时任务只知道“PR 是 open,且还没有 approve”,却不知道这个 PR 是否真的需要 AI Review。小改动、临时 PR、草稿 PR、重复提交,都会进入扫描范围。模型要读上下文、读 diff、生成结论,这些都是成本。
第二,用户没有表达意图的入口。
开发者不能方便地说:
- 这个 PR 先不要 Review。
- 这个 PR 重点看兼容性。
- 这个 PR 只看测试。
- 这个 PR 修改后重新 Review 一次。
所有策略都写死在定时任务里。
第三,状态不可见。
任务跑到哪一步了?GitHub 认证是否过期?仓库 clone 是否失败?Codex 是否超时?评论是否已经发出?approve 是否成功?
这些问题只能去开发机或 GitHub 上翻,很难让普通使用者直接理解。
第一版证明了 Codex 可以做 PR Review,但也证明了“全仓库自动轮询”不是一个好的长期形态。
第二版:从聊天入口触发
第二版把入口放到聊天工具里。
思路是:开发者在聊天里发送 PR 地址,请机器人帮忙 Review。机器人理解消息内容,解析 PR 链接,再调用 Codex Review 能力。
这比定时轮询前进了一步。用户终于可以主动触发 Review,而不是等后台扫描。也可以在聊天窗口里看到执行结果,使用门槛比命令行低得多。
但这版很快暴露出另一个问题:链路太长。
一次 Review 请求进来后,先要经过聊天机器人。机器人需要理解自然语言,再决定调用哪个能力,再把参数转换成具体命令。用户可能写:
- 帮我看一下这个 PR。
- review 这个链接。
- approve 一下。
- 跑一下 Codex。
- 这个 PR 看看有没有问题。
这些表达都很自然,但对后面的程序来说并不是稳定协议。机器人如果把命令拼错、参数名写错、字段对不上,第一次执行就会失败。失败以后再让 Agent 自动修复,链路就更不可控。
实际使用中会遇到几类问题:
- Review 命令参数拼错。
- Skill 或 Tool 的字段名和真实接口不一致。
- GitHub clone 或认证失败时,错误信息被多层转述,用户看不出问题在哪。
- 实时回复看起来很慢,像是在一个字一个字吐结果。
- 很难确认最终动作到底来自指定 Review 能力,还是 Agent 中途改用了别的工具。
- GitHub 评论结构不稳定,有时建议区域排版很难看。
这说明一件事:代码 Review 是确定性很强的工程任务,不应该把核心流程完全交给通用 Agent 临场组织。
Agent 可以理解用户意图,也可以理解代码;但拉取 PR、执行命令、格式化评论、approve、记录历史、恢复失败,这些步骤应该由普通程序接管。
第三版:做成独立服务
当前更合适的形态,是把 Review 做成一个独立服务。
它不再依赖“某个 Agent 这次是否理解对了”,而是提供清晰的命令协议。聊天入口、Web 页面、命令行入口都只是入口,真正的 Review 流程由服务负责。
服务需要做几件事:
- 接收命令。
- 解析 PR URL。
- 检查 GitHub 认证。
- 准备本地仓库。
- 调用 Codex。
- 整理输出。
- 评论 GitHub PR。
- 按策略 approve。
- 记录历史。
- 把结果反馈给用户。
这样以后,即使入口换了,核心流程也不变。
命令协议
服务可以支持一组很小的命令:
/review pr_url [approve=true]
/run message
/status
/history [limit]
/help [command]
/review 是核心能力,用于审查 GitHub PR。
/run 用于执行普通 Codex 任务,例如总结某个工作区、分析一段日志、解释一个文件。为了降低使用门槛,普通文本可以默认等同于 /run message。
/status 用来查看服务状态和正在执行的任务。
/history 用来查看最近执行历史。
/help 用来告诉使用者当前支持哪些命令。
群聊里还应该有一条基本规则:只有 @ 机器人时才处理消息。否则群里任何一句“帮我看一下”都有可能被误当成命令。
Review 主流程
服务收到 /review 后,流程应该是确定的:
- 解析 PR URL,得到 owner、repo 和 PR number。
- 检查 GitHub CLI 认证,必要时执行
gh auth setup-git。 - 克隆或更新目标仓库,切换到 PR 对应分支。
- 获取 base 分支和 PR diff。
- 调用 Codex 执行代码 Review。
- 将 Review 输出整理成统一格式。
- 在 GitHub PR 下发布评论。
- 按策略执行 approve。
- 将命令、状态、输出、错误写入历史记录。
- 把结果回复到触发入口。
这里最重要的是职责拆分。
Codex 只负责代码理解和问题发现。GitHub CLI 负责 PR、评论和 approve。聊天工具和 Web 页面负责入口和反馈。服务自己负责命令协议、状态、历史、格式化和策略。
把这些边界拆清楚以后,系统才容易稳定。
Review 评论不应该原样贴模型输出
很多 AI Review 的第一版,都会直接把模型输出贴到 PR 评论里。
这能用,但不好用。
一个真正可用的 Review 评论,应该像一个产品功能,而不是模型的一段长回答。
比较理想的结构是:
- 顶部先给结论:可以合并、需要关注、存在阻塞问题。
- 明确 approve 状态:是否已自动 approve,没 approve 的原因是什么。
- 问题按严重程度分组:阻塞、高、中、低、建议。
- 每个问题都包含位置、原因、影响和修改建议。
- 如果建议涉及代码变更,尽量用 diff 展示。
- 避免大段无结构文字。
比如评论可以长成这样:
## Codex Review
结论:需要关注,但未发现阻塞性问题。
Approve:已自动 approve。
### 中风险
1. `src/api/user.ts:87`
- 问题:异常分支没有释放连接。
- 影响:高并发下可能导致连接池耗尽。
- 建议:把释放逻辑移动到 `finally`。
### 建议
1. `tests/user.test.ts`
- 建议补充 token 过期场景。
模型可以生成原始判断,但最终评论最好由服务统一组装。这样团队可以逐步优化评论模板,而不是每次都看模型随机发挥。
默认 approve 也要成为策略
当前可以先采用简单策略:Review 完成后默认 approve。
这听起来有点激进,但在很多内部流程里是合理的。因为第一阶段的目标不是让 AI 代替人做最终责任判断,而是让它帮助 PR 快速进入可合并状态,同时把风险点留在评论里。
但这件事必须是一个明确策略,而不是模型自己决定。
后续可以逐步改成:
- 没有阻塞性问题才 approve。
- draft PR 不 approve。
- CI 未通过不 approve。
- 某些仓库默认不 approve。
- 涉及安全或计费模块时只评论不 approve。
这些都应该放在配置里,而不是写进 prompt 里让模型每次理解。
为什么服务化比 Agent 转发更稳
把 Review 做成服务以后,收益很明显。
第一,成本更可控。
只有明确触发的 PR 才会 Review,不再全仓库轮询。后续还可以按仓库、PR 大小、文件类型、标签做过滤。
第二,状态更清楚。
每个任务都有状态:queued、running、success、failed。失败原因可以直接保留原始错误,不需要通过多层 Agent 转述。
第三,历史可追溯。
什么时候谁触发了哪个 PR,模型输出了什么,是否评论成功,是否 approve,耗时多久,都可以查。
第四,入口可以变化。
今天是聊天工具,明天可以是 Web UI,后天可以是 GitHub comment command。入口变了,核心流程不用变。
第五,Review 质量更容易迭代。
评论模板、严重程度分类、默认 approve 策略、幂等更新逻辑,都可以在普通代码里迭代,不必每次重写 prompt。
一个实用的能力清单
一个能长期使用的 Codex Review 服务,至少应该具备这些能力:
| 能力 | 作用 |
|---|---|
| 聊天入口 | 让开发者不用离开日常沟通工具 |
| Web UI | 查看历史、状态、详情和错误 |
| GitHub PR 评论 | 保留团队原有 Review 工作流 |
| 自动 approve | 支持轻量化合并流程 |
| 历史记录 | 方便追踪任务和排查问题 |
| 队列控制 | 避免多个大 PR 同时压垮开发机 |
| 失败反馈 | 让用户知道是认证、网络、clone 还是 Codex 超时 |
| 配置化策略 | 不同仓库使用不同 Review 和 approve 规则 |
| 评论幂等 | 重复 Review 时更新旧评论,减少 PR 噪音 |
| token 统计 | 按仓库、PR、日期估算成本 |
这些能力看起来不像“AI”,但它们决定了 AI Review 能不能长期跑。
后续可以继续做什么
第一,统计 token 消耗。
按 PR、仓库、日期统计 Codex 消耗,才能知道哪些 Review 最贵,哪些仓库需要过滤,哪些 prompt 需要压缩。
第二,做评论幂等更新。
同一个 PR 的 Codex 评论,最好优先更新旧评论,而不是每次新增一条。否则一个 PR 多次 push 后,评论区会很快变乱。
第三,按仓库配置规则。
例如:
- 文档仓库只做轻量检查。
- 后端仓库重点看事务、异常和兼容性。
- 前端仓库重点看状态管理、交互边界和可访问性。
- 安全相关仓库只评论不 approve。
第四,支持 Review 模板。
不同团队关注点不一样。有的团队更关心测试,有的更关心性能,有的更关心接口兼容。模板应该配置化,而不是都塞在同一个 prompt 里。
第五,把结果做成更友好的消息卡片。
聊天工具里的回复不需要贴完整 Review。可以只展示状态、PR 链接、approve 结果、问题数量和失败原因,完整内容留在 GitHub PR 和 Web UI 里。
结论
AI Code Review 的关键不是“让哪个 Agent 更聪明”,而是把工程流程拆清楚。
Codex 适合读代码、找问题、解释风险。GitHub CLI 适合处理 PR、评论和 approve。聊天工具和 Web UI 适合做入口和反馈。服务本身负责协议、状态、历史、格式化、配置和策略。
当这些职责拆开以后,AI Review 才会从一次性的演示,变成可以长期使用的团队基础设施。
这也是我现在更推荐的方向:不要让通用 Agent 承载整个 Review 流程,而是把 Codex Review 做成一项服务。
参考资料
- google-github-actions/run-gemini-cli
- Gemini CLI GitHub Action PR Review 示例
- TechRadar: Google Gemini and GitHub are teaming up for AI-powered coding
- The Verge: Google makes Gemini Code Assist free for individuals
微信公众号
欢迎关注「字与码」
如果这篇文章对你有用,也欢迎在微信里继续关注后续更新。
X / Twitter
关注 @ax2_zicode
更即时的技术观察、新文章提醒和一些短想法会发在 X 上。