LangChain Agent集成MCP与Skills:构建动态扩展的AI智能体

在实际 AI 应用开发中,构建一个能理解用户意图、调用工具并完成复杂任务的智能体(Agent)是核心挑战。传统的 LangChain Agent 框架虽然提供了基础范式,但在工具扩展性、协议标准化和技能复用性上仍存在瓶颈。当我们将 LangChain Agent 与模型上下文协议(Model Context Protocol, MCP)以及标准化的技能(Skills)体系相结合时,Agent 的能力边界和工程效率将得到显著跃升。这种集成不仅让 Agent 能动态接入海量外部工具和数据源,还能实现技能的模块化开发与跨项目复用,为基于 Claude、GPT 等大模型构建更强大、更稳定的 AI 应用提供了坚实的技术底座。

本文旨在深入解析 LangChain Agent 接入 MCP 与 Skills 的技术原理,并通过一个从环境搭建到生产级实践的全流程示例,展示如何利用这套技术栈全方位提升开发效率与应用能力。我们将从核心概念入手,逐步完成一个能查询数据库、调用 API 并处理文件的智能体构建,并深入探讨其中的配置细节、常见陷阱及性能优化策略。

1. 理解 MCP 与 Skills:Agent 能力扩展的基石

在深入代码之前,必须厘清 MCP 和 Skills 这两个核心概念,它们共同构成了现代 Agent 扩展能力的协议层和模块层。

1.1 模型上下文协议(MCP)是什么

模型上下文协议是一种开放协议,用于在大语言模型(LLM)与外部工具、数据源之间建立标准化的通信桥梁。你可以将其理解为 LLM 世界的“USB 协议”或“驱动程序接口标准”。在没有 MCP 之前,每个工具都需要为不同的 Agent 框架(如 LangChain、LlamaIndex)编写特定的适配器代码,导致重复劳动和兼容性问题。

MCP 的核心价值在于解耦与标准化:

  • 对模型/Agent 而言 :它只需实现 MCP 客户端,就能接入任何遵循 MCP 协议的服务端(Server)所提供的工具,无需关心工具的具体实现。
  • 对工具开发者而言 :只需将工具包装成一个 MCP 服务端,就能被所有支持 MCP 的 Agent 框架使用,极大地扩展了工具的受众。

一个典型的 MCP 服务端会通过标准接口向客户端“公布”自己提供了哪些工具(Tools)、数据源(Resources)以及提示词模板(Prompts)。例如,一个数据库 MCP 服务端可能公布一个“执行 SQL 查询”的工具;一个天气 API 的 MCP 服务端可能公布一个“获取城市天气”的工具。

1.2 Skills:可复用的能力模块

Skills(技能)是比工具(Tools)更高一层的抽象。一个 Skill 通常是为了完成一个特定领域任务而打包的一组工具、提示词、工作流程甚至小模型。如果说工具是“螺丝刀”,那么技能就是“组装家具的完整工具箱和说明书”。

在 LangChain 的生态中,Skills 强调可复用性和组合性。例如,“数据分析”技能可能包含数据加载、清洗、可视化和报告生成等多个工具和预设提示词。通过将 Skills 与 MCP 结合,我们可以实现:

  1. 动态发现与加载 :Agent 在运行时可以通过 MCP 发现并加载远端服务器上的 Skills。
  2. 版本管理与共享 :Skills 可以像软件包一样进行版本管理,并在团队或社区内共享。
  3. 热插拔 :无需重启 Agent 服务,即可动态添加或移除 Skills,实现能力的灵活伸缩。

1.3 LangChain Agent 的工作范式

LangChain Agent 的核心思想是“推理-执行”循环。Agent 内部有一个 LLM 作为“大脑”,它根据用户输入和当前上下文,决定下一步是直接回答,还是调用某个工具。调用工具后,工具的执行结果会返回给 LLM,LLM 再据此决定后续动作,直到任务完成或达到终止条件。

传统的 LangChain Agent 在工具管理上相对静态,通常需要在代码中显式定义并传入一个工具列表。而接入 MCP 后,Agent 的工具列表可以动态地从多个 MCP 服务端获取,实现了工具管理的“云原生”化。

2. 环境准备与核心依赖配置

为了构建一个接入 MCP 与 Skills 的 LangChain Agent,我们需要搭建一个包含客户端、服务端和技能库的完整开发环境。

2.1 基础环境与 Python 包管理

