Nodes/ComfyUI-IntoTheLatent-Utils/ITL MOSS-Image Prompt Builder
ComfyUI Node

ITL MOSS-Image Prompt Builder

MOSS-Image Reads Coordinates, Not Adjectives — So Draw the Boxes

By Into-The-Latent·Created 2 months ago·Updated 3 days ago· 6
ITL MOSS-Image Prompt Builder
  • image
  • bboxes
  • prompt
  • preview
  • bboxes
  • width
  • height
◄width1024►
◄height1024►
◄caption►
◄meta►
◄canvasnone►
◄style_palette_data►
◄elements_data►
◄bg_brightness25►
◄import_modewhen empty►
◄output_formatcompact►
◄import_json►

Why you'd reach for this

MOSS-Image (OpenMOSS) doesn't want a paragraph. It wants a layout: a small JSON document with a summary - one caption for the whole scene - and a list of items, each with a label, its own caption, and a bounding box saying where that thing goes. Same bet Ideogram 4 made, and it's where regional control has been drifting: instead of masking cross-attention and hoping the girl on the left keeps her hair colour, the boxes are part of the caption schema the model was trained on.

ComfyUI core can already assemble that JSON from Create Bounding Boxes, which works right up until you want to move a box without typing four numbers. This node swaps in a canvas: drag a region, describe it in the inspector, layout out the other end. The editor comes from the pack's Ideogram 4 Prompt Builder, itself derived from Kijai's KJNodes (GPL-3.0, attribution kept) - if you've used that, you know the controls.

How the layout gets built

You draw boxes on a canvas sized to your width and height. Each region gets a label - object, character or text - plus a caption, and for text regions the verbatim string to render. Regions nest (drag a parent, children follow); groups from the Overview are editor-only and never exported.

On execute, every placed region becomes an item. Boxes convert to absolute pixels measured from the canvas centre, [ymin, xmin, ymax, xmax], edges floor/ceil'd so sub-pixel drift doesn't creep in - and a region too thin to survive rounding is dropped, because MOSS rejects zero-area boxes. The output carries bbox_coord_space: "abs_centralized" and bbox_format: "yxyx". Place nothing and you get the plain summary.caption string instead.

There's a per-region weight in the inspector (Weak << 0.5, Normal = 1, Strong > 1.25, Very strong >> 1.5). Anything but Normal wraps that caption as (caption:1.25) and expects KJNodes' MOSS-Image Prompt Weight downstream - without it, brackets reach the model as literal punctuation. It also shifts the whole image, not just the box, so stay at or under 1.5; beyond that objects wander out of their squares.

The inputs that matter

  • width / height - the bboxes are measured in these. MOSS-Image wants multiples of 16, default 1024×1024.
  • caption - the scene and style, summary.caption. This is your entire prompt when you place no regions, so write it even if you box everything up.
  • import_mode - when empty (default) lets a wired import_json seed the editor once and then hands control to your edits; always keeps the wired JSON authoritative.

meta (comma-separated medium/genre tags) and canvas (single / multi_panel / collage) are genuinely useful summary fields. The rest: image shows a reference behind the canvas, import_json takes a MOSS layout or an Ideogram 4 caption and converts it, bboxes seeds regions from wired pixel boxes. style_palette_data, elements_data, bg_brightness and output_format are editor-managed - leave them alone.

Outputs: prompt (to your MOSS-Image text encode), preview (a rendered overlay - send it to PreviewImage and check placement before queueing), bboxes (pixel-space {x, y, width, height} for SAM3 or crop nodes), and width / height.

Wire width and height into the latent. Actually.

The prompt carries no canvas size, so those bboxes are meaningless unless the sampler generates at exactly the node's width × height. Wire the width/height outputs into your empty-latent node, or drive both from the pack's ITL Resolution Selector. Change the latent resolution and forget the builder, and your carefully placed title lands off-canvas while the JSON looks perfectly fine.

Install

Same pack for both wizards and the builder. In ComfyUI Manager search the pack title, or:

cd ComfyUI/custom_nodes
git clone https://github.com/Into-The-Latent/ComfyUI-IntoTheLatent-Utils

Then install the requirements with ComfyUI's Python (Manager does this for you): pip install -r requirements.txt. You need none of transformers / librosa / soundfile / huggingface_hub for a prompt builder, but the pack imports soundfile at module load for its Breeze TTS nodes - so a missing one takes the whole pack down and these nodes never show up in the menu. That's the usual "Manager says it's installed but I can't find the node" story: read the startup console instead of trusting the Manager list. The pack also replaces the author's older ComfyUI-AI2Go-Utils (AI2Go* → ITL* IDs), so old workflows need both installed.

Common issues

The output is plain prose, not JSON. No placed regions. An unplaced region is deliberately not exported, and the Overview marks it - MOSS needs a bbox.

Weights do nothing. Wire prompt into KJNodes' MOSS-Image Prompt Weight; the editor warns when it isn't connected.

Converting from Ideogram 4. Point the Ideogram builder's prompt at this import_json with import_mode = always, but leave the Ideogram node's absolute pixels and xy order toggles at defaults - the caption JSON carries no marker for them, so the converter assumes the 0–1000 yx grid.

CategoryInto The Latent/text

Inputs (13)

NameTypeDefaultDescription
widthINT102464–16384Generation width in pixels — the bboxes are measured in it. MOSS-Image needs multiples of 16.
heightINT102464–16384Generation height in pixels — the bboxes are measured in it. MOSS-Image needs multiples of 16.
captionSTRINGsummary.caption: the whole scene and style. Used as the plain prompt when no region is placed.
metaSTRINGsummary.meta: comma/newline-separated medium or genre tags (blank = omitted).
canvasCOMBOnonesummary.canvas: single, multi_panel or collage ('none' = omitted).
style_palette_dataSTRINGSerialized summary palette from the editor (managed by the node UI).
elements_dataSTRINGSerialized regions from the editor (managed by the node UI).
bg_brightnessINT250–100Background image brightness % (managed by the node UI slider).
import_modeCOMBOwhen emptyHow a wired import_json is used: 'when empty' only seeds the editor while it has no regions (then the editor wins, so you can edit); 'always' makes the wired JSON authoritative so its changes always propagate to the output.
output_formatSTRINGcompactOutput JSON formatting (set via the editor toolbar): 'compact' (default, one line, what MOSS-Image reads) or 'pretty' (indented, for readability).
imageoptIMAGEOptional reference image shown as the editor background (and behind the preview).
import_jsonoptSTRINGOptional: a MOSS-Image layout or Ideogram 4 caption JSON. When connected, it loads into the editor and drives the output per 'import_mode'.
bboxesoptBOUNDING_BOX[object Object]Optional pixel-space boxes ({x, y, width, height}) used to seed the editor's regions when it has none. Ignored once regions exist.

Outputs (5)

NameTypeDescription
promptSTRING—
previewIMAGE—
bboxesBOUNDING_BOX—
widthINT—
heightINT—