Skip to content
Expedify
6 min

Multi-Condition Router

When two branches are not enough. How condition groups, output paths and boolean expressions let one field fan out to as many routes as you need — and which operators actually evaluate.

A Condition asks one question and gives you two answers. That runs out fast. A lead is Hot, Warm or Cold; a ticket is billing, technical or sales; a deal is under 10k, under 100k, or the kind you tell the founder about. Chaining Conditions together works, but three of them nested is already a workflow nobody wants to open again.

The Multi-Condition Router is the node for that. One node, as many output paths as you need, each with its own rule. On the canvas it appears with a coloured handle per path.

Conditions, groups, paths

This node has more moving parts than most, and they only make sense in order. There are three layers, and each one is built out of the layer below it.

  1. A condition is one test: a field, an operator, a value. Same shape as the Condition node.
  2. A group bundles conditions together with AND or OR, and gets a name — group1, group2.
  3. A path is an output handle with a boolean expression over those groups: group1=true, or group1=true AND group2=false.

The reason for the middle layer is the thing worth understanding. Paths do not have to map one-to-one onto groups. Write the tests once, then combine them differently for each route — which is what makes this a router rather than a switch.

The four fields that matter. The four legacy ones beside them are migrated automatically; ignore them.

condition_groups

What it holds
Groups of logical conditions

output_paths

What it holds
Rich output path configurations

default_path

What it holds
Default fallback path configuration

execution_mode

What it holds
How to handle multiple matching paths One of: first_match · all_matches · error_on_all Defaults to first_match.

A worked example

A contact's lead status changes, and the router sends the run down one of three arms. The connector labels are the path names — that is what you type when you create a path, and what the canvas prints.

One field, three destinations

Click the router to see its groups and paths. Each arm leaves from its own handle.

Hot leadWarm leadEveryone else

Scroll for all 6 steps →

Two groups do the testing — one for Hot, one for Warm — and three paths consume them. The third path is the catch-all, and its expression is group1=false AND group2=false: everything that matched neither. That is a deliberate choice worth copying, and the next section explains why.

The Default Path, and why the example does not use it

Every router also has a Default Path — a fallback handle that fires when no other path matches. It is the right tool when you want a safety net without describing what falls into it.

An explicit catch-all path is usually better anyway. It appears in the panel with a name someone can read, its expression states what it catches, and you can give it a priority. A Default Path is silent about all three.

If you author workflows through the API rather than the canvas: wiring branches: { default: … } on this node does not reach the Default Path. The compiler treats default as the primary-flow handle and connects it to path1 instead — so your fallback silently becomes a second copy of path 1, and nothing tells you. Verified 2026-08-01. Wire an explicit path id (path3) until that is fixed.

Which operators actually work

Twelve operators evaluate. They cover text, numbers and emptiness:

The twelve the router evaluates.

Equality

Operators
equals · not_equals

Numeric

Operators
greater_than · less_than · greater_equal · less_equal

Text

Operators
contains · not_contains · starts_with · ends_with

Emptiness

Operators
is_empty · is_not_empty

The dropdown offers ten more that do nothing. Date and time operators — before, after, date_between, within_last_days and their time_* siblings — are declared in this node's schema and are selectable in the panel, but the evaluator has no branch for them and returns false. A path that depends on one never fires, and there is no error. Verified against the node source, 2026-08-01. Do the date test in a condition node upstream — it implements all 27 — and route on the result.

What happens when two paths both match

Nothing stops two expressions being true at once, so the router needs a rule. That is execution_mode, and the default is usually what you want.

Priority is a number per path; lower wins.

first_match

What runs
The highest-priority matching path, and only that one.
Reach for it when
The routes are alternatives — a lead is Hot or Warm, not both.

all_matches

What runs
Every matching path, in parallel.
Reach for it when
One event should genuinely cause several things.

best_match

What runs
The single highest-priority match.
Reach for it when
Rarely — first_match already does this for ordered paths.

The failure this creates is quiet. Leave the mode on first_match when you meant several arms to fire, and the extra ones simply never run — no error, just work that silently did not happen. If a path stops firing after you add another one above it, check the priorities before anything else.

Watch out: Needs output_paths[] (id/name/priority/condition_expression) + condition_groups[] + a default_path.

Wire edges on the path handles: path1…pathN and `default`. Operators: contains,not_contains,equals,is_empty,is_not_empty,in.

Condition or Router?

condition

When
Two outcomes, one test. Also when you need date or time comparison — it has 27 operators and all of them evaluate.

multi_condition

When
Three or more outcomes, or several tests combined differently per route.

Reach for the Router when a third branch appears, not before. Two Conditions in a row are easier to read than a router with two paths, and the router's config panel is a lot of surface for a yes/no question.

Try it

  1. Add a Multi-Condition Router after any node that returns a record.
  2. Make one group with a single equals test, and two paths: one for group1=true, one for group1=false.
  3. Wire a different node to each handle and run it both ways.
  4. Now add a third path whose expression is group1=true as well, leave the mode on first_match, and watch it never fire. Then switch to all_matches.

Next: Loop — for when the answer is not which path, but doing the same thing to every item in a list.

Related lessons