Learn more →
All Work
Agentic WorkflowAI-Enabled Outbound

An Outbound Agent That Knows When Not to Send

We built an agent that turns a raw lead list into a booked, briefed sales call with almost no manual work. The workflow runs across six systems, from enrichment to sending to calendars to call recordings, and every decision along the way can be explained. That includes the decision not to email someone. Sending email was the easy part. The work was in the rules.

0Pipeline Stages Automated
0Systems Orchestrated
0Suppression Checks
0Mailboxes on One CRM Seat
The Challenge

The costly mistake is emailing the wrong person, not sending too little.

The operation sends from 125 mailboxes on behalf of senior partners. Its outbound workflow was spread across a lead database, an enrichment tool, a sequencer, a CRM, every partner's calendar, and a call recorder. Each tool did its own job well. None of them could answer the question that mattered: should this person be emailed at all?

The failures that hurt were never about volume. They were things like a cold pitch landing on the colleague of someone mid-negotiation, or a prospect who said “try me in March” and never heard back. Sometimes an unsubscribe reached the sequencer but never reached the CRM, so the next campaign emailed them again. And a booked call might exist only in one partner's calendar, where nobody chased the no-show.

What makes this a hard workflow to hand to an agent is that the rules interact. Whether to send depends on deal state, correspondence history, a parked follow-up date, and whether the address is deliverable. That information lives in different systems and arrives out of order.

Scope

A working build on the real stack, run end to end in a live client demo, not a production deployment. The logic is real. The hosting is still a local scheduler and a temporary webhook tunnel. It was demonstrated on a live offer: geospatial site selection sold to energy developers.

The Approach

Write the rules down before letting an agent follow them

The usual way to build an outbound agent is to wire the tools together and add guardrails later. We did it the other way around. We wrote down every rule for who may be contacted and why, then picked and connected tools so that those rules could not be skipped.

Phase 1
Write the Rules First

Before any code, six rule files: who may be contacted, how replies are routed, what each system owns, and what lands on a deal. The specs are the source of truth — the code implements them and the tests assert them. When the two disagree, the code is wrong.

Phase 2
Pick Tools by How They Fail

Every vendor was judged on its failure modes, not its feature list. One sequencer was dropped because it has no unsubscribe webhook, so an opt-out could never reach the CRM. The one we chose tends to stop sending silently, so the build writes a last-sent date on every email and that failure shows up within hours.

Phase 3
Build the Gates

Two suppression passes, reply routing, and a single sending client that refuses any lead without a gate token. Every block carries exactly one reason code, so an operator can answer why a given person was or wasn't emailed.

Phase 4
Close the Loop

Calendars, recordings, and briefs sync back to the CRM on a 15-minute cycle. A booked call gets an automatic research brief. A recorded call gets a summary, action items as tasks, and a proposal clock. None of it is typed by a person.

The Pipeline

Eleven stages, from a lead list to a briefed call

Each stage has exactly one owner. Most are deterministic code or a single tool. The two gold rows are suppression gates, and they sit right before the two steps that spend something: money on enrichment, and reputation on sending. A model appears in only one place, and it reads a reply only after the rules have run.

01
A PitchBook export becomes a list of accounts
Code
02
Resolve each company's web domain
Clay
03
Suppression pass A — company levelOpen deal, do-not-contact, or already in the CRM? Stop here. It costs nothing.
Gate
04
Find the right people, then their work emailsThe first step that costs money, across a waterfall of 150+ data providers.
Clay
05
Suppression pass B — email level, before draftingParked, recently contacted, already in a colleague's inbox, or an address that won't land.
Gate
06
Draft, then send from a warmed mailbox
Smartlead
07
Each send event writes a last-sent date to the CRM
Code
08
A reply is routed by rules first, then classified
Code + Model
09
Live team availability and a booking link
Nylas
10
The calendar invite marks the deal booked and tracks the RSVP
Nylas
11
Recording → summary → tasks → proposal clock
Fathom
↻ One deal record carries the whole journeyBrief generated, call scheduled, RSVP, call completed, duration, recording, next step, and a proposal deadline that is never reset. A call that lasts 0.7 minutes against a 30-minute booking is flagged as a misfire. Action items become CRM tasks, so “what do I owe people” is one filtered list across every deal.
The Arguments

Six design decisions that make the agent trustworthy

In each case, the obvious build works in a demo and fails in month three. The correct build takes only slightly more work.

01

Code decides. A model only labels.

Suppression, dedupe, state, and routing have to give the same answer hundreds of times a day, so they are code. The model reads a human reply and returns a verdict. Separate code then performs every write. The model cannot create a deal, stop a sequence, or add anyone to the block list. It can decide on a label. It never takes an action.

02

Suppress before you spend, and do it twice

The lead source gives names without reliable emails, so finding an email is a cost worth protecting. Pass A runs at the company level, before enrichment, for free. Pass B runs on the address before anything is drafted. Pass A's open-deal rule blocks everyone at that company. Cold-pitching a colleague of someone you are mid-negotiation with is the most damaging thing this system prevents.

03

A rule you must remember to call eventually isn't called

So the sending client refuses any lead that arrives without a gate token. It is enforced, not advised. The check had already been skipped once, in a test harness, on leads that happened to be safe. It will not be skipped on leads that aren't.

04

Never guess into a permanent suppression

