AI 自动写 PR:模型是最简单的一环,难的是别让它把生产库点着
Inkitt 把“接任务—改代码—跑 CI—修失败—解冲突—开草稿 PR”做成了状态机:智能体只…
文章目录
让 AI 写代码不难,难的是让它每天在一家真实公司的代码库里干活,还不至于把生产环境点着。Inkitt 的工程团队最近公开了他们的一次性 PR 创建器:从 Slack、Linear 或另一个智能体发起任务,系统自动完成小型、低风险的代码变更,一路跑到生成可测试、可审查的草稿 PR。这套系统已经每天用于交付代码。

一分钟速览
- 系统采用事件驱动的编排器,协调短生命周期的智能体容器,而不是固定流水线。
- 阶段拆分为需求说明、实现、验证、CI 失败修复、合并冲突解决,状态持久化,可断点恢复。
- 决策逻辑与副作用严格分离;智能体只拿短期仓库 Token 和模型凭证,无法访问 Slack、云身份或生产系统。
- 数据库迁移、Schema、共享契约、CI 与容器构建配置、鉴权、支付、依赖增删等变更一律拒绝。
- 输出永远是草稿 PR,不能绕过分支保护,也不能自行合并。
为什么不用一条“万能流水线”
很多团队的直觉是写一条很长的提示词,让模型从头干到尾。Inkitt 的选择相反:把任务拆成多个短生命周期容器,每个阶段只负责一件事,由编排器根据当前状态和传入事件决定下一步。这样做的直接好处是可恢复——每次运行的状态都写进数据库,某个阶段失败后可以从已记录的状态继续,而不是整条重跑。
另一个好处是权限收敛。编排器自己保管外部系统凭证,智能体容器只拿到短期有效的代码仓库 Token 和模型凭证;它不能直接访问 Slack 或生产凭证,不能随意建立网络连接,也不能拿云身份去调用别的服务。即便模型被提示词注入带偏,能造成的破坏也被限制在一个很窄的范围内。
真正的安全阀:Diff 检查和拒绝清单
Inkitt 在智能体之外加了一道独立检查:直接查看实际的 Git Diff,确认变更没有触及受限制的路径。这比“让模型自己保证不碰敏感文件”可靠得多,因为模型的自述不可验证,而 Diff 是事实。
拒绝清单同样值得抄作业:数据库迁移、Schema 或共享契约变更、CI 和容器构建配置、身份验证、支付代码,以及软件包的添加或更新,全部拒绝。这些改动的共同点是——一旦出错,影响面远超一次普通提交。把“不该自动化的事”明确写死,比事后救火便宜得多。
重试要有预算,事件要幂等
验证、CI 修复和合并冲突解决,最多各尝试两次。这个数字背后是对失败模式的判断:如果一个智能体两次都修不好,第三次大概率只是换个方式烧钱。
重复投递的 Webhook 是另一个坑。系统通过去重和条件数据库写入来处理,把幂等原则应用到可能重试或接收重复事件的工作流上。判断 CI 是否完成时,编排器会主动查询 GitHub,确认所有相关任务都已结束,而不是把每一个任务事件都当成整个工作流完成的信号——后者在并发场景下几乎必然误判。
人还在环里
这套系统最克制的地方,是它不追求“全自动合并”。流程的终点是草稿 PR:CI 通过、变更进入预发布环境后,系统通知任务发起者;之后必须由人把 PR 标记为可供审查,并管理审查者请求与审批。分支保护无法被绕过,智能体也不能自己点合并。
对于更大的任务,Inkitt 还维护了一个本地版本,让人持续参与开发过程。这其实是在承认一个现实:当前模型适合处理边界清晰、影响面小的变更,不适合独立承担架构级改动。
可复用的三条经验
第一,把“决策”和“执行”分开。状态机决定做什么,容器只负责做,这样权限、审计和恢复都有落点。第二,把安全约束放在模型外面。Diff 检查、路径白名单、拒绝清单,都是不依赖模型自觉的硬约束。第三,把重试和幂等当成一等公民。事件驱动系统里,重复和失败不是异常,而是常态。
至于模型,它确实是这套系统里最简单的一环。真正决定成败的,是编排、权限和边界设计——也是大多数“AI 自动写代码”项目最容易忽略的部分。
本文地址:https://www.163264.com/21218


