Cold Email
I Asked My AI Pipeline for 500 Leads and Got 57: The Real Yield Numbers
500 requested, 57 contactable. Total API cost: about two dollars. The full funnel, why cost per lead misleads, and the rebuild I abandoned after three days.
Every article about AI-assisted outbound reports the same metric: cost per lead. The models got cheap, the number got small, and the conclusion writes itself — outbound is now essentially free, so send more.
I run an AI-assisted lead pipeline for industrial exports out of Nanjing. My cost per contactable company is roughly three US cents. And I've come to think that number is one of the most misleading figures in outbound, because it describes the one part of the process that stopped being a constraint.
Here's what actually happened on a recent run.
The funnel, with real numbers
I asked the pipeline for 500 companies. Here is what survived each stage:
- Requested: 500 companies.
- Complete records — company plus a named decision-maker plus an email: 130–150, roughly 28% of what I asked for.
- Email addresses collected: about 119.
- Passed bulk verification: 74, or 62% of those collected.
- Distinct contactable companies: 57 — an end-to-end survival rate of 11.4%.
Eleven percent. That is the number I have never seen published anywhere, and it's the number that actually governs planning. If you need to reach 200 companies, you don't source 200 — you source 1,700.
Two stages do most of the killing.
Completeness, not existence. Getting 500 company names is trivial. Getting a company name plus a verified named decision-maker plus a working email collapses it to under a third. The pipeline can find companies all day; what it can't reliably find is the human inside them. Roughly seven in ten records died here, and almost all of them died on the person, not the company.
Verification. Of the addresses that were collected, 62% survived bulk verification. That is not a criticism of the collection step — it's the expected outcome when you refuse to guess address formats and instead keep everything sourced and unconfirmed until a verifier rules. I'd rather discard 38% at a verification bill of a few dollars than discover the same 38% as bounces against my sending domain. I wrote about why guessing format is a prohibited operation in my system in the post on disqualification rules.
What it cost
The sourcing stage: about ¥8 and 25 minutes of wall-clock time, running a low-cost model. The research and signal-detection stage: about ¥4, with most of the actual work done by non-LLM APIs rather than the model itself. With follow-on steps, roughly ¥14 total — a little under two US dollars — for 57 contactable companies with verified addresses.
That's ¥0.25 per contactable company. Three cents.
Drafting sits on top of that: a mid-tier model produces the first draft, a frontier model reviews and rewrites. That's the one place I deliberately spend more, because it's the only stage whose output a customer actually sees.
So: the entire acquisition and research layer for a batch costs less than lunch. This is the number everyone quotes. And it explains nothing about why my pipeline is slow.
The constraint is downstream, and it is physical
Here is my sending configuration: five mailboxes per domain, five emails per mailbox on weekday mornings. That's 25 sends per day. Before any of it runs, a new domain goes through roughly 24 days of warmup.
Now put the two halves together.
Generating 57 contactable companies: 25 minutes. Sending to 57 companies: a bit over two working days. Making a fresh domain capable of sending at all: 24 days.
The generation side is running about a hundred times faster than the delivery side. And the delivery side isn't slow because I chose a cheap tool — it's slow because sending more than that from a young domain damages its reputation, and a damaged domain silently degrades everything you send for weeks afterward.
This is why cost per lead is a trap. It measures the abundant resource. The scarce resources in this system are:
- Daily send capacity, capped by deliverability physics, not budget.
- Domain reputation, which is consumed by every bad address and every irrelevant send, and which cannot be bought back.
- My own attention, since every email gets a human pass before it goes out.
None of those get cheaper when the model gets cheaper. Model prices have collapsed — open-weight models now sit at or below the price of the previously cheapest commercial options, and the trend is continuing. It has changed my API bill and it has not changed my throughput by a single email.
Reply latency, and why small batches lie to you
Two data points, both honest and both small. They come from different batches in a three-batch program running across roughly two weeks — I'm keeping them separate on purpose, because pooling batches to get a nicer denominator is how you manufacture a trend that isn't there.
- Batch 1 (the campaign I broke down in an earlier post): 128 sends, three positive replies, the first arriving around send 60 at managing-director level.
- Batch 2, much smaller: 44 sends produced one positive reply, from a C-level contact at a company in the Philippines, who asked for our product catalogue.
- Batch 3 is still going out as I write this. It has no numbers yet, and anyone quoting one would be guessing.
That Batch 2 reply arrived four to five days after sending.
That latency matters more than it sounds. At 25 sends a day, a 44-email batch takes two days to go out. If you check results at the end of the week and see nothing, you will conclude the batch failed — and you'll conclude it wrong. I nearly did. I wrote in my notes that I was getting impatient and expecting too much too fast, and then the reply landed.
The practical rule I've taken from this: a batch is not evaluable until at least seven days after the last send. Any dashboard that shows you a reply rate before then is showing you a partial number that will make you change a working system.
Applied honestly, that rule disqualifies my own numbers. Three batches inside a two-week window means Batch 1's reply window was still open when Batch 2 started, and Batch 3 is in flight right now. So the figures above are running totals taken mid-experiment, not results. I'm publishing them anyway, labelled as such, because the alternative convention in this genre — wait until the number looks good, then present it as final — is worse. When these close out, I'll update them here whichever direction they move.
There's a second cost to compressing three batches into two weeks that I underestimated: overlapping reply windows make attribution harder. A reply landing today could belong to any of the three unless every contact carries its own send date. It does now. It didn't at the start.
It should also temper how you read both of those figures. One reply from 60 and one from 44 are not rates. They're anecdotes with denominators. I'm reporting them because the alternative — waiting until I have statistically meaningful data before publishing anything — is how this entire genre ends up containing nothing but vendor case studies.
Why I tried to replace my agent
For months the pipeline ran inside a general-purpose agent framework with my workflow encoded as a set of skills. It worked. I built the 100-plus-contact batches with it.
I still tried to replace it, for one reason: I couldn't see inside it.
I gave the agent a workflow and a library of skills. What I got back was output. What I did not get back was which skill fired, what each one contributed, which API calls each stage consumed, or which step was responsible for a given result. When a batch came out badly, I couldn't attribute the failure. When it came out well, I couldn't tell you why, which meant I couldn't repeat it deliberately.
For a system whose entire purpose is generating claims about real companies that I then send under my own name, that's not a minor ergonomic complaint. My drafting rules require every factual statement to carry a traceable source — that's the core of how I keep a language model from inventing a decision-maker. A pipeline that can't show its work is in tension with the standard I hold the output to.
So the plan was: build a small application that does the same thing, but itemizes everything. Every API call listed separately, every token counted, the framework structure written out explicitly. Observability first, cleverness second. A secondary goal was cost control — getting daily spend under a specific ceiling, which requires knowing where it goes.
Why that failed
It didn't work. I want to be precise about how it didn't work, because "AI can't build software" is not what I found.
The requirements were clear — I was specifying a workflow I had personally run hundreds of times. The method was reasonable: a frontier model produced the architecture and specifications, a coding model implemented against them, with explicit instructions to search open-source repositories for existing components rather than writing everything from scratch.
What came out was a good-looking interface that could not execute the workflow. Ten-plus versions. Constant runtime errors. UI freezes. Each iteration fixed something and broke something adjacent. Three days in, after substantial token spend, the thing still would not run end to end.
I stopped.
The honest post-mortem isn't "the tools weren't good enough." Two things were true:
I was optimizing the fast half. Everything I was building sat on the generation side of the pipeline — the side already running a hundred times faster than my ability to send. Even a perfect version of that tool would have moved my actual output by zero emails per day. I spent three days and a meaningful budget making the abundant resource slightly more abundant.
I was solving an observability problem with a rewrite. What I actually needed was instrumentation: logging, per-stage cost attribution, a record of which step produced which record. That's a much smaller problem than a working application, and I could have attached most of it to the system I already had. I chose the rewrite because the rewrite felt like progress, and because specifying features to a model is genuinely pleasant work in a way that reading logs is not.
That second one is the trap I'd warn other people about. AI-assisted development makes building a new thing feel cheap, which biases you toward replacing systems when you should be measuring them. The cost only becomes visible three days later.
What I'm doing instead
Instrument the existing pipeline rather than rebuild it. Per-stage record counts, per-stage cost, and a source trace on every generated claim. That's a logging problem.
Plan against yield, not volume. 11.4% end to end is my current planning constant. If I need 100 companies contacted, I source 900. Sourcing more is nearly free; discovering the shortfall mid-campaign is not.
Track the two survival rates that move. Completeness at ~28% and verification pass at 62% are the only two numbers in the funnel worth optimizing, because they're where 89% of the loss happens. Anything I do to the model layer is noise by comparison.
Stop treating model spend as the budget. The real budget is sends per day and domain reputation. When those are the binding constraints, the correct response to cheaper models is not to generate more — it's to generate better, and send the same 25.
Don't evaluate a batch before day seven. Written on the wall now.
None of this means the AI layer is unimportant. It compressed a research process that used to take me hours per company down to minutes, and it did so at a cost that's effectively zero. That's real, and it's the reason I can run a list-building operation at all as one person.
But it moved a constraint rather than removing one. The bottleneck used to be finding and researching companies. Now it's the number of emails I can put into the world per day without wrecking my domain, and the number of drafts I can personally stand behind. Neither of those is on a pricing page.
Third of three posts on running outbound from Nanjing into emerging markets. Earlier: what to do when a prospect generates no signals, and why my system deletes 69% of the companies it finds.
The first outreach round is now complete. The follow-up report separates reply rate from positive reply rate across all 282 sends.
Continue the series: Positive Reply Rate vs Reply Rate: 282 Sends of Data and The Disqualification Layer: Why My Outbound System Deletes More Than It Finds.