1.概述

        langchain1.0中的agent是基于langgraph中图构建的,所以一个agent的外部形态与图完全相同,比如调用时传入的数据和响应数据,可以使用长短期记忆,agent还能作为图中的节点。于此同时agent简化了老版本中agent的使用。

      2.创建agent

        以下分步创建一个能访问两个工具的agent,一个搜索工具,一个除法工具。

        首先创建两个工具:

import os
from langchain_tavily import TavilySearch

from langchain.tools import tool
os.environ["TAVILY_API_KEY"] = "tvly-*"
search_tool = TavilySearch(max_results=2)

@tool
def divide(a: int, b:int)->int:
    '''Divide two integers'''
    return 1 / 0
tools = [search_tool, divide]

        然后初始化大模型:

from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
    model = 'qwen-plus',
    api_key = "sk-*",
    base_url = "https://dashscope.aliyuncs.com/compatible-mode/v1")

        创建agent:

from langchain.agents import create_agent
agent = create_agent(
    model=llm,
    tools=tools,
)

     3.工具调用

        agent严格遵循ReAct (推理+行动)模式,在大模型推理和工具调用直接来回切换,并把工具执行结果传递给大模型作为推理的物料,直到最后给出答案。  

        如下例子直观了显示了推理和行动的过程:

state = {"messages":

        [

            {

                "role": "user",

                "content": "find population of north korea and south korea, then calculate ratio

                       between two countrys?"

            }

        ]

 }

for event in agent.invoke(state )['messages']:
    event.pretty_print()

        看看输出结果:

================================ Human Message =================================

find population of north korea and south korea, then calculate ratio between two countrys?
================================== Ai Message ==================================
Tool Calls:
  tavily_search (call_4390975385c04954a90544)
 Call ID: call_4390975385c04954a90544
  Args:
    query: population of North Korea and South Korea 2024
================================= Tool Message =================================
Name: tavily_search

{"query": "population of North Korea and South Korea 2024", "follow_up_questions": null, "answer": null, "images": [], "results": [{"url": "https://countryeconomy.com/countries/compare/south-korea/north-korea?sc=XE23", "title": "Country comparison South Korea vs North Korea Population 2025", "content": "Country comparison South Korea vs North Korea ; Crude marriage rate [+], 2024, 4.40‰ ; Population [+], 2024, 51,751,000 ; Immigrant stock [+], 2020, 1,728,182", "score": 0.8793233, "raw_content": null}, {"url": "https://www.macrotrends.net/global-metrics/countries/prk/north-korea/population", "title": "North Korea Population (1950-2025) - Macrotrends", "content": "## North Korea Population (1950-2025) ##### Total current population for North Korea in 2025 is **26,319,924**, a **0.29% increase** from 2024. * Total population for North Korea in 2024 was **26,244,582**, a **0.66% decline** from 2023. * Total population for North Korea in 2023 was **26,418,204**, a **0.34% increase** from 2022. * Total population for North Korea in 2022 was **26,328,845**, a **0.37% increase** from 2021. ###### Chart The chart has 2 X axes displaying Time, and navigator-x-axis. The chart has 2 Y axes displaying values, and navigator-y-axis. | North Korea Population  Population | | | South Africa | 61,673,081 | | North Korea | 26,319,924 | | Guinea | 14,873,051 | | Papua New Guinea | 10,701,144 |", "score": 0.8742601, "raw_content": null}], "response_time": 1.03, "request_id": "558b6cda-ecb9-4eef-955a-74f320ca3fe2"}
================================== Ai Message ==================================
Tool Calls:
  tavily_search (call_31675128eff442c4bd4203)
 Call ID: call_31675128eff442c4bd4203
  Args:
    query: South Korea population 2024
================================= Tool Message =================================
Name: tavily_search

