LangChain Agent 详解

本文详细介绍了 LangChain 中 Agent(智能体)的核心概念、ReAct 推理模式、create_agent 高级 API 的使用方法,以及 Agent-to-Agent(A2A)多智能体协作架构。通过电商助手、天气查询助手和出行规划三个实战案例,帮助读者全面掌握 Agent 的开发流程。


目录

  1. 什么是 Agent

  2. Agent vs 传统链式调用

  3. ReAct 推理模式

  4. create_agent 高级 API

  5. Agent 核心组件

  6. 实战案例一:ReAct 电商助手

  7. 实战案例二:结构化输出天气助手

  8. 实战案例三:A2A 多智能体协作

  9. A2A 协作架构设计

  10. 工具封装规范

  11. 常见问题与解决方案


1. 什么是 Agent

1.1 概念定义

Agent(智能体) 是一种能够自主决策、调用工具、执行复杂任务的 AI 系统。与传统固定流程的链式调用不同,Agent 具有以下核心能力:

能力 说明
自主决策 根据用户输入决定是否需要调用工具、调用哪些工具
工具调用 能够使用外部工具(搜索、数据库、API 等)完成特定任务
推理思考 采用 ReAct 等模式进行多步推理,逐步接近目标答案
动态规划 根据中间结果调整下一步行动
传统链式调用:  输入 → 固定流程 → 输出(线性执行)
     Agent:   输入 → 推理(Reason) → 行动(Act) → 观察 → 推理... → 输出(循环执行)

1.2 Agent 的工作流程

用户提问: "查找最受欢迎的游戏鼠标,检查是否有库存"
                    │
                    ▼
┌─────────────────────────────────────┐
│  Step 1: Reason(推理)              │
│  "用户想要找游戏鼠标,需要先搜索产品,  │
│   然后检查库存"                       │
└─────────────────────────────────────┘
                    │
                    ▼
┌─────────────────────────────────────┐
│  Step 2: Act(行动)                 │
│  调用 search_products("游戏鼠标")     │
└─────────────────────────────────────┘
                    │
                    ▼
┌─────────────────────────────────────┐
│  Step 3: Observe(观察)              │
│  获得搜索结果:罗技 G Pro 排名第一     │
└─────────────────────────────────────┘
                    │
                    ▼
┌─────────────────────────────────────┐
│  Step 4: Reason(推理)              │
│  "知道了,用户还要求检查库存"         │
│  "需要调用 check_inventory(GPW)"     │
└─────────────────────────────────────┘
                    │
                    ▼
┌─────────────────────────────────────┐
│  Step 5: Act(行动)                 │
│  调用 check_inventory("GPW")         │
└─────────────────────────────────────┘
                    │
                    ▼
┌─────────────────────────────────────┐
│  Step 6: Final(最终回答)            │
│  综合所有工具结果,生成完整回答        │
└─────────────────────────────────────┘

2. Agent vs 传统链式调用

2.1 传统链式调用特点

# 传统 LCEL 链式调用
rag_chain = (
    {"context": retriever, "question": RunnablePassthrough()}
    | prompt
    | llm
)
特性 说明
固定流程 检索 → 组装 Prompt → 生成,顺序固定
无工具调用 无法访问外部系统(搜索、数据库等)
一次执行 不支持循环推理和多步决策
适合场景 RAG 问答、简单文本处理

2.2 Agent 的优势

特性 说明
动态决策 根据中间结果决定下一步行动
工具调用 支持任意数量和类型的外部工具
循环推理 支持 ReAct 循环,直到获得完整答案
自适应 根据问题复杂度自动调整调用次数
适合场景 复杂问答、多步骤任务、跨系统协作

2.3 简单对比

场景: 查询 "北京今天天气如何"
​
传统链式调用:
  → 直接回答(模型自己的知识,可能不准确或无最新数据)
​
Agent 方式:
  → 推理:需要调用天气工具
  → 行动:调用 get_weather("Beijing")
  → 观察:获取到 {temp: 25, condition: "晴"}
  → 回答:今天北京天气晴,气温25°C

3. ReAct 推理模式

3.1 什么是 ReAct

