Skip to content

About

A python bridge to turn your ComfyUI instance into a grid worker.

Resources

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Latest commit

 

History

78 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Grid Media Worker

Run image, video, 3D, and managed audio generation for AI Power Grid. The current production path connects an existing ComfyUI installation. The ACE-Step audio manager is a signed-profile release candidate and is not approved on the live Grid yet.

Runtime Paths

Path Status Runtime
ComfyUI image/video/3D Current Operator-managed ComfyUI workflows
ACE-Step 1.5 audio Draft Manager-installed, pinned local API runtime
Both current paths use /v1/workers/ws for push dispatch and upload outputs
through short-lived, presigned URLs. Workers never receive Grid storage keys.

ComfyUI Worker

Requirements: Python 3.10+, a running ComfyUI instance, and a Grid API key from the developer console.

git clone https://github.com/AIPowerGrid/grid-media-worker.git
cd grid-media-worker
python -m venv .venv
source .venv/bin/activate
pip install -e .
cp .env.example .env

Set at least:

GRID_API_KEY=your-grid-api-key
GRID_WORKER_NAME=your-worker-name
GRID_API_URL=https://api.aipowergrid.io
COMFYUI_URL=http://127.0.0.1:8188

Start ComfyUI, then run:

comfy-bridge

The bridge advertises only models it can resolve and serve. GRID_MODEL can restrict that list, but it cannot make a missing workflow or checkpoint valid.

Which models can earn

Serving a model and selling it are separate gates. Paid media generation needs a configured price; GET https://api.aipowergrid.io/v1/pricing publishes those rates and their aliases. A worker advertising an unpriced model may register, but that does not make it eligible for paid demand. Unpriced image requests are rejected before dispatch with 402 "model '<name>' has no image price". Pricing does not prove availability, an enabled generation path, or earnings.

Currently priced media models: flux.2 klein 4b fp8, krea 2 turbo, and z-image-turbo for images, ltx-2.3 for video, trellis2 for 3D. These are price-book keys, not necessarily dispatch names. Pricing matches names case-insensitively, but request routing can require the exact advertised name (for example, FLUX.2 Klein 4B FP8). Use /v1/status/models for dispatch names.

Listing another model. The catalog is reviewed, not closed. Core loads curated local recipes and can separately enable verified RecipeVault sync on Base. The existence of ModelVault/RecipeVault contracts does not mean every live model is admitted through on-chain enforcement. To propose a model, contact the AI Power Grid maintainer (Discord) with the model/license, workflow, required nodes and weights, and tested hardware. The recipe, price, and generation path need review; chain-governed recipes also need their updated commitments published. Worker-side setup alone cannot make a model sellable.

