资讯动态

前端开发者的AI Agent实战:用Mastra搭建工具调用应用

发布时间:2026/10/16 15:14:57 来源:尧图企业网站定制
从写了两三年 React 的前端视角切入 AI Agent最反直觉的一点是我不需要先补 Python也不需要啃 LangChain 那套厚重的抽象。今年年初我用一个周末的时间把团队内部一个依赖检查的手动流程改成了带工具调用、跨会话记忆的 Agent 服务选的技术栈就是标题里这个 Mastra。这篇文章不打算写成官方文档的复读而是想老老实实讲清楚一个习惯了组件树、状态管理、异步请求的前端为什么在 Agent 框架选型时选 Mastra以及第一次真刀真枪搭工具调用 Agent 会遇到哪些文档里没写的问题。如果你也是前端正在犹豫要不要转全栈或者做 AI 应用这篇笔记应该能帮你少走弯路。1. 从组件树到Agent 节点前端经验是这块最好的翻译器很多前端朋友一听Agent 开发就心虚觉得那是后端算法工程师的领域。但真正上手之后我发现前端这几年的积累在 Agent 场景里几乎是无缝迁移的区别只是换了一套名词。Mastra 恰好把这一层翻译工作做得特别顺因为它本身是 TypeScript 优先的框架原语和前端熟悉的节奏非常接近。1.1 状态管理就是 Agent 记忆的预演React 里的useState、Redux、Zustand本质都在解决同一个问题数据在多个动作之间怎么保持一致。Agent 的 Memory 也是这个事。早期我写聊天机器人没接记忆用户问完我上次让你查的那个包后来更新了吗模型一脸茫然。后来给 Agent 配上内存存储它才能在多次会话里记住上下文。你完全可以这么理解前端的状态是你页面上的短期记忆Agent 的 Memory 是跨请求的长期记忆你早就懂这个概念了只是没意识到它叫上下文。Mastra 对记忆的处理比很多框架更贴近前端直觉。它把记忆分成线程内的短期上下文和跨线程的持久化存储配置方式类似给 store 加中间件。我第一次看到Agent的配置项里有memory字段时脑子里立刻浮现的是 Redux 中间件那种往 store 里塞自定义能力的模式——这种熟悉感让学习成本大幅下降。1.2 请求封装就是工具调用的雏形前端最日常的工作是什么封装 API、拦截错误、处理 loading 状态、做防抖。这些活儿放在 Agent 里就是工具调用的骨架。Mastra 的Tool概念说白了就是一个带描述和参数校验的异步函数你告诉模型这个函数是干什么的、需要什么参数模型根据你的描述决定什么时候调用它。这就跟你在组件里维护一个fetchUser函数然后根据用户操作决定是否调用它一个道理。我写下第一个工具函数时感受特别深这不就是把我平时写的api/getLatestVersion.ts包了一层 schema 描述吗前端强项恰恰是协调各种异步服务并把它们暴露成清晰接口这正是 Agent 工具层最需要的能力。所以别再觉得自己不懂 Agent你缺的只是一个把已有技能翻译过去的框架。1.3 组件生命周期与 Workflow 的编排思路React 的useEffect依赖数组、组件挂载卸载、事件冒泡这些时序控制的经验放到 Agent 的多步任务编排里正好对应 Workflow。Mastra 的 Workflow 让我定义一个任务有几个阶段、谁先谁后、谁依赖谁的输出。比如先查 npm 上这个包的最新版本再比对 package.json 里的旧版本最后生成升级建议就是一个典型的串行工作流。前端天天写这个请求等那个请求的结果再发起理解起来毫无障碍。2. 别人都在用 LangChain.js / Vercel AI SDK / OpenAI Assistants我选 Mastra 的理由选型那几天我也纠结过毕竟前排那几位名气大得多。但把每个框架都装进一个真实 Demo 里跑了一遍之后结论反而清晰了它们解决的问题层级不一样Mastra 正好卡在我需要的位置。框架核心定位语言体验记忆/持久化工作流编排我的评价LangChain.js通用 Agent/RAG 框架偏 Python 思维TS 支持较糙有但概念重有Runnable/Graph 抽象偏绕功能最全学得最累Vercel AI SDKAI 对话 UI 流式渲染原生 TS体验极好无内置需自接无本质是请求层做聊天页面首选做 Agent 要拼积木OpenAI Assistants API平台托管式 Agent 运行TS 封装好在线程内绑定平台靠 Run/Step 轮询省事但锁平台换模型基本重写MastraTypeScript 原生 Agent 运行时原生 TSAPI 精炼内置多存储适配器内置 Workflow 原语前端上手最快能力边界清晰2.1 LangChain.js 的问题抽象比业务还复杂LangChain 生态确实大但给我最大的感受是抽象层数比实际业务还多。Chain、Runnable、LCEL、AgentExecutor一堆名词砸过来最后可能只是为了实现模型调一个函数。它的很多设计思路源于 Python 世界的学术社区文档和社区案例也以 Python 为主TS 版本总有一种移植过来的疏离感。我学了两个下午发现自己还在研究怎么把两个 Runnable 拼在一起而我的真实需求不过是给它一个工具让它帮我查版本号。Mastra 则几乎没有这种负担。它一共就那么几个核心原语Agent、Tool、Workflow、Memory、RAG、Evaluator。每个原语做的事情一句话能讲清楚写起来也和写普通 TypeScript 模块差不多。对半路转型的前端来说原语少意味着可以快速建立心智模型而不是先修一门框架哲学课。2.2 Vercel AI SDK优秀的 UI 库但不是 Agent 运行时Vercel AI SDK 的useChat体验确实舒服前端几乎没有学习成本就能接一个流式聊天框。但当我试图往里面加工具调用链跨会话记忆多步骤任务的时候发现它更像一个AI 请求封装层并没有内置 Agent 运行时。这意味着我要自己设计状态持久化、自己维护工具执行的循环、自己处理模型返回的 tool_call 再二次请求。不是说不行而是这些逻辑本应该由框架承担而不是让每个开发者重新发明一遍。Mastra 也复用了 Vercel AI SDK 的模型 provider 生态但它把 Agent 运行时的职责补全了状态管理、工具执行、记忆存储、工作流编排都内置好了。对我来说这就够了——我不想在一个UI 库上面再铺三层自己的基础设施。2.3 为什么不用 OpenAI 官方那套OpenAI Assistants API 开箱即用线程和文件搜索都帮你托管了Demo 一个小时就能跑通。但它的代价是你的 Agent 逻辑和 OpenAI 平台深度绑定换模型供应商基本等于重写线程状态也拿不回来自己控制排查问题全靠平台日志。对于个人项目和需要一个备选模型策略的产品这种绑定不是一个好选择。Mastra 的模型 provider 是可插拔的今天用 OpenAI明天可以换成其他厂商代码只改一处配置这个灵活性对我很重要。3. 动手搭第一个能跑的工具调用 Agent理论说再多不如跑通一个真实例子。下面是我搭的第一个 Agent它能响应帮我查一下 React 最新版本这类问题然后调用真实的 npm registry 接口返回数据。3.1 创建项目Mastra 提供了脚手架命令可以直接生成带示例的工程npx create-mastralatest my-first-agent如果想和 Next.js 一起用可以选择带 Next.js 模板的版本。我本地用的是基础模板目录结构大致是src/mastra下面放 agent 和工作流定义。这一步没什么坑跟着提示选就行。唯一提醒一下Node 版本至少 18 以上否则依赖安装会有兼容性问题。3.2 定义一个最简单的 Agentimport { Agent } from mastra/core; import { openai } from ai-sdk/openai; export const packageAgent new Agent({ name: package-checker, instructions: 你是一个前端依赖检查助手。当用户询问某个 npm 包的版本或升级建议时使用 getPackageInfo 工具查询真实数据并根据返回结果组织回答。, model: openai(gpt-4o), });这里instructions很关键它相当于系统提示词 行为边界。我第一次写的时候把规则写得很长很细结果模型反而抓不住重点。后来把 instructions 精简成什么场景必须调工具、回答的风格是什么、禁止做的事情是什么准确率提升不少。记住工具怎么用不是你用自然语言堆给模型的而是写在工具描述里的。3.3 定义工具把 API 封装成模型能用的函数工具是 Agent 和外部世界交互的接口。我写了一个查询 npm 包信息的工具import { Tool } from mastra/core; import { z } from zod; const getPackageInfo new Tool({ id: getPackageInfo, description: 查询 npm 上指定包的最新版本号、描述和发布时间。当用户问某个包的情况时使用。, inputSchema: z.object({ packageName: z.string().describe(npm 包名如 react、next、vue), }), execute: async ({ context: { packageName } }) { const res await fetch(https://registry.npmjs.org/${packageName}); const data await res.json(); const latest data[dist-tags]?.latest; const desc data.description || 无描述; return { packageName, latest, desc }; }, });然后把这个工具挂到 Agent 上export const packageAgent new Agent({ name: package-checker, instructions: ……, tools: { getPackageInfo }, model: openai(gpt-4o), });有个细节值得说inputSchema里的describe字段会直接影响模型生成参数的质量。模型并不是自己猜参数而是根据这个 schema 的描述来决定填什么。描述写得越贴近真实语气比如当用户问某个包的情况时使用调用准确率越高。我一开始随手写了包名结果模型经常把最新版本当成包名传给工具后来把描述补充成如 react、next、vue这样带例子的句子错误立刻少了。3.4 跑起来测试Mastra 提供了本地开发命令行类似 Next.js 的 dev servernpm run dev启动后可以在终端直接和 Agent 对话也可以打开 localhost 的 playground 页面调试。我习惯用 playground因为它能看到模型完整的思考步骤、工具调用参数和返回结果排查问题特别方便。第一次测试我输入react 现在到哪个版本了Agent 先调用getPackageInfo拿到latest: 19.0.0后组织了一句完整回答返回。那一刻的感受是原来工具调用没想象中那么玄本质就是模型决定调哪个函数、填什么参数、把你的返回结果融入回答。顺带提一句工具执行时如果网络请求很慢模型会卡在等结果。建议在execute里加超时控制或者用Promise.race兜底别让 Agent 无限等下去。这个我一开始没注意后来遇到一次 npm registry 响应超时整个对话卡了一分多钟体验很差。4. 记忆、向量检索和工作流Agent 不只是对话框第一个 Demo 跑通之后很快会发现单次问答不够用。用户希望 Agent 记得上次聊过什么甚至希望它能自动完成一串任务。Mastra 在这一层给了三条路径Memory、RAG、Workflow。4.1 Memory 配置跨会话记住用户状态默认情况下 Memory 存在本地重启就丢。要让 Agent 真正记得用户需要配置持久化存储。Mastra 支持多种存储适配器本地开发我用的是 Postgresimport { PostgresStore } from mastra/pg; const pgStore new PostgresStore({ connectionString: postgres://localhost:5432/mastra, }); const agent new Agent({ name: checker, memory: { storage: pgStore }, instructions: ……, tools: { getPackageInfo }, model: openai(gpt-4o), });配好之后Agent 就能在多个会话之间保留用户偏好。比如用户之前说过我关心 React 的更新Vue 不用管之后它再回答时就会主动偏向 React。这个能力对应的前端心智模型就是全局 Store之前你写 Zustand 是为了让组件共享状态现在你配置 memory 是为了让 Agent 共享记忆思路完全一致。4.2 RAG让 Agent 能读文档如果想让 Agent 回答私有知识库的问题就得走 RAG。Mastra 提供向量存储抽象流程三步把文本切片、嵌入向量、存进向量库。查询时把用户问题也嵌入然后找最相关的片段拼进上下文。我做过一个实验性质的公司前端规范问答 Agent用到的核心代码大致是import { PgVector } from mastra/pg; import { embedMany } from ai; const vectorStore new PgVector(postgres://localhost:5432/mastra); await vectorStore.createIndex({ indexName: docs, dimension: 1536 }); // 切分文档、生成向量并存入向量库RAG 本身是个大话题但对前端来说关键点在于你不用自己写向量检索算法Mastra 已经把存取和相似度查询封装成了接口你要做的只是喂文档进去查询时取结果。真正要花精力的是文档切分的颗粒度——切太碎会丢上下文切太大会超 token。我在实践中发现按章节切分通常比固定字符数切分效果更稳。4.3 Workflow把多个步骤编排成自动化任务如果说单 Agent 是问答机器人Workflow 就是自己会干活的流水线。典型场景用户发一个项目路径Agent 自动完成检查依赖版本→对比当前项目依赖→生成升级建议报告。Mastra 的 Workflow 可以声明多个 Step明确依赖关系。概念上很像前端的 Pipe 或中间件链只是每个环节都可能调用 LLM 或工具。import { Workflow, Step } from mastra/core; const checkWorkflow new Workflow({ steps: { fetchDeps: new Step({ id: fetchDeps, execute: async ({ context }) { // 读取 package.json 的依赖列表 return { deps: [react, next] }; }, }), checkLatest: new Step({ id: checkLatest, dependsOn: [fetchDeps], execute: async ({ context, context: { deps } }) { // 逐个调用 npm registry 查最新版本 return { suggestions: react 需要从 18 升到 19 }; }, }), }, });用dependsOn声明依赖后Workflow 会按拓扑顺序执行这一步就是 useEffect 依赖数组的翻版。我第一次写完这段代码心里只有一个想法前端多年的调度经验终于有了用武之地。5. 前端转过来最容易踩的 5 个坑这部分是我真实记录下来的问题清单按踩坑时间排序每个都花了我至少一小时排查。5.1 提示词写成长篇小说模型反而不会用工具我第一次给 Agent 写 instructions 时把业务规则、工具用法、语气偏好全部塞进去写了 300 多字。结果模型经常该调工具时不调或者答非所问。后来发现instructions 应该只负责角色和策略工具怎么调用、参数怎么填全交给工具自己的description和inputSchema描述。两者分工明确之后模型表现立刻变稳了。这个教训对前端来说特别深就像你写组件时把样式和逻辑拆开提示词和组织代码的道理是相通的。5.2 工具出参和入参类型没对齐模型二次调用连环出错这是最隐蔽的坑。inputSchema定义了入参结构但如果execute返回的东西和模型预期不一致模型下一步可能继续调同一个工具参数却填错。比如我有个工具返回了{ latest: 19.0.0 }但模型在回答里想引用data.latestVersion自然拿不到值。解决办法是保持返回对象的 key 名称稳定、语义单一最好把返回结构也用 TypeScript 类型声明并导出让模型通过 schema 感知。Mastra 的 Tool 其实支持声明输出 schema别偷懒不写后面调试能省一半时间。5.3 模型密钥别打到前端 bundle和 Next.js 集成时最容易犯的错环境变量命名不带NEXT_PUBLIC_前缀却在客户端组件里引用密钥。这样模型 key 会被打进浏览器 bundle等于公开。正确的做法是 Agent 只跑在服务端 Route Handler 或 Server Action 里环境变量只在服务端读。我自己有一次测试时图方便在页面组件里直接调 agent结果浏览器 network 面板里看到了 key 的 MD5 片段幸亏及时发现。这条对任何 AI 项目都成立不只是 Mastra。5.4 本地存储没接数据库上下文说没就没不配存储适配器时Memory 默认落在内存里服务一重启所有会话记录清零。开发时感觉不明显因为反正每次对话都是新的调试但一旦开始做真实功能用户会投诉你刚才明明答应给我记录偏好的。如果你本地没有 Postgres可以先接 LibSQL 适配器一个本地文件就能持久化或者直接用 Docker 起一个 Postgres 容器。这步配置十分钟搞定别跳过。5.5 工具调用慢导致请求超时前端以为 Agent 挂了我的工具里有一个请求 npm registry 的接口正常情况下 200ms 返回但偶尔会卡到几十秒。第一次遇到时前端页面一直转圈用户以为服务挂了。后来才意识到工具执行是受模型调用周期约束的一旦超过模型 provider 的超时时间整个请求就会失败。解决思路有两个一是给工具内部的网络请求设置合理的超时比如 5 秒二是让前端走流式响应先把正在查询 xxx这种中间状态推给用户减少等待焦虑。Mastra 对流式事件的支持是内置的前端用ReadableStream就能逐步接收 Agent 状态。6. 什么时候该用 Mastra什么时候别被框架绑架选型到最后还是要回答这个框架适合什么。我的使用场景是一个带工具调用、需要跨会话记忆、可能要跑多个步骤的前端技术栈项目。Mastra 把 Agent 运行时、记忆、工作流、RAG 这些能力以 TypeScript 原语的形式集成在一个地方我可以用熟悉的语言和心智模型快速构建同时保留部署层面的自由——它能以 Node 服务或 Serverless 函数的方式跑在主流平台上。如果你的情况和我类似它值得优先考虑。反过来如果只是给 Next.js 项目加一个聊天弹窗Vercel AI SDK 的useChat加一个 route 就够了完全不需要引入整套 Agent 运行时。如果团队里全是 Python 工程师那就跟生态走别为了 TypeScript 强行换框架。框架本身不是越重越好关键是它的原语能不能覆盖你最短的闭环路径。我自己的判断方法是先把核心功能翻译成有没有触发外部工具/有没有长期记忆/有没有多步骤流程这三个问题如果三个里面有任意两个是有Mastra 这类完整 Agent 运行时才有价值如果全是没有那就老老实实轻量化。最后分享一个实操小技巧Mastra 的 playground 里能看到每次工具调用的完整入参出参我习惯在每轮对话后点开看一次比任何日志都好用。毕竟前端出身的人直觉是哪里不对就点哪里。用它把模型自作主张的时刻记录下来你会对提示词和工具描述怎么做微调比看十篇教程都管用。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