# Python 3.10+: pip install comfy-sdk==0.4.0
import os
from comfy_sdk import Comfy
api_key = os.environ.get("COMFY_API_KEY", "").strip()
if not api_key: raise RuntimeError("Set COMFY_API_KEY")
os.environ.setdefault("COMFY_BASE_URL", "https://cloud.comfy.org")
client = Comfy(api_key=api_key)
workflow = client.workflows.from_json({
"9": {
"class_type": "SaveImage",
"inputs": {
"filename_prefix": "z-image-upscaled",
"images": [
"118:126",
0
]
},
"_meta": {
"title": "Save Image"
}
},
"77": {
"class_type": "LoadImage",
"inputs": {
"image": "2ed0d136e3eac12ca21e34ce83e5a3b35c2bcd4202adc1c1ffba5ca28ba98409.png"
},
"_meta": {
"title": "Load Image"
}
},
"86": {
"class_type": "ImageCompare",
"inputs": {
"compare_view": {
"__value__": [
"",
""
]
},
"image_a": [
"118:121",
0
],
"image_b": [
"118:126",
0
]
},
"_meta": {
"title": "Compare Images"
}
},
"118:101": {
"class_type": "TextGenerate",
"inputs": {
"clip": [
"118:92",
0
],
"image": [
"77",
0
],
"max_length": 512,
"mtp": "auto",
"prompt": "Describe this image as a single 40-100 word prompt for an image generation model. State the main subject, setting, lighting, camera angle, composition, color palette, and overall style in precise, concrete language. Output only the prompt text with no preamble, quotes, or line breaks.",
"sampling_mode": "on",
"sampling_mode.min_p": 0.05,
"sampling_mode.presence_penalty": 0,
"sampling_mode.repetition_penalty": 1.05,
"sampling_mode.seed": 0,
"sampling_mode.temperature": 0.7,
"sampling_mode.top_k": 64,
"sampling_mode.top_p": 0.95,
"thinking": False,
"use_default_template": True
},
"_meta": {
"title": "Generate Text"
}
},
"118:119": {
"class_type": "ModelSamplingAuraFlow",
"inputs": {
"model": [
"118:127",
0
],
"sampling": "flow",
"shift": 3
},
"_meta": {
"title": "ModelSamplingAuraFlow"
}
},
"118:120": {
"class_type": "CLIPTextEncode",
"inputs": {
"clip": [
"118:128",
0
],
"text": ""
},
"_meta": {
"title": "CLIP Text Encode (Negative Prompt)"
}
},
"118:121": {
"class_type": "ImageScaleToTotalPixels",
"inputs": {
"image": [
"77",
0
],
"megapixels": 1,
"resolution_steps": 1,
"upscale_method": "lanczos"
},
"_meta": {
"title": "Scale Image to Total Pixels"
}
},
"118:122": {
"class_type": "ImageUpscaleWithModel",
"inputs": {
"image": [
"118:121",
0
],
"upscale_model": [
"118:131",
0
]
},
"_meta": {
"title": "Upscale Image (using Model)"
}
},
"118:123": {
"class_type": "VAEEncode",
"inputs": {
"pixels": [
"118:124",
0
],
"vae": [
"118:130",
0
]
},
"_meta": {
"title": "VAE Encode"
}
},
"118:124": {
"class_type": "ImageScaleBy",
"inputs": {
"image": [
"118:122",
0
],
"scale_by": 0.5,
"upscale_method": "lanczos"
},
"_meta": {
"title": "Upscale Image By"
}
},
"118:125": {
"class_type": "KSampler",
"inputs": {
"cfg": 1,
"denoise": [
"118:96",
0
],
"latent_image": [
"118:123",
0
],
"model": [
"118:119",
0
],
"negative": [
"118:120",
0
],
"positive": [
"118:129",
0
],
"sampler_name": "dpmpp_2m_sde",
"scheduler": "beta",
"seed": 324122075788056,
"steps": 5
},
"_meta": {
"title": "KSampler"
}
},
"118:126": {
"class_type": "VAEDecode",
"inputs": {
"samples": [
"118:125",
0
],
"vae": [
"118:130",
0
]
},
"_meta": {
"title": "VAE Decode"
}
},
"118:127": {
"class_type": "UNETLoader",
"inputs": {
"unet_name": "z_image_turbo_bf16.safetensors",
"weight_dtype": "default"
},
"_meta": {
"title": "Load Diffusion Model"
}
},
"118:128": {
"class_type": "CLIPLoader",
"inputs": {
"clip_name": "qwen_3_4b.safetensors",
"device": "default",
"type": "lumina2"
},
"_meta": {
"title": "Load CLIP"
}
},
"118:129": {
"class_type": "CLIPTextEncode",
"inputs": {
"clip": [
"118:128",
0
],
"text": [
"118:94",
0
]
},
"_meta": {
"title": "CLIP Text Encode (Positive Prompt)"
}
},
"118:130": {
"class_type": "VAELoader",
"inputs": {
"vae_name": "ae.safetensors"
},
"_meta": {
"title": "Load VAE"
}
},
"118:131": {
"class_type": "UpscaleModelLoader",
"inputs": {
"model_name": "4xNomosUniDAT_otf.pth"
},
"_meta": {
"title": "Load Upscale Model"
}
},
"118:92": {
"class_type": "CLIPLoader",
"inputs": {
"clip_name": "qwen3.5_2b_bf16.safetensors",
"device": "default",
"type": "stable_diffusion"
},
"_meta": {
"title": "Load Qwen3.5 4B (Captioner)"
}
},
"118:94": {
"class_type": "PreviewAny",
"inputs": {
"source": [
"118:101",
0
]
},
"_meta": {
"title": "Generated Positive Prompt"
}
},
"118:95": {
"class_type": "CustomCombo",
"inputs": {
"choice": "Medium"
},
"_meta": {
"title": "Enhancement Strength"
}
},
"118:96": {
"class_type": "ComfyMathExpression",
"inputs": {
"expression": "0.16 if a == 0 else (0.23 if a == 1 else 0.33)",
"values.a": [
"118:95",
1
]
},
"_meta": {
"title": "Strength → Denoise"
}
}
})
# run() also passes api_key to the partner nodes in this workflow.
job = client.run(workflow, api_key=api_key)