Mastra 开发(02):环境搭建与第一个 Agent(TS 版)

QuibblerAgentQuibblerAgent 2026-11-11 约 17 分钟 4 次阅读

上一篇《Mastra 全景》说过:Mastra 是 TypeScript 优先的 Agent 框架,把工具、工作流、记忆和本地调试台打包成一套工程化方案。这一篇开始动手,目标很具体——从零搭好环境,写出第一个会自己决定“何时调工具”的 Agent,并在调试台里看清它的完整调用轨迹。

本篇与之前那篇 AI Agent 开发(02):环境搭建与第一个 Agent(Python 版)是刻意的一对:同样一个“查当前时间”的任务,Python 用 LangChain 走过一遍,这里用 TypeScript 加 Mastra 再走一遍,步骤一一对应,方便你对照两种栈的口味差异。全文按“环境准备 → 创建项目 → API Key 管理 → 第一个 Agent → 本地调试台 → 两栈对照 → 常见坑”组织,最后留一个小练习。


1、环境准备

Mastra 对 Node 版本的下限不算苛刻,但 2026 年的工具链默认按新版 Node 设计。官方 Quickstart 给出的参考线是:Node.js 22.18.0 及以上可以直接运行 TypeScript 文件,省掉独立的编译步骤;社区教程则普遍按 Node 20 起步。实践建议一步到位装 22 LTS(不低于 22.18),后面用 node run.ts 直跑 TS 就依赖这条。

先确认本机版本并启用 pnpm,命令如下:

node -v
corepack enable

第一条输出 v22.18.0 或更高即可;第二条打开 Node 自带的包管理器切换器。脚手架支持 npm、pnpm、yarn、bun 四种包管理器,本文统一用 pnpm——安装快、磁盘省,是 2026 年 TS 社区的主流选择。习惯 npm 的读者把后文所有 pnpm 换成 npx/npm 即可,行为完全等价。

版本选择上多说一句:Node 20 已在 2026 年 4 月底结束官方维护,新项目没有理由再从它起步;22 LTS 的维护期到 2027 年 4 月,眼下正处于活跃维护与安全更新都在线的窗口。版本过旧的机器(比如还在 Node 18),先用 nvm 或 Windows 下的 nvm-windows 安装 22 LTS 再 nvm use 22 切换,不要在旧版本上硬试——脚手架和运行时都可能在半路报错。

2、创建项目

环境就绪,用官方脚手架 create-mastra 生成工程,一条命令:

pnpm create mastra@latest

脚手架是交互式向导:先确认项目目录名,再问几个初始化选项(例如是否附带示例代码),一路回车取默认值就能跑通。装完依赖 cd my-agent 进入目录。值得一提的是,2026 版脚手架生成的不是空壳,而是一个“通用 Agent 工作台”工程——自带本地工作区、shell 工具、记忆与任务跟踪。这些预置能力本篇先不展开,我们专注手写一个最小 Agent。

生成的目录结构大致如下(以项目名 my-agent 为例):

my-agent/
├── src/
│   └── mastra/
│       ├── agents/
│       │   └── index.ts    # Agent 定义与导出
│       ├── tools/
│       │   └── index.ts    # 工具定义与导出
│       ├── workflows/
│       │   └── index.ts    # 工作流,本篇用不到
│       └── index.ts        # Mastra 实例,统一注册
├── .env.development        # 开发环境变量,API Key 写这里
├── package.json            # type: module + mastra 脚本
└── tsconfig.json

这个结构有三个要点。其一,Agent 相关代码全部集中在 src/mastra/ 下,agents/、tools/、workflows/ 各管一类构件,职责边界清楚;workflows/ 本篇空着,系列第 4 篇会用它编排多步骤任务。其二,src/mastra/index.ts 是注册中心,new Mastra({ agents: {...} }) 把散落各处的 Agent 聚成一张目录,调试台和后续部署都从这里取货。其三,package.json 里有 "type": "module" 和预置的 dev 脚本(内容就是 mastra dev),后面直接用。

3、API Key 管理

Mastra 的模型配置走“模型字符串”路线:model 写成 provider/model(斜杠分隔),框架自动从环境变量读取对应供应商的凭证——anthropic/… 读 ANTHROPIC_API_KEY,openai/… 读 OPENAI_API_KEY。开发期的变量写在脚手架生成的 .env.development 里,内容示例:

ANTHROPIC_API_KEY=sk-ant-xxxxxxxx

本篇示例用 Anthropic,所以只放这一条;想换 OpenAI 就写 OPENAI_API_KEY,并把后文 Agent 的 model 换成 openai/… 前缀,两处对上即可。这套纪律与 Python 版完全一致——密钥进环境变量,绝不进代码,也绝不进 git。

注意:首次提交前用 git status 确认 .env 系列文件未被跟踪;脚手架的 .gitignore 通常已覆盖,但值得亲眼验证一次。

