Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion examples/hotel_receptionist/book_restaurant.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,18 @@ def _status(self) -> str:
return "name captured - next: call open_phone_dialog"
return "all required details captured - call confirm_reservation() now to finalize the reservation"

def _not_reserved(self) -> str:
# Same split as BookRoomTask._not_booked: _status() is progress text, and
# read as the result of a refused confirm_reservation it says only "here
# is the next step" - nothing in it says no table was reserved. The
# is_error flag never reaches the model (the OpenAI provider format sends
# this string as the whole tool message), so it has to state the outcome.
return (
"NOT reserved - no reservation was created and no confirmation code exists. "
"Never tell the caller the table is reserved and never speak a confirmation code. "
f"Where the reservation actually stands: {self._status()}"
)

@function_tool()
async def set_party(self, on_date: date, party_size: Annotated[int, Field(ge=1)]) -> str:
"""Record the date + party size. The return lists the open time slots - offer them to the caller and let them pick; don't choose a slot yourself.
Expand Down Expand Up @@ -150,7 +162,7 @@ async def confirm_reservation(self) -> str | None:
on_date, party_size, at_time = self._date, self._party_size, self._time
first_name, phone = self._first_name, self._phone
if not (on_date and party_size and at_time and first_name and phone):
raise ToolError(self._status())
raise ToolError(self._not_reserved())
try:
reservation = await self._db.book_restaurant(
first_name=first_name,
Expand Down
17 changes: 16 additions & 1 deletion examples/hotel_receptionist/book_room.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,21 @@ def _status(self) -> str:
"never compute your own."
)

def _not_booked(self) -> str:
# The refusal path gets its own text; _status() is for the success and
# progress returns only. _status() on its own reads as "here is the next
# step" - nothing in it says no booking happened, and by this point in a
# multi-room call the model has usually already spoken a real "HTL-..."
# code, so it has a template to invent one from. The is_error flag is no
# help here: the OpenAI provider format drops it and sends a tool message
# whose content is this string and nothing else, so the text itself has to
# carry the outcome. Still no missing-field list, for the reason above.
return (
"NOT booked - no reservation was created and no confirmation code exists. "
"Do not tell the caller they're booked and never speak a confirmation code. "
f"Where the booking actually stands: {self._status()}"
)

@function_tool()
async def set_stay(
self,
Expand Down Expand Up @@ -274,7 +289,7 @@ async def confirm_booking(self) -> str | None:
and phone
and card_last4
):
raise ToolError(self._status())
raise ToolError(self._not_booked())
try:
booking = await self._db.book_room(
room_type=room_type,
Expand Down