从零吃透 AI 智能体 Agent:架构原理 + LangChain 工具实战 + Promise 异步完整复习手册
前言
很多初学者以为 Agent 就是简单调用大模型接口,这是典型误区。原生 LLM 本身存在大量天然缺陷:无长期记忆、无法操作本地文件、不能联网获取实时信息、读不到企业私有文档、无法自动执行复杂任务。而 AI Agent 就是一套增强系统,给 LLM 补齐记忆、工具、知识库、外部能力,让模型拥有自主规划、自主执行任务的能力。本文结合理论笔记、完整可运行 JS 代码、Promise 异步底层知识整理,适合日常复习、面试复盘。
一、原生 LLM 五大核心缺陷(Agent 各模块对应解决方案)
原生大模型属于无状态(stateless)服务,单次对话结束后不会留存任何信息,同时没有访问外部资源的权限,对应 5 类问题与配套模块:
- 无法长期记忆对话历史问题:隔一段时间再提问,模型忘记之前聊天内容解决方案:Memory 记忆模块,搭配数据库 / Redis / 前端存储持久化对话
- 不能操作本地文件、执行命令、访问网页问题:模型只能输出文字思路,无法真实落地操作解决方案:Tool Use 工具调用模块,封装文件读写、命令行、接口等函数
- 无法读取企业内部私有文档问题:训练数据不含公司内部资料,无访问权限解决方案:RAG 检索增强生成,向量库存储私有文档,查询时召回相关内容
- **没有实时最新资讯(世界杯、实时新闻)**问题:模型训练数据存在时间截止,无法获取实时动态解决方案:MCP 第三方工具标准协议,对接实时数据接口
- **复杂自动化任务(自动做 PPT、分析股市自动交易)**问题:单轮对话无法完成多步骤连锁任务解决方案:Skills 技能蒸馏,封装成套自动化流程
Agent 完整公式
Agent = LLM大模型 + Memory记忆 + Tool工具调用 + RAG知识库 + MCP第三方协议 + Skills自动化技能
行业落地产品举例
- 代码类 Agent:Claude Code、Codex、代码智能体
- 通用自动化 Agent:Manus、小龙虾智能体
二、Agent 标准完整工作流程
- 用户输入自然语言复杂任务,传递给 Agent;
- LLM 执行 Planning+Reasoning 规划推理,自主拆解任务:判断是否读取历史记忆、是否调用工具、是否检索私有知识库;
- 若需要 RAG:检索向量文档,把检索内容注入 Prompt 模板;
- 下发工具调用指令:携带唯一 id、工具名称、入参;
- 后端执行异步工具函数(读文件、命令行、接口请求);
- 工具执行结果携带 id 回填会话上下文 messages;
- LLM 匹配工具请求与工具返回结果,整合全部信息生成最终回答返回用户。
核心关键点:工具是异步操作,依靠唯一 id 区分多工具调用,防止上下文错乱。
三、Agent 开发技术栈与框架
技术选型
后端:Node.js + NestJSLLM 开发框架:
- LangChain:单智能体开发主流框架,兼容全球所有大模型;
- LangGraph:多智能体协同开发框架。
商业落地价值
结合后端工程化 Harness Engineering,将 AI 能力落地为商业化产品,简称 FDE 全栈 AI 开发。
四、LangChain 核心模块详解(附完整可运行代码)
1. LLM 统一兼容层
LangChain 封装统一调用标准,一套代码无缝切换 OpenAI、DeepSeek、Claude 等模型,依赖包@langchain/openai。基础模型调用示例:
js
运行
import 'dotenv/config';
import { ChatOpenAI } from '@langchain/openai';
// 初始化大模型
const model = new ChatOpenAI({
modelName: 'deepseek-v4-flash',
apiKey: process.env.DEEPSEEK_API_KEY,
temperature: 0, // 0代表输出稳定,无随机发散
configuration: {
baseURL: 'https://api.deepseek.com/v1',
},
});
// 基础问答调用
const response = await model.invoke('谢鲁立为什么比吴贤宏帅');
console.log(response.content);
2. Tool 工具调用核心机制(Agent 核心能力)
工具分为两部分:
- 异步执行函数:真实业务逻辑(读文件、执行命令);
- 工具描述对象:给 LLM 看的规则,包含
name、description、schema参数约束。
schema 约束作用
基于 zod 做参数强校验,规定参数类型、含义,LLM 调用工具时必须严格遵守参数规范,否则调用失败。
LLM 工具调用逻辑
当模型判断需要使用工具时,不会直接生成回答,而是返回tool_calls数组,包含:唯一 id、工具名称、入参;后端执行异步工具函数,执行完成后携带相同 id 把结果封装为ToolMessage,追加到会话消息列表,让 LLM 匹配请求与返回数据。
完整文件读取 Tool 实战代码
js
运行
import 'dotenv/config';
import { ChatOpenAI } from '@langchain/openai';
import { tool } from '@langchain/core/tools';
import {
HumanMessage,
SystemMessage,
ToolMessage,
AIMessage
} from '@langchain/core/messages';
import fs from 'node:fs/promises';
import { z } from 'zod'; // 参数类型约束库
// 初始化大模型
const model = new ChatOpenAI({
modelName: 'deepseek-v4-flash',
apiKey: process.env.DEEPSEEK_API_KEY,
temperature: 0,
configuration: {
baseURL: 'https://api.deepseek.com/v1',
},
});
// 定义读取文件工具
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: `用此工具读取本地文件,用户要求查看/解释代码时调用;支持相对、绝对文件路径`,
// zod参数约束:规定入参格式
schema: z.object({
filePath: z.string().describe('待读取的文件路径')
})
}
)
// 注册全部工具
const tools = [readFileTool];
// 给模型绑定工具能力
const modelWithTools = model.bindTools(tools);
// 会话上下文消息列表
const messages = [
new SystemMessage(`
你是代码助手,可调用read_file读取本地文件分析代码
执行流程:
1. 用户要求读取文件,立刻调用read_file工具
2. 等待工具返回文件原文
3. 基于原文完成代码解释
`),
new HumanMessage('请读取 tool.mjs 文件内容并解释代码'),
];
// 发起请求,模型返回工具调用指令
let response = await modelWithTools.invoke(messages);
// 将模型响应存入上下文,用于后续拼接工具结果
messages.push(response);
五、工具异步底层:Promise 完整知识点(面试高频)
工具读写文件、请求接口全是异步操作,JS 依靠 Promise 处理异步,搭配async/await实现异步转同步。
1. Promise 三种固定状态(单向流转,仅变更一次)
- pending:等待中,任务未完成;
- fulfilled:成功,调用
resolve()切换; - rejected:失败,调用
reject()切换。
状态只能单向切换:pending → fulfilled /pending → rejected,切换后永久固定,无法回退。
2. resolve 与 reject 作用
- resolve (数据):任务正常完成,向外抛出业务结果,只能传 1 个有效参数;多值需要封装数组 / 对象;
- reject (错误):任务异常失败,抛出错误信息,通过 try/catch 捕获。
3. 基础 Promise 模拟延时任务(串行执行)
js
运行
// 封装可复用异步函数
function getWeather() {
return new Promise((resolve) => {
setTimeout(() => {
resolve({ temp: 38, conditions: 'Sunny with Clouds' })
}, 2000)
})
}
function getTweets() {
return new Promise((resolve) => {
setTimeout(() => {
resolve(['I like cake', 'BBQ is good too!'])
}, 500)
})
}
// await串行:排队执行,总耗时叠加 2000+500=2500ms
const main = async () => {
console.time("my-operation");
const weatherData = await getWeather();
const tweetsData = await getTweets();
console.timeEnd("my-operation");
}
main();
4. Promise.all 并行执行(工具多任务并发核心)
互不依赖的异步任务同时启动,总耗时取最长任务时长,大幅提升执行效率;约束:数组内任意一个 Promise 触发 reject,整体直接报错终止。
js
运行
const main = async () => {
console.time("my-operation");
// 并行启动两个任务,同时倒计时
const [weatherData, tweetsData] = await Promise.all([getWeather(), getTweets()]);
console.timeEnd("my-operation"); // 总耗时≈2000ms
}
main();
5. 异步变同步:async + await
Promise 本身不会阻塞代码,属于异步;在 async 函数内使用 await,会强制暂停代码,等待异步任务完成拿到结果后再执行下一行,该特性称为异步转同步,是 Agent 工具调用必备语法,保证任务执行顺序不乱。
6. 错误捕获标准写法
js
运行
function errorDemo() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error("文件不存在,读取失败"))
}, 1000)
})
}
async function run() {
try {
const res = await errorDemo();
} catch (err) {
console.log("任务异常:", err.message)
}
}
run()
六、实战案例:创建 React+Vite TodoList 需要哪些 Tool
用户需求:让 Agent 自动搭建 react+vite todolist 项目,拆解规划三步并匹配对应工具:
- 项目初始化工具:调用 CLI 命令行工具执行
npm create vite; - 文件写入工具:fs 文件读写工具,自动生成页面代码;
- 运行启动工具:命令行工具执行启动脚本;配套要求:选用代码能力强的 LLM(DeepSeek/Claude),自主规划分步执行。
极简 Agent 架构:LLM + Tool(文件读写 + 命令行)
七、复习核心总结
- Agent 本质:给无状态 LLM 拓展记忆、工具、知识库、实时数据能力,让模型自主完成多步骤复杂任务;
- 核心公式:
Agent = LLM + Memory + Tool + RAG + MCP + Skills; - Tool 调用核心:通过 zod 做参数约束,依靠唯一 id 绑定工具请求与返回结果,工具全部为 Promise 异步函数;
- 异步核心:Promise 管理耗时操作,串行 await 保证任务顺序,Promise.all 并行提速;
- LangChain 价值:统一多模型调用标准,封装工具、消息、会话上下文,降低 Agent 开发成本;
- 落地流程:用户输入→LLM 推理规划→工具异步执行→结果回填上下文→整合输出回答。