HECATE

A swarm of AIs that grows when you add hardware.

Control plane in Rust and Tokio, data plane in Python and PyTorch, contract in Protobuf. Local models hand over what they learn without handing over the data.

  • v1.3.0
  • MIT
  • Rust 1.88+
  • Python 3.10+

View the repository Read the documentation

The state of the repository

  • 563 Rust tests
  • 193 Python tests
  • 21 verification steps
  • 57 documents under docs/
  • v1.3.0 in development

What it is

HECATE is not a pipeline. A pipeline is a single model running in a chain: when one node dies the service stops, when you add hardware nothing happens, and when a laptop learns something it stays on the laptop.

HECATE is a swarm. Several complete copies of the model run side by side, the topology grows while it runs, and every node can hand over what it learned as an adapter. Three pillars carry that.

Pillar A

A multi-model swarm with redundancy

With enough nodes the scheduler instantiates several concurrent pipelines out of replicated fragments. The redundancy map stops being a safety net and becomes the deployment map: the same layer lives on several nodes and feeds several pipelines at once.

Up to 100 nodes deploy 10 complete copies of the model: ten replicas per layer, ten times the service capacity, and the loss of any node has a replacement.

Pillar B

Growth by adding hardware

A new node does not restart the cluster. The scheduler runs an expansion protocol and decides whether that node becomes a replica of a fragment, extends the model with new layers, or joins as an expert bringing its own model.

The extension score follows the FSENNL frame: it combines the device profile (VRAM, RAM, NPU, latency) to decide where to expand.

Pillar C

Telomerase: the learning without the data

Every node can run a local model on its own. Telomerase lets it hand a neural payload to the swarm: a LoRA adapter trained on its local data, which the swarm merges by federated averaging and returns applied.

The node keeps its adapter and stays autonomous. The swarm takes in a merged copy. The local data never leaves the node.

Architecture

Two planes and one contract. The split is explicit: if something needs to know who runs what, it lives in Rust. If something needs to know how large a tensor is, it lives in Python.

Control plane, data plane and contract
Module Plane Responsibility
Control plane · Rust + Tokio
mesh-proto Rust Contract and activations. Generates the stubs from the .proto and validates activations before sending them.
mesh-scheduler Rust Assignment, capacity and growth. Node profile, plan_swarm with N pipelines, growth_decision and apply_growth. Pure and deterministic.
mesh-router Rust Cost and failover by replica. route_request per model, failover_in_swarm and the degraded route.
mesh-discovery Rust Registry and mDNS discovery. Announces capabilities and telomerase, and keeps the node registry.
mesh-worker-net Rust Transport and peer pool. Message framing, connection pool and gRPC clients. Never runs a fragment.
mesh-orchestrator Rust Lifecycle and telomerase. Swarm state, telemetry, growth application and the adapter merge round.
mesh-profiler Rust Hardware profiling. Detects the hardware, benchmarks it and returns a node capability profile with a tier. Nothing is assumed: a field that cannot be measured stays at zero, marked absent, and a declared figure is marked declared.
hecate-node Rust Command line: serve, orchestrate, plan, swarm, swarm-sim, swarm-live, fine, moe, profile, zoo, guard, probe and bench.
Data plane · Python + PyTorch
ncm_tokenizer Python Residual vector quantizer: turns frames into discrete codes and rebuilds them by adding centroids.
ncm_transformer Python The model fragment in PyTorch: RMS norm, causal attention with SDPA and SwiGLU activations over a frozen substrate.
telomerase Python LoRA adapter, federated merge weighted by sample count, and the gRPC service for extract, merge and apply.
dataplane Python gRPC server of the data plane: describe, health, forward and profile.
Contract
proto/hecate.proto Contract Single source of truth. The Rust and Python stubs are generated from it, and verification fails if they drift.
f32 little-endian Format 32-bit floats in little-endian order, no header and no padding: the same bytes Rust writes and the same bytes Python writes. The adapter payload reuses that codec.

Swarm lab

A swarm of nodes and the pipelines that cover them. Add a node and the plan is recomputed; kill one and the route is re-spliced.

Idle: the swarm is stopped. Press “Start swarm”.

12 layers in the model chain

An illustration of the routing model, not a benchmark: latency and throughput are measured with hecate-node bench and published in the methodology notes.

How a new node joins the swarm A model chain of layers is served by three nodes. Each newcomer joins with a different growth action: a replica of a layer, new layers at the end of the chain, or a second model joining as an expert. ncm-vision ncm-base ×2 gpu mini laptop old-tablet beast seer
  1. Step 1

    Replicate

    −2.0 FSENNL score 2 replicas of the first layer

    old-tablet · 0 GB VRAM · 60 ms

    The node cannot hold a new segment, but it can hold a replica. The redundancy map gains a holder for the first layer and the risk of a failed failover drops.

  2. Step 2

    ExtendDepth

    20.9 FSENNL score 3 new layers on the base chain

    beast · 20 GB VRAM · 14 TOPS

    There is capacity to make the model longer. New layers are added at the end of the chain, on a frozen substrate, and the plan is validated before anything is deployed.

  3. Step 3

    AddExpert

    49.9 FSENNL score 4 expert layers on the second chain

    seer · 16 GB VRAM · telomerase and a local model

    The node brings its own model rather than more of the same one. It joins as an expert on a second chain, and the router keeps the two models apart.