建议使用 Python 3.10 或更高版本,并使用虚拟环境隔离依赖。

# 创建并激活虚拟环境(以 conda 为例)
conda create -n langchain-mcp-agent python=3.10
conda activate langchain-mcp-agent

# 使用 pip 安装核心依赖
pip install langchain langchain-community langchain-core

2.2 安装 MCP 相关 SDK

MCP 的实现通常包含客户端库和服务端开发库。我们将使用 mcp 这个 Python SDK,它提供了开发 MCP 组件所需的核心功能。

# 安装 MCP SDK
pip install mcp

# 安装 LangChain 与 MCP 的集成库(如果官方或社区有提供)
# 例如,一个可能的集成包(请根据实际生态调整)
pip install langchain-mcp-integration

注意:MCP 生态仍在快速发展中,具体的集成库名称可能变化。关键在于找到或实现一个能将 MCP 服务端提供的工具转换为 LangChain Tool 对象的适配器。

2.3 安装示例 Skills 与工具服务端

为了进行演示,我们需要一些实际的 MCP 服务端来提供工具。这里以两个常见的服务端为例:

  1. 文件系统服务端 :提供读取、写入、列出文件等工具。
  2. SQLite 数据库服务端 :提供执行 SQL 查询的工具。

我们可以从社区寻找或自己实现这些服务端。假设我们使用一个名为 mcp-server-filesystem mcp-server-sqlite 的包。

# 安装示例 MCP 服务端(假设的包名,请替换为实际可用的包)
pip install mcp-server-filesystem mcp-server-sqlite

2.4 配置大模型访问

本文以 Anthropic 的 Claude 模型为例,你需要准备相应的 API 密钥。其他模型如 OpenAI GPT 的配置逻辑类似。

# 安装 Claude SDK
pip install anthropic

在项目根目录创建 .env 文件来管理敏感配置:

# .env
ANTHROPIC_API_KEY=your_anthropic_api_key_here

在代码中通过 python-dotenv 加载:

# config.py
import os
from dotenv import load_dotenv

load_dotenv()

ANTHROPIC_API_KEY = os.getenv("ANTHROPIC_API_KEY")
if not ANTHROPIC_API_KEY:
    raise ValueError("请在 .env 文件中设置 ANTHROPIC_API_KEY")

3. 构建一个动态工具发现的 LangChain Agent

本节将分步构建一个核心 Agent,它能够从本地运行的多个 MCP 服务端动态发现工具,并利用 Claude 模型进行推理和调用。

3.1 启动并连接 MCP 服务端

首先,我们需要在后台启动 MCP 服务端进程。在实际部署中,这些服务端可能以独立进程、容器或远程服务的形式存在。这里我们在同一台机器上以子进程方式启动它们。

# mcp_servers.py
import subprocess
import time
import signal
import sys

class MCPServerManager:
    def __init__(self):
        self.servers = []

    def start_file_server(self):
        """启动文件系统 MCP 服务端"""
        # 假设服务端通过命令 `mcp-server-filesystem` 启动,监听 8001 端口
        cmd = ["mcp-server-filesystem", "--root", "./data", "--port", "8001"]
        proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        self.servers.append(("filesystem", proc, 8001))
        time.sleep(2) # 等待服务端启动
        print(f"文件系统 MCP 服务端已启动 (PID: {proc.pid})")
        return proc

    def start_sqlite_server(self, db_path="./data/example.db"):
        """启动 SQLite MCP 服务端"""
        # 假设服务端通过命令 `mcp-server-sqlite` 启动,监听 8002 端口
        cmd = ["mcp-server-sqlite", "--db", db_path, "--port", "8002"]
        proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        self.servers.append(("sqlite", proc, 8002))
        time.sleep(2)
        print(f"SQLite MCP 服务端已启动 (PID: {proc.pid})")
        return proc

    def stop_all(self):
        """停止所有 MCP 服务端"""
        for name, proc, _ in self.servers:
            print(f"正在停止 {name} 服务端...")
            proc.terminate()
            proc.wait()
        self.servers.clear()

# 使用上下文管理器确保资源清理
if __name__ == "__main__":
    manager = MCPServerManager()
    try:
        manager.start_file_server()
        manager.start_sqlite_server()
        print("所有 MCP 服务端已就绪,按 Ctrl+C 停止...")
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        manager.stop_all()

3.2 实现 MCP 客户端并转换为 LangChain Tools