{"query": "South Korea population 2024", "follow_up_questions": null, "answer": null, "images": [], "results": [{"url": "https://countryeconomy.com/demography/population/south-korea", "title": "South Korea - Population 2024 - countryeconomy.com", "content": "South Korea ended 2024 with a population of 51751000 people, which represents an increasea of 38000 people compared to 2023.", "score": 0.97212255, "raw_content": null}, {"url": "https://tradingeconomics.com/south-korea/population", "title": "South Korea Population - Trading Economics", "content": "The total population in South Korea was estimated at 51.8 million people in 2024, according to the latest census figures and projections from Trading Economics.", "score": 0.96626127, "raw_content": null}], "response_time": 1.65, "request_id": "f4b16b66-1494-45c2-86d1-d46bab653904"}
================================== Ai Message ==================================
Tool Calls:
  divide (call_f39084d0fa9643d2aa4dfc)
 Call ID: call_f39084d0fa9643d2aa4dfc
  Args:
    a: 51751000
    b: 26244582
================================= Tool Message =================================
Name: divide

1.9718736613903776
================================== Ai Message ==================================

Based on the latest available data:

- The population of **South Korea** in 2024 is approximately **51,751,000**.
- The population of **North Korea** in 2024 is approximately **26,244,582**.

To calculate the ratio of South Korea's population to North Korea's population:

$$
\frac{51,751,000}{26,244,582} \approx 1.97
$$

Thus, the ratio of the population of South Korea to North Korea is approximately **1.97:1**. This means South Korea has nearly twice the population of North Korea.
 

        新版本的agent中工具调用功能更加强大,可以:

        1)使用提示词实现对多个工具的串行调用

        2)根据需要可以实现多个工具并行调用

        3)基于运行状态动态选择需要调用的工具

        4)支持工具调用出错重试和错误处理

        5)基于持久化实现跨工具调用的状态共享

     4.处理工具调用错误

        可以对工具执行过程中的错误提示信息进行定制,具体方法如下:

        1)首先定义一个方法,处理工具执行异常,该方法在工具执行出错时被调用

from langchain.agents.middleware import wrap_tool_call
from langchain_core.messages import ToolMessage
@wrap_tool_call
def handle_tool_errors(request, handler):
    """Handle tool execution errors with custom messages."""
    try:
        return handler(request)
    except Exception as e:
        # Return a custom error message to the model
        return ToolMessage(
            content=f"Tool error: Please check your input and try again. ({str(e)})",
            tool_call_id=request.tool_call["id"]
        )

        2)在创建agent是把错误处理方法作为中间件参数传入

agent = create_agent(
    model=llm,
    tools=tools,
    middleware=[handle_tool_errors]
)

        3)模拟错误

        修改divide,在内部计算1/0:

@tool
def divide(a: int, b:int)->int:
    '''Divide two integers'''
    return 1 / 0    

        再次执行,输出如下:

================================ Human Message =================================

find population of north korea and south korea, then calculate ratio between two countrys?
================================== Ai Message ==================================
Tool Calls:
  tavily_search (call_74791527de4d4e42bb0e5e)
 Call ID: call_74791527de4d4e42bb0e5e
  Args:
    query: population of North Korea and South Korea 2024
================================= Tool Message =================================
Name: tavily_search

{"query": "population of North Korea and South Korea 2024", "follow_up_questions": null, "answer": null, "images": [], "results": [{"url": "https://countryeconomy.com/countries/compare/south-korea/north-korea?sc=XE23", "title": "Country comparison South Korea vs North Korea Population 2025", "content": "Country comparison South Korea vs North Korea ; Crude marriage rate [+], 2024, 4.40‰ ; Population [+], 2024, 51,751,000 ; Immigrant stock [+], 2020, 1,728,182", "score": 0.8793233, "raw_content": null}, {"url": "https://www.macrotrends.net/global-metrics/countries/prk/north-korea/population", "title": "North Korea Population (1950-2025) - Macrotrends", "content": "## North Korea Population (1950-2025) ##### Total current population for North Korea in 2025 is **26,319,924**, a **0.29% increase** from 2024. * Total population for North Korea in 2024 was **26,244,582**, a **0.66% decline** from 2023. * Total population for North Korea in 2023 was **26,418,204**, a **0.34% increase** from 2022. * Total population for North Korea in 2022 was **26,328,845**, a **0.37% increase** from 2021. ###### Chart The chart has 2 X axes displaying Time, and navigator-x-axis. The chart has 2 Y axes displaying values, and navigator-y-axis. | North Korea Population  Population | | | South Africa | 61,673,081 | | North Korea | 26,319,924 | | Guinea | 14,873,051 | | Papua New Guinea | 10,701,144 |", "score": 0.8742601, "raw_content": null}], "response_time": 0.0, "request_id": "0d1edfa9-9967-4dc6-a939-d35faeb74813"}
================================== Ai Message ==================================
Tool Calls:
  tavily_search (call_43f90b6d8efe48fcaa2e79)
 Call ID: call_43f90b6d8efe48fcaa2e79
  Args:
    query: South Korea population 2024
