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.
| 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. |
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 .envSet 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:8188Start ComfyUI, then run:
comfy-bridgeThe 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.
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/*.
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=trueOn 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.
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.
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, plusmodels/vae/,models/clip/(text encoders), andmodels/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.
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 .envNotes for a fresh machine:
- No activation or execution-policy change is needed. After configuring
.envand starting ComfyUI, run.venv\Scripts\comfy-bridge.exe. - Missing tools install with winget:
winget install --id Git.Git -eandwinget install --id Python.Python.3.12 -e. Open a new terminal afterwards — already-open shells keep the oldPATHand will not findgit/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.
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.jsonThe 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.
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.
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.lockhash; - 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-runtimeOn 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 0Release 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.jsonFor 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.
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.jsonThe 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.
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.jsonThe 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-managerWith 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 setupsetup 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.
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-rigThe 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 showNever 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.
- 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_DEVICEScannot 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.
pip install -e '.[test]'
pytest -qBuild 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 inspectThe 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.
AGPL-3.0-or-later. See LICENSE.