The problem
GTM teams do not need more lists. They need to know which accounts have a reason to be contacted this week and why.
A static list of good-fit companies is stale the day you build it. A company that fit your ICP eighteen months ago and a company that just hired its first RevOps lead are not the same opportunity, and nothing in a normal prospecting database can tell them apart.
The system
Eight stages, running on a schedule in n8n, self-hosted in Docker.
Discovery. Three RSS sources merged, deduplicated and limited, plus an HTTP pull.
Classification. A model decides one thing only: is this an AI-GTM company as defined, or is it something adjacent — a research lab, a consumer AI product, an infrastructure vendor? Each rejection is written back with its reason.
Scoring. Deterministic. The model never returns a score.
Signal decay. Every signal carries a detected date and a freshness multiplier. Under 30 days it counts fully, 30 to 90 days at 0.6, 90 to 180 at 0.25, and past 180 days it counts for nothing.
Contact intelligence. Role targets, not scraped individuals: Head of Marketing, Head of Growth, Founder, VP Sales, Head of RevOps, each with a written rationale for why that role would care.
Suppression. Every surfaced contact gets a cooldown date. Nothing resurfaces inside it.
State. Google Sheets, one tab per concern: Companies, Signals, Contacts, Suppression, Partners, Runs. Every run writes a row to Runs.
Output. A Slack digest listing what qualified, what was rejected and why, and which contacts to look at.
The decisions
The model classifies. The code does the maths.
The tempting build asks the LLM for a score out of 100. It will happily give you one, and the number will be unreproducible, unexplainable and different next Tuesday for the same input.
So the split is: fuzzy judgment to the model, arithmetic to the code. Is this an AI-GTM company is a judgment call, and a model is good at it. What is this account worth this week is arithmetic over signals, weights and dates, and code is good at that.
The result is that every score can be recomputed by hand from the sheet. That is the difference between a system an operator trusts and one they quietly stop using.
Rejections are written down, with reasons
Most scoring systems discard what they reject. This one writes every rejection back with its reason.
That turns the reject pile into the most useful table in the system. If “at research labs” is rejecting thirty companies a week, either the definition is wrong or the source is wrong, and you can only see that if the rejections are recorded.
The engine stops at a recommendation
It discovers, classifies, scores, finds contacts and hands a human a digest. It sends nothing.
That boundary is not timidity. An automated send is irreversible and lands on a real person, and the cost of being wrong is a burned domain. Everything upstream of that is reversible, so everything upstream of that is automated.
Where this came from
I built this as the technical assessment for a GTM Engineer engagement. It won the engagement, and the four things I shipped once I was inside their stack are the case studies that follow.





