# Using Tools Agents use tools to call APIs, query databases, or run custom functions from your codebase. Tools give agents capabilities beyond language generation by providing structured access to data and performing clearly defined operations. You can also load tools from remote [MCP servers](https://mastra.ai/docs/mcp/overview) to expand an agent's capabilities. ## When to use tools Use tools when an agent needs additional context or information from remote resources, or when it needs to run code that performs a specific operation. This includes tasks a model can't reliably handle on its own, such as fetching live data or returning consistent, well defined outputs. ## Creating a tool When creating tools, keep descriptions simple and focused on what the tool does, emphasizing its primary use case. Descriptive schema names can also help guide the agent on how to use the tool. This example shows how to create a tool that fetches weather data from an API. When the agent calls the tool, it provides the required input as defined by the tool's `inputSchema`. The tool accesses this data through its `inputData` parameter, which in this example includes the `location` used in the weather API query. ```typescript import { createTool } from "@mastra/core/tools"; import { z } from "zod"; export const weatherTool = createTool({ id: "weather-tool", description: "Fetches weather for a location", inputSchema: z.object({ location: z.string(), }), outputSchema: z.object({ weather: z.string(), }), execute: async (inputData) => { const { location } = inputData; const response = await fetch(`https://wttr.in/${location}?format=3`); const weather = await response.text(); return { weather }; }, }); ``` ## Adding tools to an agent To make a tool available to an agent, add it to `tools`. Mentioning available tools and their general purpose in the agent's system prompt helps the agent decide when to call a tool and when not to. An agent can use multiple tools to handle more complex tasks by delegating specific parts to individual tools. The agent decides which tools to use based on the user's message, the agent's instructions, and the tool descriptions and schemas. ```typescript import { Agent } from "@mastra/core/agent"; import { weatherTool } from "../tools/weather-tool"; export const weatherAgent = new Agent({ id: "weather-agent", name: "Weather Agent", instructions: ` You are a helpful weather assistant. Use the weatherTool to fetch current weather data.`, model: "openai/gpt-5.1", tools: { weatherTool }, }); ``` ## Using multiple tools When multiple tools are available, the agent may choose to use one, several, or none, depending on what's needed to answer the query. ```typescript import { weatherTool } from "../tools/weather-tool"; import { activitiesTool } from "../tools/activities-tool"; export const weatherAgent = new Agent({ id: "weather-agent", name: "Weather Agent", tools: { weatherTool, activitiesTool }, }); ``` ## Using agents as tools Agents can be added to other agents through the `agents` configuration. When you add a subagent, Mastra automatically converts it to a tool that the parent agent can call. The generated tool is named `agent-`. ```typescript import { Agent } from "@mastra/core/agent"; export const parentAgent = new Agent({ id: "parent-agent", name: "Parent Agent", description: "Take care in writing a good description here", instructions: `Instructions`, model: "openai/gpt-5.1", agents: { subAgent, }, }); const subAgent = new Agent({ id: "sub-agent", name: "Sub Agent", description: "Take care in writing a good description here", instructions: `Instructions`, model: "openai/gpt-5.1", }) ``` The subagent should include a `description` to help the parent agent understand when to use it. See the [`toolName` docs](#subagents-and-workflows-as-tools) to learn more about the tool naming scheme. ## Using workflows as tools Workflows can be added to agents through the `workflows` configuration. When you add a workflow, Mastra automatically converts it to a tool that the agent can call. The generated tool is named `workflow-` and uses the workflow's `inputSchema` and `outputSchema`. ```typescript import { Agent } from "@mastra/core/agent"; import { researchWorkflow } from "../workflows/research-workflow"; export const researchAgent = new Agent({ id: "research-agent", name: "Research Agent", instructions: ` You are a research assistant. Use the research workflow to gather and compile information on topics.`, model: "openai/gpt-5.1", tools: { weatherTool, }, workflows: { researchWorkflow, }, }); ``` The workflow should include a `description` to help the agent understand when to use it: ```typescript import { createWorkflow } from "@mastra/core/workflows"; import { z } from "zod"; export const researchWorkflow = createWorkflow({ id: "research-workflow", description: "Gathers information on a topic and compiles a summary report.", // Rest of the workflow... }) .commit(); ``` When the agent calls the workflow tool, it receives a response containing the workflow result and a `runId` that can be used to track the execution: ```typescript { result: { summary: "...", sources: ["..."] }, runId: "abc-123" } ``` See the [`toolName` docs](#subagents-and-workflows-as-tools) to learn more about the tool naming scheme. ## Controlling `toolName` in stream responses The `toolName` in stream responses is determined by the **object key** you use, not the `id` property of the tool, agent, or workflow. ```typescript // Tool defined with id: "weather-tool" export const weatherTool = createTool({ id: "weather-tool", // ... }); // Using the variable name as the key tools: { weatherTool } // Stream returns: toolName: "weatherTool" // Using the tool's id as the key tools: { [weatherTool.id]: weatherTool } // Stream returns: toolName: "weather-tool" // Using a custom key tools: { "my-custom-name": weatherTool } // Stream returns: toolName: "my-custom-name" ``` This lets you specify how tools are identified in the stream. If you want the `toolName` to match the tool's `id`, use the tool's `id` as the object key. ### Subagents and workflows as tools Subagents and workflows follow the same pattern. They are converted to tools with a prefix followed by your object key: | Property | Prefix | Example key | `toolName` | | ----------- | ----------- | ----------- | ------------------- | | `agents` | `agent-` | `weather` | `agent-weather` | | `workflows` | `workflow-` | `research` | `workflow-research` | ```typescript const orchestrator = new Agent({ agents: { weather: weatherAgent, // toolName: "agent-weather" }, workflows: { research: researchWorkflow, // toolName: "workflow-research" }, }); ``` Note that for subagents, you'll see two different identifiers in stream responses: - `toolName: "agent-weather"` in tool call events — the generated tool wrapper name - `id: "weather-agent"` in `data-tool-agent` chunks — the subagent's actual `id` property ## Tools with structured output When using tools with [structured output](https://mastra.ai/docs/agents/structured-output), some models don't support combining both features in the same API call. If your tools aren't being called when structured output is enabled, or you receive errors about incompatible options, see [Combining tools and structured output](https://mastra.ai/docs/agents/structured-output) for model compatibility information and workarounds. ## Related - [MCP Overview](https://mastra.ai/docs/mcp/overview) - [Dynamic Tool Search](https://mastra.ai/reference/processors/tool-search-processor) - Load tools on demand for agents with large tool libraries - [Structured Output](https://mastra.ai/docs/agents/structured-output) - [Agent Memory](https://mastra.ai/docs/agents/agent-memory) - [Request Context](https://mastra.ai/docs/server/request-context)