ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

AI Agent开发选型:为什么TypeScript比Rust更高效?

2026/9/10 1:30:10 拓冰建站 浏览量
AI Agent开发选型:为什么TypeScript比Rust更高效? 最近我拿 Rust 写了一个 AI Agent 原型然后又在一个深夜把核心逻辑全部换成了 TypeScript。那次切换让我彻底想明白了一件事很多开发者争论 Rust 和 TypeScript 谁才是 AI Agent 开发的正统语言其实是在错误的赛道上比正确率。AI Agent 的核心不是算力、不是内存安全、不是极致并发而是生态、迭代速度和工程化的综合效率。在这个标准下TypeScript 确实是绝大多数团队的最优解甚至可以说它才是当前 AI Agent 战场上的“神”。当然这个结论很容易被误解成“Rust 不行”。恰恰相反我在后面的章节会专门给 Rust 正名。但如果你想做的是业务型 Agent、工具调用型 Agent、或者面向用户的智能体产品而不是去造 LLM 推理引擎那 TypeScript 的赢面几乎是碾压级的。1. 我的“翻车”经历用 Rust 写 Agent差点把项目写没了1.1 当初为什么选 Rust起因是团队里一位前辈力推 Rust理由很“正当”AI Agent 未来会变成基础设施高并发、低延迟、内存安全Rust 全都能给。听起来没毛病。我当时手上正好有个项目要做的是一个多步骤的客服 Agent用户提问之后Agent 需要拆解意图、查知识库、调用工单系统、生成回复中间还要处理多轮上下文。我信了那套“性能至上”的说法开工第一天就切到了 Rust。初始阶段确实爽cargo new一下类型安全把很多错误挡在编译期而且编译完跑起来飞快。但这种快感只维持了三天等到开始接外部 API、做函数调用、管理多轮状态的时候痛苦就来了。1.2 借用检查器、异步生命周期和找不到的 SDK我用的是reqwest调 OpenAI 接口配合tokio做异步。问题不是这些库本身不好而是整个 Agent 的状态机太动态了。Agent 要维护一个上下文数组数组里既有字符串又有结构化工具调用结果有时还需要 RVec 嵌套。在 Rust 里这些类型要么枚举处理要么用 trait object 做动态分发复杂度直线上升。更深层的痛点是借用检查器和 async lifetime 的碰撞。当我想把 LLM client、工具列表、历史消息全部塞进一个Agent结构体时会因为static生命周期限制、Sendtrait 约束问题反复改代码。更别提那些社区库大多还处于“能跑 demo、不能上生产”的状态有的 SDK 甚至连流式输出都没有完整实现。1.3 换到 TypeScript 后的第一晚切换到 TypeScript 之后第一晚我就把之前的 ReAct Agent 核心逻辑重新写了一遍。定义工具、调用 LLM、解析流式输出、维护上下文整个过程行云流水。第二天下班前原型就上线了还接了一个简单的 Web 对话框。第三天开始做工具调用自动纠错和异常重试这在 TS 里就是几十行代码的事。所以当我看到“Rust 输了”这个说法时第一反应是不认可——毕竟 Rust 并没有“输”它只是不适合做 Agent 业务层。但第二反应是认同如果要给“最适合当前 AI Agent 应用开发的通用语言”投一票我会投给 TypeScript而且不会有任何犹豫。2. AI Agent 不是性能游戏而是“生态与迭代”的游戏2.1 Agent 的本质大量的外部调用和状态流转要理解为什么 TypeScript 更适合得先看清 AI Agent 到底是什么。Agent 不是一个算法密集型的组件不像搜索引擎排序或者视频编解码它本质上是一个“协调器”接收用户输入把任务拆解成若干子任务选择工具调用外部 API把结果反馈给 LLM再继续循环。这意味着 Agent 的运行时主要花在等待外部服务响应上LLM 推理要几百毫秒到几秒工具调用走网络又要几百毫秒。语言本身的性能在这种场景下占比极低。真正决定项目成败的是你写 Agent 逻辑本身花了多少时间改需求的时候能不能快速响应以及遇到 LLM 输出格式变化时代码能不能扛住。2.2 一张表看懂两个语言在 Agent 开发中的真实差异我根据自己的实测和观察整理了一张对比表维度TypeScriptRustAgent SDK/框架成熟度高Vercel AI SDK、LangChain.js、Mastra、OpenAI JS SDK 等低rig、agenture 等较新且不完善LLM API 客户端质量官方 SDK 基本都是 TS/JS 优先依赖社区封装流式/函数调用支持参差原生类型系统灵活联合类型、泛型、可选字段便于处理动态结构强但刻板处理动态 JSON 结构成本高异步开发体验async/await Promise.all极简需要处理 Send、lifetime、pin学习曲线陡状态机/图编排可以自由修改对象序列化方便数据竞争由编译器保证但表达复杂状态图很累部署生态Vercel、Cloudflare Workers、Vercel Edge、Node 服务都成熟编译为原生二进制部署链路相对重人才供给前端/全栈开发基本都会 TS招聘难度低熟练 Rust 工程师难找成本高内存安全和性能有 GC性能尚可内存占用较高性能极强安全特性业界顶尖但对 Agent 收益有限这张表不是否定 Rust而是点出一个关键事实在 AI Agent 这个具体业务场景中Rust 的“性能优势”被无限稀释而它的“开发复杂度”却被无限放大。2.3 在 Agent 项目里需求变化是常态我做过好几个 Agent 项目几乎没有一个需求是稳定不变的。提示词要改、工具参数要加、上下文策略要换、LLM 模型从 GPT-4 切到 Claude 或者本地模型。这种快速试错的节奏决定了语言必须有很强的“动态适应能力”。TypeScript 的动态类型配合可选的严格模式天然适合这种场景。你可以先用type定义一个大概的形状后边再慢慢收窄你可以临时给工具对象加一个字段不用像 Rust 那样先定义枚举再全链路匹配。团队协作时这种灵活性可以大大缩短“需求变更—代码改动—上线验证”的循环。3. TypeScript 的“基础设施红利”从 SDK 到协议几乎全是亲儿子3.1 你想要的 Agent 框架TS 几乎都有现成的这是 TypeScript 最“躺赢”的地方。AI Agent 的底层逻辑其实已经逐渐标准化了模型调用、工具注册、Memory、Retriever、Agent Chain、多 Agent 协作。这些概念在 TypeScript 生态里基本都有库可以直接用。我用得最多的是 Vercel AI SDK。它把流式对话、函数调用、React hooks 都封得很完善streamText一行就能输出流式结果还能直接对接 Vercel Edge Runtime。Mastra 和 LangChain.js 则提供了更抽象的 Agent 编排能力。如果不想用大而全的框架原生 TypeScript 写一个 Agent 核心也没多少代码后面我会给出完整示例。3.2 MCP 协议把 TypeScript 推上了“官方轨道”还有一个大变化是 MCP也就是 Model Context Protocol。这个协议让 Agent 可以统一接入外部数据源和工具是当前 AI Agent 生态的关键基础。Anthropic 发布 MCP 时官方 SDK 提供的第一批语言就是 TypeScript 和 Python。后续各种 Server SDK 层出不穷TypeScript 版本依然是社区维护最活跃的那个。Rust 也有 MCP SDK但成熟度完全不在一个等级。拿我自己的体验来说在 TS 里写一个 MCP server几分钟就能跑通在 Rust 里光是处理 JSON-RPC 的生命周期和并发就得折腾不少时间。如果 Agent 最终要以统一协议对外提供能力TypeScript 就能帮你节省大量重复劳动。3.3 前端、后端、自动化全链路都是 TS开发心智负担最低Agent 通常不是独立存在的它要被包在聊天 UI 里、或者被做成 API 服务、或者接到自动化工作流里。TypeScript 最大的杀手锏是“全栈同构”前端 React/Vue 写界面后端 Node 写服务Agent 的逻辑可以直接统一复用类型定义。这种同构的价值平时看不出来但一旦你的 Agent 需要把工具调用的中间结果实时渲染到前端或者需要把同一个 Agent 实例跑在 SPA、Node server、Cloudflare Worker 里差别就非常明显了。Rust 当然可以通过 WASM 跑在浏览器里但开发和调试的复杂度依然高很多。4. 从编码到手撕代码TS 的类型系统与异步模型为什么更适合 Agent 状态机4.1 用一段真实代码对比 ReAct Agent 的核心类型定义我尽量不空谈直接看代码。一个简单的 ReAct Agent核心是“工具列表 上下文消息 LLM 循环”。在 TypeScript 里工具类型可以定义得非常自然type Tool { name: string; description: string; inputSchema: Recordstring, unknown; execute: (args: any) Promisestring; }; type AgentContext { history: Array{ role: user | assistant | tool; content: string; toolCalls?: Array{ name: string; arguments: unknown }; }; };然后在循环里工具返回的结果可以直接 push 进 history。因为数组可以动态增长对象形状可以随意扩展Agent 的 ReAct loop 写起来很直观IDE 的自动提示也不会丢。这在 TypeScript 里是日常操作。换成 Rust 呢你大概率要定义枚举enum Message { User(String), Assistant { content: String, tool_calls: VecToolCall }, Tool { name: String, content: String }, }然后每加一种消息类型所有匹配这个 enum 的match分支都要改一遍。更麻烦的是工具执行结果可能来自不同外部系统它们的结构各不相同为了放进同一个Message::Tool你得先做一层序列化。不是说 Rust 做不到而是这种琐碎的样板代码会不断消耗你的精力让“实现 Agent 逻辑”变成“伺候类型系统”。4.2 动态图编排所有权机制反而成了束缚Agent 项目里有大量“图”结构节点是工具或 LLM 调用边是依赖关系。TypeScript 里你可以用普通对象来声明式地创建 DAG或者用Map保存节点随时增删改任何边。这种灵活性对快速实验至关重要。Rust 里做同一件事会经常碰到自引用结构体的问题。比如一个 agent graph 节点可能持有 LLM client 的引用同时又要被多个其他节点引用。Rust 的所有权机制会强制你引入RcRefCell、ArcMutex或者干脆把所有数据都放到一个 arena 里用索引访问。这不只是代码写起来麻烦更严重的是让初学 Rust 的人根本没法专注于 Agent 本身的算法设计。4.3 异步并发Promise.all 比 tokio 的 spawn JoinAll 省心太多Agent 经常要同时调用多个工具或者并行查询多个知识库最后汇总结果。TypeScript 的写法简洁到不需要思考const [weather, calendar, userProfile] await Promise.all([ getWeather(city), getCalendar(date), getUserProfile(userId), ]);而 Rust 的异步生态虽然也很强但在 Agent 这种偏业务动态调度的场景下futures::future::join_all还得配合生命周期处理特别是当多个将来要借用同一个对象时很容易写出让自己都崩溃的编译错误。不是说 Rust 写不出优雅的并发代码而是这种优雅通常需要额外封装对业务优先的 Agent 开发来说很不划算。5. 别再被“性能”忽悠了Agent 场景的性能瓶颈在 API不在语言5.1 算一笔延迟账LLM 和外部 API 占了 99% 的时间我经常会遇到一些人说“Rust 性能好所以做 Agent 更快。”这种观点其实建立在“性能 语言运行速度”的简单思维上。我们来算一笔账一个常见的 Agent 请求会经历接收用户输入几毫秒第一轮 LLM 调用大概 500 毫秒到 3 秒解析 LLM 输出识别工具调用几毫秒调用外部工具 API通常 200 毫秒到 1 秒把工具结果回传给 LLM 做第二/第三轮推理又几百毫秒到几秒整个链路里TypeScript 和 Rust 的差距只在“几毫秒”级别的解析和调度上而且随着 LLM 调用次数增多这个差距基本可以忽略。真正决定用户体验的是上游 API 延迟。就算你把 Agent 引擎换成 Rust用户也不会感觉到任何区别。5.2 我实测过的 Node.js 和 Rust 网关对比我之前为了验证这个结论把一个 Agent 的 API 网关部分分别用 Node.jsTypeScript和 Rustaxum实现了一次。在纯转发场景下Rust 的 QPS 确实比 Node 高不少大概 2 倍左右。但一旦接入真实 LLM 和外部工具调用两者的整体吞吐差距降到 5% 以内因为所有请求都阻塞在上游响应。这还没算 Rust 版本多花的开发时间。如果整个 Agent 系统有一百个接口TypeScript 可能三天写完Rust 可能要十天而且后期维护成本更高。用“用户根本感知不到”的性能优势换取开发效率的巨大劣势这买卖怎么看都不划算。5.3 Rust 真正大幅领先的局部场景当然我也遇到过必须用 Rust 的场景。比如一个高速并发抓取和清洗外部数据的 Agent 中间层每秒要处理几千个 Webhook 回调并做协议解析、数据清洗、规则过滤。这时 TypeScript 单线程事件循环就比较吃力Rust 的多线程并行处理能力就能发挥优势。但这属于 Agent 的“数据管道”和“基础设施”而不是 Agent 的“智能决策层”。如果在系统里遇到了这类性能热点我的建议是单独用 Rust 做微服务对外暴露 gRPC 或 HTTP 接口TypeScript 负责整个 Agent 业务的编排两者各司其职。这个混合架构我后面会详细展开。6. 一个“能上线”的 TS Agent 项目我到底写了什么6.1 整体架构与目录结构我分享一个已经稳定跑在生产的客服型 Agent 项目。技术栈是 Fastify Vercel AI SDK Qdrant 向量库 MCP 工具服务。核心结构大致如下src/ agent/ tools/ // 各类工具 core.ts // Agent 主循环 context.ts // 上下文管理 memory.ts // 短期/长期记忆 llm.ts // LLM 调用封装 server.ts // Fastify HTTP 服务 mcp/ server.ts // 对外 MCP server这个 Agent 需要处理用户的售后问题判断问题类型、调用订单系统、查询物流信息、给出退换货建议。它不是最复杂的架构但足够代表大多数业务型 Agent。6.2 Agent 主循环的 TypeScript 实现要点Agent 主循环的核心是“LLM 输出 → 解析工具调用 → 执行工具 → 回填上下文”的循环。我会用 TypeScript 实现一个极其简化的版本方便理解async function runAgent(userInput: string, tools: Tool[], maxIterations 5) { const context: AgentContext { history: [] }; context.history.push({ role: user, content: userInput }); for (let i 0; i maxIterations; i) { const response await callLlm(context.history, tools); const toolCalls extractToolCalls(response); if (toolCalls.length 0) { return response.content; } for (const call of toolCalls) { const tool tools.find((t) t.name call.name); const result await tool!.execute(call.arguments); context.history.push({ role: tool, content: result, toolCalls: [{ name: call.name, arguments: call.arguments }], }); } } throw new Error(Agent 达到最大迭代次数); }这段代码如果移植到 Rust最大难点不是逻辑本身而是tools数组里的每个工具都有不同的入参类型。在 TypeScript 里你用unknown、类型守卫、zod校验就能解决在 Rust 里你得用Boxdyn Tool或枚举统一签名灵活性差很多。6.3 工程化细节和踩坑经验Agent 上线之后真正考验人的其实是各种边界情况。我整理了四个必须注意的点结构化输出必须加 schema 校验LLM 返回的 JSON 偶尔会多一个字段或少一个引号。我用zod定义输出类型在入口处做 parse一旦校验失败就自动让 LLM 重新生成一次而不是直接崩溃。这个机制在 TS 生态实现非常成熟Rust 里则需要引入较重的 serde 反序列化错误处理。重试策略必须和“幂等性”绑定Agent 调用工具时如果第一次调用超时自动重试会导致业务数据重复创建。我的方案是每个工具都带一个requestId在外部系统里做幂等判断。TypeScript 闭包特性让携带requestId变得很自然。流式输出和工具调用走两条通道如果用户等一个 Agent 处理多个工具千万别一次性把过程全用事件流发出去。我用的是 Fastify Server-Sent Events先给前端发“正在使用 XX 工具”的状态等最终答案再流式打印 LLM 文本。Vercel AI SDK 对流式支持很好Rust 需要自己手写 SSE 协议。上下文裁剪必须提前做大部分 Agent 的多轮对话最终会卡在 Token 限制上。我的策略是只保留最近 6 轮全量消息更早的按摘要压缩。这个策略用 TypeScript 写非常灵活一个数组方法就能完成。6.4 部署体验边缘运行时是真省心想重点夸一下 TypeScript 的部署体验。同一个 Agent 引擎我可以很轻松地从本地 Node 服务迁移到 Cloudflare Workers 或 Vercel Edge Functions 上。尤其前端 Next.js 项目里Agent 接口可以直接写成 Next.js Route Handler和页面一起发布。整个过程不需要关心容器、二进制跨平台编译也没有 Rust 那样折腾 musl 工具链的问题。7. Rust 也没输混合架构里的正确打开方式7.1 工具型的 Agent不一定非要用 Rust前面说了这么多 TypeScript 的优势但千万不要误解成 Rust 一无是处。实际上Rust 在 AI Agent 领域的角色正在变得越来越清晰它是“镰刀”也就是制造 Agent 底层的下一层基础设施而 TypeScript 是“驾驶员”负责实际的业务调度。如果你在做 Agent 开发框架、Agent 网关、共享调用追踪系统、高性能向量检索组件那么 Rust 仍然是很棒的选择。这类组件往往处于整个系统的核心链路对延迟和并发要求极高而且它们的 API 面相对稳定不会频繁变化正好能发挥 Rust 的编译期检查优势。7.2 我的混合架构TS 编排 Rust 高性能内核我现在最喜欢的架构长这样整个 Agent 业务层完全用 TypeScript 写包括工具选择、上下文管理、对话循环、外部系统对接。然后针对真正有性能瓶颈的环节用 Rust 写一个独立服务通过 JSON-RPC 或 HTTP 暴露给 Agent 调用。举个例子我的一个数据清洗工具需要从大量非结构化文本中提取关键词同时计算文本相似度。这部分我用 Rust 写了一个独立 worker利用 rayon 并行处理吞吐量提升非常明显。Agent 主流程依然是 TypeScript只是把那个工具的执行函数指向 Rust worker 的服务地址而已。这种混合架构的好处是你不需要让整个 Agent 团队都会 Rust只需要一两个对 Rust 熟悉的人负责性能敏感模块其他人依然在 TS 生态里高效开发。7.3 给 Rust 开发者的一句话如果你对 Rust 有热情完全可以继续深耕。未来的 AI Agent 底层工具链、嵌入式 Agent 设备、边缘计算节点都会大量用到 Rust。但如果你是要快速交付一个商业 Agent 产品请放下“用 Rust 才能证明技术品味”的想法。在 Agent 应用层Rust 的学习曲线和生态瓶颈会拖慢整个团队。8. 选型建议什么人该用 TypeScript什么人可以坚持 Rust8.1 我的建议清单独立开发者 / 小团队 / 创业公司无脑 TypeScript。你们的核心竞争力是快速验证想法而不是征服编译器的生命周期。全栈工程师 / 前端团队TypeScript 是主场。Agent 业务逻辑需要和前端强互动选择 TS 能最大化复用代码。后端团队已有 Node 或 Java 技术栈如果目标只是做上层 Agent 应用我还是推荐 TypeScript。直接用 Node 生态即可不需要引入新的重型语言。性能基础设施团队可以继续用 Rust。网关、向量检索、高并发调度器、嵌入式设备 Agent 这些地方Rust 仍然是最佳选项。学术研究者如果你研究多 Agent 协作算法且不在乎工程效率Rust 会让你写出更精致的系统但如果需要频繁修改实验逻辑TS 才更适合你。8.2 不要神化任何语言回到标题“TypeScript 才是唯一的‘神’”这句话我理解其实是一种“效率信仰”。在当前这个时间点AI Agent 的舞台确实由 TypeScript 主导因为它是连接底层模型、业务系统和用户界面的最短路径。生态、工具链、人才池这些都是实打实的生产力。但“唯一的神”这种说法放在严谨的工程语境里是危险的。没有万能语言只有场景适配。Rust 没有输它只是换了一条赛道TypeScript 也不是无所不能只是在这个战场上的匹配度更高。选择语言的本质是选择一种团队协同和交付节奏而不是为语言本身的荣辱买单。我自己现在的习惯是上手新 Agent 项目默认 TypeScript遇到性能热点再考虑引入 Rust 做局部强化。这种组合让我既保持了开发效率又满足了少数场景的极致性能。如果你也被“Rust 和 TS 选哪个”折磨过我的建议是先认真分析一下项目瓶颈在哪里。如果你的瓶颈是“代码写都写不完”那答案已经很明显了。