ReAct = Reason + Act 是一种结合推理和行动的 AI 框架,让模型能够像人类一样边想边做:

  • Reason(推理): 分析当前状态,决定下一步做什么

  • Act(行动): 执行具体动作(调用工具)

  • Observe(观察): 获取行动结果

  • 循环: 重复直到得到最终答案

3.2 ReAct 工作流程图

┌──────────────────────────────────────────────────────────────┐
│                        ReAct 循环                             │
├──────────────────────────────────────────────────────────────┤
│                                                              │
│   ┌──────────┐    ┌──────────┐    ┌──────────┐               │
│   │  推理    │ →  │  行动    │ →  │  观察    │               │
│   │ Reason   │    │   Act    │    │ Observe  │               │
│   └──────────┘    └──────────┘    └──────────┘               │
│        ↑                                            │        │
│        └────────────────────────────────────────────┘        │
│                                                              │
│   循环直到:得到完整答案 / 达到最大迭代次数 / 判定无法回答      │
│                                                              │
└──────────────────────────────────────────────────────────────┘

3.3 ReAct 示例解析

用户问题: "查找当前最受欢迎的鼠标并检查是否有库存"

🔄 步骤1: Reasoning + Acting
   🛠️ 工具调用: search_products({"query": "游戏鼠标"})
   📋观察结果: 找到5个匹配产品:
      1. 罗技 G Pro 无线 (GPW) - 受欢迎度: 90%
​
🔄 步骤2: Reasoning + Acting
   🛠️ 工具调用: check_inventory({"product_id": "GPW"})
   📋观察结果: GPW: 有库存 (8件)
​
✅ 最终回答: 当前最受欢迎的游戏鼠标是罗技 G Pro 无线(GPW),
   受欢迎度达90%,目前有库存8件。

4. create_agent 高级 API

4.1 API 概述

create_agent 是 LangChain 1.0+ 提供的高级 API,用于快速创建 Agent 实例,相比旧版 create_tool_calling_agent + AgentExecutor 的方式更加简洁。

from langchain.agents import create_agent
​
agent = create_agent(
    model,              # 大模型实例(ChatOpenAI 等)
    tools,              # 工具列表
    system_prompt,       # 系统提示词
    response_format,     # 可选:结构化输出格式
    **kwargs            # 其他参数
)

4.2 核心参数说明

参数 类型 必填 说明
model BaseChatModel 大模型实例,支持 ChatOpenAI、DashScope 等
tools List[BaseTool] Agent 可调用的工具列表
system_prompt str 系统提示词,定义 Agent 角色和行为
response_format TypedDict 结构化输出格式,指定输出字段类型

4.3 调用 Agent

# 单轮对话
result = agent.invoke({
    "input": "用户问题"
})
​
# 多轮对话
result = agent.invoke({
    "messages": [{"role": "user", "content": "用户问题"}]
})

4.4 返回结果结构

{
    "messages": [...],                    # 对话历史(包含推理过程)
    "structured_response": {...},         # 结构化输出(如果指定了 response_format)
    "output": "最终回答内容"              # 最终文本回答
}

5. Agent 核心组件

5.1 组件一览

┌─────────────────────────────────────────────────────────┐
│                       Agent                              │
├─────────────────────────────────────────────────────────┤
│                                                          │
│  ┌─────────────┐    ┌─────────────┐    ┌─────────────┐ │
│  │   Model     │ +  │   Tools     │ +  │ System      │ │
│  │  (大模型)   │    │  (工具集)    │    │ Prompt      │ │
│  └─────────────┘    └─────────────┘    └─────────────┘ │
│          │                │                │            │
│          └────────────────┼────────────────┘            │
│                           ▼                              │
│                  ┌─────────────────┐                     │
│                  │  ReAct 推理引擎  │                     │
│                  └─────────────────┘                     │
│                           │                              │
│                           ▼                              │
│                  ┌─────────────────┐                     │
│                  │    执行结果       │                     │
│                  │ (文本/结构化)     │                     │
│                  └─────────────────┘                     │
│                                                          │
└─────────────────────────────────────────────────────────┘

5.2 Model(模型)

Agent 的大脑,负责推理和决策。通常使用功能强大的大语言模型:

from langchain_openai import ChatOpenAI
​
model = ChatOpenAI(
    model="qwen-plus",
    api_key=os.getenv("aliQwen-api"),
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)

5.3 Tools(工具)

