Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Configure and author rgthree-comfy nodes — Fast Groups Bypasser/Muter (group toggles), Power Lora Loader, Context/Context Big, Seed, Any Switch. Use when a workflow contains rgthree nodes, when asked to add stage/section toggles or an A/B switch, when stacking LoRAs, or when an rgthree node needs configuring. Covers the frontend-only nodes that are absent from /object_info and the properties-not-widgets configuration model.
.claude/skills/artokun-rgthree/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-06 | ✗→✓ | ▲ Improved | 98% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 194% | 0% |
| case-11 | ✗→✓ | ▲ Improved | 178% | 0% |
| case-13 | ✗→✓ | ▲ Improved | 109% | 0% |
| case-15 | ✗→✓ | ▲ Improved | 85% | 0% |
rgthree-comfy is one of the most widely installed packs, so its nodes turn up in a large share of community workflows. Three of its properties make it a recurring agent-failure mode — all three fail quietly enough to look like success.
1. Some rgthree nodes are FRONTEND-ONLY. They are registered by the pack's JS (registerCustomNodes()), have no Python class, and are therefore absent from /object_info by design. Checking /object_info and concluding "this node doesn't exist" is wrong. /object_info lists 24 rgthree backend types; the toggles are not among them.
2. They are configured through PROPERTIES, not widgets. matchTitle, toggleRestriction and sort live in node.properties (right-click → Properties), not in widgets. Use panel_set_property. panel_set_widget does not silently half-work — it refuses, with has no widget "matchTitle" (available: …) listing the widgets that do exist. That refusal is the fastest confirmation you are on the properties path; read it rather than retrying the write.
3. Fast Groups nodes take NO wiring and enumerate GROUPS by title. Leave the OPT_CONNECTION output unconnected. The node renders one toggle per matching group, so the groups must exist and be named before the node is useful.
panel_add_node will actually addThe panel authorizes every add against fresh /object_info and fails closed on a type it cannot find. Genuinely frontend-only types are exempt only via an explicit allowlist (FRONTEND_ONLY_NODE_TYPES), so the exemption covers seven rgthree types and no others:
| Frontend-only, panel_add_node WORKS | Frontend-only, panel_add_node REFUSES | |---|---| | Fast Groups Bypasser (rgthree) | Bookmark (rgthree) | | Fast Groups Muter (rgthree) | Mute / Bypass Relay (rgthree) | | Fast Bypasser (rgthree) | Mute / Bypass Repeater (rgthree) | | Fast Muter (rgthree) | Fast Actions Button (rgthree) | | Node Collector (rgthree) | Random Unmuter (rgthree) | | Label (rgthree) | | | Reroute (rgthree) | |
A refusal in the right-hand column is the guard working as designed, not a broken pack and not something to work around — the node has no backend def and is not on the allowlist. Say so and pick a different approach (the Bypasser/Muter cover almost every real toggle need). Everything with a Python class — Power Lora Loader, Context, Seed, Any Switch, Power Prompt, Image Comparer — is a normal backend node and adds normally.
Fast Groups Bypasser (rgthree) sets the nodes of a group to bypass (mode 4 — the node is skipped and its input passes through). Fast Groups Muter (rgthree) sets them to mute (mode 2 — the node does not execute and everything downstream dies). Prefer the Bypasser for toggling an optional stage inside a chain; reach for the Muter only when you genuinely want to stop a branch.
All of the following are node properties — set them with panel_set_property:
| Property | Values | Default | Notes | |---|---|---|---| | matchTitle | regex, case-insensitive | "" | Set this. Empty means every group in the workflow becomes a toggle. It is a real regex matched unanchored against the group title, so anchor it (^STAGE) or it matches mid-title. | | matchColors | comma-separated colors | "" | Alternative filter; pairs with a color convention. | | toggleRestriction | default / max one / always one | default | Both non-default values enforce mutual exclusion (they are matched on the substring " one"). Do NOT set either if the user may ever want all stages on in one queue. | | sort | position / alphanumeric / custom alphabet | position | The default means moving a group on the canvas silently reorders the toggles. alphanumeric is stable — prefer it. | | customSortAlphabet | string | "" | Only read when sort is custom alphabet. | | showNav | bool | true | Per-row jump-to-group arrow. | | showAllGraphs | bool | true | Include groups that live inside subgraphs. |
panel_set_property stores matchTitle (and matchColors / sort / …) and the reply from/to is truthful. Fast Groups nodes do not implement onPropertyChanged. The toggle list is rebuilt by rgthree's refreshWidgets() on a service tick (~8 ms after add, then every ~500 ms), and leftover-row removal increments the index while splicing — a 22-group list can stall at 13 with non-matching Enable … rows still present. A never-drawn node can also come back as widgets:{} — that means the list has not been built yet, not that there are no matching groups. panel_query_graph also keys widgets by name, and every toggle is named RGTHREE_TOGGLE_AND_NAV, so a built list collapses to one key.
Do this:
matchTitle immediately after panel_add_node (before the firstunfiltered refresh paints every group).
panel_query_graph {ids:[<id>], fields:'detail'}.widgets is empty or the canvas still shows Enable rows that donot match the regex, set matchTitle again. Do not delete and re-add the node — that is slower and still needs a second set.
panel_create_group per stage, with a prefixed title (STAGE 1 — …) so oneanchored regex selects exactly the intended set.
geometric: LiteGraph counts a node as a member when its centre falls inside the box, and the auto-fit box around your node_ids will happily swallow unrelated neighbours. When the live members differ from what you asked for, the result carries extra_node_ids, missing_node_ids and a warning alongside requested_node_ids — read them. (They appear only when you passed node_ids and something differs, so their absence is a real all-clear.)
A stray node here is not cosmetic: toggling one stage will disable part of another. To fix it, move the nodes apart (panel_edit_node, or panel_auto_layout) so the regions are contiguous, or set an explicit bounds with panel_edit_group — then re-check. panel_move_group does not help: by default it drags the contained nodes along with the box, so the same nodes stay inside it.
panel_add_node(class_type="Fast Groups Bypasser (rgthree)"). Leave its outputunwired. Add nodes one at a time, not as a parallel batch.
panel_set_property → matchTitle = ^STAGE, and sort = alphanumeric.Set them immediately after the add, then re-read the node. If widgets is empty or leftover Enable rows remain, set matchTitle again — do not delete and re-add.
panel_graph_outline — it tags nodes [bypass] / [mute].A backend node (present in /object_info) that stacks N LoRAs in one node. Each row is a widget named lora_1, lora_2, … whose value is a composite object {on: bool, lora: "subdir\\name.safetensors", strength: float, strengthTwo: float|null} (strengthTwo is the separate CLIP strength, null in the simple view). Rows are identified by the presence of a lora key, and the node's control widgets are appended after them, so do not index positionally — address the row by name.
Rows CAN be created programmatically. A freshly added Power Lora Loader has no lora_N widgets at all — the on-canvas "➕ Add Lora" button opens a chooser on a mouse event that no panel tool can press, but panel_set_widget does not need it: writing lora_1 (then lora_2, …) with a JSON object STRING creates the row and the reply carries created_widget: "lora_1". Create rows in order, one call each:
panel_set_widget(node_id=<id>, widget="lora_1",
value='{"on":true,"lora":"subdir/turbo.safetensors","strength":1,"strengthTwo":null}')
# A Windows subdir separator is a JSON escape — write it DOUBLED in the string:
# "lora":"Anima\\Tools\\turbo.safetensors"Re-read with panel_query_graph {ids:[<id>], fields:'detail'} to confirm the row landed. If you need a stack from scratch, create lora_1, then lora_2, and so on; do not assume a skipped number is the next row.
On an existing row, write ONE field with dotted sub-field addressing — it merges onto the current object and preserves every other field:
panel_set_widget(node_id=<id>, widget="lora_1.strength", value=0.8)
panel_set_widget(node_id=<id>, widget="lora_2.on", value=false)
panel_set_widget(node_id=<id>, widget="lora_1.lora", value="style/foo.safetensors")Writing a bare scalar to lora_1 itself is the trap: it would set one field and null the rest, so it is refused. To change several fields at once, pass a JSON object STRING (the value argument accepts only string/number/boolean, so a literal object fails tool validation before any write) — it is parsed and merged:
panel_set_widget(node_id=<id>, widget="lora_1", value='{"on":false,"strength":0.6}')Fields are schema-checked: on non-nullable boolean, strength non-nullable number, lora nullable string, strengthTwo nullable number. An unknown field name (a typo like lora_1.strenght) is refused, not silently created, and nested paths are unsupported.
Clearing a nullable field takes the JSON-string form, not a dotted write. The panel accepts null for lora / strengthTwo, but value is typed string | number | boolean, so a bare value=null is rejected by tool-arg validation before any write happens — the same schema limit as the whole-row case above. Clear it through the string:
panel_set_widget(node_id=<id>, widget="lora_1", value='{"lora":null}')Turning a LoRA off (lora_N.on = false) is usually safer than clearing it anyway.
MODEL/CLIP/VAE/conditioning into one RGTHREE_CONTEXT wire. These are NOT virtual wiring. Unlike Get/Set buses they are real executable backend nodes, so panel_strip_workflow and panel_flatten_workflow deliberately keep them — they run. Do not expect either tool to dissolve a Context chain. There is no hidden edge to resolve: every link is a real link, traceable with panel_query_graph. What a Context hides is which field a downstream node pulls out of the bundle, so read the chain node by node. (panel_slice_workflow still carves one pipeline out of a toggled monolith, and panel_strip_workflow still resolves any genuine Get/Set buses and Reroutes around it.)
control_after_generate widget oncreation, so do not try to write it; the widget is not there. Control is by SPECIAL SEED VALUES written to the seed widget instead: -1 randomize, -2 increment, -3 decrement. Any concrete seed is returned unchanged — 42 stays 42 every run — so to pin a run, write the number; to re-randomize, write -1. The frontend resolves a special value into a real seed before queueing and shows the result in a read-only last_seed widget, so a seed re-read after a run may not be the special value the user set (a fixed seed, however, is stable).
with bypassed branches. An empty Context counts as null, so an unfilled Context branch is skipped rather than selected.
everything downstream. Choosing the Muter where the Bypasser was meant breaks the chain rather than shortening it.
panel_graph_outline before a run — a stale toggle is a top cause of a wrongrender, and the outline marks [bypass] / [mute] explicitly.
Bookmark nodes respond to keypresses and are inert to agents.#1808 matchTitle rebuild: Fast Groups have no onPropertyChanged; refreshWidgets() leftover removal is removeWidget(index++) in fast_groups_muter.ts; first unfiltered tick is scheduled from addFastGroupNode in fast_groups_service.ts.| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 5,650 | 8,041 | +42% | 1 | 1 | 0% | 378 | 3,837 | +915% | 0 | 0 | — |
case-02 | fail→fail | 18,624 | 5,564 | -70% | 1 | 1 | 0% | 3,408 | 3,894 | +14% | 0 | 0 | — |
case-03 | fail→fail | 11,657 | 7,192 | -38% | 1 | 1 | 0% | 1,854 | 3,967 | +114% | 0 | 0 | — |
case-04 | pass→pass | 15,178 | 5,506 | -64% | 1 | 1 | 0% | 2,163 | 4,312 | +99% | 0 | 0 | — |
case-05 | pass→pass | 14,635 | 8,021 | -45% | 1 | 1 | 0% | 2,205 | 4,607 | +109% | 0 | 0 | — |
case-06 | fail→pass | 16,015 | 6,089 | -62% | 1 | 1 | 0% | 2,238 | 4,433 | +98% | 0 | 0 | — |
case-07 | pass→pass | 13,169 | 7,130 | -46% | 1 | 1 | 0% | 2,171 | 4,479 | +106% | 0 | 0 | — |
case-08 | pass→pass | 10,599 | 6,894 | -35% | 1 | 1 | 0% | 1,593 | 4,535 | +185% | 0 | 0 | — |
case-09 | pass→pass | 7,228 | 5,690 | -21% | 1 | 1 | 0% | 1,037 | 4,242 | +309% | 0 | 0 | — |
case-10 | fail→pass | 9,548 | 4,579 | -52% | 1 | 1 | 0% | 1,426 | 4,192 | +194% | 0 | 0 | — |
case-11 | fail→pass | 10,133 | 5,814 | -43% | 1 | 1 | 0% | 1,559 | 4,340 | +178% | 0 | 0 | — |
case-12 | pass→pass | 9,395 | 7,904 | -16% | 1 | 1 | 0% | 1,609 | 4,649 | +189% | 0 | 0 | — |
case-13 | fail→pass | 13,749 | 5,534 | -60% | 1 | 1 | 0% | 2,087 | 4,372 | +109% | 0 | 0 | — |
case-14 | pass→pass | 15,570 | 5,571 | -64% | 1 | 1 | 0% | 2,149 | 4,257 | +98% | 0 | 0 | — |
case-15 | fail→pass | 14,767 | 3,721 | -75% | 1 | 1 | 0% | 2,096 | 3,876 | +85% | 0 | 0 | — |
case-16 | fail→pass | 12,292 | 3,260 | -73% | 1 | 1 | 0% | 1,858 | 3,888 | +109% | 0 | 0 | — |
case-17 | fail→pass | 14,507 | 4,908 | -66% | 1 | 1 | 0% | 2,049 | 4,112 | +101% | 0 | 0 | — |
case-18 | pass→pass | 9,270 | 5,280 | -43% | 1 | 1 | 0% | 1,206 | 4,291 | +256% | 0 | 0 | — |
case-19 | pass→pass | 15,329 | 5,284 | -66% | 1 | 1 | 0% | 1,814 | 4,301 | +137% | 0 | 0 | — |
case-20 | fail→pass | 7,622 | 4,798 | -37% | 1 | 1 | 0% | 1,285 | 4,284 | +233% | 0 | 0 | — |
case-21 | pass→pass | 9,008 | 8,449 | -6% | 1 | 1 | 0% | 1,425 | 4,811 | +238% | 0 | 0 | — |
case-22 | pass→pass | 10,476 | 5,367 | -49% | 1 | 1 | 0% | 1,333 | 4,274 | +221% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 19 counted toward the lift figure. The other 3 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +36 percentage points is the difference between those two pass rates over the 19 comparable cases. 2 cases got worse with the skill loaded, and they are included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.