AI 编程AI Agent

AI 开始写 agent 的执行层:Rust 的胜出理由,和它的三个漏洞

AI 自己把执行层重写了一遍

过去一年多,有几个核心团队在把底层执行层用Rust重写。这类重构往往涉及几十万甚至上百万行代码,核心代码不再是工程师手工敲出来的,而是大部分由自主运行的AI coding agent批量生成。AI 开始自己写这套基础设施了。于是问题变成:这一层到底该用什么语言来写,Rust 是不是最合适的那个?

从传统的工程经验出发,给基础软件换个编程语言,没几年时间和整个团队的投入是搞不定的。但 AI 把代码转换的边际成本降下来了,原来几年的人肉迁移,几天或几个月就能搞定。四家代表性项目公布了各自的细节:

项目 原技术栈 重构后规模 AI 参与度与周期 官方自报效果
GitHub Copilot runtime Node.js 与 V8 上的 TypeScript 超过 80 万行生产级 Rust AI agent 写下大部分代码、经 128 个 PR 合入,约 43 万行 TypeScript 经手迁移,单名开发者数月内交付,token 花费约 12 万美元 厂商自建 benchmark:单轮交互耗时由 5.25 秒降至 292 毫秒(进程内提升 18.0 倍),会话吞吐量由 7.55 提升至 120.0 sessions
Bun 53.5 万行 Zig(不含注释) 超过 100 万行 Rust 约 50 个 Claude Code 动态工作流持续运行 11 天,API 标价折合约 16.5 万美元 官方自报:跨语言链接时优化使 HTTP 吞吐与构建提升约 2%–5%
Prime Agent TypeScript 完整迁移至 Rust 2000 多个 agent 在超 10,000 个沙箱中消耗 2000 亿 token,两周完成主体重写、随后数周补齐到发布质量;人类主要负责建立自动化验证流程 厂商自建 benchmark(注明无统一标准需谨慎对比):冷启动由 736.1 毫秒降至 51.9 毫秒,大 session 内存常驻由 1130.0MB 降至 237.3MB
OpenAI Codex CLI Node.js(原需 Node v22+) 核心 harness 选用 Rust 官方定位核心功能为循环调用模型的 agentic harness,该讨论未披露 AI 参与度 官方列举零依赖安装、原生 Linux 沙箱绑定、无 GC 降低内存消耗、扩展协议四条理由

GitHub Copilot 在运行中的迁移博客提到,以前需要整个团队花一两年的工作量,在 agent 的帮助下,一个人几个月就可以完成,但文章中特别指出,这并不意味着所有大型 TypeScript 项目都应该转向 Rust。Bun 官方在重写公告中也表达了类似的意思。它原本是个 JavaScript 运行时和工具链,不少 coding agent 就跑在它上面。在官方看来,过去选择编程语言就像买了一张单程票,一旦选定,只能接受现实,但现在 AI 正在改变这一切。Prime Intellect 的重写记录和 Codex 仓库的技术讨论也展示了类似的趋势。

执行层到底在干什么

聊技术选型之前,先得看看 agent 在系统里具体都在干什么。通常所说的执行层,指的是 agent 在宿主机器上的执行核心。

具体到 coding agent 的执行过程,你看到的屏幕背后其实是很多高密集的系统操作。核心的一个事件循环负责组装上下文、发送 prompt 给模型,同时实时解析模型的输出以触发相应的工具调用。它可能需要在本地启动子进程、把文本命令打入 shell 管道、监控 stdout/stderr、管理毫秒级的超时、处理外部的中断信号。在前端方面,它可能要把代码的 diff 实时渲染到终端上,管理交互式的 cursor,捕捉用户的键盘事件和窗口拉伸。在系统层面,它可能要在内核里搞一个轻量级的 sandbox 来限制文件的写入,隔离网络命名空间。最后,它可能还要打包成一个漂亮的动态库,给外层的 SDK 提供跨语言调用支持。

这种组合让执行层的运行特征相当典型。它是一个常驻进程,经常要在开发者的终端/服务器上面挂上几个小时甚至几天。它直面不可信代码和外部脚本,脚本稍微有点出格,就可能误删文件或者越权读取。它还是个多线程调度的十字路口,后台在收流式网络包,前台在画终端字符,旁边还在沙箱里管着子进程的生老病死。在这样的环境里,哪怕漏掉一次内存释放、出现一次死锁,或者指针出了偏差,终端就可能直接卡死,留下满地的孤儿进程。

