Full System Architecture

How Every Lead Becomes a
Booked Repair

From first contact to confirmed appointment — every stage Gabby moves a customer through, every timer, every handoff.

5+
Entry Sources
~Minutes
Response Time
4+
Objection Types
6
Background Systems
GPT-4o Powered Conversations
Twilio SMS Delivery
Supabase + PostgreSQL Data Layer
Redis Session Memory
n8n Automation Workflows
35+ Years PDR Expertise
01
Entry Sources
🧠
DentIQ Form
Smart intake form on dentlegit.com. Captures vehicle, damage type, and estimate range before Gabby opens.
Warm Lead
💬
Inbound SMS
Customer texts the business number directly. Gabby receives and takes over the conversation automatically.
Direct
🌐
Website Widget
Chat widget on denttime.com. Captures phone number and bridges to SMS conversation.
Web-to-SMS
📋
Opt-In Forms
Lead capture pages and marketing funnels. Number entered → conversation seeded → Gabby opens.
Marketing
📞
Retell AI Calls
After a Retell voice call ends, webhook fires → Gabby sends SMS follow-up with next steps.
Post-Call
02
Intake & Routing Logic
🔎
Number Lookup
Incoming phone number checked against PostgreSQL. Known customer? Existing conversation? Determines greeting path and context to load.
🧩
Context Assembly
System pulls: prior conversation history (Redis), DentIQ lead data (Supabase), customer record, vehicle info, prior estimate. All fed into GPT-4o as context before Gabby opens.
🚦
State Detection
Is this a new lead? DentIQ warm lead? Post-handoff follow-up? Returning customer? State determines which opener path Gabby uses and what she says first.
📸
Photo Handling
MMS photos are uploaded to Supabase storage (dent-photos bucket). Public URL saved to lead record. Myke reviews via War Room admin panel.
🪞
Same-Number Guard
Twilio will error (21266) if To = From. Guard compares digit-stripped numbers before sending. Returns status: 'skipped' if they match — prevents Myke's business number from triggering itself.
🔁
Stale Convo Guard
If a DentIQ lead seeds onto a phone number with a prior completed handoff, Gabby would enter post-handoff mode incorrectly. Fix: always use a fresh number for testing; system checks lead creation time vs. convo age.
03
Gabby's Opening Paths
DentIQ Form Lead
Warm & Personal Opener
"Hey [name]! This is Gabby from Dent Time — I saw your [vehicle] came through the form with what looks like [damage type]. We can usually handle that for [estimate range]. Want to get a closer look?"
References vehicle + estimate range from form data. Does NOT immediately hand off — Gabby opens the conversation first.
Cold Inbound SMS
Curious & Direct Opener
"Hey! This is Gabby with Dent Time. Looks like you reached out — what's going on with your vehicle? Happy to take a look and get you some info."
No prior context. Gabby opens warm, asks what's up, gets them talking before going to photos.
Post-Retell Call
Follow-Up SMS Opener
"Hey [name] — Gabby here, following up on your call. Just wanted to make sure you have everything you need to take the next step. What works best for you?"
Webhook fires after call ends. Gabby picks up conversation in SMS with full call context.
Returning Customer
Recognition Opener
"Hey, good to hear from you again! What are we working with this time?"
System detects prior customer record. Gabby acknowledges the history without being creepy about it.
Opt-In / Marketing
Offer-Aware Opener
"Hey [name]! This is Gabby from Dent Time — you came through our form about [offer or campaign]. Here's what we can do for you..."
Ties conversation back to what they opted in for. Context from form data shapes the angle.
Website Widget
Chat-to-SMS Bridge
"Hi! I'm Gabby from Dent Time. I can answer your questions and get you an estimate — what's the damage situation?"
Conversation starts in chat widget, bridges to SMS when phone number is captured.
04
Conversation Engine
GPT-4o — Gabby
Dent Time's AI front desk · 35+ years PDR knowledge · conversational, confident, never salesy
📖 System Prompt
~1,800+ word prompt defining Gabby's personality, brand voice, objection protocols, DentIQ handling, handoff triggers, and post-handoff behavior. Lives in src/prompts/systemPrompt.js
🧠 Memory (Redis)
Last N turns of the conversation stored in Redis (Valkey). Injected as context each message. Session persists across texts, even hours apart. Auto-healer watches for Redis reconnect loops.
💼 Lead Context Injection
DentIQ intel (vehicle, damage, estimate), customer history, prior appointments, and photo links injected at conversation start. Gabby opens knowing who she's talking to.
🎙️ Voice / Tone Rules
Short, real sentences. No corporate fluff. Dry confidence. She educates — doesn't sell. Uses "courtesy adjustment" not "discount." Knows when to stop talking.
📷 Photo Request Logic
Asks for photos when damage type and scope aren't clear. Once photos arrive, uploads to Supabase, notifies Myke via Telegram, and sets status to "Pending Estimate."
🚫 Post-Handoff Exception
After handoff, Gabby gives ONE closing line — then goes quiet. Exception: price/competition/trust/timing objections after handoff → Gabby re-engages with full objection protocol instead of silence.
05
Objection Handling Protocol
Philosophy

