FB Custom Function
Python, right inside your workflow graph
- i0
- i1
- i2
- i3
- i4
- i5
- i6
- i7
- o0
- o1
- o2
- o3
- o4
- o5
- o6
- o7
Every so often you hit a wall that no node covers: combine two numbers, reorder a filename, build a prompt from three separate strings with a bit of logic between them. FBCustomFunction ("FB Custom Function") is the escape hatch. You type Python straight into a node, it runs locally every time the queue fires, and whatever you return comes out the other side as outputs.
It doesn't call any API, needs no key, and runs nothing but the code you paste in. The name undersells it: this is a miniature Python executor parked inside the graph.
How it works
You get one big multiline func input where you write a function, eight optional inputs i0 through i7 that can carry any type, and eight outputs o0 through o7. The default template looks like this:
def func(*, i0, i1, i2, i3, i4, i5, i6, i7, **kwargs) -> dict:
return {
"o0": i0,
"o1": i1,
"o2": i2,
"o3": i3,
"o4": i4,
"o5": i5,
"o6": i6,
"o7": i7,
}
On each run the node exec()s your code into a fresh namespace, pulls out func, calls it with i0..i7 as keyword arguments, then reads o0..o7 from the dict it returns. Any key you don't include in the returned dict comes out as None. Unwired inputs are passed in as None too, so your function should be written to cope with that - or just ignore the ones you don't use.
The inputs that matter
- func - the only thing you actually write. Multiline, plain Python.
- i0..i7 - optional inputs, all wildcard type. ComfyUI won't check what you wire in, which is exactly what makes this node flexible and exactly what makes it dangerous.
That looseness cuts both ways. Since the outputs are also untyped *, the graph will happily let you wire a None into an IMAGE input and only blow up at runtime. Garbage in, garbage out - here there's no red wire to warn you first.
Where people get burned
- No imports at module level.
exec()runs your code in an empty namespace, soimport mathhas to live inside the function. If the whole body is the function, put your imports on the first line of it. - It's real arbitrary code execution. ComfyUI's own built-in Python node is gated off by default for exactly this reason. This one has no guard rail - it runs with your user privileges. That's fine when you wrote the code and the pack is a tiny dependency-free repo you can eyeball in ten minutes, but know what you're installing. The ecosystem has a genuine malware history for a reason.
- It re-runs every queue. Keep whatever's in here cheap; it's not the place for heavy lifting.
- Keep
**kwargsin the signature. The node may pass every input through, and dropping it means a crash when you add an input later.
Honestly? For most people this is a last-resort node. But when you need one small computation the dedicated FB string nodes can't express - a computed seed, prompt assembly with conditions, string arithmetic - the last resort is exactly the node you want.
Install
Same story as the rest of this pack: no dependencies, no models, nothing to download besides the repo itself.
cd ComfyUI/custom_nodes
git clone https://github.com/FredBill1/comfyui-fb-utils
Restart ComfyUI and the node appears under the FredBill1 category. You can also install it via ComfyUI Manager - search for comfyui-fb-utils. There's no requirements.txt and no pip step, because the entire pack is Python standard library. One warning: the repo's README is a single line, so treat the code as the documentation.
Inputs (9)
| Name | Type | Default | Description |
|---|---|---|---|
| func | STRING | def func(*, i0, i1, i2, i3, i4, i5, i6, i7, **kwargs) -> dict: return { "o0": i0, "o1": i1, "o2": i2, "o3": i3, "o4": i4, "o5": i5, "o6": i6, "o7": i7, } | — |
| i0opt | * | — | |
| i1opt | * | — | |
| i2opt | * | — | |
| i3opt | * | — | |
| i4opt | * | — | |
| i5opt | * | — | |
| i6opt | * | — | |
| i7opt | * | — |
Outputs (8)
| Name | Type | Description |
|---|---|---|
| o0 | * | — |
| o1 | * | — |
| o2 | * | — |
| o3 | * | — |
| o4 | * | — |
| o5 | * | — |
| o6 | * | — |
| o7 | * | — |