Back to the journal
Momo Business Guides

Flow steps: Decide

Variables, conditions, switches, checks, split tests, loops, subflows and jumps — the logic between the messages.

Message flows run on WhatsApp in this release. Other channels are on the roadmap; a flow bound to any other channel is refused at publish.

Decide steps are the logic between the messages: variables, conditions, switches, splits, loops and jumps. They run instantly and the customer sees nothing.

This is the reference for the Decide group of the flow builder's palette. Every step below is listed with what it does, the settings it takes, the branches it can leave by and the one thing to keep in mind. Settings marked "templated" accept {{vars.x}}, {{contact.name}} and {{last.text}}.

Set variable

Assign one or more variables.

Setting What it does
assignments [{name, value}] — value is templated and keeps its type when it is exactly one {{…}}. Arithmetic: {{vars.qty * vars.price}}, round/min/max/number. Dates: now(), today(), date_add(date, n, unit), date_sub(date, n, unit), date_diff(a, b, unit) (a minus b, in seconds unless a unit is named), date_format(date, pattern), date_part(date, part) where part is year, month, day, weekday (1 Monday – 7 Sunday), hour, minute, second, week, quarter or timestamp; and the literal N unit — {{vars.created_at + 7 days}}, {{today() + 1 month}}, {{now() - 90 minutes}}, {{vars.due - now()}} for the seconds between two dates.

Branches: next

Keep in mind: A value that is exactly one {{…}} keeps its type, so a list stays a list.

Decision

Branch on a condition.

Setting What it does
condition {var, op, value} | {all: [...]} | {any: [...]}; var is a path such as vars.choice, or a whole expression ({{vars.due - now()}} gt 0). Operators: eq / neq — case-insensitive text, numeric for numbers, truthy for booleans; contains / not_contains / starts_with / ends_with — case-insensitive text; on a LIST var, contains / not_contains / in test membership; gt / gte / lt / lte — numbers (thousands separators such as 1,000 accepted), else two dates as dates, else false with the reason in vars.__compare; empty / not_empty — null, "" and [] are empty; in — value is a list or a comma-separated string, matched case-insensitively; matches — a regular expression, case-insensitive; one that does not compile is false with vars.__regex_error set.

Branches: true false

Keep in mind: Text compares case-insensitively; a comparison that cannot be made is false, with the reason in vars.__compare.

Switch

Many cases on one value, plus a default.

Setting What it does
var The path to compare, e.g. vars.choice.
cases [{value, out}] — the value to match and the out to leave by (out defaults to value); no match leaves by default.

Branches: default — One out per config.cases[].out (defaulting to the case value), plus default.

Keep in mind: No match leaves by default — draw it.

Check value

Is it a real amount, phone, date or email? Store it cleaned up, or branch on why not.

Setting What it does
rules [{value, as, store_as?, label?, message?, optional?, …options}] — value is templated; as is one of text, number, integer, decimal, money, percent, boolean, date, datetime, time, email, phone, url, uuid, id, regex, in, length, range, required. A rule that passes writes its cleaned-up value to store_as (money → a number, phone → 255712345678, date → YYYY-MM-DD, uuid → lower-case). Options: min / max (a number, a length, or a date), decimals, currency, country (phone, default TZ), version (uuid: any, 4 or 7), pattern (regex and id), values (in), optional (an empty answer is fine), label (what to call it to a customer), message (your own wording instead of ours).
mode all (every rule must pass, the default) or any (one is enough).
store_errors_as Optional variable to put the full list of failures in; the first one is always in vars.__check as {field, label, kind, reason, code, message, value}.

Branches: valid invalid

Keep in mind: The first failure is always in vars.__check, so the invalid branch can say what was wrong.

Split test

A weighted split, sticky per contact.

Setting What it does
variants [{out, weight}] — each out becomes an exit; the choice is weighted and sticky per contact.

Branches: (dynamic) — One out per config.variants[].out — there are no fixed outs.

Keep in mind: Sticky per contact: the same customer takes the same branch every time.

Loop

Repeat a branch a bounded number of times.

Setting What it does
max_iterations How many times the body branch may run before leaving by done (1–50).
index_as Variable name for the position, from 0 (default loop_index); give a nested loop its own.
reset true (default) starts the count over when the loop is entered from outside its body; false carries on where it left off.

Branches: body done

Keep in mind: Bounded at 50 laps; sends inside a loop count against the session's quotas.

For each

Walk a list one item at a time — records from Find records, or any list variable.

Setting What it does
list The path to the list to walk, e.g. vars.customers.
item_as Variable name for the current item (default item); give a nested walk its own.
index_as Variable name for the position, from 0 (default index); give a nested walk its own.
max_items Stop after this many items (1–50).
reset true (default) starts the walk over when the node is entered from outside its body; false carries on where it left off.

Branches: item done

Keep in mind: Walks at most 50 items; the body must lead back to this node to close.

Subflow

Call another published flow and come back with its answers. A child that ends — by an End node or by running off its last edge — returns to next; one that fails, or ends with a reason other than completed, takes failed, with vars.__subflow = {reason, via} saying why.

Setting What it does
flow_id Id of the published flow to run.
inputs Optional {name: value} passed into the subflow's variables (templated; a value that is exactly one {{…}} keeps its type, so a list crosses as a list).
outputs Optional list of variable names to bring back when it returns. The child's own defaults (onError, onTimeout) are ignored: the root flow's apply throughout.

Branches: next failed

Keep in mind: The child must be published (a draft child runs only in the simulator); its own defaults are ignored.

Go to

Jump to another node.

Branches: next

Keep in mind: Jumps inside this flow only.

End

Finish the session with a reason.

Setting What it does
body Optional goodbye message.
reason Why the session ended, e.g. completed; shown in analytics.

Branches: (none — the flow ends)

Keep in mind: The reason is what analytics and the runs list show — pick a stable one.

Where next

Thanks for reading.Explore more stories