给Agent装上“手脚”:LangChain Tools 定义与使用完全指南

在前一篇博客中,我们认识了AI Agent的核心概念——一个能够自主决策、规划并执行任务的智能体。如果说LLM是Agent的“大脑”,负责思考和推理,那么Tools(工具) 就是Agent的“手脚”,让它能够真正地与世界互动:查询数据库、调用API、执行代码、搜索实时信息。

没有工具的Agent,只是一个能说会道的“理论家”;而装备了工具的Agent,则是一个能动手解决问题的“实干家”。本文将深入LangChain框架,从Tools的本质出发,手把手带你学会如何定义工具、构建Agent并调用它完成实际任务。

1. Tools的本质:给LLM的“说明书”

在LangChain中,Tool的本质是一个封装好的可调用函数,它拥有明确定义的输入和输出,并被传递给聊天模型。模型会根据对话的上下文,自主决定何时调用这个工具,以及应该提供哪些输入参数。

关键在于,LLM本身并不执行代码,它是一个文本生成模型。Tools的存在,充当了LLM与外部世界之间的“桥梁”:LLM通过文本生成一个“调用工具”的指令,LangChain框架负责解析这个指令,执行对应的函数,并将执行结果(文本形式)返回给LLM,LLM再根据结果生成最终的回答。

为了让LLM这个“大脑”能够准确地理解和使用工具,Tools的定义必须遵循两条黄金法则:

  • 类型提示是必需的:函数的参数类型提示(Type Hints)至关重要,它们定义了工具的输入模式(Schema),LLM需要根据这个模式来生成正确的参数。

  • 文档字符串是核心:函数的文档字符串(Docstring)会成为工具的描述,直接帮助LLM理解这个工具是做什么的,以及何时应该使用它。描述越清晰、信息越丰富,LLM调用工具的准确率就越高

2. 在LangChain中定义Tools:从装饰器到Pydantic

LangChain提供了多种方式来定义工具,以适应从简单到复杂的各种需求。

2.1 最简单的方式:@tool装饰器

对于大多数场景,使用@tool装饰器是定义工具最快捷、最优雅的方式。它会自动将函数的名称和文档字符串映射为工具的名称和描述。

@tooldefget_weather(city:str,date:str)->str:""" 根据城市以及日期查询该城市的当天的天气情况 """returnf"该{city}{date}的天气情况是:晴朗"

注意:工具名称建议使用snake_case格式(如web_search),以兼容不同的模型提供商。一些模型对于包含空格或特殊字符的名称可能会报错。

2.2 第三方搜索工具

search=TavilySearch(max_result=5)

2.3 高级模式:使用Pydantic定义复杂输入

当你的工具需要接收复杂或结构化的输入时(比如多个字段,或者有校验规则),可以借助Pydantic来定义输入模型,这能让LLM更准确地理解和生成参数。

# Pydantic定义复杂参数classGetWeatherArgs(BaseModel):"""天气查询参数"""city:str=Field(description="城市名称,如'北京'、'上海'")date:str=Field(description="查询日期,格式为YYYY-MM-DD")# 内部工具@tool(args_schema=GetWeatherArgs)defget_weather(city:str,date:str)->str:"""获取指定城市在指定日期的天气预报"""returnf"{city}{date}天气多云,有下雨的可能性。"

通过这种方式,你为LLM提供的不仅仅是函数名,而是一份完整的、结构化的“API说明书”。

3. 构建Agent:让大脑学会用工具

定义好工具后,下一步就是将它们交给Agent。这就像给一个“大脑”配备了一个“工具箱”。

# 需要预先配置好LLM (例如:OpenAI, ChatAnthropic等)load_dotenv()# 大模型llm=ChatOpenAI(model="qwen3.7-max",api_key=os.getenv("QWEN_API_KEY"),base_url=os.getenv("QWEN_BASE_URL"))# 外部工具search=TavilySearch(max_result=5)# 建立好工具之后,就可以创建智能体了agent=create_agent(model=llm,tools=[get_weather,search],system_prompt="你是一个天气查询助手,只能根据城市以及日期查询该城市当天的天气情况。")

一个agent的流程:

  1. 定义工具
  2. 构建agent
    1. 初始化LLM大模型 models=llm
    2. 使用自定义的工具和第三方工具(tavily search)tool=[]
    3. 系统提示词 system_promot
  3. 调用agent:invoke | stream

4. 调用Agent:发起任务,观察“自主决策”

构建完成后,调用Agent就和调用一个普通的函数一样简单。你所需要做的,就是提出你的目标。

resp=agent.invoke({"messages":[("human","2026-7-8的北京的天气")]})print(resp["messages"][-1].content)

当你运行这段代码时,Agent会展示出它强大的自主决策能力:

  • 思考 (Thought):Agent的“大脑”会首先分析你的问题,意识到需要工具:get_weather

  • 行动 (Action):它会先调用get_weather工具,并传入北京和日期两个参数

  • 观察 (Observation):它接收get_weather返回的结果

通过verbose=True参数,你可以清晰地看到Agent的整个“心路历程”,这就是智能代理最迷人的地方——它不再是一个死板的程序,而是一个会思考、会规划的自主实体。

5. 完整代码

importosfromdotenvimportload_dotenvfromlangchain.toolsimporttoolfrompydanticimportBaseModel,Fieldfromlangchain_openaiimportChatOpenAIfromlangchain_community.tools.tavily_searchimportTavilySearchResultsfromlanggraph.prebuiltimportcreate_react_agent load_dotenv()# 1. 初始化大模型llm=ChatOpenAI(model="qwen3.7-max",api_key=os.getenv("QWEN_API_KEY"),base_url=os.getenv("QWEN_BASE_URL"))# 2. 定义工具@tooldefget_weather(city:str,date:str)->str:"""查询指定城市在指定日期的天气情况。"""returnf"{city}{date}的天气情况是:晴朗"# 3. 第三方工具search=TavilySearchResults(max_results=5)# 4. 构建Agentagent=create_react_agent(model=llm,tools=[get_weather,search],prompt="你是一个天气查询助手,根据城市和日期查询该城市当天的天气情况。")# 5. 调用Agentresp=agent.invoke({"messages":[("human","2026-7-8的北京的天气")]})print(resp["messages"][-1].content)