AI Agent:从工具调用到自主任务执行(实战篇)

0 阅读8分钟

导读:理论再完美,代码跑不通也是白搭。本文是《AI 智能体全景指南》的实战续篇。我们将抛弃繁琐的理论,直接上手,用 Python + LangChain 1.0 + MCP 构建一个能自主规划、多工具协作的“旅行规划助手”。

你将学到

  1. 如何手写一个标准的 MCP Server(让 AI 拥有新技能)。
  2. 如何使用 LangChain 1.0 最新语法构建 Agent。
  3. 如何实现 ReAct 模式,让 AI 自动拆解任务、循环调用工具。
  4. 完整可运行代码,复制粘贴即可体验。

🎯 实战目标:打造“智能旅行规划师”

场景描述: 用户只需输入:“我想去北京玩 3 天,预算 5000 元,帮我查下天气、推荐景点并计算总花费。”

Agent 需要自主完成

  1. 思考:识别出需要“查天气”、“搜景点”、“算账”三个步骤。

  2. 行动

    • 调用 get_weather (MCP 工具) 查询北京天气。
    • 调用 search_attractions (MCP 工具) 获取景点列表。
    • 调用 calculate_budget (本地函数) 计算花费。
  3. 反思:如果天气不好,自动调整推荐(如推荐室内景点)。

  4. 交付:输出一份完整的行程单。


🛠️ 环境准备

确保你的 Python 版本为 3.10+ ,并安装以下核心库(基于 2026 年最新生态):

pip install langchain langchain-openai mcp uvicorn fastmcp

注意

  • langchain: 核心编排框架(使用 1.0+ 新版语法)。
  • mcp & fastmcp: 用于快速构建 MCP 服务器。
  • uvicorn: 用于运行 MCP 服务(如果使用 SSE 模式)。

你需要一个 OpenAI API Key (或兼容的 LLM Key),并在终端导出:

export OPENAI_API_KEY="sk-..."

第一步:构建 MCP Server(制造工具)

在旧模式下,我们需要为每个工具写适配代码。现在,我们利用 MCP 协议,将工具标准化。我们将创建一个包含“天气查询”和“景点搜索”的 MCP 服务。

新建文件 travel_mcp_server.py

# travel_mcp_server.py
from mcp.server.fastmcp import FastMCP
import random
​
# 初始化 MCP 服务器
mcp = FastMCP("TravelAssistantServer")
​
@mcp.tool()
def get_weather(city: str) -> str:
    """
    查询指定城市的天气情况。
    Args:
        city: 城市名称,例如 '北京', '上海'
    Returns:
        天气描述字符串
    """
    # 模拟真实 API 调用
    weathers = ["晴朗", "多云", "小雨", "大雨", "雪"]
    temp = random.randint(10, 30)
    status = random.choice(weathers)
    return f"{city}今天天气{status},气温{temp}摄氏度。"@mcp.tool()
def search_attractions(city: str, preference: str = "自然风光") -> list:
    """
    搜索指定城市的旅游景点。
    Args:
        city: 城市名称
        preference: 偏好类型,如 '自然风光', '历史人文', '室内娱乐'
    Returns:
        景点列表
    """
    # 模拟数据库查询逻辑
    db = {
        "北京": {
            "自然风光": ["颐和园", "香山公园"],
            "历史人文": ["故宫", "长城", "天坛"],
            "室内娱乐": ["国家博物馆", "环球影城"]
        },
        "上海": {
            "自然风光": ["外滩", "世纪公园"],
            "历史人文": ["豫园", "中共一大会址"],
            "室内娱乐": ["上海迪士尼", "海洋水族馆"]
        }
    }
    
    # 简单的容错处理
    if city not in db:
        return ["未知城市,无法推荐具体景点,建议查询通用攻略。"]
    
    # 如果偏好不匹配,默认返回第一项
    attractions = db[city].get(preference, list(db[city].values())[0])
    return attractions
​
if __name__ == "__main__":
    # 启动 MCP 服务器 (使用 stdio 模式,适合本地调试)
    # 生产环境通常使用 SSE (http) 模式
    mcp.run()

💡 代码解析

  • 使用 @mcp.tool() 装饰器,普通 Python 函数瞬间变成符合 MCP 协议 的标准工具。
  • 函数文档字符串(Docstring)会被自动提取,作为 LLM 理解工具用法的 Schema
  • 无需关心 HTTP 请求细节,MCP 库会自动处理序列化。