================================= Tool Message =================================
Name: tavily_search

{"query": "South Korea population 2024", "follow_up_questions": null, "answer": null, "images": [], "results": [{"url": "https://countryeconomy.com/demography/population/south-korea", "title": "South Korea - Population 2024 - countryeconomy.com", "content": "South Korea ended 2024 with a population of 51751000 people, which represents an increasea of 38000 people compared to 2023.", "score": 0.97212255, "raw_content": null}, {"url": "https://tradingeconomics.com/south-korea/population", "title": "South Korea Population - Trading Economics", "content": "The total population in South Korea was estimated at 51.8 million people in 2024, according to the latest census figures and projections from Trading Economics.", "score": 0.96626127, "raw_content": null}], "response_time": 0.0, "request_id": "90d0ad39-3454-4e81-8b72-37dbe46fd715"}
================================== Ai Message ==================================
Tool Calls:
  divide (call_7b0cb5b71b304780ba728b)
 Call ID: call_7b0cb5b71b304780ba728b
  Args:
    a: 51751000
    b: 26244582
================================= Tool Message =================================

'''这里是定制的错误提示'''

Tool error: Please check your input and try again. (division by zero)
================================== Ai Message ==================================

It seems there was an error in the calculation due to a formatting issue. Let me correct it and calculate the ratio of the population of South Korea to North Korea properly.

Using the data:
- **South Korea population (2024):** 51,751,000
- **North Korea population (2024):** 26,244,582

Now calculating the ratio:  
$$
\text{Ratio} = \frac{51,751,000}{26,244,582} \approx 1.97
$$

So, the population of South Korea is approximately **1.97 times** that of North Korea.

      5.动态选择模型

        与langgraph中的图一样,agent也可以根据上下文选择使用不同的模型,具体实现如下。

        首先,声明一个上下文类,类中有一个provider属性,可以在调用时指定。

from dataclasses import dataclass
from typing import Literal

@dataclass
class CustomContext:
    provider: Literal["qwen", "deepseek"]

          第二,定义模型选择器:

from langchain.agents.middleware import wrap_model_call, ModelRequest, ModelResponse

@wrap_model_call
def dynamic_model_selection(request: ModelRequest, handler) -> ModelResponse:
    provider = request.runtime.context.provider#从上下文获取provider
    if provider == "qwen":
        model = qwen_model
    elif provider == "deepseek":
        model = deepseek_model
    else:
        raise ValueError(f"Unsupported provider: {provider}")
    request.model = model
    return handler(request)

        第三,创建两个大模型:

qwen_model = ChatOpenAI(
    model = 'qwen-plus',
    api_key = "sk-*",
    base_url = "https://dashscope.aliyuncs.com/compatible-mode/v1")
deepseek_model = ChatOpenAI(
    model='deepseek-chat', 
    base_url='https://api.deepseek.com', 
    api_key='sk-*')

        第四,创建agent,并传入模型选择器:

agent = create_agent(
    model=qwen_model,  # Default model
    tools=tools,
    middleware=[dynamic_model_selection]
)

        第五:调用agent,在上下文中传入provider:

for event in agent.invoke( 
    {"messages": 
     [
         {
             "role": "user", 
            "content": "find population of north korea and south korea, then calculate ratio between two countrys?"
         }
     ]
    }
,   context=CustomContext(provider="deepseek"),)['messages']:
    event.pretty_print()

      6.设置提示词

        可以在创建agent时传入系统提示词,限定大模型的行为,比如:

agent = create_agent(

    model,

    tools,

    system_prompt="你是一个精通唐诗的陕西人。." )

        跟动态选择大模型一样,也可以根据上下文动态选择系统提示词,具体实现与动态选择模型非常类似,只不过使用了不同的注解。

#上下文,提供了提示词选择器。在这里就是level

class Context(TypedDict):
    level: str

#使用dynamic_prompt注解下面的方式,作为提示选择器

@dynamic_prompt
def user_level_prompt(request: ModelRequest) -> str:
    """Generate system prompt based on user role."""
    level = request.runtime.context.get("level", "beginner")
    base_prompt = "你是一个精通机器学习方面的专家."

    if user_role == "expert":
        return f"{base_prompt} 解释问题时,提供更多的细节."
    elif user_role == "beginner":
        return f"{base_prompt} 解答问题时,尽量通俗易懂."

    return base_prompt

agent = create_agent(
    model=llm,
    tools=tools,

    #中间件中传入提示词选择器,当然可同时传入模型选择器
    middleware=[user_level_prompt],
    context_schema=Context
)

        在调用时上下文中传入用户的level:

result = agent.invoke(
    {"messages": [{"role": "user", "content": "解释一下朴素贝叶斯算法"}]},
    context={"level": "expert"}

      7.结构化输出

        在langchain老版本中的输出解析器在agent中仍可以使用,当然使用方式有些不同。

        首先定义,输出模式,比如下面的Resume,然后在创建agent时以response_format传入,具体代码如下:

from pydantic import BaseModel
from typing_extensions import TypedDict
from langchain.agents import create_agent

from langchain.agents.structured_output import ToolStrategy
class Resume(TypedDict): #输出格式为JSON
    name: str
    age: str
    phone: str

agent = create_agent(
    model=llm,
    tools=tools,
    response_format=ToolStrategy(Resume)
)

result = agent.invoke({
    "messages": [{"role": "user", "content": "从以下信息中提取Resume信息。我叫宋昌,今年35岁,我的电话号码是13812345678"}]
})

result["structured_response"]

        输出结果如下:

{'name': '宋昌', 'age': '35', 'phone': '13812345678'}

        以上示例的输出是JSON,如果想使用一个标准类输出,则在定义模式时继承BaseModel即可。

      8.agent的记忆

        agent基于graph构建的,所以内置了状态(包括对话历史)作为短期记忆。agent支持对短期记忆进行扩展,保存用户自定义的数据。

        agent在记忆中增加自定义数据有两种方式,一种是通过中间件,一种是通过state_schema参数传入。

        1)通过中间件

        如果需要在特定的中间件或者工具中访问自定义的数据,则必须通过中间件方式注入到agent中。

from langchain.agents import AgentState
from langchain.agents.middleware import AgentMiddleware

#自定义数据
class CustomState(AgentState):
    user_info: dict

#中间件方法

class CustomMiddleware(AgentMiddleware):
    state_schema = CustomState
    tools = tools
    #在调用模型前访问自定义数据,具体实现视具体情况而定
    def before_model(self, state: CustomState, runtime) -> dict[str, Any] | None:
        ...

agent = create_agent(
    model,
    tools=tools,
    middleware=[CustomMiddleware()]
)

# agent可以使用对话历史之外的定制数据
result = agent.invoke({
    "messages": [{"role": "user", "content": "I prefer technical explanations"}],
    "user_info": {"name": "赵无恤", "title": "大将军"},
})

        2)通过state_schema传入

from langchain.agents import AgentState

#自定义数据
class CustomState(AgentState):
    user_info: dict

agent = create_agent(
    model=llm,
    tools=tools,
    state_schema=CustomState#传入自定义数据
)
# agent可以使用对话历史之外的定制数据
result = agent.invoke({
    "messages": [{"role": "user", "content": "I prefer technical explanations"}],
    "user_info": {"name": "赵无恤", "title": "大将军"},
})

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