Widget To String Ovum
Read any node's widget as text — without hardcoding it twice
- any_input
- STRING
The moment you build a workflow with more than a handful of nodes, you'll want to reuse one node's widget value somewhere else - the seed you just rolled, the CFG, the steps - and you'll be tempted to type it in a second place. Then you change it in one spot and forget the other. Widget To String Ovum is the honest fix: it reads a widget from any node in your workflow and hands it back as a plain STRING you can pipe into a filename, a prompt builder, or a text node.
It lives in comfy-ovum, sfinktah's grab-bag utility pack, under the "Workflow Helpers" family. This is a re-implementation of the KJNodes "Widget To String" trick, and the pack's README claims a real advantage over the original: it works inside subgraphs, where KJNodes' version reportedly doesn't. Whether you need that specific escape hatch or not, it's a genuinely useful node - and it's free of any of the model-download baggage that makes some utility packs heavy.
How it works
At execution, the node looks at the serialized workflow graph and finds the target node three ways: by its numeric node id, by a manually-edited node_title, or by following the any_input link. Then it pulls the requested widget's value and stringifies it. It deliberately marks itself as always-changed, so it re-reads the widget on every run instead of caching - that's what makes it usable as a live "mirror" of another node's setting.
Three inputs do the real work:
id(STRING) - the target node's ID. See them by enabling node id display from the Manager badge menu.widget_name(STRING) - the widget to read, e.g.seedorsteps.return_all(BOOLEAN, default false) - instead of one widget, dump every input of the target node as"name: value, ...". Handy as a quick debug output.
Optional extras: node_title (only matches nodes whose title you actually edited - titles don't exist otherwise), any_input (any type - when id and title are blank, the node follows this link to identify its target), and allowed_float_decimals (default 2) which formats floats cleanly so a seed doesn't arrive as a 20-digit smear. Output is a single STRING.
Where you'd actually use it
Filename composition is the classic case: pull seed and steps from your KSampler and build a Save Image prefix like img_{seed}_{steps} without updating two widgets per run. Dynamic prompts and metadata reporting are the others. This is the kind of node that feels pointless until you wire it once, then you can't imagine the workflow without it.
Installing it
Through ComfyUI Manager, search comfy-ovum and hit install, then restart. Or the manual route:
cd ComfyUI/custom_nodes
git clone https://github.com/sfinktah/comfy-ovum
# restart ComfyUI
Dependencies are light. The pack's real requirements.txt lists requests, aiohttp, pillow, numpy, plus a few niche ones (pymediainfo, markdown-it-py, braceexpand, tomli-w) - no checkpoints, no model downloads, nothing VRAM-sized.
Gotchas
Node IDs are per-workflow: delete and re-add the target node and the ID changes, so the string id breaks. The README stresses that wiring any_input is what guarantees the target actually exists in the graph - it's the fallback that keeps you out of "why is my node returning nothing" territory. And missing widgets don't crash the run; you'll just get the literal string None, which is easy to spot and shrug at.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| id | STRING | — | |
| widget_name | STRING | — | |
| return_all | BOOLEAN | false | — |
| any_inputopt | * | — | |
| node_titleopt | STRING | — | |
| allowed_float_decimalsopt | INT | 20–10 | Number of decimal places to display for float values |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| STRING | STRING | — |