Noventra AI
Teardown № 03 · Sales and outreach

How we built a controlled cold email outreach engine

A managed outbound email system that sends only human-written messages, checks for replies and bounces before every send, paces delivery, and reports the outcome of every run.

  • 7 min
  • 46 workflow steps
  • 12 processing stages
  • Live system

Built and run internally by Noventra. System details and recorded figures are real.

How do you automate cold email follow-ups without emailing someone who already replied?

Each weekday morning the engine reads a queue of prospects that a person has written and approved, never generated by the system. Before it emails anyone it checks, live, whether that exact person has already replied or bounced; if they have, it does not send, cancels their remaining follow-ups, and flags them for a human answer. If they have not, it sends the right step, a first email or a follow-up posted as a reply in the original thread, marks the row sent, waits a random couple of minutes, and moves on. A hard per-run cap stops it ever sending a burst, a separate check watches through the day for replies and bounces, and a summary lands in the owner's inbox every run so that silence means something is wrong.

The problem

Founder-led outreach is repetitive and easy to get wrong in ways that cost you. Follow-ups have to go out on time, but the moment someone replies or an address bounces, sending them the next scripted message is exactly the wrong thing to do: it looks careless and it burns the relationship.

Doing it by hand means either staying on top of a spreadsheet every morning or risking a follow-up landing after someone has already answered. The goal was to take the routine of sending off the owner's morning, without ever letting the system do the one thing a person would never do: keep emailing someone who has already replied.

The outcome

What the finished system does

The engine now runs each weekday morning, sends the outreach that is due from a human-approved queue, and checks every recipient for a reply or bounce in the moment before sending, so that a detected reply or bounce blocks the next scheduled message. Follow-ups go out as replies in the original thread, sending is paced and capped to prevent bursts, and the owner receives a summary every run plus an alert when the monitor detects a reply or bounce.

Due today
Live reply/bounce check
Send or hold back
Mark sent
Pause, then next

We design managed automation systems like this around the tools a team already uses.

How it works

How the system works, stage by stage

Stage 01

The queue is written by a person first

Each prospect and the exact wording is written and approved by hand and loaded into a shared queue. The system never generates the message.

Stage 02

Each weekday morning the engine wakes

A scheduled run reads the rows due to go out today.

Stage 03

A daily cap is enforced

No more than a set number can go out in a run; if that is exceeded the run halts and alerts instead of sending a burst.

Stage 04

Before every email, a live reply and bounce check

The system searches the inbox, right then, for a reply or a bounce from that exact person, rather than trusting a status saved earlier.

Stage 05

If they already replied or bounced, it does not send

The row is marked, that person's remaining follow-ups are cancelled, and the owner is alerted.

Stage 06

Otherwise it sends the right step

A first-touch email, or a follow-up posted as a reply inside the original conversation, matched by thread.

Stage 07

The row is marked sent and the engine pauses

A random two-to-four-minute gap follows before the next one, so sending is paced and never bursts.

Stage 08

A summary lands every run

Including on mornings with nothing due, so silence is itself a signal that something is wrong.

Stage 09

A separate check runs through the day

Every fifteen minutes in business hours a second flow watches for replies and bounces to anyone already contacted and flags them to answer.

Under the hood: the 12 internal stages

These stages group the 46 workflow steps that run across three connected workflows. The Morning Step Sender (stages 01 to 07) does the sending, the Reply and Bounce Marker (stages 08 to 11) is the independent daytime monitor, and the Engine Failure Alert (stage 12) is the crash alarm. The three never call each other: they coordinate only through one shared Google Sheet, using its status column as the handshake, so the monitor being down cannot, by itself, cause a message to be sent.

  1. 01
    Wake on schedule and load settings
    Internal stage: sender.schedule_config

    A scheduled weekday-morning trigger starts the run, then every outreach setting is loaded from one configuration step.

  2. 02
    Read the queue and enforce the cap
    Internal stage: sender.read_queue_cap

    Reads the queue, selects the rows due to go out today, and enforces the per-run cap, halting and alerting if it is breached rather than sending a burst.

  3. 03
    Run the live reply and bounce gates
    Internal stage: sender.gates

    Loops over each due row and, for each one, runs a live reply-gate search and a live bounce-gate search against the mailbox, then finds the original conversation thread.

  4. 04
    Plan the action, with a dry-run branch
    Internal stage: sender.plan

    Decides what should happen for the row, with a dry-run branch that can exercise the whole engine end to end without sending anything.

  5. 05
    Handle the stop cases
    Internal stage: sender.handle_stops

    Marks a replied or bounced row terminal, cancels that person's sibling follow-ups, and alerts the owner; also handles the case where the original thread cannot be found.

  6. 06
    Send the right step, mark, and pause
    Internal stage: sender.send_mark_wait

    Chooses a first email or a same-thread follow-up, sends it, marks the row sent, then waits a random two to four minutes before the next one.

  7. 07
    Send a run summary every time
    Internal stage: sender.run_summary

    Builds and emails a summary of the run every time, including on mornings with nothing due.

  8. 08
    Run every fifteen minutes and load settings
    Internal stage: marker.schedule_config

    A scheduled trigger fires every fifteen minutes in business hours, then loads its configuration.

  9. 09
    Reduce the queue to distinct contacts
    Internal stage: marker.read_dedupe

    Reads the queue and reduces it to the distinct people already contacted.

  10. 10
    Search each contact for a reply or bounce
    Internal stage: marker.search_decide

    Loops over them, running a reply search and a bounce search for each, then decides.

  11. 11
    Mark and alert on a hit
    Internal stage: marker.mark_alert

    On a hit, marks the row replied or bounced and alerts the owner.

  12. 12
    Alert on any unhandled crash
    Internal stage: alert.crash_alert

    An error trigger set on both flows above fires on any unhandled crash and emails an alert to the owner.

