BetaMaShop is in public beta. We improve it continuously, and your feedback shapes what comes next.
MaShop/Blog/Tools/Reading a ComfyUI Workflow as a Graph
ToolsAugust 5, 2026
Read · 5 min
comfyui · comfyui workflow

Reading a ComfyUI Workflow as a Graph

ComfyUI explained by the graph rather than the buttons: one minimal workflow node by node, then the same graph extended three ways.

Key takeaways
  • A ComfyUI workflow is one pipeline: something produces a latent, the sampler denoises it, the VAE turns it back into pixels. Everything else is a variation on where that latent came from.
  • Image to image, inpainting and upscaling are not three techniques. They are the same graph with a different node feeding the sampler and a different denoise value.
  • The official example puts image to image at a denoise of 0.87, and the rule underneath it is simple: lower denoise means less change to what you started with.
  • Every image ComfyUI saves carries the whole workflow in its metadata, which is why dragging a PNG onto the canvas rebuilds the graph, and why publishing outputs can publish your method.
  • That metadata survives a direct file transfer and usually does not survive an upload, because platforms recompress and strip it.
  • Four beginner errors account for most stuck sessions, and each one points at a specific node rather than at the model.

You open it once. There is a canvas, six boxes, and a nest of coloured wires running between them. The prompt box you came for is somewhere in there, apparently split into two, and one of the boxes says VAE Decode. You close the tab and go back to typing sentences into something simpler.

The tutorials do not help much because they teach the buttons. Click here, set this to 20, drag this wire. Six months later the interface has changed and the tutorial is wrong, while the thing it never explained, what the graph is actually doing, has not changed at all. So this piece teaches the graph. If you understand what is travelling down each wire, every workflow you meet afterwards reads like a sentence.

What is a ComfyUI workflow, really?

A pipeline drawn as boxes. Each node takes inputs of a specific type, does one thing, and emits outputs of a specific type. Wires connect an output to an input of the same type, which is why the canvas refuses some connections: you are trying to plug a picture into a socket expecting a model.

The ComfyUI Wiki puts it as the core concept of the whole application, a visual system of connected nodes that describes a complete generation process, stored either as a JSON file or inside the metadata of a generated PNG. That second storage format matters more than it sounds and it gets its own section below.

Three types carry almost all the meaning, and once you can name them the canvas stops being decorative:

  • MODEL: the weights that do the denoising.
  • CONDITIONING: your words after they have been encoded into something the model can steer by.
  • LATENT: the image while it is still in compressed form, not yet pixels.

A workflow is the story of one LATENT. It gets created, it gets denoised, it becomes an image. That is the whole plot.

Sequence diagram of the minimal ComfyUI text to image graph from checkpoint loader through text encoding, empty latent, sampler and decode

The minimal graph, node by node

Load Checkpoint

Reads a model file and emits three things at once, which is the first thing that confuses people. One output is the MODEL. One is the CLIP, the text encoder. One is the VAE, the translator between latent space and pixels. They come from a single file because they were trained together, and a graph needs all three at different points.

CLIP Text Encode, twice

There are two of these and they are identical nodes. One will be wired into the sampler's positive input and one into its negative. Nothing about the node itself makes it positive or negative: the wire decides. This is the single most useful realisation for a beginner, because it explains why the interface looks like it has two prompt boxes for no reason.

Each one takes your text and the CLIP from the checkpoint, and emits CONDITIONING. The node documentation describes the pair as conditions describing desired content and conditions describing content to exclude.

Empty Latent Image

A blank canvas in latent space, at whatever width and height you set, with a batch size. It contains nothing. In text to image this is where the LATENT is born, and this is precisely the node that gets replaced in every variation further down.

KSampler

The engine. It takes the MODEL, both CONDITIONING inputs and a LATENT, and emits a denoised LATENT. Its parameters are the ones people trade tips about, and the documentation is unusually clear about each:

  • seed: fixes randomness so a result is reproducible.
  • steps: more steps mean finer detail and slower generation.
  • cfg: guidance scale, ranging from 0 to 100, where higher values track the prompt more closely but too high hurts quality.
  • sampler_name and scheduler: which algorithm removes the noise and along what trajectory.
  • denoise: from 0 to 1, where 1.0 is full denoising and lower values preserve the structure of whatever latent came in.

