Westside boutique. Worldwide buyers.
A production-ready WhatsApp Business AI assistant that auto-replies to inbound real-estate leads in under 30 seconds, qualifies them through a natural bilingual (English / Spanish) conversation, scores them with an LA-tuned rubric, and pushes the lead into Google Sheets + Slack.
Built around a fictional but realistic boutique agency — Casa Verde Realty (Santa Monica, CA) — see docs/case_study.md for the full story and projected impact.
Built as a portfolio piece to show how Claude + Twilio + a sane Python backend can replace a $5k/mo SDR for a small services business.
4-frame loop showing the full pipeline: a Spanish-speaking buyer messages WhatsApp → Sofia qualifies → an English-speaking renter messages → the lead lands in Google Sheets and Slack ~5 seconds later.
![]() Spanish qualifier flow |
![]() English qualifier flow |
![]() Lead in Google Sheets |
![]() Slack notification |
- Bilingual — auto-detects Spanish vs English on the first message and mirrors the prospect; switches mid-conversation if they switch
- One question at a time — short WhatsApp-native messages, never an essay
- Natural — uses the prospect's name once given, light emoji, no "I am an AI assistant" formality
- Strict qualification flow enforced via Claude tool use — no aimless small-talk; the LLM only finishes when it has enough info to call
record_lead - Edge-case aware — out-of-budget, casual browsing, hostile/spam, off-topic, existing-client all handled politely in the prompt
- Deterministic LA-tuned scoring in pure Python —
HOT/WARM/COLDbased on budget tier, financing type, timeline urgency - Foreign-national premium — recognizes Casa Verde's high-intent international segment
- Rental vs purchase — separate scoring lanes (a $5k/mo rental in Venice is HOT; a $5k home is COLD)
- Twilio WhatsApp — works out of the box with the free Sandbox; one env-var swap for production
- Google Sheets CRM — appends one row per qualified lead, auto-creates the header row on startup
- Slack incoming webhooks — Block Kit cards, score-based filtering (no ping for cold leads)
- Anthropic Claude with prompt caching on the system prompt — ~10× cheaper after the first call within the 5-minute window
- Async FastAPI — webhook acks Twilio in <100 ms, processes in background
- Signed Twilio webhook validation — prevents anyone on the internet from forging messages
- Structured logs (structlog) → JSON — drops into any log aggregator
- Sentry integration — set
SENTRY_DSNand you're done - SQLAlchemy 2.0 async + aiosqlite — conversation memory survives restarts
- Multi-stage Dockerfile — ~120 MB final image, non-root user
- GitHub Actions CI — pytest matrix across Python 3.10 / 3.11 / 3.12 + ruff lint
render.yaml— push to GitHub, deploy on Render free tier in 60 seconds
WhatsApp ─► Twilio ─► /webhooks/whatsapp ─► (ack 200) ─┐
│
background task
│
┌────────────────┼────────────────┐
▼ ▼ ▼
Claude API Google Sheets Slack
(qualify lead) (CRM row) (alert)
│
▼
SQLite (conversation memory)
Full sequence diagram and component-by-component breakdown in docs/architecture.md.
git clone https://github.com/KirillHat/casa-verde-bot.git
cd casa-verde-bot
python -m venv venv && source venv/bin/activate
pip install -r requirements-dev.txtFollow docs/twilio_setup.md — 5 min, no Meta verification needed.
Follow docs/google_sheets_setup.md — 5 min, free.
cp .env.example .env
# Fill in TWILIO_*, ANTHROPIC_API_KEY, GOOGLE_SHEETS_ID, SLACK_WEBHOOK_URLuvicorn app.main:app --reload --port 8000
# in another terminal:
ngrok http 8000
# paste the https://xxx.ngrok.io/webhooks/whatsapp URL into Twilio Sandbox settingsFrom your phone WhatsApp, message the Twilio sandbox number:
"Hi, looking for a 2BR rental in Venice, budget $5k/mo, need it next month"
You should get an AI reply within 5 seconds, see a row appear in Google Sheets, and get a Slack notification.
docker compose upMounts ./data for SQLite persistence and ./google_credentials.json for Sheets auth.
- Push to GitHub
- Render → New → Web Service → connect repo
- Render auto-detects
render.yamland provisions the service - Set env vars in the Render dashboard (everything from
.env.example) - Add
google_credentials.jsonas a Secret File mounted at/etc/secrets/google_credentials.json - Set the Twilio Sandbox webhook to
https://your-app.onrender.com/webhooks/whatsapp
pytest -v
# or with coverage:
pytest --cov=app --cov-report=termThe suite covers:
- Scoring rules — every HOT / WARM / COLD pathway, threshold overrides, foreign-national premium
- Conversation flow — mocked Claude responses, lead persistence, history threading, error isolation (Sheets failure ≠ user-facing failure)
- Webhook — signature validation, ack-fast behaviour, healthcheck
The architecture is generic. To repurpose for a yoga studio, dental clinic, solar installer, online school, etc:
- Edit
app/prompts/qualifier_realestate.md— domain context + qualification fields - Edit
app/services/scoring.py— your industry's HOT / WARM / COLD rules - Update headers in
app/services/sheets_client.pyto match the new fields
Total adaptation time: ~2 hours. The portability is the actual product — see docs/case_study.md.
docs/case_study.md— full Casa Verde story, projected metrics, why this is harddocs/architecture.md— sequence diagram, component-by-componentdocs/twilio_setup.md— 5-minute sandbox setupdocs/google_sheets_setup.md— service account + sheetupwork_description.md— copy-paste-ready Upwork portfolio entry
MIT — see LICENSE.
Built by Kirill (@KirillHat). If you want this adapted to your business, hire me on Upwork.






