HiLucyHelp Center

Lucy & Room Service — how the AI takes orders

HiLucy Team·تم التحديث 2026-04-26·3 min read

Lucy handles room-service ordering directly — there's no special "food" assistant to delegate to. Three tools, added in v3.20.0, mirror the proven activity-booking pattern.

What guests can say

Lucy responds to almost anything food-shaped:

| Guest says | Lucy does | |---|---| | "What's on the menu?" | Calls fetch_menu_items and presents items in a condensed list grouped by category. | | "What's vegan?" | Fetches the menu, filters by dietary_tags, and lists matches. | | "I'd like room service" | Asks the guest what they'd like, then walks through items + quantities. | | "Order me a coffee" | Confirms which coffee from the menu, then calls place_room_service_order. | | "Two mojitos and a ceviche" | Resolves each item against the menu, confirms total, then places the order. |

When in doubt, Lucy confirms before charging — the typical exchange is "Mojito ($12) and ceviche mixto ($22) — total $34. Add to your room?" Yes / No / Edit.

The three tools

hl_machine/utils/tools.py (graph repo):

  • fetch_menu_items(listing_id, category=None) — calls GET /hilucy/v1/listings/{id}/menu. Returns up to 200 items. Use the category filter for narrow asks like "what's for breakfast?".
  • get_menu_item_details(item_id) — calls GET /hilucy/v1/menu-items/{id} for a single item. Useful when Lucy wants to confirm price or dietary tags before placing.
  • place_room_service_order(items, listing_id, guest_name?, guest_phone?, guest_room?, special_requests?) — calls POST /hilucy/v1/menu-orders. Returns a Command updating five state fields:
    • room_service_order_id (folio_id or wc_order_id)
    • room_service_status (on_folio / per_charge / awaiting_payment / failed)
    • room_service_checkout_url (set when no folio is open)
    • selected_menu_items (cached for context)
    • pending_room_service_order (last placed)

When Lucy returns a checkout link vs charges to the room

The decision is made server-side in HiLucy_Menu_Order_Service::place_order — Lucy doesn't choose. Her ToolMessage just relays the result:

  • charge_status: 'on_folio' → "Done — your order has been added to your room. Total: $X.YZ. The kitchen has been notified."
  • charge_status: 'per_charge' → same message; the difference is invisible to the guest.
  • charge_status: 'awaiting_payment' → "Your order is ready to confirm — total $X.YZ. Open this secure link to pay and the kitchen will start prep: <url>"

The web chat surfaces that URL as a tappable Pay & confirm button (rich card). WhatsApp guests get the URL inline.

Listing context — how Lucy knows which menu

Lucy reads listing_id from state.listing_id, which is populated by the fetch_user_info entry node from the configurable.listing_id config. Every chat thread is bound to one listing.

If a guest somehow lands in chat with no listing_id, Lucy will politely ask which property they're at instead of guessing. Staff can set the listing by sending the guest a fresh arrival link.

Guardrails

  • Lucy will not call place_room_service_order without a guest name and phone. The tool itself returns "Please ask the guest for their name" if either is missing — Lucy follows up with the guest.
  • Lucy never invents items. If the guest asks for something not on the menu, she escalates to staff via the existing set_potential_provider_contact + ToHotelConciergeAssistant pattern (see activities docs).
  • Lucy doesn't auto-substitute. "We're out of mojitos" → she'll suggest similar drinks rather than swap silently.
هل كان هذا المقال مفيداً؟