Agent 的手脚,通过 @tool 装饰器定义:

from langchain_core.tools import tool
​
@tool
def search_products(query: str) -> str:
    """搜索产品并返回按受欢迎度排序的结果"""
    # 工具实现逻辑
    return result

5.4 System Prompt(系统提示词)

Agent 的行为准则,决定 Agent 的角色定位和执行策略:

system_prompt="""
你是电商助手,遵循ReAct模式:
1. 先推理用户需求
2. 选择合适的工具执行操作
3. 基于工具结果进行下一步推理
4. 重复直到获得完整答案
​
保持推理步骤简洁明了。"""

6. 实战案例一:ReAct 电商助手

6.1 案例概述

功能: 模拟电商场景,用户可以搜索产品、检查库存,Agent 自动决定调用顺序。

核心工具:

  • search_products: 搜索产品(支持关键词映射)

  • check_inventory: 检查产品库存

6.2 代码结构分析

# ===================== 1. 环境配置 =====================
model = ChatOpenAI(
    model="qwen-plus",
    api_key=os.getenv("aliQwen-api"),
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)
​
# ===================== 2. 数据模拟 =====================
PRODUCT_DATABASE = {...}   # 产品数据库
INVENTORY_DATABASE = {...} # 库存数据库
​
# ===================== 3. 工具定义 =====================
@tool
def search_products(query: str) -> str:
    """搜索产品并返回按受欢迎度排序的结果"""
    # 关键词映射,支持多种中文表达
    keyword_mapping = {
        "无线耳机": ["无线耳机", "蓝牙耳机", "头戴式耳机", "耳机"],
        "游戏鼠标": ["游戏鼠标", "电竞鼠标", "鼠标"],
        ...
    }
    # 搜索并按受欢迎度排序
    return result
​
@tool
def check_inventory(product_id: str) -> str:
    """检查特定产品的库存状态"""
    return result
​
# ===================== 4. 创建 Agent =====================
agent = create_agent(
    model,
    tools=[search_products, check_inventory],
    system_prompt="""你是电商助手,遵循ReAct模式:..."""
)
​
# ===================== 5. 调用 Agent =====================
result = agent.invoke({
    "messages": [{"role": "user", "content": "查找当前最受欢迎的鼠标并检查是否有库存"}]
})

6.3 关键词映射机制

为了让搜索更智能,代码实现了关键词映射:

keyword_mapping = {
    "无线耳机": ["无线耳机", "蓝牙耳机", "头戴式耳机", "耳机"],
    "游戏鼠标": ["游戏鼠标", "电竞鼠标", "鼠标"],
    "笔记本电脑": ["笔记本电脑", "笔记本", "手提电脑", "电脑"]
}
​
# 用户输入 "鼠标" → 匹配到 "游戏鼠标" 类别 → 返回游戏鼠标列表

6.4 ReAct 循环追踪

def track_react_cycle(messages):
    print("ReAct循环步骤分析:")
    step = 1
    for msg in messages:
        msg_type = msg.__class__.__name__
        if msg_type == "AIMessage" and msg.tool_calls:
            print(f"\n🔄 步骤{step}: Reasoning + Acting")
            for tool_call in msg.tool_calls:
                print(f"   🛠️  工具调用: {tool_call['name']}({tool_call['args']})")
            step += 1
        elif msg_type == "ToolMessage":
            print(f"   📋  观察结果: {msg.content[:80]}...")
        elif msg_type == "AIMessage" and not msg.tool_calls:
            print(f"\n✅ 最终回答: {msg.content}")

6.5 运行结果示例

🔍 [工具调用] search_products('游戏鼠标')
📦 [工具调用] check_inventory('GPW')
​
========================================
📊 最终结果:
AIMessage: 好的,我来帮你查找最受欢迎的游戏鼠标并检查库存...
​
🔄 步骤1: Reasoning + Acting
   🛠️  工具调用: search_products({'query': '游戏鼠标'})
   📋  观察结果: 找到3个匹配 '游戏鼠标' 的产品:
      1. 罗技 G Pro 无线 (ID: GPW) - 受欢迎度: 90% - ¥129
      2. 雷蛇 Viper V2 Pro (ID: VIPER) - 受欢迎度: 87% - ¥149
      3. 雷蛇 DeathAdder V3 (ID: DAV3) - 受欢迎度: 85% - ¥119
