结构化输出:让模型结果进入程序
问题场景
自然语言回答适合人读,不适合程序继续处理。学习助手如果要把「学习计划」渲染成日历、把「练习题」保存到数据库,不能只依赖一段 Markdown 文本。
结构化输出的目标是:让 Agent 返回符合 schema 的对象。这样 UI、API 和测试代码可以读取稳定字段,而不是从文本里猜。
Mastra 映射
Mastra 的 Agent 支持在 .generate() 或 .stream() 调用时传入 structuredOutput.schema。官方文档说明,结构化输出会让返回结果包含 response.object,其形状由 schema 定义。
ts
import { z } from 'zod'
const studyPlanSchema = z.array(
z.object({
day: z.number(),
focus: z.string(),
tasks: z.array(z.string()),
check: z.string(),
}),
)
const response = await studyAgent.generate('请生成 3 天 Mastra 学习计划', {
structuredOutput: {
schema: studyPlanSchema,
},
})
console.log(response.object)官方依据
Mastra 官方 Structured output 页面说明,可用 Zod、Valibot、ArkType 或 JSON Schema 定义输出结构,并从 response.object 读取结果。
三种 schema 不要混用
| schema | 用在哪里 | 约束谁 | 典型用途 |
|---|---|---|---|
Tool inputSchema | createTool() | 模型传给工具的参数 | 搜索关键词、用户 ID、日期 |
Tool outputSchema | createTool() | 工具返回给 Agent 和应用的结果 | 搜索命中、API 数据、计算结果 |
| Workflow step schema | createStep() / createWorkflow() | 步骤之间的数据流 | 学习计划流程的中间状态 |
Agent structuredOutput.schema | .generate() / .stream() | Agent 最终回答对象 | UI 卡片、JSON API、评估输入 |
判断原则:如果数据来自代码,用 Tool 或 Workflow schema;如果数据来自模型最终组织,用 Agent structured output。
和工具调用一起使用时的风险
有些模型不能在同一次 API 调用里同时处理工具调用和结构化输出。Mastra 官方文档给出三类处理方式:
| 方式 | 适合情况 | 代价 |
|---|---|---|
jsonPromptInjection: true | 模型不支持 provider 原生 response_format | 可靠性弱于原生结构化输出 |
单独指定 structuring model | 主 Agent 先完成工具调用,再由第二个模型抽结构 | 多一次模型调用,有额外成本和延迟 |
prepareStep 分步 | 先让 Agent 用工具,再在后续 step 输出结构 | 写法更复杂,但边界最清楚 |
教程最终项目采用更稳的路线:学习计划由 Tool 和 Workflow 返回结构化对象,Agent 负责解释和串联。真实项目需要模型生成结构时,再加 structuredOutput。
Vibe coding 提示词
text
请把这个 Mastra Agent 的最终回答改成结构化输出。
要求:
- 使用 Zod 定义 schema。
- 输出字段包括 title、summary、actions、checks。
- 不要从自然语言文本里正则解析 JSON。
- 如果 Agent 同时使用 tools,请说明当前模型是否支持 tools + structured output。
- 给出一条最小验证命令或最小调用样例。验证方式
结构化输出的验收重点不是「看起来像 JSON」,而是程序能解析:
ts
const parsed = studyPlanSchema.safeParse(response.object)
if (!parsed.success) {
console.error(parsed.error.format())
throw new Error('structured output schema mismatch')
}检查清单:
- 字段是否都有明确类型。
- 可选字段是否真的允许为空。
- 数组长度是否需要
.min()或.max()。 - 下游 UI 是否只读取 schema 中存在的字段。
- 失败时是否有
fallbackValue或明确错误提示。
常见错误
| 错误 | 后果 | 修复 |
|---|---|---|
| 让模型「请输出 JSON」但没有 schema | 格式容易漂移 | 使用 structuredOutput.schema |
| schema 太复杂 | 模型反复失败或字段缺失 | 先用小对象,再逐步扩展 |
| 同时启用工具和结构化输出后工具不调用 | 模型 API 能力限制 | 改用单独 structuring model 或 prepareStep |
| 把结构化输出当安全边界 | 恶意内容仍可能进入字段 | 结合 Processors、业务校验和人工审批 |
小练习
把 npm run final:offline 输出里的 studyPlan 当作目标结构,给它写一个 Zod schema。再让 AI 根据 schema 生成 3 条测试样例,并手动检查字段是否足够支撑 UI 渲染。