Prompt Preset
Keep your LLM prompts in a TOML file, not copy-pasted into nodes
- system_prompt
- user_prompt
- preset_meta_json
- preset_name
If you've wired an LLM into ComfyUI, you've hit the same wall: the system prompt lives as a giant multiline blob inside one node, and the moment you want a second variant - "summarize" vs "tag extractor" vs "harsh critic" - you're either duplicating nodes or pasting text around like it's 2005. Prompt Preset fixes that by keeping prompts in an external .toml file with {{placeholders}} for the parts that change, then feeding the resolved prompts straight into the pack's chat nodes.
It's the companion to Chat Once and Vision Chat Once: those send, this one prepares. And unlike the chat nodes, this is the one place in the pack with a real dependency - it uses tomli to parse TOML.
How it works
Your file is a list of presets, each with a label, a system template, and a user template:
version = 1
[presets.summary]
label = "Summary"
system = """
You are a helpful assistant.
Style: {{style}}
Instruction:
{{instruction}}
"""
user = """
Summarize the following:
{{input}}
"""
The node reads preset_path, grabs the preset by preset_id, and does simple {{name}} string substitution. Two variable sources: input_text (becomes the input variable, and wins any name collision) and variables_toml - a flat TOML block for the rest:
style = "concise"
instruction = "Use short paragraphs."
It resolves both system and user templates, normalizes line endings to LF, and outputs the finished system_prompt and user_prompt - wire those straight into Chat Once.
Inputs that matter
preset_path+preset_id- which file, which preset. Path must end in.toml.input_text- the changing content, mapped to{{input}}.variables_toml- flat key-value extras. Arrays, tables, and inline tables are errors here.keep_unresolved_variables(true) - leave unknown{{names}}in the output, or blank them out.fallback_user_prompt- used ifpreset_iddoesn't match or the preset has nouserfield.
Outputs: system_prompt, user_prompt, plus preset_meta_json (metadata, including which variables were resolved) and preset_name (the label, or the id if there's no label).
Install
Part of ComfyUi_zaknak_nodes - ComfyUI Manager, or git clone https://github.com/zaknak/ComfyUi_zaknak_nodes into ComfyUI/custom_nodes, then restart. tomli is the pack's one declared dependency; Manager will pull it if it's missing.
Troubleshooting
- "toml parse error" / "unsupported extension": only
.tomlfiles, UTF-8, withversion = 1and apresetstable at the root. JSON and YAML are right out - that's deliberate. - "variables_toml" errors: it accepts only flat key-value pairs - strings, ints, floats, bools, and multiline strings. An array (
tags = ["a","b"]) or a nested table is an explicit error, not a silent ignore. {{unknown}}survived into your prompt: that'skeep_unresolved_variablesworking as designed. Unresolved variables are logged to the ComfyUI console (with which template they appeared in), so check there before blaming the model for rambling.- Nothing resolves:
preset_idmust match a[presets.<id>]section exactly. If it doesn't andfallback_user_promptis empty, the node fails loudly - which beats sending a half-rendered prompt to your LLM.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| preset_path | STRING | — | |
| preset_id | STRING | — | |
| input_text | STRING | — | |
| variables_toml | STRING | — | |
| fallback_user_prompt | STRING | — | |
| keep_unresolved_variables | BOOLEAN | true | — |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| system_prompt | STRING | — |
| user_prompt | STRING | — |
| preset_meta_json | STRING | — |
| preset_name | STRING | — |