Attribute
The Attribute node is the contract you hand an LLM before it writes anything
- attributes_in
- attributes
One variable, one node, zero API calls
The Attribute node from the ComfyUI Structured Outputs pack doesn't call any API, doesn't need a key, doesn't touch the network. It's the boring-but-essential first step: you tell the LLM what you want it to return, one variable at a time.
Think of it as declaring a single field of a schema. Want gpt-4o to tell you the background of an image? One Attribute node. Want it to also decide whether the image is cool, the style, and the text it shows? Add three more and chain them. Each node is a Lego brick, and the whole pack is the shape they build.
It exists because "describe the image" is not an answer you can wire into a prompt template. {foreground} has to mean something concrete to both the LLM and to your workflow, and this node is how you make it concrete.
How it works
Under the hood each Attribute node builds a tiny pydantic model - a key (your name) plus a typed value field. When you wire several together via the attributes_in input, they concatenate into one growing list that gets handed to the Structured Output node. The type you pick (str, int, float, bool) becomes the actual Python type the model is constrained to, and if you fill in options, the value is further restricted to that exact list of allowed choices.
The inputs that matter
Only two are required, and one of them barely counts:
- name - the variable name, e.g.
foregroundoris_cool. This is what you'll reference later as{foreground}. - attribute_type - one of
str,int,float,bool. Keep it honest: aboolfor "is the image cool", astrfor "what does the text say". - description - optional but don't skip it. This is the author's own framing and it's the real steering wheel. The LLM reads your description to decide what to extract, so "Detailed description of the background" gets you better results than a blank field.
- example - an optional example value shown to the model.
- options - a comma-separated list (
photograph, painting, render) that pins the value to a fixed set. Great for style choices, dangerous if you forget a valid one.
The output is attributes (type ATTRIBUTE, a list). Wire it into the attributes_in input of the next Attribute node to chain, or straight into the Structured Output node.
Installing it
This node ships with the whole pack, so you get it via the standard route:
cd ComfyUI/custom_nodes
git clone https://github.com/tigeryy2/comfyui-structured-outputs
or search "ComfyUI Structured Outputs" in ComfyUI Manager and click install. Then restart ComfyUI. For the Attribute node alone you need nothing else - no .env, no API key, no model download. That changes the moment you add the Structured Output node, which needs an OpenAI key, but this node doesn't.
Where people get burned
Two things, both small:
- Keep the name a clean identifier - no spaces, no weird characters. It's used as a Python keyword and later as a
{placeholder}in the Attribute to Text node's format string, and both choke on a name like "the background".backgroundworks; "the background" breaks. - An empty name is a hard error - the node logs "Attribute name cannot be empty" and refuses to validate. It's the only validation it does, which tells you the name is the thing it cares about.
The real limitation is that you only get four scalar types. If you need a list, a nested object, or a free-form paragraph as a single value, this pack's schema language won't stretch that far - you'd be looking at a heavier LLM suite for that.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| name | STRING | — | |
| attribute_type | COMBO | 4 options: str, int, float, bool | |
| attributes_inopt | ATTRIBUTE | — | |
| descriptionopt | STRING | — | |
| exampleopt | STRING | — | |
| optionsopt | STRING | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| attributes | ATTRIBUTE | — |