​
🔄 步骤2: Reasoning + Acting
   🛠️  工具调用: check_inventory({'product_id': 'GPW'})
   📋  观察结果: 产品 GPW: 有库存 (8 件库存) - 位置: 仓库-C
​
✅ 最终回答: 当前最受欢迎的游戏鼠标是罗技 G Pro 无线(GPW),
   受欢迎度达90%,目前有库存8件,可以放心购买!

7. 实战案例二:结构化输出天气助手

7.1 案例概述

功能: 查询多个城市的天气并进行对比分析,支持结构化输出。

核心工具:

  • get_weather: 调用 OpenWeather API 查询天气

7.2 结构化输出定义

from typing_extensions import TypedDict
​
class WeatherCompareOutput(TypedDict):
    beijing_temp: float      # 北京温度
    shanghai_temp: float      # 上海温度
    hotter_city: str          # 更热的城市
    summary: str              # 总结说明

7.3 完整代码解析

# ===================== 1. 工具定义 =====================
@tool
def get_weather(loc: str) -> dict:
    """
    查询即时天气函数
​
    :param loc: 必要参数,字符串类型,用于表示查询天气的具体城市名称。
                注意,中国的城市需要用对应城市的英文名称代替,
                例如如果需要查询北京市天气,则 loc 参数需要输入 'Beijing'/'shanghai'。
    :return: OpenWeather API 查询即时天气的结果。
    """
    url = "https://api.openweathermap.org/data/2.5/weather"
    params = {
        "q": loc,
        "appid": os.getenv("OPENWEATHER_API_KEY"),
        "units": "metric",
        "lang": "zh_cn"
    }
    response = httpx.get(url, params=params, timeout=30)
    data = response.json()
    return json.dumps(data, ensure_ascii=False)
​
# ===================== 2. 创建 Agent(带结构化输出)=====================
agent = create_agent(
    model=model,
    tools=[get_weather],
    system_prompt=(
        "你是天气助手。"
        "当用户询问多个城市天气时,"
        "你需要分别调用工具获取数据,并进行比较分析。"
    ),
    response_format=WeatherCompareOutput,  # 指定结构化输出格式
)
​
# ===================== 3. 调用 Agent =====================
result = agent.invoke(
    {"input": "请问今天北京和上海的天气怎么样,哪个城市更热?"}
)
​
# ===================== 4. 获取结构化结果 =====================
print(json.dumps(result["structured_response"], ensure_ascii=False, indent=2))

7.4 返回结果对比

普通文本输出:

今天北京天气晴,气温25℃,上海天气多云,气温28℃。
上海比北京更热。

结构化输出:

{
  "beijing_temp": 25.0,
  "shanghai_temp": 28.0,
  "hotter_city": "上海",
  "summary": "今天北京天气晴,气温25℃,上海天气多云,气温28℃。综合比较,上海更热。"
}

7.5 结构化输出的优势

特性 文本输出 结构化输出
解析难度 需要正则解析 直接使用字典/对象
类型安全 有类型声明,IDE 自动补全
下游处理 复杂 简单,直接访问字段
适合场景 对话式回答 API 调用、程序处理

8. 实战案例三:A2A 多智能体协作

8.1 案例概述

文件: Agent2Agent.py

功能: 模拟完整出行规划流程,跨平台协作(携程订机票 → 美团订酒店 → 滴滴打车)

核心设计: 一个总协调 Agent 调度三个专属业务 Agent

8.2 业务流程图

用户需求: "安排2026年5月5日北京飞上海的完整行程"
​
┌─────────────────────────────────────────────────────────────┐
│                   A2A 多智能体协作流程                        │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  ┌─────────────────┐                                        │
│  │  总协调 Agent   │ ← 用户入口,接收需求                     │
│  └────────┬────────┘                                        │
│           │ 调度                                            │
│     ┌─────┴─────┬───────────────┐                           │
│     ▼           ▼               ▼                           │
│  ┌────────┐ ┌────────┐    ┌────────┐                       │
│  │ 携程   │ │ 美团   │    │ 滴滴   │                       │
│  │ 机票   │ │ 酒店   │    │ 打车   │                       │
│  │ Agent  │ │ Agent  │    │ Agent  │                       │
│  └────┬───┘ └───┬────┘    └────┬───┘                       │
│       │         │              │                            │
│       └─────────┴──────────────┘                            │
│                     │                                        │
│                     ▼                                        │
│            ┌─────────────────┐                               │
│            │  整合最终报告     │                               │
│            └─────────────────┘                               │
│                                                              │
└─────────────────────────────────────────────────────────────┘

