Skip to content

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

本章目标:组合多个工具构建一个实用的旅行规划助手,掌握工具选择调优与多步推理控制。

6.1 实战目标

构建一个能回答"北京到上海旅游怎么安排"的助手,它需要组合两个工具:

  • getWeatherTool:查目的地天气(决定穿什么、去哪玩);
  • calculatorTool:精确计算预算(LLM 算术不可靠,必须外挂)。

6.2 定义第二个工具:计算器

typescript
// src/mastra/tools/calculator-tool.ts
import { createTool } from '@mastra/core/tools';
import { z } from 'zod';

export const calculatorTool = createTool({
  id: 'calculator',
  description: '执行精确的四则运算,输入合法算术表达式',
  inputSchema: z.object({
    expression: z.string().describe('算术表达式,如 "(1200 + 350) * 2"'),
  }),
  outputSchema: z.object({
    result: z.number(),
  }),
  execute: async ({ context }) => {
    const { expression } = context;
    // 安全白名单校验:只允许数字与运算符,防止注入
    if (!/^[\d+\-*/().\s]+$/.test(expression)) {
      throw new Error('非法表达式');
    }
    // 用 Function 构造器求值(表达式已过白名单)
    const result = new Function(`return (${expression})`)() as number;
    return { result };
  },
});

注意白名单正则——任何把模型输出直接拼进求值器的代码都必须做这层防御。

6.3 组合注册与调用

typescript
// src/mastra/agents/trip-agent.ts —— 双工具 Agent
import { Agent } from '@mastra/core/agent';
import { weatherTool } from '../tools/weather-tool';
import { calculatorTool } from '../tools/calculator-tool';

export const tripAgent = new Agent({
  id: 'trip-planner',
  name: 'Trip Planner',
  instructions: `
    You are a travel planning assistant.
    - Use getWeather to check destination conditions.
    - ALWAYS use the calculator for any arithmetic (never compute in your head).
    - Present plans as: 天气概况 / 行程建议 / 预算明细.`,
  model: 'openai/gpt-5-mini',
  tools: {
    weatherTool,
    calculatorTool,
  },
});
typescript
// 调用:一次请求可能触发多个工具、多轮循环
const res = await tripAgent.generate(
  '帮我规划周六上海一日游,两个人预算 2000 元,含门票餐饮交通',
);
console.log(res.text);

6.4 观察多步推理过程

一次提问背后是完整的 agentic 循环:

text
User: 帮我规划上海一日游…
 ├─ [step 1] tool-call: weatherTool({ city: "上海" })
 │   └─ { temperature: 22, condition: "多云" }
 ├─ [step 2] tool-call: calculatorTool({ expression: "150*2 + 400 + 300*2" })
 │   └─ { result: 1300 }
 └─ [final]  天气概况:多云 22°C…预算明细:门票 300×2 + 交通 400 + 餐饮 300×2 = 1300 元…

在 Studio 的对话面板可以逐步展开每次工具调用;这就是"模型决策 → 执行 → 回灌 → 再决策"的循环。

6.5 工具选择调优技巧

模型不调用或乱用工具时,按以下顺序排查:

症状原因修复
从不调用工具description 太模糊写清触发条件:"当用户询问 X 时使用"
该用 A 却用了 B两个工具 description 语义重叠明确划分边界并互斥描述
参数总是错.describe() 或约束太松补充参数说明、收紧 Zod 校验
无限循环调用没有终止信号instructions 中要求"拿到结果即回答"
typescript
// 从响应中读取结构化的工具调用记录(用于审计与调试)
for (const msg of res.response.messages ?? []) {
  if (msg.role === 'tool') {
    console.log('工具调用:', JSON.stringify(msg.content));
  }
}

成本提示

每轮工具循环都是一次新的 LLM 请求。任务越复杂 token 消耗越高,生产环境务必设置步数上限。

本章小结

  • 多工具 Agent = 各司其职的工具集合 + 明确分工的 instructions;
  • 涉及计算的任务必须外挂工具,不能信任 LLM 心算;
  • 白名单校验是一切动态求值类工具的安全底线;
  • 工具行为问题优先从 description 和 schema 两处排查。

🧪 随堂测验

点击你认为正确的选项。答错时会展示正确答案与原因解析。

1. 让 LLM 计算订单总额时,正确做法是?

2. 模型从不调用你定义的工具,最应该先检查什么?

3. 对执行用户输入表达式的求值类工具,必不可少的安全措施是?

4. 关于多步工具调用的成本,正确的认识是?

🛠️ 动手实践

  1. 给 tripAgent 追加第三个工具 currencyConvert(汇率换算),并在 instructions 中规定预算同时以人民币和美元展示。
  2. 把 weatherTool 的 description 改成一句模糊的"处理数据",对比改造前后模型调用准确率的变化。
  3. 在 Studio 中发起 10 次相同提问,统计 calculatorTool 的调用成功率。

下一章:第 7 章 · Workflow 基础与 .then()