*   [](/v0.2/)
*   [How-to guides](/v0.2/docs/how_to/)
*   How to create custom tools

On this page

How to create custom 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, 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 provides 3 ways to create tools:

1.  Using [@tool decorator](https://api.python.langchain.com/en/latest/tools/langchain_core.tools.tool.html#langchain_core.tools.tool) -- the simplest way to define a custom tool.
2.  Using [StructuredTool.from\_function](https://api.python.langchain.com/en/latest/tools/langchain_core.tools.StructuredTool.html#langchain_core.tools.StructuredTool.from_function) class method -- this is similar to the `@tool` decorator, but allows more configuration and specification of both sync and async implementations.
3.  By sub-classing from [BaseTool](https://api.python.langchain.com/en/latest/tools/langchain_core.tools.BaseTool.html) -- This is the most flexible method, it provides the largest degree of control, at the expense of more effort and code.

The `@tool` or the `StructuredTool.from_function` class method should be sufficient for most use cases.

tip

Models will perform better if the tools have well chosen names, descriptions and JSON schemas.

@tool decorator[​](#tool-decorator "Direct link to @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@tooldef 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)

**API Reference:**[tool](https://api.python.langchain.com/en/latest/tools/langchain_core.tools.tool.html)

    multiplymultiply(a: int, b: int) -> int - 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@toolasync def amultiply(a: int, b: int) -> int:    """Multiply two numbers."""    return a * b

**API Reference:**[tool](https://api.python.langchain.com/en/latest/tools/langchain_core.tools.tool.html)

You can also customize the tool name and JSON args by passing them into the tool decorator.

    from langchain.pydantic_v1 import BaseModel, Fieldclass 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-toolmultiplication-tool(a: int, b: int) -> int - Multiply two numbers.{'a': {'title': 'A', 'description': 'first number', 'type': 'integer'}, 'b': {'title': 'B', 'description': 'second number', 'type': 'integer'}}True

StructuredTool[​](#structuredtool "Direct link to StructuredTool")
------------------------------------------------------------------

The `StrurcturedTool.from_function` class method provides a bit more configurability than the `@tool` decorator, without requiring much additional code.

    from langchain_core.tools import StructuredTooldef multiply(a: int, b: int) -> int:    """Multiply two numbers."""    return a * basync def amultiply(a: int, b: int) -> int:    """Multiply two numbers."""    return a * bcalculator = StructuredTool.from_function(func=multiply, coroutine=amultiply)print(calculator.invoke({"a": 2, "b": 3}))print(await calculator.ainvoke({"a": 2, "b": 5}))

**API Reference:**[StructuredTool](https://api.python.langchain.com/en/latest/tools/langchain_core.tools.StructuredTool.html)

    610

To configure it:

    class CalculatorInput(BaseModel):    a: int = Field(description="first number")    b: int = Field(description="second number")def multiply(a: int, b: int) -> int:    """Multiply two numbers."""    return a * bcalculator = StructuredTool.from_function(    func=multiply,    name="Calculator",    description="multiply numbers",    args_schema=CalculatorInput,    return_direct=True,    # coroutine= ... <- you can specify an async method if desired as well)print(calculator.invoke({"a": 2, "b": 3}))print(calculator.name)print(calculator.description)print(calculator.args)

    6CalculatorCalculator(a: int, b: int) -> int - multiply numbers{'a': {'title': 'A', 'description': 'first number', 'type': 'integer'}, 'b': {'title': 'B', 'description': 'second number', 'type': 'integer'}}

Subclass BaseTool[​](#subclass-basetool "Direct link to Subclass BaseTool")
---------------------------------------------------------------------------

You can define a custom tool by sub-classing from `BaseTool`. This provides maximal control over the tool definition, but requires writing more code.

    from typing import Optional, Typefrom langchain.pydantic_v1 import BaseModelfrom langchain_core.callbacks import (    AsyncCallbackManagerForToolRun,    CallbackManagerForToolRun,)from langchain_core.tools import BaseToolclass CalculatorInput(BaseModel):    a: int = Field(description="first number")    b: int = Field(description="second number")class CustomCalculatorTool(BaseTool):    name = "Calculator"    description = "useful for when you need to answer questions about math"    args_schema: Type[BaseModel] = CalculatorInput    return_direct: bool = True    def _run(        self, a: int, b: int, run_manager: Optional[CallbackManagerForToolRun] = None    ) -> str:        """Use the tool."""        return a * b    async def _arun(        self,        a: int,        b: int,        run_manager: Optional[AsyncCallbackManagerForToolRun] = None,    ) -> str:        """Use the tool asynchronously."""        # If the calculation is cheap, you can just delegate to the sync implementation        # as shown below.        # If the sync calculation is expensive, you should delete the entire _arun method.        # LangChain will automatically provide a better implementation that will        # kick off the task in a thread to make sure it doesn't block other async code.        return self._run(a, b, run_manager=run_manager.get_sync())

**API Reference:**[AsyncCallbackManagerForToolRun](https://api.python.langchain.com/en/latest/callbacks/langchain_core.callbacks.manager.AsyncCallbackManagerForToolRun.html) | [CallbackManagerForToolRun](https://api.python.langchain.com/en/latest/callbacks/langchain_core.callbacks.manager.CallbackManagerForToolRun.html) | [BaseTool](https://api.python.langchain.com/en/latest/tools/langchain_core.tools.BaseTool.html)

    multiply = CustomCalculatorTool()print(multiply.name)print(multiply.description)print(multiply.args)print(multiply.return_direct)print(multiply.invoke({"a": 2, "b": 3}))print(await multiply.ainvoke({"a": 2, "b": 3}))

    Calculatoruseful for when you need to answer questions about math{'a': {'title': 'A', 'description': 'first number', 'type': 'integer'}, 'b': {'title': 'B', 'description': 'second number', 'type': 'integer'}}True66

How to create async tools[​](#how-to-create-async-tools "Direct link to How to create async tools")
---------------------------------------------------------------------------------------------------

LangChain Tools implement the [Runnable interface 🏃](https://api.python.langchain.com/en/latest/runnables/langchain_core.runnables.base.Runnable.html).

All Runnables expose the `invoke` and `ainvoke` methods (as well as other methods like `batch`, `abatch`, `astream` etc).

So even if you only provide an `sync` implementation of a tool, you could still use the `ainvoke` interface, but there are some important things to know:

*   LangChain's by default provides an async implementation that assumes that the function is expensive to compute, so it'll delegate execution to another thread.
*   If you're working in an async codebase, you should create async tools rather than sync tools, to avoid incuring a small overhead due to that thread.
*   If you need both sync and async implementations, use `StructuredTool.from_function` or sub-class from `BaseTool`.
*   If implementing both sync and async, and the sync code is fast to run, override the default LangChain async implementation and simply call the sync code.
*   You CANNOT and SHOULD NOT use the sync `invoke` with an `async` tool.

    from langchain_core.tools import StructuredTooldef multiply(a: int, b: int) -> int:    """Multiply two numbers."""    return a * bcalculator = StructuredTool.from_function(func=multiply)print(calculator.invoke({"a": 2, "b": 3}))print(    await calculator.ainvoke({"a": 2, "b": 5}))  # Uses default LangChain async implementation incurs small overhead

**API Reference:**[StructuredTool](https://api.python.langchain.com/en/latest/tools/langchain_core.tools.StructuredTool.html)

    610

    from langchain_core.tools import StructuredTooldef multiply(a: int, b: int) -> int:    """Multiply two numbers."""    return a * basync def amultiply(a: int, b: int) -> int:    """Multiply two numbers."""    return a * bcalculator = StructuredTool.from_function(func=multiply, coroutine=amultiply)print(calculator.invoke({"a": 2, "b": 3}))print(    await calculator.ainvoke({"a": 2, "b": 5}))  # Uses use provided amultiply without additional overhead

**API Reference:**[StructuredTool](https://api.python.langchain.com/en/latest/tools/langchain_core.tools.StructuredTool.html)

    610

You should not and cannot use `.invoke` when providing only an async definition.

    @toolasync def multiply(a: int, b: int) -> int:    """Multiply two numbers."""    return a * btry:    multiply.invoke({"a": 2, "b": 3})except NotImplementedError:    print("Raised not implemented error. You should not be doing this.")

    Raised not implemented error. You should not be doing this.

Handling Tool Errors[​](#handling-tool-errors "Direct link to Handling Tool Errors")
------------------------------------------------------------------------------------

If you're using tools with agents, you will likely need an error handling strategy, so the agent can recover from the error and continue execution.

A simple strategy is to throw a `ToolException` from inside the tool and specify an error handler using `handle_tool_error`.

When the error handler is specified, the exception will be caught and the error handler will decide which output to return from the tool.

You can set `handle_tool_error` to `True`, a string value, or a function. If it's a function, the function should take a `ToolException` as a parameter and return a value.

Please note that only raising a `ToolException` won't be effective. You need to first set the `handle_tool_error` of the tool because its default value is `False`.

    from langchain_core.tools import ToolExceptiondef get_weather(city: str) -> int:    """Get weather for the given city."""    raise ToolException(f"Error: There is no city by the name of {city}.")

**API Reference:**[ToolException](https://api.python.langchain.com/en/latest/tools/langchain_core.tools.ToolException.html)

Here's an example with the default `handle_tool_error=True` behavior.

    get_weather_tool = StructuredTool.from_function(    func=get_weather,    handle_tool_error=True,)get_weather_tool.invoke({"city": "foobar"})

    'Error: There is no city by the name of foobar.'

We can set `handle_tool_error` to a string that will always be returned.

    get_weather_tool = StructuredTool.from_function(    func=get_weather,    handle_tool_error="There is no such city, but it's probably above 0K there!",)get_weather_tool.invoke({"city": "foobar"})

    "There is no such city, but it's probably above 0K there!"

Handling the error using a function:

    def _handle_error(error: ToolException) -> str:    return f"The following errors occurred during tool execution: `{error.args[0]}`"get_weather_tool = StructuredTool.from_function(    func=get_weather,    handle_tool_error=_handle_error,)get_weather_tool.invoke({"city": "foobar"})

    'The following errors occurred during tool execution: `Error: There is no city by the name of foobar.`'

[Edit this page](https://github.com/langchain-ai/langchain/edit/master/docs/docs/how_to/custom_tools.ipynb)

* * *

#### Was this page helpful?

  

#### You can also leave detailed feedback [on GitHub](https://github.com/langchain-ai/langchain/issues/new?assignees=&labels=03+-+Documentation&projects=&template=documentation.yml&title=DOC%3A+%3CPlease+write+a+comprehensive+title+after+the+%27DOC%3A+%27+prefix%3E).

[

Previous

Custom Retriever

](/v0.2/docs/how_to/custom_retriever/)[

Next

How to debug your LLM apps

](/v0.2/docs/how_to/debugging/)

*   [@tool decorator](#tool-decorator)
*   [StructuredTool](#structuredtool)
*   [Subclass BaseTool](#subclass-basetool)
*   [How to create async tools](#how-to-create-async-tools)
*   [Handling Tool Errors](#handling-tool-errors)