How it started
This was my capstone for GTM Engineer School, Cohort 4, in 2026. The school handed us a sheet of real companies with real GTM problems, and we each picked one and reached out to the contact. Mine was a training firm in the Middle East that runs bootcamps for people moving into consulting.
What was going wrong
Their biggest problem, the way they put it, was getting qualified leads consistently for expensive courses. Outreach, targeting and follow-up were all being done by hand, in bits and pieces. So they couldn't tell who was actually close to buying, couldn't personalise at any kind of scale, and couldn't see which channels were working.
What I found
I went through 130 LinkedIn profiles of people who'd already paid for the bootcamp. Job title and industry barely came into it. What they had in common was where they were in their careers. They'd been stuck in the same role for years, and lately they'd started looking for a way out.
A filter wouldn't have caught that. You'd have to sit down and sift through someone's profile, and no sales team has time to do that for every name on a list. So I built the engine to do the reading for them.
What I built
The engine reads someone's public profile and posts, then scores how close they are to buying. Every score comes with its reasons. It says what's pushing them to make a move and what's holding them back, and ties each one to something they posted. For the people worth talking to, it writes a short sequence of messages, and every claim in those messages links back to the post it came from.
The first version was an AI agent running on an open-source framework called Hermes. It worked, but it was doing a lot of deciding for itself, wandering off between steps, and every extra step cost money. It felt like a tool I was using for the sake of using it. Then the client's security policy ruled out open-source agent frameworks, which settled it.
So I ditched the agent and rebuilt it as a plain Python program. Claude Code did the coding. I told it exactly what to build. It runs the same steps in the same order every time. The rebuild took three days, and these days I ask about a client's security rules before I pick a single tool.
Guardrails
Before anything costs money, a free check throws out anyone who clearly doesn't fit. Every paid call gets logged with what it cost, and a batch won't even start if it would go over the spend cap. If someone swaps in an AI model the system doesn't have a price for, it refuses to run instead of quietly logging the cost as zero.
To stop the AI making things up, a coded check goes through every message before a person sees it and flags any claim that doesn't trace back to a source.
The engine only drafts, it never sends. I wanted someone on the sales side to check every message before it goes anywhere.
What the sales team sees
There are two tabs the screens above don't show. The board is the full list of leads, which the team can filter by tier, persona, country or status, save as a view, and export to CSV. The status tab follows each lead from contacted through to booked, and if one drops out, the reason goes in there too.
Screens from the running system. Client name and real people replaced with sample data.
What broke
In a live test run, the AI wrote two messages around a "peer" called Loai, with a career story to match. Nobody had given it any of that. The check I had at the time read each message on its own and flagged nothing. I caught it because I read the output myself.
So I added a check that reads the whole sequence together. It stops any named person who isn't backed by the lead's own data, and it catches the same phrase turning up in two different messages. It still doesn't replace a person reading it, though.
What the numbers say
I ran the engine against the client's own records for 32 past graduates: 17 who went on to land consulting work and 15 who didn't. People with momentum in their careers, meaning a recent move they'd chosen to make themselves, showed up 4 to 6 times more often in the first group. It's a small sample, so it points in a direction more than it proves anything.
The same test showed one of my rules was backwards. It was about people who'd hit a dead end and then started moving again, and it was pointing the opposite way to what the data said. So I flipped it.