AT LoraLoader
An entire LoRA stack crammed into one text field
- model
- clip
- model
- clip
Chain four stock LoraLoader nodes together and your graph grows a staircase of identical boxes just to say "character at 0.8, style at 0.5, hands at 1.2." AT LoraLoader collapses that into one node with a slot per LoRA, each with its own weight and an on/off toggle - and it lets you drag LoRAs straight out of the pack's Loras sidebar onto the canvas to add them.
The odd part, and the thing to understand before you debug anything: the node's real input is a JSON string.
What stack_snapshot actually is
The node has exactly three inputs: model, clip, and stack_snapshot, a STRING defaulting to []. That string is the whole stack. Everything you see on the node - the rows, the weights, the toggles - is a frontend illusion drawn over it.
The frontend hides the raw text box and draws custom slot widgets over it. Add a slot, nudge a weight or hit a toggle and it rewrites the JSON in stack_snapshot; reload the workflow and it parses the string back to rebuild the rows. That's the same pattern rgthree's Power Lora Loader uses, and the code says so in a header comment. Good pattern - the workflow file stays one node instead of six.
The JSON looks like this, one object per LoRA:
[{"lora_name": "char.safetensors", "strength_model": 0.8, "strength_clip": 0.8, "enabled": true}]
Backend side, the entries are normalized (blank names dropped, backslashes turned into forward slashes, strength_clip defaulted to strength_model when it's missing), anything with enabled: false is filtered out, and the rest are applied in order through the stock nodes.LoraLoader().load_lora().
That last point matters: the maths is identical to chaining stock loaders by hand, CLIP patch included. No clever merging, no different weight behaviour - a UI win, not a quality win.
Inputs, outputs, and one thing it does not do
Wire model and clip in from your checkpoint loader; take model out to the sampler and clip out to your text encode. Two outputs, both patched in place.
Two practical notes on the settings:
Weight per entry, not per node. The familiar 0.5–0.8 guidance is SDXL-era advice and still holds on that lineage, but it doesn't generalize - LoRAs on newer architectures get run at 1.0 and above because dropping the weight costs likeness. Read the model page. Add them one at a time on a fixed seed, since stacking interactions are unpredictable; if a stack goes black or NaNs, reorder with the larger LoRA first.
Trigger words are recorded, not injected. Entries can carry trigger_words and preferred_trigger_phrase, which the sidebar writes in and the UI shows you. The node outputs only model and clip - no string output - so nothing is appended to your prompt for you. You still type the trigger word into the text encode. A missing trigger word is one of the four standard reasons a LoRA looks like it's doing nothing, along with base-model mismatch, weight too high, and wrong CLIP skip.
Installing it
Same pack, so same install. ComfyUI Manager, search AssetThingie, or:
cd ComfyUI/custom_nodes
git clone https://github.com/pogo-pedagog/asset-thingie
pip install -e asset-thingie/at-comfy
Restart afterwards. No model files, no heavyweight dependencies - aiohttp, httpx and pydantic, which your environment probably already has, plus a Python 3.11+ requirement. The install also gives you the three sidebar tabs (Browse, LoRAs, Checkpoints) and the CivitAI backend the drag-and-drop comes from.
Where people get burned
A malformed snapshot fails silently. If stack_snapshot isn't valid JSON, or isn't a list, the node returns your model and clip unchanged - no error, just LoRAs that quietly aren't there. If you hand-edit the string (you can - it's a real text widget), validate it first:
python -c "import json;d=json.load(open('stack.json'));print(type(d).__name__, len(d))"
Honestly, use the slot UI and leave the string alone.
The slots render badly and the toggles stick. This node draws its own widget with LiteGraph draw() calls - the same technique that made Power Lora Loader the poster child for ComfyUI's Nodes 2.0 rendering breakage when it landed in late 2025, with stacked text fields, properties that won't open and toggles that don't redraw until you resize the node. That issue was still open well into 2026. If the rows look wrong, switch back to the legacy canvas first; if you can't, the stack_snapshot JSON still works.
Nothing loads at all. The pack's __init__.py boots the at_comfy backend and re-raises on failure, so skipping the pip install -e .../at-comfy step takes the loader nodes down with it - look for Failed to initialize at_comfy backend in the console.
Duplicate entries. Adding a LoRA that's already in the stack is rejected with an "Already in stack" status instead of silently doubling the weights. Which also means a stale row you'd forgotten about is worth checking before you conclude the LoRA is broken.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | — | |
| clip | CLIP | — | |
| stack_snapshot | STRING | [] | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| model | MODEL | — |
| clip | CLIP | — |