第 5 章 · Tools 工具定义
本章目标:掌握 createTool 定义工具的完整模式——Zod 参数校验、execute 执行体,以及工具与 Agent 的绑定方式。
5.1 工具是什么
LLM 本身只会生成文本。Tool(工具)是让模型获得"行动能力"的机制:你把一个函数的名称、参数说明和执行逻辑注册给 Agent,模型在推理时自主决定何时调用、传什么参数,框架负责真正执行函数并把结果回传给模型继续推理。
text
用户提问 → 模型判断需要查数据 → 发起 tool-call → 框架执行你的函数
← 结果回传模型 ← 函数返回值 ←
模型基于结果组织最终回答5.2 用 createTool 定义第一个工具
typescript
// src/mastra/tools/weather-tool.ts
import { createTool } from '@mastra/core/tools';
import { z } from 'zod';
export const weatherTool = createTool({
// 工具唯一 ID:模型据此引用该工具
id: 'get-weather',
// 描述写给模型看:说清楚"什么时候该用我"
description: '获取指定城市当前的天气信息',
// 输入 schema:用 Zod 声明参数并自动完成校验
inputSchema: z.object({
city: z.string().describe('城市名称,如 "北京"'),
unit: z.enum(['celsius', 'fahrenheit']).default('celsius'),
}),
// 输出 schema:声明返回结构,便于类型推断
outputSchema: z.object({
temperature: z.number(),
condition: z.string(),
}),
// 执行体:真正的业务逻辑(框架保证入参已通过校验)
execute: async ({ context }) => {
const { city, unit } = context;
// 实际项目中这里调用真实天气 API
const mockData: Record<string, { temperature: number; condition: string }> = {
北京: { temperature: 18, condition: '晴' },
上海: { temperature: 22, condition: '多云' },
};
const data = mockData[city] ?? { temperature: 20, condition: '未知' };
return data;
},
});四个字段各司其职:id 标识工具、description 教模型何时使用、inputSchema 约束并校验参数、execute 承载真实逻辑。
5.3 Zod schema 的作用
Zod 不只是类型声明,它在运行时提供三重保障:
typescript
inputSchema: z.object({
// .describe() 会进入模型的函数说明,直接影响传参质量
query: z.string().min(1).describe('搜索关键词'),
// .optional() 允许模型不传;.default() 自动补默认值
limit: z.number().int().max(50).default(10),
})- 提示增强:
.describe()文本会注入模型的工具定义中; - 自动校验:模型幻觉出的非法参数会被拦截并要求重试;
- 类型推导:TypeScript 自动获得
context.query: string类型。
5.4 把工具挂到 Agent 上
typescript
// src/mastra/agents/weather-agent.ts
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 weather assistant.
Use the get-weather tool to fetch current conditions.`,
model: 'openai/gpt-5-mini',
// tools 是对象形式:键名会成为模型可见的工具引用名
tools: { weatherTool },
});typescript
// 真实场景示例:工具内调用外部 HTTP API 并做超时保护
execute: async ({ context }) => {
const res = await fetch(`https://wttr.in/${encodeURIComponent(context.city)}?format=j1`, {
signal: AbortSignal.timeout(5000), // 5 秒超时防止挂死
});
const data = await res.json();
return {
temperature: data.current_condition[0].temp_C,
condition: data.current_condition[0].weatherDesc[0].value,
};
}instructions 里要提工具
在 instructions 中明确提及工具用途(如 "Use the get-weather tool...")能显著提高模型调用工具的准确率。
本章小结
- Tool = 让 LLM 获得"行动能力"的机制,模型决策调用、框架执行函数;
createTool({ id, description, inputSchema, outputSchema, execute })五件套缺一不可;- Zod
.describe()写给模型看,schema 校验运行时兜底,TS 类型自动推导; - 通过
tools: { myTool }对象形式挂载到 Agent。
🧪 随堂测验
点击你认为正确的选项。答错时会展示正确答案与原因解析。
1. createTool 中 description 字段的作用是?
2. 模型生成的工具参数不符合 inputSchema 时会发生什么?
3. inputSchema 中 z.string().describe("城市名称") 的 describe 主要影响什么?
4. 把工具挂载到 Agent 的正确方式是?
🛠️ 动手实践
- 为第 4 章的 chef-agent 编写
searchRecipe工具:输入食材数组,从本地字典返回可做的菜名列表。 - 给 searchRecipe 的 inputSchema 加上
.max(5)数组长度限制,故意让模型传 8 个食材,观察校验失败后的行为。 - 在 Studio 中调用带工具的 Agent,找到工具调用的入参展示位置并截图记录。