Loops
A step with a loop definition repeats its nested steps multiple times. Two loop types are supported: while and forEach.
while loop
Repeat while a condition is truthy:
steps:
- ordinal: 0
description: "Process pages until no next button"
action:
type: click
selector:
tagName: button
innerText: "Next"
url: "https://app.example.com/list"
riskLevel: low
requiresConfirmation: false
loop:
condition: "{{hasNextPage}}"
maxIterations: 50
counterVariable: pageIndex
steps:
- ordinal: 0
description: "Extract data from current page"
action:
type: extract
script: "document.querySelector('.data').textContent"
url: "https://app.example.com/list"
riskLevel: low
requiresConfirmation: false
captures:
- name: hasNextPage
strategy: evaluate
expression: "!!document.querySelector('button:has-text(\"Next\")')"
forEach loop
Iterate over items in a JSON array variable or a memory collection:
steps:
- ordinal: 0
description: "Process each user"
action:
type: navigate
url: "https://app.example.com/users"
url: "https://app.example.com/users"
riskLevel: low
requiresConfirmation: false
loop:
forEach: "{{userList}}"
itemVariable: currentUser
indexVariable: userIndex
maxIterations: 100
steps:
- ordinal: 0
description: "Navigate to user profile"
action:
type: navigate
url: "https://app.example.com/users/{{currentUser}}"
url: "https://app.example.com/users/{{currentUser}}"
riskLevel: low
requiresConfirmation: false
To iterate over a memory collection, use the collection: prefix:
loop:
forEach: "collection:products"
itemVariable: product
Loop fields
| Field | Type | Required | Description |
|---|
condition | string | One of | Template expression for while loop |
forEach | string | One of | Template variable (JSON array) or collection:name |
itemVariable | string | No | Variable name for the current item (forEach only) |
indexVariable | string | No | Variable name for the current index (forEach only) |
maxIterations | integer | No | Maximum number of iterations (safety limit) |
counterVariable | string | No | Variable name for the loop counter |
A loop must have exactly one of condition or forEach — not both.
Branches
A step with branches executes different sets of steps based on a variable’s value:
steps:
- ordinal: 0
description: "Branch based on account type"
action:
type: navigate
url: "https://app.example.com/account"
url: "https://app.example.com/account"
riskLevel: low
requiresConfirmation: false
branches:
value: "{{accountType}}"
cases:
- match: "personal"
steps:
- ordinal: 0
description: "Fill personal form"
action:
type: input
value: "{{name}}"
selector:
tagName: input
name: "fullName"
url: "https://app.example.com/account"
riskLevel: low
requiresConfirmation: false
- match: "business"
steps:
- ordinal: 0
description: "Fill business form"
action:
type: input
value: "{{companyName}}"
selector:
tagName: input
name: "company"
url: "https://app.example.com/account"
riskLevel: low
requiresConfirmation: false
default:
steps:
- ordinal: 0
description: "Skip unrecognized type"
action:
type: wait
url: "https://app.example.com/account"
riskLevel: low
requiresConfirmation: false
Branch fields
| Field | Type | Required | Description |
|---|
value | string | Yes | Template expression to evaluate |
cases | BranchCase[] | Yes | At least one case |
default | object | No | Default case with steps array |
BranchCase fields
| Field | Type | Required | Description |
|---|
match | string | Yes | Value to match against |
steps | Step[] | Yes | Steps to execute if matched (min 1) |
Conditional steps
Any step can have a condition field. When the condition evaluates to a falsy value, the step is skipped:
steps:
- ordinal: 0
description: "Click confirm only if total > 0"
condition: "{{totalAmount}}"
action:
type: click
selector:
tagName: button
innerText: "Confirm"
url: "https://app.example.com/checkout"
riskLevel: medium
requiresConfirmation: true
A step cannot have both loop and branches at the same time.