# 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({
"73": {
"class_type": "CustomCombo",
"inputs": {
"choice": "American Traditional"
},
"_meta": {
"title": "Tattoo Style"
}
},
"74": {
"class_type": "JsonExtractString",
"inputs": {
"json_string": "{\n \"American Traditional\": \"rendered as an American traditional tattoo with bold black outlines, a limited palette of saturated red, yellow, and green, solid color fills, and clean whip shading\",\n \"Japanese Irezumi\": \"rendered as a Japanese irezumi tattoo with flowing dynamic linework, rich traditional color, motifs of stylized waves, wind bars, and cherry blossoms, and dramatic smoke-like black shading\",\n \"Blackwork\": \"rendered as a blackwork tattoo using only solid black ink, heavy bold graphic shapes, high contrast, and dense dotwork shading, no color\",\n \"Fine Line\": \"rendered as a black-and-white fine line minimalist tattoo, drawn entirely with delicate thin single-needle black ink lines on white, sparse elegant detail, airy open composition, pure black and white line drawing, absolutely no color\",\n \"Watercolor\": \"rendered as a watercolor tattoo with vibrant translucent paint washes, soft color bleeds, expressive splatters, and minimal loose outlines\"\n}",
"key": [
"73",
0
]
},
"_meta": {
"title": "Style Prompt (JSON)"
}
},
"75": {
"class_type": "CustomCombo",
"inputs": {
"choice": "Snake"
},
"_meta": {
"title": "Tattoo Subject"
}
},
"76": {
"class_type": "JsonExtractString",
"inputs": {
"json_string": "{\n \"Snake\": \"a coiled snake with an open mouth, exposed fangs, and detailed scales\",\n \"Dragon\": \"a serpentine dragon with sweeping curves, sharp claws, and flowing whiskers\",\n \"Rose\": \"a blooming rose with layered petals, a stem, leaves, and thorns\",\n \"Skull\": \"a human skull with hollow eyes, viewed at a three-quarter angle\",\n \"Wolf\": \"a wolf head portrait with intense eyes and detailed layered fur\",\n \"Tiger\": \"a roaring tiger head with bared fangs and bold stripes\",\n \"Koi Fish\": \"a koi fish swimming upstream among stylized water splashes\",\n \"Butterfly\": \"a butterfly with fully spread symmetrical wings and ornate wing patterns\",\n \"Eagle\": \"an eagle with outstretched wings and talons extended in a landing pose\",\n \"Phoenix\": \"a phoenix rising with sweeping tail feathers and flames\",\n \"Owl\": \"an owl facing forward with wide eyes and a patterned feathered chest\",\n \"Anchor\": \"a nautical anchor wrapped with rope and a banner ribbon\",\n \"Dagger and Rose\": \"a dagger piercing through a rose, wrapped with a ribbon banner\",\n \"Sun and Moon\": \"a sun and crescent moon with faces, intertwined with floral accents\",\n \"Compass\": \"a vintage nautical compass with an ornate needle and wind rose\"\n}",
"key": [
"75",
0
]
},
"_meta": {
"title": "Subject Prompt (JSON)"
}
},
"77": {
"class_type": "PrimitiveStringMultiline",
"inputs": {
"value": "a hummingbird hovering beside a peony flower"
},
"_meta": {
"title": "Custom Subject Text"
}
},
"78": {
"class_type": "ComfySwitchNode",
"inputs": {
"on_false": [
"76",
0
],
"on_true": [
"77",
0
],
"switch": True
},
"_meta": {
"title": "Custom Subject?"
}
},
"79": {
"class_type": "StringConcatenate",
"inputs": {
"delimiter": " ",
"string_a": [
"78",
0
],
"string_b": [
"74",
0
]
},
"_meta": {
"title": "Subject + Style"
}
},
"80": {
"class_type": "StringConcatenate",
"inputs": {
"delimiter": " ",
"string_a": [
"79",
0
],
"string_b": "Tattoo design illustration presented flat on a clean solid white background, centered composition, no skin, no body, high detail, professional tattoo flash art."
},
"_meta": {
"title": "Assemble Prompt"
}
},
"81": {
"class_type": "PreviewAny",
"inputs": {
"source": [
"80",
0
]
},
"_meta": {
"title": "Final Prompt"
}
},
"82": {
"class_type": "SaveImage",
"inputs": {
"filename_prefix": "tattoo_generator",
"images": [
"83:8",
0
]
},
"_meta": {
"title": "Save Image"
}
},
"87": {
"class_type": "ResolutionSelector",
"inputs": {
"aspect_ratio": "1:1 (Square)",
"megapixels": 1,
"multiple": 8
},
"_meta": {
"title": "Resolution Selector"
}
},
"83:10": {
"class_type": "UNETLoader",
"inputs": {
"unet_name": "krea2_turbo_fp8_scaled.safetensors",
"weight_dtype": "default"
},
"_meta": {
"title": "Load Diffusion Model"
}
},
"83:11": {
"class_type": "CLIPLoader",
"inputs": {
"clip_name": "qwen3vl_4b_fp8_scaled.safetensors",
"device": "default",
"type": "krea2"
},
"_meta": {
"title": "Load CLIP"
}
},
"83:12": {
"class_type": "VAELoader",
"inputs": {
"vae_name": "qwen_image_vae.safetensors"
},
"_meta": {
"title": "Load VAE"
}
},
"83:13": {
"class_type": "ConditioningZeroOut",
"inputs": {
"conditioning": [
"83:6",
0
]
},
"_meta": {
"title": "Conditioning Zero Out"
}
},
"83:19": {
"class_type": "PrimitiveStringMultiline",
"inputs": {
"value": [
"81",
0
]
},
"_meta": {
"title": "Text String (User Prompt)"
}
},
"83:3": {
"class_type": "KSampler",
"inputs": {
"cfg": 1,
"denoise": 1,
"latent_image": [
"83:5",
0
],
"model": [
"83:10",
0
],
"negative": [
"83:13",
0
],
"positive": [
"83:6",
0
],
"sampler_name": "euler",
"scheduler": "simple",
"seed": 796754965156923,
"steps": 8
},
"_meta": {
"title": "KSampler"
}
},
"83:5": {
"class_type": "EmptyLatentImage",
"inputs": {
"batch_size": 1,
"height": [
"87",
1
],
"width": [
"87",
0
]
},
"_meta": {
"title": "Empty Latent Image"
}
},
"83:6": {
"class_type": "CLIPTextEncode",
"inputs": {
"clip": [
"83:11",
0
],
"text": [
"83:19",
0
]
},
"_meta": {
"title": "CLIP Text Encode (Prompt)"
}
},
"83:8": {
"class_type": "VAEDecode",
"inputs": {
"samples": [
"83:3",
0
],
"vae": [
"83:12",
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)