Features · deep dive

Every surface, with the file paths.

Five product surfaces. For each one: what it does, how it's wired, and the specific safety machinery that exists so an engineer can't silently regress it.

01

Inbound email pipeline

SendGrid Inbound Parse → multi-stage AI safety chain → reply.

  • Webhook secret verified with crypto.timingSafeEqual; production rejects unsigned
  • SendGrid raw + parsed modes both supported (parses MIME when raw)
  • Lead lookup keyed strictly by email (or phone for SMS) — never both
  • Idempotent reply: SHA256 hash over (lead, message, minute) prevents retry duplicates
  • Per-channel system prompt assembled per request from dealership profile + agent identity
  • Inventory-grounded smart-component dropped if confidence < threshold (no hallucinated cars)
  • Post-generation chain: stripEmDashes → stripUngroundedClaims → HTML sanitizer
Files
app/api/webhooks/email/route.ts · trigger/SendResponse.ts · lib/prompts/emailSystemPrompt.ts
Why it matters

Inbound message answered in under a minute, in the dealership's voice, without quoting a price the AI shouldn't.

02

Outbound campaigns with AI targeting

Describe the audience in English; the assistant translates to a typed Supabase query.

  • Vercel AI SDK generateObject with zod schema — never returns free-text SQL
  • Two modes: chat (t=0.6) and analysis (t=0.1) auto-detected from intent
  • On error returns 4xx/5xx — explicitly never falls back to 'all leads'
  • Operator confirms the resolved segment before fan-out
  • A/B variants split into leads_a / leads_b at confirm time, reproducible at re-send
  • Trigger.dev v3 fan-out — one job per lead, observable in the Trigger dashboard
  • Lead-field interpolations HTML-escaped via lib/text/escapeLeadField
Files
/api/campaigns-ai · /api/campaigns/[id]/trigger · trigger/sendCampaign{Emails,Sms}.ts
Why it matters

"Everyone who asked about a RAV4 in 30 days and never replied" — typed query, confirmed segment, two-stage safety, real send.

03

Embedded chat widget

One <script> tag. Shadow DOM (not iframe). Per-widget Origin allow-list.

  • Loader served from /widget.js with controlled CORS / CORP / cache headers
  • Renders inline via Shadow DOM so host-page CSP can't block it
  • Pre-conversion transcripts buffer in widget_sessions.messages_buffer (no CRM clutter)
  • Promotes to a real leads row only when contact info (regex EMAIL_RE / PHONE_RE) appears
  • Per-widget allowed_origins[] checked against the request's Origin header — primary abuse gate
  • Inventory query inline so 'do you have a RAV4?' answers immediately
  • 8-hour session TTL — kiosk-safe (next visitor doesn't inherit prior lead)
Files
app/widget.js/route.ts · app/api/widget/chat/route.ts · widget_sessions table
Why it matters

Customer asks 'do you have a 2024 RAV4?' on the dealership site; gets a real answer + scheduled callback.

04

Lead pipeline

One lead row per customer, captured from any channel.

  • Six capture sources: email, SMS, voice, widget conversion, CSV upload, ADF feed
  • Lookup keyed by ONE of email or phone (never both) — shared landlines don't merge customers
  • Conversation history filtered per channel — email ≠ SMS thread
  • Lead scoring materialized to leads.lead_score (0–100), drives queue ordering
  • DNC flags (do_not_email, do_not_mail) honored on outbound; SMS opt-out via lib/compliance/sms
  • next_followup column drives the appointment-reminder Trigger task
Files
supabase-actions/leads/getLeadByEmailorPhone.ts · lib/leads/{deduplication,routing,validation}.ts
Why it matters

Lead history is one queryable timeline per customer, not a pile of duplicate rows from cross-channel double-counts.

05

Voice (Twilio + personaplex)

Twilio handles the carrier; a separate Python service handles voice cloning.

  • Inbound voice → /api/twilio/incoming-call → /api/twilio/process-speech (TTL-mapped state)
  • STT + intent extraction in-app via OpenRouter; system prompt from voiceSystemPrompt.ts
  • Voice cloning service is a separate FastAPI app (personaplex-service) — independent scaling
  • WebSocket bridge to personaplex-service authed via BRIDGE_SECRET signed token
  • Recording disclosure prompt wired into the call-open path
  • Outbound voice campaigns via trigger/aiCallAgent.ts
Files
app/api/twilio/* · lib/voice/* · personaplex-service/server.py
Why it matters

Inbound calls answered by an AI that knows the dealership's hours, current inventory, and what to never quote.

Want to see it in your stack?

Two weeks. One channel. Real reps.