Building Custom Tools in CrewAI
In CrewAI, custom tools let your agents call your own Python logic or APIs as first‑class capabilities. You can build them in two main ways: by subclassing BaseTool or by using the @tool decorator, with optional caching and async support.
1. When and Why to Build Custom Tools
Use custom tools when agents need to:
- Call internal APIs (CRM, ticketing, billing, logs).
- Run business logic (pricing, routing, scoring, validation).
- Do specialized I/O (custom DBs, files, internal services).
You define the tool once, then attach it to any agent via tools=[my_tool, ...].
2. Pattern 1 – Subclassing BaseTool
Best when you want strong typing, validation, and full control.
2.1 Basic sync tool with input schema
Key ideas:
- name + description are what the agent sees when deciding to use the tool.
- args_schema (Pydantic) validates inputs and documents parameters.
- _run(...) contains your sync business logic.
You then instantiate and pass it to an agent:
3. Pattern 2 – @tool Decorator (Quick & Concise)
Great for simple tools and rapid prototyping.
- The decorator wraps your function as a Tool object.
- The docstring explains when the agent should call it.
- You attach my_simple_tool directly in tools=[...] on an agent.
4. Adding Caching to Tools
CrewAI lets tools decide when to cache their results via cache_function.
Use this to avoid repeated expensive calls (e.g., slow APIs, large queries).
5. Building Async Tools
Async tools prevent blocking when you do HTTP requests, DB calls, or other I/O.
5.1 Async function with @tool
Simplest async option:
The framework will await this tool in async workflows.
5.2 Async BaseTool subclass (_run + _arun)
Use this when you want both sync and async entry points.
- _run is used in regular (sync) crews.
- _arun is used in async flows / async crew execution.
6. Your approach as “Agentic Architect”
Recap:
- Start with a decorator tool for a toy task (e.g., calculator, date formatter).
- Introduce BaseTool + Pydantic schema for more serious, typed tools (e.g., CRM fetch).
- Add caching for expensive operations and let them tune cache_function.
- Finish with an async web/API tool to show non‑blocking patterns.
The core mindset: you’re not just prompting; you are designing a toolbelt that your agents can intelligently pick from as they work.