The defect the engine exists to fix
A whale-sized allocation with a fake identity is not a hot investor
My first version scored a lead's stated investment range as real even when the name, company and message were keyboard mash — a gibberish $1M submission would have fired a red whale alert straight at the CEO. Auditing my own system surfaced it, and the fix was to make identity and capital independent signals. A credible whale now requires the capital and a real name and a real company or LinkedIn and either an institutional signal or a high quality score and low spam risk; high capital alone never escalates. When the two disagree — large money, unconvincing identity — the lead is classified Spam Review / Whale Conflict and sent to manual review, explicitly never escalated. That single rule is the difference between an alerting system a team trusts and one they learn to ignore.
lead_intelligence.py · classify() · _whale_credible()
Scoring · pure module
Two scores, every point explained
Each lead is parsed field by field — blanks stay blank, nothing is inferred — then scored twice. Investor quality 0–100 across seven weighted components: stated range 25, crypto and RWA relevance 20, real-estate relevance 15, professional credibility 15, contact completeness 10, message quality 10, prior engagement 5. Spam risk 0–100 additively, where every point is attributable: gibberish name +25, gibberish message +20, disposable email domain +20, hosting or Tor IP range +15, no reachable handle at all +10. The two together resolve to one of eight segments. No network, no model calls — the classification is reproducible and unit-testable. Across the 2,225 leads the system captured, roughly 400 resolved to bot or disqualified segments — close to one in five of everything inbound, held back from a person's attention without a human ever reading it.
score_investor_quality() · score_spam_risk()
Precision
Catching keyboard mash without false positives
The gibberish detector reads three signals: lower-to-upper camel transitions inside one token (eHdgDaskrup), an implausibly low vowel ratio on long tokens, and runs of six or more consonants. The hard part is not catching junk — it is not catching real names. The tests pin that ordinary title-case entities like "Hartwell Family Capital" score clean, because a filter that rejects genuine institutional leads is worse than no filter at all.
looks_random() · lead_intelligence.py
Ingestion · Telegram Bot API
Parse, deduplicate, alert by segment
Leads are deduplicated against the live CRM across email, phone, Telegram handle and — for anonymous website events — IP plus exact timestamp. Segment then decides the alert: credible whales raise a red card to the CEO chat and a Telegram ping, whale conflicts go orange to manual review, hot investors trigger a 24-hour outreach card, warm leads queue quietly, and spam is summarised in the daily report rather than pinged per lead, so the team's attention stays worth something.
telegram_intake.py · fire_alerts()
Reliability
No lead is ever lost
Two transports — a long-polling loop and a webhook that verifies Telegram's secret-token header and fails closed. Processing retries with bounded exponential backoff. The polling offset only advances past updates that were handled or were never ours, so a genuine failure is written to a dead-letter log and re-fetched next poll rather than being checkpointed away. Dead-letter records store a redacted preview, never the full payload.
poll_once() · _process_with_retries() · webhook_security.py
Cost engineering
7,500 API calls down to under 10
The CRM's API was capped at 10,000 calls a month. The naive import spent about five calls per lead, so a single 1,500-lead backfill would have burned three quarters of the monthly budget. I rewrote it to index the entire CRM once at maximum page size, deduplicate the whole batch in memory, and bulk-create only genuinely new records — roughly 7,500 calls became fewer than ten.
_index_existing_records() · process_notifications_bulk()
Architecture
Moving the system of record to Postgres
Rather than keep optimising against a quota, I moved the source of truth to Supabase Postgres and left the CRM as a synced view. Deduplication became a database guarantee: every lead resolves to one dedup_key — Telegram, then email, then phone, then IP plus timestamp — and writes are upserts that skip existing keys, so re-importing months of history is a no-op that can never clobber enriched data.
supabase_store.py · sync_supabase_to_lark.py
Web3 · Ethereum
Reading purchases straight off the chain
Knowing who actually bought normally means waiting on DApp backend access. Instead the tracker reads Ethereum directly, in either of two modes: watching token transfers from the sale contract to buyers — which is the purchase event — or watching stablecoin inflows to the treasury address. Purchase reality reaches the CRM without depending on another team's API or release schedule.
onchain_tracker.py · JSON-RPC
Governance
Nothing sends without a human
The daily queue selects whale, then hot, then warm leads with complete contact details, ranks by priority and score, and drafts a configurable top fifteen — fewer if fewer qualify, never padded to hit the number. Each draft carries why that lead was selected, a personalised opening line, per-channel messages and a soft call to action, and lands in the queue as Pending Approval. The system proposes; a person sends.
capital_relations_daily.py · build_outreach_queue()
Data recovery
Reading history a bot cannot see
Telegram bots cannot read chat history and cannot see messages posted by other bots — and the entire lead archive sat in a private group, posted by a bot. I built a user-account client to extract it: joins once via invite link, pulls full history or only new messages, writes a raw export, and remembers its position so daily runs never re-import. Alerts are silenced during backfill so importing months of history doesn't spam the team.
telegram_history_extractor.py · Telethon