Skip to content

第 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),
})
  1. 提示增强.describe() 文本会注入模型的工具定义中;
  2. 自动校验:模型幻觉出的非法参数会被拦截并要求重试;
  3. 类型推导: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 的正确方式是?

🛠️ 动手实践

  1. 为第 4 章的 chef-agent 编写 searchRecipe 工具:输入食材数组,从本地字典返回可做的菜名列表。
  2. 给 searchRecipe 的 inputSchema 加上 .max(5) 数组长度限制,故意让模型传 8 个食材,观察校验失败后的行为。
  3. 在 Studio 中调用带工具的 Agent,找到工具调用的入参展示位置并截图记录。

下一章:第 6 章 · Agent 与工具集成实战