LangChain+LangGraph从零搭建AI智能体,踩坑完整教程 文章目录前言第一章项目初始化或者叫npm install地狱第二章Agent到底是个啥第三章定义工具或者叫给LLM装上义肢第四章创建Agent把大脑和义肢缝在一起第五章流式输出或者叫别让用户干瞪眼第六章多轮对话或者叫给金鱼装上硬盘第七章Extended Thinking或者叫偷看AI的草稿纸第八章回顾与展望或者叫终于写完了P.S. 目前国内还是很缺AI人才的希望更多人能真正加入到AI行业共同促进行业进步增强我国的AI竞争力。想要系统学习AI知识的朋友可以看看我精心打磨的教程 http://blog.csdn.net/jiangjunshow教程通俗易懂高中生都能看懂还有各种段子风趣幽默从深度学习基础原理到各领域实战应用都有讲解我22年的AI积累全在里面了。注意教程仅限真正想入门AI的朋友否则看看零散的博文就够了。前言2026年你要是没写过AI Agent出门都不好意思跟同行打招呼。就像2018年没买过比特币2020年没炒过NFT2022年没玩过AIGC——咱们程序员圈子的焦虑永远比技术更新快三个版本。所以今天咱们就来手搓一个Agent。不是那种调个API就敢说自己是AI工程师的Hello World而是一个真正能动手、能思考、能记仇——不对能记上下文——的完整Agent。全程TypeScript全程LangChain全程踩坑。第一章项目初始化或者叫npm install地狱搭建项目的第一步永远是创建文件夹。我给它起名叫lingshi灵感来源于我写完这个项目后可能剩下的头发数量——零星的几根简称零拾。然后安装依赖。看到这一串包名了吗langchain、langchain/anthropic、langchain/core、langchain/langgraph、deepagents、zod、dotenv……这阵仗比我女朋友的购物车还长。最离谱的是那个叫deepagents的包听起来像是某种深海特工组织实际上它只是帮我们少写几行样板代码的贴心小棉袄。冷知识pnpm的安装速度比npm快不是因为技术更先进而是因为npm在下载依赖的时候会顺便帮你把前世今生的所有版本都下载一遍生怕你错过任何一个历史时刻。tsconfig.json的配置也有讲究。module要设成ESNextmoduleResolution要设成bundlernoEmit要设成true。翻译成人类语言就是“我用tsx直接跑tsc你别多管闲事编译产物这玩意生出来也是占硬盘空间的电子垃圾。”环境变量文件.env里藏着一个骚操作ANTHROPIC_BASE_URL指向一个代理服务器底层实际跑的是qwen3.7-plus。这就好比你去米其林餐厅点餐后厨实际给你炒的是楼下沙县小吃——但摆盘用的是米其林标准所以吃起来感觉特别高级。第二章Agent到底是个啥很多人搞不清Agent和普通LLM的区别。我打个比方普通LLM就是你那个只会动嘴的室友。你跟他说帮我算一下128乘47他回你根据我的训练数据128和47都是正整数乘法是一种基本的算术运算……说了八百字答案没给一个。Agent不一样。Agent是你那个不仅会动嘴还会动手翻计算器的室友。你问他128乘47他二话不说掏出手机打开计算器啪啪啪按完告诉你6016。如果算错了他甚至还会再按一遍——这就是Agent的核心竞争力有手。Agent的本质公式Agent LLM 工具 一个死循环。LLM负责思考我要不要用工具工具负责执行我真的去做了循环负责保证没做完就继续干直到LLM说收工为止。这个循环的逻辑大概是这样的LLM看着用户的提问陷入沉思——这题我会吗不会。那我有工具吗有。用哪个计算器。参数是什么a128, b47, operationmultiply。然后工具执行完把结果6016喂回去LLM一看“哦原来答案是6016那我包装一下用人类语言说出来。”整个过程就像你让实习生去打印文件。你不会自己去打印你告诉实习生去打印三份合同实习生跑到打印机前操作拿回来给你。你LLM是老板实习生工具是执行者打印机外部系统是最终干活的。唯一不同的是LLM这个老板不会给实习生发工资也不会在实习生做错的时候骂它——因为LLM骂了也没用工具听不懂人话它只认JSON参数。第三章定义工具或者叫给LLM装上义肢工具是Agent的手。没有工具的Agent就像没有手的奥特曼——光会摆pose打不了怪兽。咱们给Agent装两只手一只叫calculator负责算术一只叫get_current_time负责看表。定义工具要用Zod写schema。Zod这玩意本质上就是一个参数说明书生成器。你写z.number().describe(‘第一个数字’)框架就会把它翻译成JSON Schema发给LLM。LLM看到这份说明书就知道“哦这个参数得是数字而且它是第一个数字。”重要警告describe()里的描述一定要写清楚。如果你写z.number().describe(‘一个数字’)LLM就会一脸懵逼什么数字干嘛用的是我生日吗最后它可能会把温度当参数传过去或者把股价当参数传过去——总之LLM的想象力比你丰富得多你得把它锁死在正确的理解轨道上。计算器工具的代码看起来有点长但核心逻辑就两行switch判断operation然后return结果。除法的时候加了个防零判断因为除以零在数学上是不被允许的在编程上会让你的程序直接原地爆炸在情感上会让你的用户直接原地爆炸。获取当前时间的工具更有意思。它的schema是z.object({})一个空对象。这就好比你去餐厅点餐服务员问你要什么你说随便——但这里的随便是字面意思因为时间工具真的不需要任何参数。LLM看到空schema就知道“这个工具我直接调用就行不用传参比我的前任还省心。”第四章创建Agent把大脑和义肢缝在一起创建Agent用的是createDeepAgent。这个函数名听起来很深沉像是某个哲学家的笔名实际上它只是LangGraph的一个封装。LangGraph是LangChain的图结构引擎专门用来管理Agent的决策流程——“先干什么再干什么如果出错怎么办如果成功又怎么办”。配置ChatModel的时候有两个骚操作。第一个是streaming: true开启流式输出。这很重要因为如果你用invoke用户发完问题后要等好几秒才能看到回复。这几秒里用户在干嘛在盯着空白屏幕发呆在怀疑自己的网络是不是断了在思考人生是不是就是这么虚无。而streaming能让用户看到AI在打字——虽然它实际上是在吐token但视觉效果上就是它在思考它在组织语言用户的心理体验从焦虑等待变成了沉浸式观看。streaming的心理学原理人类对渐进式反馈的容忍度远高于一次性结果。这就是为什么你等外卖的时候App显示骑手正在赶往商家比直接显示预计30分钟后送达让你更安心——虽然实际上都是30分钟但前者给了你事情正在推进的幻觉。第二个骚操作是thinking参数。type: ‘enabled’, budget_tokens: 5000。这意思是模型啊你在给出最终答案之前可以先花5000个token进行内部推理。就像考试的时候老师允许你先打草稿。只不过这个草稿是透明的用户能看到——当然你也可以选择不看但既然都开了为什么不看呢看AI思考的过程比看AI给出答案的过程有趣多了。Agent的四个参数各司其职model是大脑tools是双手systemPrompt是入职培训手册checkpointer是记忆存储器。MemorySaver是内存版的记忆存储特点是快但重启就丢。生产环境建议换成PostgresSaver虽然慢点但至少你的Agent不会一觉醒来忘记自己是谁——这剧情太科幻了不适合用在生产环境。第五章流式输出或者叫别让用户干瞪眼流式输出是Agent体验的分水岭。没有流式的Agent就像没有进度条的下载——你根本不知道它是在努力工作还是已经死机了。用户盯着空白屏幕的那几秒足够他在心里把你的产品骂十八遍。stream()配合streamMode: ‘messages’每次yield出来的是一个[message, metadata]元组。message的类型有三种ai’是LLM的输出tool’是工具执行后的返回human’是用户消息——不过stream里一般不会出现human除非你的用户是个话痨在AI回答的过程中疯狂插嘴。这里有个巨坑AI消息的content字段有两种形态。没调用工具的时候它是字符串直接输出就行。调用了工具的时候它变成了数组里面可能有text块、tool_use块、thinking块。如果你只处理了字符串形态那调用工具的时候输出就会一片空白——就像你准备了雨伞但只带了伞柄下雨的时候才发现自己拿的是根棍子。踩坑实录我最初只处理了string类型的content结果调用计算器工具时输出为空。调试了半小时最后发现content变成了数组。那一刻我的心情就像花了半小时找手机最后发现手机一直在自己手里——既愚蠢又无奈。正确的处理方式是先判断_getType()是不是’ai’再看content是string还是Array。如果是数组就遍历每个block找到type为’text’的块把它的text字段输出。如果是thinking块就额外处理一下——后面会讲。第六章多轮对话或者叫给金鱼装上硬盘普通LLM的记忆能力大概跟金鱼差不多——七秒最多七秒。你问它我叫什么名字它说我不知道。你告诉它我叫张三它说好的张三。你紧接着问我叫什么它说我不知道。这不是AI这是某种行为艺术。Agent通过checkpointer解决了这个问题。核心机制是thread_id你给每次对话分配一个唯一的thread_idMemorySaver就会按这个ID把所有消息存起来。下次再调用的时候只要thread_id不变Agent就能看到之前的完整对话历史。thread_id的哲学意义thread_id就是Agent的身份证。同一个ID代表同一个灵魂不同ID代表不同的转世。你可以理解为thread_idsession-1’的Agent记得你thread_idsession-2’的Agent是个陌生人。这设定是不是很像某些玄幻小说的设定实际效果很惊艳。第一轮你问128乘47等于多少Agent回答6016。第二轮你直接说算的不对吧——注意这句话里没有数字没有运算没有任何上下文信息。但Agent因为记得上一轮的内容能理解你是在质疑之前的计算结果。它会重新审视然后告诉你我重新检查了一遍128乘47确实是6016不信你自己按计算器。这种记得上下文的能力让Agent从问答机器人升级成了对话伙伴。虽然这个伙伴偶尔还是会算错但至少它不会每次都问你你是谁——这已经比大部分人类客服强了。第七章Extended Thinking或者叫偷看AI的草稿纸Extended Thinking是Anthropic提供的一个能力让模型在给出最终答案之前先进行一段内心独白。你可以把它理解为AI在考试的时候允许你站在旁边看它打草稿。这草稿里可能写着这题看起来是乘法让我想想用哪个工具……哦对calculator参数是a128, b47, operationmultiply……开启thinking需要两个条件一是模型本身支持二是配置里显式设置maxTokens和thinking参数。maxTokens必须显式设置这是Anthropic API的硬性要求——大概是因为他们怕AI思考得太投入忘了还有最终答案要输出最后把token全花在思考上留给答案的就只剩一个嗯……thinking的预算管理budget_tokens: 5000的意思是思考最多花5000个token。如果AI是个哲学家它可能会把5000个token全用来思考生命的意义是什么最后告诉你128乘47等于一个关于存在的深刻问题。所以预算管理很重要不能让AI想太多。处理thinking block的时候我给它加了ANSI灰色转义码。在终端里thinking内容会显示成灰色和最终答案区分开。这就像你偷看学霸的草稿纸草稿纸上的涂涂画画是灰色的正式答题卡上的字迹是黑色的——虽然都是同一个人写的但重要性不一样。运行效果是这样的用户问128乘47等于多少终端先输出一行灰色的[思考] 用户想要计算128乘以47这是一个乘法运算我应该使用calculator工具……“然后输出正常颜色的128 × 47 6016”。整个过程就像看一场魔术表演先让你看到幕后准备再让你看到台前效果。如果底层模型不支持thinking这个block不会出现输出行为和之前完全一致。这属于优雅降级——就像你买了辆带天窗的车但天窗坏了车照样能开只是少了个看星星的功能。第八章回顾与展望或者叫终于写完了咱们从一个空文件夹开始一步步搭了TypeScript骨架、两个工具、一个Agent、流式输出、多轮对话、Extended Thinking。整个过程就像拼乐高一开始只有一堆散件最后拼出了一个能跑能跳还能思考的小机器人。当然这只是一个起点。后续你可以加更多工具——搜索、数据库查询、API调用、文件操作。你可以把MemorySaver换成持久化存储让Agent的记忆跨越服务器重启。你可以给Agent加错误处理和重试机制让它在工具调用失败的时候不会直接躺平。你可以构建一个Web界面把流式输出通过SSE推到前端让用户在浏览器里就能和Agent聊天。最后的忠告Agent的世界很大但坑也很多。每当你觉得这个功能应该很简单的时候LangChain就会跳出来给你上一课。保持耐心保持幽默保持随时能回滚代码的心态——这是Agent开发者的三大生存法则。运行命令很简单pnpm dev。然后你会看到三个测试场景依次输出计算器工具调用、多轮对话上下文记忆、时间工具调用。如果一切正常恭喜你你现在已经是一个拥有AI Agent的程序员了——虽然这个Agent目前只会算数和看表但至少它不会在你问现在几点的时候回答我不知道因为我没有工具。Agent的世界刚刚打开。这个项目只是一个起点就像你学会骑自行车之后接下来可以骑摩托车、开汽车、甚至开飞机——虽然开飞机需要驾照但梦想总是要有的。万一实现了呢P.S. 目前国内还是很缺AI人才的希望更多人能真正加入到AI行业共同促进行业进步增强我国的AI竞争力。想要系统学习AI知识的朋友可以看看我精心打磨的教程 http://blog.csdn.net/jiangjunshow教程通俗易懂高中生都能看懂还有各种段子风趣幽默从深度学习基础原理到各领域实战应用都有讲解我22年的AI积累全在里面了。注意教程仅限真正想入门AI的朋友否则看看零散的博文就够了。