4.8 KiB
4.8 KiB
Tool Definition
How to define tools and design patterns.
Basic Definition
from langchain_core.tools import tool
@tool
def search(query: str) -> str:
"""Perform a web search.
Args:
query: Search query
"""
return perform_search(query)
Key Elements
1. Docstring
Description for the LLM to understand the tool:
@tool
def get_weather(location: str, unit: str = "celsius") -> str:
"""Get the current weather for a specified location.
This tool provides up-to-date weather information for cities around the world.
It includes detailed information such as temperature, humidity, and weather conditions.
Args:
location: City name (e.g., "Tokyo", "New York", "London")
unit: Temperature unit ("celsius" or "fahrenheit"), default is "celsius"
Returns:
A string containing weather information
Examples:
>>> get_weather("Tokyo")
"Tokyo weather: Sunny, Temperature: 25°C, Humidity: 60%"
"""
return fetch_weather(location, unit)
2. Type Annotations
Explicitly specify parameter and return value types:
from typing import List, Dict
@tool
def search_products(
query: str,
max_results: int = 10,
category: str | None = None
) -> List[Dict[str, any]]:
"""Search for products.
Args:
query: Search keywords
max_results: Maximum number of results
category: Category filter (optional)
"""
return database.search(query, max_results, category)
Structured Output
Structured output using Pydantic models:
from pydantic import BaseModel, Field
class WeatherInfo(BaseModel):
temperature: float = Field(description="Temperature in Celsius")
humidity: int = Field(description="Humidity (%)")
condition: str = Field(description="Weather condition")
location: str = Field(description="Location")
@tool(response_format="content_and_artifact")
def get_detailed_weather(location: str) -> tuple[str, WeatherInfo]:
"""Get detailed weather information.
Args:
location: City name
"""
data = fetch_weather_data(location)
weather = WeatherInfo(
temperature=data["temp"],
humidity=data["humidity"],
condition=data["condition"],
location=location
)
summary = f"{location} weather: {weather.condition}, {weather.temperature}°C"
return summary, weather
Best Practices for Tool Design
1. Single Responsibility
# Good: Does one thing well
@tool
def send_email(to: str, subject: str, body: str) -> str:
"""Send an email"""
# Bad: Multiple responsibilities
@tool
def send_and_log_email(to: str, subject: str, body: str, log_file: str) -> str:
"""Send an email and log it"""
# Two different responsibilities
2. Clear Parameters
# Good: Clear parameters
@tool
def book_meeting(
title: str,
start_time: str, # "2024-01-01 10:00"
duration_minutes: int,
attendees: List[str]
) -> str:
"""Book a meeting"""
# Bad: Ambiguous parameters
@tool
def book_meeting(data: dict) -> str:
"""Book a meeting"""
3. Error Handling
@tool
def divide(a: float, b: float) -> float:
"""Divide two numbers.
Args:
a: Dividend
b: Divisor
Raises:
ValueError: If b is 0
"""
if b == 0:
raise ValueError("Cannot divide by zero")
return a / b
Dynamic Tool Generation
Automatically generate tools from API schemas:
def create_api_tool(endpoint: str, method: str, description: str):
"""Generate tools from API specifications"""
@tool
def api_tool(**kwargs) -> dict:
f"""
{description}
API Endpoint: {endpoint}
Method: {method}
"""
response = requests.request(
method=method,
url=endpoint,
json=kwargs
)
return response.json()
return api_tool
# Example usage
create_user_tool = create_api_tool(
endpoint="https://api.example.com/users",
method="POST",
description="Create a new user"
)
Grouping Tools
Group related tools together:
# Database tool group
database_tools = [
query_users_tool,
update_user_tool,
delete_user_tool
]
# Search tool group
search_tools = [
web_search_tool,
image_search_tool,
news_search_tool
]
# Select based on context
if user.role == "admin":
tools = database_tools + search_tools
else:
tools = search_tools
Summary
Tool definitions require clear and detailed docstrings, appropriate type annotations, and error handling.
Related Pages
- 04_tool_integration_tool_node.md - Using tools in tool nodes
- 04_tool_integration_command_api.md - Integration with Command API