PRODUCTION · MVP SHIPPED · v1.0

Autopilot for
B2B prospecting.

An AI-native platform that discovers, enriches, scores, and reaches out to B2B leads on its own — Google Places → Web scrape → Claude analysis → personalized email + AI voice calls, all from one query.

14
DB Models
60+
API endpoints
5
External APIs
100%
Async I/O
leadengine.app/jobs/run
Query
boutiques in Texas USA max 100
Background pipeline
RUNNING
Discovery — Google Places
100/100
Enrichment — Places details
100/100
Deep research — scraper
67/100
AI scoring — Claude Haiku 4.5
Ready
Latest enriched
BB
Belle Boutique
Dallas, TX · Retail · 4.8★
92
e-commerce launch hiring
VAPI AI · live
Call in progress
SMTP
47 sent / 50
Built on best-in-class infrastructure
Anthropic Claude Google Places Vapi.ai Twilio PostgreSQL FastAPI SQLAlchemy Docker
THE PROBLEM

Manual prospecting is broken.

Sales reps spend 80% of their day not selling. They're copying addresses, hunting emails, researching websites, and re-writing the same outreach — one lead at a time.

5+ tools per lead

Google Maps, spreadsheets, LinkedIn, Hunter, a CRM, an email client — every prospect touches half a dozen surfaces.

Hours per list

Building a 100-lead targeted list from scratch takes a full day — research, enrichment, dedup, contact hunting.

Generic outreach

"Personalization" means swapping first names. Real context — recent launches, hiring, signals — gets ignored.

Follow-ups fall off

Most replies come on follow-up #3 — but manual sequences drop off after #1. The deals are left on the table.

THE SOLUTION

One query in.
Ready-to-close leads out.

A unified platform that runs the entire prospecting workflow as an autonomous, paced, auditable pipeline.

1

Submit a query

"boutiques in Texas USA." Optional filters for website, phone, max results.

2

5-stage background pipeline

Discovery → Enrichment → Deep research → AI scoring → Ready. Async, resumable, paced.

3

Context-aware AI outreach

Claude writes emails and scripts using the lead's actual research — signals, products, contacts — not templates.

4

Multi-channel execution

Email via SMTP, autonomous AI voice calls via Vapi, human browser calls via Twilio — paced per hour, resumable on crash.

5

Automated follow-ups & pipeline

Progressive AI follow-ups every few days, kanban pipeline, full interaction audit trail for every touch.

jobs_controller.py · run_job_background()
# 5-stage lead generation pipeline
async def run_job_background(job_id: UUID):
    job = await get_job(job_id)

    # 1. Discovery — Google Places text search
    job.current_stage = "discovery"
    leads = await places_service.search_places(
        query=job.query, max_results=job.max_results,
    )

    # 2. Enrich from Places details
    async for lead in async_iter(leads):
        await enrich_from_places(lead)

    # 3. Deep research — scrape website
    job.current_stage = "deep_research"
    await asyncio.gather(*[
        scraper_service.scrape_website(l.website) for l in leads
    ])

    # 4. AI analysis — Claude Haiku 4.5
    async for lead in async_iter(leads):
        result = await ai_service.analyze_lead(
            lead, profile=user.business_profile,
        )
        lead.ai_score = result["score"]
        lead.intelligence = result["summary"]

    # 5. Ready
    job.status = "completed"
    await db.commit()
ARCHITECTURE

Layered, async, resumable by design.

Clean separation between routes, controllers, services, and models — every heavy call is non-blocking, every long-running job is restart-safe.

Jinja2 UI
18 templates
REST API
60+ endpoints
Webhooks
Vapi · Twilio
Auth
OTP · sessions
FastAPI + Uvicorn
async · slowapi rate-limit · CORS · session middleware
Python 3.12
Controller
jobs
Pipeline runner
Controller
leads
CRUD · filters
Controller
campaign
Pacing · retry
Controller
voice
Vapi · Twilio
ai
places
scraper
email
campaign
vapi
twilio
PostgreSQL
asyncpg · 14 tables
SQLAlchemy 2.0
async ORM
Alembic
14 migrations
Schedulers
Follow-ups · resume
USER
User · BusinessProfile · OTP
Auth + personalization identity
LEAD
Job · Lead · LeadResearch
Discovery + deep enrichment
OUTREACH
Campaign · CampaignLead · OutreachItem
Paced multi-channel execution
AUDIT
VoiceCall · Interaction · ActivityLog
Every touch, fully logged
FEATURES

Every part of the funnel, covered.

Autonomous lead discovery

Google Places text search with pagination, sub-query expansion via Claude, up to 500 results per job.

places API pagination

Deep website enrichment

BeautifulSoup scraper extracts title, meta, headings, body, socials, emails, phones — stored as JSON research.

BeautifulSoup social links

AI scoring & signals

Claude scores 0–100, flags expansion signals (hiring, ecom launches), extracts key contacts and products.

Claude Haiku 4.5 JSON mode

Personalized cold emails

Per-lead subject + body referencing real signals. Tone selector. Plain text + HTML MIME with CTA buttons.

aiosmtplib calendar CTA

AI voice calling · Vapi

Autonomous cold calls with custom system prompts and per-lead context. Transcript + recording webhook.

E.164 custom prompt

Human browser calls · Twilio

