字节笔记本
2026年8月29日
Mastra:TypeScript Agent 框架怎么上手
TypeScript 里接 LLM,很多人会直接调官方 SDK:发一条 prompt,拿一段文本回来。一旦要让模型查包、走固定步骤、记住上一轮对话,胶水会很快散开。Mastra 是一套 TypeScript Agent 框架,把 Agent、Tool、Workflow、Memory 收成同一套类型和入口,适合嵌进现有 Node / Next.js 项目,也可以单独起服务。仓库在 mastra-ai/mastra,文档在 mastra.ai/docs。
什么时候用它
只是一次性补全、翻译、改写,SDK 就够了。需要模型自己决定调哪个函数、步骤之间有明确输入输出、还要跨轮记住用户,再上框架比较省事。
只是把模型当补全引擎时,自己发请求再拼 prompt 更轻。框架值回票价的地方是:tool 有 schema、workflow 有明确步骤、memory 有 thread、本地还能开 Studio 点着试。Python 那边常见是图编排;这条线是给 TS 全栈用的,多了 Agent 注册、workflow 图、MCP 进出站这一层。
Mastra 是 YC W25,核心 Apache-2.0;仓库里名为 ee/ 的目录走企业授权,本地开发和测试可以用。
模型写成 provider/model 字符串,例如 openai/gpt-5.6-sol、anthropic/claude-sonnet-4-6、google/gemini-2.5-flash。对应环境变量是 OPENAI_API_KEY、ANTHROPIC_API_KEY、GOOGLE_API_KEY。中间用斜杠,不要写成冒号分隔,也不用再装一份 AI SDK,除非文档明确要求。完整列表看 mastra.ai/models。
建项目
推荐 CLI:
npm create mastra@latest
pnpm create mastra@latest
yarn create mastra
bunx create-mastra其他包管理器也能跑同一套脚手架。
交互会问项目名和模型提供商,可选 openai、anthropic、google、xai。
非交互可以:
npm create mastra@latest my-mastra-app -- --llm openai脚手架会生成 src 下的 mastra 目录并装好依赖。
脚手架默认带一套 agent harness:工作区工具、memory、任务列表、网页访问、定时任务都在。只要空壳可以用 --empty。已经有 Next.js 或 Express 仓库时,用 init 往里塞 src/mastra 即可。
检测到 Cursor、Claude Code 一类助手时还会装 Mastra skills。进目录后:
npm run dev本地 Studio 默认开在 http://localhost:4111。以前叫 Playground,已经改名。这里可以聊 Agent、看 Workflow 图、列出挂上的 MCP server。接口文档在 /swagger-ui。
往现有仓库里加,用 npx mastra init。完全手写的话,package.json 设 type 为 module,然后:
npm install -D typescript @types/node mastra@latest
npm install @mastra/core@latest zod@^4脚本写成 dev: mastra dev。tsconfig 要用 module ES2022 和 moduleResolution bundler,CommonJS 会解析失败。Node 22.18 以上可以直接跑 TypeScript,本地 import 记得带 .ts 后缀。
定义 Agent 和 Tool
Tool 必须用 createTool()。写成普通对象看起来能编译,运行时不会被执行。execute 的第一个参数是按 inputSchema 校验过的输入,第二个是运行时上下文,用不到可以省略。
下面这个例子会去查包注册表的最新版本,Agent 根据结果写一句升级说明,可以当真跑。
// src/mastra/tools/pkg-info.ts
import { createTool } from '@mastra/core/tools'
import { z } from 'zod'
export const pkgInfoTool = createTool({
id: 'pkg-info',
description: '查询包注册表的最新版本和描述',
inputSchema: z.object({
packageName: z.string().describe('包名,例如 @mastra/core'),
}),
outputSchema: z.object({
name: z.string(),
version: z.string(),
description: z.string(),
}),
execute: async ({ packageName }) => {
const url = 'https://registry.npmjs.org/' + encodeURIComponent(packageName) + '/latest'
const res = await fetch(url)
if (!res.ok) throw new Error('lookup failed: ' + res.status)
const data = await res.json()
return {
name: data.name,
version: data.version,
description: data.description ?? '',
}
},
})// src/mastra/agents/dep-agent.ts
import { Agent } from '@mastra/core/agent'
import { pkgInfoTool } from '../tools/pkg-info.ts'
export const depAgent = new Agent({
id: 'dep-agent',
name: '依赖助手',
instructions: '你帮前端仓库看依赖。用户给出包名时,先调用 pkgInfoTool,再用一句话说明当前 latest 版本适不适合升级。',
model: 'openai/gpt-5.6-sol',
tools: { pkgInfoTool },
})// src/mastra/index.ts
import { Mastra } from '@mastra/core'
import { depAgent } from './agents/dep-agent.ts'
export const mastra = new Mastra({
agents: { depAgent },
})脚本里直接调:
import { mastra } from './src/mastra/index.ts'
const agent = mastra.getAgentById('dep-agent')
const response = await agent.generate('帮我看一下 @mastra/core 最新版')
console.log(response.text)Agent 还可以挂 agents(子代理会变成 agent- 前缀的 tool)和 workflows(变成 workflow- 前缀的 tool)。指令里写清楚什么时候该用哪把工具,比只靠 schema 稳。
一小段 Workflow
步骤固定、数据形状明确时,别把流程全塞进 Agent 的 system prompt。Workflow 用 createStep / createWorkflow,链式 then,最后 commit。第一步的 inputSchema 要和 workflow 对齐,最后一步的 outputSchema 也要和 workflow 对齐。
import { createWorkflow, createStep } from '@mastra/core/workflows'
import { z } from 'zod'
import { pkgInfoTool } from '../tools/pkg-info.ts'
const lookup = createStep(pkgInfoTool)
const note = createStep({
id: 'upgrade-note',
inputSchema: z.object({
name: z.string(),
version: z.string(),
description: z.string(),
}),
outputSchema: z.object({ note: z.string() }),
execute: async ({ inputData }) => ({
note: `${inputData.name}@${inputData.version}:${inputData.description}`,
}),
})
export const upgradeWorkflow = createWorkflow({
id: 'upgrade-note',
inputSchema: z.object({ packageName: z.string() }),
outputSchema: z.object({ note: z.string() }),
})
.then(lookup)
.then(note)
.commit()Workflow 把 tool 直接 createStep 进去时,tool 的 inputSchema 必须能接住上一步的输出,对不上就先 map 一层。
注册时把 workflow 放进 Mastra 的 workflows 字段。运行:
const wf = mastra.getWorkflow('upgradeWorkflow')
const run = await wf.createRun()
const result = await run.start({
inputData: { packageName: '@mastra/core' },
})
if (result.status === 'success') console.log(result.result)还有 parallel、branch、foreach。Studio 里能看到图,按 schema 填表跑一遍。步骤可以挂起等人审批,状态存在 storage 里,之后再 resume。
Memory 和 MCP
对话要跨轮,装 memory 包和一个 storage。本地常用 libSQL:
npm install @mastra/memory@latest @mastra/libsql@latest在 Mastra 实例上配 storage,在 Agent 上挂 Memory。
import { Memory } from '@mastra/memory'
import { LibSQLStore } from '@mastra/libsql'
export const mastra = new Mastra({
storage: new LibSQLStore({
id: 'mastra-storage',
url: 'file:./mastra.db',
}),
})Agent 构造里加上 Memory,options.lastMessages 先设成 10 即可。调用 generate 或 stream 时带上 thread(会话)和 resource(用户)。Studio 会自己生成这两个 id。自己写客户端时只发本轮新消息,历史由 storage 加载,别把整段聊天再贴回去,时间戳对不上会乱序。
MCP 在单独的包里。MCPClient 用 stdio 命令或远程 URL 连外部 server,listTools 的结果交给 Agent 的 tools。MCPServer 可以把自家的 Agent、Tool、Workflow 暴露给别的 MCP 客户端。Studio 能列出挂上的 server。
上手以 Get started 和 手动安装 为准。模型 id 会变,以 mastra.ai/models 为准。
上手时容易踩的点
模型字符串用斜杠。openai/gpt-5.6-sol 这种写法会自动去读对应环境变量。写成冒号、或者自己 import 一个 provider 对象,都和当前文档不一致。密钥放在项目根的 .env 里即可。
getAgentById 用的是 Agent 构造函数里的 id 字段,getWorkflow 用的是注册到 Mastra 时的对象键。上面例子里 workflow 的 id 是 upgrade-note,注册键是 upgradeWorkflow,跑的时候要用后者。
Studio 跑起来之后,改 src/mastra 下的文件一般会热更新。想看底层 HTTP 接口,打开 /swagger-ui。默认端口 4111,可以在 Mastra 的 server 配置里改 host 和 port。
MCP 客户端在单独的包里。连本地 stdio 服务时配 command 和 args,连远程就给 URL。配置固定时用 listTools 一次拿齐;每个请求凭证不同时用 listToolsets,在 generate 时传入 toolsets。
标准目录是 src/mastra/agents、tools、workflows,入口 index.ts。Agent 的 model、id、name 由代码决定,Studio 的编辑器改不了这三项,只能改 instructions 和部分 tool 描述。
和 Next.js、Express、Hono 的接法在官网 integrations 一节。也可以 build 之后当独立服务部署。核心框架是 Apache-2.0;ee 目录里的企业功能开发测试能用,生产要许可证。