Outbound rebuild
When I took over our outbound, the system ran fine and wasn't producing. Most of the replies were auto-responders, and reading back through what we'd sent, nearly every email made the same claim. So I rebuilt the research, the writing and the sequence.
Ask the research a writing question
The old research step decided whether a company was a fit, so by the time we wrote anything we had a yes and almost nothing to say. I kept the crawler and changed the question to the three things that would make them a fit, each with a quote and a link, plus one human detail somebody would bring up in conversation.
--- fit_angles ---
**The top three things that would make them a fit for Sensible
that we should mention.** Open ended: whatever you would actually
raise with this company. One entry each, each with its own quote
and URL. Do not pad. Rank them best first.
--- human_detail ---
The single most specific, noticeable thing on the site that a
person would genuinely mention to another person.A plain version first, then a rewrite
A template writes a plain email that's already fine to send. A stronger model rewrites it for voice using emails I liked as examples, and then the two get compared. If the rewrite added a name or a number that wasn't in the plain version, the plain one goes out.
The check is plain code
The comparison isn't another model. It pulls the names and numbers out of both versions and flags anything new, using a dictionary so a normal word at the start of a sentence doesn't get reported as a made-up company.
def drift(new, bones, card):
"""Anything factual the humanising pass added."""
old_n, old_v = facts_of(" ".join(bones[k] for k in KEYS))
new_n, new_v = facts_of(" ".join(new.get(k) or "" for k in KEYS))
added_names = sorted(n for n in new_n - old_n - safe
if not _known(n.lower()))
added_nums = sorted(new_v - old_v)
if added_names:
return "rewrite invented names: " + ", ".join(added_names[:4])
if added_nums:
return "rewrite invented figures: " + ", ".join(added_nums[:4])
return NoneI read every email before it goes
Each wave goes onto one page with the research next to every draft, and I approve, edit or skip each one. My notes feed the next round, which is where most of the improvement came from. Pasting in whole emails I liked worked a lot better than writing rules about them.

One email, then short replies on the same thread
All the personalization goes in the first email and the follow-ups are short replies on the same thread. While setting that up I found that every follow-up we'd ever sent had been starting a brand new thread, because of a subject line setting nobody had noticed.

Each wave goes out after I read it, with the research sitting next to every draft.