Using Agents
Agents let you build intelligent assistants powered by language models that can make decisions and perform actions. Each agent has required instructions and an LLM, with optional tools and memory.
An agent coordinates conversations, calls tools when needed, maintains context through memory, and produces responses tailored to the interaction. Agents can operate on their own or work as part of larger workflows.
To create an agent:
- Define instructions with the
Agent
class and set the LLM it will use. - Optionally configure tools and memory to extend functionality.
- Run the agent to generate responses, with support for streaming, structured output, and dynamic configuration.
This approach provides type safety and runtime validation, ensuring reliable behavior across all agent interactions.
Getting started
To use agents, install the required dependencies:
npm install @mastra/core @ai-sdk/openai
Mastra works with all AI SDK provider. See Model Providers for more information.
Import the necessary class from the agents module, and an LLM provider:
import { openai } from "@ai-sdk/openai";
import { Agent } from "@mastra/core/agent";
LLM providers
Each LLM provider needs its own API key, named using the provider’s identifier:
OPENAI_API_KEY=<your-api-key>
See the AI SDK Providers  in the Vercel AI SDK docs.
Creating an agent
To create an agent in Mastra, use the Agent
class. Every agent must include instructions
to define its behavior, and a model
parameter to specify the LLM provider and model:
import { openai } from "@ai-sdk/openai";
import { Agent } from "@mastra/core/agent";
export const testAgent = new Agent({
name: "test-agent",
instructions: "You are a helpful assistant.",
model: openai("gpt-4o-mini")
});
See Agent for more information.
Registering an agent
Register your agent in the Mastra instance:
import { Mastra } from "@mastra/core/mastra";
import { testAgent } from './agents/test-agent';
export const mastra = new Mastra({
// ...
agents: { testAgent },
});
Referencing an agent
You can call agents from workflow steps, tools, the Mastra Client, or the command line. Get a reference by calling .getAgent()
on your mastra
or mastraClient
instance, depending on your setup:
const testAgent = mastra.getAgent("testAgent");
See Calling agents for more information.
Generating responses
Use .generate()
to get a response from an agent. Pass a single string for simple prompts, an array of strings when providing multiple pieces of context, or an array of message objects with role
and content
for precise control over roles and conversational flows.
See .generate() for more information.
Generating text
Call .generate()
with an array of message objects that include role
and content
:
const response = await testAgent.generate([
{ role: "user", content: "Help me organize my day" },
{ role: "user", content: "My day starts at 9am and finishes at 5.30pm" },
{ role: "user", content: "I take lunch between 12:30 and 13:30" },
{ role: "user", content: "I have meetings Monday to Friday between 10:30 and 11:30" }
]);
console.log(response.text);
Streaming responses
Use .stream()
for real-time responses. Pass a single string for simple prompts, an array of strings when providing multiple pieces of context, or an array of message objects with role
and content
for precise control over roles and conversational flows.
See .stream() for more information.
Streaming text
Call .stream()
with an array of message objects that include role
and content
:
const stream = await testAgent.stream([
{ role: "user", content: "Help me organize my day" },
{ role: "user", content: "My day starts at 9am and finishes at 5.30pm" },
{ role: "user", content: "I take lunch between 12:30 and 13:30" },
{ role: "user", content: "I have meetings Monday to Friday between 10:30 and 11:30" }
]);
for await (const chunk of stream.textStream) {
process.stdout.write(chunk);
}
Completion using onFinish()
When streaming responses, the onFinish()
callback runs after the LLM finishes generating its response and all tool executions are complete.
It provides the final text
, execution steps
, finishReason
, token usage
statistics, and other metadata useful for monitoring or logging.
const stream = await testAgent.stream("Help me organize my day", {
onFinish: ({ steps, text, finishReason, usage }) => {
console.log({ steps, text, finishReason, usage });
}
});
for await (const chunk of stream.textStream) {
process.stdout.write(chunk);
}
Structured output
Agents can return structured, type-safe data by defining the expected output with either Zod  or JSON Schema . In both cases, the parsed result is available on response.object
, allowing you to work directly with validated and typed data.
Using Zod
Define the output
shape using Zod :
import { z } from "zod";
const response = await testAgent.generate("Monkey, Ice Cream, Boat", {
experimental_output: z.object({
summary: z.string(),
keywords: z.array(z.string())
})
});
console.log(response.object);
Using Tools
If you need to generate structured output alongside tool calls, you’ll need to use the experimental_output
or structuredOutput
property instead of output
. Here’s how:
const response = await testAgent.generate("Monkey, Ice Cream, Boat", {
experimental_output: z.object({
summary: z.string(),
keywords: z.array(z.string())
})
});
const responseWithExperimentalOutput = await testAgent.generate(
[
{
role: "user",
content:
"Please analyze this repository and provide a summary and keywords...",
},
],
{
// Use experimental_output to enable both structured output and tool calls
experimental_output: schema,
},
);
console.log("Structured Output:", responseWithExperimentalOutput.object);
const responseWithStructuredOutput = await testAgent.generate(
[
{
role: "user",
content:
"Please analyze this repository and provide a summary and keywords...",
},
],
{
structuredOutput: {
schema: z.object({
summary: z.string(),
keywords: z.array(z.string())
}),
model: openai("gpt-4o-mini"),
}
},
);
console.log("Structured Output:", responseWithStructuredOutput.object);
Describing images
Agents can analyze and describe images by processing both the visual content and any text within them. To enable image analysis, pass an object with type: 'image'
and the image URL in the content
array. You can combine image content with text prompts to guide the agent’s analysis.
const response = await testAgent.generate([
{
role: "user",
content: [
{
type: "image",
image: "https://placebear.com/cache/395-205.jpg",
mimeType: "image/jpeg"
},
{
type: "text",
text: "Describe the image in detail, and extract all the text in the image."
}
]
}
]);
console.log(response.text);
Multi-step tool use
Agents can be enhanced with tools, functions that extend their capabilities beyond text generation. Tools allow agents to perform calculations, access external systems, and process data. Agents not only decide whether to call tools they’re given, they determine the parameters that should be given to that tool.
For a detailed guide to creating and configuring tools, see the Tools Overview page.
Using maxSteps
The maxSteps
parameter controls the maximum number of sequential LLM calls an agent can make, particularly important when using tool calls. By default, it is set to 1 to prevent infinite loops in case of misconfigured tools:
const response = await testAgent.generate("Help me organize my day", {
maxSteps: 5
});
console.log(response.text);
Using onStepFinish
You can monitor the progress of multi-step operations using the onStepFinish
callback. This is useful for debugging or providing progress updates to users.
onStepFinish
is only available when streaming or generating text without structured output.
const response = await testAgent.generate("Help me organize my day", {
onStepFinish: ({ text, toolCalls, toolResults, finishReason, usage }) => {
console.log({ text, toolCalls, toolResults, finishReason, usage });
}
});
Testing agents locally
Use the mastra dev
CLI command to run your agents behind a local API.
By default, it loads exported agents from the src/mastra/agents
directory and creates endpoints for testing (for example, http://localhost:4111/api/agents/myAgent/generate
).
It also launches a visual playground where you can chat with your agent and view execution traces.
For more information, see the Local Dev Playground documentation.