comfyui-tooling-nodes: Running ComfyUI as a Backend for External Tools
Nodes for using ComfyUI as a backend for external tools. Send and receive images directly without filesystem upload/download.
At a glance
- What is it?
- Acly's node pack replaces ComfyUI's filesystem image handoff with base64 prompts, WebSocket binary frames and an HTTP image cache. It is aimed at people wiring ComfyUI into Krita or their own client, not at people clicking through the default UI.
- Who is it for?
- Adopt it if you are building a client that talks to ComfyUI over its HTTP and WebSocket API and want to stop shuffling PNGs through the input and output directories. Skip it if you only use the ComfyUI web UI, since the nodes exist for programmatic callers and add nothing to a manual workflow.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 42 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.
Star history
- Acly/comfyui-tooling-nodes681 ★ · +9
| Repository | 2026-09-17 | 2026-11-14 |
|---|---|---|
| Acly/comfyui-tooling-nodes | 672 | 681 |
9 Stars in the last 58 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
The filesystem round trip this pack removes
ComfyUI exchanges images through the filesystem. A client that wants to process an image has to upload it, submit a prompt, poll for completion, then download the result from the output directory. The README frames this as a problem for external tools specifically: the multi-step process "invites a whole class of potential issues you might not want to deal with", and it notes that it is unclear when those files get cleaned up. That cleanup question is the real cost. Every integration built this way has to own a garbage-collection policy for files it did not create, in a directory it does not control.
The pack targets the other side of that boundary: tools like Krita, or any custom client that already speaks ComfyUI's API. The repository layout reflects this. Alongside nodes.py there is api.py for the HTTP extensions, krita.py, and a js/ directory, so the project ships both the server-side nodes and the client glue. If you are a user who opens ComfyUI in a browser and drags images in, none of this applies to you.
How images move: base64 in, WebSocket and HTTP out
There are two directions and two mechanisms for each.
Inbound, Load Image (Base64) takes a PNG embedded directly in the prompt as a base64 string and outputs an RGB image plus an alpha mask if the PNG has one. Load Mask (Base64) does the same for single-channel masks, taking the first channel of the PNG. Embedding the image in the prompt removes the upload step entirely, at the cost of a larger JSON payload.
Outbound, Send Image (WebSocket) pushes the result over the client's existing WebSocket connection. The README specifies the wire format precisely: for each image in a batch, one binary message consisting of two 32-bit big-endian integers with values 1 and 2, followed by the PNG bytes. A JSON message follows with type executed, the node ID, and an images array whose entries carry source websocket and content-type image/png. That explicit framing matters. A client that treats the socket as text-only will not see these frames.
The second path is the HTTP cache. Save Image to Cache stores output in RAM and emits a JSON message with source http and an image ID; the client then issues a GET to /api/etn/image/{id}. The README states this is typically faster than WebSocket, especially for large images, and that images are cached for a few minutes. The inbound mirror is Load Image from Cache, which reads an image previously PUT to the same endpoint. The README says the upload returns 201 for a new image and 200 if it was already cached, and that the caller picks the id as long as it does not clash. That is a real constraint: nothing in the described API allocates IDs for you.
Installing comfyui-tooling-nodes and a first API call
The README's installation section is the entry point. The package is a ComfyUI custom node pack, so it goes in the custom_nodes directory, and the only dependency listed in requirements.txt is optional: argostranslate, needed solely for the Translate Text node. The pyproject.toml declares version 3.3.0 and a py311 target, so a Python 3.11 environment matches what the project lints and formats against.
The repository is cloned into the custom node directory:
git clone https://github.com/Acly/comfyui-tooling-nodesAfter a restart the nodes are available. The README describes the HTTP image cache as the mechanism behind Load Image from Cache and Save Image to Cache: an image is uploaded with an HTTP PUT request to /api/etn/image/{id}, and the request returns 201 if the image was uploaded and 200 if it was already cached. JPEG or other formats also work, and the caller chooses an id that does not clash with other images.
A prompt built from Load Image from Cache with that id and a Save Image to Cache node will emit a JSON message over WebSocket when an image is ready, with an images entry whose source is http and whose id identifies the stored image. Downloading it means a GET request to /api/etn/image/{id} with that id. The README warns that images are cached for a few minutes, so retrieve them promptly rather than queueing the id for later.
Tiling without a fixed pipeline
The tile nodes take a deliberately narrow position. The README contrasts them with other tiling nodes that "provide a fixed pipeline": this pack only splits an image into tiles and merges them back, so a script can generate a separate workflow per tile with different prompts, regions and control inputs.
Create Tile Layout defines the parameters. min_tile_size is the minimum resolution per tile, and the README notes tiles may be larger so the image divides evenly. padding overlaps neighbours but is not applied at the image borders. blending controls how much of the padding band is used for the smooth transition, and it affects the masks generated from the layout. The tile count follows image_size // (min_tile_size + 2 * padding), so padding increases the count non-linearly rather than just softening seams.
Extract Image Tile and Extract Mask Tile pull out a region; indices are column-major, and the README points out tile 1 is usually below tile 0. Merge Image Tile blends a sampled tile back using padding and blending. Generate Tile Mask produces the coverage mask for a tile, white in the image area and black in the padding, with a smooth transition. The README notes this mask is used internally by Merge Image Tile but is also usable as input for Set Latent Noise Mask in upscale workflows.
The trade-off is honest: you get flexibility and pay for it in orchestration. Nothing here decides prompts, samplers or seeds per tile. If you want a single node that takes an image and returns an upscaled result, this is the wrong tool.
Region attention masking and what it replaces
The region nodes implement attention masking over an arbitrary number of image regions, so a text prompt applies only inside its masked area. The README draws a specific comparison: this is less "forceful" than condition masking but produces more natural compositions. That is the choice being made for you. If you need a region to obey a prompt strictly, condition masking is the more direct control.
The flow runs through a list. Background Region starts the list and takes a prompt but no mask; that prompt covers every area not claimed by another region. Define Region appends a region with a prompt and a mask, and the README states masks must match the image size or the latent, which is a factor of 8 smaller. List Region Masks outputs every mask in the list, which the README suggests for inspection, debugging or reusing the computed background mask. Regions Attention Mask patches the model to use the list, and it replaces the positive text conditioning passed to the sampler. The README is explicit that ControlNet and other conditioning can still be passed through.
The workflow files ship with the repository, so region_attention_mask.json and image_tiles.json are the reference implementations rather than the prose. Apply Mask to Image is the small utility that closes the loop, copying a mask into an image's alpha channel to produce an RGBA result.
Krita, IPAdapter and the alternatives
The most concrete alternative is not another node pack but the default ComfyUI workflow itself: upload to input, prompt, download from output. That path has no API contract to implement and no binary framing to parse, and for a human at a browser it is fine. The difference is that it makes the filesystem the interface, which is exactly the coupling this pack exists to remove.
For inpainting and regional work, the alternative to the region nodes is condition masking, which the README already positions as the stronger but less natural-looking option. For tiling, the alternative is a monolithic tiling node that owns the whole pipeline, which trades per-tile control for less scripting.
The Krita integration is the pack's clearest demonstration of intent, and the search terms around this project cluster there. The repository carries krita.py and a js/ directory, and the README's introduction names external tools as the audience. If you are evaluating this for a Krita workflow, the question is not whether the nodes exist but whether your Krita build and the plugin side match the API version in this repository.
Maintenance, licence and upgrade cost
The last push to the default branch was on 2026-08-19, and the repository is not archived. The declared version is 3.3.0 and the repository has no published GitHub releases, so versioning appears to move through the pyproject.toml field rather than tagged releases. There is no changelog in the top-level entries, which means an upgrade requires diffing nodes.py, api.py and the workflow JSON files yourself.
That matters more here than in a typical node pack, because the pack defines a wire protocol. The WebSocket binary framing (two big-endian integers, then PNG bytes), the /api/etn/image/{id} endpoint and its 201/200 responses, and the JSON message shapes are all contracts your client implements. A change to any of them breaks callers silently unless they validate. Pin the commit you deploy and read the diff before moving.
The licence is GPL-3.0, declared in pyproject.toml as a file reference to LICENSE. The practical consequence is that a client which links against or incorporates this code inherits copyleft obligations. Talking to it over HTTP and WebSocket from a separate program is a different situation from vendoring the Python into your own tool. That distinction is worth raising with whoever handles licensing for your product; this article is not legal advice.
One dependency note: requirements.txt lists argostranslate as optional and only for the Translate node, so an installation that skips translation does not need it.
Editorial conclusion
Adopt it if you are building a client that talks to ComfyUI over its HTTP and WebSocket API and want to stop shuffling PNGs through the input and output directories. Skip it if you only use the ComfyUI web UI, since the nodes exist for programmatic callers and add nothing to a manual workflow. Before committing, verify the two things the README leaves open: how long uploaded images actually stay in RAM, and whether your client can handle the binary WebSocket framing that Send Image (WebSocket) requires.
Frequently asked questions
What are nodes in ComfyUI, and what does comfyui-tooling-nodes add?
Nodes are the processing steps you wire together into a workflow. This pack adds nodes aimed at external tools, including base64 image and mask loaders, WebSocket and HTTP image senders, region attention masking, and image tiling.
Is there a custom node manager for ComfyUI that installs comfyui-tooling-nodes?
The README documents installation through the custom_nodes directory rather than a node manager, and the repository does not describe a manager integration. The only dependency listed in requirements.txt is argostranslate, and it is marked optional and needed solely for the Translate node.
How do I make a node for ComfyUI, and how does this pack structure its nodes?
This pack keeps node definitions in nodes.py, with separate modules for regions, tiles, translation and the HTTP API extensions in api.py. The pyproject.toml targets py311 and configures ruff and black at a line length of 100, which is the style the repository is written against.
Why can't I connect nodes in ComfyUI when using the region nodes?
The region nodes form a list: Background Region starts it, Define Region appends to it, and Regions Attention Mask consumes the whole list. Masks passed to Define Region must match the image size or the latent, which is a factor of 8 smaller, so a size mismatch is a likely cause of a connection that will not resolve.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/acly-comfyui-tooling-nodes)Star history chart for your README
[](https://hysenlabs.com/projects/acly-comfyui-tooling-nodes)Was this useful?