When the Graph Decides What to Do
ComfyUI's workflow graph can be explicit without being fully eager. This chapter examines what happens when a node does not need every visible input, when independent operations can overlap, or when a node creates more graph while it runs. The practical value is selective work: the reader should be able to explain why one branch is skipped, how a node requests a dependency later, and why a dynamic workflow can introduce runtime failures that were invisible in the original graph.
A visible link is not always an immediate request
A static reading of a graph suggests that every link should be evaluated before its consumer runs. That would be safe, but it would also force work that the node may never use. Consider an image-mixing operation with two linked images and a linked mask. If the mask says that the output should come entirely from the first image, evaluating the second image may add model loading, file work, or a long computation without changing the result. ComfyUI provides a way for the node to state that decision rather than asking the executor to infer it.
A node can mark an input as lazy. A lazy input is still a real part of the node's contract, but its producer is not treated as an immediate strong dependency when the executor first builds the pending graph. The node can implement check_lazy_status, which receives the inputs that are already available and identifies the names it now needs. An unevaluated lazy input is represented as unavailable rather than as a guessed value. The node must ask for it explicitly if its current condition requires it.
This creates a small negotiation between the node and the executor. The executor selects the node and supplies the values it can already provide. The node examines those values and returns the names of missing inputs it needs. The executor then promotes those links to strong dependencies, adds the requested producers to the execution list if necessary, and waits for them. When the values are ready, the node is considered again. If its condition did not require a branch, the branch never becomes part of the required work.
The distinction is important because “not evaluated yet” and “not needed” are different states. A node that receives no value for a lazy input cannot safely assume that the upstream producer returned nothing. The producer may simply not have run. A correct lazy node asks for the input when its decision depends on it. A node that requests every lazy input immediately remains correct but loses the benefit. A node that fails to request a required input can return an incomplete or misleading result. Laziness is therefore an interface promise, not a free optimization applied from outside.
The repository's execution tests make the behavior concrete. They construct two image branches, a mask, a lazy mixing node, and a save output. With a mask that selects the first branch, the first image and mask run, the mix runs, and the second image is not executed.