The real complexity

Why this is more than a mail merge

Sending an email is trivial. Not sending the wrong one is the whole job. Most of the steps exist to make sure a follow-up is never sent to someone who has already replied or bounced, and that sending is paced and visible rather than bursty and silent.

Someone may reply or bounce between when a follow-up was queued and when it is due, and sending anyway is the one unforgivable mistake.
A follow-up has to land in the same conversation as the first email, matched by thread, not sent as a fresh message.
Burst sending creates unnecessary deliverability risk, so pacing and a hard cap matter.
If the pre-send check cannot complete, the email does not go.
The owner needs to know the same morning if the engine did not run.
Safeguards

The safeguards that make it dependable

Live reply gate

Checks for a reply from that person in the moment before sending, not from stored state.

Live bounce gate

Checks for a bounce the same way, immediately before each send.

Gates fail closed

If a check cannot complete, the email does not go.

Hard per-run cap

A run over the cap halts and alerts rather than sending a burst.

Paced delivery

A random two-to-four-minute interval separates each send, preventing burst delivery.

Same-thread follow-ups

A follow-up is posted as a reply in the original conversation, matched by thread.

Auto-cancel on reply or bounce

That person's remaining follow-ups are cancelled automatically.

Heartbeat every run

A summary lands even on zero-due mornings, so silence means something is wrong.

Independent visibility layer

A separate fifteen-minute check surfaces replies and bounces fast, but sending safety never depends on it.

Sending does not depend on the monitor

The sender performs its own live reply and bounce checks. The separate monitor improves visibility, but the sender does not rely on its stored status to decide whether an email should be sent.

Crash alerting

Any unhandled error emails the owner.

Dry-run mode

The whole engine can run end to end without sending.

The reply check has to live in the send path, not next to it

The obvious design is a monitor that watches for replies and writes a status, and a sender that trusts that status. The problem is that the status can be stale, and the monitor can be down, and either way the sender might email someone who has already replied. So the engine does the opposite: it checks for a reply or a bounce from each person itself, in the moment, inside the sending flow, immediately before it sends. A separate flow does watch for replies and bounces as well, for faster human visibility, but the two are kept deliberately independent: they share only a spreadsheet, and the monitor being down cannot, by itself, cause a message to be sent. The gates also fail closed, so if the check cannot complete, nothing is sent.

Controlled validation before go-live is where this was proven, with a queued follow-up correctly held back the moment a reply was present, rather than sent on a stale status.

Two honest limits are worth stating: the gates watch the same mailbox the engine sends from, so a full outage of that mail platform would stop the whole engine rather than be detected by it; and a successful send is a handoff to the mail service, not proof that the message reached an inbox.

System profile

What is now running

46
active workflow steps
3
connected workflows
Every send
preceded by a live reply and bounce check
Hard limit
on messages sent in each run
2 to 4 minutes
between individual sends
Every run
confirmed by a summary email

The engine is now live and managed by Noventra. No volume, response-rate, or deliverability figures are included because there is not yet enough production history to report them responsibly.

Common questions

Questions businesses ask

Does it write the emails?

No. Every message is written and approved by a person and loaded into the queue. The system only sends what has already been approved.

What stops it emailing someone who already replied?

Before each send it searches for a reply or a bounce from that exact person, right then. If it finds one it does not send, cancels their remaining follow-ups, and flags them for you to answer.

What if the reply check cannot run?

It fails closed: if the check cannot complete, nothing is sent.

How fast do you know when someone replies?

A separate check runs every fifteen minutes in business hours and alerts you, on top of the check the sender does before each send.

How does it prevent burst sending?

A hard per-run cap limits the total number of messages, and a random interval separates each send. Follow-ups are also placed in the original conversation rather than opened as new threads.

How do you know the engine ran?

It emails a summary every run, including on mornings with nothing due, so an absent summary is your signal that something needs looking at.

Want a system like this in your business?

Tell us what eats your week. We will tell you what can be automated, what should stay human, and what a first version would involve.

No build cost · Clear terms upfront · Managed by Noventra