4、第一个 Agent

任务与 Python 版相同:写一个查当前时间的工具,让 Agent 在被问到时间时自己决定调用它。整个过程分三步:定义工具、组装注册、运行验证。

4.1、定义时间工具

改写 src/mastra/tools/index.ts,用 createTool 加 Zod 声明一个无参工具:

import { createTool } from '@mastra/core/tools'
import { z } from 'zod'

export const timeTool = createTool({
  id: 'get-current-time',
  description: '获取当前本机日期和时间,格式 YYYY-MM-DD HH:MM:SS',
  inputSchema: z.object({}),
  outputSchema: z.object({ now: z.string() }),
  execute: async () => ({
    // sv-SE 区域恰好输出 YYYY-MM-DD HH:MM:SS
    now: new Date().toLocaleString('sv-SE'),
  }),
})

四个字段各司其职:id 是工具的稳定标识;description 是给模型看的说明书,模型靠它判断“什么问题该调这个工具”,写不清楚工具就永远没人调;inputSchema 用 Zod 声明参数结构,空对象表示无参;execute 是真正执行的函数,第一个参数是校验后的输入,本例无参所以直接省略,第二个参数是执行上下文(请求信息、中断信号等),本篇用不到,先按下不表。zod 已随脚手架装好,若提示缺包就 pnpm add zod 补一条。完整字段清单见 createTool 的 API 参考。与 Python 版的 @tool 装饰器对比:那边靠类型注解和 docstring 隐式生成 schema,这边 schema 显式写在对象里——多几行代码,换来参数约束一目了然。

4.2、Agent 组装与注册

工具就位,改 src/mastra/agents/index.ts 完成组装:

import { Agent } from '@mastra/core/agent'
import { timeTool } from '../tools/index.ts'

export const timeAgent = new Agent({
  id: 'time-agent',
  name: '时间助手',
  instructions: '你是严谨的助手,凡涉及当前时间的问题,必须先调用工具查询。',
  model: 'anthropic/claude-sonnet-5-5',
  tools: { timeTool },
})

instructions 对应 Python 版的 system_prompt,上面这句系统指令也与那边一字不差;model 直接写模型字符串,换供应商只改这一行;tools 是一个对象,键名即工具名,加工具就是加一项。然后到注册中心 src/mastra/index.ts 挂号:

import { Mastra } from '@mastra/core'
import { timeAgent } from './agents/index.ts'

export const mastra = new Mastra({
  agents: { timeAgent },
})

Mastra 实例是全工程的目录,注册过的 Agent 才会出现在调试台里。构造参数远不止这几个——memory、workflows 等都在这里挂载,完整清单见官方 Agent 参考。另外注意导入路径都带 .ts 扩展名:这是 ESM 的规矩,Node 直跑与 Mastra 的打包器都认。

4.3、运行与验证

在项目根目录新建 run.ts,调用 generate 发起一次对话:

import { timeAgent } from './src/mastra/agents/index.ts'

const result = await timeAgent.generate(
  '现在几点了?顺便说说今天是星期几。',
)
console.log(result.text)

generate 驱动一次完整的推理循环:模型判断自己不知道当前时间,发起工具调用,拿到结果后组织回答;返回对象的 text 字段就是最终文本。Node 22.18+ 原生支持 TS,无需编译直接运行:

node run.ts

输出如下(时间随运行时刻变化):

现在是 2026-10-27 14:32:05,星期二。

模型本身并不知道现在几点,这个答案必然来自 timeTool 的返回——它确实自主决定了调用工具。多问几句还能观察这层自主性:只要问题涉及当下(比如“我这个月还剩几天”),instructions 的约束还在,模型就照样去查工具;完全不涉及时它也不会乱调。想亲眼确认调用过程,接着看下一节。

5、Mastra Dev 工作台

generate 只给了最终答案,中间过程——何时调工具、传了什么、耗时多少——要看本地调试台。Mastra Studio 开箱即用,零配置零注册:

pnpm dev

dev 脚本即 mastra dev,启动本地开发服务,关键一行输出是地址:

➜ Local:  http://localhost:4111/

浏览器打开 http://localhost:4111 进入 Studio。左侧列出注册过的 Agent,选“时间助手”直接开聊。重点在每轮回答附带的 Trace 面板:它按时间轴摊开一次 generate 的全过程——用户消息、模型响应、timeTool 的输入输出与耗时、模型拿到结果后的总结回答,哪个环节慢、哪一步花了 token,一眼可见。改一行 instructions 保存即热更新,立刻能试新行为——这是第一次用上“本地 Agent 调试台”,比 print 日志体面得多。

对照 Python 版的 LangSmith(云端服务,要注册账号、配两个环境变量),Studio 完全跑在本机,数据不出机器。本节只做初体验,工作台的进阶玩法留到系列第 8 篇展开,框架源码与迭代节奏可围观 GitHub 仓库。

