Skip to content

fix(hotel_receptionist): stop the restaurant flow implying a table it never reserved - #6800

Closed
u9g wants to merge 2 commits into
mainfrom
fix/restaurant-phone-declined
Closed

fix(hotel_receptionist): stop the restaurant flow implying a table it never reserved#6800
u9g wants to merge 2 commits into
mainfrom
fix/restaurant-phone-declined

Conversation

@u9g

@u9g u9g commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

A caller who won't give a phone number ended BookRestaurantTask with a bare ToolError, and start_restaurant_booking let it propagate. The receptionist read the failed tool call as a booked table and spoke a confirmation for a reservation that was never written.

Cherry-picked out of #6567, which bundles this with a lot of unrelated hotel-receptionist work.

Changes

Librarydecline_phone_number_capture completed the task with a bare ToolError, indistinguishable from any other failure, so a caller that wants to react to a refusal (rather than to a crash) had only the message text to match on. PhoneNumberCaptureDeclinedError subclasses ToolError with the identical message, so existing callers are unaffected.

ExampleRestaurantReservationNotCreatedError is what the restaurant flow now completes with when the phone dialog is declined. open_phone_dialog catches the declined error and returns wording that states the outcome; start_restaurant_booking catches it and reports a non-reservation instead of falling through to the success string. The phone dialog also gets instructions to decline rather than stall when the caller has no number.

Testing

  • Full unit gate: 1942 passed, 5 skipped.
  • ruff format + check clean; mypy clean on the changed library file.

decline_phone_number_capture completed the task with a bare ToolError,
indistinguishable from any other failure, so a caller that needs to react
to a refusal (rather than to a crash) had only the message text to match
on. PhoneNumberCaptureDeclinedError subclasses ToolError with the same
message, so existing callers are unaffected.
@u9g
u9g requested a review from a team as a code owner August 11, 2026 20:12
… never reserved

A caller who won't give a phone number ended the flow with a bare
ToolError, which start_restaurant_booking let propagate; the receptionist
then read a failed tool call as a booked table and spoke a confirmation.
The flow now completes with RestaurantReservationNotCreatedError, which
the tool catches and reports as a non-reservation, and the phone dialog
is told to decline rather than stall when the caller has no number.
@u9g
u9g force-pushed the fix/restaurant-phone-declined branch from 1c40f75 to da1665f Compare August 11, 2026 20:13

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

View 2 additional findings in Devin Review.

Open in Devin Review

Comment on lines +62 to +69
class PhoneNumberCaptureDeclinedError(ToolError):
def __init__(self, reason: str) -> None:
super().__init__(f"couldn't get the phone number: {reason}")
self._reason = reason

@property
def reason(self) -> str:
return self._reason

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 New public error class ships without documentation

The newly added public error type is exported in the package's public API (PhoneNumberCaptureDeclinedError at livekit-agents/livekit/agents/beta/workflows/phone_number.py:62) without any docstring, so it appears undocumented in the generated API docs.
Impact: Users browsing the published API reference see an undocumented error type and cannot tell when it is raised.

CONTRIBUTING.md documentation requirement for new classes

CONTRIBUTING.md states: "If writing new methods/enums/classes, document them. This project uses pdoc3 for automatic API documentation generation, and every new addition has to be properly documented." The class and its reason property (livekit-agents/livekit/agents/beta/workflows/phone_number.py:67-69) have no docstrings, and the class is exported in livekit-agents/livekit/agents/beta/workflows/__init__.py:32. By contrast, the base ToolError documents itself (livekit-agents/livekit/agents/llm/tool_context.py:124-131), and the example-side counterpart RestaurantReservationNotCreatedError does carry a docstring.

Suggested change
class PhoneNumberCaptureDeclinedError(ToolError):
def __init__(self, reason: str) -> None:
super().__init__(f"couldn't get the phone number: {reason}")
self._reason = reason
@property
def reason(self) -> str:
return self._reason
class PhoneNumberCaptureDeclinedError(ToolError):
"""Raised when the user explicitly declines to provide a phone number.
`GetPhoneNumberTask` completes with this error (instead of a bare `ToolError`)
so callers can distinguish a deliberate refusal from other failures.
"""
def __init__(self, reason: str) -> None:
super().__init__(f"couldn't get the phone number: {reason}")
self._reason = reason
@property
def reason(self) -> str:
"""Short explanation of why the user declined to provide the phone number."""
return self._reason
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@u9g

u9g commented Aug 11, 2026

Copy link
Copy Markdown
Contributor Author

Duplicate of #6801, which carries the same change plus test coverage. Closing in favor of that one.

@u9g u9g closed this Aug 11, 2026
@u9g
u9g deleted the fix/restaurant-phone-declined branch August 11, 2026 20:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant