Documentation / Workflows

Building blocks: deciding, repeating and waiting

Minimum role
Organisation admin
Applies per
organisation
Last updated
11 October 2026
aishaa version
80c056408

Menu path: Account > Workflows > (open a workflow) > Add step > Decide / Repeat / Wait

In short: with flow.condition (Condition) you split the run into yes and no, with flow.switch (Choose a route) you choose a route of its own per value, and with message.check (Check the message) you test whether the message has an image or the customer has a record of a certain kind. flow.foreach (For each) repeats steps for each item of a list and flow.wait (Wait) holds the run until a moment. None of these blocks uses AI.

Where to find this

Account > Workflows, open a workflow, Add step: flow.condition, flow.switch and message.check in the group Decide, flow.foreach in Repeat, flow.wait in Wait. Who: from the role Organisation admin.

A Choose a route step in the workflow editor with the Value field (an inserted value such as Channel), the Routes per value list and, for each route plus other, the If choice.

flow.condition: Condition

Continues via true if all conditions are met, otherwise via false.

Input

Name Label Type Required Explanation
conditions Conditions Conditions yes A list of at least one {"path": ..., "op": ..., "value": ...}, as with the trigger. Every condition must have a path.
  • You write the path without curly brackets: trigger.urgent, zoek.count, trigger.message.text.
  • A path may point to the trigger, including content fields (trigger.ticket.status, trigger.message.text), or to the output of an earlier step.
  • The operators and the way of comparing are the same as with the trigger: eq, neq, gt, gte, lt, lte, contains, exists, missing; numbers as numbers, moments as moments, the rest as text, case-insensitive. See Triggers and events.

Exits: true (yes) and false (no).

Output fields: none.

Example: only continue if the record has a reference and the customer has an e-mail address.

{ "id": "compleet", "label": "Is everything known?", "block": "flow.condition",
  "inputs": { "conditions": [
    { "path": "dossier.reference", "op": "exists" },
    { "path": "trigger.customer.email", "op": "exists" }
  ] },
  "exits": { "true": "actie", "false": "vraag-collega" } }

When to use it: for a yes/no decision on something the run knows. Also to test content that a trigger condition may not read.

flow.switch: Choose a route

Chooses a route of its own per value, such as per channel or per kind of question. The first route equal to the value wins; otherwise the run goes via other.

Input

Name Label Type Required Explanation
value Value Text yes What you choose on, usually a reference such as {{trigger.channel}}.
cases Routes per value Cases yes The values with a route of their own, such as ["Email", "WhatsApp"]. 1 up to and including 12, all text, all different (capitals do not count), each at most 80 characters, not other. Every value is an exit.

Exits: every value from cases, exactly as you wrote it in the list, plus other (other).

Output fields

Field Label Content
value Value The value that was chosen on.
case Route taken The route taken, or other.

How it compares: as text, case-insensitive, without spaces at the beginning and end. A number or yes/no is compared as text (true, 42). If the value is empty, the run goes via other.

Example: a route per topic id, so that a new name for the topic does not break the routing.

{ "id": "per-onderwerp", "label": "Choose the route per topic", "block": "flow.switch",
  "inputs": { "value": "{{trigger.topicId}}", "cases": ["101", "102"] },
  "exits": { "101": "retour", "102": "levering", "other": "antwoord" } }

When to use it: to route on a fixed value (channel, status, topic, the answer of an earlier step). When not to: if a person or the AI has to judge the meaning of free text; use agent.choose then.

message.check: Check the message

Checks the message the run started on: does it contain an image, or is a record of a certain kind (an order, a dossier) known for the customer.

Input

Name Label Type Required Explanation
check Check Choice yes hasImage (Has an image), noImage (Has no image), recordFound (Customer has a record of this kind), noRecord (Customer has no record of this kind).
kind Kind of record RecordKind no Only with recordFound and noRecord: the record kind, such as order. Empty: any kind.

Exits: true (yes) and false (no).

Output fields: none.

