ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

AI大模型从“会说”到“会做”:Agent Skills、MCP与LangChain实战

AI大模型从“会说”到“会做”:Agent Skills、MCP与LangChain实战 1. 从“会用”到“用好”AI大模型应用的能力跃迁聊到AI大模型应用很多人第一反应还是“打开对话框输入问题等它吐字”。这套玩法在2023年确实够用但到了现在如果你还停留在这个层面那基本等于拿着一台顶配工作站只用来扫雷。我身边不少做开发的朋友包括我自己在过去一年里踩过的最大坑就是把大模型当成了一个更聪明的搜索引擎而不是一个可以调度工具、执行任务、串联流程的“执行引擎”。这个系列写到第十二篇我想聊的核心就一件事怎么让AI大模型从“能说会道”变成“能干活”。这中间的关键跳板就是Agent Skills、SKILL.md、MCP协议以及LangChain这一整套工具链的组合使用。你可能会问这些东西到底解决什么问题简单说它们解决的是“大模型知道该做什么但手伸不出去”的问题。大模型本身是一个推理引擎它能理解你的意图能规划步骤但它默认情况下无法读取你本地的文件、无法调用你的内部API、无法操作浏览器、无法连接数据库。Agent Skills和MCP就是给它装上“手”和“脚”的机制。这篇文章适合谁看如果你已经用过大模型API写过简单的提示词甚至跑过LangChain的Hello World但总觉得“差点意思”不知道如何把它变成一个真正能落地的自动化工具那这篇就是写给你的。如果你是完全的新手也没关系我会把每个概念拆开讲清楚用生活化的类比帮你建立直觉。全文会围绕四个核心板块展开整体设计思路、核心细节解析、实操过程实现、常见问题排查。每个板块我都会给出可以直接抄作业的配置和代码也会分享一些文档里不会写的踩坑经验。先说一个我自己的真实感受大模型应用的上限不取决于模型本身有多强而取决于你给它搭建的工具生态有多完善。一个中等能力的模型如果接入了合适的工具和技能实际表现可以远超一个顶级模型裸奔。这个结论我在多个项目中反复验证过后面会展开讲具体案例。2. 整体设计与思路拆解为什么是Agent Skills加MCP加LangChain2.1 大模型应用的三层架构推理层、调度层、执行层要理解这套技术组合的价值得先看清楚大模型应用的基本架构。我习惯把它分成三层推理层、调度层、执行层。推理层就是大模型本身负责理解意图、拆解任务、生成方案。调度层负责决定“下一步该调用哪个工具、传什么参数、拿到结果后怎么继续”。执行层就是真正干活的那些工具和接口比如读写文件、发HTTP请求、操作浏览器、查询数据库。裸用大模型的时候你只有推理层。它能告诉你“你应该去查一下数据库”但它自己查不了。LangChain这类框架补的是调度层它提供了Agent的执行循环、工具注册机制、记忆管理、中间件等能力。而MCP和Agent Skills补的是执行层的标准化问题——它们定义了一套统一的接口规范让不同的工具能够以一致的方式被大模型调用。这三层缺一不可。我见过很多项目只做了推理层和调度层执行层靠硬编码的API调用结果就是每接一个新工具就要改一次Agent的代码维护成本极高。MCP的出现就是为了解决这个“每接一个工具就要重新适配”的问题。2.2 MCP协议到底解决了什么痛点MCP的全称是Model Context Protocol翻译过来叫“模型上下文协议”。你可以把它理解成AI世界的USB接口标准。在MCP出现之前每个大模型厂商、每个Agent框架、每个工具提供方都有自己的接口格式。你想让Claude调用一个数据库得写一套适配想让GPT调用同一个数据库又得写另一套。这就像早年手机充电接口诺基亚圆口、索尼爱立信扁口、苹果30针出门得带一把线。MCP做的事情就是统一这个接口。它定义了工具如何描述自己输入参数、输出格式、功能说明定义了客户端如何发现和调用工具定义了服务端如何注册和响应。一旦某个工具实现了MCP Server任何支持MCP Client的Agent都能直接调用它不需要额外适配。这个价值在工具数量少的时候不明显但当你的Agent需要接入十几个甚至几十个工具时标准化带来的效率提升是巨大的。我实测下来用MCP方式接入一个新工具平均耗时从原来的半天到一天缩短到了半小时以内。而且因为接口标准化调试也更容易定位问题——是工具本身的问题还是Agent调度的问题一目了然。2.3 Agent Skills与SKILL.md让大模型“学会”使用工具有了MCP解决工具接入的标准化问题还有一个问题没解决大模型怎么知道在什么场景下该用哪个工具、该怎么组合使用。这就是Agent Skills要解决的问题。Agent Skills本质上是一组结构化的指令和知识告诉大模型“当你遇到某类任务时应该按照什么步骤、调用哪些工具、注意哪些事项”。而SKILL.md就是承载这些技能的Markdown文件。你可以把它理解成给大模型看的“操作手册”——不是给人类看的文档而是专门为大模型的上下文理解优化的指令集。为什么用Markdown而不是JSON或YAML因为大模型对自然语言的理解能力远强于对结构化配置的解析能力。一份写得好的SKILL.md能让大模型在零样本的情况下就学会一个复杂的工作流。我试过用纯JSON描述工具调用流程模型经常在参数映射上出错换成SKILL.md的自然语言加示例的写法后成功率明显提升。2.4 LangChain在整套体系中的角色定位LangChain在这个体系里扮演的是“胶水层”和“调度中枢”的角色。它提供了Agent的执行循环AgentExecutor、工具抽象Tool、记忆管理Memory、中间件Middleware等基础设施。你可以把MCP Server注册成LangChain的Tool然后用SKILL.md来指导Agent的调度逻辑。LangChain最近几个版本在Agent中间件方面做了不少增强比如支持在Agent执行过程中插入自定义逻辑实现权限校验、日志记录、结果缓存等功能。这些中间件在实际生产环境中非常关键因为你不希望Agent无限制地调用付费API也不希望它把敏感数据传到外部服务。选LangChain而不是自己从零实现调度层主要考虑是生态成熟度和社区支持。它已经集成了大量常见的工具和模型提供商很多坑已经被踩过了。当然如果你的需求非常特殊自己实现一个轻量级的调度器也完全可行但前期开发成本会高不少。3. 核心细节解析与实操要点从SKILL.md到MCP Server的完整链路3.1 SKILL.md的编写规范与实战模板SKILL.md不是随便写写就行的。我踩过的最大坑就是一开始把它当成了普通的README来写结果大模型根本不按我预期的流程走。后来反复调整总结出了一套比较有效的结构。一份合格的SKILL.md应该包含以下几个部分技能描述、适用场景、前置条件、执行步骤、参数说明、示例、异常处理。技能描述用一两句话说明这个技能是干什么的要写得足够具体让模型能判断什么时候该激活这个技能。适用场景列出触发条件比如“当用户要求查询数据库中的订单信息时”。前置条件说明执行这个技能需要哪些环境准备比如“需要已配置好数据库连接”。执行步骤是核心要按顺序列出每一步做什么、调用哪个工具、传什么参数。这里的关键是步骤要足够细但不要细到每个HTTP头都写出来。我一般会把一个技能拆成5到10个步骤每个步骤对应一次工具调用或一次推理决策。参数说明要明确每个参数的类型、是否必填、默认值。示例部分给出一到两个完整的输入输出样例这对模型理解预期行为非常有帮助。异常处理部分经常被忽略但实际很重要。你要告诉模型“如果工具返回超时怎么办”“如果参数校验失败怎么办”“如果权限不足怎么办”。没有这部分模型遇到异常时容易陷入死循环或者胡乱尝试。3.2 MCP Server的注册与工具描述优化MCP Server的注册本身不复杂按照协议实现几个标准方法就行。但工具描述的质量直接决定了Agent的调用准确率。我见过太多项目工具功能写得没问题但描述写得太简略导致模型要么不调用要么调用了但传错参数。工具描述要回答三个问题这个工具做什么、什么时候用、参数怎么填。描述里要包含足够的上下文信息让模型能判断这个工具是否适合当前任务。比如一个查询天气的工具描述不能只写“查询天气”而要写“根据城市名称查询当前天气状况返回温度、湿度、风力等信息适用于需要实时天气数据的场景”。参数描述同样重要。每个参数都要说明类型、含义、格式要求、示例值。对于枚举类型的参数要把所有可选值列出来。对于有格式要求的参数比如日期格式要明确写出“格式为YYYY-MM-DD”。这些细节看起来琐碎但能大幅降低模型传错参数的概率。3.3 LangChain Agent中间件的配置要点LangChain的Agent中间件是我最近用得比较多的功能。它允许你在Agent执行循环的各个阶段插入自定义逻辑。比如在工具调用前做权限校验在工具调用后做结果过滤在每轮循环结束后做日志记录。配置中间件时要注意执行顺序。多个中间件会按照注册顺序依次执行所以要把权限校验放在最前面日志记录放在最后面。另外中间件里不要做太耗时的操作否则会拖慢整个Agent的响应速度。如果确实需要做耗时操作考虑异步执行或者放到单独的线程里。还有一个容易忽略的点中间件的异常处理。如果中间件抛异常整个Agent执行会中断。所以中间件里要做好try-catch对于非致命错误记录日志后继续执行不要直接让异常冒泡出去。3.4 工具选型对比MCP Server与原生Tool的取舍在实际项目中你可能会面临一个选择是把工具实现成MCP Server还是直接写成LangChain的原生Tool。两者各有优劣我整理了一个对比表格供参考。对比维度MCP ServerLangChain原生Tool标准化程度高跨框架通用低绑定LangChain开发复杂度中等需实现协议低继承基类即可调试便利性较好有标准日志一般需自己加日志性能开销略高有协议序列化较低直接函数调用生态兼容性强可被多种客户端调用弱仅限LangChain生态适用场景需要跨团队、跨框架复用快速原型、内部专用我的建议是如果这个工具只在一个项目里用而且团队统一用LangChain那直接写原生Tool更省事。如果工具需要被多个Agent或多个团队复用或者未来可能切换框架那投入时间实现MCP Server是值得的。4. 实操过程与核心环节实现搭建一个可落地的AI Agent4.1 环境准备与依赖安装先说一下基础环境。我用的Python版本是3.11LangChain版本是0.3.xMCP的Python SDK用的是官方实现。内存方面如果你只是跑Agent调度不本地部署大模型16GB就够用了。但如果要本地跑模型32GB起步比较稳妥具体取决于模型参数量。安装依赖的命令如下pip install langchain langchain-openai langchain-community mcp pip install fastapi uvicorn pip install playwright playwright install chromium这里解释一下为什么装Playwright。很多实际任务需要操作浏览器比如抓取网页数据、填写表单、截图等。Playwright是目前比较稳定的浏览器自动化工具而且有现成的MCP Server实现接入成本低。4.2 编写第一个SKILL.md以“网页信息提取”为例假设我们要实现一个技能给定一个URL提取页面中的关键信息并整理成结构化数据。这个SKILL.md可以这样写# 技能网页信息提取 ## 描述 根据用户提供的URL打开网页并提取指定类型的信息返回结构化结果。 ## 适用场景 - 用户要求提取某个网页的标题、正文、链接列表 - 用户要求监控某个页面的内容变化 - 用户要求从网页中抓取特定字段 ## 前置条件 - 已安装Playwright及Chromium浏览器 - 网络连接正常 ## 执行步骤 1. 调用browser_navigate工具传入目标URL等待页面加载完成 2. 调用browser_get_content工具获取页面HTML内容 3. 根据用户指定的提取类型调用对应的解析工具 - 提取标题调用extract_title工具 - 提取正文调用extract_main_content工具 - 提取链接调用extract_links工具 4. 将提取结果整理成JSON格式返回给用户 ## 参数说明 - url必填目标网页地址需包含协议头 - extract_type必填提取类型可选值为title、content、links - timeout可选页面加载超时时间默认30秒 ## 示例 输入提取https://example.com的标题 输出{title: Example Domain, url: https://example.com} ## 异常处理 - 如果页面加载超时返回错误信息并建议用户检查URL - 如果提取类型不支持返回支持的提取类型列表 - 如果页面内容为空返回空结果并说明原因这份SKILL.md的关键在于步骤清晰、参数明确、异常处理完整。模型拿到这份指令后基本能按照预期流程执行。4.3 实现MCP Server封装Playwright浏览器操作接下来实现一个简单的MCP Server封装Playwright的浏览器操作。这里用Python的mcp库来实现from mcp.server import Server from mcp.types import Tool, TextContent from playwright.async_api import async_playwright import asyncio app Server(browser-mcp) app.list_tools() async def list_tools(): return [ Tool( namebrowser_navigate, description打开指定URL的网页等待页面加载完成。适用于需要获取网页内容的场景。, inputSchema{ type: object, properties: { url: { type: string, description: 目标网页地址需包含http或https协议头 }, timeout: { type: integer, description: 页面加载超时时间毫秒默认30000, default: 30000 } }, required: [url] } ), Tool( namebrowser_get_content, description获取当前页面的HTML内容。需先调用browser_navigate打开页面。, inputSchema{ type: object, properties: {}, required: [] } ) ] app.call_tool() async def call_tool(name: str, arguments: dict): if name browser_navigate: url arguments[url] timeout arguments.get(timeout, 30000) async with async_playwright() as p: browser await p.chromium.launch() page await browser.new_page() await page.goto(url, timeouttimeout) html await page.content() await browser.close() return [TextContent(typetext, texthtml[:5000])] elif name browser_get_content: return [TextContent(typetext, text请先调用browser_navigate)] else: raise ValueError(f未知工具{name}) if __name__ __main__: import mcp.server.stdio asyncio.run(mcp.server.stdio.run_server(app))这段代码实现了一个最简化的MCP Server提供了两个工具打开网页和获取内容。实际项目中你需要根据需求扩展更多工具比如点击元素、填写表单、截图等。4.4 用LangChain组装Agent并接入MCP工具最后一步是把MCP Server注册到LangChain的Agent里。LangChain提供了MCP适配器可以把MCP工具转换成LangChain的Toolfrom langchain.agents import AgentExecutor, create_openai_tools_agent from langchain_openai import ChatOpenAI from langchain_mcp_adapters import MCPToolkit from langchain.prompts import ChatPromptTemplate async def create_agent(): # 连接MCP Server toolkit MCPToolkit(server_command[python, browser_mcp_server.py]) tools await toolkit.get_tools() # 初始化模型 llm ChatOpenAI(modelgpt-4o, temperature0) # 构建提示词 prompt ChatPromptTemplate.from_messages([ (system, 你是一个网页信息提取助手。根据用户需求调用合适的工具完成任务。), (human, {input}), (placeholder, {agent_scratchpad}) ]) # 创建Agent agent create_openai_tools_agent(llm, tools, prompt) executor AgentExecutor(agentagent, toolstools, verboseTrue) return executor # 使用 async def main(): executor await create_agent() result await executor.ainvoke({ input: 请提取https://example.com页面的标题 }) print(result[output]) asyncio.run(main())这套代码跑通后你就有了一个能自动打开网页、提取信息的Agent。虽然功能简单但整个链路是完整的SKILL.md指导行为MCP Server提供工具LangChain负责调度。4.5 参数调优与性能优化实录在实际使用中有几个参数对Agent的表现影响很大。第一个是temperature做工具调用时建议设为0或接近0的值减少随机性。第二个是max_iterations控制Agent最多执行多少轮循环设太小会导致任务没完成就退出设太大会浪费token。我一般设为10到15轮。第三个是工具返回结果的截断长度。MCP工具返回的内容如果太长会占用大量上下文窗口导致模型“忘记”前面的指令。我通常会把返回结果截断到5000字符以内如果确实需要完整内容就存到文件里只返回文件路径和摘要。性能方面最大的瓶颈通常是工具调用的网络延迟。如果Agent需要连续调用多个工具总耗时可能是单个工具耗时的数倍。优化思路有两个一是尽量并行调用无依赖的工具二是对频繁调用的结果做缓存。LangChain的中间件机制可以很方便地实现缓存逻辑。5. 常见问题与排查技巧实录5.1 Agent不调用工具或调用错误工具怎么办这是最常见的问题。模型要么直接用自己的知识回答要么调用了不相关的工具。排查思路分三步先检查工具描述是否足够清晰再检查SKILL.md的适用场景是否写得太模糊最后检查系统提示词是否给了模型足够的引导。我遇到过一个典型案例一个查询订单的工具描述写的是“查询订单信息”结果模型经常在用户问“订单什么时候到”的时候调用它而实际上应该调用物流查询工具。后来把描述改成“根据订单号查询订单的详细信息包括商品、金额、下单时间不包含物流状态”问题就解决了。工具描述要明确边界说清楚它不做什么和说清楚它做什么同样重要。5.2 MCP连接失败与超时排查MCP连接失败通常有几个原因Server进程没启动、端口被占用、协议版本不匹配、认证信息错误。排查时先看Server端的日志确认进程是否正常运行。然后用MCP客户端工具单独测试连接排除Agent层的干扰。超时问题多半是工具执行时间太长。比如浏览器操作如果页面加载慢很容易超过默认超时时间。解决办法是合理设置超时参数同时在SKILL.md里告诉模型“如果超时可以尝试增加timeout参数后重试”。另外对于确实耗时的操作考虑改成异步模式先返回任务ID后续再查询结果。5.3 上下文溢出与记忆管理当Agent执行多轮循环后上下文会越来越长最终超出模型的上下文窗口。表现是模型开始“胡言乱语”或者重复之前的操作。解决办法有几个一是限制工具返回结果的长度二是使用LangChain的记忆管理功能只保留最近几轮的关键信息三是把中间结果存到外部存储上下文里只保留引用。我个人的习惯是对于超过5轮的任务一定要加记忆压缩逻辑。具体做法是在每轮循环结束后用一个小模型对当前上下文做摘要只保留任务目标、已完成步骤、当前状态和待办事项。这样即使执行20轮上下文也不会爆炸。5.4 常见问题速查表问题现象可能原因排查方法解决方案Agent不调用工具工具描述不清晰检查工具description字段补充使用场景和参数说明调用错误工具工具边界模糊对比相似工具的description明确各工具的适用范围和不适用场景MCP连接超时Server未启动或端口冲突查看Server日志和端口占用重启Server或更换端口上下文溢出工具返回内容过长检查每轮返回的token数截断返回内容或启用记忆压缩参数传递错误参数schema不明确检查inputSchema定义补充参数类型、格式和示例执行循环不终止缺少终止条件检查SKILL.md的完成标准明确任务完成标志和最大轮次5.5 几个文档里不会写的实操心得第一个心得SKILL.md要版本化管理。我一开始把SKILL.md直接写在代码里后来发现调整技能描述时很难追踪改了哪些内容。现在我把SKILL.md单独放在一个目录里用Git管理每次调整都提交记录。这样当Agent行为发生变化时可以快速定位是哪次修改导致的。第二个心得工具返回结果要加“置信度”字段。很多工具返回的数据质量参差不齐如果模型不知道结果是否可靠可能会基于错误数据继续推理。我在工具返回的JSON里加了一个confidence字段0到1之间告诉模型这个结果的可靠程度。模型会根据置信度决定是直接使用还是需要进一步验证。第三个心得给Agent加“思考日志”。在中间件里记录Agent每轮的推理过程和决策依据输出到一个单独的日志文件。这个日志在调试时非常有用能清楚看到模型为什么选择了某个工具、为什么传了某个参数。生产环境中也可以用来做审计。第四个心得不要追求一次到位。我见过很多项目想把所有功能都塞进一个Agent里结果就是技能描述越来越长模型越来越困惑。正确的做法是先做一个最小可用的技能跑通后再逐步增加。每个技能只做一件事做好一件事。6. 从单Agent到多Agent协作的扩展思路单个Agent的能力边界是有限的。当任务复杂度上升到需要多个专业领域知识时多Agent协作就成了必然选择。LangChain在这方面提供了不少支持比如AgentExecutor可以嵌套一个Agent可以把另一个Agent当作工具来调用。我最近在做一个项目需要同时处理数据查询、报告生成和邮件发送三个环节。最初的方案是一个Agent包揽所有工作结果SKILL.md写了上千行模型经常搞混步骤。后来拆成三个Agent查询Agent负责数据库操作报告Agent负责数据整理和格式化发送Agent负责邮件相关操作。每个Agent有自己的SKILL.md和工具集通过一个协调Agent来调度。拆分之后每个Agent的指令都控制在200行以内执行准确率明显提升。多Agent协作的关键是定义好Agent之间的接口。输入输出格式要统一错误处理要一致超时和重试策略要协调。另外协调Agent的SKILL.md要写清楚“什么情况下调用哪个子Agent”这个判断逻辑的质量直接决定了整体效果。这个方向后续还可以继续扩展比如引入Agent之间的协商机制、动态技能发现、基于执行历史的技能推荐等。但那是更后面的内容了先把单Agent的技能体系搭扎实再考虑多Agent的复杂度。我个人在实际操作中的体会是这套技术栈的学习曲线在前两周比较陡因为概念多、组件多、配置项多。但一旦跑通一个完整链路后面的扩展就会快很多。关键是不要一开始就追求大而全先做一个能跑通的最小闭环哪怕只是“打开网页提取标题”这么简单的功能。跑通之后你对SKILL.md、MCP、LangChain三者的关系就会有直观的理解后面加功能就是在这个骨架上添砖加瓦。
返回列表