Tools that break mid-run
A tool that raises does not stop the crew. The error text goes to the model, the run finishes, and the failure is recorded on the result where your code can check it.
Lesson 9's tool always answered. A real order system goes down. Here the tool raises instead.
from crewai import Agent, Crew, Task
from shop_llm import ShopLLM
from tools import lookup_order
clerk = Agent(
role="Order clerk",
goal="Find the status of customers' orders",
backstory="You can look up any order in the shop's system.",
llm=ShopLLM(model="shop"),
tools=[lookup_order],
)
task = Task(description="Answer the customer: {question}",
expected_output="The order's status in one sentence.", agent=clerk)
crew = Crew(agents=[clerk], tasks=[task])from crewai.tools import tool
@tool
def lookup_order(order_id: str) -> str:
"""Look up an order's shipping status by its id, such as A17."""
raise ConnectionError("the order database is not answering")result = crew.kickoff(inputs={"question": "Where is my order A17?"})
print(result.raw)The crew finished, and its answer is the error. CrewAI caught the exception and sent Error executing tool: and the message to the model as the tool's result. Your model repeated it. A hosted model would write something politer, and the run would look like a success.
Checking the result
result = crew.kickoff(inputs={"question": "Where is my order A17?"})
print(result.has_tool_failures)
for record in result.tool_failures:
print(record.tool_name, "|", record.failure.message)CrewAI records the failure even though the run completed. The documentation's advice is to check has_tool_failures before treating raw as complete. A desk could send the ticket to a person instead of mailing the customer.
Stopping the run instead
task.tool_failure_policy = "raise"
try:
crew.kickoff(inputs={"question": "Where is my order A17?"})
except Exception as error:
print(type(error).__name__)
print(error)tool_failure_policy has three values: warn, the default you saw, records the failure and continues; raise stops the run with ToolExecutionFailedError; ignore records nothing. The two warning lines come from CrewAI's event bus as the failed run unwinds. The policy can be set on a tool, a task, an agent or the crew, and the most specific setting wins.
- Set the policy to
"ignore"and printhas_tool_failures. - Set the policy on the agent instead of the task.
- Make the tool return a normal string for C40 and raise only for other ids.
Every expert started right here.