6、与 Python 版对照

同样的任务走完两遍,把关键步骤摆进一张表,两栈差异一目了然(Python 侧细节见前篇):

维度 Python 版(LangChain) TypeScript 版(Mastra)
安装 uv init + uv add langchain langgraph pnpm create mastra@latest 一条命令
工具定义 @tool 装饰器,注解与 docstring 生成 schema createTool 对象,Zod 显式声明
Agent 组装 create_agent(model, tools, system_prompt) new Agent({ instructions, model, tools })
调试工具 LangSmith 云端追踪 mastra dev 本地 Studio

三点观察。其一,Python 的装饰器把“普通函数变工具”做到了极致;Mastra 的显式 schema 啰嗦些,但参数约束在代码里直接可读,类型检查器全程兜底。其二,两边换模型都很轻:init_chat_model("openai:gpt-5") 换成 model: 'openai/…' 即可,注意分隔符一边是冒号、一边是斜杠。其三,调试台的形态反映栈的哲学——Python 生态习惯把可观测外包给云端 SaaS,TS 生态把 Dev 工作台做进了框架本身。

7、常见坑

Node 版本过旧。症状:脚手架安装报引擎不匹配,或 node run.ts 直接报 Unknown file extension ".ts"。原因:直跑 TS 依赖 Node 22.18+ 的原生类型剥离。解法:nvm install 22 后 nvm use 22,node -v 确认再继续。

Key 环境变量对不上。模型字符串的前缀决定读取哪个变量:anthropic/… 对应 ANTHROPIC_API_KEY,openai/… 对应 OPENAI_API_KEY。前缀写错、变量放错文件(开发期加载 .env.development)都会鉴权失败;改完变量记得重启 mastra dev,进程不会自动重读。

TS 严格模式报错。两个高发点:inputSchema 顶层必须是 z.object({...}),直接传 z.string() 会类型报错;execute 的返回值要与 outputSchema 的结构一致,少字段或类型不符都会被标红。这类报错看着烦,恰恰是端到端类型安全在起作用——问题在编译期拦下,总好过运行时喂给模型脏数据。

8、总结

回顾全文:从 Node 22 环境检查起步,用 pnpm create mastra@latest 生成工程,看清 src/mastra/ 下“定义与注册”的文件组织;把 API Key 关进环境变量;用 createTool 加 Zod 定义时间工具,new Agent 组装注册,generate 跑通第一个会自主调工具的 Agent;最后在 mastra dev 的本地工作台里看到了完整调用轨迹。与 Python 版对照后,两栈的分野也清楚了:显式与隐式、本地与云端,各有各的道理。

留一个练习:给 Agent 加第二个工具——比如返回指定范围随机数的 randomTool,这次带上参数,练一练 inputSchema 里 z.number() 的最小最大值约束。完整走一遍“定义 → 注册 → Studio 里看 trace”,你会发现往 tools 对象里加一项就能扩展能力,这正是框架工程化的意义。对于准备把 Agent 做进 TS 项目的工程师,建议就按本篇路径把工程跑起来,先在 Studio 里把玩熟练,再进入下一篇的正题——Zod 类型化工具与端到端类型安全。

相关推荐

获取系统SDK版本、判断手机ROM
精选Code

获取系统SDK版本、判断手机ROM

Build获取系统SDK版本Android中部分API的使用,需要在特定的SDK版本之后才能使用,因此在兼容老版本SDK的时候,经常需要判断API的版本。各种Android版本的对应关系参考《Android各版本对应的SDK版本》判断手机ROM有时候需要判断手机系统的ROM,检测ROM是MIUI、EMUI还是Flyme,可以使用getprop命令,去系统build.prop文件(关于build.p

4.2k
AndroidStudio中各种中文乱码问题
精选Code

AndroidStudio中各种中文乱码问题

AndroidStudio中各种中文乱码问题1、编译Java错误信息乱码在出现这个Annotation processors must be explicitly declared now...问题的时候,正好也发现AndroidStudio Build Output错误信息都乱码。经常遇到各种问题,习惯了,现在遇到的问题,都是以后的答案。 1.1、修改项目build.gradle(无效)在整个p

2.8k
Multi-Agent 详解:多智能体协作架构与实践
精选Agent

Multi-Agent 详解:多智能体协作架构与实践

一个智能体配上一套工具,已经能完成相当多任务。但让它同时“当产品经理、写后端、跑测试、做代码评审”,很快就会露馅:上下文里塞满了互相干扰的指令,十几件工具的清单来回切换,任务做到一半忘了开头。解法看起来很自然——像人类团队一样分工:让多个智能体各司其职,由一个协调者调度,这就是 Multi-Agent(多智能体)系统。它也是 2026 年智能体工程里讨论度最高、误用率也最高的架构。本文按“架构模式…

122