为什么是这一层

执行层上述苛刻的要求,恰好撞上了四个典型的工程约束。在团队们的官方解释中,Rust 的特性恰好卡在每一个痛点里。

第一道关是分发成本。CLI 和桌面/本地小工具是直接部署在用户电脑上的,装一步少一步都会劝退。Codex 早期依赖 Node.js 22+,很多机器没有现成的高版本运行时,上手门槛就高了。Rust 可以分发成不依赖 Node.js 的原生二进制,扔到系统里就能跑,不要求宿主另装 Node.js,真正做到开箱即用。

第二道关是进程内嵌入。很多底层执行层需要作为公共核心,被不同语言的客户层集成。比如 GitHub Copilot 的重构运行时就要直接嵌入宿主进程,通过标准 C 接口暴露给多达六种 SDK 语言。Rust 天然兼容 C ABI,跨语言调用非常轻量,无缝打包到宿主进程里。

第三道关是拿到可预测的内存表现:常驻进程、每会话独立进程、不带 GC 是一种架构选择,而 Rust 恰好让这种架构更容易落地。执行层经常要拉起成千上万个并行沙箱,会话上下文还会持续膨胀。在带运行时的脚本语言里,每个进程都得背一套虚拟机和垃圾回收器。高密度的运算和高频 I/O 挤在一个事件循环里,GC 一旦停顿,终端界面就会卡一下。Prime Agent 拿掉 JavaScript 运行时和 GC 之后,大 session 的内存常驻从 1130.0MB 降到了 237.3MB(厂商自建 benchmark),一下给并发沙箱腾出了可观的物理内存。

第四道关也是AI编程时代最大的变量:让编译器当自动化的质量门禁。AI写绝大多数的代码,人类根本不可能逐行看几千上万行的diff,只能靠确定性的工具在前端卡死低级错误。TypeScript的类型在运行时荡然无存,逻辑漏洞常常用未捕获的异常直接炸出来。但在安全Rust里,所有权、生命周期、穷尽模式匹配,加上Send和Sync线程安全约束,在编译那一步就把数据竞争、悬垂指针这类内存安全隐患直接掐灭。

Bun 在公告中解释过,他们的许多历史 bug 往往出在异常处理部分,比如释放后使用、双重释放或忘记释放。在安全 Rust 中,这些情况甚至无法通过编译。Bun 团队认为,编译器报错比代码规范提供了更好的反馈循环。Prime Intellect 也指出,编译器结合 Clippy 对大量 AI 生成的代码进行严格静态检查,能够在程序运行前排除多个维度的缺陷。因此,工程师的核心任务是给机器生成设计验证机制。

但这里有三个漏洞

这套话乍听很顺。但真扔到实际工程里,会发现三个填不上的坑。

第一个坑是市场和技术的脱节。市场在吹 Rust,但如果你去看现在最流行的、大家天天用的执行层工具,主流那一批其实还是 TypeScript。

仓库 / 工具 核心代码构成(GitHub API 字节口径) 近一月 npm 下载量(截至 2026-10-10,含 CI 与镜像噪声) 分发形态与语言选型事实
anthropic-ai/claude-code TypeScript(根据泄漏与安装包) 约 58.7M npm 包要求 Node >= 22.0.0;官方从未发布语言选型声明;SDK 文档标明按平台分发原生二进制
anomalyco/opencode TypeScript 78.7% 约 11.8M 开源 coding agent,核心逻辑与运行时主体为 TypeScript
google-gemini/gemini-cli TypeScript 97.1% 约 1.8M 官方命令行工具,以 TypeScript 为绝对主力
cline/cline TypeScript 97.9% 未采集 知名开源 VS Code 插件与 agent 执行框架
openai/codex Rust 97.1% 约 97.6M 核心 harness 采用 Rust,发布原生二进制
aaif-goose/goose Rust 71.5%,TypeScript 23.6% 未采集 Goose 官方文档明确声明基于性能与可移植性选用 Rust