If you only remember one parameter, remember denoise, because it is the dial that turns one workflow into another.

VAE Decode, then Save Image

VAE Decode takes the denoised LATENT and the VAE and emits an IMAGE, meaning actual pixels. Save Image writes it to disk. That is the end of the pipeline, and it is also where your workflow gets embedded into the file.

How does the same graph become image to image?

You delete one node and add two. That is the entire difference.

Remove Empty Latent Image. Add Load Image, which brings in your photograph, and VAE Encode, which converts those pixels into a LATENT using the same VAE from the checkpoint. Wire that LATENT into the sampler where the empty one used to go. Then lower the denoise, because you no longer want the sampler to invent everything.

The official image to image example uses 0.87 and states the rule plainly: the lower the denoise, the less noise is added and the less the image changes. For catalogue work that number is the whole control surface. Around 0.3 to 0.5 you are restyling a product shot while keeping the object recognisable. Push toward 0.9 and you are generating a new object that happens to have started from yours, which is a different legal and commercial proposition entirely. We covered where that boundary sits for a shop in the piece on what a generated catalogue image can honestly claim.

And inpainting?

Same shape again, plus a mask. Load Image can emit a MASK alongside the IMAGE, and ComfyUI ships a mask editor you reach by right clicking the image inside that node. The inpainting examples note that a transparent alpha channel is what becomes the mask, so an image erased in an external editor works too, provided the transparent pixels keep their values.

The mask tells the sampler which region to regenerate. Everything else about the graph is unchanged: still a checkpoint, still two text encodes, still a KSampler, still a decode. For a shop this is the most useful branch of the three, because it is how you remove a price sticker, replace a background behind a fixed product, or fix one blown highlight without touching anything else.

And an upscale pass?

You take the LATENT that comes out of the sampler, enlarge it, and run it through a second sampler at low denoise. Two KSamplers in one graph, in series. The second one is not there to change the picture; it is there to add detail at the new size, which is why its denoise sits low.

Once you see that, the intimidating workflows people share stop being intimidating. They are the base graph with branches: a second sampler here, a mask there, a couple of nodes rearranging the latent in between. Nobody built those from scratch.

Card explaining that every ComfyUI branch changes only the latent entering the sampler and the denoise value applied to it

What do the sampler settings actually trade against each other?

Three of them interact, and the interaction is where people waste evenings.

Steps against time. The documentation states it directly: more steps mean finer details and slower generation. What it does not say, because it depends on the sampler, is that the curve flattens. Beyond a point the extra steps change almost nothing and cost real seconds each. For a catalogue run of two hundred images, twenty wasted steps per image is a coffee break you did not need to take.

Guidance against fidelity. The cfg scale accepts anything from 0 to 100, and the docs warn that higher values track the prompt more closely but that too high hurts quality. This is the setting people push when the model ignores an instruction, and pushing it usually produces an image that obeys the words and looks worse. When a prompt is being ignored, check the wiring before you raise cfg.

Seed against everything. Fixing the seed makes a result reproducible, which turns generation from a slot machine into an experiment. Change one parameter with the seed fixed and you can attribute the difference to that parameter. Change one parameter with the seed random and you have learned nothing. Anyone comparing settings without pinning the seed is comparing noise.

The practical routine that follows: pin the seed, find a denoise that keeps what you want, then tune cfg, then reduce steps until quality drops and step back one notch. In that order, because each stage changes what the next one should be.

The node reference

What each core node consumes, what it emits, and the single parameter that moves the output most. Assembled from the node documentation and the official examples.

NodeConsumesEmitsParameter that matters most
Load CheckpointA model fileMODEL, CLIP, VAEWhich checkpoint, since it sets the whole aesthetic
CLIP Text EncodeCLIP and your textCONDITIONINGThe text, and which sampler input you wire it to
Empty Latent ImageNothingLATENTWidth and height, which the model was trained around
Load ImageA fileIMAGE and MASKThe mask, when inpainting
VAE EncodeIMAGE and VAELATENTNothing, it is a converter
KSamplerMODEL, two CONDITIONING, LATENTLATENTdenoise, then cfg, then steps
VAE DecodeLATENT and VAEIMAGENothing, it is a converter
Note

