Most writing about automation is about making things happen. The harder and more valuable problem is making them stop.
An automation that fails to send is a missed opportunity. An automation that keeps sending after the customer has replied is actively damaging: it tells them that nobody read their message, that the business is a machine, and that their answer went nowhere.
Exit conditions are part of the design
Every sequence needs three things defined before it is built: what starts it, what it does, and what ends it.
The third is routinely omitted, and the result is a follow up sequence that continues through a reply, a phone call, a signed quote and occasionally a cancellation.
Write the exit conditions explicitly. A quote chase sequence ends when the quote is accepted, when it is declined, when the customer replies by any channel, when the opportunity moves out of the sending stage, or when the configured number of attempts is reached. Anything not on that list does not stop it, which is a decision rather than an oversight.
Replies by any channel
The subtle part is that a reply rarely arrives where the automation is looking.
The sequence sends email. The customer phones. Somebody logs the call, or does not. Meanwhile the second and third emails go out.
Suppression has to be driven by the record rather than by the channel. Any activity attached to the opportunity from the customer side, whether an email reply, a logged call, a portal message or a form submission, sets a flag that stops the sequence. That means logged calls have to be easy to record, which is a usability problem with a direct commercial consequence.
Where replies arrive in a shared mailbox rather than a system, route them in. An automation that cannot see the inbox where customers reply is an automation that will keep chasing.
Platform level controls
Some rules should not be implemented in each workflow, because a rule implemented eleven times is a rule implemented wrongly at least once.
Suppression lists. A contact who has unsubscribed, hard bounced, or been marked as do not contact is excluded at the sending layer regardless of which automation asked.
Quiet hours. Nothing non urgent sends outside defined hours in the recipient time zone. Nobody needs a marketing follow up at half past two in the morning.
Rate caps per recipient. A hard ceiling on how many messages one contact can receive from all automations combined in a period. This is the control that turns a runaway loop into a nuisance rather than an incident.
Global pause. One switch that stops all outbound sending without a deployment, for the moment when something is clearly wrong and you need it to stop now rather than after a release.
Triggers that do not re fire
The other source of unwanted sends is a trigger that fires more than once.
If a sequence starts when an opportunity enters the quoted stage, and somebody edits the record in a way that touches the stage field again, a naive implementation starts it a second time.
Record the transition rather than watching the field. When the sequence starts, write that fact against the opportunity. The trigger checks for it and does nothing if it is present. This is the same idea as idempotency, applied to workflow triggers.
Make the sequence inspectable
When somebody asks why a customer received four emails, the answer should take a minute.
Run history with inputs, outputs, timing and the reason each step executed. The record should show what fired, what suppressed, and what is scheduled next. Without it, every question about an automation becomes an investigation.
Design the tone for the situation
A practical point rather than a technical one. A chase sequence that reads as though a person wrote it produces replies. One that reads as a template produces unsubscribes.
Reference the specific thing being chased rather than sending a generic nudge. Make the last message in a sequence say that it is the last, with an easy way to say not now. That gives the recipient a clear way to pause the conversation without another unexplained reminder.
The rule of thumb
Before building any sequence, ask what the worst case looks like if the exit conditions fail. If the answer is that a customer receives the same message five times after telling you they are not interested, build the exit conditions first and the sends second.
Check suppression again at the point of sending
Removing future jobs when a reply arrives is useful, but it does not catch a job already claimed by a worker. Check the contact and sequence state immediately before dispatch. Record which state version authorised the send so an operator can distinguish a stale job from an unobserved reply.
There is still a boundary between that check and an external provider accepting a message. A reply received after dispatch cannot recall every email already in flight. The interface should make that distinction explicit: cancelled before dispatch, accepted by the provider, or outcome uncertain. Do not promise that a pause button can retract a message another system has already accepted.
Test the race with a delayed provider response. Start a send, record a customer reply, and then release the response. Verify that no later steps execute and that the activity history explains the one message already dispatched. Separately test a reply before the worker claims the job; that message must not send at all.
Treat automated out of office replies separately from a person's answer. Whether they pause, reschedule or leave a sequence unchanged is a business rule that needs an explicit decision, not a guess based only on the presence of an inbound event.