Workflow makes every route explicit. Branching steps create named outgoing paths, while terminal steps deliberately end a path.

## Choose the right branching step

| Need                                    | Step           | Routes                          |
| --------------------------------------- | -------------- | ------------------------------- |
| Check subscriber state once             | Condition      | Yes / No                        |
| Wait for behavior or state change       | Wait for event | Matched / Timeout               |
| Randomly distribute traffic             | A/B test       | One route per weighted variant  |
| Rejoin or jump to another existing step | Move to step   | Direct target, no outgoing edge |
| End a successful path                   | Goal           | Terminal                        |
| End a non-success path                  | Exit           | Terminal                        |

## Condition

A condition evaluates the subscriber once when the run reaches it. Every filter in the condition must match for the **Yes** path; otherwise Lumail follows **No**.

![Condition step with explicit Yes and No routes](/docs/workflows/condition-branches.png)

Use a condition for facts that are meaningful at one moment, such as:

- Has the customer tag now?
- Is lifetime revenue above a threshold?
- Does the plan field equal `pro`?

Do not use a condition when the workflow should pause and wait for the answer to change. Use **Wait for event** instead.

## Wait for event

This step pauses the run until one of two outcomes:

- **Matched**: the selected event arrives or the audience filters become true.
- **Timeout**: the configured duration expires first.

Event mode can listen for payment, tag, field, email, capture-page, and workflow events. Audience mode wakes when relevant subscriber data changes.

Always design both routes. A missing business decision on the timeout path often leaves subscribers receiving content that no longer makes sense.

## A/B test

An A/B test distributes runs across weighted routes. It does not duplicate email content automatically: add the actual email, wait, or action for each variant.

Read [A/B Testing](/docs/workflows/workflow-ab-testing) for assignment, success attribution, and result interpretation.

## Move to step

Use **Move to step** to rejoin a shared sequence or intentionally loop to an earlier node. The target must already exist and cannot be the move step itself.

The runtime follows the configured target directly, so this step does not use a normal outgoing edge. Avoid unbounded loops: every loop should have a state change, wait, counter, or branch that eventually ends it.

## Goal and Exit

Both are terminal:

- **Goal** records conversion and completes the run.
- **Exit** completes that routed path as exited and records its optional reason.

Global exit rules are different. They repeatedly guard future steps regardless of the current route. See [Goals](/docs/workflows/workflow-goals) and [Exit Rules](/docs/workflows/workflow-exit-rules).

## Graph rules

- Every condition needs **Yes** and **No** edges.
- Every event wait needs **Matched** and **Timeout** edges.
- A/B percentages must total exactly 100%.
- Goal steps cannot have outgoing edges.
- Move-to-step targets must exist and cannot point to themselves.
- Every non-trigger node must be reachable from a trigger.
- A normal path may end without a terminal node when no next edge exists.

## Example: trial conversion path

1. Trigger when `trial-started` is added.
2. Send the onboarding email.
3. Wait up to seven days for a payment.
4. Route **Matched** to the `Purchased` goal.
5. Route **Timeout** to a condition that checks engagement.
6. Send a reminder on **Yes** and exit quietly on **No**.

This graph separates waiting for a future event from evaluating current state once.

## Related documentation

- [Wait Step](/docs/workflows/workflow-wait-step)
- [A/B Testing](/docs/workflows/workflow-ab-testing)
- [Goals](/docs/workflows/workflow-goals)
- [Exit Rules](/docs/workflows/workflow-exit-rules)