这是最关键的一步:我们需要编写一个 MCP 客户端,连接到服务端,获取其提供的工具列表,并将每个工具包装成 LangChain 能识别的 Tool 对象。

# mcp_client.py
import asyncio
from typing import List, Optional
from langchain.tools import BaseTool
from langchain_core.tools import Tool
from mcp import ClientSession, StdioServerParameters
from mcp.client import stdio

class MCPToolFetcher:
    def __init__(self, server_name: str, server_params: StdioServerParameters):
        self.server_name = server_name
        self.server_params = server_params
        self.tools: List[Tool] = []

    async def connect_and_fetch_tools(self):
        """连接到 MCP 服务端并获取工具列表"""
        # 创建与 MCP 服务端的会话
        async with stdio.stdio_client(self.server_params) as (read, write):
            async with ClientSession(read, write) as session:
                # 初始化连接
                await session.initialize()
                # 列出服务端提供的所有工具
                response = await session.list_tools()
                mcp_tools = response.tools

                for mcp_tool in mcp_tools:
                    # 为每个 MCP 工具创建一个 LangChain Tool 包装器
                    langchain_tool = Tool(
                        name=f"{self.server_name}_{mcp_tool.name}",
                        func=self._create_tool_func(session, mcp_tool),
                        description=mcp_tool.description,
                    )
                    self.tools.append(langchain_tool)
        return self.tools

    def _create_tool_func(self, session, mcp_tool):
        """创建一个能调用特定 MCP 工具的同步函数"""
        # 注意:LangChain Tool 的 func 是同步的,但 MCP 调用是异步的。
        # 我们需要在同步函数中运行异步代码。这里使用 asyncio.run 简化处理,
        # 在生产环境中需要考虑更优的异步集成方式。
        async def async_tool_func(**kwargs):
            # 调用 MCP 工具的 execute 方法
            result = await session.call_tool(mcp_tool.name, arguments=kwargs)
            # 返回工具执行结果的文本内容
            return "\n".join([c.text for c in result.content if c.type == "text"])

        def sync_wrapper(**kwargs):
            # 在新的事件循环中运行异步函数(适用于简单脚本)
            # 注意:在已有事件循环的环境中(如 FastAPI),需要使用其他方式
            return asyncio.run(async_tool_func(**kwargs))

        return sync_wrapper

# 工具获取工具函数
def get_all_mcp_tools() -> List[Tool]:
    """获取所有已配置 MCP 服务端的工具"""
    all_tools = []
    # 定义服务端连接参数
    servers = [
        ("filesystem", StdioServerParameters(command="mcp-server-filesystem", args=["--root", "./data"])),
        ("sqlite", StdioServerParameters(command="mcp-server-sqlite", args=["--db", "./data/example.db"])),
    ]
    
    async def fetch_all():
        for name, params in servers:
            fetcher = MCPToolFetcher(name, params)
            tools = await fetcher.connect_and_fetch_tools()
            all_tools.extend(tools)
    
    # 运行异步函数获取所有工具
    asyncio.run(fetch_all())
    return all_tools

3.3 创建 LangChain Agent 并集成动态工具

现在,我们可以使用获取到的动态工具列表来初始化一个 LangChain Agent。这里使用 ReAct 代理类型,它适合多步骤的工具调用场景。

# agent_builder.py
from langchain.agents import AgentExecutor, create_react_agent
from langchain_core.prompts import PromptTemplate
from langchain_anthropic import ChatAnthropic
from config import ANTHROPIC_API_KEY
from mcp_client import get_all_mcp_tools

