Sortie structurée
La sortie structurée permet à un agent de renvoyer un objet conforme à la forme définie par un schéma plutôt que du texte. Le schéma indique au modèle les champs à produire, et le modèle veille à ce que le résultat final respecte cette forme.
Quand utiliser la sortie structuréeLien direct vers Quand utiliser la sortie structurée
Utilisez la sortie structurée lorsque vous avez besoin qu’un agent renvoie un objet de données plutôt que du texte. Des champs bien définis facilitent l’extraction des valeurs nécessaires aux appels d’API, au rendu de l’interface utilisateur ou à la logique applicative.
Définir des schémasLien direct vers Définir des schémas
Les agents peuvent renvoyer des données structurées en définissant la sortie attendue avec le schéma JSON standard (Zod, Valibot, ArkType, etc.) ou avec JSON Schema. Les bibliothèques comme Zod sont recommandées, car elles fournissent l’inférence de types TypeScript et la validation à l’exécution, tandis que JSON Schema est utile lorsqu’un format indépendant du langage est nécessaire.
- Zod
- Valibot
- ArkType
- JSON Schema
Définissez la forme de output avec Zod :
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)
Définissez la forme de output avec Valibot :
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)
Définissez la forme de output avec ArkType :
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)
Vous pouvez également utiliser JSON Schema pour définir la structure de votre sortie :
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)
Consultez .generate() pour obtenir la liste complète des options de configuration.
Exemple de sortie : response.object contiendra les données structurées telles qu’elles sont définies par le schéma.
[
{
"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"]
}
]
Diffuser une sortie structuréeLien direct vers Diffuser une sortie structurée
La diffusion en continu prend également en charge la sortie structurée. L’objet structuré final est disponible dans stream.fullStream, puis dans stream.object une fois la diffusion terminée. Des fragments de flux textuel sont toujours émis, mais ils contiennent du texte en langage naturel plutôt que des données structurées.
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 de structurationLien direct vers Agent de structuration
Lorsque votre agent principal ne maîtrise pas la création de sorties structurées, vous pouvez fournir un model à structuredOutput. Dans ce cas, Mastra utilise en interne un second agent pour extraire des données structurées de la réponse en langage naturel de l’agent principal. Deux appels au LLM sont alors effectués : l’un pour générer la réponse et l’autre pour la convertir en objet structuré. Cela augmente quelque peu la latence et le coût, mais peut améliorer la précision des tâches de structuration complexes.
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)
Combiner les outils et la sortie structuréeLien direct vers Combiner les outils et la sortie structurée
Lorsqu’un agent est configuré à la fois avec des outils et une sortie structurée, certains modèles peuvent ne pas prendre en charge l’utilisation conjointe de ces deux fonctionnalités. Il s’agit d’une limitation des API des modèles sous-jacents, et non de Mastra.
Si vos outils ne sont pas appelés lorsque la sortie structurée est activée, ou si vous recevez une erreur en combinant les deux fonctionnalités, essayez l’une des solutions de contournement ci-dessous.
Solutions de contournement possiblesLien direct vers Solutions de contournement possibles
Lorsque votre modèle ne prend pas en charge simultanément les outils et la sortie structurée, trois options s’offrent à vous :
- Utiliser
jsonPromptInjection: définissez sa valeur sur'auto'afin de sélectionner la sortie structurée native lorsqu’elle est prise en charge et, dans le cas contraire, l’injection de prompt en ligne, ou choisissez explicitement un mode d’injection - Utiliser un modèle de structuration distinct : transmettez un
modelàstructuredOutputpour utiliser un second LLM chargé de la structuration - Utiliser
prepareStep: gérez les outils et la sortie structurée au cours d’étapes distinctes
Chaque approche est détaillée dans les sections ci-dessous.
Prise en charge de la sortie structurée par les LLMLien direct vers Prise en charge de la sortie structurée par les LLM
La prise en charge de la sortie structurée varie selon les LLM en raison des différences entre leurs API. Les sections ci-dessous présentent des solutions de contournement pour les modèles qui ne prennent pas entièrement en charge la sortie structurée ou sa combinaison avec des outils.
jsonPromptInjectionLien direct vers jsonpromptinjection
Par défaut, Mastra transmet le schéma au fournisseur du modèle à l’aide du paramètre d’API response_format. Définissez jsonPromptInjection: 'auto' pour laisser Mastra choisir le mode à partir des données relatives aux capacités du modèle. Mastra utilise la sortie structurée native pour les modèles compatibles et l’injection de prompt en ligne pour les modèles incompatibles ou ceux dont les données de capacité ne sont pas disponibles.
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)
Utilisez un mode explicite lorsque vous devez remplacer le choix fondé sur les capacités :
falseou omis : utilisez la sortie structurée native du fournisseur.'inline': ajoutez les instructions du schéma au dernier message de l’utilisateur.trueou'system': ajoutez les instructions du schéma au message système.'auto': utilisez la sortie structurée native lorsque le modèle la prend en charge. Sinon, utilisez l’injection de prompt en ligne.
Les modèles Gemini 2.5 ne permettent pas de combiner response_format (sortie structurée) et l’appel de fonctions (outils) au sein d’un même appel d’API. Si votre agent dispose d’outils et que vous utilisez structuredOutput avec un modèle Gemini 2.5, vous devez définir jsonPromptInjection: true pour éviter l’erreur 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
},
})
Utiliser un modèle de structuration distinctLien direct vers Utiliser un modèle de structuration distinct
Lorsqu’un model est fourni à la propriété structuredOutput, Mastra utilise un agent interne distinct pour gérer la sortie structurée. L’agent principal prend en charge toutes les étapes (y compris l’appel d’outils), tandis que le modèle de sortie structurée se charge uniquement de générer cette sortie.
const response = await testAgent.generate('Tell me about TypeScript.', {
structuredOutput: {
schema: yourSchema,
model: 'openai/gpt-5.6-sol',
},
})
Si vous souhaitez que ce modèle de structuration accède également à l’historique de la conversation en cours, définissez useAgent: true en plus de model. Mastra réutilisera l’agent parent avec le modèle de structuration distinct et lui associera un contexte de mémoire en lecture seule lorsqu’un fil de discussion est disponible.
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,
},
})
Laissez useAgent non défini si vous souhaitez que le modèle de structuration distinct travaille uniquement à partir de la réponse actuelle, sans hériter de la mémoire des conversations précédentes.
Approche en plusieurs étapes avec prepareStepLien direct vers multi-step-approach-with-preparestep
Pour les modèles qui ne prennent pas en charge simultanément les outils et les sorties structurées, vous pouvez utiliser prepareStep afin de les gérer au cours d’étapes distinctes.
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(),
}),
},
}
},
})
Gérer les erreursLien direct vers Gérer les erreurs
Lorsque la validation du schéma échoue, vous pouvez contrôler la gestion des erreurs à l’aide de errorStrategy. La stratégie par défaut, strict, déclenche une erreur, tandis que warn consigne un avertissement et poursuit l’exécution. La stratégie fallback renvoie les valeurs fournies via 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)