Become an Agentic Architect

Agent Tools in CrewAI

In CrewAI, tools are how agents take real actions: search the web, read files, query databases, run code, or even collaborate with other agents. You attach tools to an agent so it stops being “just a chat model” and becomes a capable worker in your workflow.


1. What Is a Tool?

A tool is a function or skill an agent can call when reasoning is not enough.

Examples:

  • Web search (e.g., SerperDevTool, WebsiteSearchTool).
  • File and directory access (FileReadTool, DirectoryReadTool).
  • RAG over PDFs, CSVs, databases, etc.
  • Code execution and data analysis (CodeInterpreterTool).
  • Collaboration helpers (delegate work, ask coworker).

Key characteristics:

  • Utility – Tools perform concrete actions (search, read, write, scrape, compute).
  • Integration – Tools plug directly into agents via the tools=[...] parameter.
  • Customizability – You can build your own tools for any API or internal system.
  • Error handling – Tools are designed to fail gracefully.
  • Caching – Tools can cache results to avoid repeated expensive calls.
  • Async support – Tools can run asynchronously for non‑blocking IO.

2. Using Built‑In CrewAI Tools

Most common tools live in the crewai_tools package.[web:126][web:116]

2.1 Installation

# bash
pip install "crewai[tools]"

2.2 Example: research + writing workflow

import os
from crewai import Agent, Task, Crew
from crewai_tools import (
    DirectoryReadTool,
    FileReadTool,
    SerperDevTool,
    WebsiteSearchTool,
)

# API keys
os.environ["SERPER_API_KEY"] = "YOUR_SERPER_KEY"
os.environ["OPENAI_API_KEY"] = "YOUR_OPENAI_KEY"

# Tools
docs_tool = DirectoryReadTool(directory="./blog-posts")
file_tool = FileReadTool()
search_tool = SerperDevTool()
web_rag_tool = WebsiteSearchTool()

# Agents
researcher = Agent(
    role="Market Research Analyst",
    goal="Provide up-to-date market analysis of the AI industry",
    backstory="An expert analyst with a keen eye for market trends.",
    tools=[search_tool, web_rag_tool],
    verbose=True,
)

writer = Agent(
    role="Content Writer",
    goal="Craft engaging blog posts about the AI industry",
    backstory="A skilled writer with a passion for technology.",
    tools=[docs_tool, file_tool],
    verbose=True,
)

# Tasks
research = Task(
    description="Research the latest trends in the AI industry and provide a summary.",
    expected_output=(
        "A summary of the top 3 trending developments in the AI industry "
        "with a unique perspective on their significance."
    ),
    agent=researcher,
)

write = Task(
    description=(
        "Write an engaging blog post about the AI industry, based on the research "
        "analyst's summary. Draw inspiration from the latest blog posts in the directory."
    ),
    expected_output=(
        "A 4-paragraph blog post in markdown, engaging and accessible, avoiding jargon."
    ),
    agent=writer,
    output_file="blog-posts/new_post.md",
)

crew = Crew(
    agents=[researcher, writer],
    tasks=[research, write],
    verbose=True,
    planning=True,  # enable planning
)

crew.kickoff()

Here tools let:

  • The researcher pull fresh web data.
  • The writer read prior posts and save a new one to disk.

3. Common Tool Types (High‑Level)

CrewAI and crewai_tools include many ready‑made tools:

Search & Web / RAG

  • SerperDevTool, WebsiteSearchTool, ScrapeWebsiteTool, ScrapeElementFromWebsiteTool, FirecrawlSearchTool, FirecrawlCrawlWebsiteTool.
  • RAG over PDFs/CSVs/text: PDFSearchTool, CSVSearchTool, TXTSearchTool, JSONSearchTool, MDXSearchTool, DOCXSearchTool, DirectorySearchTool, RagTool.
  • GitHub & DB: GithubSearchTool, PGSearchTool, XMLSearchTool.

Files & Directories

  • DirectoryReadTool, FileReadTool.

Code & Data

  • CodeInterpreterTool, CodeDocsSearchTool.

