Skip to content

Tools 工具调用

工具(Tools)扩展了 Agent 的能力——让它们获取实时数据、执行代码、查询外部数据库,以及在真实世界中采取行动。在 LangChain 中,工具就是 Python 函数——带上一些元数据。

定义工具

使用 @tool 装饰器

创建工具最简单的方式是使用 @tool 装饰器。函数名自动成为工具名,文档字符串成为工具描述:

python
from langchain.tools import tool

@tool
def search_database(query: str, limit: int = 10) -> str:
    """搜索客户数据库。

    Args:
        query: 搜索关键词
        limit: 最大返回结果数
    """
    return f"找到 {limit} 条关于 '{query}' 的结果"

@tool 装饰器自动:

  • 使用函数名作为工具名(建议使用 snake_case
  • 使用文档字符串作为工具描述
  • 使用类型注解作为参数 schema

注意:类型注解是必须的,它们定义工具的输入 schema。

自定义工具属性

python
from langchain.tools import tool

# 自定义工具名
@tool("web_search")
def search(query: str) -> str:
    """搜索互联网信息"""
    return f"关于 '{query}' 的搜索结果..."

# 自定义工具描述
@tool("calculator", description="执行算术运算。用于任何数学问题。")
def calc(expression: str) -> str:
    """计算数学表达式"""
    return str(eval(expression))

使用 Pydantic 定义复杂参数

对于更复杂的工具输入,推荐使用 Pydantic 模型:

python
from pydantic import BaseModel, Field
from typing import Literal
from langchain.tools import tool

class WeatherInput(BaseModel):
    """天气查询输入"""
    location: str = Field(description="城市名或坐标")
    units: Literal["celsius", "fahrenheit"] = Field(
        default="celsius",
        description="温度单位偏好"
    )
    include_forecast: bool = Field(
        default=False,
        description="是否包含 5 天预报"
    )

@tool(args_schema=WeatherInput)
def get_weather(location: str, units: str = "celsius", include_forecast: bool = False) -> str:
    """获取当前天气和可选预报"""
    temp = 22 if units == "celsius" else 72
    result = f"{location}当前天气:{temp}度"
    if include_forecast:
        result += "\n未来5天:晴"
    return result

也可以使用 JSON Schema:

python
weather_schema = {
    "type": "object",
    "properties": {
        "location": {"type": "string"},
        "units": {"type": "string"},
        "include_forecast": {"type": "boolean"}
    },
    "required": ["location", "units"]
}

@tool(args_schema=weather_schema)
def get_weather(location: str, units: str = "celsius", include_forecast: bool = False) -> str:
    """获取当前天气和可选预报"""
    ...

将工具传入 Agent

python
from langchain.agents import create_agent
from langchain.tools import tool

@tool
def get_weather(city: str) -> str:
    """获取指定城市的天气"""
    return f"{city}: 晴,22°C"

@tool
def search(query: str) -> str:
    """搜索信息"""
    return f"搜索结果: {query}"

agent = create_agent(
    model="openai:gpt-5.5",
    tools=[get_weather, search],
    system_prompt="你是一个助手,可以使用工具回答问题",
)

工具运行时上下文 (ToolRuntime)

工具最强大的地方在于它们可以访问运行时信息——对话历史、用户数据、持久化记忆。通过 ToolRuntime 参数实现:

ToolRuntime 提供以下组件:

组件说明
State短期记忆——当前会话的可变数据(消息、计数器、自定义字段)
Context上下文数据——通过 create_agentcontext 参数传入的应用数据
Store长期记忆——跨会话持久化的用户数据和知识
python
from langchain.tools import tool
from langchain.tools import ToolRuntime

@tool
def get_user_info(runtime: ToolRuntime) -> str:
    """获取当前用户信息"""
    user_id = runtime.context.user_id
    name = runtime.store.get(("users", user_id), "name")
    return f"用户: {name}, ID: {user_id}"

@tool
def record_purchase(item: str, amount: float, runtime: ToolRuntime) -> str:
    """记录用户的购买行为"""
    user_id = runtime.context.user_id
    history = runtime.store.get(("users", user_id), "purchases")
    purchases = history.value if history else []
    purchases.append({"item": item, "amount": amount})
    runtime.store.put(("users", user_id), "purchases", purchases)
    return f"已记录购买:{item} ¥{amount}"

保留参数名

以下参数名是保留的,不能用作工具参数:

参数名用途
config内部传参 RunnableConfig
runtimeToolRuntime 参数(访问状态、上下文、存储)

如果你使用 InjectedStateInjectedStoreget_runtime()InjectedToolCallId 等旧版注入模式,请迁移到 ToolRuntime 参数。

动态工具选择

你可以在运行时通过 Middleware 动态限制 Agent 可用的工具子集:

python
from langchain.agents import create_agent
from langchain.agents.middleware import LLMToolSelectorMiddleware

agent = create_agent(
    model="openai:gpt-5.5",
    tools=[get_weather, search, calculator, send_email],
    middleware=[
        LLMToolSelectorMiddleware(
            # 根据输入内容自动选择合适工具
            selector="auto",
        )
    ],
)

或者直接在 create_agent 中传入不同工具集:

python
# 只包含部分工具
tools_limited = [get_weather, search]
agent_limited = create_agent(
    model="openai:gpt-5.5",
    tools=tools_limited,
)

服务端工具

部分模型提供商(如 OpenAI、Google)内置了服务端工具(Web 搜索、代码解释器),这些工具由模型端执行:

python
from langchain.agents import create_agent

# OpenAI 内置 Web 搜索
agent = create_agent(
    model="openai:gpt-5.5",
    tools=[{"type": "web_search"}],  # 服务端工具
)

# Google 内置 Web 搜索
agent = create_agent(
    model="google_genai:gemini-3.5-flash",
    tools=[{"type": "web_search"}],
)

工具命名规范

  • 使用 snake_case 命名(如 web_search 而非 Web Search
  • 某些模型提供商可能拒绝包含空格或特殊字符的工具名
  • 建议只使用字母、数字、下划线和连字符

最佳实践

  1. 工具描述要清晰:描述应该让模型准确理解工具用途和使用时机
  2. 参数类型要具体:使用精确的类型注解,让模型正确填写参数
  3. 避免参数名冲突:不要使用 configruntime 作为参数名
  4. 错误处理:工具内部做好异常捕获,返回友好的错误信息
  5. 幂等设计:工具应尽量设计为可重复安全执行

下一步

本站为非官方中文学习站点,不代表 LangChain 官方。部分内容参考官方文档并重新整理为中文学习笔记。