Erik Hernal
Reply

The last mile is everything that changes between the draft and the send

AlphaForge P9 · 2026-08-31

AlphaForge is Clay's GTM engineering cohort. Each numbered prompt is a build with a deadline and a public write-up, so the work below was done in the open and graded by people who do this for a living.

I sent 25 cold emails under a real company's name and got zero replies, after cutting 14 of 39 restaurants right before send.

14 of 39cut before sendingsource: prompt9/p9_report.py, read from Clay 2026-09-04

What I sent

The segment was the 990 independent restaurants already running a head-to-head competitor of Owner.com, and 376 of those are on Slice. I was sending 25, not 376, so I pulled a working batch of 39 off the top of that list to leave room for the ones I expected to lose before send. The other 337 were never in this project. I picked Slice because it publishes its prices, so every message could carry a number the owner could check against their own bill: $39 a month plus $3 an order on the Online tier, which crosses over a flat $499 plan around 154 orders a month.

Every email went from my own mailbox on my own domain, signed with my name. I told each restaurant what I was doing in one line: a GTM engineer studying Owner.com's market for a program. I've never worked for Owner. The cap was 25 messages, and that's what went out, all on August 31.

The system

Clay held one record per restaurant, tracking the message from draft through send to reply. A workflow wrote every update through one webhook, so the sender and the reply loop both talked to Clay the same way.

Email Bison did the actual sending: plain text, no open tracking or unsubscribe link, just a reply-stop line I'd honor on sight. A poller on my server checked Bison every five minutes for bounces and replies, then mirrored each one into Clay with a ping to Slack.

I'd written tests for the logic that separates a bounce from an opt-out from a real answer, so someone typing "stop" would trip the same code whether they meant it or whether I'd misread a reply that actually said they'd switched vendors. The campaign sat behind a fence too, so my own auto-reply machine could never touch it.

What changed between draft and send

The segment data was four days old by the time I sat down to send, so I re-checked every restaurant's site first. Three of them had switched vendors since the draft: their order buttons now pointed at Toast or a DoorDash storefront, and the Slice arithmetic I'd written no longer described their bill. Borrowing Owner's name raised the bar on that check, because a wrong number under their name costs them, not just me.

Then Bison refused eleven more restaurants when I tried to load them, because the only address they'd published was a personal mailbox on Gmail, mostly. I'd drafted some of my sharpest messages for exactly those owners, and I could have routed around the block by sending from my own Gmail account instead.

I didn't. A cold email to someone's personal inbox is a different act from one to their business address, and the rule I keep for my own campaigns doesn't bend because these happened to be good drafts.

The number that moved

Fourteen of the 39 restaurants in the segment got cut before a single email went out: three for a vendor that had changed, eleven for a personal-only mailbox. That's the number that actually moved, from 39 down to 25.

The 25 that went out sent clean except for one bounce, all on August 31. Nobody replied and nobody opted out; twenty-four of the twenty-five just sat in silence. I'm reporting that flat, because a project built to measure the last mile has to report a null result the same way it would report a good one.

What I'd change

I'd stop padding the list to hit a round number. Two of the 25 seats went to restaurants with thin research, one site my scraper could only partly read and one that was just an image and an ordering button, because I'd set 25 as the target and wanted to reach it. Twenty-three strong messages beat 25 with two weak ones riding along.

I'd also check whether an address is a personal mailbox before I draft the email. Eleven of my best drafts got cut at the load step because the owner's only listed address was a Gmail account, and I'd already spent the time writing them.

p9_ledger.jsonlopen, 53 lines

every send, bounce, and reply got logged as an event when it happened, not written up after the fact

The send ledger, one line per event as it happened

