我创有一个 AI 交流群,如果你想学习 Agent 项目落地或者想交流 Agent 技术的的可以加我v
yunmz777,
最近看了几套比较知名的 Coding Agent,发现 TypeScript 确实出现得非常频繁。
新的 Kimi Code CLI 是 TypeScript + Node.js,DeepSeek Harness 也是 TypeScript + Node.js。Gemini CLI、Qwen Code 同样主要跑在 Node.js 上,终端界面还用了 React、Ink 这一套。
Claude Code 稍微不一样,它也是 TypeScript,但现在主要跑在 Bun 上。OpenCode也是类似路线,用 TypeScript + Bun,只不过终端层换成了 SolidJS 和 OpenTUI。
再往另一边看,Codex CLI 现在的核心已经是 Rust,Aider 则一直是 Python。
所以严格来说,不能说 Coding Agent 全是 Node.js 写的。
但有一个现象非常明显:做 Coding Agent 的团队特别喜欢 TypeScript 这套生态,而 Node.js 又是其中最常见的运行环境之一。
这件事一开始我也挺疑惑。
AI 相关的东西,不是 Python 最多吗?
模型训练是 Python,RAG 是 Python,各种 Agent Framework 也有一大堆 Python 项目。为什么到了 Claude Code、Kimi Code、Gemini CLI 这种真正跑在开发者电脑上的 Coding Agent,反而经常看到 Node.js?
后来我发现,问题其实出在我们很容易把 Coding Agent 当成一个 AI 项目来看。
但它更像一个开发工具。
Coding Agent 本地真正忙的,不是算模型
假设我让一个 Coding Agent:
帮我看看为什么登录接口偶尔返回 500,修掉以后把测试也补上。
模型当然要参与,但真正执行任务时,本地 Agent 要做的事情远比调用一次模型多。
它可能先扫一下项目目录,搜索登录相关代码,再打开几个文件。模型判断可能是数据库查询的问题,于是 Agent 修改代码,然后执行测试。
测试失败以后,它还得继续读取终端输出,再把报错交给模型。
模型重新判断以后,也许又让它看另外一个文件,或者执行一条 Git 命令。
所以一次 Coding Agent 任务,经常是在不停地做这些事情:
读文件、写文件、搜索代码、请求模型、执行命令、接收命令输出、继续请求模型。
这里面大部分都不是计算密集型任务。
它们更多是在等待。
等磁盘。
等网络。
等模型。
等测试跑完。
等一个外部进程返回结果。
Node.js 刚好很擅长干这种事情。
Node.js 很适合这种到处都在等的程序
Node.js 最经典的特点就是异步 I/O。
普通后端里,这个特点经常用来处理大量网络请求。放到 Coding Agent 里,其实也非常合适,只不过等待的东西变了。
Agent 发出模型请求以后,可以继续处理其他事件。
测试进程跑起来以后,可以一边接收 stdout、stderr,一边更新终端界面。
用户突然按 Ctrl+C,也得马上处理取消。
如果还有多个 Tool 同时工作,Agent 还可能同时等待几个不同的结果。
所以 Coding Agent 的运行方式天然有一点像事件驱动程序。
不是一个函数从头算到尾,而是:
某个结果回来了,就继续推进一点。
又有新的输出了,再处理一点。
模型给出下一步动作以后,再启动新的工具。
Node.js 的事件循环、Promise、Stream、文件系统 API、子进程 API,本来就是为这类程序准备的。
这也是它和 Coding Agent 很合拍的第一个原因。
Agent 不需要重新实现 Git、npm 和测试工具
还有一个很容易忽略的地方。
Coding Agent 会执行很多开发工具,但它自己并不需要实现这些工具。
比如我要跑:
bash
pnpm test
真正执行测试的是 Vitest、Jest 或其他测试框架。
Agent 只负责把这个进程启动起来,接收输出,最后看看退出码是不是 0。
运行:
bash
git diff
也是一样。
Git 自己完成计算,Agent 只负责调用 Git,再读取结果。
Node.js 做这些事情非常顺手,因为它本身就有完整的子进程能力。
通过 child_process,程序可以启动一个外部命令,持续读取 stdout 和 stderr,也可以监听进程什么时候结束。
碰到真正需要交互式终端的工具,还可以继续接 node-pty。
所以即使 Agent 本身是 TypeScript 写的,它照样可以处理 Python、Java、Rust、Go 项目。
因为它并不需要理解这些语言的编译器内部是怎么实现的。
它只需要能够调用:
text
python
pytest
cargo
go
javac
git
docker
pnpm
然后把这些工具的结果重新交给模型。
从这个角度看,Node.js 其实很像 Coding Agent 和开发环境之间的胶水。
更重要的是,Node.js 本来就在开发者工具生态里
如果只有异步 I/O,其实还解释不了为什么 Node.js 会这么常见。
Python 也能异步,Rust 也有 Tokio,Go 做并发更不差。
真正让 Node.js 在 Coding Agent 里特别顺手的,我觉得还是它离开发者工具太近了。
开发者每天都在碰 npm、pnpm、npx、VS Code、Electron、TypeScript。
这些东西本身就是 JavaScript 生态。
比如一个新的 Coding Agent 想快速让开发者试起来,npm 分发就很方便。
过去很多 CLI 都是:
bash
npm install -g xxx
或者:
bash
npx xxx
对于开发工具来说,这种体验非常重要。
因为开发者只是想试一下你的 Agent,不太可能为了一个 CLI 先折腾半天环境。
现在很多产品进一步做成单文件安装,不再要求用户手动准备 Node.js。但它们内部依然完全可以继续使用 TypeScript。
这也是为什么安装形式和实现技术已经不能直接画等号。
一个程序下载下来是单个二进制,不代表它一定是 Rust 或 Go 写的。
VS Code 又把 TypeScript 的优势放大了一次
Coding Agent 做到后面,很少只停留在 CLI。
很多产品都会继续进入编辑器。
比如 VS Code 插件、JetBrains 插件,或者通过 ACP 之类的协议接入 IDE。
而 VS Code 的插件生态本来就大量使用 TypeScript。
这时候,如果 Agent 核心本身也是 TypeScript,整个团队就会舒服很多。
终端是一套 TypeScript。
VS Code 插件也是 TypeScript。
SDK 还是 TypeScript。
如果再做 Electron 桌面端,依然可以继续沿用这套东西。
协议类型、Tool 定义、事件结构、会话模型,有不少都可以共享。
对于一个正在高速迭代的 Agent 产品,这种开发效率其实比运行时快那一点点更有价值。
因为 Coding Agent 现在变化太快了。
今天加 MCP,明天加 Subagent,后天又开始做 Skill、Hook、ACP、Remote Control。
产品还没定型的时候,先把功能跑起来,比一开始把所有东西都写成 Rust 更实际。
TypeScript 对 Agent 这种系统也比较友好
Coding Agent 还有一个特点,就是系统里会存在大量结构化数据。
比如 Tool Call:
ts
type ToolCall = {
id: string;
name: string;
args: unknown;
};
再比如 Agent 运行过程中可能不断产生事件:
ts
type AgentEvent =
| { type: "text.delta"; text: string }
| { type: "tool.started"; toolName: string }
| { type: "tool.finished"; exitCode: number }
| { type: "approval.required"; id: string };
这些东西会在 Runtime、CLI、插件、SDK、Web 界面之间来回传。
TypeScript 在这种场景里很好用。
不是因为它有什么 AI 加成,而是 Agent 系统本身就特别依赖协议和状态。
模型返回什么结构,Tool 接受什么参数,运行时会发出什么事件,UI 收到以后怎么展示,都可以提前定义好。
再搭配 Zod 之类的运行时校验库,用起来会很自然。
所以很多团队最后形成的组合就是:
text
TypeScript
+
Node.js 或 Bun
+
Zod
+
CLI/TUI
+
MCP
+
各种模型 SDK
这套东西刚好能把 Coding Agent 需要的大部分外围能力串起来。
那为什么 Codex 又改成 Rust 了
看到这里可能还有一个问题。
既然 Node.js 这么适合 Coding Agent,为什么 OpenAI 又把 Codex CLI 的核心迁到 Rust?
其实并不矛盾。
Node.js 很适合快速开发产品,但当 Agent 越来越深入用户电脑以后,团队关心的问题会发生变化。
一开始最重要的是:
功能能不能快速做出来?
工具能不能快速接进去?
CLI 好不好改?
用户能不能方便安装?
产品跑起来以后,开始关心的东西就会越来越底层:
启动是不是够快?
常驻内存有多大?
能不能做成真正干净的单文件程序?
跨平台行为是否稳定?
进程和文件权限怎么控制?
沙箱怎么做?
某些高权限操作能不能更靠近操作系统实现?
Rust 在这些地方就会越来越有吸引力。
所以 Codex 从 TypeScript 往 Rust 迁,可以理解成产品发展到一定阶段以后,工程重点发生了变化。
但这并不代表 Node.js 只能做 Demo。
Claude Code、Kimi Code、DeepSeek Harness、OpenCode 这些项目都还在大量使用 TypeScript 生态。
真正成熟的方案,也完全可能是混合架构。
比如 Agent Runtime 和界面继续使用 TypeScript,一部分高权限或者性能敏感的能力放到 Rust,本地模型实验、数据处理、RAG 继续放在 Python。
没有必要为了技术栈统一,强迫所有东西使用同一种语言。
总结
我现在理解 Coding Agent 为什么喜欢 Node.js,会比以前简单很多。
原因和 AI 本身关系没那么大。
Coding Agent 本地每天干的事情,本来就是读文件、跑命令、请求模型、监听终端,再把这些结果不断串起来。
Node.js 很擅长处理这种 I/O 密集、事件驱动的程序,又天然处在 npm、TypeScript、VS Code、Electron 这些开发者工具生态中。
所以很多团队做 Coding Agent 时,很自然就会从这里开始。
它最大的优势不是某一个性能指标,而是开发工具需要的很多东西,它周围本来就已经有了。