The short answer
An email sequence is a closed loop. It enrols a record, sends its steps, and ends. There is no node that enrols anyone into another sequence — so a multi-stage ladder cannot be built out of sequences alone.
What a sequence does have is global actions: hooks that fire on reply, unsubscribe, bounce, and a custom condition — the last being how an open or a click is caught. Each can create a record from a template. So the chain is built like this: the sequence creates a task carrying a pointer to the next sequence, and a catcher process triggered on task creation writes that pointer onto the contact and re-enrols. The task is the message bus between two sequences that cannot see each other.
The warning that matters more than the mechanism: those tasks are bookkeeping, not work. Build the ladder so that nothing ever asks a human to act, and a stalled campaign becomes invisible — hundreds of activity records, nobody to notice.
01The business problem
You have a list of people worth contacting and a message worth more than one send. A single email is ignored; five identical ones are spam. What you actually want is a ladder where behaviour decides the rung:
- somebody who replies should stop receiving the campaign immediately and reach a person;
- somebody who opens or clicks has shown interest and should get the next, different message;
- somebody who never engages should progress on a timer, or stop;
- somebody who unsubscribes or bounces should be suppressed everywhere, permanently;
- and you should be able to answer "is this campaign still running?" without opening five screens.
The first four are mechanism. The fifth is the one that decides whether the machine is worth having, and it is the one that is almost never built.
02Why the obvious approach fails
One long sequence with every step in it
The simplest reading of "multi-touch campaign" is one sequence with ten steps. It sends on a timer and it cannot branch: a recipient who clicks at step two receives step three exactly as though they had not. The only behavioural lever a sequence has over its own flow is unenrol — it can stop, but it cannot turn.
Expecting a sequence to hand over to another sequence
The next idea is a set of short sequences with the last step of each enrolling into the next. There is no such step. A sequence's nodes send emails, wait, and create records — enrolment into a sequence is not an action a sequence can take. Nothing in the editor hints at this until you look for the node and find it absent.
Sweeping with a scheduled process instead
A daily scheduled process over contacts, moving anyone whose engagement changed, does work — and throws away the thing that made this worth doing. Engagement is an event: opened at 09:14, clicked the pricing link, replied. A nightly sweep sees only state, arrives up to a day late, and cannot tell you which message produced the reaction.
Letting the catcher fire for anybody
Once the task-based chain is built, the catcher process watches task creation. Leave its actor at any user — the default reading of "when a task is created" — and every task a salesperson creates by hand is evaluated by the campaign machinery. The fix is a single setting, and §05 is about why it is not optional.
03Data model
Three objects and one convention carry the whole design.
| Piece | Role |
|---|---|
| Email sequence | Sends the steps. Ends. Cannot chain |
| Task (created by a global action) | The message. Carries the pointer to the next sequence |
| Catcher process | Triggered on task creation; writes the pointer onto the contact and hands off |
| Step counter on the contact | Which rung the contact is on. The enrolment process branches on it |
What a sequence enrols, and on what
A sequence's trigger names an entity type and a specific field id — the email field it sends to — with an optional lookup so it can reach an address on a related record. That detail matters more than it sounds: a sequence enrolling leads can send to the primary contact's email through the relation, which is why the enrolled record and the addressee need not be the same thing.
The settings that bound a sequence
| Setting | What it does |
|---|---|
timezone, dayOfWeek, fromTimeOfDay/toTimeOfDay | Sending window — sends are held outside it |
activeFrom, activeTo | Campaign life, as dates |
autoUnenrollWhenExpired | Whether anyone still in flight is released when it expires |
everyEmailStartsConversation | Whether each send opens a new thread or continues one |
triggerProcess, triggerProcessId | The named catcher. One process per sequence |
Why the message has to be a record
A global action can create a task, a lead, or a text — and the statistics count each separately. A task is the right carrier here because it is cheap, it attaches to the contact, it holds custom fields, and its creation is a trigger surface. The pointer rides in one of those fields.
The rejected alternative. The tidy instinct is a counter the chain increments — step 1 becomes step 2 becomes step 3. What a real ladder does instead is have each sequence name its successor, because the task template is where the value is written and the template is per sequence. That makes the chain a set of hard-coded pointers, which is more flexible (a branch can skip a rung) and more fragile (§06).
04Field-level configuration
The four global actions, in full
These are the sequence's only behavioural hooks. There are exactly four events:
| Event | Unenrol | Send a different email | Create a record | Also |
|---|---|---|---|---|
| On reply | ✅ | ✅ | ✅ | — |
| On unsubscribe | implicit | — | ✅ | — |
| On custom condition | ✅ | ✅ | ✅ | takes a filter |
| On bounce | ✅ | — | — | can unsubscribe the recipient |
Each is a flag plus its payload — a reply can unenrol, send a holding reply, and create a task, independently of one another.
The custom condition is where opens and clicks live
Reply, unsubscribe and bounce are fixed events. Open and click are not events you subscribe to — they are conditions you describe. The custom condition takes an ordinary filter, and the working shape is two clauses:
Message.subject Is "{the subject of the step you are watching}"
Email.tracking_status Is Opened OR Clicked
The subject clause is what scopes the condition to one step of the sequence rather than any message ever sent. It also means editing a step's subject line silently breaks the condition watching it — the filter still matches a string nobody sends any more.
The pointer and the counter
| Field | Lives on | Written by | Read by |
|---|---|---|---|
| Next-sequence pointer | Task | The sequence's task template | The catcher |
| Step counter | Contact | The catcher (and the entry process, once) | The enrolment process's branches |
| Campaign membership | Contact | The entry process | Every gate in the chain |
| Suppression flags | Contact | Unsubscribe, bounce, or a person | Every gate in the chain |
Name the pointer field for what it does. It is the single most load-bearing value in the chain and the easiest to mistake for something harmless — §06 has the consequence.
A note on boolean conditions in filters
Suppression gates test booleans, and a boolean "is false" test is stored with no operator at
all — operator: null with a value of 0. This is consistent
wherever booleans are filtered, so a rule with a null operator against a checkbox field is
normal rather than broken. It is worth knowing before you go hunting for a missing operator
that was never meant to be there.
05Automation & logic
The catcher, and the setting that makes it safe
One process, triggered on task creation, reads the pointer and routes. Its trigger actor is the part to get right. A record trigger's actor takes one of four values:
| Actor | Fires when the record is created by… |
|---|---|
AnyUser | anyone at all — including a person |
ProcessOwner | the process's own owner |
SelectedUnitsAndUsers | a named set of units or users |
ApplicationsOnly | automation only — never a human |
Applications-only is the correct choice for a catcher, and it is the difference between a closed loop and one anybody can accidentally push someone into. A salesperson logging a call should not re-enrol a prospect in a drip campaign.
The route, end to end
sequence step / global action fires
└─ creates Task { pointer = "next sequence" }
└─ catcher process (Task · Create · ApplicationsOnly)
├─ filter: task activity type is an engagement type
├─ filter: pointer is not empty
├─ filter: contact is in this campaign, not unsubscribed, not archived
└─ write Contact.step_counter = Task.pointer
└─ hand off to the enrolment process
└─ branch on step_counter → enrol into that sequence
The hand-off at the end is a sub-process call, which is how anything crosses a process boundary here — the constraint and the naming discipline are in Blueprint 011.
The shared enrolment ladder is the fragile part
In practice the enrolment process is not built per campaign — it accumulates. One production example carries dozens of unrelated campaigns in a single process of over a hundred nodes, with one campaign's gate sitting nineteen deep. Because a filter is one gate whose branches are first-match-wins, a contact's enrolment depends on its position relative to nineteen campaigns it has nothing to do with. Anything that makes an earlier gate match first silently removes the later one from reach.
Give a campaign its own enrolment process when it matters. The shared ladder is convenient once and expensive thereafter.
Make one rung produce work
The whole chain above is machinery. Somewhere in it, one branch must create a task a person is actually expected to do — open, assigned to a real owner, with a due date. The obvious candidate is the reply hook, and the next is a click on something commercially meaningful. Blueprint 014 makes the same argument from the other side: automation should route attention to a human, and a human should be the one who commits.
06Limits & trade-offs
A completed task is not work. Where every task template is created with a status of already-completed, owned by a single administrator, and consumed by a process that accepts only automation, the ladder produces activity records and no work items. It is easy to do by accident, because the tasks exist to carry a value rather than to ask anybody anything — and the result is a campaign that looks busy in every report and asks nothing of anyone.
- Because nothing asks, nothing notices. Observed on a live ladder: a cohort parked at the first step for months, with no recorded response, no meeting and no disqualification against any of them. The chain was working; the feed into it had stopped. Nothing reports the absence of new records, because an empty campaign and a quiet week are the same shape — the same failure class as the replication outage in Blueprint 009.
- A misnamed pointer field is a live wire. A field labelled as a duration in minutes, carrying the number of the next sequence, is doing the most consequential job in the chain under a name that invites edits. Anyone who changes it — a person tidying a task, or any future automation touching a field of that name — silently reroutes contacts into a different campaign. Name it for its function, and treat any short generic label on a control field as a defect waiting to happen.
- The ladder can terminate on a setting rather than on its data. A final sequence whose task template still points back to an earlier rung, and which stops only because its create-task flag is switched off, is one checkbox away from an infinite loop. Make the last rung's pointer terminal in the data — zero, or a value no branch matches — so that turning the flag on is safe.
- Nothing advances the counter except engagement. The entry process writes step one; only the catcher moves it on. A contact who never opens, clicks or replies stays at step one forever — correct behaviour, and invisible unless someone reports on it.
- Editing a subject line breaks the condition that watches it. The custom condition matches on the subject string, so a copy tweak silently detaches the hook. Nothing fails; the rung simply stops catching anybody.
- Bounce handling burns addresses permanently. On-bounce can unsubscribe the recipient, which is right for deliverability and unforgiving of a bad list: a poorly validated import suppresses a chunk of itself on first contact, and those contacts are then excluded from every future campaign by the same suppression gates. Validate before the first send — Blueprint 005 covers what an unvalidated import looks like.
- Statistics are per sequence, not per chain. Each sequence reports enrolments, sends, recipients, opens, clicks, replies, bounces, unsubscribes, created tasks and leads, and a current-enrolment count — but nothing aggregates a ladder. The health of the campaign as a whole has to be assembled by hand from five screens, which is exactly why nobody does it.
The trade-off worth stating plainly
Building the ladder from tasks buys real behavioural branching on a platform whose sequences cannot branch, using nothing but native parts. What it costs is that the chain's logic lives in three places at once — the task template inside each sequence, the catcher's filters, and the enrolment process's gates — and no screen shows all three together. That is survivable with a naming convention and a diagram, and unsurvivable without. If the campaign is genuinely linear and nobody needs to branch on behaviour, one sequence with more steps is the honest answer and costs a fraction as much to keep alive.
07Verification
Read from a live production space: a five-rung sequence ladder, its catcher process, the shared enrolment process, and the schema behind all three.
- The global-action set was read from the schema, confirming exactly four events — reply, unsubscribe, custom condition, bounce — with their independent unenrol, send-email and create-record flags, that only the custom condition carries a filter, and that bounce alone offers to unsubscribe the recipient.
- The custom condition was read from a live sequence: a subject-line clause combined with an email tracking status of opened or clicked.
- The sequence settings — sending window, timezone, active-from and active-to, auto-unenrol on expiry, every-email-starts-conversation, and the named trigger process — were read from the schema and confirmed populated on live sequences.
-
The catcher was traced in production: triggered on task creation with actor
ApplicationsOnly, filtering on engagement activity type, a non-empty pointer and the contact's campaign membership and suppression flags, then writing the pointer onto the contact and handing off. - The four actor values were confirmed from the enum, as were the trigger events, which include email-sent and email-received alongside create, update and delete.
- The ladder's pointer scheme was read from the task templates — each rung writing the number of its successor, and the final rung still carrying a pointer back to an earlier one while relying on a switched-off flag to terminate.
- The shared enrolment process was measured: over a hundred nodes, dozens of unrelated campaigns in one first-match-wins ladder, one campaign's gate nineteen deep, and the process itself carrying a warning status.
- The null-operator boolean convention was confirmed across three independent processes: a boolean "is false" test stores no operator and a value of zero.
Not observed, and stated as such:
- A sequence sending during this work. Every finding is read from stored configuration and stored statistics, not from a campaign run for the purpose.
- What happens if the final rung's create-task flag is switched on — the loop is inferred from the stored pointer value, not watched.
- Whether editing a step's subject line detaches the custom condition, which follows from the filter's shape but was not tested.
- The behaviour of the lead and text record types a global action can create; only the task path was traced.
What would signal a regression
- Every sequence in the ladder reporting zero current enrolments. The single cheapest health check, and the only one that distinguishes "nobody is in flight" from "nobody has engaged yet".
- Tasks accumulating while the step counter stays at one. The catcher is firing and the hand-off is not, so contacts are being marked and never moved.
- A rung's created-task count falling to zero while sends continue. Its custom condition has stopped matching — most often because a subject line was edited.
- Any human-owned open task of the campaign's activity type. Either the catcher's actor has been loosened off applications-only, or somebody is working inside the machine's task types, and both will produce surprising enrolments.