如果我们去看这些工具的实际代码的话,包括Claude Code、Gemini CLI、opencode、Cline等等,其实它们的核心交互都还是TypeScript实现的。在2026年一个Claude Code的源码泄露事件里,出现了大约51.2万行TypeScript的代码。第三方的分析认为这是打包器的一个bug造成的,但至少提示了这些流行工具的骨架与成熟的 TypeScript 前端生态关系密切。从敏捷性、生态支持、前端协作的角度来看,TypeScript仍然占据着巨大的市场份额。这张表里六行只有 Codex 和 Goose 是 Rust,其余主力都还是 TypeScript,这就是落差所在。

第二个坑是性能光环下的水分。行业里习惯把 Rust 和高性能画等号,但要是只换语言、不动整体架构,测出来的差距往往小得可怜。Bun 把整套底层代码用 AI 从 Zig 重写成 Rust,在 Bun 官方的重写公告里,官方自报的 HTTP 吞吐和构建速度只提升了 2%–5%,而且这点微弱增益主要来自跨语言的链接时优化。这跟大众心里换了 Rust 就能脱胎换骨的预期差得太远。再回头看厂商自建 benchmark 里 Copilot 的约 18 倍提速,或者 Prime Agent 的约 14 倍冷启动优化,对比就能看出一件事,而且这还只是个推论:那些十几倍的跨越,很大程度上来自架构重构带来的红利。团队把跨进程通信改成了进程内嵌入,落地了常驻进程、每会话独立进程、不带 GC 这一整套架构选择;而 Bun 没动原有架构,只换了实现语言,所以只有几个百分点的收益。光换一套语法收益有限,顺势把底层架构翻新一遍,性能也可能因此大幅提升。

同样叫 AI 重写,收益差两个量级:只换语言的 Bun 只有 2–5%,换语言又换架构的 Copilot 与 Prime Agent 达到十几到十八倍。

第三个坑是把编译器当万能挡箭牌,这里头有两个硬伤。其一,内存安全不只一条路。Google 做的容器沙箱 gVisor 处在系统的险要位置,它选用了一种内存安全语言(Go),Go 的带 GC 的运行时同样守住了内存安全。其二,Rust 的安全保证也有边界,安全 Rust 也不是免死金牌。Rust 官方教程引用循环章节白纸黑字写着,编译器不保证杜绝内存泄漏,引用计数的循环引用照样漏。Rust 死灵书对竞态的定义也说明,语言层面的并发保证只管底层数据竞争,死锁或业务逻辑里的竞态条件编译器不管。直接调用未经安全封装的底层接口或 FFI 时,往往需要 unsafe,这些边界实现的内存安全兜底责任又回到实现者手里(参见 Rust 官方参考手册对未定义行为的说明)。即使是在强调安全的 Bun 里,据官方自报,新代码仍然约有 4% 包在 unsafe 块中,里面有大约 13,000 个 unsafe 关键字。

第三个坑还有更棘手的一面:用编译器当自动化验收门,前提是团队里得有人看得懂 AI 写的 Rust。在 Hacker News 上的团队复盘讨论里,一个机器学习团队分享了真实的过度工程踩坑记:让 AI agent 做一个只要动一两个文件的小功能,结果 agent 一路改动了 40 个文件;提示者却可能因经验不足而识别不出这些过度工程和其他问题。更麻烦的是,靠编译器兜底两头都不省心:红灯拦下的报错模型自己修不利索,微软研究院关于 RustAssistant 的论文给出的数据是,大模型修复现实中 Rust 编译报错的峰值准确率只有约 74%;而绿灯放行的代码人类看不懂,也同样防不住逻辑漏洞。在 Yusuke Endoh 的多语言评测记录里,用 Claude 写简版 git 共跑了 600 次实验,Rust 的 40 次运行里有 2 次没过测试,与 Haskell 同为出现失败的两种语言。如果团队没有真正懂 Rust 的老手坐镇把关,编译器一路绿灯放进来的代码,迟早会变成没人敢动的烂泥潭。

编译器能不能当老师:飞轮与它的反证条件

三个坑都摆在这里了,按理说该收手。可几个主力团队偏偏还在往 Rust 上加注,这就牵出一个更远的猜想:编译器能不能反过来给模型当老师?

