Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

neops-worker-sdk-py

Python SDK for building network automation function blocks for the neops 2.0 platform. Write small, typed Python units that the workflow engine orchestrates, schedules, and scales.

@register_function_block(Registration(name="show_version", run_on="device", ...))
class ShowVersion(FunctionBlock[ShowVersionParams, ShowVersionResult]):
    async def run(self, params, context):
        async with ConnectionProxy.connect(context.device) as conn:
            output = await conn.send_command("show version")
        return FunctionBlockResult(success=True, data=ShowVersionResult(output=output))

Prerequisites

  • Python 3.12+
  • uv (recommended) or pip
  • A running neops-workflow-engine instance (default: http://localhost:3030)

Quick Start

uv sync --extra test               # install all dependencies (dev + fb groups are defaults)
cp .env.example .env               # configure URL_BLACKBOARD, DIR_FUNCTION_BLOCKS
uv run neops_worker                # start worker (polls engine for jobs)
uv run pytest -q && make lint && make typeCheck-baseline  # verify

Architecture

Your Function Blocks (@register_function_block)
    |
    v
Registry (global singleton, discovers FBs from DIR_FUNCTION_BLOCKS dirs)
    |
    v
Worker Startup
  |- Register worker with engine (POST /workers/register -> UUID)
  |- Register function blocks (POST /function-blocks/register for each)
  |- Start heartbeat task (POST /workers/:uuid/ping every 20s)
  \- Start job polling task (POST /blackboard/job every 10s)
        |
        v
    ThreadPoolExecutor (max_workers=1)
        |
        v
    FunctionBlock.acquire() / run() / rollback()
        |
        v
    ConnectionProxy -> ConnectionPlugin -> BaseConnection
        |                                      |
        v                                      v
    WorkflowContext (snapshot + diff)    Device (netmiko/napalm/scrapli/ncclient)
        |
        v
    Push result to engine (POST /blackboard/job/result)

Development

Install

uv sync                              # default: dev tools + fb deps (default-groups in pyproject.toml)
uv sync --extra test                 # + test deps (pytest, remote-lab)
uv sync --no-dev                     # without dev tools (fb group stays — only dev is excluded)

Run

The worker connects to a workflow engine at URL_BLACKBOARD and polls it for jobs. This repo does not ship an engine or a CMS — there is no docker-compose.yml and no lab/ here any more (see Local environment). Point the worker at an engine you already run, or at the one in the lab stack.

uv run neops_worker                  # start worker process
python -m neops_worker_sdk.cli.neops_worker  # alternative

Code Quality

uv run ruff format --check neops_worker_sdk examples tests  # format check
uv run ruff check neops_worker_sdk examples tests            # lint
uv run ruff check --fix neops_worker_sdk examples tests      # lint + auto-fix
make lint                                                    # format + lint combined
make typeCheck                                               # pyrefly, full view incl. pre-existing debt
make typeCheck-baseline                                      # pyrefly, CI gate: fails only on NEW errors (pyrefly-baseline.json)

Testing

Tests are organized in tiers using pytest markers. By default, remote lab tests are excluded.

Command What runs
uv run pytest Unit + SDK tests (default)
uv run pytest -m function_block Function block integration tests
uv run pytest -m remote_lab Remote lab tests (needs REMOTE_LAB_URL)
make test Unit tests (uv run pytest -q)
make test-examples Example function block tests
make test-function-blocks Function block + remote lab tests
make test-all Everything

Remote lab tests require REMOTE_LAB_URL to be set:

export REMOTE_LAB_URL=http://<remote-lab-host>:8000
make test-all
Marker Applied by Purpose
function_block @fb_test_case Local function block lifecycle tests
remote_lab @fb_test_case_with_lab Tests requiring a provisioned lab topology
examples Auto (conftest.py) All tests collected from examples/
sdk -- SDK internal tests

Local environment

The full local stack — CMS, workflow engine, web client, a worker and 15 containerlab devices (10 FRRouting + 5 Nokia SR Linux) — used to live in lab/ in this repo and no longer does. It was extracted into its own repo, zebbra/neops-lab, together with the root docker-compose.yml; the local-env-*, local-lab-* and apply-cms-config make targets went with it and do not exist here.

Get the lab next to this repo, then drive it from there:

git clone git@github.com:zebbra/neops-lab.git ../neops-lab   # skip if you have it

make build-docker                                  # HERE: -> neops-worker-sdk:latest
export NEOPS_WORKER_SDK_IMAGE=neops-worker-sdk:latest
make -C ../neops-lab local-env-init                # one-time; local-lab-up aborts without it
make -C ../neops-lab local-lab-up
make -C ../neops-lab local-lab-discover            # 15 devices + interfaces land in the CMS

Building the image here is required, not optional: the lab defaults to quay.io/zebbra/neops-worker-sdk:develop, which is built from origin/develop and carries no base function blocks, so discovery fails there with "Function block … not found". The lab also needs a Linux host with sudo-less containerlab and several GB of RAM — read ../neops-lab/README.md § Prerequisites first. Deeper notes on this seam (including the exact function block version the lab pins) are in AGENTS.md § Local Lab.

Configuration

Environment variables loaded via python-dotenv from .env. See .env.example for all options.

Variable Default Purpose
URL_BLACKBOARD (required) Workflow engine base URL
DIR_FUNCTION_BLOCKS (required) Comma-separated dirs to scan for function blocks
WORKER_NAME (none) Human-readable worker name
HEARTBEAT_INTERVAL 20 Seconds between heartbeat pings
POLL_INTERVAL 10 Seconds between job poll requests
SHUTDOWN_TIMEOUT 60 Seconds a running job gets after a shutdown request; then the worker deregisters and ends its process, killing the job mid-run
RESULT_PUSH_TIMEOUT 300 Seconds to keep re-sending a job result while the engine is unreachable
STARTUP_RETRY_TIMEOUT 120 Seconds to keep retrying registration at startup
BLOCKING_DETECTION_THRESHOLD 0.5 Seconds threshold for blocking warnings

Docker

make build-docker                                           # production image, exactly as CI builds it (-> neops-worker-sdk:latest)
docker run --env-file .env neops-worker-sdk:latest          # run worker (needs a reachable engine)
docker build --target linter -t neops-worker-sdk:lint .     # lint stage
docker build --target test -t neops-worker-sdk:test .       # test stage

Build stages: base (Python 3.12 + uv + deps), deps-dev (+ dev/test deps), linter (ruff + pyrefly), test (pytest), run-ci (combined results).

Project Structure

neops_worker_sdk/
  cli/                Worker entry point, job processing loop
  concurrency/        @run_in_thread, run_parallel, BlockingDetector
  connection/         3-tier device connection system
    capabilities/     Abstract capability interfaces
    plugins/          Platform-specific implementations (netmiko, napalm, scrapli, ncclient)
  function_block/     FunctionBlock ABC, result types
  logger/             Loguru-based structured logging
  registry/           FB discovery, registration decorator, global registry
  testing/            Test framework (@fb_test_case, context factories)
  workflow/           WorkflowContext, entity wrappers, DB update diffing
  worker/             Worker registration with engine

neops/fb/             Built-in function blocks (`fb.base.neops.io/*`), e.g.
                      base/global/discover_network.py. Shipped inside the image.
examples/             Example function blocks (getting-started, ping, use-cases)
docs/                 MkDocs documentation source
tests/                Test suites and topologies

Contributing

Default branch: develop. Branch from develop for all changes. Run verification before committing: uv run pytest -q && make lint && make typeCheck-baseline && make audit

See Also

  • See AGENTS.md for AI agent context, conventions, and gotchas.
  • .env.example -- environment variable reference

Metadata

Release files for neops_worker_sdk 0.2.0b6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for neops_worker_sdk 0.2.0b6
File Size Uploaded Provenance
neops_worker_sdk-0.2.0b6.tar.gz 97.7 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for neops_worker_sdk 0.2.0b6
File Interpreter ABI Platform
neops_worker_sdk-0.2.0b6-py3-none-any.whl Python 3 none any Details

Total release size: 240.7 kB

Release files / neops_worker_sdk-0.2.0b6.tar.gz

Download URL neops_worker_sdk-0.2.0b6.tar.gz
Size 97.7 kB
Tags Source
SHA-256 checksum
How to use checksums
5ec2d9c1c042bd71980dcf81dbb36021fd665eabfc3c2226f404cf7e6b582fe6
BLAKE2b-256 checksum
How to use checksums
ac286e60f66d57d4256476825504ee1909a1a53771c81153d941b76133730187
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.4 {"installer":{"name":"uv","version":"0.13.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / neops_worker_sdk-0.2.0b6-py3-none-any.whl

Download URL neops_worker_sdk-0.2.0b6-py3-none-any.whl
Size 143.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
06984bbe7292431699d9be886dcb6fba56e7a3e5cc76ab8acc0ed59121dc9f4d
BLAKE2b-256 checksum
How to use checksums
c0f7787d1958ec839959521ff77fe12d11e7d70c3f59b4f9612924349fb2082d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.4 {"installer":{"name":"uv","version":"0.13.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for neops_worker_sdk 0.2.0b6

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page