第二步:构建 Agent 客户端(组装大脑)

现在,我们要创建一个 Agent,它能连接到刚才写的 MCP 服务器,并自主使用这些工具。我们将使用 LangChain 1.0create_agentToolNode 模式。

新建文件 agent_runner.py

# agent_runner.py
import asyncio
from langchain_openai import ChatOpenAI
from langchain.agents import create_tool_calling_agent, AgentExecutor
from langchain_core.prompts import ChatPromptTemplate
from langchain_mcp import MCPToolkit  # 假设 langchain-mcp 集成包已可用,或使用标准加载方式
from mcp.client.stdio import stdio_client
from langchain.tools import Tool
​
# --- 1. 连接 MCP Server 并加载工具 ---
async def load_mcp_tools():
    """
    连接到本地运行的 MCP Server 并转换为 LangChain Tools
    """
    tools = []
    # 这里模拟通过 stdio 连接到我们刚才写的 server
    # 在实际生产中,你可能需要配置具体的 command 和 args
    from mcp.client.stdio import StdioServerParameters
    
    server_params = StdioServerParameters(
        command="python",
        args=["travel_mcp_server.py"]
    )
    
    async with stdio_client(server_params) as (read, write):
        from mcp.client.session import ClientSession
        async with ClientSession(read, write) as session:
            await session.initialize()
            # 获取工具列表
            response = await session.list_tools()
            
            langchain_tools = []
            for tool_def in response.tools:
                # 将 MCP 工具定义转换为 LangChain 可调用的对象
                # 这里为了演示简化了转换逻辑,实际需封装调用 session.call_tool
                async def make_func(t_name, t_desc):
                    async def func(**kwargs):
                        async with stdio_client(server_params) as (r, w):
                            async with ClientSession(r, w) as s:
                                await s.initialize()
                                result = await s.call_tool(t_name, kwargs)
                                return str(result.content)
                    return func
                
                tool = Tool(
                    name=tool_def.name,
                    description=tool_def.description,
                    coroutine=make_func(tool_def.name, tool_def.description)
                )
                langchain_tools.append(tool)
            return langchain_tools
​
# --- 2. 定义 Agent 核心逻辑 ---
async def run_agent():
    # 加载工具
    print("🔌 正在连接 MCP 服务器加载工具...")
    tools = await load_mcp_tools()
    print(f"✅ 成功加载 {len(tools)} 个工具: {[t.name for t in tools]}")
​
    # 初始化 LLM (大脑)
    llm = ChatOpenAI(model="gpt-4o", temperature=0)
​
    # 定义 Prompt (赋予角色)
    prompt = ChatPromptTemplate.from_messages([
        ("system", "你是一个专业的旅行规划助手。你需要根据用户的需求,自主调用工具查询天气和景点,并给出合理的建议。如果天气不好,请优先推荐室内活动。"),
        ("human", "{input}"),
        ("placeholder", "{agent_scratchpad}") # 用于存放思考过程
    ])
​
    # 构建 Agent (ReAct 模式)
    # LangChain 1.0 推荐使用 create_tool_calling_agent
    agent = create_tool_calling_agent(llm, tools, prompt)
​
    # 创建执行器 (Executor)
    agent_executor = AgentExecutor(
        agent=agent,
        tools=tools,
        verbose=True, # 开启详细日志,观察思考过程
        handle_parsing_errors=True
    )
​
    # --- 3. 执行任务 ---
    user_query = "我想去北京玩,帮我查下天气,如果下雨就推荐室内景点,否则推荐自然风光,并简单估算一下门票花费(假设每个景点 50 元)。"
    
    print(f"\n👤 用户指令:{user_query}\n")
    print("🤖 Agent 开始思考与执行...\n")
    
    response = await agent_executor.ainvoke({"input": user_query})
    
    print("\n" + "="*50)
    print("📝 最终回复:")
    print(response["output"])
    print("="*50)
​
if __name__ == "__main__":
    asyncio.run(run_agent())

⚠️ 注意: 上面的 load_mcp_tools 函数展示了最核心的连接逻辑。在 2026 年的成熟生态中,langchain-mcp 包通常会提供类似 MCPToolkit.from_server(...) 的一行代码加载方式。上述代码为了展示原理,手动实现了连接过程,确保你在任何环境下都能理解底层发生了什么。


