> Discover all available pages from the documentation index: https://mastra.zisheng.pro/llms.txt # 结构化输出 结构化输出让 Agent 返回符合 schema 所定义形状的对象,而不是文本。schema 会告诉模型要生成哪些字段,模型则确保最终结果符合该形状。 ## 何时使用结构化输出 当你需要 Agent 返回数据对象而不是文本时,请使用结构化输出。定义明确的字段可以简化提取所需值的过程,以便用于 API 调用、UI 渲染或应用逻辑。 ## 定义 schema Agent 可以使用 [Standard JSON Schema](https://standardschema.dev/json-schema)([Zod](https://zod.dev/)、[Valibot](https://valibot.dev/)、[ArkType](https://arktype.io/) 等)或 [JSON Schema](https://json-schema.org/) 定义预期输出,从而返回结构化数据。推荐使用 Zod 等库,因为它们提供 TypeScript 类型推断和运行时验证;当你需要与语言无关的格式时,JSON Schema 更适合。 **Zod**: 使用 [Zod](https://zod.dev/) 定义 `output` 形状: ```typescript import { z } from 'zod' const response = await testAgent.generate('Help me plan my day.', { structuredOutput: { schema: z.array( z.object({ name: z.string(), activities: z.array(z.string()), }), ), }, }) console.log(response.object) ``` **Valibot**: 使用 [Valibot](https://valibot.dev/) 定义 `output` 形状: ```typescript import * as v from 'valibot' import { toStandardJsonSchema } from '@valibot/to-json-schema' const response = await testAgent.generate('Help me plan my day.', { structuredOutput: { schema: toStandardJsonSchema( v.array( v.object({ name: v.string(), activities: v.array(v.string()), }), ), ), }, }) console.log(response.object) ``` **ArkType**: 使用 [ArkType](https://arktype.io/) 定义 `output` 形状: ```typescript import { type } from 'arktype' const response = await testAgent.generate('Help me plan my day.', { structuredOutput: { schema: type({ name: 'string', activities: 'string[]', }).array(), }, }) console.log(response.object) ``` **JSON Schema**: 你也可以使用 JSON Schema 定义输出结构: ```typescript const response = await testAgent.generate('Help me plan my day.', { structuredOutput: { schema: { type: 'array', items: { type: 'object', properties: { name: { type: 'string' }, activities: { type: 'array', items: { type: 'string' }, }, }, required: ['name', 'activities'], }, }, }, }) console.log(response.object) ``` 有关完整配置选项列表,请参阅 [`.generate()`](https://mastra.zisheng.pro/reference/agents/generate)。 **输出示例:** `response.object` 将包含 schema 定义的结构化数据。 ```json [ { "name": "Morning Routine", "activities": ["Wake up at 7am", "Exercise", "Shower", "Breakfast"] }, { "name": "Work", "activities": ["Check emails", "Team meeting", "Lunch break"] }, { "name": "Evening", "activities": ["Dinner", "Relax", "Read a book", "Sleep by 10pm"] } ] ``` ## 流式传输结构化输出 流式传输也支持结构化输出。最终的结构化对象可在 `stream.fullStream` 中获取,流完成后也可在 `stream.object` 中获取。文本流块仍会发出,但其中包含自然语言文本,而不是结构化数据。 ```typescript import { z } from 'zod' const stream = await testAgent.stream('Help me plan my day.', { structuredOutput: { schema: z.array( z.object({ name: z.string(), activities: z.array(z.string()), }), ), }, }) for await (const chunk of stream.fullStream) { if (chunk.type === 'object-result') { console.log('\n', JSON.stringify(chunk, null, 2)) } process.stdout.write(JSON.stringify(chunk)) } console.log(await stream.object) for await (const chunk of stream.textStream) { process.stdout.write(chunk) } ``` ## 结构化 Agent 当主 Agent 不擅长创建结构化输出时,可以向 `structuredOutput` 提供 `model`。在这种情况下,Mastra 会在底层使用第二个 Agent,从主 Agent 的自然语言响应中提取结构化数据。这会发起两次 LLM 调用:一次生成响应,另一次将响应转换为结构化对象。这样会增加一些延迟和成本,但可以提高复杂结构化任务的准确性。 ```typescript import { z } from 'zod' const response = await testAgent.generate('Analyze the TypeScript programming language.', { structuredOutput: { schema: z.object({ overview: z.string(), strengths: z.array(z.string()), weaknesses: z.array(z.string()), useCases: z.array( z.object({ scenario: z.string(), reasoning: z.string(), }), ), comparison: z.object({ similarTo: z.array(z.string()), differentiators: z.array(z.string()), }), }), model: 'openai/gpt-5.6-sol', }, }) console.log(response.object) ``` ## 组合 Tool 与结构化输出 当 Agent 同时配置了 Tool 和结构化输出时,某些模型可能不支持同时使用这两项功能。这是底层模型 API 的限制,并非 Mastra 本身的限制。 如果启用结构化输出后未调用 Tool,或组合两项功能时收到错误,请尝试以下解决方法之一。 ### 解决方法 当模型不支持同时使用 Tool 和结构化输出时,有三种选择: 1. **使用 `jsonPromptInjection`**:将其设为 `'auto'`,在支持时选择原生结构化输出,否则使用内联提示词注入;也可以明确选择注入模式 2. **使用单独的结构化模型**:向 `structuredOutput` 传入 `model`,使用第二个 LLM 进行结构化 3. **使用 `prepareStep`**:在不同步骤中分别处理 Tool 和结构化输出 以下各节详细介绍每种方法。 ## LLM 结构化输出支持 由于 API 不同,各 LLM 对结构化输出的支持也不同。以下各节介绍不完全支持结构化输出或不支持将其与 Tool 组合使用的模型所对应的解决方法。 ### `jsonPromptInjection` 默认情况下,Mastra 使用 `response_format` API 参数将 schema 传递给模型 Provider。将 `jsonPromptInjection: 'auto'` 设置为让 Mastra 根据模型能力数据选择模式。Mastra 对受支持模型使用原生结构化输出,对不受支持的模型或没有能力数据的模型使用内联提示词注入。 ```typescript import { z } from 'zod' const response = await testAgent.generate('Help me plan my day.', { structuredOutput: { schema: z.array( z.object({ name: z.string(), activities: z.array(z.string()), }), ), jsonPromptInjection: 'auto', }, }) console.log(response.object) ``` 需要覆盖根据能力作出的选择时,请使用明确模式: - `false` 或省略:使用 Provider 的原生结构化输出。 - `'inline'`:将 schema 指令添加到最新的用户消息中。 - `true` 或 `'system'`:将 schema 指令添加到系统消息中。 - `'auto'`:模型支持时使用原生结构化输出,否则使用内联提示词注入。 > **Gemini 2.5 与 Tool:** Gemini 2.5 模型不支持在同一 API 调用中组合使用 `response_format`(结构化输出)和函数调用(Tool)。如果 Agent 有 Tool,并且你在 Gemini 2.5 模型中使用 `structuredOutput`,则必须设置 `jsonPromptInjection: true`,以避免出现 `Function calling with a response mime type: 'application/json' is unsupported` 错误。 > > ```typescript > const response = await agentWithTools.generate('Your prompt', { > structuredOutput: { > schema: yourSchema, > jsonPromptInjection: true, // Required for Gemini 2.5 when tools are present > }, > }) > ``` ### 使用单独的结构化模型 向 `structuredOutput` 属性提供 `model` 后,Mastra 会使用单独的内部 Agent 来处理结构化输出。主 Agent 会处理所有步骤(包括 Tool 调用),结构化输出模型只负责生成结构化输出。 **对于 AI Agent:** `model` 属性是 Mastra 模型路由器格式的字符串:`provider/model`,例如 `openai/gpt-5.6-sol`、`openai/gpt-5-mini`、`anthropic/claude-sonnet-4-6` 或 `google/gemini-2.5-pro`。请使用 `/` 而不是 `:` 作为分隔符。例如,使用 `openai/`,不要使用 `openai:`,也不要传入 Provider 对象。此格式无需导入 Provider。除非 Mastra 文档另有说明,否则不要安装任何 AI SDK 包。通过 `provider/model` 格式定义模型后,Mastra 会自动查找相应 Provider 的环境变量。定义的模型需要设置对应 Provider 的环境变量。OpenAI:`OPENAI_API_KEY`。Anthropic:`ANTHROPIC_API_KEY`。Google:`GOOGLE_API_KEY`。 ```typescript const response = await testAgent.generate('Tell me about TypeScript.', { structuredOutput: { schema: yourSchema, model: 'openai/gpt-5.6-sol', }, }) ``` 如果希望该结构化模型也能看到当前对话历史,请在 `model` 旁设置 `useAgent: true`。Mastra 会使用单独的结构化模型复用父 Agent,并在线程可用时附加只读 Memory 上下文。 ```typescript const response = await testAgent.generate('Return my profile as structured data.', { memory: { thread: 'thread-123', resource: 'user-123', }, structuredOutput: { schema: z.object({ favoriteColor: z.string(), hometown: z.string(), petName: z.string(), }), model: 'openai/gpt-5.6-sol', useAgent: true, }, }) ``` 如果希望单独的结构化模型仅根据当前响应工作,而不继承之前的对话 Memory,请不要设置 `useAgent`。 ### 使用 `prepareStep` 的多步骤方法 对于不支持同时使用 Tool 和结构化输出的模型,可以使用 `prepareStep` 在不同步骤中分别处理它们。 ```typescript const result = await agent.stream('weather in vancouver?', { prepareStep: async ({ stepNumber }) => { if (stepNumber === 0) { return { model: 'openai/gpt-5.6-sol', tools: { weatherTool, }, toolChoice: 'required', } } return { model: 'openai/gpt-5.6-sol', tools: undefined, structuredOutput: { schema: z.object({ temperature: z.number(), humidity: z.number(), windSpeed: z.number(), }), }, } }, }) ``` ## 处理错误 schema 验证失败时,可以使用 `errorStrategy` 控制错误处理方式。默认的 `strict` 策略会抛出错误,而 `warn` 会记录警告并继续。`fallback` 策略会返回通过 `fallbackValue` 提供的值。 ```typescript const response = await testAgent.generate('Tell me about TypeScript.', { structuredOutput: { schema: z.object({ summary: z.string(), keyFeatures: z.array(z.string()), }), errorStrategy: 'fallback', fallbackValue: { summary: 'TypeScript is a typed superset of JavaScript', keyFeatures: ['Static typing', 'Compiles to JavaScript', 'Better tooling'], }, }, }) console.log(response.object) ```