8.3 三个专属 Agent 定义

# ===================== 携程 Agent =====================
@tool("CtripBookFlight", description="预订机票的唯一工具...")
def ctrip_book_flight(departure: str, arrival: str, date: str) -> str:
    """携程订机票:固定返回测试结果"""
    return f"【携程机票预订成功】\n航班号:CA1885..."
​
def create_ctrip_agent(llm):
    llm_with_tools = llm.bind_tools([ctrip_book_flight])
    prompt = ChatPromptTemplate.from_messages([
        ("system", "你是专业的工具调用助手,只能调用CtripBookFlight工具..."),
        ("human", "{input}")
    ])
    return prompt | llm_with_tools | output_parser
​
# ===================== 美团 Agent =====================
@tool("MeituanBookHotel", description="预订酒店的唯一工具...")
def meituan_book_hotel(city: str, near_by: str, check_in: str, check_out: str) -> str:
    """美团订酒店:固定返回测试结果"""
    return f"【美团酒店预订成功】\n酒店名称:上海浦东机场铂尔曼大酒店..."
​
def create_meituan_agent(llm):
    llm_with_tools = llm.bind_tools([meituan_book_hotel])
    prompt = ChatPromptTemplate.from_messages([...])
    return prompt | llm_with_tools | output_parser
​
# ===================== 滴滴 Agent =====================
@tool("DidiBookTaxi", description="预约打车的唯一工具...")
def didi_book_taxi(start: str, end: str, time: str) -> str:
    """滴滴打车:固定返回测试结果"""
    return f"【滴滴打车预约成功】\n车型:滴滴快车(舒适型)..."
​
def create_didi_agent(llm):
    llm_with_tools = llm.bind_tools([didi_book_taxi])
    prompt = ChatPromptTemplate.from_messages([...])
    return prompt | llm_with_tools | output_parser

8.4 总协调 Agent

def create_travel_coordinator_agent(llm, ctrip_chain, meituan_chain, didi_chain):
    """总协调:按顺序调用+空值兜底+打印详细测试"""
    def a2a_schedule(input_dict):
        print("🔍 开始执行A2A协作测试,依次调用各业务Agent...\n")
​
        # 1. 携程 Agent 调用
        print("1. 调用【携程机票Agent】>>>")
        try:
            ctrip_result = ctrip_chain.invoke({"input": "订机票"})
        except:
            ctrip_result = ""
        if not ctrip_result.strip():
            ctrip_result = ctrip_book_flight("北京", "上海", "2026-05-05")  # 兜底
        print(f"✅ 携程测试结果:\n{ctrip_result}\n")
​
        # 2. 美团 Agent 调用
        print("2. 调用【美团酒店Agent】>>>")
        try:
            meituan_result = meituan_chain.invoke({"input": "订酒店"})
        except:
            meituan_result = ""
        if not meituan_result.strip():
            meituan_result = meituan_book_hotel("上海", "浦东机场", "2026-05-05", "2026-05-06")
        print(f"✅ 美团测试结果:\n{meituan_result}\n")
​
        # 3. 滴滴 Agent 调用
        print("3. 调用【滴滴打车Agent】>>>")
        try:
            didi_result = didi_chain.invoke({"input": "预约打车"})
        except:
            didi_result = ""
        if not didi_result.strip():
            didi_result = didi_book_taxi("上海浦东机场T2", "上海浦东机场铂尔曼大酒店", "2026-05-05 16:40")
        print(f"✅ 滴滴测试结果:\n{didi_result}\n")
