Appearance
04-multi-tool.ts
多工具编排示例,createAgent 配 4 个工具,演示 agent 自主选择 + 并行 tool calls。
功能介绍
这个示例演示了如何用 createAgent 构建多工具 agent。4 个工具(天气 / 计算器 / 时间 / 搜索)各有不同输入 schema,agent 根据 description 自主决定调用哪个工具。演示用例会触发 3 个工具并行调用(time + weather + calculator),展示 agent 在一个 turn 里发起多个 tool_calls 的能力。
使用场景
- 需要结合多种能力的任务(查询 + 计算 + 检索)
- agent 根据问题自主选择工具
- 并行调用多个工具提升效率
- 构建多功能智能助手
学习要点
createAgent的tools参数接受工具数组,agent 按description自主选择- agent 能在一个 turn 里并行调用多个工具(同一 AIMessage 多个 tool_calls)
tool()helper 配 zod schema 处理不同输入形态(结构化对象 / 算术 / 无参 / 文本)- 计算器用
switch而非Function(),避免代码注入风险 - 打印
result.messages可看到AIMessage(tool_calls × N) -> ToolMessage × N -> AIMessage(最终)的轨迹
源码
typescript
import "dotenv/config";
import { ChatOpenAI } from "@langchain/openai";
import { createAgent } from "langchain";
import { tool } from "@langchain/core/tools";
import { z } from "zod";
if (!process.env.ZHIPUAI_API_KEY) {
throw new Error("ZHIPUAI_API_KEY is not set in environment variables");
}
// 复用 01-tools 的天气工具定义
const weatherTool = tool(
async ({ city, unit }) => {
const weatherData: Record<string, { temp: number; condition: string }> = {
"北京": { temp: 25, condition: "晴天" },
"上海": { temp: 22, condition: "多云" },
"广州": { temp: 28, condition: "小雨" },
};
const data = weatherData[city] || { temp: 20, condition: "未知" };
const temp = unit === "fahrenheit" ? Math.round(data.temp * 9/5 + 32) : data.temp;
return `${city} 的天气: ${data.condition},${temp}°${unit === "celsius" ? "C" : "F"}`;
},
{
name: "get_current_weather",
description: "获取指定城市的当前天气",
schema: z.object({
city: z.string().describe("城市名称"),
unit: z.enum(["celsius", "fahrenheit"]).default("celsius").describe("温度单位"),
}),
}
);
// 计算器工具:用 switch 而非 Function(),避免代码注入风险
const calculatorTool = tool(
async ({ a, b, op }) => {
switch (op) {
case "+": return `${a} + ${b} = ${a + b}`;
case "-": return `${a} - ${b} = ${a - b}`;
case "*": return `${a} * ${b} = ${a * b}`;
case "/": return b === 0 ? "错误:除数不能为 0" : `${a} / ${b} = ${a / b}`;
}
},
{
name: "calculator",
description: "执行两个数的四则运算",
schema: z.object({
a: z.number().describe("第一个数"),
b: z.number().describe("第二个数"),
op: z.enum(["+", "-", "*", "/"]).describe("运算符"),
}),
}
);
// 时间工具:获取当前北京时间
const timeTool = tool(
async () => {
const now = new Date();
return `当前时间: ${now.toLocaleString("zh-CN", { timeZone: "Asia/Shanghai" })}`;
},
{
name: "get_current_time",
description: "获取当前时间(北京时间)",
schema: z.object({}),
}
);
// 搜索工具:mock 实现,关键词命中返回预设结果
const searchTool = tool(
async ({ query }) => {
const searchResults: Record<string, string> = {
"LangChain": "LangChain 是一个用于开发由语言模型驱动的应用程序的框架",
"DeepSeek": "DeepSeek 是一家中国 AI 公司,提供大语言模型",
"agent": "AI agent 是能自主调用工具完成任务的智能体",
};
for (const [keyword, result] of Object.entries(searchResults)) {
if (query.includes(keyword)) {
return result;
}
}
return `没有找到关于"${query}"的结果`;
},
{
name: "search",
description: "搜索网络获取信息",
schema: z.object({
query: z.string().describe("搜索关键词"),
}),
}
);
async function main() {
try {
console.log("=== Multi-Tool 示例(createAgent + 4 工具)===\n");
const model = new ChatOpenAI({
model: "deepseek-v3-1",
temperature: 0,
configuration: {
baseURL: "https://ark.cn-beijing.volces.com/api/coding/v3/",
apiKey: process.env.ZHIPUAI_API_KEY,
},
});
const agent = createAgent({
model,
tools: [weatherTool, calculatorTool, timeTool, searchTool],
});
const question = "帮我查一下:现在几点?北京天气怎么样?15 加 27 是多少?";
console.log("问题:", question);
console.log("\n---\n");
const result = await agent.invoke({
messages: [{ role: "user", content: question }],
});
// 打印消息历史,让并行 tool calls 可见
console.log("消息历史(共", result.messages.length, "条):");
for (const msg of result.messages) {
console.log(` [${msg._getType()}]`, msg.content);
}
console.log("\n---\n");
console.log("最终回答:", result.messages.at(-1)?.content);
} catch (error) {
console.error("Error during multi-tool example:", error);
process.exit(1);
}
}
main().catch(console.error);运行方式
bash
npm run dev src/05-agents/04-multi-tool.ts