Browser-to-PSTN via JWT token + TwiML conference. Recording, hold/resume, status webhooks.

TwiML conference

Paced campaign execution

Per-second and per-hour throttles. Resumable on crash via resume_interrupted_campaigns().

pace limits auto-resume

Progressive follow-ups

5-min scheduler generates follow-ups with full thread context. Never repeats the pitch — progressive angles.

gentle nudge value-add social proof

Pipeline & audit trail

Drag-drop kanban (new → closed) + Interaction log of every call, email, reply, bounce — full compliance.

kanban interactions
AI LAYER

Claude, orchestrated carefully.

The AI service is not just an SDK wrapper — it's a production-grade orchestrator with concurrency caps, exponential backoff, forgiving JSON parsing, and reusable task-specific prompts.

Semaphore-gated concurrency
Global cap of 2 concurrent Claude calls prevents 429s during bulk lead scoring.
Exponential backoff retries
Up to 4 retries with 3s · 2^n delay on rate-limit errors.
Graceful JSON parsing
Strips markdown code fences, unwraps nested content, falls back to raw text — never crashes on malformed output.
Task-specific prompts
Scoring · email · follow-up · call script · query expansion — each with its own system prompt and schema.
ai_service.py
# Concurrency-controlled Claude client
_sem = asyncio.Semaphore(2)
_client = AsyncAnthropic(api_key=...)

async def _call_claude(
    system: str, user: str,
    max_retries: int = 4,
) -> dict:
    async with _sem:
        for attempt in range(max_retries):
            try:
                resp = await _client.messages.create(
                    model="claude-haiku-4-5-20251001",
                    max_tokens=4096,
                    system=system,
                    messages=[{"role": "user",
                               "content": user}],
                )
                return _parse_json(resp.content[0].text)
            except RateLimitError:
                await asyncio.sleep(3 * 2**attempt)
        raise RuntimeError("Claude unavailable")
TECH STACK

Modern, async, production-ready.

Backend

  • Python 3.12
  • FastAPI 0.115
  • Uvicorn 0.34
  • SlowAPI rate limit
  • Pydantic v2
  • httpx 0.28 (async)

Data

  • PostgreSQL
  • asyncpg driver
  • SQLAlchemy 2.0
  • Alembic migrations
  • UUID PKs · JSON fields
  • Fernet encryption

AI / Voice

  • Anthropic Claude
  • Haiku 4.5
  • Vapi.ai 1.9
  • Twilio 9.0
  • phonenumbers (E.164)
  • BeautifulSoup4

Infra / UI

  • Docker / Compose
  • Azure Pipelines CI
  • Poetry lockfile
  • Jinja2 templates
  • TailwindCSS
  • aiosmtplib SMTP
END-TO-END FLOW

How a lead becomes a deal.

STEP 01

User submits query

"boutiques in Texas USA" · max 100 · require website. Job row created, queued.

STEP 02

Discovery + enrichment

Google Places text search, paginated. Basic data extracted — name, address, phone, website, rating, category.

STEP 03

Deep research scrape

BeautifulSoup scrapes each website: title, meta, headings, socials, emails, phones. Stored as JSON research blob.

STEP 04

AI analysis with Claude

Score 0–100, expansion signals, key contacts, business description, products list. Persisted on the Lead.

STEP 05

Review, filter, select

User filters by score, signals, industry, location. Picks the top 50 leads for a campaign.

STEP 06

Campaign executes (paced)

Emails or AI voice calls, throttled per second and per hour. Every touch logged as an Interaction.

STEP 07

Automated follow-ups

Scheduler fires every 5 min · gentle nudge → value-add → social proof → last chance. Thread-aware, never repeats.

STEP 08

Pipeline → closed won

Drag through NEW → CONTACTED → REPLIED → MEETING → PROPOSAL → CLOSED. Full interaction history on every lead card.

PRODUCT TOUR

See it in action.

A server-rendered Jinja2 UI with TailwindCSS — dashboards, lead tables, kanban, voice test console, and more.

leadengine.app/dashboard
Dashboard screenshot
Dashboard
Job overview, recent leads, pipeline at a glance.
Primary view
/jobs
Jobs screenshot
Jobs monitor
Real-time stage + progress tracking
/leads/list
Leads list screenshot
Leads database
Sortable table with AI score, filters, bulk actions
/leads/{id}
Lead detail screenshot
Lead detail
Full enrichment, AI signals, outreach history
/campaigns
Campaigns screenshot
Campaign runner
Pacing, follow-ups, live send status
/cold_emails
Cold email screenshot
Email generator
Tone, type, angle → ready-to-send body
/pipeline
Pipeline screenshot
Kanban pipeline
Drag leads through stages, see velocity
/test-assistant
Voice test screenshot
Voice test console
Dial a number, test your Vapi agent live
/profile
Profile screenshot
Business profile
Sender identity + Vapi prompt config
IMPACT

A full sales team,
compressed into one app.

From a single search query to closed-won — discovery, enrichment, personalization, multi-channel outreach, follow-ups, and audit — all automated, paced, and restart-safe.

8hrs → 8min
Per 100-lead list
5-in-1
Tools consolidated
0-touch
Enrichment + scoring
100%
Auditable touches
Production-ready MVP · 14 migrations · async throughout · restart-safe