What is @tool?
@tool is the primary way to expose a Python function to a LangChain agent or language model. The decorator inspects the function's type annotations and docstring, generates a JSON schema that describes the function's inputs, and registers the function as a StructuredTool that the model can call by name. The function's docstring becomes the tool's description — the text the model reads to decide when and whether to use the tool, so clear, specific docstrings directly improve tool-calling accuracy.
Type annotations are required for all parameters. Without them, LangChain cannot infer the JSON schema and will raise a ValueError at decoration time. Supported annotation types include Python primitives (str, int, float, bool), Optional[T], List[T], Dict[str, T], and Pydantic BaseModel subclasses (for complex structured inputs). When a parameter is annotated with a Pydantic model, the model can pass a nested JSON object as the argument. The return type annotation is optional but useful for documentation; LangChain does not validate the return value.
Async tools are supported natively: decorate an async function and the resulting tool exposes both synchronous .run() and asynchronous .arun() interfaces. The @tool decorator also accepts a response_format argument: "content" (default) returns the function's return value as a string to be added to the conversation; "content_and_artifact" allows returning a tuple of (string_for_model, artifact_for_code) for cases where you want to pass a large artifact (a DataFrame, an image) separately from the model-facing summary.
Use Cases
- • Web search in agents
- • Database queries
- • API calls
- • File operations
- • Business logic
- • Data transforms
Key Features
- ✓ Schema auto-generation
- ✓ Type validation
- ✓ Docstring metadata
- ✓ Async support
- ✓ Error handling
- ✓ Discovery
When NOT to Use
For simple functions without agent use. Direct calls are simpler.
Notes
Docstring quality directly affects how often the model uses the tool correctly
The model reads the docstring to decide when to call the tool and what arguments to pass. A vague docstring like "Does search" produces poor tool-calling accuracy. A specific one like "Search the web for current information. Use when the user asks about recent events, prices, or facts not in training data" drastically improves selection precision.
Type annotations are required — missing annotations raise ValueError at decoration time
Every parameter must have a Python type annotation. @tool cannot infer a JSON schema from untyped parameters and will raise ValueError: "Could not determine type" at decoration time. For complex structured inputs, annotate with a Pydantic BaseModel subclass.
ToolException is the preferred way to signal tool errors to the model
Raising a standard Python exception inside a @tool function causes the agent to crash unless the exception propagates through a ToolNode with handle_tool_errors=True. Raise ToolException("...") instead — LangChain catches it and returns the error message as a ToolMessage back to the model, allowing it to retry or backtrack.
response_format="content_and_artifact" for returning large data alongside a summary
When a tool returns a large artifact (a DataFrame, a binary file, a rendered image) that you do not want to serialize into the conversation, return a tuple: ("summary text for the model", artifact). Pass response_format="content_and_artifact" to the decorator. The model sees only the summary; the artifact is accessible from the ToolMessage.artifact field in the graph state.
Import
from langchain_core.tools import tool
How to Apply
@tool
def search(query: str) -> str:
"""Search the web."""
return results
Parameters
| Parameter | Type | Default | Purpose |
|---|---|---|---|
| response_format | str | content | Output format |
What It Enables
- ✓ Agents discover and call functions
- ✓ JSON schema auto-generated
- ✓ Docstring becomes description
- ✓ Type validation
Code Examples
Basic tool with type hints
from langchain_core.tools import tool
@tool
def add(x: int, y: int) -> int:
"""Add two integers and return the sum."""
return x + y
Tool with Pydantic schema and custom name
from langchain_core.tools import tool
from pydantic import BaseModel, Field
class SearchInput(BaseModel):
query: str = Field(description="The search query")
max_results: int = Field(default=5, description="Max results to return")
@tool("web_search", args_schema=SearchInput)
def search(query: str, max_results: int = 5) -> str:
"""Search the web and return the top results."""
return run_search(query, max_results)
Async tool for non-blocking HTTP requests
from langchain_core.tools import tool
@tool
async def fetch_data(url: str) -> str:
"""Fetch content from a URL asynchronously."""
async with httpx.AsyncClient() as client:
r = await client.get(url)
return r.text
# Use in async agent
model_with_tools = model.bind_tools([fetch_data])
Integration Patterns
agent = create_agent(model, tools=[add])
llm.bind_tools(tools)
Common Mistakes
❌ @tool def fn(x): pass # No hints
✅ @tool def fn(x: int) -> int: """Desc.""" return x
Related LangChain References
Browse the full LangChain API reference index to explore more classes, methods, and decorators, or start with the LangChain introduction tutorial for end-to-end context on building with @tool and the wider framework.
@tool FAQ
What does @tool do in LangChain?
Register a Python function as an agent-callable tool with auto-generated JSON schema. @tool is the primary way to expose a Python function to a LangChain agent or language model. The decorator inspects the function's type annotations and docstring, generates a JSON schema that describes the function's inputs, and registers the function as a StructuredTool that the model can call by name. The function's docstring becomes the tool's description — the text the model reads to decide when and whether to use the tool, so clear, specific docstrings directly improve t…
Which package provides @tool?
DevShelfHub documents @tool from the langchain_core.tools package. Pin your installed LangChain version and match imports to the snippet on this page.
When should I use @tool?
Use @tool when your LangChain agents, workflows, or pipelines need the behavior described in this guide.
When should I avoid using @tool?
For simple functions without agent use. Direct calls are simpler.
How do I apply @tool in Python?
Apply @tool as a decorator above your function definition. Import it from from langchain_core.tools import tool and annotate the function you want to wrap. See the code examples on this page for a complete working snippet.
Where can I explore more LangChain API reference pages?
Open the LangChain API reference index on DevShelfHub to browse classes, methods, and decorators, each with runnable examples, parameters, common mistakes, and cross-links.