Sandesh Shrestha
Sandesh Shrestha
Sep 2026 - Present/Advanced
Live DemoArrow Up Right
LockCodebase is confidential

Case Study: ARG Smart Reply - Human-Approved AI Lead Automation

Project at a Glance

  • Role: Full-Stack / Automation Engineer (API, Puppeteer worker, AI drafting, dashboard, deploy)
  • Duration: Sep 2026 - Present
  • Live: app.americasrealtygroup.org
  • Stack: React, Vite, TypeScript, Express, Prisma, PostgreSQL, Redis, BullMQ, Puppeteer, OpenAI/OpenRouter, Docker, Nginx, Bull Board
  • Scale: ~55,000 lines of code, 25 Prisma models, multi-queue worker with browser automation lanes
  • Client context: America's Realty Group - SmarterContact inbox automation with strict human approval gates

Problem

Real-estate lead inboxes move fast. Manually answering every SmarterContact conversation does not scale, but fully autonomous AI senders destroy trust and compliance. ARG needed automation that drafts like a skilled SDR, never sends without a human click, and still follows up when leads go quiet.

What I Built

End-to-end reply loop with a hard human gate

  • Puppeteer worker logs into SmarterContact and crawls the inbox on a schedule
  • Passive GraphQL interception (reads what the browser already requests - does not invent brittle private API calls)
  • AI drafts a reply, or classifies a hard decline and closes the conversation with no draft
  • Operators review/edit in the dashboard and Approve or Deny
  • Only Approve enqueues a rate-limited send job; Deny disqualifies without redraft spam

Follow-up cadence that respects silence

  • Hourly scan for conversations where we sent last and got no reply for 48h+
  • Automatic multi-step follow-up sequence with policy controls
  • Send caps (hourly/daily) and emergency pause switches for operational safety

Operator dashboard

  • Login, Dashboard, and Leads views with near-real-time polling
  • Draft review UX tied to the exact conversation in SmarterContact
  • Bull Board queue visibility for poll, send, follow-up, and scan jobs

Production-hardened automation

  • Same TypeScript codebase, two entrypoints: API server + worker
  • Redis browser lease so only one Chromium owner runs at a time across container restarts
  • Docker Compose production path (ALB or self-managed TLS via Nginx/Let's Encrypt)
  • Strict CORS in production, structured logging, smoke scripts for selectors/send paths

Architecture Highlights

SmarterContact (browser)
        ^
        | Puppeteer lanes (poll / send / follow-up / backfill)
        |
 Redis + BullMQ workers  <----->  Postgres (Prisma domain)
        |
        v
 Express API  <----->  React dashboard (approve / deny / edit)
        |
        v
 Nginx TLS @ app.americasrealtygroup.org

Hard Problems I Solved

  • Browser automation that survives production: Chromium crashes, singleton locks, and session expiry are normal. Built lease + recovery paths so a dead tab does not brick the whole worker.
  • AI that knows when to shut up: Decline detection closes conversations permanently instead of inventing "just checking in" spam.
  • Trust boundary: Nothing outbound without Approve. Follow-ups are explicit policy, not sneaky autonomy.
  • Queue correctness under concurrency: DraftRequest as source of truth, leases during long AI calls, discard superseded drafts when a newer inbound arrives.
  • Selector/DOM fragility: Smoke tests and archived discovery contracts document SmarterContact shapes so UI changes are diagnosable.

Results & Impact

  • Live at app.americasrealtygroup.org for America's Realty Group operators
  • Lead replies draft continuously while humans stay in control of every send
  • Quiet leads get a disciplined follow-up cadence instead of falling through cracks
  • Ops can pause queues instantly when the market or inbox behavior changes

What This Shows About Me

  • I build automation systems with safety, rate limits, and human control - the difference between a demo bot and a production SDR engine
  • I am comfortable owning Puppeteer + queues + AI + React admin in one vertical slice
  • I design for failure modes (browser death, API flakiness, superseded drafts), not happy-path scripts
  • I can take a messy third-party web app and turn it into a reliable internal product

Links

Note: The codebase is confidential and not publicly available.