摆在眼前的事实是,现阶段语言模型写复杂 Rust 代码的水平确实有限。在 Multi-SWE-bench 评测(arXiv:2504.02605)里,GPT-4o 处理现实里的 Python 缺陷能解决约 36%,换到 Rust 却不到 6%(Go 和 TypeScript 也都在个位数打转)。面对真实工程里的复杂 Rust 缺陷,这次评测里 GPT-4o 的成功率确实还在低位徘徊。

但 Rust 有个独特优势:它的错误信息又详细又整齐,甚至有时直接给出修复建议。无论是类型不匹配、借用越界,还是遗漏 trait 实现,rustc 的诊断信息往往能精确到字符级别,清晰展示因果关系。这种完全自动化、由程序生成的丰富反馈,正是强化学习/agent 梦寐以求的自我修正信号。Prime Intellect 也在博客中引用了相关研究(Karten 等人在 COLM 2026 发表的文章),探讨如何将自动生成的 RL 环境融入闭环,用机器验证来指导生成。

把这个循环串起来看:编译器报错变成机器可读的奖励信号,让模型更会写 Rust,进而产出更多 Rust 代码和训练与评测环境,再回到起点形成闭环。编译器推动的正是这样一个自我进化的飞轮。注意这是个推论,目前尚无证据支持。面对模型现在写不好 Rust 的现状,其实有两种互斥的解释:一种认为自回归生成与借用检查的范式冲突构成了硬上限;另一种则认为这只是因为公开训练数据少、生态经验少,并不是模型的推理极限。本文押注的是后一种解释:在数据补齐的前提下,Rust 的编译器提供的是确定、结构化的机器反馈,天然适合做强化学习的练兵场。当模型在海量编译错误中反复试错、自我修正,它对 Rust 的生成和维护能力很可能会呈现一条比动态语言更陡的学习曲线。

一个严肃的推论必须提供可证伪的条件。要否定这个飞轮假说,就盯住前一种互斥解释:Rust 的借用检查需要全局一致的生命周期设计,这种全局性可能天然与自回归模型逐 token 生成的局部性相悖。若这种范式冲突是硬上限,确实限制了模型能力,那么再给它多少编译报错也无济于事,它只会不断重复修改却难有实质性提升,从而让飞轮陷入僵局。判断真假的标准是两点:一是未来的大模型是否能在 Multi-SWE-bench 的 Rust 题上突破个位数;二是对真实的 Rust 编译报错,模型能否实现远超 RustAssistant 论文报告的约 74% 峰值的自我修复。

编译器飞轮:模型在编译报错上的自我修正反过来提升写 Rust 的能力;但若借用检查的全局性与自回归生成的局部性冲突成为硬上限,飞轮就会卡死。

说到底,这套飞轮的要害在于把编译器的结构化反馈变成了模型自我修正的确定性信号。但它能不能真正转起来,前提是模型能否跨过借用检查这道坎。如果全局生命周期的范式冲突真是一堵不可逾越的硬上限,再详尽的报错也只会让模型在局部修改中空转;只有当模型在真实基准与修复上跨过这道门槛,这种机器反馈才能转化为能力跃升,编译器也才真正算得上是推动模型自我进化的老师。

结论之外,更想分享的是这套拆法

从执行层的工程现实一路推导到编译器的飞轮假说,聊到这里,我其实并不想证明 Rust 是什么放之四海皆准的好语言。把这件事情理顺之后,我更想分享自己刚琢磨明白的一套拆法:先弄清对象在系统里具体负责什么,再推导它面临哪些硬性的工程约束,最后检验候选技术是不是真的匹配这些约束,在什么条件下成立,边界和反例又在哪里。

先问它是什么、要什么,再问谁满足:先弄清对象,再推出约束,最后检验匹配与边界。

Rust 成为执行层的默认候选之一,只是这套拆法在当前场景下的一个例子,换到别的场景完全可以有不同的结论。相比结论本身,我更想留下的是一套顺手就能搬到别的领域的拆法:不去追一刀切的宏大答案,先把问题收敛到一个具体对象的物理约束上,再去检验匹配度、前提条件和失效边界。我自己试下来,这套顺序换到其他技术选型或者复杂决策里,用着也挺顺。

鸭哥每日手记

日更的深度AI新闻和分析