1. 为什么要把 OpenClaw 和 ComfyUI 接在一起用第一次听到OpenClaw ComfyUI这个组合很多人会愣一下一个是偏自动化操作与流程编排的开源工具一个是当下最火的节点式图像生成前端这俩凑一块儿到底图什么我最初也是抱着这个疑问去折腾的折腾完之后最大的感受是——它们解决的是同一件事的两端ComfyUI 负责把图生成出来OpenClaw 负责把生成这件事自动化、批量化、可编排化。单用 ComfyUI你是在手动点按钮接上 OpenClaw你是在写一条能反复跑的流水线。先说清楚这两个东西各自是什么不然后面全是空中楼阁。ComfyUI 的核心是节点图node graph每个节点干一件小事——加载模型、编码提示词、采样、解码、保存节点之间用连线传递张量数据。它的强大之处在于把扩散模型的整个推理链路完全暴露出来你能精确控制每一步。但它的短板也很明显交互靠鼠标拖拽批量任务靠队列跨机器调度、条件分支、失败重试这些工程化能力基本没有。OpenClaw 这类工具的价值就在这儿。它本质是一个任务编排与自动化执行层能把调用某个接口、等待结果、根据结果决定下一步这套逻辑用配置或脚本描述出来。把它和 ComfyUI 接起来你就能做到给一批提示词自动排队生成生成失败自动重试生成完自动做后处理甚至根据上一张图的结果动态决定下一张图的参数。这套东西对做批量出图、A/B 参数对比、数据集构造、电商主图流水线的人来说价值是实打实的。注意本文讲的接入是指通过 ComfyUI 官方提供的 API 接口进行程序化调用不涉及任何网络代理类工具。所有操作都在本机或内网完成。适合读这篇的人大概分三类一是已经会用 ComfyUI 但被手动操作折磨的二是想搭自动化出图流水线但不知道从哪下手的三是做 AI 应用集成、需要把图像生成能力嵌进自己系统的。不管你是哪类下面的内容都按能直接抄作业的标准来写。2. 动手之前ComfyUI 的 API 模式到底怎么开2.1 默认启动和 API 启动的区别很多人用 ComfyUI 用了半年都不知道它自带一套 HTTP API。默认启动方式直接跑main.py其实已经开了 API但有个关键细节默认只监听本地回环地址而且没有开启开发者模式的节点信息接口。如果你只是本机调用默认启动就够了但如果你想让 OpenClaw 跑在另一台机器上、或者跑在容器里就必须显式指定监听地址。启动命令大概长这样python main.py --listen 0.0.0.0 --port 8188--listen 0.0.0.0表示监听所有网卡--port指定端口。这里有个坑我踩过某些环境下0.0.0.0会被安全策略拦实际起不来这时候换成具体的内网 IP 更稳。另外如果你要跨机器调用记得确认防火墙放行了对应端口否则你会对着连接超时怀疑人生。2.2 两个必须记住的核心接口ComfyUI 的 API 表面上看有一堆端点但真正干活的核心就两个接口方法作用关键参数/promptPOST提交一个工作流任务prompt工作流 JSON、client_id/history/{prompt_id}GET查询任务执行结果prompt_id/viewGET下载生成的图片filename、subfolder、type/object_infoGET获取所有节点的参数定义无/prompt接收的不是你在界面上看到的那个工作流文件而是API 格式的工作流。这两者长得像但不一样后面会专门讲怎么转换。提交成功后会返回一个prompt_id你拿着这个 id 去/history轮询直到状态变成完成再从返回结果里拿到输出图片的文件名最后用/view把图下载下来。整个链路就这四步没有任何魔法。2.3 为什么必须用 API 格式的工作流这是新手最容易卡住的地方。你在 ComfyUI 界面里点保存存下来的是带界面布局信息的工作流 JSON里面包含了节点的坐标、大小、颜色这些纯 UI 数据。而/prompt接口要的是纯执行图只包含节点 id、class_type 和 inputs。转换方法有两种。第一种是界面里自带的导出API功能直接导出成 API 格式最省事。第二种是手动转换适合你想程序化生成工作流的场景。手动转换的规则是每个节点变成一个键值对键是节点 id字符串值包含class_type和inputs两个字段inputs里凡是连线的输入值写成[上游节点id, 输出槽位索引]的形式。举个最小例子一个只有加载检查点 → 空 latent → KSampler → VAE 解码 → 保存的极简文生图工作流转成 API 格式大概是这样{ 3: { class_type: KSampler, inputs: { seed: 12345, steps: 20, cfg: 7.5, sampler_name: euler, scheduler: normal, denoise: 1.0, model: [4, 0], positive: [6, 0], negative: [7, 0], latent_image: [5, 0] } } }看到[4, 0]这种写法了吗意思就是这个输入来自节点 4 的第 0 号输出。理解了这个你就能用代码动态改工作流了——比如把seed换成随机数、把steps换成变量这就是自动化的起点。3. 用 OpenClaw 编排从单次调用到批量流水线3.1 最小可跑通的调用脚本在把逻辑塞进 OpenClaw 之前我强烈建议先用一段最简单的 Python 脚本把整条链路跑通。原因很简单如果裸脚本都跑不通套上编排层只会让你更难定位问题。下面这段是我常用的最小验证脚本逻辑清晰直接能跑import json import time import urllib.request import urllib.parse SERVER http://127.0.0.1:8188 CLIENT_ID openclaw-demo def load_workflow(path): with open(path, r, encodingutf-8) as f: return json.load(f) def queue_prompt(workflow): payload {prompt: workflow, client_id: CLIENT_ID} data json.dumps(payload).encode(utf-8) req urllib.request.Request( f{SERVER}/prompt, datadata, headers{Content-Type: application/json} ) with urllib.request.urlopen(req) as resp: return json.loads(resp.read())[prompt_id] def wait_result(prompt_id, timeout300): start time.time() while time.time() - start timeout: with urllib.request.urlopen(f{SERVER}/history/{prompt_id}) as resp: history json.loads(resp.read()) if prompt_id in history: return history[prompt_id] time.sleep(1) raise TimeoutError(生成超时) if __name__ __main__: wf load_workflow(workflow_api.json) pid queue_prompt(wf) result wait_result(pid) print(json.dumps(result[outputs], ensure_asciiFalse, indent2))这段代码跑通之后你会看到输出里带着生成图片的文件名。到这一步说明 ComfyUI 的 API 链路是通的接下来才是 OpenClaw 登场。3.2 把改参数这件事做成变量自动化的核心不是能调用而是能按不同参数反复调用。所以第二步是把工作流里需要变的字段抽出来。我一般会写一个patch_workflow函数接收工作流和一组参数字典返回改好的工作流def patch_workflow(wf, positive_textNone, seedNone, stepsNone): wf json.loads(json.dumps(wf)) # 深拷贝避免污染原图 if positive_text is not None: wf[6][inputs][text] positive_text if seed is not None: wf[3][inputs][seed] seed if steps is not None: wf[3][inputs][steps] steps return wf这里的节点 id6、3必须和你实际工作流里的 id 对上不能照抄。怎么确认打开 API 格式的工作流 JSON找到对应的class_type看它的键是什么。这一步千万别偷懒id 对不上是最常见的改了没生效的原因。3.3 OpenClaw 里怎么描述一条流水线OpenClaw 这类编排工具的核心概念通常是任务task 依赖dependency 触发条件。把上面的逻辑翻译过去一条完整的出图流水线大概包含这几个任务节点参数准备任务从 CSV、数据库或上游接口读取一批提示词和参数组合。提交任务对每一组参数调用/prompt提交拿到prompt_id。轮询任务对每个prompt_id轮询/history直到完成或超时。下载任务从结果里解析文件名调用/view下载到指定目录。后处理任务对下载的图做裁剪、加水印、重命名、入库。这五个任务之间是串行依赖但提交任务本身可以并发。这里有个经验ComfyUI 的队列是串行执行的除非你开了多实例所以你并发提交 100 个任务它们还是排队一个个跑。真正能提升吞吐的是多开 ComfyUI 实例 负载分发而不是在客户端疯狂并发。我见过有人写 50 个线程去提交结果只是把队列塞爆显存该不够还是不够。提示如果你的机器显存有限建议在 OpenClaw 里加一个并发闸门比如最多同时提交 2 个任务其余排队。这样能避免显存溢出导致的整批失败。4. 踩坑实录那些让我熬夜的报错和它们的根因4.1 改了参数但生成结果没变这是最高频的问题没有之一。现象是脚本明明改了seed生成的图却和上一张一模一样。根因通常有三个按概率从高到低排第一你改的节点 id 不是真正生效的那个。有些工作流里存在多个 KSampler或者提示词被某个中间节点覆盖了。解决办法是把 API 工作流打印出来逐个节点核对。第二工作流里有缓存节点。ComfyUI 对相同输入的节点会复用缓存如果你只改了不影响该节点的参数它就不会重新执行。这时候要么改一个真正影响链路的参数要么在提交前给工作流加一个扰动比如改一下无意义的 seed。第三你改的是深拷贝前的对象但提交的是另一个。这个纯属代码 bug但很隐蔽。养成改完立刻打印确认的习惯能省很多时间。4.2 轮询把服务打挂我早期写的轮询是while True里sleep(0.1)结果一批 200 张图跑下来ComfyUI 的日志被刷爆服务响应变慢。后来改成指数退避第一次等 0.5 秒之后每次乘以 1.5上限 5 秒。这样既不会漏掉快速完成的任务也不会把服务压垮。def poll_with_backoff(prompt_id, max_wait600): delay 0.5 elapsed 0 while elapsed max_wait: # 查询逻辑... time.sleep(delay) elapsed delay delay min(delay * 1.5, 5.0)4.3 图片下载下来是 0 字节这个坑很迷惑。/view接口返回 200但文件是空的。排查下来通常是参数拼错filename、subfolder、type三个参数必须和/history返回的完全一致尤其是subfolder如果保存节点设置了子目录你不传这个参数就会拿到空响应。另外type一般是output但如果你用了临时目录可能是temp别想当然。4.4 显存溢出导致整批中断批量任务最怕的就是跑到第 80 张突然 OOM前面 79 张白跑。我的做法是在 OpenClaw 里给每个任务加独立的重试策略失败后先等 10 秒再降一档分辨率或步数重试一次还失败就标记为待人工处理并继续下一个。这样单点失败不会拖垮整批。同时把每张图的参数和结果都落库方便事后补跑。报错现象最可能根因处理方式参数改了没生效节点 id 错 / 缓存 / 拷贝问题打印工作流核对服务变慢轮询过频指数退避图片 0 字节view 参数不全对齐 history 返回字段整批中断显存溢出单任务重试 降档提交返回 400工作流格式错确认是 API 格式5. 让流水线真正好用的几个进阶技巧5.1 用模板 覆盖的方式管理工作流如果你有十几条不同的工作流文生图、图生图、局部重绘、放大不要为每条都写一套调用代码。我的做法是统一走一个模板 参数覆盖的入口所有工作流都转成 API 格式存起来调用时只传用哪个模板和覆盖哪些字段。这样 OpenClaw 里只需要维护一份提交逻辑新增工作流只是加一个 JSON 文件的事。5.2 结果落库别只存图片图片存磁盘就够了但参数和结果的对应关系必须落库。我一般会存这几列任务 id、提示词、seed、steps、cfg、模型名、生成耗时、输出文件名、状态。有了这张表你才能做哪组参数效果最好的复盘也才能在失败时精准补跑。纯靠文件名记参数跑上几百张之后你一定会后悔。5.3 给生成结果做自动质检批量出图最头疼的是跑完了但一半是废图。可以在流水线末尾加一个轻量质检节点用一个人脸检测或清晰度评估的小模型过一遍把明显崩坏的图打上标记。这不追求 100% 准确只要能过滤掉最离谱的那批就能省下大量人工筛选时间。质检不通过的图不删除移到rejected目录方便你回头确认是不是误杀。5.4 多实例负载分发的思路当单实例吞吐不够时最直接的办法是起多个 ComfyUI 实例监听不同端口然后在 OpenClaw 里做一个简单的轮询分发任务来了就发给当前队列最短的实例。判断队列最短可以调每个实例的/queue接口看排队数。这套方案比在单实例上堆并发有效得多因为瓶颈通常在 GPU 而不是 CPU 调度。注意多实例会成倍占用显存起之前先算清楚你的卡能扛几个。一般来说一个 12G 显存的卡跑 SD1.5 级别的模型两个实例是安全线再多就要降分辨率了。6. 我在实际项目里踩出来的几条经验折腾这套组合有小半年了说几条文档里不会写、但实际特别有用的体会。第一条先把单次调用跑稳再谈编排。我见过太多人一上来就搭复杂的 DAG结果底层 API 都没调通排查问题时根本分不清是编排层的锅还是 ComfyUI 的锅。花半小时把裸脚本跑通后面能省几小时。第二条工作流的节点 id 是脆弱的。你在界面上重新拖一下节点导出的 API 格式里 id 可能就变了。所以我的做法是一旦某条工作流定稿就把它当成冻结资产改参数只通过覆盖字段绝不在界面上重新编辑。需要改结构就新建一条别动老的。第三条日志要记全但别记太碎。每个任务的提交时间、prompt_id、参数、结果状态都要记但不要把每张图的 base64 塞进日志那会让日志文件爆炸。图片走文件系统日志只记路径。第四条给流水线留一个手动刹车。批量任务跑起来之后如果发现参数整体错了你得能一键停掉。OpenClaw 里可以设一个暂停标志文件任务执行前检查这个文件是否存在存在就挂起。这个土办法在关键时刻能救你一整晚的算力。最后说个心态上的事这套组合的价值不在于炫技而在于把重复劳动交给机器。你花两天搭好的流水线可能一周就回本了。但前提是你得接受它一开始会各种报错——这不是你水平不行是这类工具链本来就处在能用但不够顺的阶段。把每次报错都当成一次对系统理解的加深跑通之后那种一键出几百张图的爽感是手动点按钮永远给不了的。