Building blocks: deciding, repeating and waiting
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
pathwithout 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
eachwithout 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
skippedsays 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
untilmore 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.
