ComfyUI-OpenClaw
ComfyUI-OpenClaw is a security-first ComfyUI custom node pack that adds:
- LLM-assisted nodes (planner/refiner/vision/batch variants)
- A built-in extension UI (
OpenClawpanel) - A secure-by-default HTTP API for automation (webhooks, triggers, schedules, approvals, presets)
- And more exciting features being added continuously
This project is intentionally not a general-purpose “assistant platform” with broad remote execution surfaces. It is designed to make ComfyUI a reliable automation target with an explicit admin boundary and hardened defaults.
Security stance (how this project differs from convenience-first automation packs):
- Localhost-first defaults; remote access is opt-in
- Explicit Admin Token boundary for write actions
- Webhooks are deny-by-default until auth is configured
- Strict outbound SSRF policy (callbacks + custom LLM base URLs)
- Secrets are never stored in browser storage (optional server-side key store is local-only convenience)
Latest Updates - Click to expand
Sprint A: closes out with five concrete reliability and security improvements
- Configuration save/apply now returns explicit apply metadata, so callers can see what was actually applied, what requires restart, and which effective provider/model is active.
- The Settings update flow adds defensive guards against stale or partial state, reducing accidental overwrites.
- Provider/model precedence is now deterministic across save, test, and chat paths, and prevents model contamination when switching providers.
- In localhost convenience mode (no admin token configured), chat requests enforce same-origin CSRF protection: same-origin requests are allowed, cross-origin requests are denied.
- Model-list fetching now uses a bounded in-memory cache keyed by provider and base URL, with a 5-minute TTL and LRU eviction cap to improve responsiveness and stability.
Sprint B: ships security doctor diagnostics, registry quarantine gates, and constrained transforms defaults
- Added the Security Doctor surface (
GET /openclaw/security/doctor) for operator-focused security posture checks across endpoint exposure, token boundaries, SSRF posture, state-dir permissions, redaction drift, runtime mode, feature flags, and API key posture. - Added optional remote pack registry quarantine controls with explicit lifecycle states, SHA256 integrity verification, bounded local persistence, and per-entry audit trail; this path remains disabled by default and fail-closed.
- Added optional constrained transform execution with trusted-directory + integrity pinning, timeout and output-size caps, and bounded chain execution semantics; transforms remain disabled by default and mapping-only behavior remains intact unless explicitly enabled.
Settings contract, frontend graceful degradation, and provider drift governance
- Enforced a strict settings write contract with schema-coerced values and explicit unknown-key rejection, reducing save/apply regressions across ComfyUI variants.
- Hardened frontend behavior to degrade safely when optional routes or runtime capabilities are unavailable, with clearer recovery hints instead of brittle failures.
- Added provider alias/deprecation governance and normalization coverage to reduce preset drift as upstream model IDs and endpoint shapes evolve.
Mapping v1, job event stream, and operator doctor
- Added webhook mapping engine v1 with declarative field mapping + type coercion, enabling external payload normalization without custom adapter code paths.
- Added real-time job event stream support via SSE (
/openclaw/events/stream) with bounded buffering and polling fallback (/openclaw/events) for compatibility. - Added Operator Doctor diagnostics tooling for runtime/deployment checks (Python/Node environment, state-dir posture, and contract readiness signals).
Security doctor, registry quarantine, and constrained transforms
- Added Security Doctor diagnostics surface (
GET /openclaw/security/doctor) for operator-focused security posture checks and guarded remediation flow. - Added optional remote registry quarantine lifecycle controls with integrity verification, bounded local persistence, and explicit trust/audit gates.
- Added optional constrained transform execution with integrity pinning, timeout/output caps, and bounded chain semantics; default posture remains disabled/fail-closed.
Table of Contents
- Installation
- Quick Start (Minimal)
- Nodes
- Extension UI
- API Overview
- Templates
- Execution Budgets
- LLM Failover
- State Directory & Logs
- Troubleshooting
- Tests
- Updating
- Remote Control (Connector)
- Security
Installation
- ComfyUI-Manager: install as a custom node (recommended for most users), then restart ComfyUI.
- Git (manual):
git clone <repo> ComfyUI/custom_nodes/comfyui-openclaw
Alternative install options:
- Copy/clone this repository into your ComfyUI
custom_nodesfolder - Restart ComfyUI.
If the UI loads but endpoints return 404, ComfyUI likely did not load the Python part of the pack (see “Troubleshooting”).
Quick Start (Minimal)
Sprint A Reliability Highlights
Sprint A closes the M1 release gate with stronger config behavior and safer local convenience mode:
R53: config save/apply semantics are explicit inPUT /openclaw/configresponsesR54: frontend guards for stale/partial settings states reduce accidental overwrite riskR57: provider/model precedence is deterministic and stable across save/test/chat pathsS27:/openclaw/llm/chatenforces same-origin checks in localhost convenience modeR60:/openclaw/llm/modelsuses bounded in-memory caching (TTL + max entries)
1) Configure an LLM key (for Planner/Refiner/vision helpers)
Set at least one of:
OPENCLAW_LLM_API_KEY(generic)- Provider-specific keys from the provider catalog (preferred; see
services/providers/catalog.py)
Provider/model configuration can be set via env or /openclaw/config (admin boundary; localhost-only convenience if no Admin Token configured).
Notes:
- Recommended: set API keys via environment variables.
- Optional: for single-user localhost setups, you can store a provider API key from the Settings tab (“UI Key Store (Advanced)”).
- This writes to the server-side secret store (
{STATE_DIR}/secrets.json). - Environment variables always take priority over stored keys.
- This writes to the server-side secret store (
2) Configure webhook auth (required for /webhook*)
Webhooks are deny-by-default unless auth is configured:
OPENCLAW_WEBHOOK_AUTH_MODE=bearerandOPENCLAW_WEBHOOK_BEARER_TOKEN=...- or
OPENCLAW_WEBHOOK_AUTH_MODE=hmacandOPENCLAW_WEBHOOK_HMAC_SECRET=... - or
OPENCLAW_WEBHOOK_AUTH_MODE=bearer_or_hmacto accept either - optional replay protection:
OPENCLAW_WEBHOOK_REQUIRE_REPLAY_PROTECTION=1
3) Optional (recommended): set an Admin Token
Admin/write actions (save config, /llm/test, key store) are protected by the Admin Token:
- If
OPENCLAW_ADMIN_TOKEN(or legacyMOLTBOT_ADMIN_TOKEN) is set, clients must send it viaX-OpenClaw-Admin-Token. - If no admin token is configured, admin actions are allowed on localhost only (convenience mode). Do not use this mode on shared/public deployments.
Remote admin actions are denied by default. If you understand the risk and need remote administration, opt in explicitly:
OPENCLAW_ALLOW_REMOTE_ADMIN=1
Windows env var tips (PowerShell / CMD / portable .bat / Desktop)
- PowerShell (current session only):
$env:OPENCLAW_LLM_API_KEY="<YOUR_API_KEY>"$env:OPENCLAW_ADMIN_TOKEN="<YOUR_ADMIN_TOKEN>"
- PowerShell (persistent; takes effect in new shells):
setx OPENCLAW_LLM_API_KEY "<YOUR_API_KEY>"setx OPENCLAW_ADMIN_TOKEN "<YOUR_ADMIN_TOKEN>"
- CMD (current session only):
set OPENCLAW_LLM_API_KEY=<YOUR_API_KEY> - Portable
.batlaunchers: addset OPENCLAW_LLM_API_KEY=.../set OPENCLAW_ADMIN_TOKEN=...before launching ComfyUI. - ComfyUI Desktop: if env vars are not passed through reliably, prefer the Settings UI key store for localhost-only convenience, or set system-wide env vars.
Nodes
Nodes are exported as Moltbot* class names for compatibility, but appear as openclaw:* display names in ComfyUI:
openclaw: Prompt Planneropenclaw: Prompt Refineropenclaw: Image to Promptopenclaw: Batch Variants
See web/docs/ for node usage notes.
Extension UI
The frontend lives in web/ and is served by ComfyUI as an extension panel. It uses the backend routes below (preferring /api/openclaw/*).
API Overview
Base paths
Routes are registered to support both:
- New prefix:
/openclaw/* - Legacy prefix:
/moltbot/*
And both:
- Direct:
/openclaw/... - ComfyUI API shim:
/api/openclaw/...
Use /api/... from browsers and extension JS.
Observability (read-only)
GET /openclaw/health— pack status, key presence, and basic metricsGET /openclaw/logs/tail?n=50— log tail (supportstrace_id/prompt_idfilters)GET /openclaw/trace/{prompt_id}— trace timeline (redacted)GET /openclaw/capabilities— feature/capability probe for frontend compatibilityGET /openclaw/jobs— currently a stub (returns an empty list)
Access control:
- loopback is allowed
- remote access requires
OPENCLAW_OBSERVABILITY_TOKENviaX-OpenClaw-Obs-Token
LLM config (non-secret)
GET /openclaw/config— effective config + sources + provider catalog (observability-protected)PUT /openclaw/config— update non-secret config (admin boundary)POST /openclaw/llm/test— test connectivity (admin boundary)POST /openclaw/llm/chat— connector chat completion path (admin boundary)GET /openclaw/llm/models— fetch model list for selected provider/base URL
Notes:
- Queue submission uses
OPENCLAW_COMFYUI_URL(defaulthttp://127.0.0.1:8188). PUT /openclaw/confignow returns apply metadata so callers can reason about what actually took effect:apply.ok,apply.requires_restart,apply.applied_keysapply.effective_provider,apply.effective_model
- Provider/model precedence is strict:
- explicit request values > persisted config > provider defaults
- model is revalidated against provider when provider changes (prevents cross-provider contamination)
POST /openclaw/llm/chatin localhost convenience mode (no admin token configured):- allows same-origin loopback requests
- denies cross-origin requests with CSRF error
/openclaw/llm/modelscache behavior:- key:
(provider, base_url) - TTL: 5 minutes
- capacity: 16 entries (LRU eviction)
- key:
- Custom
base_urlis protected by SSRF policy:- built-in provider hosts are allowlisted by default
- allow additional exact hosts via
OPENCLAW_LLM_ALLOWED_HOSTS=host1,host2 - or opt in to any public host via
OPENCLAW_ALLOW_ANY_PUBLIC_LLM_HOST=1 OPENCLAW_ALLOW_INSECURE_BASE_URL=1disables SSRF blocking (not recommended)
Webhooks
POST /openclaw/webhook— authenticate + validate schema and return normalized payload (no queue submission)POST /openclaw/webhook/validate— dry-run render (no queue submission; includes render budgets + warnings)POST /openclaw/webhook/submit— full pipeline: auth → normalize → idempotency → render → submit to queue
Payload Mapping (F40):
- Submit arbitrary payloads (GitHub, Discord, etc.) by adding
X-Webhook-Mapping-Profile: github_push(ordiscord_message). - The internal engine maps fields to the canonical schema before validation.
Job Events (R71):
GET /openclaw/events/stream— SSE endpoint for real-time job lifecycle events (queued, running, completed, failed).GET /openclaw/events— JSON polling fallback.- Supports
Last-Event-IDheader to resume streams without data loss.
Request schema (minimal):
{
"version": 1,
"template_id": "portrait_v1",
"profile_id": "SDXL-v1",
"inputs": { "requirements": "..." },
"job_id": "optional",
"trace_id": "optional",
"callback": { "url": "https://example.com/callback" }
}
Auth headers:
- Bearer:
Authorization: Bearer <token> - HMAC:
X-OpenClaw-Signature: sha256=<hex>(legacy header:X-Moltbot-Signature)- optional replay protection:
X-OpenClaw-TimestampandX-OpenClaw-Nonce(legacyX-Moltbot-*)
- optional replay protection:
Callback allowlist:
OPENCLAW_CALLBACK_ALLOW_HOSTS=example.com,api.example.comOPENCLAW_CALLBACK_TIMEOUT_SEC=10OPENCLAW_CALLBACK_MAX_RETRIES=3
Triggers + approvals (admin)
POST /openclaw/triggers/fire— fire a template with optional approval gateGET /openclaw/approvalsGET /openclaw/approvals/{approval_id}POST /openclaw/approvals/{approval_id}/approve— can auto-executePOST /openclaw/approvals/{approval_id}/reject
Admin boundary:
OPENCLAW_ADMIN_TOKENviaX-OpenClaw-Admin-Token- strict localhost auth is enabled by default (
OPENCLAW_STRICT_LOCALHOST_AUTH=1)
Schedules (admin)
GET/POST /openclaw/schedulesGET/PUT/DELETE /openclaw/schedules/{schedule_id}POST /openclaw/schedules/{schedule_id}/togglePOST /openclaw/schedules/{schedule_id}/runGET /openclaw/schedules/{schedule_id}/runsGET /openclaw/runs
Presets (admin)
GET /openclaw/presetsandGET /openclaw/presets/{preset_id}:- public-read is allowed only when
OPENCLAW_PRESETS_PUBLIC_READ=1andOPENCLAW_STRICT_LOCALHOST_AUTH=0 - otherwise requires admin token
- public-read is allowed only when
POST/PUT/DELETE /openclaw/presets*always require admin token
Packs (admin)
GET /openclaw/packsPOST /openclaw/packs/import(multipart upload)GET /openclaw/packs/export/{name}/{version}DELETE /openclaw/packs/{name}/{version}
Packs are versioned zip bundles (templates/presets/profiles) with an integrity manifest (file hashes). Import/export is designed to be reproducible and hardened against common archive attacks (path traversal, zip bombs).
Operational notes:
- Packs are local-only by default (no auto-download).
- Packs management requires the Admin Token boundary (or localhost-only convenience mode).
- UI:
OpenClawpanel →Packstab. - Verification:
python -m unittest tests.test_packs_integrity -v
Bridge (sidecar; optional)
Sidecar bridge routes are registered under /openclaw/bridge/* and /moltbot/bridge/*.
Enablement and auth (device token model):
OPENCLAW_BRIDGE_ENABLED=1OPENCLAW_BRIDGE_DEVICE_TOKEN=...- optional allowlist:
OPENCLAW_BRIDGE_ALLOWED_DEVICE_IDS=dev1,dev2
Callback delivery allowlist (sidecar HTTP adapter):
OPENCLAW_BRIDGE_CALLBACK_HOST_ALLOWLIST=example.com
Templates
Templates live in data/templates/.
- Any
data/templates/<template_id>.jsonfile is runnable (template ID = filename stem). data/templates/manifest.jsonis optional metadata (e.g. defaults).- Rendering performs strict placeholder substitution:
- Only exact string values matching
{{key}}are replaced - Partial substitutions (e.g.
"foo {{bar}}") are intentionally not supported
- Only exact string values matching
For the full step-by-step guide (where to put exported workflow JSON, how to author manifest.json, how to verify /openclaw/templates, and how to use /run), see tests/TEST_SOP.md.
Basic /run usage (chat)
Free-text prompt mode (no key=value needed):
/run z 画面中央是一位年轻女性… seed=-1
The connector will map the free text into a prompt field using:
allowed_inputsif a single key is declared inmanifest.json, or- fallback order:
positive_prompt→prompt→text→positive→caption.
Key=value mode (explicit mapping):
/run z positive_prompt="a cat" seed=-1
Important:
- Ensure your workflow uses the same placeholder (e.g.,
"text": "{{positive_prompt}}"). seed=-1gives random seeds; a fixed seed reproduces outputs.
Execution Budgets
Queue submissions are protected by concurrency caps and render size budgets (services/execution_budgets.py).
Environment variables:
OPENCLAW_MAX_INFLIGHT_SUBMITS_TOTAL(default: 2)OPENCLAW_MAX_INFLIGHT_SUBMITS_WEBHOOK(default: 1)OPENCLAW_MAX_INFLIGHT_SUBMITS_TRIGGER(default: 1)OPENCLAW_MAX_INFLIGHT_SUBMITS_SCHEDULER(default: 1)OPENCLAW_MAX_INFLIGHT_SUBMITS_BRIDGE(default: 1)OPENCLAW_MAX_RENDERED_WORKFLOW_BYTES(default: 524288)
If budgets are exceeded, callers should expect 429 (concurrency) or 413 (oversized render).
LLM Failover
Failover is integrated into services/llm_client.py and controlled via runtime config:
OPENCLAW_FALLBACK_MODELS(CSV)OPENCLAW_FALLBACK_PROVIDERS(CSV)OPENCLAW_MAX_FAILOVER_CANDIDATES(int, 1–5)
State Directory & Logs
By default, state is stored in a platform user-data directory:
- Windows:
%LOCALAPPDATA%\\comfyui-openclaw\\ - macOS:
~/Library/Application Support/comfyui-openclaw/ - Linux:
~/.local/share/comfyui-openclaw/
Override:
OPENCLAW_STATE_DIR=/path/to/state
Logs:
openclaw.log(legacymoltbot.logis still supported)
Troubleshooting
UI shows “Backend Not Loaded” / endpoints return 404
This means ComfyUI did not load the Python part of the pack or route registration failed.
Steps:
-
Check ComfyUI startup logs for import errors while loading the custom node pack (search for
openclaw,Route registration failed,ModuleNotFoundError). -
Confirm the pack folder is directly under
custom_nodes/and contains__init__.py. -
Run the smoke import check inside the same Python environment ComfyUI uses:
python scripts/openclaw_smoke_import.py # or python scripts/openclaw_smoke_import.py --verbose -
Manually verify the endpoints used by the Settings tab:
GET /api/openclaw/healthGET /api/openclaw/configGET /api/openclaw/logs/tail?n=50
Notes:
- If your pack folder name is not
comfyui-openclaw, the smoke script may needOPENCLAW_PACK_IMPORT_NAME=your-folder-name. - If imports fail with a
services.*module error, check for name collisions with other custom nodes and prefer package-relative imports.
Operator Doctor (R72)
Run the built-in diagnostic tool to verify environment readiness (libraries, permissions, contract files):
python scripts/operator_doctor.py
# Or check JSON output:
python scripts/operator_doctor.py --json
Webhooks return 403 auth_not_configured
Set webhook auth env vars (see “Quick Start”) and restart ComfyUI.
Admin Token: server-side vs UI
OPENCLAW_ADMIN_TOKEN is a server-side environment variable.
The Settings UI can use an Admin Token for authenticated requests, but cannot set or persist the server token.
Full setup steps: see tests/TEST_SOP.md.
Tests
Run unit tests from the repo root:
python3 -m unittest discover -s tests -p "test_*.py"
Updating
- Git install:
git pullinsidecustom_nodes/comfyui-openclaw/, then restart ComfyUI. - ComfyUI-Manager install: update from Manager UI, then restart ComfyUI.
🎮 Remote Control (Connector)
OpenClaw includes a standalone Connector process that allows you to control your local instance securely via Telegram, Discord, LINE, or WhatsApp.
- Status & Queue: Check job progress remotely.
- Run Jobs: Submit templates via chat commands.
- Approvals: Approve/Reject paused workflows from your phone.
- Secure: Outbound-only for Telegram/Discord. LINE/WhatsApp require inbound HTTPS (webhook).
👉 See Setup Guide (docs/connector.md)
Security
Read SECURITY.md before exposing any endpoint beyond localhost. The project is designed to be secure-by-default (deny-by-default auth, SSRF protections, redaction, bounded outputs), but unsafe deployment can still create risk.
Disclaimer (Security & Liability)
This project is provided “as‑is” without warranty of any kind. You are solely responsible for:
- API keys / Admin tokens: creation, storage, rotation, and revocation
- Runtime configuration: environment variables, config files, UI settings
- Network exposure: tunnels, reverse proxies, public endpoints
- Data handling: logs, prompts, outputs, and any content generated or transmitted
Key Handling Guidance (all environments)
- Prefer environment variables for API keys and admin tokens.
- UI key storage (if enabled) is for local, single‑user setups only.
- Never commit secrets or embed them in versioned files.
- Rotate tokens regularly and after any suspected exposure.
Common Deployment Contexts (you must secure each)
- Local / single‑user: treat keys as secrets; avoid long‑term browser storage.
- LAN / shared machines: require admin tokens, restrict IPs, disable unsafe endpoints.
- Public / tunneled / reverse‑proxy: enforce strict allowlists, HTTPS, least‑privilege access.
- Desktop / portable / scripts: ensure secrets are not logged or persisted by launchers.
No Liability
The maintainers and contributors accept no responsibility for:
- Unauthorized access or misuse of your instance
- Loss of data, keys, or generated content
- Any direct or indirect damages resulting from use of this software
By using this project, you acknowledge and accept these terms.

