Skip to main content

FlashNode

The open host agent of the FlashML system. Install FlashNode on a machine you own, and it can safely execute distributed ML tasks for the FlashML network — earning contribution credits for verified useful work.

FlashNode is one of three components in the FlashML system by Zolli Labs:

  • flashnode (this repo) — open host agent installed by resource contributors. Because it runs on someone else's machine and executes third-party workloads, it must be inspectable, minimal, and explicit about permissions — which is why it is open source.
  • flashruntime — the open workload protocol and execution layer.
  • flashml-cloud (private) — the managed control plane and dashboard.

Read docs/SYSTEM_OVERVIEW.md for the full product architecture, and AGENTS.md if you are an AI coding agent working in this repo.

Status

Pre-release; the device executor works today (July 2026). A machine with this agent can join a FlashRuntime coordinator over outbound HTTP, pull leased tasks, execute them, relay training checkpoints, and commit verified results. Two profiles:

  • Device profile (flashnode work) — the pull-based executor for laptops/workstations. Implemented.
  • Kubernetes profile (flashnode agent) — per-node telemetry reporter inside managed pools (DaemonSet); KubeRay owns workload pods there. Implemented.

What it does today

pip install -e .                      # plus: pip install -e ../flashruntime
flashnode work --coordinator http://<coordinator>:8100
# optional hardening / pool config:
#   FLASHNODE_JOIN_CODE=...          join-code-gated pools
#   --runner docker + FLASHNODE_ALLOWED_IMAGES=img:tag,...   container tier
#   FLASHNODE_WORKDIR=$HOME/.cache/flashnode   (macOS + colima: VM-visible workdirs)
#   FLASHNODE_WORKDIR=C:\Users\<you>\.flashnode  (Windows: must be under a
#                                                 directory Docker Desktop shares)
#   FLASHNODE_LOCAL_DATA=patients=/srv/data/patients-2026,labs=/srv/labs
#                                    lend local directories to tasks by LABEL

FLASHNODE_LOCAL_DATA lets you offer data without uploading it. Only the label names (patients, labs) are advertised to the coordinator — never the paths — and a task that names a label in its local_inputs gets that directory bind-mounted read-only at /work/inputs/<label>. A task asking for a label this machine does not lend is refused, not run half-fed; a task that asks for nothing sees nothing, exactly as before.

If the coordinator enforces per-machine authentication (FLASHML_NODE_TOKENS set server-side), save the bearer token you were given before running work:

flashnode login --coordinator http://<coordinator>:8100 --token <token>
flashnode work --coordinator http://<coordinator>:8100   # reads the saved token automatically
flashnode logout --coordinator http://<coordinator>:8100 # forget it locally (does not revoke server-side)

