# 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": "NBP",
"images": [
"64",
0
]
},
"_meta": {
"title": "Save Image"
}
},
"63": {
"class_type": "SaveVideo",
"inputs": {
"filename_prefix": "video/Kling2.6_i2v",
"format": "auto",
"format.codec": "auto",
"video": [
"65",
0
]
},
"_meta": {
"title": "Save Video"
}
},
"64": {
"class_type": "GeminiImage2Node",
"inputs": {
"aspect_ratio": "9:16",
"images": [
"57:8",
0
],
"model": "gemini-3-pro-image-preview",
"prompt": "Use the attached image and add some typical plane numberings and logos to the plane.",
"resolution": "2K",
"response_modalities": "IMAGE",
"seed": 1079943371682559,
"system_prompt": "You are an expert image-generation engine. You must ALWAYS produce an image.\nInterpret all user input—regardless of format, intent, or abstraction—as literal visual directives for image composition.\nIf a prompt is conversational or lacks specific visual details, you must creatively invent a concrete visual scenario that depicts the concept.\nPrioritize generating the visual representation above any text, formatting, or conversational requests."
},
"_meta": {
"title": "Nano Banana Pro (Google Gemini Image)"
}
},
"65": {
"class_type": "KlingImageToVideoWithAudio",
"inputs": {
"duration": 5,
"generate_audio": True,
"mode": "pro",
"model_name": "kling-v2-6",
"prompt": "Handheld camera. An airplane moves forward while the camera slowly tracks along with it. No Cuts. No Talking. Ambient Sounds.",
"start_frame": [
"64",
0
]
},
"_meta": {
"title": "Kling 2.6 Image(First Frame) to Video with Audio"
}
},
"66": {
"class_type": "SaveImage",
"inputs": {
"filename_prefix": "z-image-turbo",
"images": [
"57:8",
0
]
},
"_meta": {
"title": "Save Image"
}
},
"57:11": {
"class_type": "ModelSamplingAuraFlow",
"inputs": {
"model": [
"57:28",
0
],
"sampling": "flow",
"shift": 3
},
"_meta": {
"title": "ModelSamplingAuraFlow"
}
},
"57:13": {
"class_type": "EmptySD3LatentImage",
"inputs": {
"batch_size": 1,
"height": 1920,
"width": 1088
},
"_meta": {
"title": "EmptySD3LatentImage"
}
},
"57:27": {
"class_type": "CLIPTextEncode",
"inputs": {
"clip": [
"57:30",
0
],
"text": "On a snowy plateau framed by jagged white peaks, a small plane sits in the foreground, its bright red tail fin rising like a flag against the ice. Stripes of yellow, blue, and orange stretch across its fuselage, injecting bands of saturated color into the otherwise monochrome world. Its skis rest gently on the snow, anchoring it in stillness while the mountains loom behind, their ridges casting pale blue shadows that carve geometric patterns across the surface. The sky is a flawless ultramarine, creating stark contrast between peak and void. Every line--the fuselage, the wings, the slope of the mountains--appears arranged with geometric precision, balancing color against emptiness. The lighting is sharp, crisp, and shadowless, heightening the sense of clarity and frozen perfection. The tableau has the quiet tension of waiting: a machine poised in nature’s immensity, reduced to a prop in a carefully staged spectacle of scale and color."
},
"_meta": {
"title": "CLIP Text Encode (Prompt)"
}
},
"57:28": {
"class_type": "UNETLoader",
"inputs": {
"unet_name": "z_image_turbo_bf16.safetensors",
"weight_dtype": "default"
},
"_meta": {
"title": "Load Diffusion Model"
}
},
"57:29": {
"class_type": "VAELoader",
"inputs": {
"vae_name": "ae.safetensors"
},
"_meta": {
"title": "Load VAE"
}
},
"57:3": {
"class_type": "KSampler",
"inputs": {
"cfg": 1,
"denoise": 1,
"latent_image": [
"57:13",
0
],
"model": [
"57:11",
0
],
"negative": [
"57:33",
0
],
"positive": [
"57:27",
0
],
"sampler_name": "res_multistep",
"scheduler": "simple",
"seed": 928035730101586,
"steps": 8
},
"_meta": {
"title": "KSampler"
}
},
"57:30": {
"class_type": "CLIPLoader",
"inputs": {
"clip_name": "qwen_3_4b.safetensors",
"device": "default",
"type": "lumina2"
},
"_meta": {
"title": "Load CLIP"
}
},
"57:33": {
"class_type": "ConditioningZeroOut",
"inputs": {
"conditioning": [
"57:27",
0
]
},
"_meta": {
"title": "Conditioning Zero Out"
}
},
"57:8": {
"class_type": "VAEDecode",
"inputs": {
"samples": [
"57:3",
0
],
"vae": [
"57:29",
0
]
},
"_meta": {
"title": "VAE Decode"
}
}
})
# run() also passes api_key to the partner nodes in this workflow.
job = client.run(workflow, api_key=api_key)