Documentation Index Fetch the complete documentation index at: https://mintlify.com/mastra-ai/mastra/llms.txt
Use this file to discover all available pages before exploring further.
Agent Tools
Tools extend agent capabilities by allowing them to perform actions, access external systems, and manipulate data. This guide covers creating tools and assigning them to agents.
Tools are type-safe functions that agents can call during conversations. Each tool has:
Unique ID - Identifier for the tool
Description - What the tool does (used by LLM for selection)
Input Schema - Zod schema for parameter validation
Execute Function - The actual logic to run
Optional Output Schema - Validate tool results
From: packages/core/src/tools/tool.ts
import { createTool } from '@mastra/core/tools' ;
import { z } from 'zod' ;
const weatherTool = createTool ({
id: 'get-weather' ,
description: 'Get current weather for a location' ,
inputSchema: z . object ({
location: z . string (). describe ( 'City name or zip code' ),
units: z . enum ([ 'celsius' , 'fahrenheit' ]). optional (). default ( 'fahrenheit' ),
}),
execute : async ({ location , units }) => {
// Call weather API
const response = await fetch ( `https://api.weather.com/ ${ location } ` );
const data = await response . json ();
return {
temperature: data . temp ,
condition: data . condition ,
units ,
};
},
});
import { createTool } from '@mastra/core/tools' ;
import { z } from 'zod' ;
const stockPriceTool = createTool ({
id: 'get-stock-price' ,
description: 'Get current stock price for a ticker symbol' ,
inputSchema: z . object ({
symbol: z . string (). describe ( 'Stock ticker symbol (e.g., AAPL)' ),
}),
outputSchema: z . object ({
symbol: z . string (),
price: z . number (),
change: z . number (),
changePercent: z . number (),
}),
execute : async ({ symbol }) => {
const data = await fetchStockData ( symbol );
// Output is validated against outputSchema
return {
symbol: data . symbol ,
price: data . currentPrice ,
change: data . priceChange ,
changePercent: data . changePercent ,
};
},
});
For sensitive operations, require user approval:
const deleteFileTool = createTool ({
id: 'delete-file' ,
description: 'Delete a file from the system' ,
requireApproval: true , // User must approve
inputSchema: z . object ({
filepath: z . string (). describe ( 'Path to file to delete' ),
}),
execute : async ({ filepath }) => {
await fs . unlink ( filepath );
return { deleted: true , filepath };
},
});
Access Mastra resources in tools:
const saveDataTool = createTool ({
id: 'save-data' ,
description: 'Save data to persistent storage' ,
inputSchema: z . object ({
key: z . string (),
value: z . any (),
}),
execute : async ({ key , value }, context ) => {
// Access Mastra storage through context
const storage = context ?. mastra ?. getStorage ();
if ( ! storage ) {
throw new Error ( 'Storage not available' );
}
await storage . set ( key , value );
return { saved: true , key };
},
});
Assign tools when creating the agent:
import { Agent } from '@mastra/core/agent' ;
const agent = new Agent ({
id: 'weather-agent' ,
name: 'Weather Agent' ,
instructions: 'Help users with weather information' ,
model: 'openai/gpt-4o' ,
tools: {
weatherTool ,
stockPriceTool ,
},
});
From: examples/agent/src/mastra/agents/dynamic-tools-agent.ts
Load tools based on request context:
import { Agent } from '@mastra/core/agent' ;
import { RequestContext } from '@mastra/core/request-context' ;
const agent = new Agent ({
id: 'dynamic-agent' ,
name: 'Dynamic Agent' ,
instructions: 'You are a versatile assistant' ,
model: 'openai/gpt-4o' ,
// Tools function receives requestContext
tools : ({ requestContext }) => {
const userTier = requestContext . get ( 'userTier' );
const permissions = requestContext . get ( 'permissions' );
const tools : any = {
weatherTool ,
};
// Premium users get additional tools
if ( userTier === 'premium' ) {
tools . stockPriceTool = stockPriceTool ;
tools . advancedAnalysisTool = advancedAnalysisTool ;
}
// Admin users get admin tools
if ( permissions . includes ( 'admin' )) {
tools . deleteFileTool = deleteFileTool ;
}
return tools ;
},
});
// Use with context
const ctx = new RequestContext ();
ctx . set ( 'userTier' , 'premium' );
ctx . set ( 'permissions' , [ 'user' , 'admin' ]);
const result = await agent . generate ( 'Check the weather' , {
requestContext: ctx ,
});
From: examples/agent/src/mastra/agents/dynamic-tools-agent.ts
Let agents discover and load tools on demand:
import { Agent } from '@mastra/core/agent' ;
import { Memory } from '@mastra/memory' ;
import { ToolSearchProcessor } from '@mastra/core/processors' ;
const toolSearchProcessor = new ToolSearchProcessor ({
tools: {
calculator_add: calculatorAdd ,
calculator_multiply: calculatorMultiply ,
calculator_divide: calculatorDivide ,
get_stock_price: getStockPrice ,
translate_text: translateText ,
send_notification: sendNotification ,
},
search: {
topK: 5 , // Return top 5 matches
},
});
export const dynamicToolsAgent = new Agent ({
id: 'dynamic-tools-agent' ,
name: 'Dynamic Tools Agent' ,
description: 'An agent that discovers tools on demand' ,
instructions: `You are a helpful assistant with a large library of tools.
You do NOT have direct access to most tools. Instead, you have:
1. **search_tools**: Search for tools by keyword
2. **load_tool**: Load a tool by name
Workflow:
1. When you need a capability, use search_tools
2. Review results and pick the most relevant
3. Use load_tool to load it
4. The tool will be available on your next response` ,
model: 'openai/gpt-4o' ,
memory: new Memory (),
inputProcessors: [ toolSearchProcessor ],
});
Override agent tools for specific calls:
const agent = new Agent ({
id: 'basic-agent' ,
name: 'Basic Agent' ,
instructions: 'You are helpful' ,
model: 'openai/gpt-4o' ,
tools: {
weatherTool ,
},
});
// Use additional tools for this call only
const result = await agent . generate ( 'Send a notification' , {
clientTools: {
notificationTool ,
},
});
Control when and how tools are called:
// Let model decide (default)
const result = await agent . generate ( 'What is the weather?' , {
toolChoice: 'auto' ,
});
// Require tool usage
const result = await agent . generate ( 'Get weather for NYC' , {
toolChoice: 'required' ,
});
// Force specific tool
const result = await agent . generate ( 'Check weather' , {
toolChoice: { type: 'tool' , toolName: 'get-weather' },
});
// Disable tools
const result = await agent . generate ( 'Just chat' , {
toolChoice: 'none' ,
});
Limit which tools are available:
const agent = new Agent ({
id: 'agent' ,
name: 'Agent' ,
instructions: 'You are helpful' ,
model: 'openai/gpt-4o' ,
tools: {
weatherTool ,
stockTool ,
calculatorTool ,
deleteTool ,
},
});
// Only allow specific tools for this call
const result = await agent . generate ( 'Help me' , {
activeTools: [ 'get-weather' , 'get-stock-price' ],
});
Require approval for sensitive operations:
const result = await agent . stream ( 'Delete old logs' , {
requireToolApproval: true , // Approve all tools
});
for await ( const chunk of result . fullStream ) {
if ( chunk . type === 'tool-call' ) {
console . log ( 'Tool call pending approval:' , chunk . toolName );
// Approve or reject
await chunk . approve (); // or chunk.reject('Not allowed')
}
}
From: examples/agent/src/mastra/agents/model-v2-agent.ts
const cookingTool = createTool ({
id: 'get-recipe' ,
description: 'Get a recipe for a given ingredient' ,
inputSchema: z . object ({
ingredient: z . string (). describe ( 'Main ingredient' ),
}),
execute : async ({ ingredient }) => {
// Fetch recipe from API
return {
name: ` ${ ingredient } Recipe` ,
ingredients: [ '...' ],
steps: [ '...' ],
};
},
});
From: examples/agent/src/mastra/agents/dynamic-tools-agent.ts
const calculatorAdd = createTool ({
id: 'calculator-add' ,
description: 'Add two numbers together' ,
inputSchema: z . object ({
a: z . number (). describe ( 'First number' ),
b: z . number (). describe ( 'Second number' ),
}),
execute : async ({ a , b }) => {
return { result: a + b };
},
});
const searchDatabase = createTool ({
id: 'search-database' ,
description: 'Search the database for records' ,
inputSchema: z . object ({
query: z . string (). describe ( 'Search query' ),
limit: z . number (). optional (). default ( 10 ),
}),
outputSchema: z . object ({
results: z . array ( z . object ({
id: z . string (),
title: z . string (),
content: z . string (),
})),
total: z . number (),
}),
execute : async ({ query , limit }) => {
const results = await db . search ( query , limit );
return {
results ,
total: results . length ,
};
},
});
When you attach a workspace to an agent, file operation tools are automatically added:
import { Workspace , LocalFilesystem } from '@mastra/core/workspace' ;
const workspace = new Workspace ({
filesystem: new LocalFilesystem ({
basePath: './data' ,
}),
});
const agent = new Agent ({
id: 'file-agent' ,
name: 'File Agent' ,
instructions: 'You can work with files' ,
model: 'openai/gpt-4o' ,
workspace , // Injects file tools automatically
});
// Agent can now use:
// - write_file
// - read_file
// - list_files
// - delete_file
// - create_directory
Tool descriptions help the LLM decide when to use each tool: // Good
description : 'Get current weather conditions and forecast for a specific location'
// Avoid
description : 'Weather'
Use descriptive parameter names
Add .describe() to schema fields: inputSchema : z . object ({
location: z . string (). describe ( 'City name or zip code' ),
units: z . enum ([ 'C' , 'F' ]). describe ( 'Temperature units' ),
})
Validate both input and output
Return user-friendly error messages: execute : async ({ query }) => {
try {
return await searchAPI ( query );
} catch ( error ) {
return {
error: true ,
message: 'Failed to search. Please try again.' ,
};
}
}
Use requireApproval for sensitive operations
Protect destructive actions: createTool ({
id: 'delete-data' ,
requireApproval: true ,
// ...
})
Next Steps
Streaming Learn about streaming agent responses
Structured Output Get typed, validated output from agents
Workflows Execute multi-step workflows from agents
Tool API Reference Complete API documentation for tools