Evidence-first prospecting without guessed emails
Two rules do most of the work. A claim with nothing behind it never reaches the prospect record, and Connect never guesses an email address — a prospect with no discoverable one is kept as researched with a different next action instead. The cost is volume, paid deliberately. What it buys is a list that is still defensible when somebody reads it six months later.
Where the two rules sit in the chain#
Prospecting runs as a sequence — discovery criteria, candidate collection, public-source research, evidence capture, qualification and scoring, contactability, compliance check, first outreach, reply classification, and then an opportunity or a clean stop. Each stage may end the chain, which is the property that makes the rules enforceable rather than aspirational.
Evidence capture sits before qualification, so a score is computed from sourced claims rather than from impressions. Contactability sits before the compliance check, so an address that does not exist never reaches the stage that would decide whether writing to it is allowed.
A claim carries its source or it does not exist#
prospect_evidence.py attaches the source to the claim. A statement about a prospect that arrived without one does not reach the record at all — it is not stored with a lower confidence, not flagged for review, not kept as a hint. This is stricter than it first appears, and it is the strictness that makes the record useful: every line on a prospect can be checked back to where it came from.
The alternative is familiar. A research pass produces plausible sentences; they are stored; a month later nobody can tell which came from the organisation's own site and which came from a model completing a pattern. At that point the record is not evidence, it is atmosphere, and the sales note written from it goes out to a real person.
Why no address is ever generated#
Pattern-generated addresses — first.last, initial-surname, the eight common shapes — are the standard way to convert a researched organisation into something you can write to. prospect_contacts.py produces none of them, tests none of them and sends to none of them.
- A generated address that bounces teaches a receiving domain that this sender does not know who it is writing to, which is exactly the signal spam filtering is built to detect.
- A generated address that *works* often belongs to somebody who never published it, and the first contact is therefore an intrusion rather than an approach.
- Verification services convert the guess into a slightly better guess. They do not convert it into a source.
- A prospect with no discoverable address is kept as a researched prospect with a different next action, so the research is not thrown away — it is simply not turned into a send.
What is measured, and what is not#
The cost is straightforward: fewer contactable prospects per hundred researched than a generator would produce. That is a deliberate trade and it is visible on the prospects screen as researched-but-not-contactable.
The gain in reply rate is UNKNOWN. No controlled comparison between sourced and generated addresses exists in this corpus, and quoting an industry figure here would be the same kind of unsourced claim the method refuses. What can be said without a number is that a sourced address cannot bounce for the reason a guessed one does, and that a claim with a source survives a customer disputing it.
One measurement is worth quoting because it is about the numbers themselves. prospect_summary derived every headline figure from the newest 500 contacts and the newest 500 organisations, so a larger workspace was told it had exactly 500 of everything. Driven with 540 contacts whose 40 already-contacted ones were the oldest, it reported 500 organisations against a real 530 and 0 already contacted against a real 40. A method judged by a broken counter is not judged at all; contacts are counted in batches now and organisations by the database.
Compliance is a single gate, not a habit#
Suppression, unsubscribe, complaints and do-not-contact are checked in one place before any outreach, so a new outreach path cannot accidentally skip them. The Assistant cannot clear a do-not-contact entry at all — its rights are narrower than a person's, by design. Outreach email and a reply from an existing customer are two separate paths with different gates and are never merged, because the moment they share a code path the outreach rules start applying to conversations that a customer began.
Three prospect_* tables once shipped with row-level security switched off, because create_all makes a table at boot while row-level security comes from an operational script. They were enabled and forced afterwards, and a test now fails on any new table that repeats it.
Questions#
Does refusing generated addresses just mean less prospecting?
It means less *sending*, and the same amount of research. The organisations are still discovered, still researched and still scored; what changes is that a prospect without a real address gets a next action a person can act on — find the right contact — instead of a message dispatched into a pattern.
What counts as a source?
Something a reader can go and look at. The point of the rule is that a claim can be re-checked by somebody who does not trust the process that produced it, which rules out a model's recollection and rules in a published page.
Is a scored prospect with no evidence still useful as a lead?
There is no such record. Scoring reads evidence, so a prospect with none has nothing to score, and the honest state — researched, no contactable address, next action with a person — is more useful than a confident number with nothing underneath it.