Give your Mastra agent tools with createTool and Zod schemas. Build an order status tool, control steps with maxSteps, and test it in Mastra Studio.
Large language models are trained on historical data. They cannot look inside your live database or check current package tracking numbers on their own. Tools bridge this gap by turning your TypeScript functions into actions that an AI agent can execute on demand.
In the previous lesson, you built a basic support agent that answers general text queries. Now you will expand your online store assistant by giving it an order lookup tool so it can fetch real-time shipping data for customers.
Previous lesson: Building Your First Mastra Agent | Next lesson: Adding Memory to Your Mastra Agent
A tool is a typed TypeScript function exposed to a model along with a schema that describes what the function does and what arguments it expects.
Think of a tool like a database lookup terminal on a support rep's desk. The representative knows when to type an order number into that terminal based on what the customer asks.
When you pass tools to a Mastra agent, the following interaction happens:
The model never touches your database directly. It only produces the parameters, and your code executes the actual logic.
Quick Insight: The model decides whether to call a tool based on the text description you write for that tool. If your description is vague, the model will not know when to invoke it.
Mastra uses Zod schemas to validate inputs and outputs at runtime. The createTool function from @mastra/core/tools requires an id, a descriptive string, an inputSchema, an outputSchema, and an execute function.
Create a new file in your project at src/mastra/tools/order-status-tool.ts:
tsCopy
The execute function receives the validated input object directly as its first parameter. You can destructure fields like orderId right in the parameter list.
Common Mistake: Do not wrap your arguments inside a context parameter like execute: async ({ context }) => context.orderId. Mastra provides the validated properties directly on the root input object.
Once a tool is created, you attach it to an agent using the tools configuration property. The key you use in the tools object becomes the tool identifier the model observes during inference.
Update your support agent definition in src/mastra/agents/support-agent.ts:
tsCopy
Make sure your agent is exported in src/mastra/index.ts so the Mastra CLI and runtime detect it:
tsCopy
Pro Tip: The agent instructions should explicitly mention that the agent has access to the tool. Clear guidance prevents the model from apologizing and claiming it lacks live information.
When an agent calls a tool, it uses one step to call the function and another step to generate the final response from the tool output. If an agent needs to call multiple tools in sequence, it requires several steps.
Mastra agents run up to 5 steps per call by default, which is enough for a single tool call and a final answer. Use the maxSteps option on agent.generate() or agent.stream() to raise or lower that limit. A lower limit keeps costs predictable. A higher limit lets the agent chain several tool calls in one request.
Create a test script at src/test-tool.ts to run the agent from the command line:
tsCopy
Run this file with tsx:
bashCopy
If you set maxSteps to 1, the agent stops right after the tool call and never writes a final answer, because reading the tool result takes a second step.
Quick Challenge: Change the prompt in src/test-tool.ts to ask for ORD-9999 instead of ORD-1001. Observe how the agent handles the not_found status returned by your tool without crashing.
Mastra includes a local development environment called Mastra Studio. It provides an interface to execute tools independently from the model, inspect schema validations, and trace agent tool calls.
Start the Mastra development server:
bashCopy
Open your browser and navigate to http://localhost:4111.
In Mastra Studio:
get-order-status.{"orderId": "ORD-1002"} and click Run.Support Agent, and type: "What is the status of ORD-1003?"Studio displays the trace showing the user prompt, the tool invocation with arguments, and the final response.
Try This: Add a second property named carrier (a string) to both the outputSchema and the return value of orderStatusTool. Run the agent in Studio and see if the assistant mentions the carrier in its final answer.
| Feature | Purpose | Key Property |
|---|---|---|
createTool | Defines typed functions the model can execute | @mastra/core/tools |
inputSchema | Enforces and documents argument types | Zod object schema |
outputSchema | Validates data sent back to the model | Zod object schema |
tools | Registers the tool on the Agent instance | Object map on Agent |
maxSteps | Sets maximum multi-step execution loops | Parameter in agent.generate |
In the next lesson, Adding Memory to Your Mastra Agent, you will add stateful conversation threads and persistent working memory so your agent remembers customer details between messages.
Was this lesson helpful?