Hotel guests do not care whether the front desk is staffed. They want to text or call one number and have their room service, housekeeping, concierge, or maintenance request handled. A concierge line is a good test case for voice AI because the workflow is familiar and the volume is real.
The Telnyx code example is:
https://github.com/team-telnyx/telnyx-code-examples/tree/main/hotel-guest-services-python
It is a Python Flask app that combines Telnyx Voice, AI Inference, Messaging, and Slack into a small demo you can clone and run in a few minutes.
A guest calls or texts the Telnyx number. The Flask app receives the webhook, looks up the room by caller ID, and either greets the guest by name or asks for the room number. Each request is sent to Telnyx AI Inference, which classifies it into room_service
, housekeeping
, concierge
, or maintenance
. Urgent phrases (fire
, flood
, leak
, locked out
, gas
, medical
) override the LLM and route the request as urgent
.
The request is appended to a log, the guest gets an SMS confirmation, and staff get a Slack alert with the right emoji for the department. When staff mark the request complete, the guest gets another SMS.
It is small enough to demo live, but it covers the parts that often get cut from a "Hello World" voice AI demo:
That makes it useful as a starting template for any single-vertical phone service where one phone number handles a small set of structured requests.
git clone https://github.com/team-telnyx/telnyx-code-examples.git
cd telnyx-code-examples/hotel-guest-services-python
cp .env.example .env
pip install -r requirements.txt
python app.py
Expose the webhook:
ngrok http 5000
In the Telnyx Portal, set the Voice API app webhook URL to https://<ngrok-id>.ngrok-free.app/webhooks/voice
and the Messaging Profile inbound webhook URL to https://<ngrok-id>.ngrok-free.app/webhooks/sms
. Call or text the Telnyx number to test.
I would keep the demo short:
curl http://localhost:5000/requests
.curl -X POST http://localhost:5000/requests/0/complete
.Then call from an unknown number, say "Room 205 please", and make a second request to show the unknown-caller path.
The demo uses in-memory state, which is fine for learning. Production would replace ROOMS
and service_requests
with your PMS database (Opera, Mews, Cloudbeds), persist call state and event IDs to Redis, queue Slack and SMS side effects, add call recording for QA, and map urgent requests to a real paging system instead of Slack.