8.4 KiB
ComfyUI-Distributed API (Experimental)
This document describes the public HTTP API added to ComfyUI-Distributed to allow queueing distributed workflows from external tools (scripts, services, CI jobs, render farms, etc.) without using the ComfyUI web UI.
Demo
- Video walkthrough: https://youtu.be/yiQlPd0MzLk
Examples Repository
Overview
What this adds
POST /distributed/queue— queues a workflow using the same distributed orchestration rules as the UI:- Detects distributed nodes in the prompt (
DistributedCollector,UltimateSDUpscaleDistributed). - Resolves enabled/selected workers.
- Probes and dispatches workers through
/distributed/worker_wsby default. - If
settings.websocket_orchestration=false, probes withGET /promptand dispatches withPOST /promptinstead. - Queues the master workflow in ComfyUI’s prompt queue.
- If any
DistributedCollectorhasload_balance=true, selects one least-busy participant for this run.
- Detects distributed nodes in the prompt (
What it does not add
- Authentication/authorization.
- A separate “job status” API for distributed results (you still use ComfyUI’s normal prompt history / websocket flow, and the existing
/distributed/queue_status/{job_id}behavior for collector queues).
Endpoint: POST /distributed/queue
Queue a workflow for distributed execution.
URL
http://<master-host>:<master-port>/distributed/queue
Headers
Content-Type: application/json
Request Body
{
"prompt": { "<node_id>": { "class_type": "...", "inputs": { } } },
"workflow": { },
"client_id": "external-client",
"delegate_master": false,
"enabled_worker_ids": ["1", "2"],
"workers": ["1", "2"],
"auto_prepare": true,
"trace_execution_id": "exec_1700000000_ab12cd"
}
Fields
prompt(required unlessworkflow.promptis present, object)- A complete ComfyUI API-format prompt graph, using the same shape as
POST /prompt. - This is not the normal visual workflow export from the ComfyUI editor.
- A complete ComfyUI API-format prompt graph, using the same shape as
workflow(optional, object)- Workflow metadata that ComfyUI normally stores in
extra_pnginfo.workflow. - If you don’t care about UI metadata, you can omit it.
- Workflow metadata that ComfyUI normally stores in
client_id(required, string)- Passed through as
extra_data.client_id(useful if you consume ComfyUI websocket events).
- Passed through as
delegate_master(optional, boolean)- If
true, attempts “workers-only” execution for workflows based onDistributedCollector. - Current limitation: delegate-only mode does not support
UltimateSDUpscaleDistributedand will fall back to running the full prompt on master.
- If
enabled_worker_ids(required, array of strings)- The explicit worker IDs to consider for this run.
workers(optional, array of strings or objects withid)- Transitional alias for
enabled_worker_idsused by older clients.
- Transitional alias for
auto_prepare(optional, boolean)- Kept for wire compatibility.
- Backend orchestration always runs with auto-prepare semantics.
- If top-level
promptis omitted, backend will attemptworkflow.prompt.
trace_execution_id(optional, string)- Passed through to orchestration logs.
- Server log lines include the marker as
[exec:<trace_execution_id>].
How to get enabled_worker_ids
Worker IDs come from the plugin config (GET /distributed/config) under workers[].id.
Example (bash + jq):
curl -s "http://127.0.0.1:8188/distributed/config" \
| jq -r '.workers[] | "id=\(.id)\tname=\(.name)\tenabled=\(.enabled)\thost=\(.host)\tport=\(.port)\ttype=\(.type)"'
Example (PowerShell):
$cfg = Invoke-RestMethod "http://127.0.0.1:8188/distributed/config"
$cfg.workers | Select-Object id,name,enabled,host,port,type | Format-Table -AutoSize
Response Body
{
"prompt_id": "<uuid>",
"worker_count": 2,
"auto_prepare_supported": true
}
prompt_id— the master prompt id queued into ComfyUI.worker_count— number of workers that received a dispatched prompt (only those that passed the health check).
Status Codes
200— queued.400— invalid JSON or invalid body.500— orchestration/dispatch failure (see server logs for details).
Worker requirements (important)
For a worker to participate, it must be reachable from the master. By default:
- WebSocket probe and dispatch:
<worker-base>/distributed/worker_wsmust accept the connection.
If settings.websocket_orchestration=false:
- Health check:
GET <worker-base>/promptmust return HTTP 200. - Dispatch:
POST <worker-base>/promptmust accept the prompt.
Also, for collector-based flows:
- Workers will send results back to the master via
POST /distributed/job_complete(that route must be reachable from workers).
Endpoint: POST /distributed/job_complete
Submit one completed worker image back to the master collector queue.
URL
http://<master-host>:<master-port>/distributed/job_complete
Request Body
{
"job_id": "exec_1234567890_17",
"worker_id": "worker-1",
"batch_idx": 0,
"image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...",
"is_last": false
}
Canonical envelope (required fields)
job_id(string, required)worker_id(string, required)batch_idx(integer >= 0, required)image(string, required)- PNG payload as either:
- data URL:
data:image/png;base64,... - raw base64 PNG bytes
- data URL:
- PNG payload as either:
is_last(boolean, required)
Legacy multipart/tensor payload formats are no longer accepted on this endpoint.
CORS note
If you call the API from a browser (not from a backend), ensure the master ComfyUI is started with --enable-cors-header.
Log Endpoints
GET /distributed/worker_log/{worker_id}
Read log files for workers launched locally by the master UI process manager.
- Intended for managed local workers.
- Query param:
lines(optional, default1000).
GET /distributed/local_log
Read this ComfyUI instance's in-memory runtime log buffer.
- Available on any ComfyUI-Distributed instance (master or worker).
- Query param:
lines(optional, default300, max3000).
GET /distributed/remote_worker_log/{worker_id}
Proxy endpoint on master that fetches logs from a configured remote/cloud worker's
/distributed/local_log.
- Intended for remote/cloud workers in master config.
- Query param:
lines(optional, default300, max3000).
Examples
1) Minimal curl request envelope
curl -X POST "http://127.0.0.1:8188/distributed/queue" \
-H "Content-Type: application/json" \
-d @payload.json
payload.json must contain a complete ComfyUI API-format prompt. The abbreviated envelope below illustrates the request shape but is not directly executable:
{
"prompt": {
"<node_id>": {
"class_type": "<node class>",
"inputs": {"<required_input>": "<value or connection>"}
}
},
"enabled_worker_ids": [],
"client_id": "external-client"
}
Export or construct a valid API-format prompt with all required node inputs and at least one output node before submitting it.
2) Python (requests)
import requests
url = "http://127.0.0.1:8188/distributed/queue"
payload = {
"prompt": {...},
"workflow": {...},
"client_id": "external-client",
"delegate_master": False,
"enabled_worker_ids": ["1", "2"],
}
r = requests.post(url, json=payload, timeout=60)
r.raise_for_status()
print(r.json())
3) JavaScript (fetch)
const url = "http://127.0.0.1:8188/distributed/queue";
const payload = {
prompt: {/* ... */},
workflow: {/* ... */},
client_id: "external-client",
delegate_master: false,
enabled_worker_ids: ["1", "2"],
};
const resp = await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload),
});
if (!resp.ok) throw new Error(await resp.text());
console.log(await resp.json());
Operational notes / gotchas
- If the workflow contains no distributed nodes, the endpoint falls back to normal master queueing and returns
worker_count: 0. - Worker selection is “best-effort”: offline workers are skipped.
- For public URLs/tunnels: prefer configuring
master.hostwith an explicit scheme (https://...) to avoid ambiguity.
Changelog (this feature)
- Added
POST /distributed/queueendpoint. - Added orchestration module used by the endpoint.