CMK InstantID Boundary
The node that exists so InstantID doesn't run twice
- MODEL
- PROCESS
- SAMPLED
- LOG
- diagnostic
- MODEL
- PROCESS
- SAMPLED
- LOG
- diagnostic
An InstantID pass on SDXL is one of the more expensive things you can ask a graph to do: load a face analysis model, pull ArcFace identity embeddings, patch cross-attention and run a keypoint ControlNet alongside the sampler. Doing it once is fine. Doing it twice because ComfyUI resolved two subgraph outputs separately is the kind of thing that makes people quit ComfyUI.
CMK InstantID Boundary is the fix. It computes nothing. It takes five values and gives back the same five.
Why a do-nothing node is real engineering
The source docstring says it plainly: global subgraph outputs are resolved independently, so without a common non-lazy consumer, downstream requests for MODEL, PROCESS, SAMPLED and LOG can reopen the expensive InstantID sampler after its preview has already finished. You watch the preview appear, then the progress bar starts over.
The boundary forces one materialization of the whole InstantID result set, and then serves everything from cache.
Inputs and outputs
Same five names on both sides - MODEL, PROCESS, SAMPLED, LOG, diagnostic - with matching CMK pipe types (CMK_MODEL_PIPE, CMK_PROCESS_SDXL, CMK_SAMPLED_PIPE, CMK_LOG_PIPE, CMK_DIAGNOSTIC).
They're all optional, and all declared lazy. That's the mechanism, not sloppiness: a lazy input is only pulled when the node asks for it, and this node asks conditionally. On every evaluation it resets the per-prompt cache, derives a cache key from the current prompt and its own node id, then either
- returns nothing to pull because that key is already cached - you'll see
[CMK InstantID Boundary] HIT <key>in the console, or - requests whichever of the five inputs are still
Noneso they get computed.
If one of them comes back empty anyway, it stops with "CMK InstantID Boundary is missing a materialized input" rather than passing a half-result downstream. When it does build a fresh result, it stamps the PROCESS pipe with the stage key so downstream nodes know which revision they're holding.
Install
cd ComfyUI
git clone https://github.com/CMKFlow/cmk_nodes.git custom_nodes/cmk_nodes
python3 custom_nodes/cmk_nodes/scripts/install_cmk_requirements.py
Manager route: search CMK Flow (registry cmk-flow, by CMKFlow), install, restart. The manual route needs the installer script - CMK's requirements (ultralytics, onnxruntime, insightface, segment-anything, nudenet, opencv-python) do not install themselves from a clone. Enable Vue Nodes / Nodes 2.0; CMK warns at startup when it's off, and these developer nodes lean on the newer frontend.
Model weights are deliberately not shipped with the Python package. Run the resource check to see what the reference workflows expect:
python3 custom_nodes/cmk_nodes/scripts/check_cmk_resources.py --models-root "/path/to/ComfyUI-Shared"
For InstantID specifically it can fetch the adapter and the antelopev2/kontrolnet pieces:
python3 custom_nodes/cmk_nodes/scripts/check_cmk_resources.py \
--install instantid-adapter --target-root "/path/to/ComfyUI-Shared"
Should you ever place one?
No, and that's the point. You'll find it inside the shipped CMK Flow · 15 InstantID-Sampler SDXL subgraph. It's marked DEV_ONLY in the source, so it may not even show up in your node search depending on your developer settings.
Two practical notes. First, don't delete it while tidying a subgraph - the expensive pass can come back. Second, the cache is a session cache under ComfyUI/temp/cmk/, cleared by a ComfyUI restart; a first run after a restart legitimately shows MISS → STORED. If a node downstream complains that a pipe is missing, look at the boundary before you look at the sampler: it's the node that decides whether anything gets materialized at all.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| MODELopt | CMK_MODEL_PIPE | — | |
| PROCESSopt | CMK_PROCESS_SDXL | — | |
| SAMPLEDopt | CMK_SAMPLED_PIPE | — | |
| LOGopt | CMK_LOG_PIPE | — | |
| diagnosticopt | CMK_DIAGNOSTIC | — |
Outputs (5)
| Name | Type | Description |
|---|---|---|
| MODEL | CMK_MODEL_PIPE | — |
| PROCESS | CMK_PROCESS_SDXL | — |
| SAMPLED | CMK_SAMPLED_PIPE | — |
| LOG | CMK_LOG_PIPE | — |
| diagnostic | CMK_DIAGNOSTIC | — |