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.
Tools in Mastra are type-safe, reusable functions that extend agent and workflow capabilities. Tools can perform actions, access external systems, and handle complex operations with validation and error handling.
Core Concept
Tools in Mastra:
Type-safe : Input/output validation with Zod schemas
Composable : Combine tools from multiple sources
Context-aware : Access Mastra resources and request context
Suspendable : Support async operations requiring approval
Observable : Automatic tracing and logging
Agents compose tools from multiple sources:
Assigned Tools : Explicitly configured tools
Memory Tools : Tools from memory instances (e.g., working memory)
Workspace Tools : File operations and code execution
MCP Tools : Tools from Model Context Protocol servers
Toolsets : Collections of related tools
const agent = new Agent ({
id: 'assistant' ,
tools: { calculator }, // Assigned tools
memory: new Memory ({ ... }), // Memory tools (working memory)
workspace: workspace , // Workspace tools
mcpServers: { github: mcpServer } // MCP tools
});
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 coordinates' ),
units: z . enum ([ 'celsius' , 'fahrenheit' ]). optional (). default ( 'celsius' )
}),
execute : async ({ location , units }) => {
const weather = await fetchWeather ( location , units );
return {
temperature: weather . temp ,
condition: weather . condition ,
humidity: weather . humidity
};
}
});
Validate tool outputs:
const calculateTool = createTool ({
id: 'calculate' ,
description: 'Perform arithmetic operations' ,
inputSchema: z . object ({
operation: z . enum ([ 'add' , 'subtract' , 'multiply' , 'divide' ]),
a: z . number (),
b: z . number ()
}),
outputSchema: z . object ({
result: z . number (),
operation: z . string ()
}),
execute : async ({ operation , a , b }) => {
let result : number ;
switch ( operation ) {
case 'add' : result = a + b ; break ;
case 'subtract' : result = a - b ; break ;
case 'multiply' : result = a * b ; break ;
case 'divide' : result = a / b ; break ;
}
return { result , operation };
}
});
Tool Execution Context
Tools receive an execution context with metadata:
const saveTool = createTool ({
id: 'save-data' ,
description: 'Save data to storage' ,
inputSchema: z . object ({ key: z . string (), value: z . any () }),
execute : async ({ key , value }, context ) => {
// Access Mastra instance
const storage = context ?. mastra ?. getStorage ();
await storage ?. set ( key , value );
// Access request context
const userId = context ?. requestContext ?. get ( 'userId' );
// Log activity
console . log ( `User ${ userId } saved ${ key } ` );
return { saved: true , key };
}
});
Agent Context
When called from an agent:
const tool = createTool ({
id: 'agent-tool' ,
execute : async ( input , context ) => {
// Agent-specific context
const { agent } = context ;
if ( agent ) {
const { toolCallId , messages , threadId , resourceId } = agent ;
console . log ( `Called in thread ${ threadId } ` );
}
}
});
Workflow Context
When called from a workflow:
const tool = createTool ({
id: 'workflow-tool' ,
execute : async ( input , context ) => {
// Workflow-specific context
const { workflow } = context ;
if ( workflow ) {
const { runId , workflowId , state , setState } = workflow ;
setState ({ ... state , lastCall: Date . now () });
}
}
});
Request Context Schema
Validate request context values:
const apiTool = createTool ({
id: 'api-call' ,
description: 'Call external API' ,
inputSchema: z . object ({ endpoint: z . string () }),
requestContextSchema: z . object ({
apiKey: z . string (),
userId: z . string ()
}),
execute : async ({ endpoint }, context ) => {
const apiKey = context . requestContext . get ( 'apiKey' );
const response = await fetch ( endpoint , {
headers: { 'Authorization' : `Bearer ${ apiKey } ` }
});
return response . json ();
}
});
Require explicit user approval for sensitive operations:
const deleteTool = createTool ({
id: 'delete-file' ,
description: 'Delete a file' ,
requireApproval: true ,
inputSchema: z . object ({ filepath: z . string () }),
execute : async ({ filepath }) => {
await fs . unlink ( filepath );
return { deleted: true , filepath };
}
});
// When the agent tries to use this tool, execution pauses
// until explicit approval is granted
Suspend and Resume
Tools can suspend execution for async operations:
const approvalTool = createTool ({
id: 'request-approval' ,
description: 'Request approval for an action' ,
inputSchema: z . object ({ action: z . string (), details: z . string () }),
suspendSchema: z . object ({ approvalId: z . string () }),
resumeSchema: z . object ({ approved: z . boolean (), comment: z . string (). optional () }),
execute : async ({ action , details }, context ) => {
// Check if we're resuming
if ( context . agent ?. resumeData ) {
const { approved , comment } = context . agent . resumeData ;
return { approved , comment: comment || 'No comment' };
}
// Create approval request
const approvalId = await createApprovalRequest ( action , details );
// Suspend execution
await context . agent ?. suspend ({ approvalId });
// This code won't execute until resumed
return { approved: false };
}
});
Transform tool output before sending to the model:
const searchTool = createTool ({
id: 'search-database' ,
description: 'Search database for records' ,
execute : async ({ query }) => {
const results = await db . search ( query );
return {
results , // Full data for application
count: results . length ,
query
};
},
toModelOutput : ( output ) => {
// Only send summary to model, not full data
return {
count: output . count ,
query: output . query ,
sample: output . results . slice ( 0 , 3 )
};
}
});
Provider-Specific Options
Configure provider-specific behavior:
const cachedTool = createTool ({
id: 'fetch-docs' ,
description: 'Fetch documentation' ,
providerOptions: {
anthropic: {
cacheControl: { type: 'ephemeral' }
}
},
execute : async () => {
return await fetchLargeDocs ();
}
});
Define tools for Model Context Protocol:
const mcpTool = createTool ({
id: 'mcp-tool' ,
description: 'MCP-enabled tool' ,
mcp: {
toolType: 'agent' ,
annotations: {
title: 'File Operations' ,
readOnlyHint: false ,
destructiveHint: true ,
idempotentHint: false
},
_meta: {
version: '1.0.0' ,
author: 'team@example.com'
}
},
execute : async ( input , context ) => {
// Access MCP context
if ( context . mcp ) {
const { extra , elicitation } = context . mcp ;
// Request user input via MCP
const userInput = await elicitation . sendRequest ({
prompt: 'Confirm deletion?' ,
schema: z . object ({ confirm: z . boolean () })
});
if ( ! userInput . confirm ) {
return { cancelled: true };
}
}
// Execute tool logic
}
});
Group related tools into toolsets:
import { createToolset } from '@mastra/core/tools' ;
const fileToolset = createToolset ({
id: 'file-operations' ,
description: 'Tools for file operations' ,
tools: {
read: createTool ({ id: 'read-file' , ... }),
write: createTool ({ id: 'write-file' , ... }),
delete: createTool ({ id: 'delete-file' , ... })
}
});
const agent = new Agent ({
tools: fileToolset . tools
});
Create tools dynamically based on request context:
const agent = new Agent ({
id: 'api-agent' ,
tools : ({ requestContext }) => {
const apiKey = requestContext . get ( 'apiKey' );
const baseUrl = requestContext . get ( 'baseUrl' );
return {
fetchData: createTool ({
id: 'fetch-data' ,
execute : async ({ endpoint }) => {
return await fetch ( ` ${ baseUrl }${ endpoint } ` , {
headers: { 'Authorization' : `Bearer ${ apiKey } ` }
});
}
})
};
}
});
Use pre-built integration tools:
import { SlackIntegration } from '@mastra/slack' ;
import { GithubIntegration } from '@mastra/github' ;
const slack = new SlackIntegration ({ apiKey: process . env . SLACK_API_KEY });
const github = new GithubIntegration ({ apiKey: process . env . GITHUB_TOKEN });
const agent = new Agent ({
id: 'integration-agent' ,
tools: {
... slack . tools ,
... github . tools
}
});
// Agent can now use Slack and GitHub tools
const result = await agent . generate (
'Send a message to #general and create a GitHub issue'
);
Memory instances provide working memory tools automatically:
import { Memory } from '@mastra/memory' ;
const agent = new Agent ({
id: 'assistant' ,
memory: new Memory ({
name: 'conversation' ,
options: {
workingMemory: {
enabled: true ,
schema: z . object ({
name: z . string (),
preferences: z . array ( z . string ())
})
}
}
})
});
// Agent automatically has update_working_memory tool
const result = await agent . generate (
'My name is Alice and I like coffee' ,
{ threadId: 'user-123' }
);
// Agent updates working memory: { name: 'Alice', preferences: ['coffee'] }
Workspace provides file and code execution tools:
import { Workspace } from '@mastra/workspace' ;
const agent = new Agent ({
id: 'coder' ,
workspace: new Workspace ({
filesystem: new LocalFilesystem ({ rootPath: './workspace' }),
sandbox: new E2BSandbox ({ apiKey: process . env . E2B_API_KEY })
})
});
// Agent has file and code execution tools
const result = await agent . generate (
'Create a Python script that calculates fibonacci numbers and run it'
);
Best Practices
Provide clear descriptions
Write descriptions that explain when to use the tool: // Good
description : 'Get current weather conditions and forecast for a specific city or location'
// Avoid
description : 'Weather'
Always define input schemas with descriptions: inputSchema : z . object ({
location: z . string (). describe ( 'City name or coordinates' ),
units: z . enum ([ 'celsius' , 'fahrenheit' ]). describe ( 'Temperature units' )
})
Return meaningful errors instead of throwing: execute : async ({ endpoint }) => {
try {
const response = await fetch ( endpoint );
return response . json ();
} catch ( error ) {
return {
error: true ,
message: `Failed to fetch: ${ error . message } `
};
}
}
Use requireApproval for destructive operations
Protect sensitive operations: const deleteTool = createTool ({
id: 'delete-database' ,
requireApproval: true ,
execute : async () => { ... }
});