login/logout write to a per-coordinator credential store at ~/.flashnode/credentials.json (override with FLASHNODE_CREDENTIALS), keyed by coordinator URL so one machine can hold separate tokens for separate pools. The file is written with mode 0600 on every save. A missing or unparseable file is treated as "no saved token" rather than a crash. CoordinatorClient sends the saved token as a bearer header on every request to that coordinator once it's saved — there is nothing else to configure. Token issuance is still manual and out-of-band today (the coordinator operator hands you the token; there is no self-service signup or browser device flow yet), and flashnode logout only removes the local copy — the operator revokes access by removing your token from the coordinator's configuration.

  • Stable node identity; registers with capabilities (CPU, RAM, arch, GPU) and re-registers automatically if the coordinator restarts.
  • Outbound-only HTTP — no inbound ports, no router configuration.
  • Claims task leases, renews them with attempt heartbeats, and stops work the moment a lease is refused (the coordinator's idempotent commit rejects late duplicates regardless — defense in depth).
  • Two execution tiers behind one interface: SubprocessRunner (allowlisted Python modules, wall-clock timeout, scrubbed environment — agent secrets never reach task code) and DockerRunner (allowlisted images, --network none, cpu/memory limits, read-only rootfs, uid mapping).
  • Downloads shared input artifacts; uploads outputs with sha256 for the coordinator's commit-time validation.
  • Checkpoint courier: tasks stay network-isolated, so the agent fetches the task's latest valid checkpoint before a run (resume) and ships each new checkpoint file during it — a task killed on this machine resumes from its checkpoint on another.

Still to come: Ed25519-signed identity, admission benchmarks (benchmark/), richer telemetry (telemetry/), gVisor/Kata isolation tiers, and the join/status/leave UX.

Security contract

  • Outbound-only control connection; no inbound SSH or public ports.
  • Signed node identity; short-lived session credentials.
  • Allowlisted or signed workload images only.
  • Non-root execution; no host Docker socket, device passthrough, or privileged mode.
  • The agent shows exactly which limits and permissions apply to a workload before executing it.
  • Complete event logging of task assignment, image digest, permissions, and artifact commits.

Supported host class (initial): x86-64 Linux, macOS (Docker Desktop or Colima), or Windows (Docker Desktop with the WSL2 backend), Python 3.10+, ≥4 CPU cores, ≥8 GB RAM, stable outbound internet.

Windows note: flashnode work used to crash immediately on Windows (os.getuid/os.getgid don't exist there). It now omits --user on Windows instead, relying on the curated images' own non-root USER declaration for non-root execution — see docs/guides/donate-a-machine.md in flashruntime for the full picture, including honest caveats: Windows support is constructed-argv-verified (tests fake the platform), not yet execution-verified against a real Windows machine.

Package layout

Working today:

flashnode/
├── agent/       # CLI (`work`, `agent`), K8s-profile daemon, kube helper
├── identity/    # stable node ID (Ed25519 signing: planned); credentials.py
│                #   is the per-coordinator bearer-token store behind
│                #   `flashnode login`/`logout`
├── inventory/   # capability discovery (psutil + K8s allocatable)
└── executor/    # the device work cycle:
    ├── client.py         # stdlib outbound HTTP: leases, artifacts, checkpoints
    ├── runner.py         # Tier 1: allowlisted subprocess, scrubbed env
    ├── docker_runner.py  # Tier 2: allowlisted containers, network-none
    └── loop.py           # claim → run (heartbeating) → relay ckpts → commit

Scaffolds awaiting their vertical slice: benchmark/ (admission probes), telemetry/ (rich metrics), artifacts/ (local caching), config/ (host-owner policy).

License

Apache-2.0. Contributions via Developer Certificate of Origin (git commit -s).

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

flashnode-0.3.0.tar.gz (85.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

flashnode-0.3.0-py3-none-any.whl (62.0 kB view details)

Uploaded Python 3

File details

Details for the file flashnode-0.3.0.tar.gz.

File metadata

  • Download URL: flashnode-0.3.0.tar.gz
  • Upload date:
  • Size: 85.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for flashnode-0.3.0.tar.gz
Algorithm Hash digest
SHA256 1b3e7a2510fafa4fa6b207784b98e2ca9cedad500d2e55f6936b79c56d0246db
MD5 37b8ffc2f866b3ef45bad65eff346251
BLAKE2b-256 af072349cfbe318fa1619c4b67d5de347127426ecc297b4d76823632418e9748

See more details on using hashes here.

Provenance

The following attestation bundles were made for flashnode-0.3.0.tar.gz:

Publisher: release-flashnode.yml on Zolli-Labs/flashml

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file flashnode-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: flashnode-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 62.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for flashnode-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4486e76490dfea7e9dc1d562a0b19a31e38f696907ce7ae3ac62b9e896120f68
MD5 2a954f09deaacda7860ba4689544d376
BLAKE2b-256 a815f23237e3b0dcf4006e7800655e2d17e098f6c1163a1836b19963e2abc486

See more details on using hashes here.

Provenance

The following attestation bundles were made for flashnode-0.3.0-py3-none-any.whl:

Publisher: release-flashnode.yml on Zolli-Labs/flashml

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page