The sequence builder is where the actual outbound playbook is drawn. NimbusOS uses a visual React Flow editor that persists the full node graph, delay specifications, and branching conditions in a single SequenceTemplate object. Reopen a sequence months later and it shows up exactly as you drew it, down to the viewport position. This article walks through the node types, the delay semantics, conditional branching, sub-sequences, and the gotchas that trip up complex sequences.
The Sequence Model
A sequence has three layers.
SequenceTemplate holds the full visual state. Nodes (steps), edges (connections between steps), viewport (zoom and pan). When you save the builder, the entire graph serializes to JSON and writes to this table.
SequenceStep is one row per step. Each step has a type (email, delay, condition), a template binding if it is an email, a delay specification, and x/y position for the visual editor.
Enrollment tracking sits on a separate model. When a contact enrolls in a sequence, an EmailStepEnrollment row is created per step they reach, tracking status (scheduled, sent, skipped) and timestamps.
Step Types
Five step types cover every reasonable outbound pattern.
Email step
The workhorse. An email step binds to an EmailTemplate, sends at the scheduled time, and advances to the next step when complete.
Email steps also carry optional condition flags. send_only_if is a condition evaluated at send time; if it evaluates false, the step is skipped and the contact moves to the next step. stop_if_replied halts the whole sequence for that contact if any reply has been recorded.
Delay step
A standalone delay with no send. Useful when you want a wait without attaching it to an email step. Most sequences attach the delay directly to the email step (via delay_value and delay_unit), but standalone delays matter when branching joins back to a single continuation path.
Condition step
A branching node. Evaluates a condition and routes the contact to one of two (or more) downstream branches. Conditions operate on contact fields, engagement events, and custom field values.
Common conditions: lead_score > 60, opened_step_1 = true, icp_tier = 'A', custom.has_completed_trial = true.
Task step
A non-send step that creates a Task for a human. Typical use: after step 3, if no reply, create a task for the rep to manually LinkedIn connect. Task steps do not advance automatically; they mark the contact as awaiting human follow up.
Sub-sequence step
A pointer into another full sequence. When a contact reaches a sub-sequence step, they are enrolled into the referenced sequence. The main sequence pauses for this contact until the sub-sequence completes or returns.
Sub-sequences are the power tool for sophisticated outbound playbooks. More on them below.
Connecting Steps: Edges
Edges connect step outputs to step inputs. Each step has exactly one input port. Email and delay steps have one output. Condition steps have two or more outputs (one per branch). Sub-sequence steps have one output that fires when the sub-sequence completes.
The React Flow editor enforces valid connections. You cannot connect an output to an output, you cannot loop a step to itself, and you cannot create disconnected islands that have no path from the sequence start.
Delays: Value and Unit
Delays use two fields: delay_value (integer) and delay_unit (one of minutes, hours, days, business_days). business_days is the most common for B2B cold outreach and correctly skips weekends and major holidays.
A common sequence rhythm is step 1 on enrollment (delay 0), step 2 at delay 3 business_days, step 3 at delay 4 business_days, step 4 at delay 7 business_days. Four touches spread across roughly three weeks.
Delays compound. Step 2's delay is from the completion of step 1, not from enrollment. A 3 business_day delay on step 2 plus a 4 business_day delay on step 3 means step 3 sends 7 business_days after enrollment, not 4.
Conditional Send at Step Level
The send_only_if condition on an email step is evaluated immediately before send. If it fails, the step is marked skipped and the contact advances.
A useful pattern: step 3 has send_only_if: opened_step_1 = true OR opened_step_2 = true. Contacts who never opened the first two touches never get step 3. This cuts volume and protects reputation on likely-dead contacts.
Condition expressions support AND, OR, NOT, and parentheses. Field references are bare field names. Values can be strings, numbers, or booleans.
Sub-Sequences: The Power Tool
A sub-sequence is a second sequence that the first sequence calls into. Think of it as a function call. The main sequence pauses for the contact until the sub-sequence finishes or the contact exits the sub-sequence through a specific termination node.
Common sub-sequence patterns.
Objection handler. Main sequence covers the general pitch. If a contact replies with a pricing question, a sub-sequence fires that sends the short ROI primer, then a delay, then a direct ask to meet. The main sequence resumes only if the sub-sequence completes without conversion.
Event follow up. Main sequence includes a step that triggers on registration for a webinar. The main sequence pauses and a sub-sequence runs the pre-event reminder, post-event asset delivery, and pre-meeting scheduling. Main resumes once the event flow is done.
Reference gather. A late-stage contact has engaged but not converted. A sub-sequence fires that asks for a reference, delivers a case study, and offers an exec-to-exec introduction. Main resumes only if no reference is generated.
Wiring a sub-sequence
In the builder, drop a sub-sequence step node and pick the target sequence from the dropdown. Configure the trigger condition (reply contains X, lead flagged Y, custom field Z changed). Configure the return condition (sub-sequence completes, specific termination node reached, timeout).
Sub-sequences and stop conditions
Stop conditions on the main sequence still apply while a sub-sequence is running. A stop_if_replied on the main sequence halts the contact entirely if they reply during the sub-sequence.
Saving and Versioning
Saving the sequence creates a new version of the SequenceTemplate. Versions are numbered sequentially. Sequences bound to campaigns pin to a specific version, so in-flight campaigns do not change behavior when you save an edit.
To propagate an edit to an in-flight campaign, open the campaign and explicitly upgrade the sequence binding to the new version. The upgrade affects contacts who have not yet reached the edited step. Contacts who already passed it are not resent.
Pre-Launch Validation
Clicking Save runs a validation pass. Five checks run.
Every email step has a template bound. Empty steps are the single most common reason a campaign launches and quietly does nothing.
At least one step has stop_if_replied or the campaign has stop_on_reply. Without either, a sequence keeps sending after a reply. This is almost never what you want.
No unreachable steps. A step with no incoming edge is dead code. The validation flags it.
Sub-sequence references are valid. A sub-sequence reference to a deleted or disabled sequence blocks the save.
Condition expressions parse. Invalid condition syntax blocks the save.
All five must pass. The save button stays disabled until the sequence is valid.
Running a Sequence Against Contacts
A sequence does not run on its own. It is attached to a campaign. The campaign enrolls contacts based on its filter, and the sequence is what they experience.
Enrollments are batched. The sequence engine picks up pending enrollments every 5 minutes and advances whatever steps have their delay satisfied. A step with a 3 business_day delay, enrolled on Monday morning, reaches Thursday morning and the engine sends it on the next cycle after that.
Concurrency: One Contact Across Many Sequences
A contact can be in multiple sequences simultaneously. NimbusOS does not enforce a single-sequence rule by default. This is a double-edged feature.
Helpful: a contact on a nurture drip can also be in a tier A cold outreach campaign that bypasses the nurture for urgent messaging.
Harmful: accidentally running three overlapping cold outreach campaigns against the same contact produces a spam complaint waiting to happen.
The Segment level suppression setting mitigates this. A segment can specify "contacts in segment X cannot enter sequence Y". The rule is enforced at enrollment time.
Visual Editor Shortcuts
Six keyboard shortcuts to know.
spaceplus drag: pan the canvasscrollon track pad: zoomdeleteorbackspace: delete the selected nodecmd/ctrl+d: duplicate the selected nodecmd/ctrl+s: save the sequencecmd/ctrl+zandcmd/ctrl+shift+z: undo and redo
The editor preserves undo history until the next save. After save, undo history resets.
Troubleshooting
"Sequence is live but no sends are happening"
Two common causes. First, the campaign is in draft. Activate the campaign. Second, the sequence step bindings are empty; open the builder and verify each step has a template.
"Contact is stuck at step 2 for days"
The delay unit might be wrong. 7 hours looks like a week at a glance but fires in 7 hours. Check the step detail.
Or the send_only_if condition evaluates to false. The step is skipped rather than held, so the contact should advance past it; if the contact is stuck, the step after the skipped one has its own condition failing.
"Sub-sequence fires but main never resumes"
The sub-sequence termination condition is not met. If your sub-sequence lacks an explicit termination (a node marked as exit), the main waits indefinitely. Add a termination node and reconnect.
"Branch condition fires the wrong way"
Enable verbose logging on the step. The step log shows the exact values read for each field in the condition. A common cause is a boolean field stored as a string "true" instead of the boolean true.
Frequently Asked Questions
Can I copy a sequence from another workspace?
Yes, through export and import. The export produces a JSON file with nodes, edges, and template references. Import creates a new SequenceTemplate in the destination workspace. Templates are rebound to local workspace templates during import; the importer shows which templates need to be matched.
What is the maximum number of steps in a sequence?
Soft limit 50. Above that, the editor becomes slow and the branching complexity usually exceeds what is maintainable. Break into sub-sequences.
Can two steps fire at the same time?
Only if they are on parallel branches from a condition step. On a linear sequence, two steps never fire simultaneously. Parallel branches on a condition step can both fire, but the engine sequences them to avoid hitting the same inbox twice in the same minute.
Does the sequence respect per-contact cooldown?
Yes, through the global cooldown_period on the workspace. A contact who just received a send from any campaign will have their next send queued past the cooldown, even if the sequence schedule said to fire sooner.
Can a sequence send on weekends?
Only if the step uses a days or hours unit rather than business_days. business_days automatically skips weekends and recognized holidays in the contact's region.
What to Read Next
After building sequences, useful next pages are Campaign Types for picking the right type of campaign to attach your sequence to, Email Templates for the template binding details, and Personalization Variables for the variable system that sequences render.