Nodes/ComfyUI-Pi-LLM/Pi LLM Text
ComfyUI Node

Pi LLM Text

The cloud LLM that borrows a CLI instead of holding your key

By felixowens·Created 2 months ago·Updated 2 months ago· 0
Pi LLM Text
  • image
  • text
system_instructionYou are a helpful assistant. Return only the requested text.
model_nameminimax/MiniMax-M3
prompt
response_modeuse_saved_text_if_present
cache_modeuse_cache_or_generate
saved_response
seed0
timeout_seconds120
run_every_queuefalse
connected_text

It's a cloud LLM that keeps its key out of ComfyUI

Most LLM-in-the-graph nodes either run a local GGUF model on your card or take an API key straight into a node field. Pi LLM Text does neither. It shells out to Pi - the terminal coding agent from pi.dev (@earendil-works/pi-coding-agent) - in print mode, and returns whatever Pi's underlying model wrote as a plain ComfyUI STRING. Your API key or provider login lives in Pi's own config, not in the workflow. That's a genuinely nice property in a category where nodes love to swallow credentials: this one never sees yours.

The name is doing honest work, too: it does call Pi, just not through an API of its own. Pi is a separate program that already talks to a model provider, and this node drives it from the graph.

Why reach for it? A language model bolted into the graph is the standard way to turn a rough idea into a structured, model-appropriate prompt without fighting a blank text box. The usual tradeoff is local GGUF - free, uncensored, but eats VRAM - versus an API node - no VRAM, but costs per call and holds your key. Pi LLM Text sits awkwardly but usefully between: zero VRAM, no key in ComfyUI, but you pay per call through Pi's providers and everything leaves the machine. Fine for structured prompt writing and caption-ish text; don't route sensitive reference images through it.

How it works

The node builds a Pi command and runs it as a subprocess:

pi -p --no-tools --no-context-files --no-session \
  --system-prompt "..." --model "minimax/MiniMax-M3" "...prompt..."

-p is print mode - stdout only, no chat UI. --no-tools --no-context-files --no-session deliberately cripple Pi so it behaves like a plain text/image LLM call and can't touch your files or open a session. That's a safety call, and a good one: this is a prompt-writing node, not an agent.

Connect an IMAGE and the node converts each frame to a temporary PNG, passing it as @/tmp/.../image-0.png before the prompt - use a vision-capable model from the dropdown for that. The prompt text itself is prompt plus optional connected_text, joined with a blank line.

There's also a deterministic local cache: the response lands in cache/<sha256>.txt inside the pack folder, keyed by system instruction, model, prompt, image digests, and seed. Same inputs, same seed → same text, no second API call.

The inputs that matter

You mostly set three things: system_instruction (how the model should behave - the default already says "return only the requested text"), prompt (what you want it to produce, or a wired-in STRING), and model_name (a 61-entry static dropdown, default minimax/MiniMax-M3, plus OpenRouter Grok/Kimi/GLM/Gemini options). That list was generated from the author's own machine, so if your Pi can't reach a model in the dropdown you'll be editing models.py.

The rest is cache control, and it matters more than it looks:

  • response_mode - use_saved_text_if_present (default) uses saved_response when you've pasted text into it; use_saved_text always uses it; call_pi always calls.
  • cache_mode - use_cache_or_generate (default) serves the cache when present, refresh_cache forces a new call and overwrites, cache_only errors if missing, disable_cache never reads or writes.
  • seed - part of the cache key, so bumping it forces a new response for the same prompt. Note it's not passed to Pi as a sampling seed.
  • run_every_queue - disables ComfyUI's node cache so it fires every run.

The single output is text (STRING). Wire it into a CLIP Text Encode, or through the pack's extractor node first to strip any wrapper fluff the model adds.

Install

Pi is the real dependency. The pack itself is pure Python with no requirements file - it leans on the numpy/Pillow that ship inside ComfyUI. Install Pi first:

npm install -g --ignore-scripts @earendil-works/pi-coding-agent
pi /login   # or set provider API keys in Pi's config

Verify it works outside ComfyUI:

pi -p --no-tools --no-context-files --no-session "Say hello in five words."

Then, from your ComfyUI directory:

cd custom_nodes
git clone https://github.com/felixowens/ComfyUI-Pi-LLM.git

Restart ComfyUI and the nodes appear under the Pi category. ComfyUI Manager works too - search "ComfyUI-Pi-LLM".

Where people get burned

The classic failure is pi not being on the PATH the ComfyUI process sees - you'll get the node's "Could not find the pi executable" error. Windows users running ComfyUI from a desktop shortcut or service hit this most; the fix is a symlink into a common path (sudo ln -s $(which pi) /usr/local/bin/pi on Linux/macOS). After that: timeouts (default timeout_seconds is 120, and a long prompt or slow model will hit it), authentication errors raised from Pi itself, and the quiet surprise that reruns return the cached answer until you change the seed or cache_mode.

And the general caution applies - this is a network-calling node in a category that has shipped malware before. It's open source and tiny, so read it once before trusting it. Pi itself isn't a name the wider ComfyUI community talks about yet, and this pack is new; expect rough edges rather than a polished ecosystem.

CategoryPi

Inputs (11)

NameTypeDefaultDescription
system_instructionSTRINGYou are a helpful assistant. Return only the requested text.
model_nameCOMBOminimax/MiniMax-M361 options: minimax/MiniMax-M3, minimax/MiniMax-M2.7, minimax/MiniMax-M2.7-highspeed, anthropic/claude-3-5-sonnet-20240620, anthropic/claude-3-5-sonnet-20241022, anthropic/claude-3-7-sonnet-20250219, +55
promptSTRING
response_modeCOMBOuse_saved_text_if_present3 options: use_saved_text_if_present, call_pi, use_saved_text
cache_modeCOMBOuse_cache_or_generate4 options: use_cache_or_generate, refresh_cache, cache_only, disable_cache
saved_responseSTRING
seedINT00–18446744073709550000
timeout_secondsINT1201–3600
run_every_queueBOOLEANfalse
connected_textoptSTRING
imageoptIMAGE

Outputs (1)

NameTypeDescription
textSTRING