2026-08-30T15:51:29  queued          erikhernal.com
2026-08-30T16:05:38  queued          heyagentic.ai
2026-08-30T16:25:10  queued          paradisoroma.com
2026-08-30T16:25:11  queued          thepizzaplacekc.com
2026-08-30T16:25:59  queued          fratellibronx.com
2026-08-30T16:26:00  queued          waynealehouse.com
2026-08-30T16:26:01  queued          vinosjax.com
2026-08-30T16:26:02  queued          theredtomatopizzeria.com
2026-08-30T16:26:03  queued          avucchella.com
2026-08-30T16:26:05  queued          bakospizza.com
2026-08-30T16:26:06  queued          dolcebeneristorante.com
2026-08-30T16:26:08  queued          pizzasidenj.com
2026-08-30T16:26:09  queued          petesridge.com
2026-08-30T16:38:39  set_status      maximsrestaurant.com
2026-08-30T16:38:47  set_status      suppasristorante.com
2026-08-30T16:38:47  set_status      thebestpizzaingreatneck.com
2026-08-30T16:38:47  set_status      maldonadospizza.com
2026-08-30T16:38:47  set_status      oipelysburg.com
2026-08-30T16:38:47  set_status      rialto.pizza
2026-08-30T16:38:47  set_status      fatmanpizzawny.com
2026-08-30T16:38:47  set_status      nickyspizzarestaurant.com
2026-08-30T16:38:47  set_status      scottoshamptonbays.com
2026-08-30T16:38:47  set_status      dolcebeneristorante.com
2026-08-30T16:38:47  set_status      picantescanaan.com
2026-08-30T16:38:47  set_status      vignetocafe.com
2026-08-30T16:38:48  set_status      sopranospizzerianj.com
2026-08-30T16:38:48  set_status      monavalapizzaelcajon.com
2026-08-30T16:41:16  body_refreshed  paradisoroma.com
2026-08-30T16:41:16  body_refreshed  thepizzaplacekc.com
2026-08-30T16:41:17  body_refreshed  fratellibronx.com
2026-08-30T16:41:17  body_refreshed  waynealehouse.com
2026-08-30T16:41:18  body_refreshed  vinosjax.com
2026-08-30T16:41:19  body_refreshed  theredtomatopizzeria.com
2026-08-30T16:41:19  body_refreshed  avucchella.com
2026-08-30T16:41:20  body_refreshed  bakospizza.com
2026-08-30T16:41:20  body_refreshed  pizzasidenj.com
2026-08-30T16:41:21  body_refreshed  petesridge.com
2026-08-30T16:42:01  queued          heyagentic.ai
2026-08-30T16:42:44  queued          rocketcafegallup.com
2026-08-30T16:42:45  queued          ilmonellonyc.com
2026-08-30T17:59:22  queued          pizzerialitaliano.com
2026-08-30T17:59:23  queued          piantepizzeria.com
2026-08-30T17:59:24  queued          pvpieandwine.com
2026-08-30T17:59:25  queued          thesloppywaffle.com
2026-08-30T17:59:26  queued          yotsuba-restaurant.com
2026-08-30T17:59:27  queued          porkyspizzapalace.com
2026-08-30T17:59:29  queued          thejoynestrestaurant.com
2026-08-30T17:59:30  queued          magicmikespizza.com
2026-08-30T17:59:31  queued          rigazzis.com
2026-08-30T17:59:32  queued          brickerypizza.com
2026-08-30T17:59:33  queued          colomboscafe.com
2026-08-30T18:11:09  queued          infernospizzeria.com
2026-08-30T18:11:10  queued          salspizzahartford.com

53 lines, the whole file. Addresses reduced to their domain. These are real restaurants that got a real email. Read from agentic/alphaforge/prompt9/p9_ledger.jsonl at build time.

p9_lib.test.mjsopen, 5 lines

the code that tells a bounce apart from an opt-out apart from a real reply was checked before it ran against anyone's actual inbox

The tests that had to pass before any of this touched a real inbox

1. opt-out fires on the words the footer asks for, at the start of the reply
2. opt-out does NOT fire on a real answer, or on our own footer quoted back
3. stripQuoted keeps only the recipient text
4. htmlToText and toBisonHtml round-trip paragraphs
5. bounce senders are recognised

5 lines, the whole file. Test names as written in the file. Read from agentic/alphaforge/prompt9/p9_lib.test.mjs at build time.

send_list_verification.json23 of 25 addresses checked: 10 confirmed, 5 catch-all, 8 unverifiable, 0 invalid

the addresses on the send list were checked live, not assumed

cuts.jsonopen, 14 lines

the exact reason each of the 14 cut restaurants didn't make the send list

Every restaurant cut before send, with the reason in its own words

maximsrestaurant.com           cut_vendor_changed: Order Online routes to Toast, Slice is a marketplace listing only; also a Greek-American family restaurant, not a pizzeria
suppasristorante.com           cut_vendor_changed: ONLINE ORDER routes to Toast; the Slice widget is secondary
thebestpizzaingreatneck.com    cut_vendor_changed: the order button routes to a DoorDash storefront (order.online); Slice is a secondary link, so the Slice arithmetic does not describe their bill
maldonadospizza.com            cut_personal_domain: only address is gmail; Erik 2026-08-30, no personal-domain sends
oipelysburg.com                cut_personal_domain: only address is live.com; Erik 2026-08-30, no personal-domain sends
rialto.pizza                   cut_personal_domain: only address is gmail; Erik 2026-08-30, no personal-domain sends
fatmanpizzawny.com             cut_personal_domain: only address is hotmail; Erik 2026-08-30, no personal-domain sends
nickyspizzarestaurant.com      cut_personal_domain: only address is gmail; Erik 2026-08-30, no personal-domain sends
scottoshamptonbays.com         cut_personal_domain: only address is gmail; Erik 2026-08-30, no personal-domain sends
dolcebeneristorante.com        cut_personal_domain: only address is icloud; Erik 2026-08-30, no personal-domain sends (Bison had accepted it; lead 208167 unsubscribed so it cannot send)
picantescanaan.com             cut_personal_domain: only address is gmail; Erik 2026-08-30, no personal-domain sends
vignetocafe.com                cut_personal_domain: only address is gmail; Erik 2026-08-30, no personal-domain sends
sopranospizzerianj.com         cut_personal_domain: only address is gmail; Erik 2026-08-30, no personal-domain sends
monavalapizzaelcajon.com       cut_personal_domain: only address is gmail; Erik 2026-08-30, no personal-domain sends

14 lines, the whole file. 14 entries, the whole file. Read from agentic/alphaforge/prompt9/cuts.json at build time.

Loader workflow in Clay

Reply about this oneBack to the thread