1. 从「没有图片生成 Skill」说起:openclaw 图片生成 skill 落地要解决什么
openclaw 本身是一个偏 Agent 形态的本地助手框架,它的能力边界由 Skill 决定。我上个周末想在自己的 openclaw 里生成一张图,翻了一圈 Skill 列表,发现原生生态里确实没有图片生成能力。想画图只有三条路:打开云端控制台手动调模型、自己写脚本调 API、或者干脆切到别的工具里做。这三条路都有一个共同问题——它们跟 openclaw 是断开的,你得来回倒腾,Agent 的「一句话完成」体验直接碎掉。
更麻烦的是,我试过几个别人写的图片生成 Skill,用下来基本是「调 API 的壳」。你说「做个名片」,它不理解,非要你写完整 Prompt;你说「小红书配图」,它不知道是 3:4,要你手动填尺寸;想换模型?没门,只有一个引擎写死在里面。说白了,它把「产品化」这件事完全甩给了用户。
所以这篇要聊的 openclaw 图片生成 skill,核心不是「怎么调一个绘图 API」,而是三件事:第一,用 SKILL.md 把能力边界定义清楚,让 openclaw 知道什么时候该触发这个 Skill;第二,用本地意图识别决定「具体生成什么」,把「赛博朋克名片」这种自然语言拆成场景、风格、尺寸、引擎;第三,把底层模型调用收敛到统一 Key/API 通道,避免每个 Skill 各自维护一堆环境变量。
适合谁看?如果你正在给 openclaw 写 Skill,或者你手上有一堆模型 API 想统一收口,再或者你只是好奇「意图识别到底该用规则还是 LLM」,这篇的配置片段和判定逻辑都能直接抄。下面我会按「问题场景 → 前置准备 → 可复制配置 → 端到端验证 → 报错排查 → 后续接入」的顺序走,每一步都给可执行的东西。
先说清楚一个定位:这篇不是教你从零训练模型,而是教你做一个「产品化」的 Skill。产品化的意思是,用户说人话,Skill 负责把话翻译成工程参数。这个翻译过程,就是 SKILL.md 加意图识别要干的事。
2. TaoToken 前置:把模型调用收敛到统一 Key/API 通道
在写 SKILL.md 之前,得先解决一个更底层的问题:图片生成 Skill 要调模型,模型从哪来?如果你每个 Skill 都去申请一套 Key、维护一套 Base URL,那 Skill 越多,配置越乱。我的做法是把所有模型调用收敛到一个统一通道,这里用的是 TaoToken。
TaoToken 在这里扮演的角色是「统一 Key/API 通道」——你只需要在它那边拿到一个 Key,配一个 Base URL,就能在 Skill 里调用不同模型,而不用为每个模型单独维护凭证。官网入口是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 地址是 https://taotoken.net/api (这个不加 UTM)。
具体到操作,你需要先拿到 API Key。打开控制台页面 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ,登录后进 API Keys 页面 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite ,创建一个新 Key。创建时建议按用途命名,比如openclaw-image-skill,这样后面排查问题时能一眼看出是哪个 Skill 在用。
拿到 Key 之后,不要直接硬编码进脚本。openclaw 的 Skill 机制支持通过环境变量注入,所以正确做法是在 SKILL.md 的 metadata 里声明需要哪些环境变量,然后在运行环境里设置。这样 Key 不会进版本库,也不会在日志里裸奔。
这里有个关键点:TaoToken 的 Base URL 是https://taotoken.net/api,在代码里配置时要注意路径拼接。很多 OpenAI 兼容的 SDK 会自动在 Base URL 后面拼/v1/chat/completions之类的路径,所以你要确认最终请求地址是https://taotoken.net/api/v1/...这种形式。如果 SDK 默认拼的是/v1,那 Base URL 就填https://taotoken.net/api;如果 SDK 要求你填到/v1,那就填https://taotoken.net/api/v1。这个细节后面排查 404 的时候会用到。
模型 ID 这块,图片生成和文本对话用的不是同一个模型。文本意图识别(如果你走 LLM 路线)可以用通用的对话模型,图片生成则要用对应的绘图模型。在 TaoToken 的模型列表里能看到当前可用的模型 ID,配置时直接填那个 ID 就行。我建议把模型 ID 也做成可配置项,而不是写死在代码里,这样换模型不用改代码。
前置准备做完,你手上应该有三样东西:一个 TaoToken API Key、一个 Base URL(https://taotoken.net/api)、以及你要用的模型 ID。这三样就是后面 SKILL.md 和脚本里要引用的核心配置。缺任何一个,Skill 都跑不起来。
3. 可复制配置:SKILL.md 定义能力边界 + 意图识别判定规则
这一节是整篇的核心,给可直接复制的配置片段。分两部分:SKILL.md 定义「什么时候触发」,意图识别规则定义「触发后生成什么」。
先看 SKILL.md。openclaw 的 Skill 通过 SKILL.md 的 frontmatter 声明元信息,包括名称、描述、版本、需要的环境变量等。下面是我实际在用的片段,你可以直接改成自己的:
--- name: beauty-image description: 商业化 AI 图片生成助手。40+ 场景模板,30+ 风格词典,智能意图识别,支持名片、海报、头像、3D 材质等场景。 version: 3.2.0 author: your-name metadata: openclaw: requires: env: - TAOTOKEN_API_KEY - TAOTOKEN_BASE_URL - TAOTOKEN_IMAGE_MODEL primaryEnv: TAOTOKEN_API_KEY emoji: "" --- # Beauty Image V3 — 商业化 AI 图片生成 **触发场景**: - 名片设计 → 询问姓名、职称、公司、风格 - 海报创作 → 询问主题、配色、排版 - 头像/IP → 询问人物描述、风格、表情 - 3D/材质 → 询问主体、材质类型 - 通用图片 → 画面描述、尺寸比例注意requires.env里我声明了三个环境变量:TAOTOKEN_API_KEY、TAOTOKEN_BASE_URL、TAOTOKEN_IMAGE_MODEL。这样 openclaw 在加载 Skill 时会检查这些变量是否存在,缺了会提示,而不是等到运行时才报错。primaryEnv指定主 Key,方便框架做统一管理。
SKILL.md 的正文部分写「触发场景」,这是给 openclaw 的语义理解层看的。openclaw 会根据用户消息的语义判断是否调用这个 Skill。比如用户说「帮我做一张赛博朋克风格的名片」,语义上命中「名片设计」,就会触发 beauty-image。
但 openclaw 只负责「什么时候调用」,具体「生成什么」要靠 Skill 内部的意图识别。这就是第二层。我用的是本地规则引擎,核心是两组正则规则。下面是场景规则和风格规则的片段:
# scripts/image_intent_parser.py # 33 条场景规则(节选) _SCENE_RULES = [ (r"(名片|business\s*card)", "biz_card"), (r"(海报|poster|宣传图)", "biz_poster"), (r"(水晶|crystal|玻璃)", "3d_crystal"), (r"(毛绒|plush|蓬松)", "3d_plush"), (r"(头像|avatar|ip\s*形象)", "social_avatar"), (r"(表情包|meme|sticker)", "social_meme"), # ... 共 33 条 ] # 21 条风格规则(节选) _STYLE_RULES = [ (r"赛博朋克|cyberpunk", "赛博朋克"), (r"浮世绘|ukiyo", "浮世绘"), (r"吉卜力|ghibli", "吉卜力"), (r"水晶|crystal", "水晶"), # ... 共 21 条 ]为什么用规则而不是 LLM?我算过一笔账。LLM 意图识别大概 ¥0.02/次,图片生成 ¥0.15/次,加起来 ¥0.17/次。如果每天 100 次,LLM 成本 ¥2/天,一个月 ¥60;图片成本 ¥15/天,一个月 ¥450。LLM 占了 12% 的成本,而且它只是个中间步骤。规则引擎响应时间小于 1ms,成本为零,覆盖率大概 85%。剩下 15% 的边界情况,用户可以手动指定,或者加参数走 LLM 深度解析。这不是技术问题,是商业决策——85% 够用了。
规则引擎的输出是一个结构化的意图对象,包含场景 ID、风格名、尺寸、以及从用户输入里抽取的字段。比如「赛博朋克名片」会解析成:
{ "scene_id": "biz_card", "style": "赛博朋克", "size": "16:9", "fields": {"title": None, "company": None} }然后 Prompt 构建器会把这个意图对象扩展成专业级 Prompt。这里不是简单拼接关键词,而是六层结构化:
layers = { "core": "核心主体", # 这是什么? "subject": "主体描述", # 长什么样? "style": "风格特征", # 什么艺术风格? "lighting": "光照氛围", # 什么光线条件? "composition": "构图视角", # 什么视角和布局? "technical": "技术参数" # 什么质量要求? }风格词典里每个风格有三个维度:keywords、lighting、negative。比如赛博朋克:
STYLE_DICT = { "赛博朋克": { "keywords": "赛博朋克风格,霓虹灯光,深色背景,蓝紫粉渐变", "lighting": "霓虹灯混合光,彩色边缘光,逆光剪影", "negative": "白天,明亮,自然光,田园", }, }用户输入「赛博朋克名片」五个字,输出 Prompt 大概 200 字,负面 Prompt 也会自动带上。这就是「复杂留给自己,简单留给用户」。
引擎路由也是配置的一部分。不同场景适合不同模型,我实测 500+ 张图后总结的规律是:商务场景(文字多)用 wanx,3D 场景用 seedream5,艺术创作用 seedream5,默认用 seedream4 性价比高。路由逻辑:
def select_engine(scene_id, style_name): if scene_id.startswith("biz_"): return "wanx" if scene_id.startswith("3d_"): return "seedream5" if scene_id.startswith("art_"): return "seedream5" return "seedream4"尺寸适配也做了别名映射,用户说「小红书」自动转 3:4,说「头像」自动转 1:1:
SIZE_ALIASES = { "正方": "1:1", "头像": "1:1", "小红书": "3:4", "xhs": "3:4", "横版": "16:9", "电影": "21:9", "海报": "2:3", }这些配置片段拼起来,就是一个完整的「能力边界 + 意图识别」定义。SKILL.md 管触发,规则引擎管解析,Prompt 构建器管扩展,引擎路由管选模型,尺寸映射管适配。每一层都可配置、可替换。
4. 端到端验证:一次图片生成请求的完整过程
配置写完,得验证它真的能跑通。这一节给一次完整的端到端生成动作,从用户输入到图片落盘。
先确认环境变量已经设置。在 openclaw 的运行环境里,或者你本地测试的 shell 里:
export TAOTOKEN_API_KEY="你的Key" export TAOTOKEN_BASE_URL="https://taotoken.net/api" export TAOTOKEN_IMAGE_MODEL="你的绘图模型ID"然后跑主脚本。假设用户输入是「帮我做一张赛博朋克风格的名片」,脚本入口是scripts/generate_image_v3.py:
uv run scripts/generate_image_v3.py --prompt "帮我做一张赛博朋克风格的名片" --size 名片脚本执行流程是这样的:先调image_intent_parser.py解析意图,得到scene_id=biz_card、style=赛博朋克、size=16:9。然后 Prompt 构建器生成正向和负向 Prompt。接着引擎路由选中 wanx。最后在真正调用 API 之前,会打印确认信息:
即将生成图片: - 场景:biz_card - 风格:赛博朋克 - 引擎:wanx - 尺寸:16:9 (1696*960) - 缺失字段:title, company 确认?(y/n):这一步很重要,因为图片生成是要花钱的,¥0.1-0.5/次。让用户确认意图识别对不对、哪些字段没填、到底用哪个引擎,确认完再生成,省得浪费钱。输入y后,脚本会向https://taotoken.net/api发起请求,带上TAOTOKEN_API_KEY做鉴权。
请求成功后,返回的图片会保存到本地,同时打印保存路径和本次消耗。如果一切正常,你会看到类似:
[OK] 意图识别: biz_card / 赛博朋克 / 16:9 [OK] 引擎路由: wanx [OK] 请求成功,耗时 8.3s [OK] 图片已保存: ./output/biz_card_cyberpunk_1696x960.png这就是一次完整的端到端验证。如果你在 openclaw 里用,用户只需要说「帮我做一张赛博朋克风格的名片」,openclaw 的语义层触发 beauty-image Skill,Skill 内部走上面这套流程,最后把图片路径返回给用户。用户全程不需要知道 wanx 是什么、Prompt 怎么写、尺寸怎么填。
验证的时候建议先跑一个最简单的场景,比如「生成一张 1:1 的测试图」,确认 Key、Base URL、模型 ID 三件套都对,再跑复杂场景。这样出问题容易定位——是配置问题还是意图识别问题,一眼能分清。
另外,如果你想单独验证模型通道是否通,可以用模型对话页面 https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=chat&utm_campaign=rewrite 发一条消息,确认 Key 有效。这一步能排除掉大部分鉴权类问题。
5. 本篇常见错排查:401、local proxy failed、reading choices、OAuth
配置和验证过程中,最容易撞上的几类报错,我按实际遇到的顺序列一下,每个都给排查方向。
第一类:401 Unauthorized。这个最常见,基本是 Key 的问题。先确认TAOTOKEN_API_KEY环境变量真的被读到了,可以在脚本里加一行打印 Key 的前几位和后几位(不要打印全量)。如果 Key 是对的,检查请求头里的鉴权格式,通常是Authorization: Bearer <Key>。还有一种情况是 Key 创建后没生效,去 API Keys 页面确认状态是 active。如果用的是 TaoToken 的统一通道,确认 Base URL 是https://taotoken.net/api,不要多写或少写路径。
第二类:local proxy failed。这个报错通常出现在本地网络层,不是 Key 的问题。排查方向是确认你的运行环境能正常访问https://taotoken.net/api,可以用 curl 测一下连通性。如果是容器环境,检查容器的网络配置。注意,这里不要引入任何网络代理相关的配置,直接确认直连是否可达即可。如果 curl 能通但脚本不通,那就是脚本里的 Base URL 拼错了,检查是不是多拼了一层/v1或者少了/v1。
第三类:reading choices 相关报错。这个通常出现在解析响应体的时候,报错信息里会有reading 'choices'或者cannot read property 'choices' of undefined。原因是响应体结构和你预期的不一样。可能是模型 ID 填错了,返回了一个错误对象而不是正常的 completion 结构;也可能是请求路径不对,打到了别的端点。排查方法是把原始响应体打印出来看,确认返回的是不是标准的{choices: [...]}结构。如果是错误对象,里面通常有 message 字段说明原因。
第四类:OAuth 相关报错。如果你在配置过程中看到 OAuth 字样,说明你可能误用了需要 OAuth 流程的接入方式。TaoToken 的 API 通道用的是 API Key 鉴权,不需要 OAuth。检查你的配置里是不是混入了别的鉴权方式,把鉴权头统一改成Authorization: Bearer <Key>即可。
除了这四类,还有一个高频问题是「模型 ID 不存在」。这个报错信息通常比较明确,会告诉你哪个模型 ID 无效。去模型列表里核对一下,确认你填的 ID 和列表里的一致。图片生成和文本对话用的模型 ID 不一样,别填混了。
排查的时候有个通用技巧:把请求的完整 URL、请求头(脱敏后)、请求体、响应体都打印出来。大部分问题看一眼原始请求和响应就能定位。不要只盯着报错信息猜,要看实际发出去和收回来的是什么。
6. 后续接入:从单次生成到长期编码与 Agent 工作流
单次图片生成跑通之后,下一步通常是把它接进更长期的工作流。比如你在做内容创作,需要批量生成配图;或者你在搭一个 Agent,需要它自主决定什么时候画图。这时候关注点就从「能不能生成」变成「怎么稳定、低成本地持续生成」。
如果你要把图片生成 Skill 接进编码或 Agent 工作流,建议走 Coding Plan 这条线。入口是 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 。它的价值在于把模型调用、额度管理、故障转移这些事统一起来,你不需要在每个 Skill 里重复实现。比如 seedream5 额度用完了自动切 seedream4,seedream 全挂了自动切 wanx,都不可用才提示用户配置 Key。这套故障转移机制写在 Skill 里也行,但放在统一通道层更省事。
接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite ,里面有完整的 Base URL、鉴权方式、模型列表和错误码说明。写 Skill 之前过一遍文档,能少踩很多坑。特别是错误码那部分,对照着第 5 节的排查清单看,定位问题会快很多。
如果你用的是 Claude Code 这类工具做开发,Anthropic 兼容的接入方式在 https://taotoken.net/claudecode-anthropic?utm_source=taotoken_aicg_blog_end&utm_content=claudecode-anthropic&utm_campaign=rewrite 。图片生成 Skill 本身不一定用得上,但如果你在同一个项目里既有文本 Agent 又有图片生成,统一到一个通道会省掉很多配置工作。
回到 openclaw 图片生成 skill 本身,产品化的关键其实就三点:SKILL.md 把触发边界写清楚,意图识别把自然语言翻译成工程参数,统一 Key/API 通道把模型调用收口。这三点做到,用户就只需要说人话,剩下的交给 Skill。我实测下来,规则引擎加统一通道的组合,在成本和体验之间找到了一个不错的平衡点。剩下的 15% 边界情况,留给手动 override 或者按需上 LLM,不用为了完美牺牲 85% 场景的成本优势。