Get typed JSON from a Mastra agent with structuredOutput and Zod. Validate nested data, handle errors with errorStrategy, and build a triage module.
Extract type-safe, validated data structures directly from your Mastra agent responses using Zod schemas. This lesson builds on agent memory and prepares your support assistant for automated workflows.
Previous lesson: Adding Memory to Your Mastra Agent | Next lesson: Building Mastra Workflows
By default, large language models return unstructured text. When an agent answers a question in conversational prose, a human can read it easily. But what happens when your backend code needs to read that response to route an email, update a database record, or trigger a refund?
Parsing strings with regular expressions or custom string splitters is brittle. Models might change capitalization, add pleasantries like "Sure, here is your information", or omit closing punctuation. If you expect a raw boolean flag and the model writes "Yes, absolutely", your code throws a runtime error.
Think of an unstructured response like a customer writing an essay on a blank sheet of paper, while structured output is like giving that customer a strict paper form with specific checkboxes and text fields.
Mastra solves this problem by integrating schema validation directly into the generation step. When you supply a schema, Mastra forces the underlying model to return a JSON object matching that schema and validates the result.
Mastra uses Zod to define data schemas. Zod is a TypeScript-first schema declaration and validation library. When you define a Zod schema, you define both runtime validation rules and static TypeScript types simultaneously.
Here is a schema designed for your support assistant to triage incoming customer issues:
tsCopy
Field descriptions added via the .describe() method are not just comments. The model reads these descriptions to understand what values to provide for each key.
To instruct a Mastra agent to return structured data, pass the structuredOutput option to the generate method.
Mastra validates the response against your schema. If validation succeeds, you receive the parsed object directly on result.object. If it fails, the errorStrategy option decides what happens: 'strict' throws an error, 'warn' logs a warning, and 'fallback' returns a fallbackValue that you provide.
Here is a complete, runnable script demonstrating how to classify a customer inquiry:
tsCopy
When you type result.object. in your code editor, TypeScript autocompletes every field defined in triageSchema.
Common Mistake: Do not look for the parsed data in result.text. When using structuredOutput, the validated JSON output lives on result.object. The result.text property contains the raw text payload.
Real support workflows often require more than primitive strings and booleans. You can nest objects, arrays, and optional fields within your Zod schema.
The following script extracts order details, customer sentiment, and an array of detected issue tags from a support inquiry:
tsCopy
Pro Tip: Be explicit with array descriptions. Adding .describe('Three to five keywords') prevents the model from generating unnecessarily long lists that consume excessive tokens.
Understanding when to use standard text generation versus structured output keeps your agent architecture clean.
| Requirement | Standard Generation | Structured Output |
|---|---|---|
| Response Target | Human end user | Programmatic pipeline or database |
| Access Pattern | result.text | result.object |
| Schema Required | None | Zod schema |
| Type Safety | Unchecked string | Full TypeScript type inference |
| Failure Mode | Inconsistent formatting | Handled by errorStrategy (throw, warn or fallback) |
Add a dedicated triage module to your store project under src/mastra/agents/triage-agent.ts. This module will process customer emails and return clean objects for your routing pipeline.
tsCopy
Now you can import processCustomerEmail anywhere in your application and handle the returned object with complete confidence that all properties exist and match their expected types.
Quick Challenge: Try modifying the triageOutputSchema to add a customerConfidenceScore field that accepts a number between 1 and 10. Run a test message to verify the model scores the inquiry within your constraints.
In the next lesson, Building Mastra Workflows, you will learn how to chain steps, route conditional logic, and pass these structured objects through multi-step pipelines.
Was this lesson helpful?