Two nodes in that table have no meaningful parameters at all. VAE Encode and VAE Decode are pure translation between pixels and latent space. If your output looks washed out or oddly coloured, the fault is almost never in these; it is a mismatched VAE loaded separately from the checkpoint that produced the latent.

Why does dragging an image onto the canvas rebuild the whole workflow?

Because the workflow is inside the image. The wiki states that every image generated through ComfyUI carries metadata containing the graph, which is why you never strictly need to save a JSON file alongside your outputs. Drop the PNG on the canvas, or open it with the file dialogue, and the nodes and wiring come back exactly as they were.

This is a genuinely good design decision and it has a consequence nobody mentions in tutorials. If you publish an output, you may be publishing your method. Every prompt, every negative prompt, every checkpoint name, every parameter you spent a fortnight tuning travels inside the file. For most people that is a feature, since the community runs on shared workflows. For a shop that has developed a look it considers part of its brand, it is a leak.

The saving grace is accidental. The same wiki page notes that compression or network transmission can destroy the metadata, and in practice most upload paths recompress images and strip it. So an image posted to a social platform has usually lost its workflow, while the same image sent as a file attachment has not. If you care either way, test it rather than assuming: drag your own published image back onto the canvas and see what happens.

Four errors that stop beginners, and the node responsible

These are the ones that generate the most confusion per occurrence, because the visible symptom is far from the cause.

SymptomLikely causeNode to look at
A wire refuses to connectType mismatch, such as IMAGE into a LATENT inputWhichever node you are dragging from
Output ignores your image entirelyDenoise left at 1.0, so the sampler rebuilt everythingKSampler
Colours look muddy or washed outA VAE that does not match the checkpointLoad VAE, if you added one separately
Prompt appears to be ignoredText wired into the negative input instead of the positiveThe two CLIP Text Encode nodes

A fifth deserves a sentence of its own because it is not really an error. An old workflow JSON may not load in a current build, since the application updates frequently and node definitions move. When a shared workflow throws missing node errors, the graph is fine and the node pack it depends on is not installed or has been renamed.

Is this worth learning if you sell things?

Only for one reason, and it is a good one: repeatability. A prompt box gives you a nice image and no way to get the same treatment on the next forty products. A graph is a saved procedure. Load a different product photo, keep every other node fixed, and the treatment is identical across your catalogue.

That consistency is the actual commercial value here, and it is invisible in every demo because demos show one impressive image. Forty consistent images beat one impressive one on a product grid, which is a point we made when comparing generators in the piece on what the cheaper image models are good for. If your shots also need to work as the primary listing image, the constraints are different again and worth reading before you generate anything, in the guide to what still has to be photographed.

If your requirement is one background swap a month, do not learn this. A hosted tool will do it faster and you will forget the graph between uses. The threshold is roughly the point where you are doing the same edit more than ten times.

What changes between releases, and what does not

This section is the one to update; the rest of the page should stay true. The interface moves, node packs break after core updates, and the exact names of some nodes have shifted more than once. What has not changed since the application existed: the three types, the story of one latent, the role of denoise, and the fact that every advanced graph is the base graph with a branch.

So when a workflow you downloaded stops working, read it as a graph first. Find the node that produces the latent. Find the sampler. Check what feeds its positive and negative inputs. Nine times in ten the break is a missing custom node in a branch, and the spine of the graph is still doing exactly what it did in this article.

For merchants who would rather not run any of this locally, generating the storefront and its imagery in one place is the alternative, and our store builder handles the catalogue side without a canvas of wires. The reason to learn the graph anyway is that it tells you what any image tool is doing underneath, which is the difference between using one and being at its mercy.

Comments 0

0 / 4000Your email stays private.
No comments yet. Be the first.

Keep reading picked for you.

Describe it. MaShop builds it.

Commerce apps and websites from one sentence. No card to start.

Start building