def build_mcp_agent():
    # 1. 初始化 Claude 模型
    llm = ChatAnthropic(
        model="claude-3-haiku-20240307", # 可根据需要选择 sonnet, opus 等型号
        temperature=0,
        api_key=ANTHROPIC_API_KEY
    )

    # 2. 动态获取所有 MCP 工具
    print("正在从 MCP 服务端发现工具...")
    tools = get_all_mcp_tools()
    print(f"已发现 {len(tools)} 个工具: {[t.name for t in tools]}")

    # 3. 定义 ReAct 代理的提示词模板
    # 提示词需要指导模型如何思考和使用工具
    prompt = PromptTemplate.from_template("""
    你是一个有帮助的AI助手,可以访问以下工具:
    {tools}

    请使用以下格式回答:

    问题:用户提出的问题
    思考:你需要思考如何一步步解决问题。你可以使用工具,也可以直接回答。
    行动:要使用的工具名称,必须是以下工具之一:[{tool_names}]
    行动输入:工具的输入,必须是一个有效的JSON字符串
    观察:工具返回的结果
    ... (这个 思考/行动/行动输入/观察 循环可以重复多次)
    思考:我现在知道了最终答案
    最终答案:对原始问题的最终回答

    开始!

    问题:{input}
    思考:{agent_scratchpad}
    """)

    # 4. 创建 ReAct 代理
    agent = create_react_agent(llm, tools, prompt)

    # 5. 创建代理执行器,控制最大迭代次数以避免无限循环
    agent_executor = AgentExecutor(
        agent=agent,
        tools=tools,
        verbose=True, # 开启详细日志,便于调试
        handle_parsing_errors=True, # 处理模型输出解析错误
        max_iterations=10, # 限制最大思考步骤
        early_stopping_method="generate", # 当模型决定不再使用工具时停止
    )
    return agent_executor

4. 运行验证与结果分析

构建好 Agent 后,我们需要准备测试数据,运行几个典型任务来验证其能力。

4.1 准备测试环境与数据

首先,创建必要的目录和测试数据。

# 创建数据目录和示例文件
mkdir -p ./data
echo "项目报告草案\n主要内容:...\n待办:整理图表" > ./data/report.txt
echo "会议记录\n日期:2024-05-27\n议题:Agent架构评审" > ./data/meeting.txt

# 创建并初始化一个 SQLite 示例数据库
sqlite3 ./data/example.db <<EOF
CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT, department TEXT);
INSERT INTO users (name, email, department) VALUES 
('张三', 'zhangsan@example.com', '工程部'),
('李四', 'lisi@example.com', '产品部'),
('王五', 'wangwu@example.com', '市场部');
EOF

4.2 执行综合任务测试

现在,编写一个测试脚本,让 Agent 执行一个结合了文件操作和数据库查询的复杂任务。

# run_agent.py
from agent_builder import build_mcp_agent
import asyncio

async def main():
    # 构建 Agent
    agent = build_mcp_agent()

    # 测试任务 1:简单的文件读取
    print("\n=== 测试任务 1:读取文件 ===")
    result1 = await agent.ainvoke({"input": "请读取 data 目录下 report.txt 文件的内容并总结其要点。"})
    print(f"任务1结果: {result1['output']}")

    # 测试任务 2:数据库查询
    print("\n=== 测试任务 2:查询数据库 ===")
    result2 = await agent.ainvoke({"input": "查询 example.db 数据库中 users 表里所有在工程部的员工姓名和邮箱。"})
    print(f"任务2结果: {result2['output']}")

    # 测试任务 3:多步骤组合任务
    print("\n=== 测试任务 3:组合任务 ===")
    result3 = await agent.ainvoke({
        "input": """
        1. 首先,请列出 data 目录下所有的 .txt 文件。
        2. 然后,读取 meeting.txt 文件,提取会议日期。
        3. 最后,去 example.db 数据库的 users 表里,查一下产品部有哪些人,把结果和会议日期一起整理成一个简短的摘要。
        """
    })
    print(f"任务3结果: {result3['output']}")

if __name__ == "__main__":
    asyncio.run(main())

运行此脚本,你应该能看到类似以下的输出(具体内容因模型随机性略有不同):

正在从 MCP 服务端发现工具...
已发现 4 个工具: ['filesystem_read_file', 'filesystem_list_directory', 'sqlite_execute_query', 'sqlite_list_tables']

=== 测试任务 1:读取文件 ===
> 进入新的 Agent 执行链...
思考:用户要求读取 report.txt 文件并总结要点。我需要使用文件读取工具。
行动:filesystem_read_file
行动输入:{"path": "./data/report.txt"}
观察:项目报告草案\n主要内容:...\n待办:整理图表
思考:我已读取文件内容。现在需要总结要点。内容显示这是一个项目报告草案,包含主要内容和待办事项(整理图表)。我可以直接总结。
最终答案:该文件是一个项目报告草案,主要内容已列出,当前待办事项是整理图表。

任务1结果:该文件是一个项目报告草案,主要内容已列出,当前待办事项是整理图表。

