周二晚上11点,演示在九点。你给智能体推了最后一次改动,部署失败:一个本地装过却没写进依赖的包、一个只在一个文件里改了名的变量、一个框架自己挑的端口。报错藏在三百行构建日志的某个角落。

打开网易新闻 查看精彩图片

我们运营一个面向AI智能体的托管平台,想干掉的正是这个时刻。不是做一个解释日志的聊天机器人,而是一个按钮:Fix with AI。点一下,几分钟后一个修好的智能体副本上线,或者明确告诉你为什么不行。

难的部分不是"让模型给个补丁",而是模型周围的一切。

第一步不是写代码,是分诊

第一版把所有失败直接送进代码生成,结果错得很具体:一个缺少必需环境变量的智能体被反复"修复"。模型设不了变量,就绕着缺失的值写代码,部署以同样方式失败,用户再点一次。

现在每次尝试都先做诊断,在碰任何代码之前分出三种结果:

  • 只有所有者才知道的值。缺API密钥、连接串或主机地址,修复直接停下,告诉你要设哪个变量。这条是压力测试教出来的:模型把缺失的数据库URL"修"成了自己写的占位符,智能体启动了,连上了空气,还报告成功。现在,名字像凭据或值像占位符的,AI一律不填。
  • 有证据支持的配置改动。平台自身的健康检查事件显示预期端口"连接被拒",就在配置里对齐端口并重新部署。智能体被真正的内存超限杀死,就升一档规格(在套餐范围内;已是最大规格则停下并说明)。光有诊断不够,证据必须对得上——单看"退出码137"不算内存被杀的证据,因为健康检查失败退出的进程也是这个码。这条也是线上学的:一个绑错网卡的智能体被加了两次内存,才轮到那一行代码修复。
  • 真正的代码问题。其余全部进入打补丁流程。

由我们自己造成的失败,比如构建时的临时容量限制,根本不会送给模型。补丁修不了我们的容量,试了也只是白花用户的额度。

按失败类别选模型

不是每种失败都配得上同一个模型。缺个import是机械活,跨三个文件的竞态不是。所以在生成任何东西之前,一个快而便宜的模型先把失败标成LOW、MEDIUM或HIGH,附一句理由。这次调用失败,就由确定性规则接管:ModuleNotFoundError、SyntaxError这类已知模式算LOW;死锁、段错误和内存超限信号算HIGH;没有任何应用报错的笼统"始终未就绪"也归HIGH,因为没有任何可安全猜测的依据。

每个标签有自己的模型链。LOW和MEDIUM从上下文窗口很大的快模型起步;HIGH以及每一次第二次尝试,从我们用的最强编码模型起步。链上某个供应商报错、超时或被限流,下一个接上。

生产环境跑出两条教训:

  • 把所有请求都路由给最强模型,会让修复变成我们卖得最贵的东西。简单案子从便宜模型起步,贵的留给难失败和重试,质量留在该在的地方,成本被每个套餐的月度AI预算框住。
  • 从不演练的兜底不叫兜底。我们发现链上两个模型几乎每次调用都失败,持续了好几周:一个是因为我们账户的限流额度比一条修复提示词还小,另一个是上下文窗口不够。两个都修了,每条链都用真实大小的提示词重新测过。

模型看到什么

模型拿到错误输出(尾部,失败所在的地方)、你的Dockerfile(如果有),以及最多60个源文件。报错点名的文件排在最前且完整给出,哪怕超过常规的单文件上限,因为修语法错误也得看到文件头。它还会拿到你设过的环境变量的名字——只有名字,没有值,免得它凭空发明一个"缺失变量"。

任何东西离开平台之前,专门存放凭据的文件(.env、私钥)被排除,看起来像密钥的值替换成占位符,真实值在补丁写回文件后再填回去。这是基于模式的,抓不全所有密钥,所以我们建议用户把密钥放在变量里,不要写进代码。

构建前的两道闸:先解析,再安全审查

一次构建要花真时间和真钱。早期一个针对Go服务的补丁把文件的package行弄丢了,送进完整构建,编译器第一秒就拒了。现在每个补丁必须先通过解析:Python、Go、Java、JavaScript、TypeScript、Rust和JSON用真正的解析器,外加针对模型实际会犯的错的Go专项检查(package子句丢失或改名、条件里把==写成=)。解析不过的补丁带着解析器的报错退回模型。典型文件耗时远低于一毫秒。

我们检查整个快照,不只检查被补丁的文件。压力测试里,一个有好几个坏文件的仓库,每个坏文件都换来一次重新部署,因为每次修复只看最新报错点名的那个文件。现在所有解析不过的文件都列进提示词并排在最前。

然后补丁过一遍自动安全审查,和所有从源码部署走的是同一套。发现严重问题,不构建。审查本身跑不完,也不构建:点击和部署之间没有人类来权衡一次被跳过的检查,所以流水线选择失败关闭。

部署副本,然后问健康检查

打过补丁的代码永远不会推进你的仓库。没有提交、分支或拉取请求。它写进一个快照,走正常构建流水线,作为智能体的新版本部署,标记为AI修复,和你已有的版本并列。不喜欢,一键恢复上一个版本,下次推送仍然从你自己的代码构建。

新版本和任何部署一样过健康检查:智能体必须启动、监听端口、能应答。在我们自己的测试里,修好的副本上线用了2到4.5分钟,取决于错误和代码规模。健康检查失败,自动再跑一次,并告诉它第一次改了什么、发生了什么。第二次尝试路由到最强模型。两次之后停下并说明。人过一阵再点,会开启新的一轮,但之前失败的历史保留着,同一个错误修复不会被以全新的自信再提一遍。

怎么算数

套餐每月包含一定次数的AI修复。只有以智能体通过健康检查收尾的代码修复才消耗一次。解析失败、安全审查失败、构建失败或起不来的补丁,都不计次。每一次模型调用都从套餐的月度AI预算里扣,成本两头都被框住。

失败教给我们的事:记忆

模型很自信,会把同一个失败的修复提两次。所以平台记住结果:

  • 修复被确认健康,就存进你自己的账户。同样的错误、同样的文件,可以不再调用模型直接拿回那个修复。确认过的修复绝不跨账户复用。
  • 补丁失败,记录它的指纹。对相似错误已经失败过两次的补丁直接拒绝。别的客户撞上相似错误时,模型会收到错误签名、错误输出和失败补丁改过的文件名作为警告,但永远拿不到代码本身。

它不做什么

  • 它修的是失败的构建和部署,不是上线几天后才崩溃的智能体。后者现在得到的是重启、崩溃邮件和一份大白话诊断。修复运行中的智能体在我们的公开路线图上。
  • 它没法让智能体比它的负载更小。智能体因超出规格内存被杀,修复方式是更大的规格而不是补丁:确认是真被杀,AI Fix升一档;下一档不在你的套餐里,就停下告诉你。
  • 它需要源码。从现成镜像部署的智能体没有代码可打补丁,诊断仍然会解释失败原因。
  • 它不总是对的,所以两次尝试后停下,所以每个结果都是你能回滚的版本。等上线流量足够让数字诚实,我们会公布真实成功率。

每个套餐都包含AI Fix。如果你有个在笔记本上跑得通的智能体,部署它,故意弄坏它,然后按下那个按钮。