Discovery: /v1/pricing lists configured rates, /v1/status/models lists what is online right now. /v1/models (the OpenAI-style list) contains text models only — image and video models never appear there. The legacy poll-based API from before the demand-billing launch is retired and answers 410 Gone; all submission goes through /v1/*.

Serving a listed model: use GRID_PREFLIGHT

For recipe-backed ComfyUI jobs, the workflow comes from the grid's reviewed recipe, pushed with the job. The bridge binds the job inputs into that graph; it does not substitute a local workflow for a supplied recipe. The right way to advertise such a model is therefore not the default local check (which needs a repo-shipped workflow file some models don't have) but preflight:

GRID_MODEL=Krea 2 Turbo
GRID_PREFLIGHT=true

On startup the bridge fetches recipes from the grid (GET /v1/models/<name>/recipe) and checks the first returned recipe's declared node types and weight files against ComfyUI. It submits that graph with a small source image where declared, then waits for completion. This consumes local GPU time; it does not necessarily reduce the graph's resolution or steps. This is a startup smoke test, not qualification of every recipe, variant, output, or billing path. Failures are logged with the missing node or file. GRID_TRUST_MODELS=true bypasses the local workflow/weight admission check when preflight is disabled; runtime health and Core admission still apply. It is not recommended for public operators.

Test your own worker end to end

Submitting a test job costs real credit: fund the account at console.aipowergrid.io, or use any daily allowance shown for your eligible account. Check current rates before submitting. Use a separate inference-capable key from the same account, not a restricted rig-only worker key. With several workers serving the same model, the Grid may route your job to someone else's GPU — pass the optional worker field, which accepts only a worker owned by your own account, to target your rig:

curl -s https://api.aipowergrid.io/v1/images/generations \
  -H "Content-Type: application/json" -H "apikey: $GRID_INFERENCE_API_KEY" \
  -d '{"model": "FLUX.2 Klein 4B FP8", "prompt": "a lighthouse at sunset",
       "n": 1, "worker": "your-worker-name"}'

Keep n at 1 for the initial test. Advanced generation paths may be disabled until their billing canaries pass; being listed or advertised does not enable them. Watch the bridge console to confirm the job landed on your worker.

Account administration belongs in the signed-in console. Inference credentials are not a substitute for an account-management session; account reads may omit linked-identity details and other API keys. A restricted rig key uses the worker self-status/setup-canary endpoints, not the account profile.

ComfyUI prerequisites

The bridge does not install or manage ComfyUI. Before starting it:

  • ComfyUI must be running and reachable at COMFYUI_URL (default port 8188).
  • Model weights go in ComfyUI's own folders: models/checkpoints/ for checkpoints, plus models/vae/, models/clip/ (text encoders), and models/loras/ where a workflow needs them. The bridge only advertises a model when every file its workflow references is present.
  • Weights are downloaded from Hugging Face (.../resolve/main/<file>) or Civitai; some repositories (the Flux family among them) are gated and need a free Hugging Face token to download.
  • Your NVIDIA driver must support the PyTorch/CUDA build used by ComfyUI. Verify a local render before connecting; installation alone is not proof of runtime compatibility.

Windows setup (PowerShell)

The commands above are for Linux/macOS shells. On Windows:

git clone https://github.com/AIPowerGrid/grid-media-worker.git
cd grid-media-worker
python -m venv .venv
.venv\Scripts\python.exe -m pip install -e .
Copy-Item .env.example .env

Notes for a fresh machine:

  • No activation or execution-policy change is needed. After configuring .env and starting ComfyUI, run .venv\Scripts\comfy-bridge.exe.
  • Missing tools install with winget: winget install --id Git.Git -e and winget install --id Python.Python.3.12 -e. Open a new terminal afterwards — already-open shells keep the old PATH and will not find git/python.
  • Use the official ComfyUI distribution and verify published checksums where provided. Do not treat an incomplete browser download as a finished archive or bypass a security warning simply to finish setup.

Custom workflows

Approved production recipes are pushed by Core with each job. For local workflow development, see workflows/README.md — it documents the API-format export, the POSITIVE_PROMPT_PLACEHOLDER / NEGATIVE_PROMPT_PLACEHOLDER contract, and the checker:

python check_connections.py workflows/your_workflow.json

Local UI

The bridge serves a status/settings page at http://127.0.0.1:7860 while running (BRIDGE_HOST/BRIDGE_PORT to change it; it binds to loopback only — use an SSH tunnel for remote access).

Capacity remains under the operator's control. Media registrations currently serve exactly one simultaneous job; GRID_THREADS must therefore remain 1. GRID_SCHEDULE accepts at most 32 JSON windows in the operator's local time. A matching window with concurrency: 0 pauses new claims and disconnects after any active job finishes; concurrency: 1 makes the worker available. Outside matching windows, the worker uses GRID_THREADS.

GRID_THREADS=1
GRID_SCHEDULE=[{"days":"mon-fri","start":"08:00","end":"18:00","concurrency":0}]

The example leaves the worker available outside weekday business hours. Values above one fail closed until Core supports multiple media claim slots for one signed worker identity.

Help Validate the Grid

Already run persistent infrastructure? AI Power Grid is recruiting two more unrelated Linux/systemd or persistent Docker operators for the initial validator cohort. The validator is CPU-only: it does not require a GPU, stake, or a worker, and preview validators have no routing, reward, strike, or slashing authority.

Each candidate must complete a 72-hour evidence window before it can qualify. Multiple nodes controlled by the same person or organization count as one independent operator, including when that operator also runs Grid workers. Start at aipowergrid.io/validate, then post only your public val_* status ID in the qualification cohort issue. Never post an API key or private key.

ACE-Step Worker Profile V1

The standalone grid-media-manager detects hardware locally, installs exact artifacts, launches the loopback-only ACE-Step API, runs an audio canary, and starts the Grid worker. Its embedded uv installs the profile's Python runtime; the pinned ACE-Step source is a hash-verified archive, so system Git is not required.

The bundled profile commits to:

  • supported OS, architecture, NVIDIA driver, VRAM, RAM, and disk tiers;
  • the ACE-Step source commit, exact managed Python 3.12.13 runtime, and uv.lock hash;
  • every model file's revision, size, and SHA-256;
  • a derived runtime digest over source, lock, model files, and recipe;
  • a pinned upstream VRAM-auto resource policy, with language-model loading forced off for this DiT-only profile;
  • a constrained DiT-only local audio request template and recipe root;
  • capabilities that remain unavailable until a signed profile passes canary.

The conservative driver gate follows NVIDIA's CUDA 12.8 toolkit floor: Linux 570.26+ or Windows 570.65+. Older 525/528 drivers can provide broad CUDA 12.x minor-version compatibility, but this profile does not claim that fallback until ACE-Step is qualified on it.

V1 forces every language-model-assisted request mode off. ACE-Step's upstream presence check nevertheless requires its default 1.7B LM files before loading the DiT, so the complete immutable 28-file runtime model tree is pinned rather than allowing an automatic runtime download. Twenty-six files come from the exact model revision; two Python model definitions come from the exact ACE-Step source commit because the runtime overlays those definitions before loading. Every file still carries an exact size and SHA-256 commitment. The tree is about 10.09 GB (9.40 GiB), while the pinned Linux dependency environment measures about 8.28 GB allocated. A complete install is therefore about 17.2 GiB before operating headroom. V1 requires 24 GiB free, keeps managed Python and the uv cache under the install root, and retains a 32 GiB recommended floor. The runtime forces Hugging Face and Transformers offline and revalidates the source and exact model tree before serving.

The checked-in profile is deliberately draft and unsigned. These commands are for development evaluation only; an unsigned profile can install and test, but cannot advertise or serve managed capabilities:

grid-media-manager --allow-unsigned-draft inspect
grid-media-manager --allow-unsigned-draft recommend
grid-media-manager --allow-unsigned-draft install
grid-media-manager --allow-unsigned-draft canary --launch-runtime

On a multi-GPU host, select the card by index or NVIDIA UUID during install; the private install state binds future canary, benchmark, and serving processes to that exact device:

grid-media-manager --allow-unsigned-draft recommend --gpu 0
grid-media-manager --allow-unsigned-draft install --gpu 0

Release qualification uses a repeatable three-run benchmark. The local report contains exact hardware diagnostics and is written with private permissions; the optional shareable report contains only profile commitments, the coarse tier, and measured performance.

The public cohort process and current hardware-class matrix are documented in docs/MANAGER_QUALIFICATION.md. Never upload a private report to GitHub; use the issue form only for the generated public report.

grid-media-manager --allow-unsigned-draft benchmark \
  --runs 3 \
  --public-out ~/.aipg/media-worker/benchmark-public.json

For release evidence, use a separate state and report name on each selected GPU. The install root may be shared: verified artifacts resume instead of being downloaded again.

CLASS=midrange
GPU=GPU-REPLACE-WITH-NVIDIA-UUID
ROOT="$HOME/.aipg/media-worker"

grid-media-manager --allow-unsigned-draft install \
  --install-root "$ROOT" \
  --state "$ROOT/state-$CLASS.json" \
  --gpu "$GPU"
grid-media-manager --allow-unsigned-draft benchmark \
  --install-root "$ROOT" \
  --state "$ROOT/state-$CLASS.json" \
  --runs 3 \
  --out "$ROOT/$CLASS-private.json" \
  --public-out "$ROOT/$CLASS-public.json"

Use CLASS=minimum, midrange, or datacenter only for the matching release machine. The offline signer recomputes the class from the private report and rejects labels that do not match the selected GPU and profile recommendation.

Private operator pilot

A Grid-operated pilot does not need to claim support for hardware that has not been tested. Derive a separate unsigned pilot draft, qualify it on the one exact machine, and sign only that profile. Core must allowlist its final digest. Pilot profiles are never accepted by the public manager-v* release workflow, and an omitted RecipeVault root is represented honestly as null rather than claimed without an on-chain registration.

python profile_pilot.py \
  --profile bridge/profiles/ace-step-v1.profile.json \
  --hardware-class midrange \
  --out /offline/ace-step-midrange-pilot.draft.json

grid-media-manager \
  --profile /offline/ace-step-midrange-pilot.draft.json \
  --allow-unsigned-draft install \
  --install-root "$HOME/.aipg/media-worker" \
  --state "$HOME/.aipg/media-worker/state-pilot.json" \
  --gpu GPU-REPLACE-WITH-NVIDIA-UUID
grid-media-manager \
  --profile /offline/ace-step-midrange-pilot.draft.json \
  --allow-unsigned-draft benchmark \
  --install-root "$HOME/.aipg/media-worker" \
  --state "$HOME/.aipg/media-worker/state-pilot.json" \
  --runs 3 \
  --out /offline/midrange-pilot-private.json

python profile_release.py \
  --profile /offline/ace-step-midrange-pilot.draft.json \
  --private-key /offline/worker-profile-pilot.pem \
  --ask-pass \
  --key-id worker-profile-pilot-2026-01 \
  --qualification midrange=/offline/midrange-pilot-private.json \
  --out /offline/ace-step-midrange-pilot.active.json

The pilot remains fail-closed: it is signed, locally canary-validated, bound to the selected GPU and pinned runtime, identity-delegated, and accepted only when its exact profile digest is present in Core's operator-managed allowlist.

Public manager profile

After all three hardware classes pass and the hardware-wallet RecipeVault transaction is confirmed, use the separate offline signer. It is intentionally not bundled into the manager:

openssl genpkey -algorithm ED25519 -aes-256-cbc \
  -out /offline/worker-profile-release.pem
chmod 600 /offline/worker-profile-release.pem
python profile_release.py \
  --profile bridge/profiles/ace-step-v1.profile.json \
  --private-key /offline/worker-profile-release.pem \
  --ask-pass \
  --key-id worker-profile-2026-01 \
  --qualification minimum=/offline/reports/minimum-private.json \
  --qualification midrange=/offline/reports/midrange-private.json \
  --qualification datacenter=/offline/reports/datacenter-private.json \
  --recipe-vault-root 0xRECIPE_ROOT \
  --out /offline/ace-step-v1.active.json

The signer recomputes every private report against the draft policy, requires three successful runs on distinct minimum, midrange, and datacenter hardware, and writes a privacy-safe .qualification.json sidecar. Only the canonical sidecar hash is embedded in the signed profile; GPU names, UUIDs, RAM, and disk inventory remain offline.

Review the emitted public key and profile digest before adding only that public key to trusted-keys.json. Never place the release private key in this repo, a CI secret, the manager bundle, or a worker host.

An active release will use the same commands without --allow-unsigned-draft. The primary operator path is one command:

grid-media-manager

With no arguments, the executable opens the local Worker Manager at http://127.0.0.1:8791. The UI shows release verification, the selected GPU, install and canary state, payout-wallet delegation, and redacted process logs. Its setup button runs the same fail-closed CLI lifecycle described below; the UI cannot enable an unsigned profile or advertise a capability before validation. It uses a one-time local browser session, requires exact same-origin JSON for controls, and rejects non-loopback binds. Once a signed enrolled worker is online, Run Grid test asks Core to route one governed audio, image, or video canary to that exact rig. This is separate from the local profile canary and has no charge, den, payout, strike, validator-evidence, or quality effect; the rig credential stays server-side.

The equivalent terminal command is:

grid-media-manager setup

setup recommends and binds one GPU, resumes verified installation with throttled download progress on stderr, launches ACE-Step, benchmarks the canary, opens wallet pairing, and then enters the Grid worker loop. With no --worker-name, it derives a stable unique name from the funds-less rig signer. On a multi-GPU machine, pass --gpu 0 or a displayed NVIDIA UUID; otherwise the manager selects the supported card with the most VRAM. --exit-after-setup performs every step except entering the long-running worker loop.

The separate inspect, recommend, install, canary, benchmark, connect, and serve commands remain available for qualification, diagnostics, and recovery.

Worker Identity

Each rig uses a funds-less secp256k1 worker key. The payout wallet signs a time-bounded delegation to that key; the payout private key never belongs on the worker host. Core resolves the actual payout wallet from the API-key account, verifies the wallet delegation, consumes a one-use registration nonce, and then accepts job receipts from the delegated signer.

The primary setup command performs pairing automatically. To pair or rotate a rig separately without copying keys or signatures:

grid-media-manager connect --worker-name my-audio-rig

The manager creates its worker signer and final worker-only API credential locally, opens a short-lived Console link, and waits. Sign in with Google or a wallet, connect the payout wallet, review the rig identity, and sign the exact delegation message. Core stores only the API-key hash and grants only worker.connect; it cannot return the plaintext credential to the browser. Rerun connect with --restart to rotate a rig connection. Core activates the new credential only after the manager verifies and ACKs it, then revokes the prior credential for that account and rig name.

The manual identity commands below are the offline/recovery path:

grid-media-manager identity generate
grid-media-manager identity request --payout-wallet 0xYOUR_WALLET
grid-media-manager identity install \
  --request ~/.aipg/media-worker/delegation-request.json \
  --signature 0xWALLET_SIGNATURE
grid-media-manager identity show

Never paste a payout-wallet private key into this manager. The payout wallet signs in its own wallet UI and remains separate from the funds-less rig key.

Security Boundaries

  • Managed ACE-Step accepts only a loopback runtime URL; hosted generation is rejected.
  • The ACE-Step subprocess receives a narrow environment without Grid or cloud credentials. It still runs as the operator's OS user; signed profiles authorize pinned code and artifacts, but do not provide an OS/container sandbox.
  • Artifact paths are contained and downloads are size/hash verified before promotion.
  • Multi-GPU recommendations are bound by NVIDIA UUID to the runtime process; an inherited CUDA_VISIBLE_DEVICES cannot silently select another card.
  • Profile signatures protect release policy for honest operators; they are not proof that an adversarial worker executed the claimed model.
  • Media output hashes are signed provenance receipts, not fidelity proofs. Validators must fetch/sample/re-execute outputs before quality evidence affects economics.
  • Core audio charging remains dark until real hardware benchmarks set the price peg.

Development

pip install -e '.[test]'
pytest -q

Build and smoke-test the standalone manager:

uv sync --frozen --extra test --extra release
uv run --frozen --extra release pyinstaller --clean --noconfirm grid-media-manager.spec
./dist/grid-media-manager --help
./dist/grid-media-manager --allow-unsigned-draft inspect

The V1 release workflow builds Linux x86_64 and Windows x86_64 artifacts with checksums and GitHub provenance attestations, matching the NVIDIA profile. Linux V1 requires Ubuntu 22.04 or another x86_64 distribution with glibc 2.35 or newer. The runtime bundle excludes Tk and the offline profile-signing and qualification tools. A manager-v* tag can assemble only a draft release, and it fails unless the bundled profile is active, signature-verified, RecipeVault-bound, and qualified on the required hardware classes. The draft includes manager-release.json so aipowergrid.io/run can eventually consume one reviewed platform/download contract. The manifest records Windows signing state so the public download surface can expose verified Linux independently while keeping Windows closed until Authenticode is verified. Publishing the draft still requires supervised staging and review of the shared profile, qualification, RecipeVault, integrity, SBOM, and provenance gates. Apple/MPS needs its own measured profile rather than inheriting NVIDIA assumptions. GitHub immutable releases are enabled: once a qualified draft is published, its tag and assets cannot be replaced. Any correction must be a new version.

Before the active profile exists, maintainers may publish a separately named manager-qualification-v* prerelease. That binary carries the same pinned draft used by source qualification and is limited to local inspection, installation, canary, and benchmark work. The CLI refuses Grid enrollment, and the unsigned profile cannot advertise worker capabilities even after a passing canary. Qualification releases include their own manifest, SHA-256 checksums, SPDX SBOM, and GitHub build provenance; they must never be presented as a media worker download.

License

AGPL-3.0-or-later. See LICENSE.

About

A python bridge to turn your ComfyUI instance into a grid worker.

Resources

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages