> ## Documentation Index
> Fetch the complete documentation index at: https://docs.connie.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Logic and control

> Branch, loop, wait, filter, require approval and decide what happens when a step fails.

Logic steps control the path a run takes instead of doing work themselves. Use them to send different leads down different paths, repeat steps for every item in a list, wait a few days before following up, or pause for a human to approve.

**Where:** open a workflow → **Build** → click **+** → **Add an Action**. Router, AI Analyzer, For each and Delay are on the **AI** tab; the LinkedIn checks are on the **LinkedIn** tab. Search works too ("wait" finds **Delay**).

## Router

A Router sends each run down one of several paths ("flows") based on conditions. Example: leads from companies with more than 200 employees go to Flow 1 (book a demo), everyone else goes to the fallback (nurture email).

<Steps>
  <Step title="Add a Router">
    Click **+** and choose **Router**: "Route flow to multiple flows based on conditions." It starts with **Flow 1** and **Flow 2**. Flow 1 starts as the fallback: "No other flows matched (fallback)".
  </Step>

  <Step title="Set each flow's conditions">
    Open a flow, give it a name and an optional description ("Describe when this flow should be triggered..."), then click **Add filter**. Each condition is a [variable](/automations/workflows/variables), an operator and a value ("Enter value..."). Combine conditions with AND inside a group and OR between groups.
  </Step>

  <Step title="Add more flows if you need them">
    Use **Add flow** in the Router's settings, or the Router card's **⋯** → **Add Flow**.
  </Step>

  <Step title="Add steps under each flow">
    Click the **+** under each flow to add its steps.
  </Step>
</Steps>

**Operators**

* **Any value:** Exists, Does not exist, Is empty, Is not empty, Equals, Not equals.
* **Text:** Contains, Does not contain, Starts with, Ends with, Matches regex, Does not match regex.
* **Yes/no:** Is true, Is false.
* **Numbers:** Greater than, Less than, Greater or equal, Less or equal.
* **Dates:** Is before, Is after, Is on or before, Is on or after, Is between, Is within last N days, Is within next N days, Is more than N days ago.
* **Lists:** Array length equals, Array length greater than, Array length less than. Equals and Contains on a list match if **any** item matches.
* **AI Analyzer:** describe in words what to check ("Describe what AI should check..."), and AI answers true or false.

**How a Router decides**

* A router's flows (its branches) are checked **in order, top to bottom**, and **only the first matching flow runs**. Turn on **Allow multiple matching routes** to run every flow that matches.
* The fallback runs only when nothing else matched. If nothing matches and there's no fallback, the flows show **Condition not matched** and the steps after them show **Skipped**.
* **Text comparisons are case-sensitive.** "Yes" doesn't equal "yes".
* **A flow with no conditions matches everything.** An empty flow near the top catches every run. The builder flags it: "This route needs at least one filter".
* **A missing value is an error, not "false".** If a condition such as Equals or Contains points at a value that doesn't exist for this run, the run fails. Check with **Exists** or **Is not empty** first. See [Why is my variable empty?](/automations/workflows/variables#why-is-my-variable-empty)

## AI Analyzer

"Evaluate data with an AI and branch on the result." Write an **Analysis Prompt** in plain language, for example "Is this email a meeting request?", and insert the variables it should look at. The step always has two branches, **True** and **False**: "The AI decides true/false based on the analysis prompt above. No manual conditions needed."

Use it when the decision needs judgement that's hard to express as rules.

## For each

"Run every item in the array." A For each repeats the steps inside it once for every item in a list. Example: an AI Agent step returns five competitor websites; a For each runs **Scrape Web** on each one.

<Steps>
  <Step title="Add a For each">
    It appears as a box with a **Body** inside.
  </Step>

  <Step title="Choose what to loop over">
    In **Iterate Over**, insert a variable that holds a **list**. Variables that aren't lists show **not an array** ("Only array variables can be used as an iterator").
  </Step>

  <Step title="Add steps inside the Body">
    Inside the loop, the For each's group in the variable picker gives you **item** (the current item), **index** (its position, starting at 0) and **totalItems**.
  </Step>
</Steps>

**Good to know**

* **Items are processed one after another**, not all at once. A Delay inside the loop is repeated for every item.
* **Every paid step inside the loop is charged once per item.** Five items × a 1-credit step = 5 credits for that row.
* An empty list means zero iterations; the Body shows **Skipped**.
* Loops can be nested.
* The cell shows a summary such as "Success: 12 of 12" or **Partial** ("5 of 6"). A failed iteration shows "An iteration failed".
* With **Stop flow if node fails** on, the first failed item stops the loop and the run. Re-running with **Run only empty cells** carries on from the failed item.
* If a single-value field gets a list, you'll see "Arrays are not supported for this field. You must group this node to For each node to use it." Click **Wrap in For Each**.

## Delay

"Pause the flow for a specified duration." Choose a **Time Unit** (**Seconds**, **Minutes**, **Hours**, **Days**) and a **Duration** (default 5 minutes). The card shows "Waits 2 days before continuing" and, during a run, a countdown such as "3 days left".

* Delays survive restarts; a 3-day wait really waits 3 days.
* **A Delay ends early if the lead replies or their outreach is stopped.** The cell then reads "Skipped due to lead replied to msg" and the rest of that sequence doesn't run. This is on purpose, so you don't follow up with someone who already answered.

## LinkedIn checks

| Step | What it checks | Branches |
| - | - | - |
| **Check If Open Profile** | Whether a LinkedIn profile is open, meaning it can receive InMail. Set the **LinkedIn Profile URL**. | **Is Open** / **Is Not Open** |
| **Check LinkedIn Connection** | Whether a lead is a 1st-degree connection. Set **Sender LinkedIn URL** (your connected account) and **Recipient LinkedIn URL**. | **1st Degree** / **2nd/3rd Degree** |

**Send Linkedin Connection Req** also branches: **Accepted** and **Not accepted** (after a wait, 14 days by default). If you leave **Not accepted** empty, the run simply ends for leads who didn't accept.

## Filter

**Filter Records by condition** (in **Data & Logic**) is a gate: later steps only run when its condition is true. **Outside a For each, a false result ends the whole run.** Inside a For each it skips just that item. The cell reads "Condition met" or "Condition not met".

## Formula

**Formula** "Calculate a value from row data or upstream node results." Write a formula such as `add({{Amount}}, {{Tax}})` and choose a **Return type** (**Auto**, **Text**, **Number**, **Currency**, **Date**, **Boolean**, **JSON**). It's free. There's no separate code step: use **Formula** for calculations and **Api Call** to call another app.

## Require approval

Make a run stop and wait for a person before a step runs, for example before sending an email to a big account.

<Steps>
  <Step title="Turn it on">
    Step **⋯** → **Require approval**. The card gets an amber **Approval** badge.
  </Step>

  <Step title="Choose how reviewers hear about it (first time only)">
    "Email reviewers about approvals?": **In-app only** or **Also send email**. Reviewers always get an in-app notification. You can change this later in **Settings** → **Notifications**.
  </Step>

  <Step title="Approve or reject during a run">
    When a run reaches the step, its cell shows **Needs approval**. Open the cell on the **Runs** tab, or follow the notification, and click **Approve** or **Reject**.
  </Step>
</Steps>

* **Reject** stops that row's path; later steps show **Skipped**.
* **Approvals expire after 3 days and then count as rejected.** Deciding after that shows "This approval has expired: the workflow stopped waiting for a decision, so yours was not recorded. Run the workflow again to request a new approval."
* Inside a For each, the waiting item pauses while other items carry on.
* Not available on the trigger, Routers, branching steps, For each or Delay ("This node type cannot require approval.").

See [Approvals](/automations/approvals) for where approvals appear and who is notified.

## When a step fails

By default, **a failed step stops the rest of that run**, and the steps after it show **Skipped**. You can change this:

* **For the whole workflow:** **Stop flow if node fails** (on by default) in [Workflow settings](/automations/workflows/test-and-run#workflow-settings), or on the Schedule trigger card.
* **For one step:** step **⋯** → **Continue run on error** or **Stop run on error**. The step's setting wins over the workflow setting.

When a step continues after an error, it passes on error details that a later Router can check, for example to send failures to a Slack alert.

Some failures **always** stop the run, whatever the setting: running out of credits, and outages on Connie's side. **Test** runs always stop on error.

Connie retries brief, temporary errors automatically. During an outage, a step waits and retries for up to 24 hours before it fails.

## Deactivate a step

Step **⋯** → **Deactivate** skips the step in every run (dashed, dimmed card; cells read **Node deactivated**). Later steps still run, with blanks where its data would be. Deactivating a Router or For each skips everything under it ("Skipped because an upstream node is deactivated"). **Activate** turns it back on.

## Variants (A/B tests)

Step **⋯** → **Create Variant** adds an alternative version of a step, such as a second email wording. You can have up to 5 variants (A–E) per step. Not available on triggers, Routers, branching steps or For each.

## Good to know

* **Credits:** Router, For each, Delay and the LinkedIn checks are free. **AI Analyzer** and AI conditions use AI, which is billed by usage. Paid steps inside a For each are charged once per item. See [Credits](/automations/workflows/test-and-run#credits).
* There's no Merge step: to join branches, connect both to the same next step.
* There's no "End" step: a branch ends after its last step.

## Troubleshooting

<AccordionGroup>
  <Accordion title="The Router takes the wrong branch">
    **Why:** Text comparisons are case-sensitive; only the first matching flow runs; and a flow with no conditions matches everything.
    **Fix:** Check capitalisation, reorder your flows, and make sure every flow (except the fallback) has a condition. Turn on **Allow multiple matching routes** if more than one flow should run.
  </Accordion>

  <Accordion title="The Router failed instead of going to the fallback">
    **Why:** A condition points at a value that doesn't exist for this run. That's an error, not false.
    **Fix:** Add an **Exists** or **Is not empty** condition first. See [Why is my variable empty?](/automations/workflows/variables#why-is-my-variable-empty)
  </Accordion>

  <Accordion title="Everything after one failed step was Skipped">
    **Why:** **Stop flow if node fails** is on (the default).
    **Fix:** Turn it off in Workflow settings, or set that step to **Continue run on error**.
  </Accordion>

  <Accordion title="The run stopped even though Continue run on error is on">
    **Why:** Running out of credits and outages always stop a run.
    **Fix:** Add credits ([Credits](/billing/credits)) and retry the row.
  </Accordion>

  <Accordion title="The Delay ended early">
    **Why:** The lead replied, or their outreach was stopped. This is by design.
    **Fix:** Nothing to fix. The cell reads Skipped due to lead replied to msg.
  </Accordion>

  <Accordion title="My For each is slow">
    **Why:** Items run one after another, and any Delay inside repeats for every item.
    **Fix:** Move Delays outside the loop where you can, and keep the loop body small.
  </Accordion>

  <Accordion title="I ran out of credits halfway through a loop">
    **Why:** The credit check before a run counts each paid step once, but steps inside a For each are charged once per item.
    **Fix:** Make sure your balance covers the step price × the number of items. See [Credits](/billing/credits).
  </Accordion>

  <Accordion title="The Filter step stopped the whole run">
    **Why:** Outside a For each, a false result from **Filter Records by condition** ends the run.
    **Fix:** Use a **Router** if you want other steps to continue on a different path.
  </Accordion>

  <Accordion title="A deactivated step's later steps ran with blanks">
    **Why:** Deactivating a single step skips only that step.
    **Fix:** Deactivate the Router or For each above it to skip a whole branch, or deactivate the later steps too.
  </Accordion>

  <Accordion title="This approval has expired">
    **Why:** No one approved within 3 days, so it counted as rejected.
    **Fix:** Run the row again to request a new approval.
  </Accordion>
</AccordionGroup>

## Related

* [Variables](/automations/workflows/variables) — the values conditions compare
* [Build a workflow](/automations/workflows/build) — add, move and delete steps
* [Test and run](/automations/workflows/test-and-run) — run, retry and workflow settings
* [Approvals](/automations/approvals) — where approvals appear and who's notified


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.