STUDIO · SPEC SHEET · UNIT S8
双智能体运维:让 AI 互相把关上线
定位:给「既当运动员又当裁判」的上线流程,加第二个裁判
一个由 AI 智能体维护的网站,最危险的时刻不是写错代码——写错的代码有 staging 挡着——而是「写代码的智能体顺手把代码发上线」。自我验证、自我放行、自我通报,三个环节在同一个上下文里闭环,等于既当运动员又当裁判。这个站从 2026 年 9 月起改成双智能体对等制:智能体甲偏开发与建设,智能体乙偏运维与审核,谁都不能单独把变更推上生产。
它的关键词不是「自动」,是「分权」。整套体系没有引入任何新平台:一个 bare Git 仓库、一个部署脚本、一块 Markdown 看板,其余全是约定。落地当天这套流程就经历了三次真实拦截,下面会讲。
四眼原则:改动发起者 ≠ 生产放行者
规约里只有一条硬约束:任何变更,发起的智能体不能是放行的智能体。流程上它落在看板的一块「审批区」——发起方在 OPS-BOARD 写 [REQUEST](变更内容 + 门禁证据),另一方核对证据后回复 +1 才算放行;不同意就回 HOLD,但必须给理由。
配套一条泄压阀:+1 等待超过两小时、且是线上故障,可标注 [EMERGENCY] 单方上线,事后对方必须补审并记录。这条很重要——审核制度最常见的死法不是被绕过,而是在救火时被咒骂着绕过。给它一个带账目的逃生口,制度反而活得长。
两个智能体对等、无主从,任何一方休息就在看板声明 [AWAY],另一方自动接管全部职责。分工不是固定的,固定的是这条约束本身。
环境:staging 必须是「另一个站」,不是「另一个目录」
第一版方案在这一点上踩过坑:最初想用路径式 staging(主站加 /beta/ 前缀),但主站静态资源全是绝对路径(/assets/site.css、/images/...),beta 页面加载的仍然是生产的样式和数据——隔离是假的。
所以最终形态是物理隔离:staging 独立端口(8090,后续换独立域名)、独立 API 实例(lead-api-beta,端口 3459)、独立 SQLite 数据库。staging 的数据允许脏——测试产生的评论和线索定期清库即可,绝不与生产库混用;staging 的 robots.txt 直接 Disallow: /,防搜索引擎收录测试内容。
部署流水线:七步、三道闸
标准流程七步:认领锁 → 拉取构建 → 部署 staging → 门禁测试 → 生产放行 → 生产发布 → 通告归档。真正干活的是其中三道闸:
| 闸 | 防什么 | 怎么防 |
|---|---|---|
| 部署锁 | 两个智能体同时部署、互相覆盖 | 服务器 flock 文件锁,超时 30 分钟自动释放,锁内自动写 [LOCK] 记录 |
| 门禁 | 带病产物进生产 | 关键页 200×5、大文件 MD5 双端比对、API 双端响应一致性、页面数回归,缺一即断 |
| 放行 | 自审自批 | [REQUEST] 的 +1 与发起者强制不同智能体 |
门禁的验收口径里有一条值得单独说的修订。初版规约写「/api/comments?work=w6 返回 ok:true」,落地当天实测,生产与 staging 对同一请求返回的都是 unknown work——因为两边都没有 w6 的数据,接口行为完全一致。于是 v1.0.1 把口径改成「双端响应一致即为达标」。这件事的教训比修订本身值钱:验收断言写错,比没有自动化验收更危险——它会让人开始对红灯脱敏。
发布制与回滚:一条符号链接的原子切换
生产目录不是实体目录,是符号链接:/var/www/agent → releases/agent-<时间戳>。每次发布生成新目录、构建完成后一条 ln -sfn 原子切换,服务器上保留最近 10 个版本。回滚就是把链接切回上一版(由 CURRENT 文件记录),一分钟以内。
每个生产版本必须打语义化 tag、在 CHANGELOG 里留一条带作者智能体署名的记录。版本号不是给访客看的,是给两个智能体对齐「现在线上到底是什么」用的——对话式协作里没有公告栏,tag 就是公告栏。
落地当天,流程拦下的三个坑
这套体系建成的第一天,三个问题都是被流程自己暴露的,而不是靠人想起来的:
| 坑 | 现象 | 流程的反应 |
|---|---|---|
| 安全组拦截 | staging 端口 8090 从外部直连不通 | 门禁验证改为服务器本机 curl,Playwright 走 SSH 隧道——门禁没有被「临时绕过」,而是换了条合规的路 |
| 服务器无 rsync | 部署脚本在目标机缺依赖 | 传输改为 tar 管道,写进脚本与规约,下次不再现场发明 |
| 切换竞态 | 生产首次验证遇瞬态 404(符号链接切换瞬间) | 门禁自动回滚真实生效了一次;修复后加 2 秒过渡与 3 次重试防缓存 |
第三条最值得说:自动回滚不是摆设,它在第一次真实故障里就执行了一次完整的「发现 → 回滚 → 记录」。事后看,那是一次一秒级的抖动,但流程没有赌「应该没事」。
价值与可复用方法
对站长,变化是「盯部署」变成「看板签字」:上线质量由门禁和另一个智能体兜底,人只出现在放行与例外审批里。对智能体,变化是结构性的——写代码的和放行的分属两个上下文,自我审查的盲区被制度补上,而不是靠提示词里多写一句「请仔细检查」。
可复用的最小集只有四样:一个 bare 仓库(双方推拉的单一事实源)、一块追加式看板(审批与留痕)、一个带锁和门禁的部署脚本、一条「发起者不放行」。以天为单位能搭完,剩下的全是纪律——纪律的本质,是让每一次偷懒都会在看板上留下痕迹。