High severity beginner · Fix: 2-5 min

ToolNotFoundError

crewai.tools.exceptions.ToolNotFoundError

What this error means
CrewAI agent attempted to use a tool that was not registered in its tools list, causing a runtime failure when the agent tried to invoke it during task execution.

Stack trace

traceback
Traceback (most recent call last):
  File "main.py", line 45, in <module>
    result = crew.kickoff(inputs={...})
  File "crewai/crew.py", line 234, in kickoff
    task_result = self._execute_task(task)
  File "crewai/crew.py", line 198, in _execute_task
    output = agent.execute_task(task, ...)
  File "crewai/agent.py", line 156, in execute_task
    tool_result = self._invoke_tool(tool_name, tool_input)
  File "crewai/agent.py", line 289, in _invoke_tool
    raise ToolNotFoundError(f"Tool '{tool_name}' not found in agent tools list. Available tools: {[t.name for t in self.tools]}")
crewai.tools.exceptions.ToolNotFoundError: Tool 'search_web' not found in agent tools list. Available tools: ['calculate', 'get_weather']
QUICK FIX
Add missing tool to the Agent constructor: `Agent(role='...', goal='...', tools=[your_missing_tool])` and verify tool.name matches what the LLM is instructed to call.

Why it happens

CrewAI agents maintain an internal tools list that is set at agent initialization. When the agent's LLM decides to call a tool during execution, it looks up that tool by name in its registry. If the tool name doesn't match any registered tool (due to typo, missing registration, or dynamic tool addition after agent creation), the agent cannot execute the tool call and raises this exception. This commonly happens when tools are defined but not passed to the Agent constructor, or when tool names in prompts don't match their actual registered names.

Detection

Enable debug logging with `import logging; logging.basicConfig(level=logging.DEBUG)` before crew.kickoff() to see which tools the agent has registered and which tool it tried to call. Check the error message's 'Available tools' list against what you expected to pass.

Causes & fixes

1

Tool is defined but not passed to Agent constructor in the tools= parameter

✓ Fix

Pass all tools explicitly when creating the Agent: `Agent(role='...', goal='...', tools=[search_tool, calculate_tool])`

2

Tool name in LLM response doesn't match registered tool name (typo or case mismatch)

✓ Fix

Ensure tool.name matches exactly what the prompt instructs the LLM to call. Use lowercase with underscores: tool.name = 'search_web' not 'search_Web' or 'searchWeb'

3

Tools added to agent AFTER initialization instead of during __init__

✓ Fix

Pass all tools at agent creation time, not dynamically later. If dynamic tools needed, recreate the agent with the new tools list

4

Tool import missing or incorrect: agent receives None or empty list

✓ Fix

Verify all tool classes are imported correctly and instantiated before passing to Agent. Check for import errors with `print(tools)` before agent creation

Code: broken vs fixed

Broken - triggers the error
python
import os
from crewai import Agent, Task, Crew, Process
from crewai.tools import tool

@tool
def search_web(query: str) -> str:
    """Search the web for information."""
    return f"Results for {query}"

@tool
def calculate(expression: str) -> str:
    """Calculate a math expression."""
    return str(eval(expression))

# BUG: search_web tool defined but NOT passed to agent
researcher = Agent(
    role="Research Analyst",
    goal="Find information about topics",
    tools=[calculate]  # MISSING search_web here!
)

task = Task(
    description="Search for AI trends and calculate market size",
    agent=researcher,
    expected_output="Report with search results and calculations"
)

crew = Crew(
    agents=[researcher],
    tasks=[task],
    process=Process.sequential
)

result = crew.kickoff(inputs={"query": "AI market trends"})
print(result)
Fixed - works correctly
python
import os
from crewai import Agent, Task, Crew, Process
from crewai.tools import tool

@tool
def search_web(query: str) -> str:
    """Search the web for information."""
    return f"Results for {query}"

@tool
def calculate(expression: str) -> str:
    """Calculate a math expression."""
    return str(eval(expression))

# FIX: Pass ALL tools to agent constructor, including search_web
researcher = Agent(
    role="Research Analyst",
    goal="Find information about topics",
    tools=[search_web, calculate]  # FIXED: Both tools now registered
)

task = Task(
    description="Search for AI trends and calculate market size",
    agent=researcher,
    expected_output="Report with search results and calculations"
)

crew = Crew(
    agents=[researcher],
    tasks=[task],
    process=Process.sequential
)

result = crew.kickoff(inputs={"query": "AI market trends"})
print(f"Crew output: {result}")
Added search_web to the tools list passed to the Agent constructor so it's registered and available when the agent tries to invoke it during task execution.

Workaround

If you cannot modify the Agent initialization, catch the ToolNotFoundError at the crew level and re-run with all tools included: `try: crew.kickoff(...) except ToolNotFoundError as e: available_tools = [search_web, calculate]; agent.tools = available_tools; crew.kickoff(...)` (though this is fragile: fix the root cause instead).

Prevention

Build a tools registry function that is called at agent creation to ensure consistency. Use type hints to catch missing tools at lint time: `def create_researcher_agent(tools: List[tool]) -> Agent: assert any(t.name == 'search_web' for t in tools), 'search_web tool required'`. This ensures all required tools are present before the agent starts execution.

Python 3.9+ · crewai >=0.30.0 · tested on 0.55.0+
Verified 2026-04
Verify ↗

Community Notes

No notes yetBe the first to share a version-specific fix or tip.