A tool is code, and code can fail. The model may send an input your function can't use, or ask for an order that doesn't exist. A tool that fails must never crash the conversation: the failure goes back to the model as a tool result, marked as an error.
Catching an exception: the code under try runs as usual. If it raises an exception, Python jumps to the except block instead of stopping the program.
try:
number = int("four")
except Exception:
number = 0
print(number) # 0
A tool can fail in two ways. It can raise an exception, or it can return an error by itself, as lookup_order does with {"error": "Order not found"}. In both cases you send a tool_result with "is_error": True and a short, safe message. Never send the exception's own text: it talks about your database, and the model could repeat it to the customer.
In this lesson the customer asks "Where are my orders 4 and 40?" The model first sends both numbers in one list, which makes the tool raise. Your finished program prints:
Tool: lookup_order {'order_id': [4, 40]} -> {'error': 'The tool failed. Check the input and try again.'}
Tool: lookup_order {'order_id': 4} -> {'id': 4, 'ordered': '2026-04-18', 'status': 'shipped'}
Tool: lookup_order {'order_id': 40} -> {'error': 'Order not found'}
Answer: Order 4 has shipped. I couldn't find an order with the number 40. Could you check that number?
Your task: in run_tools, run the tool inside try, turn any exception into a short error result, work out is_error, and send it with the tool result.
Assignment
Follow the Coding Tutorial to make run_tools survive a failing tool and report the failure to the model with is_error.
Hinttry: and except Exception: sit at the same level, with one indented line under each. The in operator tells you whether a dictionary has a key.
Free plan: 30 tutor messages. PRO is unlimited.
