ComfyUI Extension: ComfyUI Functional
Easy functional programming and flow control within ComfyUI
Custom Nodes (0)
README
ComfyUI Functional
Functional programming primitives for ComfyUI graphs: define functions inline, call them multiple times, and build loops, recursion, and other control-flow constructs without leaving the node editor.
⚠️ This extension leans on a few hacky ComfyUI internals (scheduler hooks, coroutine runners, cache invalidation). Expect sharp edges and test workflows before relying on them in production pipelines.
- English docs:
docs/usage.md·docs/node-reference.md - 中文使用说明: https://duanyll.com/2025/9/25/ComfyUI-Functional/

Why ComfyUI-Functional?
- Function definitions inside graphs – Drop
Function ParameterandFunction Endnodes to encapsulate any node subgraph. Call it repeatedly or pass it to other nodes just like a Python closure. - Reusable, composable control flow –
Map,Fold,Nest,Select, and friends let you describe loops and branching logic without custom Python code. Bring your own functions as inputs. - Side-effect helpers –
Sow,Reap,Inspect, andSleepmake it possible to log data, accumulate results, and debug execution order when building complex flows. - Interop with other packs – Pairs especially well with Basic Data Handling; use its
LISTvalues whenever you pass arrays through the functional nodes.
Installation
- Install ComfyUI and (optionally) ComfyUI-Manager.
- Search for
Duanyll/comfyui_functionalinside ComfyUI-Manager and click install. - Manual alternative: clone this repository into
ComfyUI/custom_nodesand restart ComfyUI. - Install Basic Data Handling; convert ComfyUI Data Lists to
LISTbefore feeding them into these nodes. - Load one of the JSON files under
example_workflows/to see the nodes in action.
💡
example_workflows/functional-nested-calls.jsonmirrors the blog's nested function demo and is a great starting point for understanding how functions call other functions.
Core Concepts
Define a function
- Add one
Function Parameternode per argument. Rename them so the order is obvious. - Build any graph using those parameters.
- Finish the graph with a
Function Endnode. Each function returns exactly one value—wrap multiple outputs into aLIST.
Call a function
Connect the Function End output into a Call Function node, wire its inputs in the same order, and use the return value anywhere in your workflow. You can reuse the same function instance across multiple Call Function nodes, or even feed the function back into itself for recursion. Always guard recursion with a termination condition to avoid infinite loops.

Looping and branching with high-order nodes
Use the high-order nodes under duanyll/functional/high_order to iterate over lists or control execution:
Map/MapIndexedto transform lists.Foldto accumulate state across a list.Nest/NestWhileto repeat a function a fixed number of times or until a predicate fails.Select/TakeWhileto filter values.Comapto fan a single input into multiple processing branches.
See docs/node-reference.md for the full signature cheat sheet.

Side effects and debugging
- Sow/Reap collect intermediate results during a run. Chain the
signalsockets to enforce ordering whenever side effects matter. - Inspect reads any value in the middle of the function body without forcing the graph to evaluate eagerly. Pair with
Sleepif the output blinks too fast in the viewer. - Whenever side effects are detected the extension disables ComfyUI's caching to keep the results honest; expect reruns to take longer than pure functional graphs.

Troubleshooting Cheatsheet
- "Prompt has no outputs" – You either forgot to call the function or an output still depends on
Function Parameterwithout being routed throughFunction End. - Graph freezes – Make sure you are passing
LISTvalues (from Basic Data Handling) rather than ComfyUI's built-in Data List sockets. - Infinite loops – Configure
NestWhilepredicates andmax_depthcaps, or add counters into your Fold bodies. - Stale debug output – Ensure something depends on the
signalcoming out ofInspect; otherwise it will never execute.
Example Workflows
example_workflows/
├── functional-map.json # Mapping numeric transforms across a LIST
├── functional-list-param.json # Multiple parameter inputs + LIST handling
├── functional-nested-calls.json # Functions calling other functions
├── functional-recursion.json # Recursive calls with a guard
├── functional-sow-reap.json # Collecting values with Sow/Reap + Inspect
└── functional-inspect.json # Inspect/Sleep techniques for debugging
Feel free to copy these into your own projects and adapt the prompt data to match your checkpoints and samplers.
Development
To hack on the nodes locally:
cd comfyui_functional
pip install -e .[dev]
pre-commit install
The editable (-e) install allows ComfyUI to pick up changes immediately. Run the Ruff + pytest hooks via pre-commit run --all-files before submitting patches.
Tests
Pytest suites live under tests/. Run them with pytest or rely on the GitHub Actions workflows that ship with this template (build-pipeline.yml for lint/tests, validate.yml for node-diff checks).
Publishing to the Registry
Double-check the metadata under [tool.comfy] in pyproject.toml, set up an account on https://registry.comfy.org, and configure REGISTRY_ACCESS_TOKEN in your repo settings before enabling the provided publish workflow. See the official instructions for the full process.