How to create tools
When constructing an agent, you will need to provide it with a list of Tool
s that it can use. Besides the actual function that is called, the Tool consists of several components:
Attribute | Type | Description |
---|---|---|
name | str | Must be unique within a set of tools provided to an LLM or agent. |
description | str | Describes what the tool does. Used as context by the LLM or agent. |
args_schema | pydantic.BaseModel | Optional but recommended, and required if using callback handlers. It can be used to provide more information (e.g., few-shot examples) or validation for expected parameters. |
return_direct | boolean | Only relevant for agents. When True, after invoking the given tool, the agent will stop and return the result direcly to the user. |
LangChain supports the creation of tools from:
- Functions;
- LangChain Runnables;
- By sub-classing from BaseTool -- This is the most flexible method, it provides the largest degree of control, at the expense of more effort and code.
Creating tools from functions may be sufficient for most use cases, and can be done via a simple @tool decorator. If more configuration is needed-- e.g., specification of both sync and async implementations-- one can also use the StructuredTool.from_function class method.
In this guide we provide an overview of these methods.
Models will perform better if the tools have well chosen names, descriptions and JSON schemas.
Creating tools from functionsβ
@tool decoratorβ
This @tool
decorator is the simplest way to define a custom tool. The decorator uses the function name as the tool name by default, but this can be overridden by passing a string as the first argument. Additionally, the decorator will use the function's docstring as the tool's description - so a docstring MUST be provided.
from langchain_core.tools import tool
@tool
def multiply(a: int, b: int) -> int:
"""Multiply two numbers."""
return a * b
# Let's inspect some of the attributes associated with the tool.
print(multiply.name)
print(multiply.description)
print(multiply.args)
multiply
Multiply two numbers.
{'a': {'title': 'A', 'type': 'integer'}, 'b': {'title': 'B', 'type': 'integer'}}
Or create an async implementation, like this:
from langchain_core.tools import tool
@tool
async def amultiply(a: int, b: int) -> int:
"""Multiply two numbers."""
return a * b
Note that @tool
supports parsing of annotations, nested schemas, and other features:
from typing import Annotated, List
@tool
def multiply_by_max(
a: Annotated[str, "scale factor"],
b: Annotated[List[int], "list of ints over which to take maximum"],
) -> int:
"""Multiply a by the maximum of b."""
return a * max(b)
multiply_by_max.args_schema.schema()
{'description': 'Multiply a by the maximum of b.',
'properties': {'a': {'description': 'scale factor',
'title': 'A',
'type': 'string'},
'b': {'description': 'list of ints over which to take maximum',
'items': {'type': 'integer'},
'title': 'B',
'type': 'array'}},
'required': ['a', 'b'],
'title': 'multiply_by_maxSchema',
'type': 'object'}
You can also customize the tool name and JSON args by passing them into the tool decorator.
from pydantic import BaseModel, Field
class CalculatorInput(BaseModel):
a: int = Field(description="first number")
b: int = Field(description="second number")
@tool("multiplication-tool", args_schema=CalculatorInput, return_direct=True)
def multiply(a: int, b: int) -> int:
"""Multiply two numbers."""
return a * b
# Let's inspect some of the attributes associated with the tool.
print(multiply.name)
print(multiply.description)
print(multiply.args)
print(multiply.return_direct)
multiplication-tool
Multiply two numbers.
{'a': {'description': 'first number', 'title': 'A', 'type': 'integer'}, 'b': {'description': 'second number', 'title': 'B', 'type': 'integer'}}
True