=== 测试任务 2:查询数据库 ===
> 进入新的 Agent 执行链...
思考:用户需要查询工程部员工。我需要使用 SQLite 查询工具。
行动:sqlite_execute_query
行动输入:{"query": "SELECT name, email FROM users WHERE department = '工程部'"}
观察:[{"name": "张三", "email": "zhangsan@example.com"}]
思考:查询返回了结果。我可以直接给出答案。
最终答案:工程部的员工是张三,邮箱是 zhangsan@example.com。

任务2结果:工程部的员工是张三,邮箱是 zhangsan@example.com。

从输出中,我们可以看到 Agent 成功完成了以下工作:

  1. 动态工具发现 :启动时从两个 MCP 服务端获取了 4 个工具。
  2. 正确工具选择 :针对“读文件”任务,选择了 filesystem_read_file ;针对“查数据库”任务,选择了 sqlite_execute_query
  3. 参数构造 :能够根据任务描述,正确构造工具所需的输入参数(如文件路径、SQL 语句)。
  4. 结果解析与总结 :能够理解工具返回的原始数据(文本行、JSON 数组),并将其组织成自然语言回答。

4.3 关键配置参数解析

在构建 Agent 时,有几个关键参数直接影响其行为和性能:

参数 所在位置 含义与影响 推荐值/建议
max_iterations AgentExecutor 代理最大推理-执行循环次数。防止任务过于复杂导致无限循环。 简单任务 5-10,复杂任务 15-20。需结合 max_tokens 考虑。
handle_parsing_errors AgentExecutor 是否处理模型输出格式解析错误。开启后,解析失败会尝试让模型重试。 建议始终设为 True ,提高鲁棒性。
verbose AgentExecutor 是否打印详细的思考链(Chain of Thought)日志。 开发调试时设为 True ,生产环境设为 False
temperature ChatAnthropic 模型生成文本的随机性。值越高,输出越多样、越有创造性。 Agent 工具调用场景建议设为 0 0.1 ,以保证工具选择和参数生成的稳定性。
model ChatAnthropic 使用的 Claude 模型版本。 claude-3-haiku 速度最快,成本最低; claude-3-sonnet 平衡; claude-3-opus 能力最强但最慢最贵。根据任务复杂度选择。

5. 常见问题排查与性能优化

将 LangChain Agent 与 MCP、Skills 集成到生产环境时,会遇到一系列工程化挑战。以下是典型问题的排查路径和优化建议。

5.1 连接与工具发现失败

现象 :Agent 启动时报错,无法连接到 MCP 服务端,或工具列表为空。

可能原因 检查方式 解决方案
MCP 服务端未启动 检查对应端口(如 8001, 8002)是否在监听 ( netstat -an | grep 8001 )。查看 MCPServerManager 日志是否有启动错误。 确保启动命令正确,依赖已安装。检查服务端二进制文件路径。
命令或参数错误 检查 StdioServerParameters 中的 command args 是否与服务端程序匹配。 使用绝对路径指定命令,或确保命令在系统 PATH 中。参考服务端文档确认参数格式。
权限问题 检查服务端是否有权限访问指定目录(如 ./data )或数据库文件。 调整目录权限,或使用服务端可访问的路径。
协议版本不兼容 查看 MCP 客户端和服务端的版本。检查初始化握手阶段的错误信息。 确保客户端和服务端使用的 mcp SDK 版本兼容。可尝试升级到最新稳定版。

5.2 工具调用错误或超时

现象 :Agent 选择了正确的工具,但调用失败或长时间无响应。

问题现象 常见原因 检查方式 处理建议
工具参数格式错误 模型生成的 JSON 参数不符合工具要求。 查看 verbose 日志中的“行动输入”字段。手动用相同参数测试工具。 在提示词中更清晰地描述工具所需的参数格式。使用 Pydantic 模型对工具输入进行校验。
工具执行内部错误 MCP 服务端在处理请求时崩溃或返回错误。 查看 MCP 服务端进程的标准错误输出。 检查服务端日志。确保输入数据(如 SQL 语法、文件路径)有效。在工具包装函数中添加更详细的错误捕获和日志。
网络或进程通信超时 服务端响应慢或进程僵死。 在工具调用代码处添加超时设置。监控服务端资源占用(CPU/内存)。 为异步调用设置 asyncio.wait_for 超时。优化服务端性能,或对耗时工具单独设置更长的超时。
异步上下文冲突 在已有事件循环(如 FastAPI)中同步调用工具导致错误。 观察是否报错 RuntimeError: This event loop is already running 避免在同步函数中直接使用 asyncio.run 。改用 asyncio.create_task 或在主异步上下文中调用工具。重构代码,使整个 Agent 调用链保持异步。