Good to know: the step needs the trigger’s message (trigger.messageId). So start the workflow on message.understood or message.received; otherwise the step fails.

flow.foreach: For each

Repeats steps for each item of a list, such as each record that record.find found.

Input

Name Label Type Required Explanation
items List Text yes Exactly one reference to a list, such as {{zoek.records}}.

Exits

Exit Label When
each for each item Leads to the steps for one item. Must be connected.
done done After the last item (or straight away with an empty list).

Output fields

Field Label Content
item Item The current item. You read its fields with a path: {{elk.item.title}}.
index Index (from 0) The position of the item, starting at 0.
position Number (from 1) The position of the item, starting at 1.
count Number found The number of items in the list.
skipped Left out (above the maximum) How many items were skipped because the list was longer than 200.

How the repeat works

  • The steps for one item are all steps you reach from each without passing the repeat itself.
  • A step in there that leads nowhere (no next, or an exit that is not connected) sends the run back to the repeat. The repeat then takes the next item.
  • After the last item, the run continues via done.
  • The steps for one item may only be reached via each: not from before the repeat and not from after it. Otherwise you cannot publish the workflow.
  • At most 200 items per repeat; the rest is skipped and skipped says how many.
  • A value that is not a list counts as one item; nothing counts as no items.
  • A repeat inside a repeat is allowed.
  • When you try out a workflow, the repeat goes through the first three items.

Example: a task for each dossier found.

[
  { "id": "zoek", "label": "Find the customer's dossiers", "block": "record.find",
    "inputs": { "kind": "dossier" }, "exits": { "several": "elk", "found": "taak-een" } },
  { "id": "elk", "label": "For each dossier", "block": "flow.foreach",
    "inputs": { "items": "{{zoek.records}}" }, "exits": { "each": "taak" } },
  { "id": "taak", "label": "Task per dossier", "block": "task.create",
    "inputs": { "title": "Check dossier {{elk.item.reference}}" } },
  { "id": "taak-een", "label": "Task for the one dossier", "block": "task.create",
    "inputs": { "title": "Check dossier {{zoek.reference}}" } }
]

The step taak has no next, so after each task the repeat takes the next dossier. done is not connected, so the run ends after the last dossier.

flow.wait: Wait

Waits a number of minutes, or until a moment the run knows, and then continues. Waiting costs nothing.

Input (exactly one of the two)

Name Label Type Explanation
minutes Minutes Number How many minutes to wait: a number greater than 0 and at most 30 days (43,200). A fixed number, not a reference.
until Until Moment A moment in ISO 8601, or a reference to a moment, such as {{deadline.result}}.

If you give both or neither, you cannot publish.

Exits: none; continues with next.

Output fields: until (Until), the moment at which the run continues.

Good to know

  • A moment that has already passed lets the run continue straight away.
  • An until more than 30 days away is shortened to 30 days.
  • If the moment is unknown when the step runs (the reference is empty or not a moment), the step fails.
  • Content fields you read after a wait step (such as trigger.ticket.status) are read as they are at that point. That way you can check after a waiting time whether a conversation has been closed in the meantime.
  • When you try out a workflow, the step shows until when it would wait and continues straight away.

Example: a reminder after two days, only if the conversation is then still waiting for the customer (status answered).

[
  { "id": "wacht", "label": "Wait two days", "block": "flow.wait", "inputs": { "minutes": 2880 }, "next": "nog-open" },
  { "id": "nog-open", "label": "Is the conversation still waiting for the customer?", "block": "flow.condition",
    "inputs": { "conditions": [ { "path": "trigger.ticket.status", "op": "eq", "value": "Answered" } ] },
    "exits": { "true": "herinnering" } }
]

Good to know

  • These blocks change nothing outside the run. When you try out a workflow, aishaa really works them out.
  • A loop back to an earlier step is allowed. A run stops after 2,500 executed steps.

Related

Last updated on 11 October 2026. Checked against aishaa version 80c056408. Something wrong or missing? Email support@aishaa.nl.