Skip to content

Leads PilotU.S. — Remote

Leads Pilot — Automating the Lead Hand-Off for a Pay-Per-Lead SMS Agency

Qualified leads used to be retyped by hand. Now 97.6% are delivered by a bot, across 133 contractor accounts

Workflow AutomationAI ClassificationGoHighLevel APIChrome Extension
Leads Pilot
0% → 97.6%

Leads delivered by the bot368 of 377 on Oct 13; every one was retyped by hand before Sep 25

1 → 133

Accounts on the form botrolled out between Sep 25 and Oct 15, 2026

1,300+

Dead replies cleared dailyper weekday by early October: STOP, no and wrong-number replies the team used to clear by hand

Context

Leads Pilot sells pay-per-qualified-lead SMS outreach to U.S. home-service contractors: mostly painters, plus roofing, gutters, holiday and permanent lighting, and windows. A team of senders texts homeowners from each contractor's GoHighLevel account, qualifies the people who reply, and hands every qualified lead to the contractor.

Leads Pilot's site: pre-qualified leads for contractors, paid per leadOpen live

I ran the queue by hand before automating any of it, the same run-it-manually-first loop that came out of Systemic Digital. Everything below was built against something that slowed the work down.

The Challenge

  • Inbox noise. Most replies to an SMS blast are STOP, no, or wrong number. Senders scrolled past hundreds of them a day to find the real leads, in every contractor's inbox.
  • Hand-typed hand-offs. Every qualified lead was retyped into the contractor's lead form by a sender. It was slow, and one typo sends a contractor the wrong phone number.
  • Blast sizing. GoHighLevel's "select all" selects a page of contacts, not a number. Texting exactly the right number of uncontacted people meant counting by hand.

What I Built

Sift, a Chrome extension. It loads exactly the number of uncontacted contacts a sender asks for onto one page, so "select all" picks exactly that many. Handed to the sender team in mid-August 2026.

The intent filter. Every three minutes through the working day, it reads each unread conversation in the accounts being worked that day, the whole thread rather than the last message. Fixed rules catch the obvious replies at no cost. Everything else goes to a typed classifier that must choose from a fixed list of labels and report its confidence; below 0.7 it answers UNSURE, and the conversation stays with a human. Clear rejections are marked read and logged to an audit sheet. Once an hour, Claude re-reads the removals, restores any mistake, and pulls buried "yes" replies back into the queue. The filter never sends a message.

The intent filter: unread replies pass through free rules, then a typed classifier with a confidence floor; unsure replies stay with a human, and an hourly review restores mistakes

The form bot. A sender tags a lead qualified and notes who qualified it. The bot writes the same lead details a sender would have typed, from a fixed template, with AI writing only a sentence or two about what the homeowner wants. It then tags the contact lead-sent, which fires the contractor's own notification workflow. A watchdog flags any lead that hasn't reached its contractor within ten minutes.

The form bot: a sender tags a lead qualified, the bot writes the lead details, tags it lead-sent, the contractor's workflow fires, and a watchdog flags anything not delivered within ten minutes

Trade variants. One codebase with a settings file per trade, five niches beyond painting so far, so adding a new niche is configuration rather than a fork.

The stack: Python, the GoHighLevel API, Claude, a typed classifier with a confidence floor, SQLite, Google Apps Script and Sheets for the audit trail, a DigitalOcean server running everything as services, and a Manifest V3 Chrome extension. I build with Claude Code as my pair: I design each system, direct the sessions, review and ship.

Results

Rollout over time: contractor accounts covered by the intent filter and by the form bot, September 15 to October 16, 2026
  • 0% → 97.6% of qualified leads delivered by the bot. On October 13, 368 of 377 went out with nobody typing them; nine were done by hand.
  • 1 → 133 contractor accounts on the form bot between September 25 and October 15.
  • 1 → 112 accounts on the intent filter in its first two weeks. By week three it was clearing 1,300 to 2,300 dead replies per weekday that senders used to clear by hand.
  • 2.5 minutes, median, from the sender's hand-off note to the bot's send (90th percentile 4.9 minutes, measured on 53 sends on October 6).
  • No double deliveries. 916 unique homeowners delivered in the week of September 28, none of them sent twice.
  • 96% of the filter's removals confirmed by the hourly review; the rest were restored automatically.

Timeline

  • June 2026. Working the SMS queue by hand.
  • Mid-August. Sift handed to the sender team.
  • September 15. Intent filter live on its first account, moved to its own server two days later.
  • September 25. First lead delivered by the form bot.
  • September 28. Intent filter covering 112 accounts.
  • October 6–7. Trade variants live: five niches beyond painting.
  • October 15. Form bot covering 133 accounts.

What I'd repeat

Make the AI choose from a list and admit when it isn't sure. The classifier can't invent a label, and when it isn't confident it says so and a human gets the message. That rule, plus an hourly second opinion that can undo any removal, is what makes it safe to let a machine clear thousands of messages a day.

Hook into the client's own workflow instead of replacing it. The form bot doesn't notify contractors itself; it writes the same details a sender would and lets each contractor's existing workflow fire. Nothing about how a contractor receives leads had to change, which is why it could roll out to 133 accounts in three weeks.

Need a similar engagement?

Book a call →