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 to wait for running job on shutdown |
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.1.0b7
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| neops_worker_sdk-0.1.0b7.tar.gz | 108.5 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| neops_worker_sdk-0.1.0b7-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 268.1 kB
Release files / neops_worker_sdk-0.1.0b7.tar.gz
| Download URL | neops_worker_sdk-0.1.0b7.tar.gz |
|---|---|
| Size | 108.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3f0605806f957400544834ff2a40d7246e2b03132de91b87036480a0a79ec1d5
|
|
BLAKE2b-256 checksum How to use checksums |
36327fc91a8a3f9aae58cf6f04d94cbbd64096ecffdcd5f3a14ebda199b3a538
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.21 {"installer":{"name":"uv","version":"0.12.21","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.1.0b7-py3-none-any.whl
| Download URL | neops_worker_sdk-0.1.0b7-py3-none-any.whl |
|---|---|
| Size | 159.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
deeb0dfd6a47f249fcf4fc793f23855f3c84bdc402516e7d0542ecf1c2df8a0b
|
|
BLAKE2b-256 checksum How to use checksums |
98d9e5c412230784f9712f79b3fd8d57f37a31d2727c1ebc1fa58a7971c45ce7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.21 {"installer":{"name":"uv","version":"0.12.21","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.1.0b7
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.