​
        # 整合最终报告
        total_report = f"""
📋 【携程-美团-滴滴 A2A协作测试最终报告】
{'='*90}
📌 测试状态:本地运行成功,所有Agent均返回完整结果(含兜底保障)
📌 协作流程:携程订机票 → 美团订酒店 → 滴滴打车(按业务顺序执行)
{'='*90}
【1. 携程机票预订结果】
{ctrip_result}
【2. 美团酒店预订结果】
{meituan_result}
【3. 滴滴打车预约结果】
{didi_result}
{'='*90}
💡 测试结论:A2A协作逻辑正常,@tool装饰器集成成功,无报错!
"""
        return total_report
​
    return RunnableLambda(a2a_schedule)

8.5 运行结果

🔧 初始化携程/美团/滴滴专属Agent...
✅ 所有Agent初始化完成!
​
🔧 初始化A2A总协调Agent(调度核心)...
✅ 总协调Agent初始化完成!
​
🚀 携程-美团-滴滴 A2A协作测试正式开始 🚀
​
🔍 开始执行A2A协作测试,依次调用各业务Agent...
​
1. 调用【携程机票Agent】>>>
✅ 携程测试结果:
【携程机票预订成功】
出发地:北京
目的地:上海
出行日期:2026-05-05
航班号:CA1885(北京首都T3→上海浦东T2)
起飞时间:14:00
降落时间:16:30
座位:经济舱34A
电子客票号:999-1234567890
​
2. 调用【美团酒店Agent】>>>
✅ 美团测试结果:
【美团酒店预订成功】
城市:上海
位置:浦东机场附近
入住日期:2026-05-05
离店日期:2026-05-06
酒店名称:上海浦东机场铂尔曼大酒店
房型:豪华大床房(含双人自助早餐)
​
3. 调用【滴滴打车Agent】>>>
✅ 滴滴测试结果:
【滴滴打车预约成功】
起点:上海浦东机场T2
终点:上海浦东机场铂尔曼大酒店
用车时间:2026-05-05 16:40
车型:滴滴快车(舒适型)
预估费用:35元(券后立减5元,实付30元)

9. A2A 协作架构设计

9.1 A2A 核心概念

A2A (Agent-to-Agent) 是一种多智能体协作架构,多个专业 Agent 分工合作,共同完成复杂任务。

┌─────────────────────────────────────────────────────────────────┐
│                         A2A 架构图                               │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│    ┌─────────────┐                                              │
│    │  用户入口    │                                              │
│    └──────┬──────┘                                              │
│           │                                                     │
│    ┌──────▼──────┐                                              │
│    │  总协调     │  ← 入口 Agent,控制调度逻辑                     │
│    │  Agent      │                                              │
│    └──────┬──────┘                                              │
│           │                                                     │
│    ┌──────┴──────┬──────────────┐                               │
│    │            │              │                                │
│    ▼            ▼              ▼                                │
│ ┌────────┐ ┌────────┐    ┌────────┐                             │
│ │ 子Agent │ │ 子Agent │    │ 子Agent │                           │
│ │  A      │ │  B      │    │  C      │                           │
│ └────────┘ └────────┘    └────────┘                             │
│    ↑            ↑              ↑                                 │
│    └────────────┴──────────────┘                                 │
│                  │                                               │
│           只与总协调 Agent 通信                                    │
│           子 Agent 之间不直接通信                                  │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

9.2 A2A 设计原则

原则 说明
单一职责 每个子 Agent 只负责一个业务领域
统一接口 所有子 Agent 都是 Runnable 链,对外暴露 invoke() 方法
总协调控制 所有调度由总协调 Agent 控制,子 Agent 之间不直接交互
稳定保障 每个子 Agent 调用加 try-except,对空结果做兜底

9.3 子 Agent 规范

# ✅ 正确:单一职责 + 统一接口
def create_ctrip_agent(llm):
    llm_with_tools = llm.bind_tools([ctrip_book_flight])  # 只绑定一个工具
    prompt = ChatPromptTemplate.from_messages([
        ("system", "你是专业的...只能调用CtripBookFlight工具..."),
        ("human", "{input}")
    ])
    return prompt | llm_with_tools | output_parser  # 统一 Runnable 接口
​
# ❌ 错误:一个 Agent 绑定多个不相关工具
def create_mixed_agent(llm):
    llm_with_tools = llm.bind_tools([ctrip_book_flight, meituan_book_hotel, didi_book_taxi])
    ...

9.4 兜底机制

