What is @tool?
@tool is the fastest path from a Python function to something an Agent can call. CrewAI inspects the function name, docstring, and type annotations to build the tool description and JSON argument schema the LLM sees during planning. That makes small integrations (HTTP lookups, deterministic transforms, database reads) cheap to ship without hand-writing a BaseTool subclass for every helper.
You can optionally pass an explicit display name to @tool and attach richer schemas when the defaults are too lossy, but most teams start with strict primitive annotations and clear docstrings. The docstring is not documentation for humans only — models use it as the primary signal for when to invoke the tool versus answering directly, so phrase constraints, side effects, and units explicitly.
When a tool needs session state, custom async lifecycle hooks, or non-JSON return shapes, prefer subclassing BaseTool so you control serialization, caching, and error surfaces. @tool shines for pure or idempotent callables where failures should bubble back to the agent as natural language errors.
When to Use
Quick tools backed by a single function: API call, math op, lookup.
Use Cases
- • API wrappers
- • Calculators
- • Database lookups
- • Simple utilities
Key Features
- ✓ Auto-builds schema from type hints
- ✓ Docstring becomes description
- ✓ Optional custom name
When NOT to Use
Tools that hold state or need async execution control — subclass BaseTool directly.
Notes
Docstrings steer tool selection
Vague docstrings cause spurious calls or missed calls. Mention required formats, when not to use the tool, and what the return string contains so the planner can ground arguments.
Schema drift across versions
Renaming parameters or loosening types changes the schema agents memorize mid-project. Treat tool signatures like API contracts and version them when behavior changes materially.
Latency and side effects
Agents may retry calls after transient LLM errors. Wrap non-idempotent side effects with idempotency keys or move them behind a dedicated service tool with explicit confirmations.
When to drop down to BaseTool
Need coroutine control, custom args_schema, or structured attachments? Subclass BaseTool so you can document return payloads and handle async clients without blocking the event loop unexpectedly.
Import
from crewai.tools import tool
How to Apply
@tool
def my_tool(arg: str) -> str:
"""What this tool does."""
return result
What It Enables
- ✓ Rapid tool prototyping
- ✓ Typed agent-tool contracts
Code Examples
Search by ID
@tool
def lookup(user_id: str) -> str:
"""Return user record for the given ID."""
return db.get(user_id)
Explicit tool name and bounded query
@tool("Search tickets")
def search_tickets(query: str, limit: int = 5) -> str:
"""Search the support queue; limit caps rows for token safety."""
return jira.search(query, limit=limit)
Structured tool errors
@tool
def refund(order_id: str) -> str:
"""Attempt a refund; returns a human-readable status."""
if not order_id.startswith("ord_"):
raise ValueError("order_id must start with ord_")
return payments.refund(order_id)
Integration Patterns
Agent(tools=[my_tool])
Task(tools=[my_tool])
Common Mistakes
❌ Skipping the docstring
✅ Always write a clear docstring — agents read it to decide whether to call the tool.
Related: Task class reference, Agent class reference, and the first Crew tutorial.
@tool FAQ
What is @tool in CrewAI?
Function decorator that converts a plain Python function into a BaseTool subclass. @tool is the fastest path from a Python function to something an Agent can call. CrewAI inspects the function name, docstring, and type annotations to build the tool description and JSON argument schema the LLM sees during planning. That makes small integrations (HTTP lookups, deterministic transforms, database reads) cheap to ship without hand-writing a BaseTool subclass for every helper. You can optionally pass an explicit display name to @tool and attach richer schemas wh…
Which module defines the CrewAI decorator @tool?
DevShelfHub maps @tool to Python module crewai.tools. Pin your installed crewai version and match imports to the import snippet on this page.
When should I use @tool?
Quick tools backed by a single function: API call, math op, lookup.
When should I avoid @tool?
Tools that hold state or need async execution control — subclass BaseTool directly.
How do I apply @tool in Python?
@tool def my_tool(arg: str) -> str: """What this tool does.""" return result
Where can I explore more CrewAI API reference pages?
Open the CrewAI API reference index on DevShelfHub to search classes, methods, and decorators, each with runnable examples, parameters, common mistakes, and cross-links.