Steps
Steps are the building blocks of a workflow. Each step is one of three types: a function block invocation, an inline (embedded) workflow, or a reference to another workflow definition.
Function Block Step
The most common step type. It executes a registered function block:
- type: functionBlock
label: get_version
functionBlock: "fb.examples.neops.io/show_version:1.0.0"
runOn: device
parameters:
timeout: "{{ parameters.timeout }}"
| Field | Required | Description |
|---|---|---|
type |
Yes | Always functionBlock |
label |
Yes | Unique identifier within the workflow (alphanumeric + underscore) |
functionBlock |
Yes | SemVer reference (package/name:version) |
runOn |
No | Entity type to execute on (overrides FB default) |
parameters |
No | Key-value pairs passed to the FB (supports JMESPath interpolation) |
rawParameters |
No | Literal parameters (not interpolated) |
condition |
No | Skip this step if condition evaluates to false |
assert |
No | Fail if any assertion evaluates to false |
acquire |
No | Acquire additional entities for this step |
retryConfig |
No | Retry on failure (schema-defined, not yet enforced) |
repeatConfig |
No | Repeat the step multiple times (schema-defined, not yet enforced) |
continueOnError |
No | Continue workflow on failure (default: false) (schema-defined, not yet enforced) |
delay |
No | Wait N seconds before executing (0-600) |
description |
No | Human-readable description |
The label is how subsequent steps reference this step's results: {{ get_version.result.data.version }}.
Embedded Workflow Step
Group multiple steps into a logical unit. Useful for organizing complex workflows into phases:
- type: workflow
label: pre_checks
name: pre_checks
steps:
- type: functionBlock
label: ping
functionBlock: "fb.examples.neops.io/ping:1.0.0"
runOn: device
parameters:
host: "{{ context.device.ip }}"
- type: functionBlock
label: collect_facts
functionBlock: "fb.examples.neops.io/facts:1.0.0"
runOn: device
Embedded workflows have the same fields as the root workflow (steps, name, config, acquire, etc.) plus the step-level fields (label, condition, assert, continueOnError).
An embedded workflow:
- Executes its steps in sequence (or parallel if
config.executionStrategy.parallel: true) - Shares the parent workflow's execution context
- Can have its own
acquireclause to pull in additional entities - Is part of the parent workflow's transaction -- it does not create a separate execution
Workflow Reference Step
Not Yet Implemented
Workflow references are defined in the schema and documented here for planned behavior,
but the execution engine does not yet support them. Attempting to execute a workflow
containing a workflowReference step will result in a runtime error. Use embedded
workflow steps for composition in the meantime.
Reference another workflow definition. This enables reuse across workflows:
- type: workflowReference
label: backup
workflow: "wf.neops.io/config_backup:1.0.0"
strategy: embed
parameters:
backup_type: "running"
| Field | Required | Description |
|---|---|---|
type |
Yes | Always workflowReference |
label |
Yes | Unique identifier |
workflow |
Yes | SemVer reference to the target workflow definition |
strategy |
Yes | embed or dispatch |
parameters |
No | Parameters to pass to the referenced workflow (JMESPath interpolated) |
rawParameters |
No | Literal parameters (not interpolated, takes precedence on key conflicts) |
Embed vs Dispatch (Planned)
embed -- The referenced workflow's steps are inlined into the current execution. They share the same context and transaction. This is equivalent to copy-pasting the steps.
dispatch -- The referenced workflow runs as a separate execution with its own context and transaction. The parent workflow waits for it to complete. Use this for independent sub-workflows that should have their own locking and failure isolation.
graph TD
subgraph embed ["embed — same context & transaction"]
direction TB
E1["Step 1"] --> EA["Ref Step A<br/><i>inlined</i>"]
EA --> EB["Ref Step B<br/><i>inlined</i>"]
EB --> E3["Step 3"]
end
subgraph dispatch ["dispatch — separate execution"]
direction TB
D1["Step 1"] --> DR["Workflow Ref"]
DR -. "launches & waits" .-> DS["Sub-Workflow<br/>(own context)"]
DS -. "completes" .-> D3["Step 3"]
end
Step Execution Order
Steps execute in the order they appear in the steps array. Within each step, the engine creates jobs for all entities in scope (determined by runOn). By default, all jobs for a step must complete before the next step begins.
With config.executionStrategy.parallel: true on the workflow, the engine allows per-entity pipelining: device 1 can proceed to step 2 while device 2 is still on step 1.
Choosing the Right Step Type
| Use case | Step type |
|---|---|
| Run a single function block | functionBlock |
| Group related steps (e.g., "pre-checks", "configure", "verify") | workflow (embedded) |
| Reuse a workflow across multiple parent workflows | workflowReference with embed (planned) |
| Run a sub-workflow with independent failure isolation | workflowReference with dispatch (planned) |
See also:
- Parameters & Interpolation -- JMESPath expressions in step parameters
- Conditions & Assertions -- Conditional execution and validation
- Retry & Rollback -- Failure handling for steps
- Examples -- Complete workflow examples using all step types