40% of real estate leads go cold because agents take >5 minutes to respond. Jorge uses one unified conversation system with specialized seller, buyer, and lead-intake handlers behind a single routing layer.
Production system — Automated lead qualification for a real estate agency using GHL webhooks, Claude AI, and Redis. 1,707 tests passing.
Built for Jorge Salas (Acuity Real Estate, Rancho Cucamonga CA) by Cayman Roden / Roden AI Solutions. Processed 500+ inbound leads via GoHighLevel CRM (Jan-Mar 2026) with zero downtime. This is not a tutorial or demo -- it was a deployed, revenue-generating AI system.
| Chat Interface | Lead Activity | Bot Management |
|---|---|---|
![]() |
![]() |
![]() |
| Cost Tracking | Lead Pipeline | Tone Settings |
|---|---|---|
![]() |
![]() |
![]() |
- Missed leads -- The app responds within seconds, not minutes, and routes each contact into the correct qualification path
- Manual qualification is slow -- Structured seller and buyer flows extract budget, timeline, pre-approval status, motivation, condition, and price without agent involvement
- No pipeline visibility -- Admin and dashboard APIs expose canonical mode, status, handoff reason, and next-step state for every conversation
| Metric | Value |
|---|---|
| Tests | 1,707 passing |
| Public model | 1 canonical conversation system |
| Cross-Bot Handoff | 0.7 confidence threshold, circular prevention, rate limiting |
| CRM Integration | GoHighLevel real-time sync |
| Temperature Scoring | Hot/Warm/Cold with automated tag publishing |
| AI Routing | Claude Haiku/Sonnet model selection |
| Deploy | Render (single unified app) + Docker Compose |
| Metric | Value |
|---|---|
| Leads qualified | 500+ since January 2026 |
| Uptime | Zero downtime since launch (24/7) |
| Response time | <500ms average |
| Languages | English and Spanish (no additional staffing) |
Verified operational data from production deployment (Jan-Mar 2026):
| System | Metric | Value | How Verified |
|---|---|---|---|
| Lead Processing | Total leads handled | 500+ | GHL contact records |
| Uptime | Downtime incidents | 0 | Render health checks, 24/7 |
| Response Latency | Average response time | <500ms | FastAPI request logging |
| Webhook Reliability | Deduplication | Two-phase TTL (120s guard + 300s post-success) | routes_webhook.py dedup keys |
| Webhook Reliability | Per-contact lock | Atomic setnx, 90s TTL |
Prevents concurrent message handling |
| Rate Limiting | Global | Per-minute + per-endpoint | rate_limit_middleware.py |
| Rate Limiting | Per-contact | 10 msgs/min | Redis counter with TTL |
| Model Routing | Haiku | Routine tasks (lead categorization) | claude_client.py TaskComplexity enum |
| Model Routing | Sonnet | Complex analysis (qualification) | Cost/quality-aware routing |
| Model Routing | Opus | High-stakes (seller negotiations) | Reserved for critical decisions |
| Prompt Caching | Anthropic cache | Enabled for >1024 char system prompts | cache_read_input_tokens tracking |
| Circuit Breaker | GHL API protection | Opens after 5 failures in 60s, 30s cooldown | GHLCircuitBreaker class |
| Conversation History | Context window | 20 messages (10 turns) max | Prevents context bloat |
| Response Safety | Identity filters | 38 regex patterns | response_filter.py |
| Response Safety | Output truncation | 480 chars at word boundary | SMS-compatible responses |
| Bilingual | Spanish detection | 2+ indicator words from frozen set | Auto-routes to BILINGUAL_HANDOFF |
| Test Coverage | Passing tests | 1,707 | pytest tests/ -q |
| Retry Logic | Anthropic API | Exponential backoff (2s-15s) via tenacity | RateLimitError + InternalServerError |
| If you're evaluating for... | Where to look | Training behind it |
|---|---|---|
| AI / ML Engineer | Claude conversation engine (bots/shared/claude_client.py), confidence-based model routing (bots/shared/business_rules.py), multi-turn memory management |
IBM GenAI Engineering (144h), Microsoft AI & ML Engineering (75h) |
| Backend / AI Automation Engineer | Webhook normalization + dedup + per-contact locking (bots/lead_bot/routes_webhook.py), Redis rate limiting, GHL CRM real-time sync |
IBM GenAI Engineering (144h), Vanderbilt Agentic AI (58h) |
| CRM / Marketing Automation | Full AWARENESS→CONVERSION funnel attribution (bots/shared/funnel_attribution.py), SMS re-engagement sequences (bots/shared/stall_reengagement.py), campaign metrics (bots/shared/sms_metrics_collector.py) |
Google Digital Marketing (190h), Meta Social Media Marketing (83h) |
| Data Analyst / BI | Lead dashboard API (bots/lead_bot/routes_dashboard.py), funnel conversion metrics, per-stage ROI tracking |
Google Data Analytics (181h), IBM BI Analyst (141h) |
→ Full cert-to-code mapping: docs/certifications.md (920h across 8 certifications)
30+ endpoints across webhook routing, lead dashboard, admin controls, and real-time events:
The system runs as a single FastAPI application. Incoming webhooks are normalized, deduplicated, locked per-contact, resolved to a canonical mode, and then dispatched to specialized internal handlers.
%%{init: {'theme': 'dark', 'themeVariables': {'primaryColor': '#D4A574', 'primaryBorderColor': '#C1440E', 'primaryTextColor': '#E2E8F0', 'lineColor': '#C1440E', 'background': '#1A1510'}}}%%
flowchart TB
subgraph Incoming["Incoming Leads"]
Web["Web Forms"]
GHLHook["GHL Webhooks"]
API["REST API"]
end
subgraph App["Unified App :8001"]
Webhook["routes_webhook.py\nUnified orchestrator"]
Dashboard["routes_dashboard.py\n12 dashboard endpoints"]
Admin["routes_admin.py\nBot config & state"]
Realtime["routes_realtime.py\nWebSocket events"]
Lead["Lead Intake\nintent analysis"]
Buyer["Buyer Handler\nQ0-Q4, property matching"]
Seller["Seller Handler\nQ1-Q4, pricing"]
end
subgraph Intelligence["AI & Decision Engine"]
Intent["Intent Decoder\nRegex + semantic analysis"]
Temp["Temperature Scoring\nHot >=80 | Warm 40-79 | Cold <40"]
Claude["Claude AI\nHaiku/Sonnet routing"]
Funnel["Funnel Attribution\nRedis sorted sets, 30-day TTL"]
end
subgraph Infra["Infrastructure"]
Redis[(Redis Cache)]
GHL["GoHighLevel CRM\nTag publishing\nWorkflow triggers"]
end
subgraph Dashboard_UI["Monitoring"]
Lyrio["Lyrio Dashboard\nStreamlit Cloud"]
end
Web --> Webhook
GHLHook --> Webhook
API --> Webhook
Webhook --> Lead
Webhook --> Buyer
Webhook --> Seller
Lead --> Intent
Buyer --> Intent
Seller --> Intent
Intent --> Temp
Intent --> Claude
Lead --> Redis
Buyer --> Redis
Seller --> Redis
Funnel --> Redis
Temp --> GHL
Lyrio --> Dashboard
Real estate agencies lose 40-60% of leads due to slow follow-up. This system:
- Responds to incoming GHL webhooks within seconds
- Qualifies leads using Claude AI conversation analysis
- Books appointments directly into the agency calendar
- All integrations configurable via environment variables — no code changes needed for new verticals
git clone https://github.com/ChunkyTortoise/jorge_real_estate_bots.git
cd jorge_real_estate_bots
pip install -r requirements.txt
# Start the unified app
uvicorn bots.lead_bot.main:app --host 0.0.0.0 --port 8001cp .env.example .env
# Edit .env with your API keys
docker compose up
# App on :8001, Dashboard on :8501Production ran on Render (Jan-Mar 2026), processing 500+ leads with zero downtime. The repo includes render.yaml for Render Blueprint deployment. To redeploy, connect the repo and configure the jorge-env environment group with:
REDIS_URL, GHL_API_KEY, ADMIN_API_KEY, ANTHROPIC_API_KEY, GHL_LOCATION_ID, JORGE_USER_ID, JORGE_CALENDAR_ID
Lead Intake -- Semantic intent analysis plus conservative routing into seller, buyer, bilingual handoff, or human handoff.
Seller Handler -- Structured Q1-Q4 seller qualification, pricing and condition extraction, temperature scoring, and bounded handoff/escalation behavior.
Buyer Handler -- Full buyer qualification flow (Q0-Q4), preference extraction, temperature scoring, and weighted property matching.
| Layer | Technology |
|---|---|
| API | FastAPI (APIRouter pattern), Pydantic, uvicorn |
| Dashboard | Streamlit (Lyrio), Plotly |
| AI | Claude (Haiku/Sonnet routing) |
| Cache | Redis (sorted sets, rate limiting, bot state, funnel attribution) |
| CRM | GoHighLevel (webhooks, custom fields, workflows) |
| Testing | pytest, pytest-asyncio (1,707 tests passing) |
Directory layout (click to expand)
jorge_real_estate_bots/
├── bots/
│ ├── shared/ # Config, Claude client, GHL client, cache, auth,
│ │ # funnel_attribution, stall_reengagement,
│ │ # bot_metrics_collector, alerting_service,
│ │ # sms_metrics_collector, response_filter
│ ├── lead_bot/
│ │ ├── main.py # FastAPI app, includes all routers
│ │ ├── routes_webhook.py # GHL webhook dispatcher (unified + new-lead)
│ │ ├── routes_dashboard.py # 12 dashboard/alert endpoints
│ │ ├── routes_admin.py # Bot settings, reassign, reset state
│ │ ├── routes_realtime.py # WebSocket events, recent events
│ │ ├── routes_productization.py # Playbooks, reports
│ │ └── routes_test_endpoints.py # Hardening test endpoints
│ ├── seller_bot/ # Q1-Q4 qualification, CMA engine
│ └── buyer_bot/ # Buyer qualification + property matching
├── database/ # SQLAlchemy models, async session
├── command_center/ # Streamlit dashboard components
├── tests/ # 1,707 passing tests
├── docker-compose.yml # Redis + app + dashboard
├── render.yaml # Render Blueprint config
└── Dockerfile
All endpoints are served from a single app on port 8001. Run uvicorn bots.lead_bot.main:app and visit /docs for the interactive reference.
Full endpoint listing (click to expand)
POST /ghl/webhook/new-lead-- Compatibility entrypoint for new leadsPOST /api/ghl/webhook-- Unified inbound webhook and canonical routing/orchestration pathPOST /api/ghl/webhook/message-status-- SMS delivery status callbacks
GET /api/dashboard/metrics-- System + performance metricsGET /api/dashboard/leads/summary-- Hero metrics + conversation summaryGET /api/dashboard/leads-- Paginated lead list (filterable by temperature)GET /api/dashboard/leads/{contact_id}-- Single lead detailGET /api/dashboard/handoffs-- Recent handoff events (with contact_id)GET /api/dashboard/conversations/{contact_id}-- Q&A transcriptGET /api/dashboard/costs-- Cost/ROI data, commission pipelineGET /api/dashboard/sms-metrics-- SMS delivery stats (7-day rolling)GET /api/dashboard/funnel-- Funnel conversion by stage (AWARENESS through CONVERSION)GET /api/dashboard/stall-stats-- Stall re-engagement stats (optional ?contact_id filter)GET /api/alerts/active-- Active alertsPOST /api/alerts/{alert_id}/acknowledge-- Acknowledge an alert
GET /admin/settings-- Current bot settingsPOST /admin/reassign-bot-- Reassign contact to a canonical modePUT /admin/settings/{bot}-- Update bot configurationDELETE /admin/reset-state/{bot}/{contact_id}-- Reset conversation stateGET /admin/conversations/{contact_id}-- Canonical conversation state detail
GET /api/events/recent-- Recent events (filterable, since_minutes, event_types)GET /api/events/ws-status-- WebSocket connection healthGET /api/events/health-- Event system health (Redis check)WS /ws/events-- Live event stream
Analyze a new lead:
curl -X POST http://localhost:8001/analyze-lead \
-H "Content-Type: application/json" \
-d '{
"contact_id": "abc123",
"name": "Maria Santos",
"email": "maria@example.com",
"phone": "+1-555-0142",
"message": "Looking to buy a 3BR home in Coral Gables under $650k. Pre-approved with Chase.",
"source": "website"
}'Get funnel conversion data:
curl http://localhost:8001/api/dashboard/funnel \
-H "X-Admin-Key: YOUR_ADMIN_KEY"Get stall stats:
curl http://localhost:8001/api/dashboard/stall-stats \
-H "X-Admin-Key: YOUR_ADMIN_KEY"See docs/TROUBLESHOOTING.md for solutions to common issues: GHL webhook setup, Redis connection errors, environment variable checklist, HTTP error codes, and bot handoff failures.
Production Handoff Documentation (for operators -- click to expand)
The canonical production-finalization and handoff package lives in docs/:
- JORGE_V2_PRODUCTION_HARDENING_SPEC.md
- JORGE_OPERATOR_RUNBOOK.md
- GHL_CONFIGURATION_CONTRACT.md
- MIGRATION_CHECKLIST_CANONICAL_STATE.md
- COMPATIBILITY_SHIMS.md
- JORGE_GHL_WORKFLOW_INVENTORY.md
- JORGE_GHL_EXPORT_CAPTURE.md
- JORGE_LIVE_VALIDATION_CHECKLIST.md
- JORGE_PRODUCTION_HANDOFF_SIGNOFF.md
Helper scripts for finish-line verification:
# Verify canonical DB schema against a live database
DATABASE_URL=... python scripts/check_conversation_schema.py
# Hit deployed health/admin/dashboard endpoints and emit a readiness report
ADMIN_API_KEY=... JORGE_CONTACT_ID=... python scripts/production_readiness_report.py --base-url https://jorge-realty-ai-xxdf.onrender.com
# Validate live or exported GHL tags/custom fields/workflows against the contract
GHL_API_KEY=... GHL_LOCATION_ID=... python scripts/validate_ghl_contract.py --ghl-api-key "$GHL_API_KEY" --location-id "$GHL_LOCATION_ID"
# Export the live workflow list and heuristic workflow-risk summary
GHL_API_KEY=... GHL_LOCATION_ID=... python scripts/export_ghl_workflows.py --ghl-api-key "$GHL_API_KEY" --location-id "$GHL_LOCATION_ID" --json-output docs/ghl_workflows_export.json --md-output docs/ghl_workflows_export.md
# Generate a dry-run plan for creating missing canonical GHL tags/fields
GHL_API_KEY=... GHL_LOCATION_ID=... python scripts/sync_ghl_contract.py --ghl-api-key "$GHL_API_KEY" --location-id "$GHL_LOCATION_ID"
# Review extra live GHL tags/fields for likely routing or handoff risk
GHL_API_KEY=... GHL_LOCATION_ID=... python scripts/review_ghl_legacy_contract.py --ghl-api-key "$GHL_API_KEY" --location-id "$GHL_LOCATION_ID" --output docs/ghl_legacy_contract_review.md
# Run the repo-side production-finalization helpers and write outputs to docs/
JORGE_LIVE_URL=... ADMIN_API_KEY=... JORGE_CONTACT_ID=... DATABASE_URL=... bash scripts/run_production_finalization.shpytest tests/ -v # Full suite
pytest tests/shared/ -v # Shared services
pytest tests/api/ -v # Dashboard & API routes
pytest tests/lead_bot/ -v # Realtime eventsSee CHANGELOG.md for release history.
- EnterpriseHub -- Full real estate AI platform this was extracted from, with BI dashboards and CRM integration
- Lyrio Dashboard -- Streamlit analytics dashboard with AI concierge, connected to Jorge API
- ai-orchestrator -- AgentForge: unified async LLM interface (Claude, Gemini, OpenAI, Perplexity)
Developed by Cayman Roden (Roden AI Solutions) as a production engagement for Jorge Salas (Acuity Real Estate). The system has been in continuous production since January 2026.
- GitHub: ChunkyTortoise
- Portfolio: EnterpriseHub
MIT







