ComfyUI Node

Call Function

Where this pack's magic actually happens

By Duanyll·Created 11 months ago·Updated 4 months ago· 2
Call Function
  • closure
  • param_0
  • *

Call Function is the node that makes the whole ComfyUI Functional pack make sense. Every other node defines a function or hands one around; this one runs it. If you've built a subgraph between Function Parameter and Function End, this is how you say "do the thing, right here, right now" - as many times as you like, from as many places as you like.

Why you'd reach for it

ComfyUI is a graph, not a program. Normally, to reuse a pipeline you copy-paste the nodes or reroute wires, and a workflow with ten near-identical blocks becomes a wall of spaghetti. This pack lets you define the block once and call it repeatedly - three different seeds through the same sampler chain, the same post-processing applied to different images, a function passed into a loop. In the r/comfyui world this is the "why does ComfyUI not have functions" itch, and this is the scratch.

How it works

You feed it a CLOSURE (the output of a Function End) and optional parameters:

  • closure - required, the function object
  • param_0, param_1, … - dynamically added inputs in the order your Function Parameter nodes declared them
  • output - *, the function's return value, usable like any wire

Under the hood it's sneaky in a good way. When the pack's transform hook rewrites your workflow, the closure carries the function body as JSON. At call time, Call Function expands that body back into real graph nodes - each one given a node ID prefixed by the caller's unique ID - and substitutes the parameter and captured-value references with actual data. ComfyUI's own executor then runs the expanded graph as if you'd pasted the nodes in by hand.

Two consequences worth knowing:

  • Node IDs change per call, so ComfyUI's cache can't help here - every call re-runs. That's the price of "same function, different inputs."
  • Recursion works. Feed a closure into one of its own parameters and it can call itself. The pack guards against runaway recursion by measuring the call depth against COMFYUI_FUNCTIONAL_RECURSION_LIMIT (default 100), and throws a RecursionError if you blow past it. Always guard recursive calls with a termination condition - the README says this plainly, and it's right.

Troubleshooting

  • "Prompt has no outputs" - you defined a function but never wired a Call Function into anything that reaches an output node. Either call it or connect the closure output.
  • RecursionError / "infinite recursion detected" - your recursive call lacks a stop condition. Check the predicate, or raise the env var COMFYUI_FUNCTIONAL_RECURSION_LIMIT if you genuinely need deep recursion (rare).
  • If the function returns LIST values, make sure you're using the Basic Data Handling pack's LIST type, not ComfyUI's native Data List - the native list deadlocks the graph.

Installing it

Part of Duanyll/comfyui_functional. ComfyUI Manager: search "Duanyll/comfyui_functional", or:

cd ComfyUI/custom_nodes
git clone https://github.com/Duanyll/comfyui_functional
# restart ComfyUI

No pip deps, no models. This is the node you'll live in, so learn it first - everything else in the pack feeds it.

Categoryduanyll/functional

Inputs (2)

NameTypeDefaultDescription
closureCLOSURE
param_0opt*

Outputs (1)

NameTypeDescription
**