Function Blocks
A function block is a versioned, reusable unit of execution that does one thing: read a config, push a template, collect interface counters, discover devices. Developers write them in Python using the Worker SDK. The workflow engine registers them, resolves them by version, and orchestrates their execution.
What the Engine Knows
When a function block is registered with the engine, it receives:
| Property | Purpose |
|---|---|
package / name / version |
Identity (e.g., fb.neops.io/ping:1.0.0) |
parameterJsonSchema |
JSON Schema for input validation |
resultDataJsonSchema |
JSON Schema for output validation |
runOn |
Entity type this FB operates on (device, group, interface) |
fbType |
Category: facts, configure, check, execute, none |
isPure |
No side effects -- safe to discard without consequences |
isIdempotent |
Same input produces same output -- safe to re-run |
The engine uses this metadata to:
- Validate workflow definitions at deployment time (does the referenced FB exist? Are parameters compatible with the schema?)
- Resolve version ranges at execution time (find the best matching version)
- Determine transaction safety (can this workflow be retried? Is the failure safe?)
- Classify failures -- if all executed steps were pure, the failure is
FAILED_SAFE
Pure and Idempotent
These two properties are the foundation of the engine's transaction model. Pure means no side effects (read-only). Idempotent means safe to re-run (same input → same result). The engine uses these flags to classify failures and (when implemented) determine retry eligibility.
For the full explanation, decision trees, and best practices, see Types & Safety Semantics.
Why this matters for network automation
In traditional scripting, a failed automation run leaves you wondering: did it apply the config to some devices but not others? Do I need to undo anything? The pure/idempotent model eliminates this ambiguity. The engine tracks exactly what ran, and the safety properties tell you precisely what state you are in.
Function Block Types
The fbType categorizes function blocks for UI organization and filtering:
| Type | Description | Typically pure? |
|---|---|---|
facts |
Collect data from devices (show commands, SNMP) | Yes |
configure |
Push configuration to devices | No (but often idempotent) |
check |
Validate compliance or state | Yes |
execute |
General-purpose execution | Depends |
none |
Utility (data transformation, reporting) | Usually yes |
Lifecycle in the Engine
- Registration -- Workers register their function blocks on startup. The engine stores the metadata and JSON schemas.
- Resolution -- When a workflow references
fb.neops.io/ping:1, the engine finds the latest1.x.xversion. - Acquire -- The engine creates ACQUIRE jobs on the blackboard. Workers pick them up and run the function block's
acquire()method to determine what additional entity data is needed. - Execution -- The engine creates EXECUTE jobs on the blackboard. Workers pick them up and run the function block's
run()method. - Result -- The worker pushes the result (success/failure, data, DB updates) back to the blackboard.
Writing function blocks
This page describes function blocks from the engine's perspective. To learn how to
implement run(), acquire(), and rollback() in Python, see the Worker SDK's
Anatomy of a Function Block.