TypeScript SDK for interacting with the ComfyUI API – focused on workflow construction, prompt execution orchestration, multi-instance scheduling and extension integration.
- Fully typed TypeScript surface with progressive output typing
- High-level
WorkflowAPI – tweak existing JSON workflows with minimal boilerplate - Low-level
PromptBuilder– programmatic graph construction with validation - WebSocket events – progress, preview, output, completion with reconnection
- Multi-instance pooling –
WorkflowPoolwith smart failover & health checks (v1.4.1+) - Modular features –
api.ext.*namespaces (queue, history, system, file, etc.) - Authentication – basic, bearer token, custom headers
- Image attachments – upload files directly with workflow submissions
- Preview metadata – rich preview frames with metadata support
- Auto seed substitution –
seed: -1randomized automatically - API node support – compatible with custom/paid API nodes (Comfy.org)
Requires Node.js >= 22. Works with Bun.
npm install comfyui-nodeimport{ComfyApi,Workflow}from'comfyui-node';importBaseWorkflowfrom'./example-txt2img-workflow.json';constapi=awaitnewComfyApi('http://127.0.0.1:8188').ready();constwf=Workflow.from(BaseWorkflow).set('6.inputs.text','A dramatic cinematic landscape').output('images:9');constjob=awaitapi.run(wf,{autoDestroy: true});job.on('progress_pct',p=>console.log(`${p}%`));constresult=awaitjob.done();for(constimgof(result.images?.images||[])){console.log(api.ext.file.getPathImage(img));}- Getting Started Guide – Installation, quick start, core concepts, cheat sheet
- Workflow Guide – Complete high-level Workflow API tutorial with progressive typing
- PromptBuilder Guide – Lower-level graph construction, validation, serialization
- WorkflowPool Documentation – Production-ready pooling with health checks, profiling, and timeout protection
- Event-Based Logging – Guide to the new event-based logging system (v1.6.7+)
- Connection Stability Guide – WebSocket health check implementation details
- Hash-Based Routing Guide – Workflow-level failure tracking and intelligent failover
- Profiling Guide – Automatic per-node performance profiling (v1.5.0+)
- Execution Timeout Guide – Timeout protection for stuck servers and nodes (v1.5.0+)
- Advanced Usage – Authentication, events, preview metadata, API nodes, image attachments
- API Features – Modular
api.ext.*namespaces (queue, file, system, etc.)
- Troubleshooting – Common issues, error types, testing, diagnostics
- Migration Guide – Upgrading from <1.0 to 1.0+ with complete API mappings
Use Workflow for tweaking existing JSON workflows:
constwf=Workflow.from(baseJson).set('3.inputs.steps',20).input('SAMPLER','cfg',4).output('images:9');Use PromptBuilder for programmatic graph construction:
constbuilder=newPromptBuilder(base,['positive','seed'],['images']).setInputNode('positive','6.inputs.text').validateOutputMappings();See comparison guide for details.
Production-ready multi-instance scheduling with automatic health checks and intelligent hash-based routing:
import{WorkflowPool,MemoryQueueAdapter,SmartFailoverStrategy}from"comfyui-node";constpool=newWorkflowPool([newComfyApi("http://localhost:8188"),newComfyApi("http://localhost:8189")],{failoverStrategy: newSmartFailoverStrategy({cooldownMs: 60_000,// Block workflow for 60s after failuremaxFailuresBeforeBlock: 1// Block on first failure}),healthCheckIntervalMs: 30000,// keeps connections aliveenableProfiling: true,// NEW: enable automatic performance profilingexecutionStartTimeoutMs: 5000// NEW: 5s timeout for execution to start});// Monitor job completion and view profiling statspool.on("job:completed",ev=>{if(ev.detail.job.profileStats){const{ totalDuration, executionTime, summary }=ev.detail.job.profileStats;console.log(`Job ${ev.detail.job.jobId} completed in ${totalDuration}ms`);console.log(`Slowest nodes:`,summary.slowestNodes);}});constjobId=awaitpool.enqueue(workflow,{priority: 10});Hash-based routing intelligently handles failures at the workflow level (not client level). When a workflow fails on one client, the pool routes it to others while keeping that client available for different workflows.
See Hash-Based Routing Guide for details and demos.
For complex use cases involving a heterogeneous cluster of workers (e.g., some with SDXL models, others for video generation), MultiWorkflowPool provides fine-grained control over job routing based on workflow requirements.
It uses an event-driven architecture to manage clients with specific workflow affinities, ensuring that jobs are only sent to nodes capable of processing them.
- Workflow Affinity: Assign clients to specific workflows. Jobs are automatically routed to the correct client.
- Dynamic Job Queues: A separate job queue is created for each workflow type, preventing head-of-line blocking.
- Event-Driven Architecture: Zero polling for maximum efficiency and responsiveness.
- Built-in Monitoring: Optional real-time monitoring of client and queue states.
Example:
import{MultiWorkflowPool,Workflow}from"comfyui-node";importSdxlWorkflowfrom'./sdxl-workflow.json';importVideoWorkflowfrom'./video-workflow.json';// 1. Define workflows and generate their hash for affinity mappingconstsdxlWF=Workflow.from(SdxlWorkflow).updateHash();constvideoWF=Workflow.from(VideoWorkflow).updateHash();// 2. Create a new poolconstpool=newMultiWorkflowPool({logLevel: "info",enableMonitoring: true,});// 3. Add clients with workflow affinity// This client is specialized for SDXL workflowspool.addClient("http://localhost:8188",{workflowAffinity: [sdxlWF]});// This client is specialized for Video workflowspool.addClient("http://localhost:8189",{workflowAffinity: [videoWF]});// This client is a general-purpose workerpool.addClient("http://localhost:8190");// 4. Initialize the pool (connects to all clients)awaitpool.init();// 5. Submit jobs// The pool automatically routes them to the correct clientconstsdxlJobId=awaitpool.submitJob(sdxlWF);constvideoJobId=awaitpool.submitJob(videoWF);// 6. Wait for a job to completeconstresults=awaitpool.waitForJobCompletion(sdxlJobId);console.log("SDXL Job completed!",results.images);When one logical render needs a different graph per host — e.g. the same image
compiled for different GPUs or model quantizations (an nvfp4 build on one card,
an int8 build on another) — the variants reference different model files, so
they have different structure hashes and are, to the pool, different workflows.
Register each host's variant, then submit them together with submitToVariants:
the pool runs the variant whose host is idle right now, or (if none are idle)
enqueues one so it runs when a capable host frees. Submitting many logical jobs
spreads them across the heterogeneous pool.
constkreaNvfp4=Workflow.from(graphNvfp4).updateHash();// Blackwell filenamesconstkreaInt8=Workflow.from(graphInt8).updateHash();// Ampere filenamespool.addClient("http://blackwell:8188",{workflowAffinity: [kreaNvfp4]});pool.addClient("http://ampere:8188",{workflowAffinity: [kreaInt8]});awaitpool.init();// Runs on whichever host is free, using that host's own variant.constjobId=awaitpool.submitToVariants([kreaNvfp4,kreaInt8]);constresults=awaitpool.waitForJobCompletion(jobId);Note: the structure hash covers topology, node types and model references (checkpoints, LoRAs, VAEs), but not prompts, seeds or dimensions — so the same graph with a different prompt routes to the same affinity group, while a different model is treated as a different capability.
- Integration Test Infrastructure – Comprehensive reconnection testing with real mock server processes
- Mock servers spawn in separate OS processes that can be killed/restarted
- 13 integration tests covering manual/auto-reconnection, state transitions, and multiple restart cycles
- Test helpers and utilities for easy test development
- 900+ lines of documentation with quick-start guide and examples
- Run with:
bun test test/integration/orbun run test:integration
See CHANGELOG.md for complete release notes.
Check the scripts/ directory for comprehensive examples:
- Basic workflows:
workflow-tutorial-basic.ts,test-simple-txt2img.ts - Image editing:
qwen-image-edit-demo.ts,qwen-image-edit-queue.ts - Pooling:
workflow-pool-demo.ts,workflow-pool-debug.ts - Node bypass:
demo-node-bypass.ts,demo-workflow-bypass.ts - API nodes:
api-node-image-edit.ts(Comfy.org paid nodes) - Image loading:
image-loading-demo.ts
Live demo: demos/recursive-edit/ – recursive image editing server + web client.
constapi=newComfyApi('http://127.0.0.1:8188','optional-id',{credentials: {type: 'basic',username: 'user',password: 'pass'},wsTimeout: 60000,comfyOrgApiKey: process.env.COMFY_ORG_API_KEY,debug: true});awaitapi.ready();// Connection + feature probingawaitapi.ext.queue.queuePrompt(null,workflow);awaitapi.ext.queue.interrupt();conststats=awaitapi.ext.system.getSystemStats();constcheckpoints=awaitapi.ext.node.getCheckpoints();awaitapi.ext.file.uploadImage(buffer,'image.png');consthistory=awaitapi.ext.history.getHistory('prompt-id');See API Features docs for complete namespace reference.
api.on('progress',ev=>console.log(ev.detail.value,'/',ev.detail.max));api.on('b_preview',ev=>console.log('Preview:',ev.detail.size));api.on('executed',ev=>console.log('Node:',ev.detail.node));job.on('progress_pct',pct=>console.log(`${pct}%`));job.on('preview',blob=>console.log('Preview:',blob.size));job.on('failed',err=>console.error(err));bun test# Unit + integration tests
bun run test:integration # Run all integration tests
bun run test:integration:simple # Run simple reconnection examples
bun run test:real # Real server tests (COMFY_REAL=1)
bun run test:full # Comprehensive tests (COMFY_FULL=1)
bun run coverage # Coverage reportThe library includes a comprehensive integration test infrastructure that spawns real mock server processes to test reconnection behavior:
# Run all integration tests
bun test test/integration/
# Run simple examples (recommended first)
bun run test:integration:simple
# Validate the mock server infrastructure
bun test/integration/validate-mock-server.ts
# Debug: Run mock server standalone
bun test/integration/mock-server.ts 8191What's Tested:
- Manual and automatic reconnection after server crashes
- Connection state transitions (connecting → connected → disconnected → reconnecting)
- Event emission (
reconnected,reconnection_failed) - Multiple server restart cycles
- WebSocket message handling across reconnections
Documentation:
test/integration/README.md– Comprehensive guidetest/integration/QUICKSTART.md– Developer quick-start with patternstest/integration/SUMMARY.md– Architecture overview
Example:
// Integration test patternconstmanager=newServerManager({port: 8191});awaitmanager.startServer(8191);constapi=newComfyApi("http://localhost:8191");awaitinitializeClient(api);// Kill server to simulate crashawaitmanager.killServer(8191);awaitsleep(500);// Restart serverawaitmanager.startServer(8191);// Verify reconnectionawaitapi.reconnectWs(true);awaitwaitForConnection(api);expect(api.isConnected()).toBe(true);// Cleanupapi.destroy();awaitmanager.killAll();See Troubleshooting docs for details.
Issues and PRs welcome! Please:
- Include tests for new features
- Follow existing code style
- Keep feature surfaces minimal & cohesive
- Run
bun test && bun run coveragebefore submitting
MIT – see LICENSE
- npm:comfyui-node
- GitHub:igorls/comfyui-node
- ComfyUI:comfyanonymous/ComfyUI