メインコンテンツへ移動

構造化出力

構造化出力を使うと、Agent はテキストではなく、スキーマで定義した形状に一致するオブジェクトを返せます。スキーマは生成するフィールドをモデルに伝え、モデルは最終結果がその形状に合うようにします。

構造化出力を使用する場面
構造化出力を使用する場面への直接リンク

Agent からテキストではなくデータオブジェクトを返す必要がある場合に使用します。明確に定義されたフィールドがあれば、API 呼び出し、UI のレンダリング、アプリケーションロジックに必要な値を簡単に取り出せます。

スキーマを定義する
スキーマを定義するへの直接リンク

Agent は、Standard JSON SchemaZodValibotArkType など)または JSON Schema で期待する出力を定義し、構造化データを返せます。Zod などのライブラリは TypeScript の型推論と実行時検証を提供するため推奨します。一方、言語に依存しない形式が必要な場合は JSON Schema が便利です。

Zodoutput の形状を定義します。

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 には、スキーマで定義した構造化データが格納されます。

[
{
"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 が構造化出力をうまく生成できない場合は、structuredOutputmodel を指定できます。この場合、Mastra は内部で2つ目の Agent を使用し、メイン Agent の自然言語レスポンスから構造化データを抽出します。レスポンス生成と構造化オブジェクトへの変換で LLM を2回呼び出すため、レイテンシーとコストは増えますが、複雑な構造化タスクの精度が向上する場合があります。

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 と構造化出力の両方を設定すると、一部のモデルでは両機能を同時に使用できない場合があります。これは Mastra ではなく、基盤となるモデル API の制限です。

構造化出力を有効にしたときに Tool が呼び出されない場合や、両機能を組み合わせてエラーが発生する場合は、次の回避策を試してください。

回避策
回避策への直接リンク

モデルが Tool と構造化出力の併用をサポートしていない場合、次の3つの方法があります。

  1. jsonPromptInjection を使用する: 'auto' を設定し、サポートされる場合はネイティブの構造化出力、それ以外はインラインのプロンプト挿入を選択するか、挿入モードを明示します
  2. 別の構造化モデルを使用する: structuredOutputmodel を渡し、2つ目の LLM で構造化します
  3. prepareStep を使用する: Tool と構造化出力を別々のステップで処理します

各方法の詳細は以下で説明します。

LLM の構造化出力サポート
LLM の構造化出力サポートへの直接リンク

API の違いにより、構造化出力のサポート状況は LLM ごとに異なります。以下では、構造化出力や Tool との併用を完全にはサポートしないモデル向けの回避策を説明します。

jsonPromptInjection
jsonpromptinjectionへの直接リンク

デフォルトでは、Mastra は response_format API パラメーターを使ってスキーマをモデル Provider に渡します。jsonPromptInjection: 'auto' を設定すると、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': 最新のユーザーメッセージにスキーマの指示を追加します。
  • true または 'system': system message にスキーマの指示を追加します。
  • 'auto': モデルがサポートしていればネイティブの構造化出力を使用し、それ以外はインラインのプロンプト挿入を使用します。
Tool を使用する Gemini 2.5

Gemini 2.5 モデルは、同じ API 呼び出しで response_format(構造化出力)と function calling(Tool)を組み合わせることをサポートしていません。Agent に Tool があり、Gemini 2.5 モデルで structuredOutput を使用する場合は、Function calling with a response mime type: 'application/json' is unsupported エラーを避けるため、jsonPromptInjection: true を設定する必要があります。

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 を再利用し、thread が利用できる場合は読み取り専用の 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(),
}),
},
}
},
})

エラーを処理する
エラーを処理するへの直接リンク

スキーマ検証に失敗した場合は、errorStrategy でエラーの処理方法を制御できます。デフォルトの strict はエラーをスローし、warn は警告を記録して処理を続行します。fallbackfallbackValue で指定した値を返します。

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)