“Not interested” writes to a global block list that only a person can undo, so any ambiguity resolves to “not now.” The asymmetry is deliberate: a wrong “not now” costs one follow-up, and a wrong “not interested” loses a prospect for good. But “remove me” is not ambiguous, and it is honored at once.

05

Read calendars, not booking tools

A recorder only sees calls that happened. The calendar also knows the calls that are booked, declined, or never attended, and those are the ones someone has to chase. One calendar API holds every rep's mailbox against a single CRM seat. Swap the scheduling tool tomorrow and nothing breaks.

06

Only observable facts move a deal on their own

“Call done” is the only stage the system sets by itself, because a recording existing is a fact. “Proposal sent” is a claim only a person can make. Outreach status also only moves forward. Webhooks arrive out of order, and without that guard a late send event would downgrade someone who has already replied.

Explainable Suppression

“Why didn't we email them?” always has one answer

The rules are checked in order and the first match wins. Every block carries exactly one reason code, because an operator needs the reason, not a list of all of them. Each code maps to a sentence a partner can act on.

company_open_deal

We are mid-negotiation with a colleague at their company.

Pass A · re-checked in pass B
existing_correspondence

A partner already has an open email thread with them.

Pass B
person_exists

They were in the Q2 campaign.

Pass A · pass B
scheduled_for_later

They asked us to circle back in March, and in March they come back.

Pass B
recently_contacted

We emailed them within the last 90 days.

Pass B
catch_all_domain

The address wouldn't have reached a person.

Pass B

The details that took real debugging

None of these show up in a happy-path demo. All of them show up in the first month of live sending.

Where a record came from

The CRM creates person records from two sources that mean different things. One is our pipeline. The other is a partner's email capture. Both block, but with different codes, so the answer to “why not?” is useful. Merging them into one rule would quietly change its meaning the day mail capture is switched on.

Parked leads have to come back

A follow-up date has to gate the block, not just annotate it. Without that, a lead saved for March is still blocked in March, and “circle back in Q1” never happens.

Gmail is not a company

Free-email domains never become company records. A deal attached to “gmail.com” would make the open-deal rule block every Gmail user alive.

Never edit a live sequence

Pause, edit, resume. Editing mid-flight re-sent the sequence to every lead it had already contacted. That lesson is now written into the operating rules.

Reply Routing

The model reads a reply last, not first

Most replies do not need judgment. Bounces, out-of-office notices, and “you want my colleague” all have deterministic answers, so rules handle them in order. A language model sees only a real reply from the person we emailed, and even then it returns a label. It never takes the action itself.

1Did it bounce?

The address goes on the block list and the sequence stops. No CRM record is created.

2Is it an auto-reply?

Resume the day after their out-of-office ends, or retry in seven days.

3Did someone else answer?

A referral becomes a new lead at the same company, with the original thread attached.

4Is it our target, writing as a person?

Only now does a model read it and return interested, not now, or not interested.

Capabilities Demonstrated

What it takes to hand a messy workflow to an agent

Specific proof points across architecture, controls, and operations. These are the parts that decide whether an agent can be trusted with a revenue workflow.

Agentic Workflow Architecture

An 11-stage pipeline from lead list to booked, briefed call. Deterministic code owns every effect, and language models are confined to the three places judgment is needed: classifying replies, drafting, and writing pre-call briefs.

Spec-Driven Build

Six rule files are the deliverable even if nothing runs. The code implements them, the tests assert them, and every suppression rule passes its spec test.

Multi-System Orchestration

Clay, Smartlead, Attio, Nylas, and Fathom are joined by one sync layer. Each system owns exactly one kind of fact, no fact is written twice, and when two systems disagree the owner wins.

Suppression & Compliance Controls

Two suppression passes with a single reason code per block. The gate is enforced at the sending client, and unsubscribes are wired all the way back to the CRM.

LLM Classification & Research

A three-way reply classifier that leans toward the recoverable answer, plus automatic pre-call briefs built from live web research and linked to the deal.

Operational Observability

A one-command health check across the whole stack, an append-only event log with idempotency, and last-sent tracking that catches a sequencer silently not sending.

Deliverables

What we built

The Rules
  • Six specification files — the source of truth
  • Two-pass suppression with single reason codes
  • Reply routing: rules first, model last
  • CRM schema, built and corrected idempotently
The Agent
  • Sync layer across Clay, Smartlead, Attio, Nylas, Fathom
  • Reply classifier with a verdict-only contract
  • Automatic pre-call briefs with live research
  • Calendar and recording sync into CRM tasks
The Operations
  • One-command preflight health check
  • 15-minute cycle: calendars, recordings, briefs
  • Realistic, fully removable demo pipeline
  • Bug log and open decisions for the client
Outcome

An agent you can audit, not just an agent that sends

A lead list goes in and a booked, briefed call comes out. Every step in between is either a rule anyone can read or a label from a model that is not allowed to act on it. When a partner asks why a prospect was skipped, why a reply was filed where it was, or why a deal moved, the answer is already written on the record.

We were just as clear about the limits. Enrichment finds about 83% of work emails, so roughly one lead in six can't be reached. Sending to inboxes we own proves the plumbing works, not where messages land. The build shipped with a bug log and a short list of decisions only the client can make, such as what formally closes a dead deal. That is how an agent reaches production without surprising anyone.

Have a workflow too complicated to hand to an agent?