服务化与 API 集成:从 Studio 走向真实应用
问题场景
本教程的离线 Demo 直接运行 TypeScript 文件,最终项目也可以通过 Mastra Studio 调试。但真实应用通常还需要前端、鉴权、请求级配置、审计日志和部署环境。
这时需要把 Mastra 看成一个服务运行时:它负责暴露 Agent、Workflow、Tool 等能力,业务应用通过 HTTP、SDK 或自定义路由调用这些能力。
Mastra Server 做什么
官方部署文档说明,mastra build 会把应用编译成可独立运行的 Node.js server;Server 文档说明,注册的 Agents、Workflows 等能力会通过 API 暴露,并可通过 middleware、custom routes 和 client SDK 接入应用。
flowchart LR
UI["Web UI"] --> Server["Mastra Server"]
Server --> Agents["Registered Agents"]
Server --> Workflows["Registered Workflows"]
Server --> Routes["Custom API Routes"]
Server --> Middleware["Middleware"]
Agents --> Storage["Storage / Memory"]
Workflows --> Storage服务化以后,src/mastra/index.ts 不再只是 Studio 的入口,它也是生产服务的注册表:
agents:可被聊天 UI、Studio、SDK 调用。workflows:可被后台任务或业务 API 触发。server.middleware:处理鉴权、日志、请求上下文。server.apiRoutes:补充框架默认 endpoint 之外的业务接口。storage:保存 memory、workflow state、approval snapshot 等状态。
Studio、Swagger UI 和正式 UI
官方 Studio 文档说明,运行 mastra dev 后可以打开 Studio 交互调试,也可以访问 Swagger UI 查看底层 REST API。
| 入口 | 适合用途 | 不适合用途 |
|---|---|---|
| Studio | 开发调试、查看工具调用、试验模型参数 | 直接作为公开用户界面 |
| Swagger UI | 检查 endpoint、手工调用 API | 长期产品交互 |
| 正式 Web UI | 面向用户的聊天、进度、引用、审批 | 调试内部 trace 细节 |
教学项目先使用 Studio,是为了把 Agent 行为看清楚。等工具、记忆和工作流稳定后,再接前端。
Middleware:请求进入系统前先处理
Mastra server middleware 可以在 route handler 前后运行,适合处理:
- 鉴权。
- 请求日志。
- CORS。
- 从请求头、JWT 或业务数据库里提取用户信息。
- 写入
RequestContext。
import { Mastra } from '@mastra/core'
import { RequestContext } from '@mastra/core/request-context'
export const mastra = new Mastra({
agents: { studyAgent },
server: {
middleware: [
async (context, next) => {
const requestContext = context.get('requestContext')
const language = context.req.header('accept-language')?.startsWith('en')
? 'en-US'
: 'zh-CN'
requestContext.set('language', language)
await next()
},
],
},
})安全边界
RequestContext 可以携带权限、租户和功能开关,但不应该把原始 token、密钥或完整请求头交给模型。先在服务端提取「可用于决策的派生值」,再传给 Agent。
用户隔离:resource 不应该由前端随便传
官方 middleware 文档强调,鉴权证明「谁在访问」,授权决定「能访问什么」。Memory 的 resourceId 需要绑定到已认证用户或租户,否则用户可能通过猜测参数访问其他人的 thread。
官方 Auth 文档还说明,如果不配置 auth,Studio UI 和 API routes 都会公开访问。教学项目可以保持本地无鉴权,但任何共享环境都必须先决定认证方式。
export const mastra = new Mastra({
server: {
auth: {
authenticateToken: async token => {
return verifyToken(token)
},
mapUserToResourceId: user => user.id,
},
},
})Study Agent 的生产化设计应遵循:
| 数据 | 来源 | 是否信任 |
|---|---|---|
resourceId | 服务端鉴权结果 | 可信 |
threadId | 前端当前会话,但需校验归属 | 部分可信 |
user-tier | 服务端订阅系统 | 可信 |
debug | 内部管理员或开发环境 | 部分可信 |
apiKey | 环境变量或密钥管理系统 | 不进入模型上下文 |
Storage:哪些能力依赖持久化
官方 Storage 文档说明,MastraStorage 统一管理 suspended workflows、memory、traces 和 eval datasets。没有配置 storage 时,数据不会跨应用重启或部署持久保存。
| 能力 | 是否需要 storage | 原因 |
|---|---|---|
| 单次无状态回答 | 不强制 | 请求结束即可丢弃 |
| Memory thread | 需要 | 保存多轮消息和用户偏好 |
| Workflow suspend/resume | 需要 | snapshot 要可恢复 |
| Agent approval | 需要 | 审批状态要等待人工操作 |
| Observability traces | 需要 | 运行记录要可查询 |
| Scorers / eval datasets | 需要 | 评估结果要可比较 |
教学项目使用 LibSQL 是为了让本地学习成本低。生产环境应按部署方式选择 PostgreSQL、托管数据库或其他官方支持的 storage provider。
Custom API Routes:只补业务接口
Mastra 会自动暴露已注册 Agent 和 Workflow。自定义路由适合处理额外业务行为,例如健康检查、课程资料列表、导出报告。
import { registerApiRoute } from '@mastra/core/server'
export const mastra = new Mastra({
server: {
apiRoutes: [
registerApiRoute('/healthz', {
method: 'GET',
requiresAuth: false,
handler: async c => c.json({ ok: true }),
}),
],
},
})不要用 custom route 绕开 Agent、Tool、Workflow 的边界。能写成 Tool 的业务动作仍然写成 Tool;能写成 Workflow 的确定步骤仍然写成 Workflow。
Client SDK 与前端接入
官方 Mastra Client SDK 提供从浏览器或客户端环境调用 Mastra Server 的接口。教学项目没有安装 @mastra/client-js,但正式接前端时可以按这个方向扩展:
import { MastraClient } from '@mastra/client-js'
export const mastraClient = new MastraClient({
baseUrl: process.env.MASTRA_API_URL ?? 'http://localhost:4111',
})
const agent = mastraClient.getAgent('studyAgent')
const response = await agent.generate('解释 Agent Loop')前端集成建议:
| 前端需求 | 调用方式 | 备注 |
|---|---|---|
| 普通问答 | Agent .generate() | 简单但没有实时进度 |
| 聊天流式输出 | Agent .stream() | UI 同时处理文本和工具状态 |
| 学习计划生成 | Workflow run | 步骤明确,便于显示进度 |
| 后台导出 | Custom route 或 Workflow | 需要鉴权和任务状态 |
部署取舍
官方 Deployment 文档给出多种部署方式:独立 Mastra server、Monorepo、Mastra platform、云服务商、Web framework 集成、Workflow runner。
| 阶段 | 推荐方式 | 原因 |
|---|---|---|
| 本地学习 | mastra dev + Studio | 看清 Agent、Tool、Workflow 行为 |
| 小型内部工具 | 独立 Mastra server | 结构简单,便于隔离密钥 |
| 已有 Web 应用 | 集成到 Next.js / Astro 等框架 | 复用现有鉴权和部署 |
| 长任务和定时任务 | Workflow runner | 需要重试、状态和监控 |
| 团队持续调试 | Mastra platform 或自建可观测系统 | 需要 trace、log、scorer 数据 |
给 AI 编程工具的提示词
请为这个 Mastra Study Agent 设计服务化接入方案。
要求:
- 不新增前端框架,只先说明 API 和安全边界。
- 说明哪些能力使用自动暴露的 Agent / Workflow endpoint。
- 说明哪些能力需要 custom API route。
- 设计 middleware:鉴权、RequestContext、resourceId 隔离、请求日志。
- 不要把 token、API Key 或 tenant secret 放进 prompt。
- 给出最小验证清单。验证清单
| 验证项 | 方法 |
|---|---|
| Studio 能看到注册对象 | npm run final:dev 后检查 Agents / Workflows |
| Swagger UI 能看到 API | 打开 /swagger-ui |
| 未授权请求被拒绝 | 访问受保护接口应返回 401 或 403 |
| resource 隔离生效 | 用户 A 不能读取用户 B 的 thread |
| storage 持久化生效 | 重启后 memory thread 或 workflow snapshot 仍可恢复 |
| RequestContext 生效 | 不同语言或套餐触发不同工具策略 |
| 自定义路由不泄露内部信息 | 错误响应不包含密钥、路径或堆栈 |
常见错误
| 错误 | 后果 | 修复 |
|---|---|---|
| 把 Studio 当成用户界面 | 内部调试信息暴露 | Studio 用于开发或受控团队环境 |
前端直接决定 resourceId | 用户可能越权读取历史 | 服务端根据鉴权结果映射 |
| custom route 里重写 Agent 逻辑 | 行为分散,难以测试 | 业务能力仍放 Tool / Workflow |
| 中间件把原始 token 写进 prompt | 敏感信息泄露 | 只传非敏感派生值 |
小练习
为 Study Agent 设计一个 /api/study/summary 自定义路由。要求只返回当前认证用户的学习摘要,不允许前端传入任意 resourceId。先写出数据边界、鉴权规则和 3 条验收样例,再让 AI 生成代码。