Media & Vision

  • DALL-ETool / VisionTool for image generation.

YouTube & Video

  • YoutubeChannelSearchTool, YoutubeVideoSearchTool.

Integration connectors

  • ApifyActorsTool, ComposioTool, LlamaIndexTool, EXASearchTool, etc.

All are built with error handling + caching out of the box.


4. Creating Your Own Tools

You typically build custom tools when you need to talk to your APIs, databases, or services.

There are two main approaches:

4.1 Subclass BaseTool

Use this when you want full control and a clear input schema.

from typing import Type
from pydantic import BaseModel, Field
from crewai.tools import BaseTool

class MyToolInput(BaseModel):
    """Input schema for MyCustomTool."""
    argument: str = Field(..., description="Description of the argument.")

class MyCustomTool(BaseTool):
    name: str = "my_custom_tool"
    description: str = "What this tool does. It’s vital for effective utilization."
    args_schema: Type[BaseModel] = MyToolInput

    def _run(self, argument: str) -> str:
        # Your tool logic here
        return f"Tool processed: {argument}"

Attach it to an agent via tools=[MyCustomTool()].

4.2 Use the @tool decorator (sync)

Simplest way for quick tools.

from crewai.tools import tool

@tool("Name of my tool")
def my_tool(question: str) -> str:
    """Clear description for what this tool is useful for."""
    # Logic here
    return f"Answer for: {question}"

The docstring is important: the agent reads it to decide when to use the tool.


5. Asynchronous Tools

Async tools allow non‑blocking operations (network, IO, etc.).

5.1 Async function with @tool

import asyncio
from crewai.tools import tool

@tool("fetch_data_async")
async def fetch_data_async(query: str) -> str:
    """Asynchronously fetch data based on the query."""
    await asyncio.sleep(1)
    return f"Data retrieved for {query}"

5.2 Async BaseTool implementation

from crewai.tools import BaseTool

class AsyncCustomTool(BaseTool):
    name: str = "async_custom_tool"
    description: str = "An asynchronous custom tool"

    async def _run(self, query: str = "") -> str:
        await asyncio.sleep(1)
        return f"Processed {query} asynchronously"

Usage is the same; CrewAI handles sync vs async behind the scenes:

from crewai import Agent, Crew
from crewai.flow.flow import Flow, start

async_tool = AsyncCustomTool()

agent = Agent(role="researcher", tools=[async_tool])

class MyFlow(Flow):
    @start()
    async def begin(self):
        crew = Crew(agents=[agent])
        result = await crew.kickoff_async()
        return result

6. Tool Caching and cache_function

All tools in CrewAI support caching to avoid recomputing the same results.

  • By default, caching is enabled for tools.
  • You can define custom cache logic via cache_function on the tool.

Example: cache only even results.

from crewai.tools import tool

@tool
def multiplication_tool(first_number: int, second_number: int) -> int:
    """Useful for when you need to multiply two numbers together."""
    return first_number * second_number

def cache_func(args, result):
    # Only cache if the result is even
    return result % 2 == 0

multiplication_tool.cache_function = cache_func

Attach to an agent:

from crewai import Agent

writer = Agent(
    role="Writer",
    goal="You write lessons of math for kids.",
    backstory=(
        "You're an expert in writing and you love to teach kids "
        "but you know nothing of math."
    ),
    tools=[multiplication_tool],
    allow_delegation=False,
)

This pattern is helpful when:

  • Some outputs are reusable (e.g., static data).
  • Others should always be recomputed (e.g., time‑sensitive queries).

7. How Tools Fit the Agentic Architect Mindset

As an “Agentic Architect” Think about it this way:

  • Agents = specialists with roles, goals, and backstories.
  • Tools = their instruments and APIs (browser, DB, code runner, RAG, integrations).
  • You design which tools each role gets, so the team as a whole has all necessary capabilities without over‑arming each agent.

A practical approach:

  1. Start with a reasoning‑only agent (no tools).
  2. Add one search tool and show the difference.
  3. Add file / RAG tools for knowledge.
  4. Add custom tools for company‑specific APIs.