An outbound agent judged on emails sent will email the people it should have skipped. Leaving someone alone is the one result its report never counts, so every good reason to stop looks like work it failed to finish. If you run outbound with an agent, the repair is two rules, and both of them cost you sends:
Both hold wherever outbound runs against a record of people who must not be contacted: partners, open deals, live conversations, people who asked to be left alone. Neither is a claim that sending less fills the pipeline, and a team with no such record has nothing for an agent to check yet.
Empact Partners builds the agents that run its own outbound. We are a go-to-market consultancy, and for the software companies we partner with, the same work is part of RevOps: deciding who gets contacted, by whom, and what the CRM says about them.
So we sell this. A team whose agent already records every skip with its reason does not need us for it.
An Agent Judged On Sends Gets No Credit For Leaving People Alone
An agent learns from what its run reports. If a task can only end as sent or failed, leaving someone alone correctly is recorded as a failure, or not recorded at all. Nobody tunes a system to produce more failures. The team asks the prompt for more decisive action, loosens the retries, and teaches the agent that a reason to stop is a bug.
The fix is a third outcome with a name. The code every email our agents write passes through logs each email it holds back beside the sends: refused, with the check that stopped it and why. A crash is filed as an error and an unconfirmed delivery as ambiguous, so neither passes for a decision.
Our campaign pipeline does the same before anything is loaded. Each person it holds is recorded by reason and written back where the next run reads it, so a later import cannot quietly bring them back:
Give the credit to the reason, never to the stopping itself. A skip with no reason anyone can read is still an error, and an agent rewarded for weak reasons will learn to skip people the way the send-counted agent learned to email them.
What counts as a success is a no-send a person can check: this one is a partner, that one asked to be left alone, this one is talking to your sales team today.
What a developer said on Reddit
The case was made in a September thread about outreach agents that finish a task without sending anything, and one developer put it in a sentence:
“The key is to make “no-send” a first-class outcome in the schema, not an error path.” — r/AI_Agents, Sep 2026
First-class is the right word. An error path gets retried, logged and cleared. An outcome gets counted, read and argued about, which is what a no-send needs from the people running the agent.
An Empty Answer Is Not A Clean Answer
The dangerous case is the email nobody decided to send: the check that should have stopped it never ran. A lookup that times out, a file that was never built, an export from last month: each returns nothing, and nothing looks exactly like “we have no record of this person”.
An agent that proceeds on nothing has turned a broken check into permission. So the rule is to fail closed: a missing answer stops the email. A check can return one of three things:
| What the check returned | What the run does | What the report calls it |
|---|---|---|
| A reason not to contact: a partner, a live conversation, an opt-out | Withholds the email and writes the reason to the person’s record | Skipped, with the reason |
| Nothing, because the check could not run: a timeout, a missing file, a stale export | Holds the email and runs the check again when it can | Held, open work with an owner |
| Nothing, from a check that ran on fresh data | Clears this one check, and the next one still runs | Cleared |
The middle row is the one that gets folded into the last, because both come back empty. Empact Partners runs its own cold outbound the other way.
Every campaign wave reads one do-not-contact export rebuilt from our CRM. It lists every company in the CRM, deal or no deal, and every company where someone answered one of our campaigns, even to say no. If the export is over seven days old, empty, or unreadable, the wave does not start.
The second check is about people. Before matching anyone to a sender, the pipeline rebuilds a map of who we have already emailed, from which inbox, and who is in a live sequence today. It rejects the map when it is missing, partial or over twelve hours old, and when it is far smaller than the last one, because then the file failed to build.
The Most Valuable Skip Is The Person Already Talking To You
On 29 October our follow-up run had a batch of follow-ups ready for people we were already talking to. Each had been written against the last message the person sent. By the time each one was due to go, ten of those people had written to us again.
Before any email leaves, our sending code reads the live thread. It found the newer reply all ten times, refused all ten, and logged one reason: the person wrote again after the message the follow-up answered. Nobody got a “just following up” under a message they had just sent, and a send count would show nothing happened.
The same check fails closed. If the code cannot find the message a follow-up answers in the thread as it reads it now, it cannot tell whether the person wrote again, so it refuses instead of guessing.
Our campaign pipeline learned the same rule the hard way, on a day one of its checks passed an empty answer:
The repeat email was caught before anything went out. Since then the pipeline’s contract says it outright: a missing input stops the run, and no stage may swap in an empty result and report a clean run.
Address verification works the same way. The stage will not run without the verification results, because an empty list of bad addresses looks like an all-clear when the check behind it never ran.
Fewer Sends Means Less Pipeline
Part of the objection is right. An exclusion can be wrong: a prospect filed as nurtured two years ago and never touched since is a real opportunity the list now hides. A hold costs time, and a team that never works its holds has swapped bad sends for a silent queue.
Look at who is on the list, though: a partner, a company with an open proposal, a person halfway through a conversation with your team, a person who asked to be left alone. None of them is cold pipeline. Emailing them cold repeats an opportunity you already have, at best, and spends it at worst.
The list stays narrow because every entry carries a reason. Our CRM’s list deliberately leaves out companies we emailed cold that never answered: a cold email nobody replied to is not a relationship, and filing it as one would hide those companies from every campaign after it.
A hold is not a quiet skip. It is work with an owner, and the email can go once the check runs clean. A valid email held for a day costs a day. An email sent into a live conversation can cost the conversation.
We have no lift figure to give you, and we have not seen anyone publish one for what an exclusion list adds to pipeline. The claim is narrower: take the people your agent would skip by reason, and ask how many were ever going to become new pipeline from a cold email.
Count The Skips Next To The Sends
Put skips in the same report as sends, by reason, and give every hold an owner who clears it. If the report cannot say who the agent decided not to email last week and why, it is counting activity, and activity is the one thing an agent never runs short of.
With a partner, our RevOps work on outbound starts from that report and runs in four parts:
The measure is agreed before the build, and it is a number your team already reports.
If your agent is sending and nobody can say who it should have left alone, book a call with me, and we’ll see whether we should fix it together.
