跳到主要内容

结构化输出

结构化输出让 Agent 返回符合 schema 所定义形状的对象,而不是文本。schema 会告诉模型要生成哪些字段,模型则确保最终结果符合该形状。

何时使用结构化输出
何时使用结构化输出的直接链接

当你需要 Agent 返回数据对象而不是文本时,请使用结构化输出。定义明确的字段可以简化提取所需值的过程,以便用于 API 调用、UI 渲染或应用逻辑。

定义 schema
定义 schema的直接链接

Agent 可以使用 Standard JSON SchemaZodValibotArkType 等)或 JSON Schema 定义预期输出,从而返回结构化数据。推荐使用 Zod 等库,因为它们提供 TypeScript 类型推断和运行时验证;当你需要与语言无关的格式时,JSON Schema 更适合。

使用 Zod 定义 output 形状:

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)

有关完整配置选项列表,请参阅 .generate()

输出示例: response.object 将包含 schema 定义的结构化数据。

[
{
"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 中获取。文本流块仍会发出,但其中包含自然语言文本,而不是结构化数据。

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的直接链接

当主 Agent 不擅长创建结构化输出时,可以向 structuredOutput 提供 model。在这种情况下,Mastra 会在底层使用第二个 Agent,从主 Agent 的自然语言响应中提取结构化数据。这会发起两次 LLM 调用:一次生成响应,另一次将响应转换为结构化对象。这样会增加一些延迟和成本,但可以提高复杂结构化任务的准确性。

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 与结构化输出
组合 Tool 与结构化输出的直接链接

当 Agent 同时配置了 Tool 和结构化输出时,某些模型可能不支持同时使用这两项功能。这是底层模型 API 的限制,并非 Mastra 本身的限制。

如果启用结构化输出后未调用 Tool,或组合两项功能时收到错误,请尝试以下解决方法之一。

解决方法
解决方法的直接链接

当模型不支持同时使用 Tool 和结构化输出时,有三种选择:

  1. 使用 jsonPromptInjection:将其设为 'auto',在支持时选择原生结构化输出,否则使用内联提示词注入;也可以明确选择注入模式
  2. 使用单独的结构化模型:向 structuredOutput 传入 model,使用第二个 LLM 进行结构化
  3. 使用 prepareStep:在不同步骤中分别处理 Tool 和结构化输出

以下各节详细介绍每种方法。

LLM 结构化输出支持
LLM 结构化输出支持的直接链接

由于 API 不同,各 LLM 对结构化输出的支持也不同。以下各节介绍不完全支持结构化输出或不支持将其与 Tool 组合使用的模型所对应的解决方法。

jsonPromptInjection
jsonpromptinjection的直接链接

默认情况下,Mastra 使用 response_format API 参数将 schema 传递给模型 Provider。将 jsonPromptInjection: 'auto' 设置为让 Mastra 根据模型能力数据选择模式。Mastra 对受支持模型使用原生结构化输出,对不受支持的模型或没有能力数据的模型使用内联提示词注入。

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 错误。

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 调用),结构化输出模型只负责生成结构化输出。

const response = await testAgent.generate('Tell me about TypeScript.', {
structuredOutput: {
schema: yourSchema,
model: 'openai/gpt-5.6-sol',
},
})

如果希望该结构化模型也能看到当前对话历史,请在 model 旁设置 useAgent: true。Mastra 会使用单独的结构化模型复用父 Agent,并在线程可用时附加只读 Memory 上下文。

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 的多步骤方法
multi-step-approach-with-preparestep的直接链接

对于不支持同时使用 Tool 和结构化输出的模型,可以使用 prepareStep 在不同步骤中分别处理它们。

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 提供的值。

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)