Skip to content

comfy-api-runner is a lightweight, headless runner for submitting ComfyUI workflows via API and executing them on local servers.

License

Notifications You must be signed in to change notification settings

SagiPolaczek/comfy-api-runner

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

comfy-api-runner banner

Comfy-API-Runner

Lightweight, headless runner for submitting ComfyUI workflows via API.

Features:

  • Zero external dependencies (stdlib only)
  • Clean workflow submission with fluent API
  • Multi-GPU round-robin distribution
  • Simple result handling

📦 Installation

# Clone the repo
git clone https://github.com/SagiPolaczek/comfy-api-runner.git
cd comfy-api-runner

# Or install in development mode
pip install -e .

🚀 Quick Start

Single Submission

from comfy_runner import ComfyClient, Workflow

# Load and modify workflow
wf = Workflow.load("my_workflow.json")
wf.set_node("32", "image", "/path/to/image.png")
wf.set_node("28", "text", "my prompt")
wf.set_node("29", "filename_prefix", "outputs/run_001")

# Submit
client = ComfyClient(port=5892)
result = client.queue(wf)
print(f"Queued: {result['prompt_id']}")

Batch Submission (Multi-GPU)

from comfy_runner import Workflow, BatchRunner

# Define node mappings once
NODES = {
    "input_image": "32",
    "prompt": "28",
    "output": "29",
}

# Setup
runner = BatchRunner(ports=[5892, 5893, 5894, 5895])
workflow = Workflow.load("my_workflow.json")

# Generate and queue jobs
for params in my_params:
    job = (workflow.copy()
        .set_node(NODES["input_image"], "image", params.image)
        .set_node(NODES["prompt"], "text", params.prompt)
        .set_node(NODES["output"], "filename_prefix", f"out/{params.name}"))
    
    runner.queue(job)

print(runner.summary())

📖 API Reference

ComfyClient

client = ComfyClient(host="127.0.0.1", port=8188)

client.queue(workflow)      # Submit workflow, returns {"prompt_id": ...}
client.get_queue()          # Get queue status
client.get_history(id)      # Get execution history

Workflow

wf = Workflow.load("path/to/workflow.json")

wf.set_node("32", "image", value)  # Set node input (fluent, returns self)
wf.get_node("32")                   # Get entire node dict
wf.get_node("32", "image")          # Get specific input value
wf.has_node("32")                   # Check if node exists
wf.copy()                           # Deep copy for batch jobs
wf.validate()                       # Returns list of warnings
wf.to_dict()                        # Export as dict
wf.save("output.json")              # Save to file

BatchRunner

runner = BatchRunner(ports=[5892, 5893], host="127.0.0.1")

runner.queue(workflow)              # Queue to next server (round-robin)
runner.queue_all(workflows)         # Queue multiple with progress
runner.summary()                    # Get job distribution summary
runner.reset()                      # Reset counters

🔍 Finding Node IDs

Open your workflow JSON and look for the node you want to modify:

{
  "32": {
    "class_type": "LoadImage",
    "inputs": {
      "image": "example.png"
    }
  }
}

The key ("32") is the node ID. Use it with set_node():

wf.set_node("32", "image", "/path/to/my/image.png")

💡 Examples

See the examples/ directory:

  • simple_submit.py - Single workflow submission
  • batch_submit.py - Batch submission across multiple GPUs

🔄 Migrating from Custom Deploy Scripts

Before (repeated boilerplate):

def load_workflow(path): ...       # 15 lines
def queue_prompt(wf, port): ...    # 20 lines
def modify_workflow(wf, ...): ...  # 50+ lines

After:

from comfy_runner import Workflow, BatchRunner

runner = BatchRunner(ports=[5892, 5893])
wf = Workflow.load("workflow.json")
wf.set_node("32", "image", path).set_node("28", "text", prompt)
runner.queue(wf)

About

comfy-api-runner is a lightweight, headless runner for submitting ComfyUI workflows via API and executing them on local servers.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages