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

A sequence is not a list of emails in a Google Doc. It is a graph of steps with triggers, delays, stop conditions, branches, and channel mix. Tools (Outreach, Salesloft, Instantly, Smartlead, Apollo) implement engines; you design the graph, personalization contract, and safety rails. This lesson is that design craft.
Good sequences maximize learning and meetings under domain and attention constraints. Bad sequences maximize steps sent. Senior GTM eng defines: entry criteria, step graph, personalization slots, stop rules, concurrency limits, and experiment hooks (L7) before copywriting workshops.
Think of the engine as a workflow orchestrator: timers, external events (opens are weak; replies/bounces are strong), and side effects (CRM tasks). Idempotency matters — retries must not double-send step 2 because a webhook was delivered twice.

Sequence graph primitives

text
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
  1. 01Linear — simple cold email; fine for tests, weak for multi-persona.
  2. 02Branched — persona/industry/engagement forks.
  3. 03Event-driven — product signals or intent re-enter specific arms.
  4. 04HITL islands — research step for strategic accounts mid-graph.
  5. 05Multi-channel — email + LinkedIn + call with shared stop state.

Personalization at scale

Personalization is a spectrum: mail-merge fields → researched first lines → fully custom pods. Cost and error rates climb together. Use enrichment + light LLM drafts for mid-market; reserve human research for A-tier accounts. Always run preflight linters: empty vars, banned phrases, wrong locale, competitor name collisions.

Timing, capacity, and concurrency

Delays should respect timezone, business hours, and domain ramp (L5). Concurrency: one active primary sequence per contact per motion. Account-level caps prevent five contacts at one company getting the same blast on the same day — multi-thread with coordination, not collisions.
text
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.

Branching that is honest

Branch on reliable signals: reply sentiment (via reply ops), firmographic persona, explicit link clicks if tracked carefully, product activation. Be careful with open tracking — privacy features make opens noisy; do not build critical branches only on opens.
  1. 01Strong signals — reply, bounce, unsub, meeting booked, form fill.
  2. 02Medium — click on non-tracking-sensitive assets, inbound site visit matched.
  3. 03Weak — open, pixel, time-on-email guesses.
  4. 04Research branch — escalate strategic accounts to human before step 3.
  5. 05Breakup branch — short exit message, then suppress for cooldown TTL.

Human-in-the-loop design

HITL steps are queues with SLAs, not vibes. Define: what lands in the queue, required outputs (first line, angle, “skip”), timeout behavior (auto-skip vs hold), and QA sampling. Unbounded HITL becomes the Sheet bottleneck from L1.

Copy and offers as system parameters

Treat subject, body, CTA, and social proof as versioned parameters of arms in an experiment framework (deep dive L7). Sequence design includes how many arms, minimum sample, and freeze rules during domain warmups. Random constant churn of copy makes attribution impossible.
  1. 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.
  2. 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.
  3. 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.
Interview prompt pattern: “Design a sequence engine for two personas.” Draw entry gates, graph, stops, HITL, and capacity. Mention preflight lint and experiment freezes. Tools come last.

Exit criteria and cooldowns

Completed sequences need an exit policy: suppress for N days, move to nurture, or open a long-cycle revisit arm. Without cooldowns, list recyclers re-enroll the same people weekly and train spam complaints. Store last_exited_at and honor it in entry guards.
  1. 01Completed no-reply — cooldown 60–90d before re-enroll; require new intent signal to skip.
  2. 02After meeting no-show — short recovery arm owned by AE, not auto cold restart.
  3. 03After closed-lost — longer TTL + reason-based messaging if ever re-entered.
  4. 04After unsub — permanent email suppress; do not “try a new domain” to dodge.
text
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)
Close the lesson by redrawing: entry guards → graph steps → event edges (reply/bounce/unsub/booked) → exit cooldowns → experiment arm ids. If any edge is “someone remembers to click pause,” it is not production-ready.
A sequence is a state machine that spends reputation. Every step is a withdraw from a finite trust account.
docsOutreach sequence conceptsOutreachdocsSalesloft cadence overviewSalesloftarticleSmartlead / unlimited email sender patternsSmartleadarticleClay + sequencing GTM patternsClay

Checkpoint

Contact replies “interested — send times” but step 3 still sends 2 days later. Root architectural failure?

ASDR forgot a manual pause — train people harder onlyBMissing automatic stop/pause on reply event across channels; reply not wired as a first-class state transitionCSubject line was too good so the system assumed more education steps help
Sign up free to answer and see why

Checkpoint

You import 50k eligible contacts at 09:00. Engine tries to enroll all immediately. What should happen?

ABurst all sends to “strike while the list is fresh”BEnqueue enrolls behind per-mailbox/domain/hour caps; show queue depth; drain under policyCRandomly drop 80% of contacts to protect domains without telling anyone
Sign up free to answer and see why

Checkpoint

Product wants branch: if opened twice → aggressive discount step. Critique?

APerfect — opens are precise intent in 2026BWeak signal: prefer replies/clicks/product events; if testing opens, treat as exploratory only with capsCNever branch sequences — branching is always over-engineering
Sign up free to answer and see why

Checkpoint

HITL research queue has 3-day median wait; AEs complain. Design fix?

AMake every account HITL to improve quality furtherBTighten who enters HITL by score, add SLA + timeout fallback (safe template or skip), and staff to measured depthCRemove all templates and require full custom essays
Sign up free to answer and see why

Checkpoint

Idempotency: webhook “step_sent” arrives twice. Correct engine behavior?

ASend step again to be sure the prospect got itBDedupe on event_id / contact_step key; second delivery no-ops; state remains sentCMark contact failed and exit sequence on any duplicate
Sign up free to answer and see why

Can you design a sequence graph with stops, capacity guards, HITL queues, and idempotent sends?

New to itGetting thereConfident

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.