Agent 智能体:从概念到实践 —— 从概念到实践:如何打造一个真正能干活的 AI 助手 思维链 大模型 观察 思考 行动》 从概念到实践 —— 如何打造一个真正能干活的 AI 助手
尽管大语言模型(LLM)已经能在广泛问题上提供令人惊叹的答案,但在需要记忆过往对话、访问外部数据或执行实际操作时,其结构性短板便暴露无遗。Agent智能体通过整合记忆模块、工具调用能力与知识检索机制,将LLM从纯粹的“对话者”重塑为能够主动执行的“行动者”。

这些局限并非源于模型不够聪明,而是大模型固有的结构性短板所致。
第一,LLM 缺乏持久记忆。 每次交互中模型都将对话视为全新开端,无法保留上周讨论的项目背景。要让模型记住上下文,必须引入记忆模块,将历史对话存入数据库或本地存储,并在每次请求时将相关记录一起提交给模型。
第二,LLM 只能生成文本,无法执行具体操作。 当要求它访问网页、读写文件或调用API时,模型只能提供思路却无法亲自操作。要赋予模型执行能力,需要配备工具调用功能,使其能够调用外部函数、发送网络请求或执行系统命令。
第三,LLM 的知识存在时效性限制。 模型训练完成后,其知识便固化于训练数据的截止时间点。最新新闻、实时股价或内部私有文档均无法触及。这需要借助RAG接入外部知识库,并利用MCP标准化第三方工具的接入方式。
第四,LLM 缺乏领域专精能力。 制作PPT、分析股市并执行交易、实施多步骤工作流等任务,需要将通用能力蒸馏为特定领域的专业技能。
Agent正是针对上述问题,为LLM附加记忆模块、工具调用能力、RAG知识检索、MCP协议支持与技能体系后的产物。这并非简单的叠加,而是一次质的飞跃——LLM从“能聊天的模型”转变为“能干活的智能体”。
Agent 的工作原理:从接收到完成任务的全流程
当用户以提示词形式向Agent提出复杂任务时,系统内部会经历一套精密的协作流程:
-
规划与推理:LLM首先解析用户意图,将任务拆解为可执行的子步骤。例如针对“分析项目代码质量”的请求,Agent会规划出列出文件结构、读取关键文件、分析代码模式、生成报告等步骤。
-
记忆检索:Agent检查是否需要加载历史记忆。若用户曾讨论过项目背景,系统将从记忆模块中提取相关上下文,避免重复说明。
-
工具调用:Agent判断所需工具并按步骤执行。读取文件、搜索代码、运行测试等操作均有明确的输入参数和返回结果,Agent根据上一步结果决定下一步行动。
-
知识增强:当任务涉及内部私有知识时,Agent从向量数据库中检索相关文档片段,通过提示词模板将检索结果注入上下文,使模型获得超出训练数据的知识。
-
响应与反馈:Agent汇总所有工具执行结果与推理过程,生成最终回答,完成用户任务。
整个流程的核心在于:LLM 作为大脑,工具作为双手,记忆作为经验,RAG 作为外部知识库——四者缺一不可。
LangChain:Agent 开发的“万能胶水”
在Agent开发领域,LangChain是最成熟的开源框架之一。其核心价值在于统一与兼容——面对数十家大模型厂商各异的API格式,LangChain提供一层抽象,使开发者能用同一套代码调用DeepSeek、OpenAI、Anthropic等不同模型。
我们的实践中采用如下技术栈:
- 后端框架:NestJS(Node.js企业级框架)
- Agent 框架:LangChain.js(单智能体)与 LangGraph(多智能体协作)
- 工具生态:MCP / RAG / Skills
以下通过一个真实代码示例展示LangChain如何赋予LLM工具调用能力。
第一步:绑定模型
复制代码import { ChatOpenAI } from '@langchain/openai';const model = new ChatOpenAI({
modelName: 'deepseek-v4-flash',
apiKey: process.env.DEEPSEEK_API_KEY,
temperature: 0,
configuration: {
baseURL: 'https://api.deepseek.com/v1',
},
});
LangChain的ChatOpenAI兼容OpenAI接口规范,只需修改baseURL与modelName,即可无缝切换至DeepSeek等国产模型。这种按需加载、即插即用的设计使团队能够灵活选择性价比最高的模型,而不被单一厂商锁定。
第二步:定义工具
复制代码import { tool } from '@langchain/core/tools';
import { z } from 'zod';const readFileTool = tool(
async ({ filePath }) => {
const content = await fs.readFile(filePath, 'utf-8');
console.log(`[工具调用] read_file(${filePath}) 成功读取 ${content.length} 字节`);
return content;
},
{
name: 'read_file',
description: '用此工具来读取文件内容,当用户要求读取文件、查看代码、分析文件内容时,调用此工具。',
schema: z.object({
filePath: z.string().describe('要读取的文件路径'),
}),
}
);
一个Tool由两大部分组成:
- 功能函数(异步处理函数):实际执行操作的逻辑,此处为读取文件内容并返回。
- 描述对象:包含
name(工具名称)、description(详细功能说明,覆盖使用场景与参数需求)和schema(参数约束)。schema使用Zod定义,确保LLM调用工具时传入的参数类型与格式完全正确。
这里有一个容易被忽视但至关重要的设计细节:工具执行中需要时刻反馈执行状态。Agent任务可能复杂耗时,若用户长时间看不到反馈,会误以为程序卡死而退出。每执行一步便输出日志,是Agent开发的基本素养。
第三步:注册工具并创建 Agent
复制代码const tools = [readFileTool];
const modelWithTools = model.bindTools(tools);const messages = [
new SystemMessage('你是一个代码助手,可以使用工具读取文件并解释代码。'),
new HumanMessage('请读取 tool.mjs 文件内容并解释代码'),
];let response = await modelWithTools.invoke(messages);
messages.push(response);
LangChain通过bindTools方法将工具注册到模型。当用户提出“读取文件并解释代码”的请求时,模型会:
- 识别出需要调用
read_file工具 - 生成结构化的
tool_calls数组,包含工具ID、名称与参数 - 暂停自身文本生成,等待工具返回结果
- 将工具返回结果关联至对应的
tool_call_id,拼接到历史会话中 - 基于完整上下文(用户问题与工具返回内容)生成最终回答
这一过程十分精妙:LLM具备“自知之明”——当判断需要调用工具时,它不会强行编造内容,而是生成tool_calls数组告知系统调用需求。工具异步执行完毕,结果通过id关联回对应调用,整个任务上下文完整保存在历史会话列表中。LLM凭借自然语言理解实现精确的函数调用编排。
性能优化:Promise.all 并行执行
当Agent需要调用多个工具时,若采用串行方式(先读文件A,再读文件B,再读文件C),总耗时为所有操作时间之和。这在复杂任务中可能导致用户等待数十秒甚至数分钟。
解决方案是利用JavaScript的Promise机制实现并行执行:
复制代码const [weatherData, tweetsData] = await Promise.all([
getWeather(), // 耗时 2000ms
getTweets(), // 耗时 500ms
]);
// 总耗时 ≈ 2000ms(取最长的那个),而不是 2500ms
Promise是ES6引入的异步编程核心,具有三种状态:
- Pending(等待中):异步操作尚未完成
- Fulfilled(已成功):操作成功完成,状态从Pending变为Fulfilled
- Rejected(已拒绝):操作失败,状态从Pending变为Rejected
关键特性在于:状态只能从Pending切换至Fulfilled或Rejected之一,且改变后不可逆转,这保证了异步操作的确定性。
Promise.all()接收一个Promise数组,并行启动所有异步任务,等待全部完成返回结果数组,结果顺序与输入数组严格一致。配合async/await(ES8语法),异步代码读起来如同同步代码般清晰。
在Agent场景中,当LLM判断多个工具调用无依赖关系时(例如同时读取三个不相关配置文件),应使用Promise.all并行执行,将总耗时从“三个操作之和”降至“最慢操作”,这是打造高性能Agent的关键技巧。
从 Demo 到产品:Agent 开发的完整图景
以一个具体实例说明:让Agent“创建一个React + Vite的TodoList应用”。任务会被LLM规划为三步:
- 用Vite脚手架创建项目 → 调用CLI工具
- 编写TodoList组件代码 → 调用文件写入工具
- 启动开发服务器验证 → 再次调用CLI工具
每一步均为工具调用,每一步结果影响下一步决策。这便是手写简化版Claude Code的核心原理——LLM与文件系统工具、命令行工具的结合。
而LangGraph更进一步,支持多智能体协作:可以分配一个“架构师Agent”负责规划设计,一个“编码Agent”负责实现,一个“审查Agent”负责检查代码质量——它们通过消息传递协作,各司其职。
结语:Agent 其实不复杂
拆解来看,Agent的每个组成部分都不复杂。LLM本身具备思考与规划能力,为其配备工具便能执行操作,增添记忆即可保留关键信息,接入RAG就能查询内部知识库。将这些组件整合——一个知晓内部知识、能够思考规划、能够动手执行的大模型——便构成了Agent。
真正的挑战不在于理解概念,而在于工程落地。如何设计稳定的工具接口?如何处理工具调用异常?如何在并发与串行间做出最优调度?如何使Agent行为可预测、可调试?
这正是智能体产品开发的使命:通过扎实的工程实践让AI技术落地,实现其商业价值。从第一行演示代码到支撑千万用户的智能体产品,这条路才刚刚开启。