🚀 运行效果演示

在终端运行:

python agent_runner.py

你将看到类似以下的输出(verbose 模式):

🔌 正在连接 MCP 服务器加载工具...
✅ 成功加载 2 个工具: ['get_weather', 'search_attractions']
​
👤 用户指令:我想去北京玩,帮我查下天气,如果下雨就推荐室内景点,否则推荐自然风光,并简单估算一下门票花费(假设每个景点 50 元)。
​
🤖 Agent 开始思考与执行...
​
--- [Thought Step 1] ---
Agent 思考: 用户想去北京。我需要先查天气,根据天气决定推荐什么类型的景点。
Action: get_weather
Action Input: {"city": "北京"}
​
--- [Observation] ---
Tool Output: 北京今天天气小雨,气温 18 摄氏度。
​
--- [Thought Step 2] ---
Agent 思考: 天气是"小雨",根据指令,我应该推荐"室内娱乐"类的景点。
Action: search_attractions
Action Input: {"city": "北京", "preference": "室内娱乐"}
​
--- [Observation] ---
Tool Output: ["国家博物馆", "环球影城"]
​
--- [Thought Step 3] ---
Agent 思考: 找到了两个室内景点。用户要求估算花费,假设每个 50 元。
总共 2 个景点,花费 = 2 * 50 = 100 元。
现在可以生成最终回答了。
​
Final Answer: 
您好!为您查询到北京今天有**小雨**,气温 18℃。
考虑到天气因素,我为您推荐以下**室内景点**1. **国家博物馆**
2. **环球影城**
​
💰 **预算估算**:
按每个景点门票约 50 元计算,两个景点总计约 **100 元**。
祝您在北京旅途愉快,记得带伞哦!☔️
​
==================================================
📝 最终回复:
您好!为您查询到北京今天有**小雨**,气温 18℃... (同上)
==================================================

💡 核心原理解析

这个简单的 Demo 展示了 Agent 自主性 的三个关键点:

  1. 感知与规划 (Perception & Planning)

    • Agent 没有硬编码“先查天气再查景点”的逻辑。
    • 它是通过 LLM 的推理能力,自己意识到“不知道天气就没法决定推荐什么”,从而自主决定第一步调用 get_weather
  2. 动态分支 (Dynamic Branching)

    • 当观察到天气是“小雨”时,Agent 自动调整了下一步策略,将 preference 参数设为“室内娱乐”。
    • 如果是“晴朗”,它会自动改为“自然风光”。这就是 ReAct (Reasoning + Acting) 模式的威力。
  3. 标准化连接 (MCP)

    • travel_mcp_server.pyagent_runner.py 是完全解耦的。
    • 如果你想增加一个“查酒店”的功能,只需在 Server 端加一个 @mcp.tool() 函数,客户端代码完全不用改,Agent 会自动发现新工具并学会使用它。

🌟 进阶:如何扩展到生产级?

这个 Demo 只是起点。在 2026 年的生产环境中,你还需要考虑:

  1. 记忆模块 (Memory)

    • 引入 ConversationBufferMemory 或向量数据库,让 Agent 记住用户之前的偏好(如“我不喜欢爬山”)。
  2. 多 Agent 协作 (Multi-Agent)

    • 使用 LangGraph 编排多个 Agent。例如:一个“搜索 Agent”负责查资料,一个“财务 Agent”负责算账,一个“写作 Agent”负责生成报告。
  3. 人类反馈 (Human-in-the-loop)

    • 在执行敏感操作(如“支付退款”)前,暂停执行,请求人类确认。
  4. 部署 MCP Server

    • 将 MCP Server 部署为 SSE (Server-Sent Events) 模式,挂在 Docker 容器中,供多个 Agent 实例远程调用。

📝 总结

通过这篇实战,我们完成了从 0 到 1 的突破:

  • ✅ 理解了 MCP 如何让工具开发变得像写普通函数一样简单。
  • ✅ 掌握了 LangChain 构建自主 Agent 的核心流程。
  • ✅ 见证了 AI 从“被动问答”到“主动规划”的质变。

下一步行动: 尝试修改 travel_mcp_server.py,接入真实的 API(如高德地图、OpenWeather),让你的 Agent 真正具备改变现实世界的能力!


欢迎关注的我的公众号《码上未来》,一起交流AI前沿技术!

码上未来.jpg

扫码二维码加我微信进群聊AI

image.png