Skip to content

Registration Protocol

Function blocks are registered with the engine by workers at startup. The registration protocol ensures that schemas are compatible across versions and that function blocks are available for workflow execution.

Registration Flow

sequenceDiagram
    participant Worker
    participant Engine

    Worker->>Engine: POST /workers/register
    Engine->>Worker: worker UUID

    Worker->>Engine: POST /function-blocks/register<br/>{package, name, version, schemas, workerId}
    Engine->>Engine: Validate schema compatibility
    alt New FB or compatible version
        Engine->>Worker: 201 Created
    else Incompatible schema or changed frozen property
        Engine->>Worker: 400 Bad Request
    end

Registration Payload

Workers send function block metadata via POST /function-blocks/register:

Field Required Description
package Yes Namespace
name Yes Function block name
majorVersion / minorVersion / patchVersion Yes Semantic version
parameterJsonSchema Yes JSON Schema for input parameters
resultDataJsonSchema Yes JSON Schema for output data
runOn No Entity type: one of global, device, interface, group, client (the EntityType enum); any other value answers 400. Stored as an empty string when omitted
fbType Yes Category (facts, configure, check, execute, none)
isPure No (default false) No side effects; declared dbUpdates do not count as side effects (Pure)
isIdempotent No (default false) Safe-to-retry flag
reversible No (default false) The block’s rollback() undoes its side effects, so the engine may roll the step back. A pure block is never rolled back, so the flag has no effect on it
rollbackDataJsonSchema No JSON Schema of the block’s rollback data. Without it, a reversible block’s snapshots are dropped as no_schema
workerId No Associate this FB with a specific worker
description No Human-readable description
markdownHelpText No Extended documentation

The engine validates step parameters against parameterJsonSchema and the worker’s result data against resultDataJsonSchema before either travels on. Which JSON Schema draft applies, how defaults are filled, when values are converted and how unions such as X | None behave is in Schema Validation and Type Conversion.

Schema Compatibility Rules

When registering a new version of an existing function block, the engine enforces compatibility:

Parameter schema (input) – backward compatible: : New versions must ensure that the set of required parameters in the new version is a subset of (or equal to) the required parameters in the existing version. Adding new optional parameters is always safe. The engine validates compatibility against the exact version (if re-registering), the latest patch version, and the latest minor version of the same major, so only a new major version escapes it.

Result schema (output) – forward compatible: : New versions can add fields to results but must not stop returning required fields or return values the existing schema doesn’t allow. This ensures that workflows that reference step results still find the expected data.

Immutable properties: : runOn and fbType cannot change across versions of the same function block. These are part of the function block’s contract.

Frozen per exact version: : A re-registration of the same exact version may not flip isPure, isIdempotent or reversible, because runs still open read them for their compensation ledgers and retries, and it must carry the same rollbackDataJsonSchema, compared regardless of key order; adding a schema to a version registered without one counts as a change. Such a re-registration is refused with a 400. A new patch or minor version may change these flags and carry any rollback-data schema; that schema is not part of the compatibility checks against the latest patch and minor version.

Re-registering one exact version: : The rules above apply to the stored row of that version too. Its parameter schema may only widen, so the new registration accepts every parameter the stored one accepted, and its result schema may only narrow, so anything reading the stored schema can read the new results. A change the check finds incompatible answers 400, naming each finding by schema and path, for example parameterJsonSchema/properties/a. Against the stored row of the same exact version, enum and const count too: dropping a value from parameters, or adding one to results, is refused. A change that only reorders object keys is no change. Only description, markdownHelpText and deprecated can change freely.

A refused registration stops the worker

The Neops worker SDK treats a 400 as permanent: the worker unregisters and exits at the first refused block, and the blocks after it are not registered. A compatible schema change is also one-way. Once a copy with wider parameters is stored, a worker still carrying the narrower copy of that version is refused, so roll back such a change by publishing a new version.

The check is structural and doesn’t see every incompatible change. A change it doesn’t find is stored and only warned about:

  • Inside anyOf, oneOf, allOf or $ref. An optional str | None field is an anyOf.
  • Keywords it doesn’t read, such as format, not, minProperties, propertyNames, contains and if/then/else.
  • additionalProperties gaining a schema, such as dict becoming dict[str, str].
  • items appearing on an array that had none, and uniqueItems: true appearing where the keyword was absent.

Each of these goes unnoticed for parameters that narrow, and the reverse change for results. Give such a change a new version.

Worker Association

Function blocks can be associated with specific workers during registration. This enables:

  • Tracking which workers can execute which function blocks
  • Job routing – the blackboard only returns jobs to workers that have registered the matching function block
  • Health monitoring – if a worker goes offline, the engine knows which function blocks are affected

Multiple workers can register the same function block (for horizontal scaling). They share one stored row per exact version, so the last accepted registration wins for description, markdownHelpText, deprecated, and the parameter and result schemas. A registration that changes any of these logs one warning naming the function block, the worker that wrote, the workers linked to the version before it, and the changed fields, without their values. The engine doesn’t record which linked worker wrote the replaced content. An identical re-registration stays silent, whatever the key order of its schemas, so a restart or further workers of one deployment add no warning. Two deployments that register different descriptive content for one version warn each time the stored content flips: give the changed copy a new version.

Deregistration

When a worker gracefully shuts down (POST /workers/:uuid/unregister), its function block registrations are preserved but unlinked from the worker. The function block definitions remain available for workflow resolution – only the worker’s ability to execute them is removed.

When a function block is deprecated, existing workflows can still reference it, but new workflows should use the latest version.