GuestFlow AI is an event-driven hospitality workflow automation platform built using FastAPI, Streamlit, SQLite, RAG architecture, and local LLM inference via Ollama.
The system automates hotel guest workflows across:
- Pre-Stay Operations
- In-Stay Guest Support
- Post-Stay Follow-Up
It uses a multi-agent orchestration architecture to route events dynamically and simulate real-world hospitality automation systems.
- Webhook-based event ingestion
- Intelligent routing system
- Multi-agent architecture
- Local LLM inference using Ollama + Phi-3
- Conversational hotel assistant
- Context-aware responses
- Hotel FAQ knowledge base
- Retrieval-based contextual support
- Dynamic query handling
- VIP guest prioritization
- Escalation handling
- Urgent request detection
- SQLite database integration
- Guest history tracking
- Stateful workflow handling
- Streamlit workflow monitoring UI
- Real-time workflow execution
- AI response visualization
- Guest requests persisted as trackable tickets (
open β in_progress β resolved) - Auto follow-up with the guest when an issue is resolved
- Escalation timer alerts a manager about stale tickets (once each)
- Durable per-guest preferences, contact and VIP status (merge-upsert)
- Stored preferences injected into AI replies automatically
- Profile-driven VIP prioritisation (no hardcoded list)
- Every guest invited to review β no "review gating"
- Negative feedback privately alerts the manager for service recovery
- ROI metrics (resolution rate/time, escalations, ratings)
- Pattern detection: systemic issues, repeat rooms, recurring feedback themes
- Optional manager daily digest email
- API-key auth (fail-closed), input validation, rate limiting
- Email header-injection & prompt-injection protection, right-to-erasure
| Component | Technology |
|---|---|
| Backend API | FastAPI |
| Dashboard | Streamlit |
| Database | SQLite (WAL) |
| Local LLM | Ollama + Phi-3 (via langchain-ollama, swappable) |
| RAG Layer | ChromaDB vector retrieval |
| Guest Memory | Qdrant (embedded) |
| Rate Limiting | SlowAPI |
| Testing | pytest |
| Language | Python |
guestflow-ai/
β
βββ agents/
β βββ orchestrator.py
β βββ prestay_agent.py
β βββ instay_agent.py
β βββ poststay_agent.py
β
βββ tools/
β βββ email_tool.py
β βββ crm_tool.py
β βββ ticket_tool.py
β βββ profile_tool.py
β βββ feedback_tool.py
β βββ analytics_tool.py
β βββ insights_tool.py
β βββ digest_tool.py
β
βββ rag/
β βββ hotel_FAQ.txt
β βββ rag_service.py
β
βββ database/
β βββ db.py
β
βββ tests/
β βββ conftest.py
β βββ test_*.py
β
βββ presentation/
β βββ generate_deck.py
β βββ GuestFlow_AI.pptx
β
βββ config.py
βββ intent_classifier.py
βββ memory.py
βββ llm_service.py
βββ dashboard.py
βββ seed_demo.py
βββ main.py
βββ requirements.txt
βββ Readme.md
git clone https://github.com/DeemonDuck/guestflow-ai.gitcd guestflow-aipip install -r requirements.txtDownload Ollama: https://ollama.com/download
ollama pull phi3ollama serveuvicorn main:app --reloadSwagger Docs:
http://127.0.0.1:8000/docs
streamlit run dashboard.pyDashboard URL:
http://localhost:8501
{
"event_type": "booking_confirmed",
"guest_name": "Rahul"
}{
"event_type": "guest_request",
"guest_name": "Rahul",
"guest_question": "Can I get late checkout tomorrow?"
}{
"event_type": "guest_request",
"guest_name": "Priya",
"guest_question": "I want refund for bad service"
}Guest requests that need follow-up are stored as tickets so they can be
tracked through their full lifecycle: open β in_progress β resolved.
GET /tickets # all tickets
GET /tickets?status=open # filter by status
PATCH /tickets/{ticket_id}
{
"status": "in_progress"
}Allowed statuses: open, in_progress, resolved.
When a ticket is moved to resolved, GuestFlow automatically follows up with the
guest to confirm the issue is actually fixed β closing the loop from request to
resolution. (The follow-up fires only on the transition into resolved, so
re-saving a resolved ticket never spams the guest.)
Open tickets that sit unattended too long can be surfaced and escalated to a manager:
GET /tickets/escalations?minutes=30 # list stale open tickets (read-only)
POST /tickets/escalations/run?minutes=30 # alert manager about stale tickets
Each ticket is escalated at most once (tracked via an escalated flag), so
running the escalation repeatedly never re-notifies the same ticket. Point a
scheduler/cron at the run endpoint to make escalation automatic.
Staff can also view and update tickets visually from the π« Tickets tab in the Streamlit dashboard (filter by status, then change a ticket's state inline).
GuestFlow keeps a durable profile per guest so repeat visitors are recognised and personalised β instead of asking the same questions every stay.
A profile stores:
| Field | Example |
|---|---|
contact_email |
sharma@example.com |
preferences |
High floor, extra pillows, veg meal |
is_vip |
true |
notes |
Anniversary on 12 Aug |
Profiles are saved via a merge upsert: updating one field never erases the others, so partial updates are safe. When a guest has a profile, their stored preferences are injected into the AI prompt for both booking confirmations (pre-stay) and in-stay requests, so replies are personalised automatically.
VIP prioritisation is driven by the profile's is_vip flag (no hardcoded
guest list): when a VIP guest raises an in-stay request, the workflow enables
priority handling automatically.
GET /profiles/{guest_name} # read a profile (null if none exists)
POST /profiles/{guest_name} # create or update (merge upsert)
DELETE /profiles/{guest_name} # erase a guest's PII (right-to-erasure)
{
"contact_email": "sharma@example.com",
"preferences": "High floor, extra pillows",
"is_vip": true,
"notes": "Anniversary on 12 Aug"
}Staff can also manage profiles visually from the π€ Profiles tab in the Streamlit dashboard: look up a guest by name, and the form pre-fills with any existing profile so preferences, VIP status and notes can be edited and saved.
After checkout, GuestFlow asks every guest for feedback and helps the hotel protect its rating β without any practice that would violate review platform policies.
- Every guest receives a feedback request that includes the public review link
(when
REVIEW_LINKis configured). The invitation is never conditioned on how the guest rates their stay. - When a guest submits negative feedback (a low rating, or a comment with negative wording), the manager is privately alerted so they can recover the experience quickly.
- That alert is an internal operations signal only β it never blocks, hides or diverts the guest's ability to post a public review.
β οΈ Compliance: selectively soliciting public reviews only from happy guests ("review gating") violates Google's review policies and FTC guidance. GuestFlow intentionally offers the review invitation to all guests; the sentiment check is used solely to trigger internal service recovery.
GET /feedback # list all submitted feedback
POST /feedback/{guest_name} # submit a rating (1-5) and/or a comment
{
"rating": 2,
"comment": "The room was not clean."
}Ratings at or below REVIEW_ALERT_THRESHOLD (default 3) flag the feedback as
negative and alert the manager.
Staff can submit and review feedback from the β Feedback tab in the Streamlit dashboard, which shows total/average rating, a negative count, and flags entries where the manager was alerted.
Beyond answering guests, GuestFlow watches the data it collects and surfaces patterns a busy manager would otherwise miss:
GET /insights
- Systemic issues β a cluster of similar tickets in the same area/time window (e.g. "3 'Maintenance' tickets on floor 3 in 24h β likely one root cause").
- Repeat rooms β a single room generating many tickets.
- Feedback themes β a topic recurring across negative reviews (e.g. "'cleanliness' came up in 3 negative reviews").
These appear at the top of the π Analytics dashboard tab. The pitch: most hotel AI answers your guests β GuestFlow tells you what's about to become a problem.
GuestFlow can compose a short operations briefing (ticket counts, escalations, average rating, recent feedback, and the insights above) and email it to the manager:
GET /digest # preview the digest body without sending
POST /digest/run # compose and email it to MANAGER_EMAIL
Point a scheduler/cron at POST /digest/run to deliver a "morning brief"
automatically.
A single ROI view for the hotel owner, aggregated from the data GuestFlow already collects:
GET /analytics
Returns ticket metrics (total, open / in-progress / resolved, resolution rate, average resolution time in minutes, escalations) and feedback metrics (total responses, average rating, positive / negative counts).
The π Analytics tab in the Streamlit dashboard renders these as at-a-glance metric cards β the "here's what you're paying for" screen.
GuestFlow has been hardened against common API and data-handling risks:
- Authentication β
API_KEY(sent asX-API-Key) is checked in constant time. SetREQUIRE_AUTH=truein production so the server refuses to start without a key (fail-closed). Interactive docs (/docs,/openapi.json) are disabled automatically when a key is configured. - Input validation β request bodies are validated (email format, rating
1β5, length limits) before any processing. - Email safety β values placed in email headers are stripped of CR/LF and recipients are format-validated, preventing header injection.
- Rate limiting β abusable/expensive endpoints (
/webhook,/feedback,/digest/run,/tickets/escalations/run) are throttled per client IP. - Prompt-injection β untrusted guest text is fenced and the model is instructed to treat it as data, never as commands.
- Right to erasure β
DELETE /profiles/{guest_name}removes a guest's profile and feedback and anonymizes their tickets.
β οΈ Deployment requirements: always run behind HTTPS/TLS (the API key and guest data travel in requests/responses), and setAPI_KEY+REQUIRE_AUTH. SQLite uses WAL mode for safer concurrency, but a real multi-hotel deployment should move to Postgres and add encryption at rest for guest PII.
GuestFlow reads its settings from environment variables (e.g. a .env file):
| Variable | Purpose |
|---|---|
GMAIL_SENDER / GMAIL_APP_PASSWORD |
Mailbox used to send notifications |
GMAIL_RECIPIENT |
Default mailbox (fallback when no specific recipient) |
MANAGER_EMAIL |
Where escalation alerts go (falls back to GMAIL_RECIPIENT) |
HOTEL_NAME |
Hotel name used in guest messaging |
ESCALATION_MINUTES |
Default staleness threshold for escalations (default 30) |
LLM_MODEL / LLM_TEMPERATURE |
Ollama model + temperature (default phi3 / 0.5) |
API_KEY |
If set, all API requests must send it as the X-API-Key header |
REQUIRE_AUTH |
If true, the server refuses to start without API_KEY (fail-closed) |
REVIEW_LINK |
Public review URL included in every guest feedback request |
REVIEW_ALERT_THRESHOLD |
Ratings at/below this (1-5) alert the manager (default 3) |
Notifications are routed automatically: guest-facing messages (booking
confirmation and resolved-ticket follow-up) go to the guest's stored
contact_email, while escalation alerts go to MANAGER_EMAIL. Each falls
back to GMAIL_RECIPIENT when a specific address isn't on file.
When API_KEY is set, every endpoint requires the matching key in an
X-API-Key request header (missing/incorrect keys get 401). When API_KEY
is unset, authentication is disabled for local development and the server
prints a warning at startup. Always set API_KEY before exposing the API on
a network. The Streamlit dashboard reads API_KEY from the environment and
sends it automatically.
To make the dashboard look alive for a demo, seed realistic sample data (profiles, tickets in every state, and feedback):
python seed_demo.pyIt is non-destructive β profiles are merge-upserted and ticket/feedback seeding is skipped if demo data already exists, so it is safe to re-run.
A pytest suite (48 tests) covers the core behaviour: ticket lifecycle
(creation, status validation, resolve follow-up firing once, escalation alerting
once), guest profile merge-upsert and right-to-erasure, review/feedback sentiment
- compliance (review link offered to every guest, manager alerted only on negative feedback), proactive insights, analytics aggregation, the manager digest, intent classification, LLM fallback, and the security controls (API-key auth incl. fail-closed, input validation, email header-injection defence, rate limiting, prompt-injection fencing).
pytest tests/ -qTests run against an isolated temporary database (no impact on guestflow.db)
and stub all outbound email, so the suite sends nothing and touches no real data.
- AI Workflow Automation
- Event-Driven Systems
- Multi-Agent Architecture
- Retrieval Augmented Generation (RAG)
- Local LLM Inference
- Workflow Orchestration
- Persistent State Management
- Hospitality CRM Automation
- WhatsApp / SMS notifications (via a Business Solution Provider)
- LangChain Tool Calling Agents
- Cloud Deployment
- Real CRM/PMS Integration
- Multi-tenant support (per-hotel configuration & data isolation)
- Advanced Semantic Vector Search
Developed by Ridham Taneja
GuestFlow AI is licensed under the PolyForm Noncommercial License 1.0.0.
Free for noncommercial use. You may read, run, modify, and share the code for personal projects, study, research, hobby work, and use by charities, schools, and government institutions.
Commercial use requires a paid license. This includes any hotel, hospitality group, agency, or other business running GuestFlow AI as part of its operations, and any resale or hosting of it as a service. Self-hosting by a business is still commercial use and is not covered by this license.
For a commercial license, contact Ridham Taneja.
Copyright (c) 2026 Ridham Taneja





