Docs · Concepts

Templates and flows.

You don't draw flow DAGs by hand in Ciela. Every multi-channel sequence starts from one of four templates, which gets compiled into a nodes-and-edges shape the engine knows how to run. This page is the one-pager on how that pipeline works, what each piece owns, and where you actually edit what.

The shape

Templates
lib/flows/templates.ts
Compile step
compileSequenceToFlow
Engine schema
flows + flow_enrollments tables
Driver
Cron tick at /api/flows/process
Editor surface
Omnichannel modal on the dashboard
Source of truth
The template you picked, customized inline

The four templates

  • email-linkedin. Five steps, opens with email, two-day wait, LinkedIn connection note, two-day wait, LinkedIn follow-up message. The default pick when work email coverage is decent and LinkedIn is healthy.
  • email-call. Email opens, two email follow-ups on three-day cadences, then a cold call from Vance. The pick when the deal size justifies the human-hour cost of a phone conversation.
  • linkedin-call. Connection note, two-day wait, opening message, two-day wait, cold call. The pick when you don't have email but you do have phone numbers and LinkedIn URLs.
  • full-omnichannel. Email, LinkedIn connect, LinkedIn message, cold call, all spaced out with cooldowns. Maximum surface area, best when the list is small and high-value.

Each template is a linear list of {kind, ...fields, days} steps. The kinds are email, linkedin_connect, linkedin_message, ai_dial, and wait. The first four map to Mira, Eli, and Vance, the wait is a pure cooldown.

How a template becomes a running flow

  1. You open the Omnichannel modal on the dashboard, pick one of the four templates, and customize the copy on each step. Subjects, bodies, connection notes, dial scripts, all editable inline, the template just gives you a sane starting point.
  2. On Launch, compileSequenceToFlow turns the linear list of steps into a {nodes, edges} graph the flow engine understands. Wait steps become wait nodes, send steps become send nodes, edges chain them in order.
  3. The compiled flow saves to the flows table, status active. Every contact you selected on the campaign gets a row in flow_enrollments with the current node, the wait-until timestamp, and a per-row status.
  4. The flows cron tick (driven by cron-job.org, not Vercel) hits /api/flows/process on a schedule, the route walks every active enrollment, advances anything past its wait, fires the channel-specific send, and updates the row.

What customizing actually changes

You're editing the steps before compile, not the compiled graph. That means you can change copy, change wait days, toggle AI mode on a step (so the writer drafts dynamically at send time instead of using static text), even add a phone number or assistant id per step. You don't move steps around or branch the flow, that's intentional, it keeps the engine boring and the campaigns predictable. If you need a fundamentally different shape you pick a different template.

What runtime does on its own

  • Reply detection. A reply on any channel flips the enrollment to stopped, no more sends on any other step for that contact.
  • Graceful channel pause. Email step with no account configured logs skipped reason:no_account_configured and breaks the chain for that row. Account flagged auth-failed parks the enrollment until the next cron tick, by which time you've reconnected.
  • No silent retries. Every skip and every queue-and-retry shows up in the enrollment row, so the dashboard always tells you why a step didn't fire.

Keep reading

Need help?

Ciela can walk you through any step. Or write to support@ciela.ai and we'll jump on the connection with you.

Ask Ciela