Your guests deserve more than an autoresponder.
A fully local, agentic AI system that handles every WhatsApp message your property receives β 24 hours a day, 7 days a week. No cloud dependencies. No sensitive data leaving your network. Guest data stays yours.
If you've ever managed guest relations in hospitality, you already know: every unanswered message is a missed booking, and every missed booking is a guest who chose someone else.
This system works in two simultaneous modes:
Proactive β The moment a booking is confirmed in your PMS, the agent opens the conversation automatically: welcome message, practical info, upsell opportunity, pre-arrival checklist, check-in reminder, post-stay review request. The full guest journey, on schedule.
Reactive β Every inbound WhatsApp message gets a response. Existing guests, curious visitors, people comparing prices before booking β the agent identifies who it is talking to, loads the right context, and handles the conversation from first contact to confirmed reservation.
It connects to your PMS for real-time availability and pricing, builds personalised offers, manages common FAQs, collects pre-arrival information, and knows exactly when to step aside and hand the conversation to a human.
- Fully local inference β LLM models run on your hardware via Ollama. Nothing leaves your network except WhatsApp messages (transport layer only)
- Stateful conversations β Every session persists in Redis. The agent remembers the full guest journey across days
- Multi-language β Responds in Italian, English, French, and German based on the guest's messages
- Smart escalation β Detects complaints and human requests instantly; pauses the bot and notifies staff via WhatsApp
- PMS integration β Works with any PMS that exposes a REST API; includes a realistic mock for development
- Graceful degradation β If Ollama or Redis is unavailable, the system falls back to heuristics and in-memory storage. Guests always get a response
Inbound WhatsApp
β
βΌ
guest_lookup βββΊ classifier βββΊ pms_caller βββΊ offer_builder βββΊ send_whatsapp
β
ββββΊ direct_response / acquisition_flow / escalation
Four subagents, each with a dedicated model:
| Subagent | Model | Role |
|---|---|---|
| Guest Lookup | β (pure logic) | Identifies caller, loads session |
| Classifier | llama3.2:3b |
Intent detection, routing |
| PMS Caller | llama3.2:3b |
Parameter extraction, availability queries |
| Offer Builder | llama3.1:70b β 8b β 3b |
Personalised message generation |
hotel-crm/
βββ main.py # FastAPI webhook server + scheduler
βββ config.py # All configuration (loads from .env)
βββ .env.example # Environment variable template
βββ requirements.txt
βββ graph/
β βββ builder.py # LangGraph graph definition and routing
β βββ state.py # GuestState TypedDict (all phases)
βββ agents/
β βββ guest_lookup.py # Subagent 0: PMS lookup, session init
β βββ classifier.py # Subagent 1: intent classification
β βββ pms_caller.py # Subagent 2: PMS API calls
β βββ offer_builder.py # Subagent 3: message generation
β βββ prompts.py # All prompts centralised here
βββ tools/
β βββ whatsapp.py # WhatsApp Business API client
β βββ pms_mock.py # Realistic mock PMS (dev/test)
βββ memory/
β βββ redis_store.py # Session persistence + in-memory fallback
βββ scheduler/
β βββ message_timeline.py # APScheduler proactive message timeline
βββ tests/
βββ simulate_conversation.py # End-to-end simulation (no external deps)
Requirements: Python 3.11+, Ollama, Redis
# 1. Clone and install
git clone https://github.com/your-org/hotel-crm.git
cd hotel-crm
python3.11 -m venv .venv && source .venv/bin/activate
pip install -r hotel-crm/requirements.txt
# 2. Configure
cd hotel-crm
cp .env.example .env
# Edit .env: set HOTEL_NAME, HOTEL_LANGUAGE, WhatsApp credentials
# 3. Start services
ollama serve &
ollama pull llama3.2:3b
ollama pull llama3.1:8b
redis-server &
# 4. Run
python main.py
# 5. Verify (no external services needed)
python -m tests.simulate_conversationThe simulation runs two complete conversations end-to-end β a known guest with a booking and an unknown contact β and prints every step to the console including latency per node.
When a booking event arrives from the PMS (POST /pms/booking-event), the scheduler automatically queues:
| Trigger | When |
|---|---|
| Welcome | 1 minute after booking confirmed |
| Practical info | 30 minutes after booking confirmed |
| Upsell offer | 5 days before check-in |
| Pre-check-in | 48 hours before check-in |
| Check-in reminder | 09:00 on arrival day |
| Post-stay review | 1 day after checkout |
Each trigger respects the current guest phase β no duplicate messages, no sending to escalated sessions.
UNKNOWN_CONTACT β ACQUIRING β BOOKING_RECEIVED β WELCOME_SENT
β INFO_SENT β IDLE β UPSELL β PRE_CHECKIN β CHECKIN_DAY
β IN_HOUSE β POST_STAY
Any phase β ESCALATED (on complaint or human request)
ESCALATED β IDLE (after staff resolves and reactivates)
All parameters are documented in docs/USER_MANUAL.md (Section 8).
The most important .env settings:
HOTEL_NAME=Grand Hotel Riviera
HOTEL_LANGUAGE=it
WHATSAPP_API_URL=https://graph.facebook.com/v18.0
WHATSAPP_TOKEN=your_token
WHATSAPP_PHONE_NUMBER_ID=your_phone_number_id
STAFF_NOTIFICATION_PHONE=+39347000001
PMS_API_URL= # leave empty for mock
DEV_MODE=true # set false in productionFull documentation is available in docs/USER_MANUAL.md:
- Part I β Staff Guide: Daily operations, escalation management, WhatsApp guidelines, daily checklist. Written for hospitality staff with no technical background.
- Part II β Technical Guide: Installation, configuration reference, WhatsApp API setup, PMS integration, architecture diagrams, troubleshooting.
| Component | Technology |
|---|---|
| Agent orchestration | LangGraph |
| Local LLM inference | Ollama |
| Models | llama3.2:3b, llama3.1:8b, llama3.1:70b |
| Session storage | Redis |
| Proactive scheduling | APScheduler |
| Web server | FastAPI + Uvicorn |
| Async HTTP | httpx |
| Messaging | WhatsApp Business API |
This project uses a dual licensing model.
Non-commercial use (default): Free to use, modify, and distribute under the terms of the MIT + Commons Clause licence. This means you may not use this software β or any substantial part of it β to provide a commercial service, charge fees, or generate revenue, without explicit written permission from the author.
Commercial use: If you want to deploy this software in a revenue-generating context (e.g. a hotel, hospitality business, or SaaS product), you need a separate commercial licence.
Contact the maintainer via GitHub to discuss terms. The commercial licence is granted on a case-by-case basis and includes an explicit "as-is" clause β no warranties, no guaranteed support, no liability on the part of the author.
Already have a commercial licence? See
COMMERCIAL_LICENSE.mdfor the terms that apply to your deployment.