

























这种做法很简单:你的应用直接调 LLM API,把工具定义塞进每次请求里,自己跑 agent 循环。
┌─────────────────────────-─────────────────────────┐ │ 你的应用(单进程) │ │ │ │ ┌──────────────┐ tools 定义+messages ┌────────┐ │ │ │ Agent 循环 │ ─────────────────► │ LLM API│ │ │ │ │ ◄───────────────── │ │ │ │ └──────┬───────┘ tool_use / 文本 └────────┘ │ │ │ 调用本地函数 │ │ ▼ │ │ ┌──────────────┐ │ │ │ executeTool()│ ──► read_pdf, search_pdf │ │ └──────────────┘ (和你的代码跑在同一进程里) │ └─────────────────────────────────-─────────────────┘
你在代码里写好每个工具的名字、描述和参数格式(这叫「工具定义」),每次请求 LLM 时把工具定义和用户消息一起发过去。LLM 看到工具定义后,如果判断需要调工具,就返回一个 tool_use 响应(告诉你调哪个工具、传什么参数)。你的代码拿到 tool_use 后,调对应的函数执行,再把执行结果喂回 LLM。LLM 可能继续返回 tool_use=(调更多工具),也可能直接返回最终回答(=end_turn=)。这个「发消息 → 收 =tool_use → 执行工具 → 喂回结果 → 再发消息」的来回过程就是「工具调用循环」,在 Route 1 里你需要自己写代码管这个循环。
工具定义长这样(以 Node.js 为例):
const tools = [ { name: "read_pdf", description: "提取 PDF 文件的全部文本", input_schema: { type: "object", properties: { path: { type: "string", description: "PDF 文件路径" } }, required: ["path"] } }, ]; async function executeTool(name, input) { if (name === "read_pdf") return await extractTextFromPdf(input.path); if (name === "search_pdf") return await searchPdfs(input.directory, input.keyword); if (name === "list_pdfs") return await listPdfFiles(input.path); throw new Error(`Unknown tool: ${name}`); }
这种做法的特点是Agent 循环、工具分派、PDF 解析全跑在一个程序的内存空间里,不需要跨进程通信,也不需要额外部署。你只需要 LLM SDK 和一个 PDF 解析库。但这意味着工具和你的应用紧耦合: executeTool() 里硬编码了每个工具的分派逻辑,只有这个应用能用这些 PDF 工具。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。