Build write-up

Multi-agent outbound system: build write-up

Steve Light, SteveCV.com

3,710businesses crawled
622clean contacts, each with its source URL
17%crawled to clean, sendable contact

Summary

I built a multi-agent outreach system for an arts venue launch. It found businesses, pulled their published contact details, cleaned them against suppression lists, and only let a human-approved email go out once every claim in it was checked. It crawled 3,710 businesses from five sources and ended with 622 clean contacts, each with the source URL it came from.

The main point of this write-up is how it handles data you can trust. One version of the pipeline produced made-up email addresses. A checker caught them before anything was sent, and I redesigned the system so that kind of error can't happen.

What the system does

Funnel: where contacts dropped out

StageContactsDropped at this stageKept from previous stage
1. Businesses crawled (5 sources)3,710——
2. Published an email address1,6022,108 (no published email)43%
3. Clean contacts after suppression (6 lists) and page re-check, each with its source URL622980 (suppressed, duplicate or not confirmed on re-check)39%

Overall, 17% of crawled businesses became a clean, sendable contact.

3,710  businesses crawled
  |    - 2,108 published no email address
1,602  businesses with a published email
  |    - 980 removed: duplicates, 6 suppression lists, failed page re-check
  622  clean contacts, each with its source URL

The biggest drop is at stage 2: more than half of the businesses don't publish an email address at all. In a sales pipeline, that's the gap an enrichment tool would fill (see below).

What went wrong, and how I fixed it

The problem: one agent's page-summarising step invented plausible-looking info@domain addresses. They looked right, but they weren't on the page.

How it was caught: a checker (verify-addresses.py) re-fetched every source page and looked for the exact address, including emails hidden by Cloudflare's email protection. 71 of 939 addresses (about 8%) failed. They were held back and nothing was sent to them.

The redesign: the agents now only find businesses and their websites. A plain crawler (crawl.py) records only text it actually fetched and puts the source URL on every row. Because no language model writes the addresses any more, invented addresses can't get in at all. Every contact can be traced back to a page.

Safeguards before anything is sent

Stack

A note on results

This was a launch campaign for an event, not a sales pipeline, so there's no closed-revenue ROI to report. What I can show is the funnel above: how many contacts entered, where they dropped out at each stage, and why every remaining contact can be trusted.

How I'd apply this to your pipeline

info@stevecv.comMore of my work