AI · Setup & Infrastructure

ComfyUI Node Types

From vocabulary to grammar — five categories that make any workflow readable.

In 2.2.2 — ComfyUI: Philosophy and Interface you read through two workflows — node by node, left to right. You now know what a CheckpointLoaderSimple does, what a KSampler does, why VAEDecode comes at the end. That's vocabulary.

This article is the grammar behind it.

Every node in ComfyUI belongs to a functional category — not by name or appearance, but by its role in the data flow. Understanding these categories means being able to read an unfamiliar workflow without looking up every node individually. And building your own workflow means knowing where each node belongs before you go searching for it.

Five categories cover everything that appears in a ComfyUI workflow.

01

Loaders

Loaders bring data from outside into the system. No loaders — no workflow.

What they load: models, encoders, VAEs, images, LoRAs, ControlNet models. Everything that lives as a file on disk and is needed for the generation process enters the graph through a loader.

Loaders have no inputs — they always sit at the beginning of a data flow. Their outputs are typed: a UNETLoader outputs MODEL, a VAELoader outputs VAE, a DualCLIPLoader outputs CLIP. These types determine which nodes can connect downstream — ComfyUI only allows compatible connections.

The difference between SDXL and Flux is immediately visible here: CheckpointLoaderSimple outputs MODEL, CLIP, and VAE simultaneously — everything in one file. Flux needs three separate loaders for the same three components. More nodes, but more flexibility: each component can be swapped independently.

Nodes from 2.2.2

CheckpointLoaderSimple · UNETLoader · DualCLIPLoader · VAELoader

Further loaders

LoraLoader — loads a LoRA and applies it to MODEL and CLIP · ControlNetLoader — loads a ControlNet model · LoadImage — brings an external image into the workflow, the basis for ControlNet and image-to-image

02

Conditioning

Conditioning is translation work: human inputs are converted into a format the model understands during sampling. The text prompt is the most obvious input — but not the only one.

Text prompts are converted into CONDITIONING via CLIP or T5 encoders. CONDITIONING is no longer text — it's a numerical representation that tells the model which direction to shape the noise.

With SDXL: two CLIPTextEncode nodes, one for positive, one for negative. Both receive the same CLIP encoder, both output CONDITIONING.

With Flux: a single CLIPTextEncodeFlux node with two text fields — clip_l for the keyword list, t5xxl for full sentences. No negative prompt, because the architecture doesn't provide this channel.

What conditioning nodes share: they sit between loaders and the sampler. They receive encoders, output CONDITIONING, and that CONDITIONING always feeds into the sampling step.

Nodes from 2.2.2

CLIPTextEncode · CLIPTextEncodeFlux

Further conditioning nodes

CLIPTextEncodeSDXL — uses both SDXL CLIP encoders separately for more precise control · ConditioningCombine / ConditioningAverage — combine multiple CONDITIONING outputs, useful when style and content are conditioned separately

03

Sampling

Sampling is the actual generation process. This is where everything else prepares for: the model gradually shapes noise into a latent that matches the conditioning.

A latent isn't an image file. It's a compressed representation in the model's internal space — mathematically far from a visible pixel, but structurally already the image. Only the VAE in category 5 translates it into pixels.

The sampling process has several controllable parameters:

  • Steps — how many iteration steps. More steps, finer result, longer compute time. Typically 30–35 for SDXL, 20–25 for Flux.
  • CFG (Classifier-Free Guidance) — how strictly the model follows the conditioning. Reasonable range for SDXL: 4–7. For Flux.1 dev: must be 1 — any higher value works against the built-in guidance distillation.
  • Sampler algorithm — the mathematical method of iteration. euler, dpmpp_2m, ddim are common variants with different characteristics.
  • Scheduler — controls how noise strength decreases over steps. karras for SDXL, simple for Flux are solid starting points.

With SDXL, KSampler bundles all of this in one node. With Flux it's split: KSamplerSelect picks the algorithm, BasicScheduler defines the sigma curve, RandomNoise generates the seed, BasicGuider connects model and conditioning, SamplerCustomAdvanced runs everything together. More nodes — but each component individually swappable.

EmptyLatentImage belongs conceptually here: it creates the empty workspace in which diffusion takes place. Resolution and aspect ratio are set here — not at save time.

Nodes from 2.2.2

KSampler · SamplerCustomAdvanced · KSamplerSelect · BasicScheduler · RandomNoise · BasicGuider · EmptyLatentImage

04

Control — ControlNet

ControlNet is its own category because it has its own logic. It's not part of the prompt process and not part of sampling — it's a lateral feed that binds the generation process to an external structure.

How it works: an input image — a Blender render, for instance — is converted into an edge map by a preprocessing node. That edge map, together with a loaded ControlNet model, goes into a ControlNetApply node. The output is a modified CONDITIONING that now contains not just the text prompt, but also the geometric structure of the input image.

This modified CONDITIONING goes into the sampler — and the model generates an image that follows both the prompt and the given structure.

In the RAY-L workflow, this is the central connection: Blender delivers the geometry as an edge image, ControlNet Canny transfers that geometry into the diffusion process, the model interprets materials and atmosphere within that fixed structure. Composition and perspective come from Blender — everything else from the model.

ControlNet models aren't universal: a ControlNet Canny trained for SDXL won't work with Flux, and vice versa. The model and its ControlNet must match.

Masks — for inpainting and outpainting — follow a related logic: they also steer the generation process spatially, but targeting specific image regions. That's a separate topic, coming when RAY-L integrates these features.

Key nodes

ControlNetLoader — loads the ControlNet model · ControlNetApply / ControlNetApplyAdvanced — connects edge image and ControlNet with the CONDITIONING · CannyEdgePreprocessor — generates the edge map from an input image

05

Output & Post-processing

At the end of every workflow comes the back-translation: from latent to visible image, and from image to file.

VAEDecode is the required step. The latent from the sampler isn't an image — only the VAE translates it into pixels. Which VAE is used directly affects image quality: color rendering, sharpness, artifacts. With SDXL, the VAE comes from the checkpoint or is loaded separately; with Flux, ae.safetensors is the standard.

SaveImage saves the decoded image to ComfyUI's output directory and displays it on the canvas. That's all it does — but it's the node you look at most often.

Upscaler nodes also belong here. They receive the finished image and enlarge it — either via classical upscaling algorithms or AI-based models like ESRGAN. In a professional production chain, upscaling is often the last step before further processing in Topaz or another post-production tool. This step can be automated directly from ComfyUI — the image goes into the upscaler, the upscaler passes it to SaveImage.

Nodes from 2.2.2

VAEDecode · SaveImage

Further output nodes

ImageUpscaleWithModel — AI-based upscaling within the workflow · UpscaleModelLoader — loads the upscaling model · PreviewImage — shows an image on the canvas without saving it, useful for intermediate steps

The connection logic

One final thought on why ComfyUI types connections at all — why you can't just connect a LATENT output to a CONDITIONING input.

Typing is error prevention. A workflow with twelve nodes has dozens of possible connections — without types it would be trivial to accidentally connect a VAE output to a sampler input that expects a model. The result would be an error that's hard to locate.

With types you see immediately: this connection isn't possible because the types don't match. The graph stays readable. And readable means maintainable, shareable, reusable.

This is also why ComfyUI workflows are so portable as JSON — the connection structure is fully stored in the file, including all types. Opening a JSON opens a completely defined process.