App Workflow
Reuse a whole saved graph as a single node
- input_1
- input_2
- input_3
- input_4
- exposed
- output_1
- output_2
- output_3
- output_4
The workflow-as-a-node idea is the endgame of ComfyUI reuse. You've built an upscaler pipeline, or a fixed pre-processing chain, or a "make this look like a product shot" graph you run a hundred times. You don't want to drag that wall of nodes into every new workflow or hand-merge JSON. App Workflow is WAS Node Suite's answer: it runs a saved workflow as a single node, exposing the parts worth setting and handing you the parts worth keeping.
Under WAS Suite/Workflow, the single app control is a dropdown of your saved app workflows. When you haven't saved any yet it shows (no app workflow saved) - which is the honest hint that this node is only half the story; you also need a workflow saved in app mode for it to run. Those live in the workflows directory as *.app.json files. An app workflow is a normal saved graph whose author marked some widgets as exposed inputs (things a caller should be able to set) and some outputs as presented results (things a caller should get back).
Once you pick one, the node reshapes itself to fit it. The generic input_1–input_4 sockets rename to the exposed inputs' own names - red_offset, steps, whatever the app calls them - and narrow to each input's own type. On the output side, output_1–output_4 rename to what the app's results carry: a workflow that ends in a Preview Image answers the IMAGE itself, because the node carries whatever feeds that final node.
How you drive it
Two ways to supply values. The overrides text box takes JSON keyed on the exposed input's name - {"steps": 30, "text": "a red car"} - and anything you leave out keeps the value the workflow was saved with. Or wire values into the sockets that appeared when you chose the app. Both feed the same exposed inputs; the widgets you set are just sent through as overrides.
One nicety worth knowing: an exposed input that names a file - say the app expects a checkpoint filename - takes an IMAGE (or the matching value) on the socket instead, and the file isn't read. The node reads what you hand it rather than loading from disk, which is what lets you feed a freshly-generated image straight into a saved graph that was built around a loader.
The exposed output gives you a DICT summarising what ran: the exposed input names, the result count, and how many nodes the workflow executed. Feed it to a text list or a note if you want the run's shape logged.
The honest framing
This is subworkflow reuse done the WAS way - the same instinct as core ComfyUI's Subgraph (collapse a region into one reusable node) and the various embed/subprocess workflow players other packs ship. Its strength is that the reused graph stays a real, editable workflow on disk rather than a frozen copy. Its cost is the extra ceremony: you have to save in app mode, remember what the exposed inputs are called, and keep the .app.json file around. For the highest-frequency pipes - a company-standard upscale chain, an encode step you can't stand to rebuild - it's worth it. For a graph you'll touch twice, just copy the nodes.
Installing
Part of WAS Node Suite v3 (WASasquatch/was-node-suite-comfyui), WASasquatch's MIT pack - going since 2023, over a million downloads. Workflow nodes need nothing beyond the pack: no packages, no models, no network. Requires ComfyUI 0.14.0+, since the v3 suite is written against ComfyUI's newer node backend.
Via ComfyUI Manager, search WAS Node Suite v3, or clone:
cd ComfyUI/custom_nodes
git clone https://github.com/WASasquatch/was-node-suite-comfyui
Restart ComfyUI and it appears under WAS Suite/Workflow. If the dropdown only ever shows "(no app workflow saved)", that's not a bug - save a workflow in app mode first, then pick it here.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| app | COMBO | Which saved app workflow to run; a name ending .app.json from the workflows directory, such as upscale.app.json. | |
| overrides | STRING | {} | Values for the workflow's exposed inputs, as JSON keyed on the input name: {"steps": 30, "text": "a red car"}. Anything left out keeps the value the workflow was saved with, and the widgets below are sent through here. |
| input_1opt | * | Value for the first input the workflow exposes, replacing what it saved; any type. Choosing a workflow renames this socket to the input it feeds, such as red_offset, and narrows it to that input's own type. An input that names a file takes an IMAGE here instead, and the file is not read. | |
| input_2opt | * | Value for the second input the workflow exposes, replacing what it saved; any type. Choosing a workflow renames this socket to the input it feeds, such as red_offset, and narrows it to that input's own type. An input that names a file takes an IMAGE here instead, and the file is not read. | |
| input_3opt | * | Value for the third input the workflow exposes, replacing what it saved; any type. Choosing a workflow renames this socket to the input it feeds, such as red_offset, and narrows it to that input's own type. An input that names a file takes an IMAGE here instead, and the file is not read. | |
| input_4opt | * | Value for the fourth input the workflow exposes, replacing what it saved; any type. Choosing a workflow renames this socket to the input it feeds, such as red_offset, and narrows it to that input's own type. An input that names a file takes an IMAGE here instead, and the file is not read. |
Outputs (5)
| Name | Type | Description |
|---|---|---|
| exposed | DICT | What the workflow offers, as one value; DICT. Holds its exposed input names, its result count and the node count it ran. |
| output_1 | * | The first result the workflow presents; any type. It carries whatever feeds that node, so a workflow ending in a Preview Image answers the IMAGE itself, and choosing a workflow renames this socket to what it carries. |
| output_2 | * | The second result the workflow presents; any type. It carries whatever feeds that node, so a workflow ending in a Preview Image answers the IMAGE itself, and choosing a workflow renames this socket to what it carries. |
| output_3 | * | The third result the workflow presents; any type. It carries whatever feeds that node, so a workflow ending in a Preview Image answers the IMAGE itself, and choosing a workflow renames this socket to what it carries. |
| output_4 | * | The fourth result the workflow presents; any type. It carries whatever feeds that node, so a workflow ending in a Preview Image answers the IMAGE itself, and choosing a workflow renames this socket to what it carries. |