ComfyUI Adds Native Loops: Start Loop and End Loop Nodes

ComfyUI Wikinews

ComfyUI core now loops a workflow natively. Pair Start Loop with End Loop to iterate a graph over a count, an index range or a list, with carried values and accumulated outputs.

ComfyUI core can now loop a graph without custom nodes. PR #16227 added a generic looping mechanism built from two boundary nodes, Start Loop and End Loop, and it is part of the core release published on 2026-09-15. Update ComfyUI and both nodes show up under the utilities/looping category.

How a loop is drawn

There is no loop container to configure. A loop is a pair of nodes, and the body is whatever sits between them: anything wired from Start Loop through to End Loop runs once per iteration.

Loop structure is checked during normal prompt validation, so a malformed loop fails before execution starts. Every Start Loop must pair unambiguously with exactly one End Loop, nested scopes must stay consistent, and a loop branch cannot escape its End Loop. Start Loop and End Loop declare themselves as loop boundaries in their node schema, which is what the pairing check reads.

At execution time the original body is inhibited and each iteration is projected as fresh queued graph nodes, including the first one. Iterations stay ordinary scheduler work rather than being handled by a separate loop interpreter, and iteration progress is reported on the node as Iteration n / total.

Three ways to count iterations

Start Loop's mode input picks how the iteration counter is produced, and only the inputs for the selected mode are shown.

ModeIterates overOwn inputs
simpleA fixed number of repetitionsnum_iterations (default 4)
ForA numeric index rangestart_iteration_index (default 0), max_iteration (default 4, exclusive), step (default 1)
ListOne pass per item in a connected listlist

step is at least 1 and a value of 0 raises an error. If the computed iteration count is zero, the loop body does not run and is_last is reported as true.

What Start Loop returns

OutputMeaning
iteration_indexIndex of the current iteration
is_firstTrue on the first iteration
is_lastTrue on the last iteration
list_itemThe current item in List mode, empty in the other modes
current_iteration_valueThe loop-carried value for this iteration

is_first is the usual hook for a different first pass, for example seeding a video loop from a source frame instead of the previous window's last frame.

Start Loop and End Loop wrapping a small image generation graph

The minimal case: one Start Loop, a small generation body, one End Loop. The Save Image passthrough is wired to a termination input so it still executes once per iteration.

Closing the loop

End Loop closes the scope and decides what leaves it.

InputRole
output_valueThe value returned after the loop finishes
next_iteration_valueSent back to Start Loop as current_iteration_value for the next iteration
accumulateWhen enabled, every iteration's output_value is returned instead of only the final one
termination inputsDynamically growing inputs for previews, savers and other side effects that must run on every iteration. Their values are not returned

End Loop has a single output socket whose type follows output_value. With accumulate enabled the values come out as a normal ComfyUI list, concatenated in iteration order.

The termination inputs are the fix for a common surprise: a Preview Image or Save Image node sitting inside the body would otherwise only fire for the final iteration, because the earlier projected bodies are superseded. Wiring that node's passthrough into a termination input keeps it running once per iteration and keeps it inside the loop boundary.

Accumulating every iteration's output

With accumulate on, all four generations come back as one list. Preview Image is terminated so each iteration is visible as it completes.

Varying the work per iteration

Because iteration_index is a normal integer output, it can drive anything downstream: resolution, step count, prompt variants, or a LoRA strength ramp.

For mode driving a different resolution per iteration

For mode feeding iteration_index into the resolution, with differently sized results accumulated at the end.

Carrying state between iterations

initial_iteration_value seeds the carried value on the first iteration, and each iteration's next_iteration_value becomes the next iteration's current_iteration_value. That is the whole state channel, and there is exactly one per Start and End Loop pair.

To carry more than one thing, put them in a list. The existing Create List node now accepts heterogeneous inputs, so one carried value can hold mixed state such as an image and the text prompt that produced it. Two nodes in the utilities category support the pattern:

  • Create List: builds the carried value from mixed inputs.
  • Get Item From List: new in the same release. It takes a list and an index and returns that item as a normal value, so the components of the carried state can be unpacked inside the next iteration.
Two generations feeding each other through a carried image and prompt value

Z-Image generation and vision-language captioning passed back and forth through a single carried image and text value.

Nesting and caching

parent_iteration on Start Loop is a force input: connect the outer loop's iteration_index to it to nest a loop inside another one. Nesting is explicit rather than inferred, and each Start Loop still needs exactly one End Loop.

cache_iterations on Start Loop is advanced and off by default. When enabled, projected iteration nodes may reuse cached results from earlier executions. The End Loop node itself is an ordinary executed node, so its final output is cached normally either way.

An inner loop nested inside an outer list-driven loop

A List mode outer loop over prompts, with the generation loop nested inside it via parent_iteration.

Video and latent examples

The mechanism was built with video extension in mind, where each window depends on the previous one. Two published examples show the pattern directly.

Chaining video windows through a carried last frame

A last-frame-to-first-frame video loop: the source image seeds initial_iteration_value, each generated window's final frame becomes the next window's first frame, and the frame batches are accumulated and rebatched into one clip.

Carrying a latent through the loop and ramping a LoRA

A latent carried directly through the loop with accumulate off, so only the final latent is returned, plus a lazy switch for first-iteration handling and a LoRA strength that changes gradually as sampling proceeds.

The simplest starting point, a four-iteration generation loop with no carried state, is a single Start and End Loop pair:

Where the nodes live

Start Loop and End Loop are core nodes in the utilities/looping category and ship with ComfyUI itself, so no node pack is needed. Create List and Get Item From List sit in utilities. The looping behaviour is documented on the official built-in node pages for Start Loop and End Loop.

Existing workflows are unaffected: loops are opt-in, and a graph with no Start and End Loop pair queues exactly as before.

Comments

Sign in with GitHub to join the discussion.

Loading comments…
ComfyUI Adds Native Loops: Start Loop and End Loop Nodes | ComfyUI Wiki