# 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({
"1": {
"class_type": "InpaintCropImproved",
"inputs": {
"context_from_mask_extend_factor": 1.2,
"downscale_algorithm": "bilinear",
"extend_down_factor": 1,
"extend_for_outpainting": False,
"extend_left_factor": 1,
"extend_right_factor": 1,
"extend_up_factor": 1,
"image": [
"284",
0
],
"mask": [
"9",
1
],
"mask_blend_pixels": 32,
"mask_expand_pixels": 0,
"mask_fill_holes": True,
"mask_hipass_filter": 0.1,
"mask_invert": False,
"output_padding": "32",
"output_resize_to_target_size": True,
"output_target_height": 1024,
"output_target_width": 1024,
"preresize": False,
"preresize_max_height": 16384,
"preresize_max_width": 16384,
"preresize_min_height": 1024,
"preresize_min_width": 1024,
"preresize_mode": "ensure minimum resolution",
"upscale_algorithm": "bicubic"
},
"_meta": {
"title": "✂️ Inpaint Crop (Improved)"
}
},
"2": {
"class_type": "InpaintStitchImproved",
"inputs": {
"inpainted_image": [
"278",
0
],
"stitcher": [
"1",
0
]
},
"_meta": {
"title": "✂️ Inpaint Stitch (Improved)"
}
},
"5": {
"class_type": "LoadImage",
"inputs": {
"image": "UPLOADED_image_FILENAME"
},
"_meta": {
"title": "INPUT NEW SUBJECT"
}
},
"9": {
"class_type": "Painter",
"inputs": {
"bg_color": "#000000",
"height": 2048,
"image": [
"284",
0
],
"mask": "UPLOADED_image_2_FILENAME",
"width": 2048
},
"_meta": {
"title": "Painter"
}
},
"10": {
"class_type": "SaveImage",
"inputs": {
"filename_prefix": "revised_render",
"images": [
"2",
0
]
},
"_meta": {
"title": "Save Image"
}
},
"13": {
"class_type": "PreviewImage",
"inputs": {
"images": [
"283",
0
]
},
"_meta": {
"title": "Preview Image"
}
},
"248": {
"class_type": "PrimitiveStringMultiline",
"inputs": {
"value": "Replace the grey table in the first image into the table in the second image, leave the background unchanged"
},
"_meta": {
"title": "PROMPT"
}
},
"261": {
"class_type": "ImageCompare",
"inputs": {
"compare_view": None,
"image_a": [
"284",
0
],
"image_b": [
"2",
0
]
},
"_meta": {
"title": "Compare Images"
}
},
"273": {
"class_type": "ImageRemoveAlpha+",
"inputs": {
"image": [
"13",
0
]
},
"_meta": {
"title": "🔧 Image Remove Alpha"
}
},
"277": {
"class_type": "ImageCompare",
"inputs": {
"compare_view": None,
"image_a": [
"1",
1
],
"image_b": [
"278",
0
]
},
"_meta": {
"title": "Compare Images"
}
},
"278": {
"class_type": "ColorTransfer",
"inputs": {
"image_ref": [
"1",
1
],
"image_target": [
"273",
0
],
"method": "reinhard_lab",
"source_stats": "per_frame",
"strength": 1
},
"_meta": {
"title": "Transfer Color"
}
},
"283": {
"class_type": "ByteDanceSeedreamNodeV2",
"inputs": {
"model": "seedream 5.0 pro",
"model.height": 2048,
"model.images.image_1": [
"1",
1
],
"model.images.image_2": [
"5",
0
],
"model.size_preset": "(1K) 1024x1024 (1:1)",
"model.width": 2048,
"prompt": [
"248",
0
],
"seed": 678260072,
"thinking": True,
"watermark": False
},
"_meta": {
"title": "ByteDance Seedream 4.5 & 5.0 (Legacy)"
}
},
"284": {
"class_type": "LoadImage",
"inputs": {
"image": "UPLOADED_image_3_FILENAME"
},
"_meta": {
"title": "INPUT RENDER"
}
}
})
# Replace each example.com URL with a public URL of your file.
workflow.set_input("5", "image", client.assets.from_url("https://example.com/replace-with-a-url/image"))
workflow.set_input("9", "mask", client.assets.from_url("https://example.com/replace-with-a-url/image_2"))
workflow.set_input("284", "image", client.assets.from_url("https://example.com/replace-with-a-url/image_3"))
# run() also passes api_key to the partner nodes in this workflow.
job = client.run(workflow, api_key=api_key)