# 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({
"133": {
"class_type": "SamplerCustomAdvanced",
"inputs": {
"guider": [
"136",
0
],
"latent_image": [
"139",
0
],
"noise": [
"135",
0
],
"sampler": [
"137",
0
],
"sigmas": [
"138",
0
]
},
"_meta": {
"title": "SamplerCustomAdvanced"
}
},
"134": {
"class_type": "CLIPLoader",
"inputs": {
"clip_name": "qwen_3_8b.safetensors",
"device": "default",
"type": "flux2"
},
"_meta": {
"title": "Load CLIP"
}
},
"135": {
"class_type": "RandomNoise",
"inputs": {
"noise_seed": 754163315896983
},
"_meta": {
"title": "RandomNoise"
}
},
"136": {
"class_type": "CFGGuider",
"inputs": {
"cfg": 1,
"model": [
"158",
0
],
"negative": [
"149",
0
],
"positive": [
"148",
0
]
},
"_meta": {
"title": "CFG Guider"
}
},
"137": {
"class_type": "KSamplerSelect",
"inputs": {
"sampler_name": "euler"
},
"_meta": {
"title": "KSamplerSelect"
}
},
"138": {
"class_type": "Flux2Scheduler",
"inputs": {
"height": [
"143",
1
],
"steps": 4,
"width": [
"143",
0
]
},
"_meta": {
"title": "Flux2Scheduler"
}
},
"139": {
"class_type": "EmptyFlux2LatentImage",
"inputs": {
"batch_size": 1,
"height": [
"143",
1
],
"width": [
"143",
0
]
},
"_meta": {
"title": "Empty Flux 2 Latent"
}
},
"140": {
"class_type": "VAEDecode",
"inputs": {
"samples": [
"133",
0
],
"vae": [
"161",
0
]
},
"_meta": {
"title": "VAE Decode"
}
},
"142": {
"class_type": "SaveImage",
"inputs": {
"filename_prefix": "Flux2-Klein",
"images": [
"167",
0
]
},
"_meta": {
"title": "Save Image"
}
},
"143": {
"class_type": "GetImageSize",
"inputs": {
"image": [
"165",
0
]
},
"_meta": {
"title": "Get Image Size"
}
},
"144": {
"class_type": "ConditioningZeroOut",
"inputs": {
"conditioning": [
"157",
0
]
},
"_meta": {
"title": "Conditioning Zero Out"
}
},
"145": {
"class_type": "VAEEncode",
"inputs": {
"pixels": [
"165",
0
],
"vae": [
"161",
0
]
},
"_meta": {
"title": "VAE Encode"
}
},
"147": {
"class_type": "ImageScaleToTotalPixels",
"inputs": {
"image": [
"159",
0
],
"megapixels": 1.5000000000000002,
"resolution_steps": 1,
"upscale_method": "nearest-exact"
},
"_meta": {
"title": "Scale Image to Total Pixels"
}
},
"148": {
"class_type": "ReferenceLatent",
"inputs": {
"conditioning": [
"157",
0
],
"latent": [
"145",
0
]
},
"_meta": {
"title": "Set Reference Latent"
}
},
"149": {
"class_type": "ReferenceLatent",
"inputs": {
"conditioning": [
"144",
0
],
"latent": [
"145",
0
]
},
"_meta": {
"title": "Set Reference Latent"
}
},
"157": {
"class_type": "CLIPTextEncode",
"inputs": {
"clip": [
"134",
0
],
"text": "Remove the green areas by extending the scene into them seamlessly. Continue the flooded Victorian conservatory on both sides: more cast-iron columns with weathered verdigris, hanging ferns and curtains of moss, tiered glass terrariums, pale water lilies and drifting paper folios on the still water, and golden shafts of light falling through the broken glass roof. Match the perspective, the warm morning light, the soft haze and the celadon, bronze and parchment palette of the original exactly. Keep the seated naturalist and everything already in the picture unchanged, with no visible seam, border or repeated pattern."
},
"_meta": {
"title": "CLIP Text Encode (Positive Prompt)"
}
},
"158": {
"class_type": "UNETLoader",
"inputs": {
"unet_name": "flux-2-klein-9b.safetensors",
"weight_dtype": "default"
},
"_meta": {
"title": "Load Diffusion Model"
}
},
"159": {
"class_type": "LoadImage",
"inputs": {
"image": "UPLOADED_image_FILENAME"
},
"_meta": {
"title": "Load Image"
}
},
"161": {
"class_type": "VAELoader",
"inputs": {
"vae_name": "flux2-vae.safetensors"
},
"_meta": {
"title": "Load VAE"
}
},
"164": {
"class_type": "ImagePadForOutpaint",
"inputs": {
"bottom": 0,
"feathering": 40,
"image": [
"147",
0
],
"left": 480,
"right": 480,
"top": 0
},
"_meta": {
"title": "Pad Image for Outpainting"
}
},
"165": {
"class_type": "ImageScaleToTotalPixels",
"inputs": {
"image": [
"166",
0
],
"megapixels": 1.0000000000000002,
"resolution_steps": 1,
"upscale_method": "nearest-exact"
},
"_meta": {
"title": "Scale Image to Total Pixels"
}
},
"166": {
"class_type": "DrawMaskOnImage",
"inputs": {
"color": "0, 255, 0",
"device": "cpu",
"image": [
"164",
0
],
"mask": [
"164",
1
]
},
"_meta": {
"title": "Draw Mask On Image"
}
},
"167": {
"class_type": "ColorMatch",
"inputs": {
"image_ref": [
"159",
0
],
"image_target": [
"140",
0
],
"method": "mkl",
"multithread": True,
"strength": 1
},
"_meta": {
"title": "Color Match"
}
},
"303": {
"class_type": "ImageCompare",
"inputs": {
"compare_view": {
"__value__": [
"",
""
]
},
"image_a": [
"165",
0
],
"image_b": [
"167",
0
]
},
"_meta": {
"title": "Compare Images"
}
}
})
workflow.set_input("159", "image", client.assets.from_url("https://comfy.org/catalog-media/6dadb3e5-93c6-4512-9aac-01481e9a3c7d/4c74a3e3-fb61-488f-a711-8173c8310920"))
# run() also passes api_key to the partner nodes in this workflow.
job = client.run(workflow, api_key=api_key)
for output in job.get_outputs("142"):
output.to_file(output.name)