The objection handlers are a knowledge base, not a script. Gabby riffs on the themes. Her goal: help the customer make an informed decision — not close them, not convince them. Educate → Observe → Probe → Respond → Step Back.

💰
Price / Budget
"That's a lot" · "Other places are cheaper" · "Can you work with me?" · "I need to shop around"
1
Observe: "Price came in higher than expected"
2
Probe: "What were you thinking the ballpark would be?"
3
Educate: factory paint, no CarFax, lifetime warranty
4
Qualify + offer courtesy adjustment if needed
👫
Spouse / Partner
"Let me talk to my husband" · "Have to run it by my wife" · "Need to check with my partner"
1
Acknowledge naturally — don't treat it as an objection
2
Probe: "Price, timing, or just want them in the loop?"
3
Offer Myke for direct specialist conversation
4
No pressure — give them space, stay available
🤔
Trust / PDR Skepticism
"Not sure PDR really works" · "Heard mixed results" · "Seems too good to be true"
1
Validate: "Makes sense — you don't know us yet"
2
Probe: "Bad experience before, or just new territory?"
3
Credibility: Since 1991, lifetime warranty, factory finish
4
Offer Myke walkthrough — let the work speak
⏱️
Timing
"Maybe in a few weeks" · "I'm busy right now" · "Let me think about it" · "Not ready yet"
1
Zero pressure response: "Totally up to you"
2
Probe: "Schedule issue or something else?"
3
Inform: summer heat can set metal — sooner is easier
4
Leave door open: "Whenever you're ready, we're here"
🏪
Competition
"Dealer quoted me less" · "Another shop said $X" · "Your competitor is cheaper"
1
Don't panic or immediately undercut
2
Probe: "Was that quote for PDR or a different method?"
3
Explain: cheaper = paint/filler → shows on CarFax
4
Honest: "Send it — we'll give you a real comparison"
🎁 Courtesy Adjustment (Step 4)
Only after: probing done → concern heard → empathetic response → still hesitant → qualification confirmed.
Ask first: "First time with us, or returning?"
~5% · never call it a "discount"
Offer ONCE — if declined, move on
Never before probing
Never promise a dollar amount
Never use the word "discount"
Step 5 — Graceful Step Back (When to Escalate)
You've done your part when:
Educated on PDR and why pricing varies
Asked genuine follow-up and heard real concern
Offered appropriate next step (estimate, consult, visit)
Customer asked for Myke directly
Complexity beyond what a photo can tell (multi-panel, HSS)
Warm handoff phrasing:
"I've given you what I know — Myke can see it in person and lock in a real number. Let me get my specialist."
"Best thing at this point is to have Myke look at it directly. Let me get my specialist for you."
"Let me get Myke" — no context, cold, abrupt
06
Follow-Up Timers
Initial Follow-Up
10 min
If no reply after first outreach, Gabby sends a short nudge to re-engage. Designed for speed — most leads go cold within 30 minutes.
Fires 10 min after first message if no response
🛑Suppressed if DentIQ exit-path fired (book/specialist)
🛑Suppressed if handoff already completed
Photo Reminder
24 hrs
If Gabby asked for photos and none have arrived after 24 hours, she sends a friendly reminder with instructions.
📸Only fires if photo_requested = true and no photos received
🛑Cancelled if photos arrive before timer fires
🛑Cancelled if customer goes to handoff before 24hrs
DentIQ Re-Enable
Manual
War Room "Re-enable Follow-up" button resets booked=false and clears first_contact_sent_at so WF1 can send the 10-min follow-up again.
🖱️Triggered manually from War Room discussion tab
🔍Only shown for DentIQ leads (form_source = 'dentiq')
🔁POSTs to /api/admin/dentiq/reenable-followup
07
Specialist Handoff
Handoff Trigger Phrase
"let me get my specialist"
When Gabby says this phrase, conversationManager.js detects it and fires the handoff event — notifying Myke via Telegram and updating lead status.
📲
Telegram Notification
Myke gets an instant Telegram message: customer name, phone, vehicle, damage summary, photos link, and conversation transcript. All the context to respond immediately.
📋
War Room Card
Lead card in the admin War Room updates to "Specialist Requested" status. Full conversation thread, photos, and customer intel visible in one panel.
🤫
Gabby Goes Quiet
After handoff, Gabby sends ONE warm closing line, then stops responding. Exception: if customer raises a price/trust/competition/timing objection — Gabby re-engages with full objection protocol.
08
System Actions
💬
Send SMS
Twilio sends outbound SMS from the Dent Time number. Full error handling, rate limiting, and same-number guard built in.
☁️
Upload Photo
MMS attachments uploaded to Supabase dent-photos bucket. Public URL saved to lead record in PostgreSQL.
📲
Telegram Alert
Sends Myke an instant alert via Telegram bot. Used for new photos, handoff events, system errors, and daily health digest.
📊
Update Lead Record
PostgreSQL lead table updated: status, handoff flag, photo count, last message timestamp, booked flag, first_contact_sent_at.
📝
Weekly Digest
Every Monday 7am, n8n cron fires → POST /api/admin/dentiq/weekly-report → GPT-4o summary of last 7 days → Telegram DentIQ channel.
09
Background Systems
🏥
UptimeRobot
Pings the health endpoint every 5 minutes. Myke gets an alert if the chatbot goes down. First layer of monitoring.
GET https://chatbot.denttime.com/health · 5 min interval
⚙️
n8n Error Monitor
Error Trigger node on all 25 active n8n workflows. Any failure → Telegram alert to Myke with workflow name and error details.
WF: MM22WDukNrhI9mhf · Error Trigger → Telegram
📅
Daily Health Digest
Every morning at 8am, n8n checks chatbot health + DB stats (lead count, conversation count, handoffs) and sends a summary to Myke via Telegram.
WF: Phn30hz4pQM8eKQg · cron 0 8 * * *
🔧
Redis Auto-Healer
Shell script on DigitalOcean cron every 5 min. Detects Redis reconnect loops (10+ "Reconnecting" hits in logs), auto-restarts PM2, sends Telegram alert.
/opt/apps/redis-healer.sh · Log: /var/log/redis-healer.log
📈
Weekly DentIQ Digest
Every Monday 7am — n8n fires POST to weekly-report endpoint. GPT-4o generates a 7-day summary of DentIQ leads, conversion rate, and follow-up gaps. Sent to Telegram.
WF: s3GgLUl6KZc6Q1uE · cron 0 7 * * 1
🏗️
PM2 Process Manager
Node.js app runs under PM2 as the denttime user on DigitalOcean. Auto-restarts on crash. Nginx reverse proxies HTTPS to port 3000.
app: dent-time-chatbot · server: 143.198.69.46