5.3 Agent 逻辑错误与优化

现象 :Agent 陷入循环、选择错误工具、或生成无关内容。

问题 根因分析 优化策略
工具选择不准 1. 工具描述 ( description ) 不够清晰。
2. 提示词未充分指导模型如何选择工具。
3. 工具过多,模型混淆。
1. 优化工具描述 :用自然语言清晰说明工具功能、输入输出示例。例如,将 sqlite_execute_query 描述改为“执行一条 SQL SELECT 查询语句,并返回结果集。输入应为包含 query 键的 JSON 对象。”
2. 改进提示词 :在 PromptTemplate 中加入工具选择范例。
3. 工具分组/路由 :对工具进行分类,先让 Agent 选择大类,再选择具体工具。
无效迭代过多 模型在已经获得答案的情况下,仍继续尝试使用工具。 1. 调整 max_iterations :根据任务复杂度设置合理上限。
2. 使用更好的停止条件 AgentExecutor early_stopping_method 设为 "generate" ,让模型自己决定何时停止。
3. 优化思考链 :在提示词中强调“当你认为已有足够信息回答问题时,可以直接给出最终答案”。
处理复杂任务能力弱 单一 ReAct 代理难以规划冗长或多分支任务。 1. 升级 Agent 类型 :使用 Plan-and-Execute OpenAI Functions 代理,它们更擅长规划。
2. 引入 LangGraph :对于有状态、多分支的工作流,使用 LangGraph 来显式定义状态图和节点逻辑。
3. 任务分解 :在上层设计一个“主控”Agent,负责将复杂任务拆解为子任务,再分发给负责具体工具的“子”Agent。

5.4 生产环境部署建议

在开发环境跑通后,部署到生产环境还需考虑以下方面:

  1. MCP 服务端部署 :不应以简单的子进程方式运行。建议将每个 MCP 服务端部署为独立的容器(Docker)或系统服务(systemd),并配置健康检查、资源限制和自动重启。
  2. 连接管理与池化 :频繁创建销毁到 MCP 服务端的连接开销大。应实现连接池,让多个 Agent 实例共享到同一服务端的稳定连接。
  3. 安全性
    • 工具权限 :严格限制每个 MCP 服务端的权限。例如,文件系统服务端只允许访问特定沙箱目录;数据库服务端使用只读或最小权限账户。
    • 输入验证与清理 :对所有从模型传递给工具的参数进行严格的验证和清理,防止 SQL 注入、路径遍历等攻击。
    • API 密钥管理 :使用安全的秘密管理服务(如 Vault, AWS Secrets Manager)存储和轮换 API 密钥,切勿硬编码在代码或配置文件中。
  4. 可观测性
    • 结构化日志 :记录每个工具调用的详细信息(工具名、输入、输出、耗时、状态)。
    • 链路追踪 :为每个用户会话分配唯一 ID,并贯穿所有的 Agent 思考、工具调用步骤,便于问题排查。
    • 监控指标 :监控 Agent 的请求量、响应时间、工具调用成功率、迭代次数分布等。
  5. 性能与成本
    • 缓存 :对频繁且结果不变的工具调用(如读取静态配置)添加缓存层。
    • 模型选择 :根据任务类型选择合适的模型。简单的工具调用可用 Haiku ,复杂规划可用 Sonnet Opus
    • 限制 Token 消耗 :设置 max_tokens 上限,防止因异常导致生成过长内容而产生高费用。

6. 扩展方向:构建自定义 Skills 与高级工作流

掌握了基础集成后,你可以向两个方向深入:一是创建自己的 Skills,二是构建更复杂的智能工作流。

6.1 开发自定义 MCP 服务端与 Skill

一个 Skill 本质上是一个或多个相关工具的集合,并可能附带一些预设提示词。开发自定义 Skill 的步骤如下:

  1. 定义工具接口 :明确 Skill 要提供哪些功能。
  2. 实现 MCP 服务端 :使用 mcp SDK 实现这些功能,并遵循 MCP 协议暴露它们。
  3. 打包与分发 :将服务端代码和配置打包(如 Docker 镜像、Python 包),方便部署和共享。

以下是一个简单的“天气查询” Skill 的服务端示例:

# weather_mcp_server.py
from mcp.server import Server, NotificationOptions
from mcp.server.models import InitializationOptions
import mcp.server.stdio
import asyncio
from some_weather_lib import get_weather # 假设有一个获取天气的库

