ToolNotFoundError
crewai.tools.exceptions.ToolNotFoundError
Stack trace
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'] 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
Tool is defined but not passed to Agent constructor in the tools= parameter
Pass all tools explicitly when creating the Agent: `Agent(role='...', goal='...', tools=[search_tool, calculate_tool])`
Tool name in LLM response doesn't match registered tool name (typo or case mismatch)
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'
Tools added to agent AFTER initialization instead of during __init__
Pass all tools at agent creation time, not dynamically later. If dynamic tools needed, recreate the agent with the new tools list
Tool import missing or incorrect: agent receives None or empty list
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
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) 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}") 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.