从零搞懂 AI Agent:LLM + Tool + Reasoning 实战全解析

前言
2025-2026 年,AI Agent 工程师已经取代传统软件工程师,成为行业薪资天花板最高的岗位之一。你可能每天都在用 Agent 产品——Cursor、Claude Code、豆包、飞书 CLI、Workbuddy,它们不只是聊天机器人,而是能读文件、搜网络、写代码、操控浏览器的智能体。
但 Agent 到底是什么?它的核心机制是怎样的?本文带你用可运行的代码,一步步拆解 Agent 的三大核心概念:
- LLM(大模型) — Agent 的大脑,负责推理与生成
- Tool(工具) — 让 LLM 突破纯文本限制,对接真实世界
- Reasoning(推理) — LLM 的思考过程,决定行动的准确性
读完你会理解:为什么说「一个 Agent 有多强,取决于它用了什么大脑、装了什么工具、拿到了什么信息」。

一、环境准备:让代码跑起来

我们用 DeepSeek 的 API 来做演示(兼容 OpenAI SDK,成本低、效果好)。首先初始化项目:
mkdir reason-demo && cd reason-demo
npm init -y
npm install openai dotenv
配置环境变量 .env:
DEEPSEEK_API_KEY=你的API密钥
DEEPSEEK_API_BASE_URL=https://api.deepseek.com
DEEPSEEK_API_MODEL=deepseek-v4-flash
封装 LLM 客户端 client.mjs:
import { OpenAI } from 'openai';
import dotenv from 'dotenv';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
const __dirname = dirname(fileURLToPath(import.meta.url));
dotenv.config({ path: join(__dirname, '.env') });
// LLM Client 对象——所有 API 调用的入口
const client = new OpenAI({
apiKey: process.env.DEEPSEEK_API_KEY,
baseURL: process.env.DEEPSEEK_API_BASE_URL,
});
export default client;
这里的 client 就是后续所有操作的入口。DeepSeek 兼容 OpenAI 的 SDK 格式,所以直接用 openai 这个 npm 包即可——这对于后面理解 LLM 如何使用 Tool 非常关键,因为 Tool Calling 正是 OpenAI 定义的标准协议。
二、LLM:Agent 的大脑
2.1 LLM 的能力边界
大语言模型(Large Language Model,简称 LLM)本质上只做两件事:
- 推理(Reasoning):理解问题,拆解任务,决策下一步做什么
- 生成(Generation):产出文本内容
它天然无法与外部世界交互——不能查数据库、不能调 API、不能操作文件系统。这是 LLM 的核心局限。
先看一个最简单的调用 completion.mjs:
import client from './client.mjs';
export async function getCompletion(prompt) {
const response = await client.chat.completions.create({
model: process.env.DEEPSEEK_API_MODEL,
messages: [{ role: 'user', content: prompt }],
});
return response.choices[0].message.content;
}
这种最基础的调用方式,LLM 只能用训练数据中的知识来回答。如果问它「青岛啤酒今天的收盘价是多少」,它只能胡编或者拒绝——因为它没有实时数据,也无法自己上网搜索。
2.2 问题的关键
LLM 只负责推理和生成。真正的行动能力,来自 Tool 的调用。
这就是 Agent 的核心设计思路:LLM 做决策,Tool 做执行。
三、Tool:给 LLM 装上手脚
3.1 什么是 Tool?
Tool(工具)是 OpenAI 定义的一套标准协议,允许 LLM 在推理过程中主动调用外部函数。它的本质是:
LLM 推理 → 决定调用哪个工具 → 传入参数 → 执行函数 → 把结果还给 LLM → LLM 继续推理/生成最终答案
这个过程叫 Function Calling(函数调用),是 Agent 能力的基础。
3.2 定义 Tool
以查询股票收盘价为例,我们需要做三件事:声明工具 → 实现函数 → 发起调用。
第一步:声明有哪些 Tool
const tools = [
{
type: 'function', // Tool 的专用格式——就是函数
function: {
name: 'get_closing_price',
// ⚠️ 核心!LLM 通过 description 理解 Tool 的功能
// description 写得越具体,LLM 调用工具越准确
description: '获取指定股票的收盘价',
parameters: {
type: 'object',
properties: {
name: {
type: 'string',
description: '股票名称', // LLM 通过 NLP 理解这个参数的含义
},
},
required: ['name'],
},
},
},
];
这里有几个关键点:
type: 'function':OpenAI 定义的工具标准格式,LLM 靠这个字段识别它是可调用的函数description:这是 LLM 能否正确使用 Tool 的核心。它必须详细、具体,LLM 通过自然语言理解这段话来判断什么情况下该用这个工具parameters:用 JSON Schema 描述参数,LLM 通过properties.description(NLP)理解每个参数的含义required:标记必填参数,LLM 会确保调用时带上
第二步:实现具体函数
function get_closing_price(name) {
if (name === '青岛啤酒') return '67.92';
if (name === '贵州茅台') return '1488.21';
return '未找到股票';
}
在实际项目中,这个函数可以对接数据库、第三方 API、RPC 调用等任何外部系统。
第三步:发起带 Tool 的对话
const send_message = async (messages) => {
return await client.chat.completions.create({
model: 'deepseek-v4-flash',
messages,
tools, // 告诉 LLM 有哪些工具可用
tool_choice: 'auto', // LLM 自行判断是否调用工具
});
};
const main = async () => {
let messages = [{ role: 'user', content: '青岛啤酒的收盘价是多少?' }];
const response = await send_message(messages);
const message = response.choices[0].message;
console.log(message);
};
main();
3.3 LLM 返回了什么?
当你问「青岛啤酒的收盘价是多少」时,LLM 的返回内容大概是这样的:
{
"role": "assistant",
"content": null,
"tool_calls": [
{
"id": "call_xxxxx",
"type": "function",
"function": {
"name": "get_closing_price",
"arguments": "{\"name\": \"青岛啤酒\"}"
}
}
]
}
注意两个关键细节:
content为 null:LLM 没有生成文本回复,而是选择调用工具——它知道这个问题自己回答不了tool_calls:LLM 精确地提取了用户问题中的股票名称,并填入arguments——这说明 tool 的description和参数的description写得好不好,直接决定了 LLM 能不能准确使用工具
3.4 完整的 Tool Calling 流程
实际项目中,Tool Calling 是一个多轮对话循环:
User: "青岛啤酒收盘价?"
→ LLM: 我需要调 get_closing_price("青岛啤酒")
→ 程序执行 get_closing_price → 返回 "67.92"
→ 程序把结果追加到 messages,再次发给 LLM
→ LLM: "青岛啤酒的收盘价是 67.92 元"
这就是为什么 Agent 能自动化完成任务——LLM 负责「想」,Tool 负责「做」,循环往复,直到任务完成。Cursor 写代码、Claude Code 操作文件、飞书 CLI 发消息,底层都是这套机制。
3.5 Tool 设计的核心原则
从上面的例子可以总结出几条经验:
| 原则 | 说明 |
|---|---|
| description 要具体 | LLM 通过自然语言理解 tool 功能,模糊描述 = 错误调用 |
| 参数描述要像写文档 | properties.description 是给 LLM 看的,要用自然语言写清楚 |
| required 标记完整 | 必填参数不标记,LLM 可能漏传 |
| 一个 Tool 只做一件事 | 职责单一,LLM 更容易正确选择 |
四、Reasoning:让 LLM 把思考过程说出来
4.1 什么是 Reasoning?
Reasoning(推理)是 DeepSeek 等模型提供的深度推理模式。开启后,LLM 在生成最终答案前,会先输出一段内部思考过程(类似人类的「让我想想」)。
这对 Agent 开发非常关键,因为:
- 可观测性:你能看到 LLM 为什么做了某个决策,方便调试和优化
- 准确性提升:深度推理模式下,LLM 会花更多「算力」在思考上,复杂问题的准确率显著提高
- 人机协作:思考过程暴露后,人可以介入纠正错误的推理方向
4.2 代码实战
新建 reasoning.mjs:
import client from './client.mjs';
const main = async () => {
const res = await client.chat.completions.create({
model: 'deepseek-v4-flash',
reasoning_effort: 'high', // 🔑 开启深度推理模式
messages: [
{
role: 'system',
content: '你是一个足球领域的专家,请尽量帮我回答与足球相关的问题',
},
{ role: 'user', content: 'C罗是哪个国家的足球运动员?' },
{ role: 'assistant', content: 'C罗是葡萄牙的足球运动员' },
{ role: 'user', content: '内马尔呢?' },
],
});
console.log('思考过程:');
console.log(res.choices[0].message.reasoning_content); // 👈 推理过程
console.log('\n最终答案:');
console.log(res.choices[0].message.content); // 👈 最终答案
};
main();
4.3 关键参数解析
| 参数 | 含义 |
|---|---|
reasoning_effort: 'high' |
推理强度。可选 low / medium / high,越高 LLM 思考越深、耗时越长、效果越好 |
reasoning_content |
LLM 的思考过程——它如何理解问题、调用了什么知识、排除了哪些可能性 |
content |
最终输出给用户的答案 |
4.4 多轮对话中的 Context 传递
注意 messages 的结构——这是一个多轮对话列表:
messages: [
{ role: 'system', content: '你是一个足球领域的专家...' }, // 系统人设
{ role: 'user', content: 'C罗是哪个国家的?' }, // 用户第一问
{ role: 'assistant', content: 'C罗是葡萄牙的...' }, // LLM 第一答
{ role: 'user', content: '内马尔呢?' }, // 用户第二问(省略主语)
]
这里体现了 LLM 的一个重要能力——上下文理解。用户只说了「内马尔呢」,但 LLM 结合上文知道这是在问「内马尔是哪个国家的足球运动员」。Agent 的多轮推理同样依赖这个机制:每次 Tool Calling 的结果都要追加到 messages 列表中,LLM 才能基于完整上下文做出正确决策。
4.5 Reasoning 在 Agent 中的价值
在 Agent 场景下,Reasoning 不只是「让 LLM 说出思考过程」这么简单:
- 流式输出:
reasoning_content可以流式返回,用户能实时看到 Agent 在「想什么」 - 计划可见:LLM 会先规划再行动——「我需要先查 A,再根据 A 的结果决定是否查 B」
- 纠错机制:如果推理方向偏了,开发者可以在中间介入,追加 system message 纠正方向
五、Agent 全景图:把三者串起来
现在回到最核心的问题——Agent 到底是什么?
┌─────────────────────────────────────────────────┐
│ Agent │
│ │
│ ┌──────────┐ ┌──────────────┐ │
│ │ LLM │───▶│ Reasoning │ │
│ │ (大脑) │ │ (思考过程) │ │
│ └──────────┘ └──────────────┘ │
│ │ │
│ │ 决策:该调哪个工具? │
│ ▼ │
│ ┌──────────┐ │
│ │ Tool │───▶ 外部系统(API/DB/文件/浏览器) │
│ │ (手脚) │ │
│ └──────────┘ │
│ │ │
│ │ 返回结果 │
│ ▼ │
│ ┌──────────┐ │
│ │ Messages │───▶ 多轮对话上下文 │
│ │ (记忆) │ │
│ └──────────┘ │
│ │ │
│ └──▶ 循环,直到任务完成 │
└─────────────────────────────────────────────────┘
一句话总结:
Agent = LLM(大脑) + Tool(手脚) + Messages(记忆) + Reasoning(思考过程)
- LLM 负责推理和决策——「这个问题我回答不了,需要查数据」
- Tool 负责执行——真正去查数据库、调 API、写文件
- Messages 负责上下文——多轮对话和多次工具调用,都靠 messages 串联
- Reasoning 负责可解释性——让开发者知道 Agent 为什么这么做
你日常使用的 Cursor、Claude Code、豆包、飞书 CLI,本质上都是这套架构的实例化,只是 Tool 不同、LLM 不同、交互界面不同而已。
六、总结
| 概念 | 角色 | 一句话理解 |
|---|---|---|
| LLM | Agent 的大脑 | 只负责推理和生成,不直接操作世界 |
| Tool | Agent 的手脚 | 补齐 LLM 的行动短板,对接外部系统 |
| Reasoning | Agent 的思考过程 | 让决策过程透明化,提升准确性和可控性 |
| Messages | Agent 的记忆 | 多轮对话和工具调用结果都存在这里 |
一个 Agent 有多强,取决于三个因素:用了什么大脑(LLM)、装了什么工具(Tool)、拿到了什么信息(Context)。
下一步,建议你动手跑一遍代码,然后尝试:
- 添加更多 Tool(天气查询、网页搜索、文件读写)
- 实现完整的多轮 Tool Calling 循环(处理
tool_calls→ 执行函数 → 追加到 messages → 再次请求 LLM) - 对比
reasoning_effort: 'low'vs'high'的推理差异
更多推荐



所有评论(0)