async def main():
    # 创建 MCP 服务端
    server = Server("weather-skills")

    @server.list_tools()
    async def handle_list_tools():
        # 公布此服务端提供的工具
        return [
            {
                "name": "get_current_weather",
                "description": "获取指定城市的当前天气情况。",
                "inputSchema": {
                    "type": "object",
                    "properties": {
                        "city": {"type": "string", "description": "城市名称,例如:北京"}
                    },
                    "required": ["city"]
                }
            }
        ]

    @server.call_tool()
    async def handle_call_tool(name: str, arguments: dict):
        if name == "get_current_weather":
            city = arguments.get("city")
            if not city:
                raise ValueError("缺少参数 'city'")
            # 调用实际的外部天气 API
            weather_info = await get_weather(city)
            return [
                {
                    "type": "text",
                    "text": f"{city}的天气:{weather_info['condition']},温度{weather_info['temp']}°C。"
                }
            ]
        else:
            raise ValueError(f"未知工具: {name}")

    # 通过标准输入输出运行服务端
    async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
        await server.run(
            read_stream,
            write_stream,
            InitializationOptions(
                server_name="weather-skills",
                server_version="0.1.0"
            )
        )

if __name__ == "__main__":
    asyncio.run(main())

6.2 使用 LangGraph 编排复杂 Agent 工作流

当任务涉及多个 Agent 协作、状态持久化或条件分支时,LangChain 的基础 AgentExecutor 会显得力不从心。此时,LangGraph 是更强大的选择。它允许你将工作流定义为图(Graph),其中节点可以是 Agent、工具或任何函数,边定义了执行流程。

例如,一个“数据报告生成”工作流可能包含以下节点:

  1. 规划节点 :分析用户请求,拆解为“取数据”、“分析”、“生成图表”、“撰写报告”等子任务。
  2. 数据查询节点 :调用 SQL MCP 工具获取数据。
  3. 分析节点 :调用 Python 计算工具或另一个 LLM 进行数据分析。
  4. 图表生成节点 :调用图表生成 API。
  5. 报告汇编节点 :将数据、分析结果、图表整合成最终报告。

使用 LangGraph,你可以清晰地定义这些节点的执行顺序和条件分支(例如,如果数据为空,则跳过分析节点),并持久化整个工作流的状态,实现更稳健和可调试的复杂 Agent 系统。

通过将 LangChain Agent、MCP 协议和 Skills 模块相结合,我们构建的智能体不再是一个封闭、僵化的系统,而是一个能够动态扩展、灵活组合的开放平台。这种架构使得集成新工具、复用已有能力、以及构建复杂工作流变得前所未有的高效。从简单的文件查询到结合数据库、API 和自定义逻辑的复杂任务,Agent 都能通过统一的协议层进行调度和执行。在向生产环境迈进时,务必关注安全性、可靠性和可观测性,通过连接池、权限控制、结构化日志和监控指标来保障系统的稳定运行。下一步,你可以尝试开发自己的专属 Skills,或者利用 LangGraph 来设计更精巧的多智能体协作流程,从而解锁 AI 应用开发的更大潜力。

「LLM那些事」系列第 4 篇《上下文窗口的边界》,文章连接:https://blog.csdn.net/houwenjin/article/details/163999753。 演示什么:在「预测」Sheet 的黄色格子里输入一句话(默认「来泡一杯」),四个「模型」——分别只统计最后 1 / 2 / 3 / 4 个字的 n-gram 查表——同时预测下一个字。同一个输入,看的上下文越长,候选越少、预测越确定: ┌────────────────┬──────────┬───────────────┬──────┐ │ 只看最后几个字 │ 用的前缀 │ 候选下一字数 │ 预测 │ ├────────────────┼──────────┼───────────────┼──────┤ │ 1 个 │ 杯 │ 3(茶/子/水) │ 模糊 │ ├────────────────┼──────────┼───────────────┼──────┤ │ 2 个 │ 一杯 │ 2(茶/水) │ 收窄 │ ├────────────────┼──────────┼───────────────┼──────┤ │ 3 个 │ 泡一杯 │ 1(茶) │ 确定 │ ├────────────────┼──────────┼───────────────┼──────┤ │ 4 个 │ 来泡一杯 │ 1(茶) │ 确定 │ └────────────────┴──────────┴───────────────┴──────┘
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值