Try it

The literal commands from the repository. They need Rust 1.88 or later and Python 3.10 or later, with the data plane dependencies installed.

Build the release binary

cargo build --release -p hecate_node

Plan, simulate, connect and measure

./target/release/hecate-node swarm --topology examples/swarm.json
./target/release/hecate-node swarm-sim --topology examples/swarm.json --kill gpu --pipelines 2
./target/release/hecate-node swarm-live --topology examples/swarm-live.json --merge
./target/release/hecate-node bench --mock

The simulation returns every step and the state of the swarm after it. The live mode discovers profiles, integrates the new node and runs one telomerase round: it collects from every node, merges and hands the result back.

Start the data plane in Python

python -m hecate.dataplane \
  --node-id ncm-a --listen 127.0.0.1:50251 \
  --layers 0-5 --model ncm-base \
  --telomerase --adapter-rank 4 \
  --vram-gb 6 --ram-gb 32 --npu-tops 2 --latency-ms 2 \
  --local-model ncm-base

The node announces its profile and exposes extract, merge and apply on the same port as the inference.

Local verification

The repository does not use cloud CI: there is no .github/workflows/, no CircleCI, no GitLab CI and no Travis. Quality is guaranteed on the machine of whoever writes the code, with two entry points that live in the repository itself.

Lint and test

just check

Lint is cargo fmt --all -- --check, cargo clippy --workspace --all-targets -- -D warnings, ruff check, ruff format --check and mypy. Test is cargo test --workspace and pytest -q.

Full verification

./scripts/verify.sh

Every section, in order, aborting at the first failure: ruff check, ruff format --check, mypy, pytest, the Protobuf stub parity, the quantization parity, cargo fmt --check, cargo clippy, cargo test, cargo build --release, the release-only bench check, the version alignment against Cargo.toml, the scaffolding policy, llms.txt and the documentation check. It exits 0 when everything passes and 1 when anything fails. With SKIP_RUST=1 the Rust toolchain is left out and 15 sections remain.

What the two entry points measure today:

  1. 563 Rust tests cargo test --workspace runs the control plane suite: unit, integration and documentation tests.
  2. 193 Python tests pytest -q runs the data plane suite, the telomerase and the model zoo.
  3. 70 % coverage floor pytest --cov fails below that floor, and it moves with COVERAGE_MIN. The measured percentage is not printed here on purpose: it changes with every test and cannot be re-derived in the same step as the other figures, so it would be the first number to drift.

The COVERAGE_MIN, SKIP_RUST, PYTHON and CARGO variables adjust the behaviour. The pre-push hook runs the verification and aborts the git push if anything fails.

In a hybrid architecture, verifying only half of it would be a mirage: the network loop, the swarm scheduler and the growth protocol are in Rust, and the tensors are in Python. Verifying only Python would leave the most critical code without a network.

Documentation

The documents live under docs/ in the repository. They are not reproduced here: they are linked. These are the ones that answer a question you are likely to have.

Architecture and ownership

  • architecture.mdwhat lives in Rust, what lives in Python, where the frontier is and what each layer guarantees
  • scm.mdwhere each crate lives, what guarantee it gives and how one is promoted into core
  • hosting.mdthe organization as the canonical owner, and what happened to the old account

Routing and growth

  • routing.mdcost-aware routing: the cost model, the shortest path and failover
  • swarm-routing.mdselection by model, load spread between copies and failover by redundancy
  • redundancy.mdcapacity score, layer assignment and head replication
  • growth-protocol.mdthe FSENNL score and the three growth actions

The model and the adapter

  • ncm.mdthe model, the residual vector quantizer and the transformer fragments
  • telomerase.mdLoRA, federated merging and the gRPC service
  • data-architecture/model-zoo.mdadapted variants and device-aware selection, over the catalog both planes read

Measuring and verifying

Honest limitations

What the design does not solve, without dressing it up.

  • Growth in intelligence is gradual, not instant.

    Merging an adapter improves behaviour in the direction of the local data; it does not turn a small model into a large one. It takes many rounds and representative data.

  • Averaging can make a node worse.

    Federated averaging does not guarantee that every node improves: two nodes with opposite distributions produce a midpoint that can be worse than both ends. Fixing it needs loss weighting or adapter clustering, and neither is implemented.

  • Network latency is still the physical limit.

    Every hop adds milliseconds; over WiFi the queue explodes. Ethernet is a requirement, not a recommendation.

  • Heterogeneity demands accurate profiles.

    A misreported video memory makes the scheduler place a segment that does not fit. A profile can be faked and the system does not verify it.