def a2a_schedule(input_dict):
    try:
        ctrip_result = ctrip_chain.invoke({"input": "订机票"})
    except:
        ctrip_result = ""
​
    # 空结果兜底:调用原始函数
    if not ctrip_result.strip():
        ctrip_result = ctrip_book_flight("北京", "上海", "2026-05-05")
​
    return ctrip_result

兜底原因: 大模型有时无法正确调用工具,直接返回空字符串。兜底机制确保系统稳定运行。


10. 工具封装规范

10.1 @tool 装饰器

LangChain 1.0 推荐使用 @tool 装饰器封装业务函数:

from langchain.core.tools import tool
​
@tool("工具名称", description="工具描述,说明参数和用途")
def my_tool(param1: str, param2: int) -> str:
    """工具的详细说明文档"""
    # 实现逻辑
    return result

10.2 工具描述规范

工具的 description 必须清晰,因为大模型通过描述识别参数:

# ✅ 好的描述:明确参数名、参数类型、说明
@tool("CtripBookFlight", description="预订机票的唯一工具,必须调用,参数是departure出发地、arrival目的地、date出行日期(格式2026-02-01)")
​
# ❌ 差的描述:参数模糊
@tool("CtripBookFlight", description="预订机票的工具")

10.3 参数类型提示

必须为参数添加类型提示,否则结构化调用可能失败:

# ✅ 正确
@tool
def get_weather(loc: str, units: str = "metric") -> dict:
    ...
​
# ❌ 错误
@tool
def get_weather(loc, units="metric"):
    ...

10.4 工具返回格式

建议返回结构化的字符串或字典,便于解析:

# ✅ 结构化返回
@tool
def search_products(query: str) -> str:
    return f"找到 {len(results)} 个产品:\n" + "\n".join([f"{i}. {p['name']}" for i, p in enumerate(results, 1)])
​
# ✅ 字典返回(配合结构化输出)
@tool
def get_weather(loc: str) -> dict:
    return {"temp": 25, "condition": "晴", "humidity": 60}

11. 常见问题与解决方案

11.1 工具调用失败

问题 原因 解决方案
工具未被调用 Prompt 未明确要求 在 system_prompt 中强调"必须调用工具"
调用参数错误 description 不清晰 完善 description,明确参数格式
多次重复调用 Agent 无法判断结束 添加"重复直到获得完整答案后停止"

11.2 Agent 无响应

问题 原因 解决方案
死循环 无法判断结束条件 设置 max_iterations 限制
超时 工具执行时间过长 设置 timeout 或增加超时时间
空返回 模型拒绝调用工具 添加兜底逻辑

11.3 结构化输出问题

问题 解决方案
response_format 报错 确保 typing_extensions.TypedDict 已安装
输出格式不匹配 检查 TypedDict 字段类型是否与大模型输出匹配
部分字段缺失 在 system_prompt 中强调"必须填充所有字段"

11.4 A2A 协作问题

问题 解决方案
子 Agent 不执行 检查总协调 Agent 的调用逻辑
结果丢失 添加 try-except 和兜底机制
执行顺序混乱 使用顺序调用而非并行,确保依赖关系

11.5 调试技巧

# 1. 打印完整消息历史
for msg in result['messages']:
    print(f"{msg.__class__.__name__}: {msg.content}")

# 2. 追踪 ReAct 循环
track_react_cycle(result['messages'])

# 3. 检查工具调用
for msg in result['messages']:
    if hasattr(msg, 'tool_calls'):
        print(f"工具调用: {msg.tool_calls}")

# 4. 结构化输出调试
print(result.get("structured_response", {}))

附录:关键概念速查表

概念 说明
Agent 能够自主决策、调用工具、执行复杂任务的 AI 系统
ReAct Reason + Act 推理模式,边推理边行动
create_agent LangChain 1.0+ 高级 API,快速创建 Agent
@tool 装饰器,用于封装业务函数为 Agent 工具
A2A Agent-to-Agent,多智能体协作架构
总协调 Agent 控制多个子 Agent 调度逻辑的入口 Agent
子 Agent 专注于单一业务领域的专属 Agent
结构化输出 使用 TypedDict 定义输出格式,确保类型安全
RunnableLambda 将普通函数转换为 Runnable 接口
兜底机制 当 Agent 调用失败时,使用原始函数保证系统稳定

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