Hands

Read tools are safe. Write tools are where things get real. A booking, a cancellation, a taxi request. These change state and you cannot undo a hallucinated confirmation.

tools.py
python
SESSION_BOOKINGS = {}

def book_hotel(
    hotel_name: str,
    city: str,
    check_in: str,
    check_out: str,
    guest_name: str,
) -> str:
    """Books a hotel room."""
    booking_id = f"BK{random.randint(100000, 999999)}"
    SESSION_BOOKINGS[booking_id] = {
        "booking_id": booking_id,
        "customer_name": guest_name,
        "hotel": hotel_name,
        "city": city,
        "check_in": check_in,
        "check_out": check_out,
        "status": "confirmed",
    }
    return f"Hotel booking confirmed! ID: {booking_id}"

Write tools mutate state. Here it is an in-memory dict for the workshop, but in production this is where you talk to a database, a payment gateway, or an external booking API.

tools.py
python
def cancel_booking(
    booking_id: str,
    reason: Optional[str] = None,
) -> str:
    """Cancels a booking."""
    booking_id = booking_id.upper().strip()
    bookings = _get_all_bookings()

    if booking_id not in bookings:
        return f"Booking {booking_id} not found."

    if booking_id in SESSION_BOOKINGS:
        SESSION_BOOKINGS[booking_id]["status"] = "cancelled"
        return f"Booking {booking_id} cancelled."

    return (
        f"Booking {booking_id} cancellation processed. "
        f"Refund initiated."
    )

Notice the defensive checks. The model will confidently pass in garbage. Validate inputs, return clear errors, and never silently succeed.

Matching exercise: Match the tool to its shape

Loading practice…