2024 年你要写一个 Agent,社区的回答几乎只有一句:用 Python。2026 年再问,答案已经变成——先看你们团队是不是 TypeScript 栈。这个转变不是偏好漂移,是生态数据在说话:YC X25 批次里 60%–70% 的 Agent 创业公司用 TypeScript 开发(数据来自 Sam Bhagwat 的 Hacker News 统计),Vercel AI SDK 月下载量突破 2000 万,Mastra 拿到 2200 万美元 A 轮融资。对后端工程师来说,这不再是"要不要学 Python 做 AI"的问题,而是"Node.js 这套 Agent 技术栈怎么选、怎么用"的问题。这篇文章把三层结构、核心机制、生产案例一次讲透。
为什么 Java 后端也要关心这事?过去两年"Agent 必须 Python"的论调,把大量 Java/Node 团队挡在门外:要么逼全栈组学一门外语,要么让 AI 能力永远长在"另一个服务"里,集成靠 HTTP 对接。TS 生态补位之后,做后端的第一次有了"在自己主语言里直接写 Agent"的选项——类型定义、依赖管理、部署链路全部复用现有基建,这才是真正的生产力拐点。
两年前 Python 独大,现在 60% 的 Agent 创业公司押注 TS
先看一组不常被放在一起的数字。LangGraph、CrewAI、AutoGen 统治 Agent 框架讨论的那两年,Python 几乎是唯一选项;到了 2026 年,TS 侧三个代表性项目——Vercel AI SDK、Mastra、LangGraph.js——在 GitHub 上分别拿到约 2.5 万、2.53 万和 0.3 万 stars,前两者的量级已经追平 Python 一线框架。Mastra 的周下载量达到 30 万,Vercel AI SDK 月下载量超过 2000 万(来源:pkgpulse、speakeasy、dreaming.press)。
这张图说明:TS 生态不是出了一个"能用的移植版",而是长出了两个头部项目,规模远超第三名。 LangGraph.js 的 3k stars 恰恰暴露了它的定位——它是 Python 版 LangGraph 的移植,新特性先落 Python 再落 JS,用的人少不是因为差,是因为它服务的是"复杂图编排"这个窄需求。
为什么是 TS 而不是别的?三个原因叠在一起:
- 全栈同构:Agent 应用天然是"前端聊天 UI + 后端流式接口 + 工具调用"的形态,Next.js/React 团队用同一门语言把三层写穿,不需要 Python 后端和 JS 前端之间维护两套类型。
- 事件驱动天生匹配:LLM 输出是流式的,工具调用是异步的,Agent loop 本质是一个事件循环——这正是 Node.js 的主场,背压、取消、并发这些原语直接复用。
- Serverless 亲和:Agent 应用按 token 计费、按请求伸缩,Vercel/Cloudflare Workers/Netlify 的 scale-to-zero 模型比常驻 Python 服务省一个数量级的钱。
对后端来说,这个信号很明确:如果你在 Java/Node 团队里,做 Agent 应用的第一语言选项已经不是"要不要学 Python",而是"在 TS 框架里怎么选"。
三层技术栈:Vercel AI SDK、Mastra、LangGraph.js 不是三国杀
TS 团队选型最常犯的错,是把这三个名字当竞争对手。它们根本不是同一层的东西:
| | | |
| | 统一多模型接口、流式输出、工具调用循环(tool loop) | |
| | Agent、Workflow、记忆、RAG、评测,开箱即用 | |
| | 有状态图、检查点、人类介入、复杂多 Agent 控制流 | |
Vercel AI SDK 的本质是"模型和流式层":一行代码切换 OpenAI/Anthropic/Google/本地 Llama,streamText 把 token 流式推到 React 页面。它明确不做编排——没有崩溃后可恢复的持久状态,没有一等公民的长期记忆。官方自己都承认:它的"agent"就是一个工具调用循环,模型在单次调用内可以多步调用工具。把 AI SDK 当 Agent 框架用,是 TS 团队最常见的认知错位。
Mastra 站在 AI SDK 之上,把编排层补齐:Agent、Workflow(.then() / .branch() / .parallel())、记忆(Postgres/LibSQL)、RAG 管道、评测,还自带本地开发 UI(Mastra Studio)。Gatsby 团队出品,Apache 2.0,2026 年 1 月发布 1.0,4 月拿到 2200 万美元 A 轮。它的定位是"Python 开发者说的 agent framework"在 TS 里的完整对应物。
LangGraph.js 是低层图引擎:把 Agent 建模成有状态图,执行可以跨失败持久化、从中断点恢复,人类可以在运行中检查状态。它是三兄弟里最"重"的,也是唯一适合"控制流真的是张图"的场景的。 如果你的状态图在纸上画出来不到十个状态、转移全是确定性的,用 XState 甚至 switch 语句就行,别上 LangGraph。
1应用层 Workflow / Agent / 记忆(你的业务逻辑)
2编排层 Mastra LangGraph.js
3模型层 Vercel AI SDK OpenAI Agents SDK
4底座 GPT-4o / Claude / Gemini / 本地模型
这张架构图说明的是 2026 年 TS Agent 生态的核心事实:下层(AI SDK)负责把模型调用和流式做扎实,上层(Mastra/LangGraph.js)负责编排,两层之间是标准接口,你可以先只用下层,等需要记忆和工作流时再叠加上层,不用推倒重来。
选型的决策树其实很短:
- 只是聊天 UI + 简单工具调用(<5 个工具、<10 步)→ Vercel AI SDK 够用;
- 要做真正的 Agent 产品(记忆、RAG、工作流、评测)→ Mastra;
- 控制流复杂到需要图、检查点、人类介入 → LangGraph.js;
- 深度绑定 OpenAI → @openai/agents(Swarm 风格 handoff,官方维护)。
还有个容易踩的盲区:三层不是互斥选项,是叠加关系。 Mastra 底层就是 Vercel AI SDK,它把 SDK 故意不做的编排、记忆、评测补全;OpenAI Agents SDK 也在自己的模型调用层之上做 handoff。所以"用了 Mastra 就不该再用 AI SDK"是个伪命题——你看到的几乎所有生产项目都是"AI SDK 打底,上层再套一个编排框架"。选型时真正要回答的问题是"我需不需要那层编排",而不是"我选哪个"。
Agent loop:Node 里一个 streamText 就转起来的工具循环
Agent 和普通聊天接口的本质区别,是"模型可以调用工具,工具结果再喂回模型",这个循环叫 Agent loop(也叫 ReAct loop:Reason → Act → Observe)。在 Python 里你要么用 LangChain 的 AgentExecutor,要么自己写 while 循环;在 Node 里,Vercel AI SDK 用 maxSteps 一个参数就把循环转起来了:
1// npm i ai @ai-sdk/openai zod
2// 真实 API:需要 OPENAI_API_KEY(或换成其它 provider)
3import { streamText, tool } from'ai';
4import { openai } from'@ai-sdk/openai';
5import { z } from'zod';
6
7constresult=awaitstreamText({
8model:openai('gpt-4o'),
9messages: [{ role:'user', content:'查一下订单 1024 的状态,并告诉我是否要人工介入' }],
10tools: {
11lookupOrder:tool({
12description:'按订单号查询订单状态',
13parameters:z.object({ orderId:z.string() }),
14execute:async ({ orderId }) => db.orders.find(orderId), // 你的业务查询
15 }),
16escalateToHuman:tool({
17description:'把订单转给人工客服',
18parameters:z.object({ orderId:z.string(), reason:z.string() }),
19execute:async ({ orderId, reason }) => ticketApi.create({ orderId, reason }),
20 }),
21 },
22maxSteps:5, // 关键:允许模型在单次请求里最多转 5 轮工具循环
23});
24
25returnresult.toDataStreamResponse(); // 直接作为 HTTP 流式响应
maxSteps 是这段代码里唯一"Agent 味"的参数:没有它,模型只能调用一次工具;有了它,模型可以"查订单 → 看到已发货 → 判断无需介入 → 直接回复",每一步的中间结果都被框架自动拼回上下文。这就是工具循环的最小实现,也是后端工程师理解 Agent 成本模型的关键:一次用户请求,背后可能是 5 轮模型调用,token 消耗按轮叠加。
这里有个后端视角很容易忽略的细节:工具结果要截断,上下文要设上限。 数据库查询可能返回几千行,直接拼进 messages 会让下一轮模型调用的输入 token 暴涨;生产环境的标准做法是给每个工具结果设最大长度(比如 2000 字符),超出截断并注明"结果已截断,共 N 行"。另外,循环本身是 token 放大器——maxSteps=5 意味着一次用户请求最多放大 5 倍输入量,日志里必须记录每轮的 token 消耗,否则月底账单会教做人。
如果不想被框架绑定,理解这个循环的内核也就 30 行。下面是无外部依赖的模拟实现(LLM 部分用桩数据,展示的是循环结构,不是生产代码):
1// 模拟实现:展示 Agent loop 的循环结构,不依赖任何 SDK
2asyncfunctionrunAgentLoop(initialInput, { maxSteps=5 } = {}) {
3letmessages= [{ role:'user', content:initialInput }];
4
5for (letstep=0; step<maxSteps; step++) {
6// 1. 调模型,让它决定:回答问题,还是要调用工具
7constdecision=awaitcallLLM(messages); // 桩函数,见下
8messages.push({ role:'assistant', content:decision.content });
9
10// 2. 如果模型直接给了最终答案,循环结束
11if (!decision.toolCall) returndecision.content;
12
13// 3. 执行工具调用,把结果作为新消息喂回去
14consttoolResult=awaitexecuteTool(decision.toolCall);
15messages.push({ role:'tool', toolCallId:decision.toolCall.id, content:toolResult });
16// 回到循环顶部:模型看到工具结果,决定下一步
17 }
18thrownewError(`超过 ${maxSteps} 步仍未收敛,可能有死循环`);
19}
20
21asyncfunctioncallLLM(messages) {
22// 桩实现:真实场景换成 OpenAI/Anthropic SDK 的 chat completion
23constlast=messages.at(-1).content;
24if (last.includes('天气')) {
25return { content:'', toolCall: { id:'t1', name:'getWeather', args: { city:'北京' } } };
26 }
27return { content:'北京今天 28 度,晴。', toolCall:null };
28}
29
30asyncfunctionexecuteTool({ name, args }) {
31if (name==='getWeather') return'{"city":"北京","temp":28,"condition":"晴"}';
32return'{}';
33}
34
35console.log(awaitrunAgentLoop('北京今天天气如何?'));
这段代码的价值不是让你手写 Agent,而是让你看懂框架替你做了什么:一个 for 循环、两个消息 push、一个工具执行分支。 看懂之后,maxSteps 该设多少、工具结果该不该截断、上下文会不会爆,你都能自己推出来——而不是把框架当黑盒。
还有一个生产细节值得单独说:工具调用是"不可信输入",要校验。 模型可能编造一个不存在的工具名、传一个越权的参数(比如 orderId 传成别人的订单),所以 executeTool 前面必须有参数校验和权限检查,把模型当普通外部调用方对待。后端做接口防越权的经验,在 Agent 工具层一行不少地要重来一遍。
记忆四件套:Mastra 把"开箱即用"做到了什么程度
Agent 从 demo 走向生产,第一个撞墙的就是记忆。聊天接口是无状态的,Agent 产品不是。Mastra 把记忆拆成四种类型,各自解决不同问题:
| | |
| | 可配置窗口,Postgres/LibSQL 持久化 |
| | Zod 校验的 JSON 或 Markdown,Agent 主动读写 |
| | RAG:embedding + 向量库(pgvector/Pinecone/Qdrant) |
| | 30k token 自动触发,压缩 5–40 倍,LongMemEval 约 95 分 |
前三种好理解:对话历史、工作状态、语义记忆,都是"你要不要自己建表"的问题——Mastra 的答案是"你不用建"。第四种 Observational memory 才是真正拉开差距的设计:它不要求你手动配置,在上下文达到 3 万 token 时自动触发压缩,把历史对话压成摘要,压缩比 5–40 倍,在 LongMemEval 基准上拿约 95 分。
代价也很诚实:压缩是后台 LLM 调用(默认 Gemini 2.5 Flash),这部分 token 成本不会出现在你 agent 的使用量账单里——Mastra 官方文档没有高亮这个隐藏成本,社区已经有人踩了。
对后端工程师,记忆选型的实质是:你的 Agent 需要"记住"什么,决定了你要不要上全家桶框架。 只是聊天记录 → 自己建张表就行;需要跨会话的结构化状态 + 语义检索 → 自己写这套要一个团队干两周,Mastra 一行 memory: new Memory({ storage: postgresStorage }) 拿下。这笔账,后端算得最快。
用后端熟悉的词翻译一下这四类记忆:Message history 就是聊天流水表;Working memory 是"会话级缓存"——Agent 把临时结论写进去,像 Redis 里放个 JSON;Semantic recall 是"向量检索 + embedding 管道",等价于你给文档建了个语义索引;Observational memory 是"自动归档压缩",像日志系统把旧日志聚合成摘要。每一类你都能在后端找到对应物,区别只在于:框架帮你把表建好、管道接好、压缩逻辑写好,你只负责业务字段。
Docker、Elastic、Marsh McLennan:生产案例拆开看
框架宣传可以不信,生产案例不好造假。Mastra 在 2026 年的公开落地名单已经覆盖从 DevOps 到企业搜索:
Docker:事件驱动的 PR 自动化。 GitHub webhook 在 PR 打开时触发,Mastra 接收事件,跑三步工作流(分析 diff → 生成评审 → 发评论),几秒内出现在 PR 上。选 Mastra 的核心理由是"多 Agent 编排 + 事件驱动而非聊天驱动"——这是生产自动化与 demo 的分水岭。
Elastic:Agentic RAG。 Elasticsearch 做向量库,Agent 语义检索文档、用 Claude 综合答案、内联引用来源。技术选型上,TypeScript 优先 + 模型无关架构是决定性因素:同一份 Agent 代码在 GPT-4o、Claude、Gemini 之间切换做 A/B,不动架构。
Marsh McLennan:10 万员工日常使用的企业搜索。 这大概是公开案例里流量最大的 Mastra 部署之一,日均 10 万级用户量级验证了"TS Agent 能扛生产负载"这个命题。
Replit:Agent 造 Agent。 Replit Agent 3 用 Mastra 让 AI 编码助手去"脚手架、配置、部署另一个 Mastra Agent"——递归模式,Agent 的生产力工具是 Agent 本身。
这些案例对后端意味着三件事:第一,Agent 不是只有聊天形态,事件驱动的工作流自动化才是企业买单的大头;第二,模型无关架构是刚需,锁死一家 provider 的 Agent 没法做 A/B 和降级;第三,TS Agent 已经扛住了企业级流量,不再是玩具。
从这些案例里还能提炼出一个通用架构模式:事件触发 → 工作流编排 → 工具调用 → 人工介入点。 Docker 的 PR 机器人是 GitHub webhook 触发,Elastic 的 RAG 是用户查询触发,Marsh McLennan 的搜索是员工输入触发——入口不同,骨架一致:Agent 不是"一个会聊天的接口",而是"一条带分支、可重试、能暂停等人工确认的业务流水线"。这个心智模型,和做后端消息队列、状态机、BPM 的思路完全同构。
落地清单:先抄走的五条,先躲开的三个坑
如果你是后端工程师,准备在 Node 栈里做第一个 Agent,这份清单可以直接用:
- 起步用 Vercel AI SDK:streamText + tool + maxSteps 覆盖 90% 的 API 形态,先跑通再谈框架。
- 画状态图再选编排层:白板上状态 < 10 个且转移确定 → 不选框架,写状态机;要记忆/工作流/评测 → Mastra;真图结构 → LangGraph.js。
- 工具调用循环必须设上限:CrewAI 用户已报告单次运行 $400+ 的失控账单,maxSteps/迭代上限是成本护栏,不是可选项。
- 记忆先定"记什么":聊天记录建表即可,跨会话结构化状态和语义检索才值得上全家桶。
- 模型无关是第一架构原则:所有模型调用走统一接口,provider A/B 和降级才有空间。
三个坑,都是社区真实踩过的:
- Serverless 超时天花板:Vercel 函数超时 Pro 300 秒 / Enterprise 800 秒,长时 Agent 任务会被硬切。需要小时级任务时,别把 Agent 挂在请求链路里,用 durable workflow 或队列拆解。
- LibSQL 的 serverless 陷阱:Mastra 默认存储 LibSQL,但 LibSQL 的 file URL 在 serverless 环境不可用,上 Vercel/Cloudflare 必须换 Postgres 等外部存储。
- 隐藏的 LLM 成本:Observational memory 的自动压缩、语义记忆的 embedding 都在后台调模型,账单里看不到。上线前把 token 用量接进监控,而不是等月底账单。
如果从零开始,我建议的路径是:先花一小时用 npm create 起一个 Vercel AI SDK 的流式聊天 + 一个工具调用,把 Agent loop 跑通;再评估要不要上 Mastra。 别一上来就全家桶——框架的抽象在你没跑通过裸循环之前是负担,跑通之后才是加速器。这个顺序和当年学 Spring 之前先写 Servlet 是一个道理:先懂机制,再上框架。
选型没有银弹,但 TS Agent 生态在 2026 年已经给出了清晰的分层答案:模型层用 AI SDK,编排层按需求选 Mastra 或 LangGraph.js,剩下的交给业务代码。
框架还会继续洗牌,但"Agent 应用的后端运行时"这个位置,Node.js 在 2026 年已经坐稳了。你团队里第一个 Agent,是从聊天工具调用开始,还是直接上工作流编排?评论区聊聊你们的选型理由。
参考资料
- Mastra vs Vercel AI SDK vs LangGraph.js: TypeScript Agent Frameworks in 2026(dreaming.press)
- Top npm Packages for AI Agents in 2026 (Ranked)(pkgpulse.com)
- How to Choose an Agent Harness in 2026(uselemma.ai)
- Choosing an agent framework: LangChain vs LangGraph vs CrewAI vs PydanticAI vs Mastra vs Vercel AI SDK(speakeasy.com)
- Mastra in 2026: What It Is, When to Use It, and How It Compares(dev.to)
- Mastra AI Guide 2026(baeseokjae.github.io)
- Mastra vs LangGraph vs Vercel AI SDK: TypeScript Agents in 2026(particula.tech)