結構化輸出
結構化輸出讓 Agent 傳回符合 schema 所定義結構的物件,而非文字。Schema 會告訴模型要產生哪些欄位,而模型則會確保最終結果符合該結構。
何時使用結構化輸出何時使用結構化輸出 的直接連結
需要 Agent 傳回數據物件而非文字時,便可使用結構化輸出。明確定義欄位後,可更輕鬆擷取 API 呼叫、UI 渲染或應用程式邏輯所需的值。
定義 schema定義 schema 的直接連結
Agent 可使用 Standard JSON Schema(例如 Zod、Valibot、ArkType 等)或 JSON Schema 定義預期輸出,以傳回結構化數據。建議使用 Zod 等函式庫,因為它們提供 TypeScript 類型推斷和執行階段驗證;如需與編程語言無關的格式,則可使用 JSON Schema。
- Zod
- Valibot
- ArkType
- 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)
使用 Valibot 定義 output 的結構:
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 定義 output 的結構:
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 定義輸出結構:
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()。
輸出範例: 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 和結構化輸出時,你有三個選項:
- 使用
jsonPromptInjection:將其設定為'auto',以便在支援時選用原生結構化輸出,否則使用行內提示注入;你亦可明確選擇注入模式 - 使用另一個結構化模型:向
structuredOutput傳入model,使用第二個 LLM 執行結構化處理 - 使用
prepareStep:在不同步驟分別處理 Tool 和結構化輸出
以下各節會詳細說明每種方式。
LLM 的結構化輸出支援LLM 的結構化輸出支援 的直接連結
由於各 LLM 的 API 不同,對結構化輸出的支援亦有所差異。以下各節介紹模型未完全支援結構化輸出,或未能同時配合 Tool 使用時的替代方案。
jsonPromptInjectionjsonpromptinjection 的直接連結
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 模型不支援在同一次 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,並在有可用執行緒時附加唯讀記憶體內容。
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,
},
})
如果希望另一個結構化模型只處理目前的回應,而不繼承先前的對話記憶,請不要設定 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)