Skip to main content

What a series is

A series is a multi-step automation. Each step is one of:
Step typeWhat it does
EmailSend an email
SMSSend an SMS message (in-builder; SMS sending is currently not wired in production cron)
In-appSurface an in-app message
WaitPause for N hours/days/weeks
ConditionBranch based on a condition (open, click, property, event)
EndMark the user as done
Steps run in step_order — the recipient advances row by row. The visual graph in the builder is for editing and “Day N” labels; runtime execution follows the linear step order. Use series for welcome flows, re-engagement, onboarding, drip campaigns, and lifecycle sequences.

Two ways to build

When you create a series, you pick how to build it:
OptionWhen to use
AI AgentsDescribe what you want and the AI plans the series, generates emails in parallel, and lays them out for you. Good for first drafts.
Manual BuilderA React Flow canvas where you drag and drop nodes. Good for fine control, complex branching, and editing existing series.
Switch at Series > Setup while the series is still in draft. After activation, you stay in the manual builder.

Manual Builder nodes

In the canvas, you can add:
NodePurpose
TriggerPinned to top — defines how users enter (manual / event / segment match / user created)
EmailSubject + body with merge tags
SMSSMS content (builder only, sending not wired)
Wait/DelayPause N hours / days / weeks
ConditionBranch on email opened, link clicked, user property, or event fired
EndMarks the journey complete
The builder shows “Day N” labels on email and SMS nodes computed by walking the graph from the trigger. This is purely visual — runtime advances by step_order regardless of edges drawn.
Keep step order and graph order consistent. The runtime advances strictly by step_order — if your drawn edges and the underlying step list disagree, the order in the step list wins.

Email content

The email editor is the same ReplyComposer used in the inbox, in series mode. You can:
  • Write rich-text content (HTML)
  • Insert merge tags from a dropdown:
    • {{first_name|there}}
    • {{last_name}}
    • {{name|there}}
    • {{email}}
    • {{company_name}}
    • Any custom field — {{your_field|fallback}}
  • Use AI draft to generate subject and body from a prompt (with optional team/sender context)
Each merge tag has a fallback value used when the field is empty for a recipient.

Email styles

Each email step has an email_style setting:
StyleLook
PlainSimple text email, minimal framing
PersonalLooks like a personal email, light styling
BrandedUses your full brand template (logo, colors, footer)

A/B variants

Each email step can store variants. The cron splits recipients round-robin across the base + variants and tags each delivery with metadata.variant_id so you can track performance. Use variants to test subject lines, opening copy, or CTAs against each other.

Waits

Wait steps pause the recipient for a specified time. Configure:
  • Duration — number of units
  • Unit — minutes, hours, days, weeks
Common patterns:
  • 1 day after signup → “How’s it going?” email
  • 3 days after no activity → re-engagement email
  • 7 days after onboarding complete → ask for feedback

Conditions

Conditions branch the flow based on what users do. Available condition types:
TypeWhat it checks
email_openedDid the user open a previous email step?
link_clickedDid the user click a link in a previous email?
user_propertyDoes a user property match key=value?
event_firedHas a specific event been tracked?
When a condition is met, the user advances. When it isn’t met, the user is skipped with reason: "condition_not_met" and stops at that step. There’s no separate “No” branch in the engine — failed users are removed from the journey at that point.

Send windows and business days

Per series, configure:
SettingPurpose
Business days onlySkip Saturdays and Sundays
Send window enabledOnly send between certain hours
Send window start / endThe hour range (in series timezone)
Series timezoneDefault if no per-user timezone is known
Halo respects each recipient’s end_users.timezone when set; otherwise falls back to the series’ default timezone. When a send falls outside the window or on a weekend (with business days only), it’s deferred to the next valid time, not dropped.

Throttling

Set max_sends_per_hour on a series to throttle sending. Halo uses Redis to track a rolling-hour cap and defers sends that would exceed it. Use this when you have a large audience and want to spread sending to avoid spikes.

Re-enrollment

Whether users can re-enter a series:
SettingBehavior
reenroll_enabled off (default)Once a user enrolls, they can’t enroll again, even after completing
reenroll_enabled onUsers can re-enroll after completing
reenroll_delay_daysOptional delay before re-enrollment is allowed
When re-enrolling, prior rows are deleted to satisfy uniqueness; aggregate stats stay counter-based. If a user has an active pending or processing row, new enrollment is skipped (no reset, no duplicate).

Subscription lists

When a series uses a subscription audience or has an unsubscribed exit rule, recipients can unsubscribe from the linked list mid-series and exit cleanly. See Subscription Lists.

Exit rules

Each series can configure exit rules — conditions under which users are removed from the journey before completing. Available:
RuleWhen it fires
completedUser reaches the end
unsubscribedUser unsubscribes from a linked subscription list
repliedUser replies to a series email
segment_leaveUser no longer matches the segment audience
eventSpecific exit_event_name fires
manualA teammate manually removes the user

Series API

Programmatically enroll users via the Series API:
curl -X POST https://api.haloagents.ai/api/sdk/series \
  -H "Authorization: Bearer ab_live_xxxxxxxxxxxxxxxx" \
  -d '{
    "action": "enroll",
    "user_id": "user_123",
    "series_id": "uuid"
  }'
Use this to enroll users from your backend on specific events (signup, integration connection, plan upgrade).

Where to go next

Triggers & Conditions

Detail on how series start and how conditions evaluate.

Subscription Lists

Consent management for marketing emails.

Series API

Programmatic enrollment from your backend.