Lesson 4 of 8 · 48 min
Sequence engines, branching, and human-in-the-loop
Design sequence engines as graphs: entry gates, multi-channel steps, reliable stop conditions, capacity backpressure, personalization contracts, HITL queues, and idempotent event handling.
Linear 5-step spam → graph engine
Key idea
Sequence graph primitives
1SEQUENCE GRAPH PRIMITIVES23 Entry: band==A AND valid_email AND not suppressed AND channel_ok4 Step types: email | linkedin_task | call_task | wait | manual_review5 Edges: on_complete → next; on_reply → exit_to_reply_ops;6 on_bounce → suppress; on_unsub → suppress;7 on_no_reply after T → branch_B8 Branches: persona, industry, engaged vs dark, A/B copy arm9 Guards: max_emails_per_domain_per_day; contact.concurrency==11011 Personalization contract:12 required slots filled or step skips to safe generic / HITL13 never send {{empty}} or wrong company name — preflight lint- 01Linear — simple cold email; fine for tests, weak for multi-persona.
- 02Branched — persona/industry/engagement forks.
- 03Event-driven — product signals or intent re-enter specific arms.
- 04HITL islands — research step for strategic accounts mid-graph.
- 05Multi-channel — email + LinkedIn + call with shared stop state.
Personalization at scale
Common mistake
“LLM-personalize every email as uniquely as possible — spam filters love creativity.”
Timing, capacity, and concurrency
1CAPACITY GUARDS23 per_mailbox_daily_send_limit # warmup + provider caps4 per_domain_daily_send_limit # your sending root domain policy5 per_target_company_daily_touch # avoid pile-ons6 per_contact_active_sequences = 17 global_new_enrolls_per_hour # smooth spikes post-list-load89 Backpressure: if limits hit, queue enrolls — do not drop silently.10 Surface queue depth on the L1 observability census.Key idea
Branching that is honest
- 01Strong signals — reply, bounce, unsub, meeting booked, form fill.
- 02Medium — click on non-tracking-sensitive assets, inbound site visit matched.
- 03Weak — open, pixel, time-on-email guesses.
- 04Research branch — escalate strategic accounts to human before step 3.
- 05Breakup branch — short exit message, then suppress for cooldown TTL.
Human-in-the-loop design
Common mistake
“If SDRs personalize every step manually, quality automatically wins.”
Copy and offers as system parameters
- 01Q: How many steps in a cold sequence? Enough to cover angles without normalizing ignore — often 3–5 email touches over 2–4 weeks plus optional multi-channel. Justify with reply curves, not folklore. Stop early on any reply.
- 02Q: Email vs multi-channel first? Start where identity is strongest and cost is clear. Multi-channel helps strategic ABM but needs shared stop state. Do not duct-tape LinkedIn tasks that continue after email unsub.
- 03Q: How do you prevent double-sends after integration glitches? Idempotency keys per contact-step, durable sent log, stop flags as source of truth, and reconcile jobs comparing ESP sent events vs engine state.
Exit criteria and cooldowns
- 01Completed no-reply — cooldown 60–90d before re-enroll; require new intent signal to skip.
- 02After meeting no-show — short recovery arm owned by AE, not auto cold restart.
- 03After closed-lost — longer TTL + reason-based messaging if ever re-entered.
- 04After unsub — permanent email suppress; do not “try a new domain” to dodge.
Common mistake
“If they didn’t reply, we should immediately restart a longer 12-step sequence.”
1ENTRY GUARD (before enroll)23 assert band in {A,B}4 assert valid_email and not suppressed5 assert active_sequences(contact)==06 assert now - last_exited_at >= cooldown_for(exit_reason)7 assert company_daily_touch_count < cap8 assert personalization_preflight_ok(step1)9 else: enqueue_or_reject(reason_code)Key idea
docsOutreach sequence conceptsOutreachdocsSalesloft cadence overviewSalesloftarticleSmartlead / unlimited email sender patternsSmartleadarticleClay + sequencing GTM patternsClayA sequence is a state machine that spends reputation. Every step is a withdraw from a finite trust account.
Checkpoint
Contact replies “interested — send times” but step 3 still sends 2 days later. Root architectural failure?
Checkpoint
You import 50k eligible contacts at 09:00. Engine tries to enroll all immediately. What should happen?
Checkpoint
Product wants branch: if opened twice → aggressive discount step. Critique?
Checkpoint
HITL research queue has 3-day median wait; AEs complain. Design fix?
Checkpoint
Idempotency: webhook “step_sent” arrives twice. Correct engine behavior?
Can you design a sequence graph with stops, capacity guards, HITL queues, and idempotent sends?
Takeaways
- Sequences are graphs with stops, branches, and capacity — not step lists.
- Personalization needs contracts and linters; HITL needs SLAs.
- Backpressure and idempotency protect domains and trust.
- Next: deliverability, domains, warming, bounce hygiene (gos-deliverability).
Next lesson: treat sending infrastructure as production — domains, warmup, and hygiene.
Sources
Free to read · better with Enzo
Learn it with Enzo
Save your progress, answer the checkpoints, and let Enzo quiz you on what you just read.