Conditions & Assertions
Conditions and assertions let you control which steps execute and guard against unexpected state.
Conditions
A condition on a step determines whether the step runs. If the condition evaluates to false, the step is skipped and the workflow continues to the next step.
- type: functionBlock
label: backup_config
functionBlock: "fb.examples.neops.io/configBackup:1.0.0"
runOn: device
condition:
type: jmes
jmes: "{{ check_reachability.result.success == true }}"
description: "Only back up reachable devices"
parameters:
backup_type: "running"
Structure
condition:
type: jmes
jmes: "{{ <expression> }}"
description: "Human-readable explanation" # optional
The jmes field is a JMESPath expression that must evaluate to a truthy value. The type is always jmes.
Common Patterns
Skip unreachable devices:
Only configure access ports:
Skip devices that already have the config:
Run only on Cisco devices:
Assertions
Assertions are guardrails. If any assertion evaluates to false, the step fails (instead of being silently skipped). Use assertions to enforce preconditions.
assert:
- type: jmes
jmes: "{{ check_neighbors.result.success == true }}"
description: "Device must have CDP neighbors before configuring interfaces"
- type: jmes
jmes: "{{ length(context.interfaces) > `0` }}"
description: "Device must have at least one interface"
Condition vs Assertion
| Behavior | Condition (condition) |
Assertion (assert) |
|---|---|---|
| False → | Step is skipped (workflow continues) | Step fails (triggers error handling) |
| Use for | Optional steps, platform-specific steps | Safety checks, preconditions |
| Typical | "Only do this if..." | "This must be true before..." |
Combine them
You can use both on the same step. The condition is evaluated first. If the condition is false, the step is skipped entirely and assertions are not checked. If the condition is true, assertions are evaluated before the step executes.
Continue on Error
Not Yet Enforced
continueOnError is defined in the workflow schema and can be set on steps, but the
execution engine does not yet evaluate it. A failed step will always stop the workflow
regardless of this setting. This feature is planned for a future release.
By default, a failed step stops the entire workflow. When implemented, setting continueOnError: true will let the workflow proceed even if this step fails:
- type: functionBlock
label: check_reachability
functionBlock: "fb.examples.neops.io/ping:1.0.0"
runOn: device
parameters:
host: "{{ context.device.ip }}"
continueOnError: true
This will be useful for non-critical steps like reachability checks where you want to attempt an operation but not block the rest of the workflow if a few devices are unreachable.
Info
When implemented, continueOnError will not change the transaction classification. If a
non-pure step executes and fails, the workflow may still end up as FAILED_UNSAFE even
if execution continues past that step.