生产环境报错,其实特别适合交给AI代理处理。有堆栈信息,有代码仓库,"做完"的标准也很明确:一个等人审核的Pull Request。
但这类工具通常长什么样?你把仓库的读权限交给一个SaaS服务,往往连AI密钥也一起交了,然后祈祷一切顺利。所以作者从一条规则出发:负责协调代理的服务,永远不该有能力读取代码。
下面所有设计,都是从这条规则推出来的。
拆成两半:控制面碰不到代码
整个系统分两部分。控制面知道报错、配置和运行历史;运行器跑在你自己的GitHub Actions里,代码和AI密钥都在它手上。
流程是这样走的:
- 错误追踪器送来一条报错。
- 控制面找到映射的仓库,在里面启动一个workflow。
- 在你的运行器里,代理探索已检出的代码,写出修复。
- 修复提交到新分支,开出一个Pull Request。
- 运行器把状态、PR链接、摘要和token用量报回去。
控制面是一个GitHub App,只有两个权限:Metadata读,以及Actions读写。没有Contents权限。它没法克隆你的仓库,也读不了任何文件。它能做的只有一件事:用workflow_dispatch启动一个workflow。
workflow本身住在你的仓库里,所以你能看清它到底跑了什么。AI密钥是你仓库里的secret,控制面从头到尾看不到它。
一个只能用一次的令牌
运行器需要拉取报错上下文、上报结果,而GitHub没法向这个服务证明它的身份。于是控制面签发一个单次运行的令牌,作为workflow输入传进去:
- 它是对运行id和过期时间做的HMAC签名,有效期30分钟。
- 它只作用于一次运行,只能读这次运行的报错上下文、提交这次运行的结果,别的都干不了。
- 它在任务日志里被
::add-mask::遮掉。
作者纠结过的点是:workflow输入会显示在运行页面上。任何能看你仓库Actions运行记录的人,都能在令牌过期前看到它。所以它必须短命、范围窄,而不是一个指望没人去看的长期凭证。
四个工具,没有Shell
代理只有四个工具,没有Shell,也没法自己发网络请求。原因是模型的输入有一部分受攻击者影响:报错信息、堆栈、代码注释里,可能藏着别人写的文字。一个只能读文件、产出diff的代理,爆炸半径很小,而且diff还要过代码审核。
读取走一个路径守卫,拒绝../逃出检出目录。搜索用的是git grep -l -I -F,最多返回20个文件名。修复只在一个地方落地:create_pull_request新建分支、以bot用户提交、推送、开PR。它从不推送到你的基础分支,也从不合并。
这个设计的代价很实在:代理没法跑你的测试。它能读测试文件、能提一句,但执行不了任何东西。作者认为眼下这是对的默认值,但不确定永远都对。
循环有预算
循环在30次工具调用或20分钟墙钟时间里停下,谁先到算谁。workflow的任务超时是25分钟,留出开PR和上报的余量。
真正要紧的细节是:每次模型调用只拿到剩余的时间,而不是固定超时。没有这一条,第19分钟来一个慢响应,就能把任务拖过超时,这次运行永远不会被标记为结束。
几个坑
- GitHub默认拒绝来自Actions的PR。仓库默认关掉"允许GitHub Actions创建和批准Pull Request",workflow里的
pull-requests: write也覆盖不了。推送成功,开PR却返回403。现在这被当成单独一种情况处理:分支保留,运行失败并明确告诉你该翻哪个设置,拟好的PR文本也留着,工作不丢。 - 把易变数据挡在运行器外。模型价格变得勤,早期action自己算成本,每次调价就得发新版本。现在action只上报每次模型请求的token用量,控制面用自己的价目表算钱。加模型、改价格都不用发版。
- 较新的OpenAI模型通过Responses API做工具调用,所以OpenAI适配器走的是Responses API。支持多家供应商时,把每家藏在一个小适配器后面,返回同样归一化的"turn"。
- JavaScript action直接从仓库运行,没有安装步骤,打包好的
dist/index.js必须提交。用户引用一个移动的主标签@v1,每次发布也打标签以便固定。 git add -A是个陷阱。PR提交会把工作区里所有东西都暂存。如果有人在action之前加了构建步骤,产物就会跑进PR里。
什么会离开运行器
"你的代码从不离开你的基础设施"这句话是错的,准确的说法是:控制面永远收不到你的源代码。代理的摘要是模型自己写的文字,所以它可能提到文件名或短片段。
它不跑你的测试,不保证修复正确,也从不合并。默认指令要求最小diff、不加新依赖、不改测试;代理没把握时,应该只开一个带防御性守卫的PR,并附上"Uncertain fix"一节,说明审核者必须检查什么。
作者留了几个问题:你会让代理从生产报错开PR吗?该不该让它开PR前先跑测试——那意味着给它Shell,爆炸半径就回来了。路径守卫够不够,还是该解析符号链接、把任务放进没有secret的容器里跑?
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.