Prompt Variable Substitutor
This node wants @placeholders, not {placeholders}
- prompt
- json_variables
If you google this node, the first thing you'll hit is the README, which says it swaps {key} placeholders. It doesn't. The code that actually ships swaps @key placeholders. That mismatch is the single most useful fact about the Prompt Variable Substitutor, and it's the kind of thing that costs you an afternoon before you notice your prompt never changes.
Here's the honest job description: you give it a prompt template and a blob of key='value' pairs, and it pastes the values into the template. That's the whole thing - no API, no model, no embedding. It exists so you can drive batch variation from one string instead of rebuilding graph nodes. It's part of the prompt/util_pack family, and it's designed to sit at the end of the chain: extract or build your variables upstream, substitute them here, and feed the finished prompt into whatever your checkpoint uses for positive conditioning.
How it actually works
The node reads variables as lines of key='value' pairs (single quotes - not double), parses them with a regex, and lowercases every key. Then it runs a case-insensitive replace of @key across your template. Because the substitution is case-insensitive, @expression and @EXPRESSION both match a key parsed as expression - handy, but it also means the key you get back in the JSON output is always lowercase, so don't go hunting for a key you wrote in CamelCase.
The second output, json_variables, is just a pretty-printed JSON dump of the parsed key/value map. It's genuinely useful if you're piping the same variables into a filename or a logging node - you can see exactly what the model was built from.
The inputs that matter
prompt_template(multiline) - your prompt with@keyplaceholders scattered through it.A @expression portrait, @lighting lightingis the shape you want.variables(multiline) - onekey='value'per line. The parser tolerates commas inside the quoted value, which is the difference between this and a naivesplit('=').
Outputs: prompt (the filled-in string) and json_variables.
Where people get burned
Three traps, all straight from the source:
- Empty input means empty output. If
variablescontains nokey='value'match at all, the node returns a blank prompt - not your template untouched. Wire it up with an empty variables string and you'll generate a bunch of images from an empty prompt before you notice. - Single quotes only.
seed="123"with double quotes matches nothing. The author's parser only knows'. - Keys are lowercased silently.
seed=123in the variables becomes@seedin your template. That's predictable once you know it.
Installation
It ships in a four-node pack with no dependencies beyond Python's standard library - no requirements.txt, no model downloads, works with any checkpoint (SDXL, Flux, Wan, you name it).
cd ComfyUI/custom_nodes
git clone https://github.com/fmartinellidev/ComfyUI-Prompt_util_pack
Restart ComfyUI, or install via ComfyUI Manager by searching "Prompt_util_pack". One note: the README has drifted from the code - the {key} syntax it documents doesn't exist. Trust the node's own behavior, not the docs.
In the pack's intended workflow, this is the last stop before the sampler: Prompt Snippet Extractor hands you a caption, Prompt Hidden Processor resolves the [[...]] variation blocks, and the Substitutor fills in the @key values. It's simple, and after the placeholder-syntax gotcha, it's predictable.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| prompt_template | STRING | — | |
| variables | STRING | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| prompt | STRING | — |
| json_variables | STRING | — |