IMA Image AI Creation
⚠️ 重要:模型 ID 参考
CRITICAL: When calling the script, you MUST use the exact model_id (second column), NOT the friendly model name. Do NOT infer model_id from the friendly name.
Quick Reference Table:
| 友好名称 (Friendly Name) | model_id | 说明 (Notes) |
|---|---|---|
| Nano Banana2 | gemini-3.1-flash-image | ❌ NOT nano-banana-2, 预算选择 4-13 pts |
| Nano Banana Pro | gemini-3-pro-image | ❌ NOT nano-banana-pro, 高质量 10-18 pts |
| SeeDream 4.5 | doubao-seedream-4.5 | ✅ Recommended default, 5 pts |
| Midjourney | midjourney | ✅ Same as friendly name, 8-10 pts |
User Input Variations Handled by Agent:
- "香蕉" / "香蕉2" / "小香蕉" → Nano Banana2 →
gemini-3.1-flash-image - "香蕉Pro" / "香蕉专业版" / "大香蕉" → Nano Banana Pro →
gemini-3-pro-image - "可梦" / "豆包可梦" / "SeeDream" →
doubao-seedream-4.5 - "MJ" / "Midjourney" →
midjourney
How to get the correct model_id:
- Check this table first
- Use
--list-models --task-type text_to_image(orimage_to_image) - Refer to command examples below
Example:
# ❌ WRONG: Inferring from friendly name
--model-id nano-banana-pro
# ✅ CORRECT: Using exact model_id from table
--model-id gemini-3-pro-image
⚠️ MANDATORY PRE-CHECK: Read Knowledge Base First!
If ima-knowledge-ai is not installed: Skip all "Read …" steps below; use only this SKILL's default models and the 📥 User Input Parsing tables for task_type, model_id, and parameters.
BEFORE executing ANY image generation task, you MUST:
-
Check for visual consistency needs — Read
ima-knowledge-ai/references/visual-consistency.mdif:- User mentions: "系列"、"多张"、"同一个"、"角色"、"续"、"series"、"same"
- Task involves: multiple images, character actions, product shots, video stills
- Second+ request about same subject (e.g., "旺财在游泳" after "生成旺财照片")
-
Check workflow/model/parameters — Read relevant
ima-knowledge-ai/references/sections if:- Complex multi-step task
- Unsure which model to use
- Need parameter guidance (resolution, aspect ratio, etc.)
Why this matters:
- AI generation defaults to 独立生成 (independent generation) each time
- Without reference images, "same character/product" will look different
- Text-to-image CANNOT maintain visual consistency — must use image-to-image with reference
Example failure case:
User: "生成一只小狗,叫旺财"
→ You: generate dog image A
User: "生成旺财在游泳的视频"
→ ❌ Wrong: generate new dog (looks different)
→ ✅ Right: read visual-consistency.md → use image A as reference
How to check:
# Step 1: Read knowledge base
read("~/.openclaw/skills/ima-knowledge-ai/references/visual-consistency.md")
# Step 2: Identify if reference image needed
if "same subject" or "series" or "character":
# Use image-to-image with previous result as reference
reference_image = previous_generation_result
use_image_to_image(prompt, reference_image, reference_strength=0.8)
else:
# OK to use text-to-image
use_text_to_image(prompt)
No exceptions — if you skip this check and generate visually inconsistent results, that's a bug.
📥 User Input Parsing (Model & Parameter Recognition)
Purpose: So that any agent (Claude or other models) parses user intent consistently, follow these rules when deriving task_type, model_id, and parameters from natural language. Normalize first, then map.
1. User phrasing → task_type
| User intent / phrasing | task_type | Notes |
|---|---|---|
| Only text, no input image | text_to_image | "画一张…" / "生成图片" / "text to image" |
| One input image + edit/transform | image_to_image | "把这张图…" / "参考这张图生成" / "图生图" / "风格迁移" |
If the user attaches or links one image and asks to change it or generate something "like this" (same subject/style), use image_to_image with that image as input.
2. Model name / alias → model_id (normalize then lookup)
Normalize user wording (case-insensitive), then map to model_id:
| User says (examples) | model_id | Notes |
|---|---|---|
| 可梦 / SeeDream / 豆包可梦 / Seedream | doubao-seedream-4.5 | Default, 5 pts |
| Midjourney / MJ / Mid journey | midjourney | Artistic, 8–10 pts |
| Nano Banana / 香蕉 / Banana2 / NB2 | gemini-3.1-flash-image | Nano Banana2, 4–13 pts |
| Nano Banana Pro / Banana Pro / NB Pro | gemini-3-pro-image | Premium, 10–18 pts |
| 最便宜 / 最省钱 / cheapest / budget | gemini-3.1-flash-image (512px) | 4 pts |
| 最好 / 最高质量 / best / premium | gemini-3-pro-image (4K) or SeeDream 4.5 | — |
| 艺术 / 插画 / artistic / 画风 | midjourney | When user wants illustration/art style |
If the user names a model not in the table, match by Name in the "Supported Models" section below and use its model_id.
3. User phrasing → size / aspect_ratio
| User says (examples) | Parameter | Normalized value | Notes |
|---|---|---|---|
| 16:9 / 横图 / 横向 | aspect_ratio | 16:9 | SeeDream / Nano Banana 支持 |
| 9:16 / 竖图 / 竖向 | aspect_ratio | 9:16 | — |
| 4:3 / 3:4 | aspect_ratio | 4:3 or 3:4 | — |
| 1:1 / 方形 | aspect_ratio | 1:1 | — |
| 4K / 4k | size | 4K | Nano Banana Pro/2; Midjourney 仅 1:1 |
| 2K / 1K / 512 | size | 2K / 1K / 512px | Via attribute_id for Nano Banana |
Midjourney: Does not support custom aspect_ratio (fixed 1024×1024). If user asks for 16:9 etc. with "MJ", recommend SeeDream 4.5 or Nano Banana and use their model_id. 8K: No model supports 8K; max is 4K — inform user and use 4K if they insist on "highest resolution".
💬 User Experience Protocol (IM / Feishu / Discord) v1.3 🆕
CRITICAL FIX in v1.2: Added Step 0 to ensure correct message ordering in group chats. NEW in v1.3: Added original image URL in Step 3 caption for easy copying/sharing.
v1.1 Bug: Confirmation message ("好的!来帮你画...") appeared LAST because it used
NO_REPLY. v1.2 Fix: Always reply with confirmation FIRST (Step 0), then push updates viamessagetool. v1.3 Enhancement: Include🔗 原始链接:[url]in success caption so users can copy/share the URL.
This skill runs inside IM platforms (Feishu, Discord via OpenClaw).
Never let users wait in silence. Always follow all 6 steps below, every single time.
🚫 Never Say to Users
| ❌ Never say | ✅ What users care about |
|---|---|
ima_image_create.py / 脚本 / script | — |
| 自动化脚本 / automation | — |
| 自动处理产品列表 / 查询接口 | — |
| 自动解析参数 / 智能轮询 | — |
| attribute_id / model_version / form_config | — |
| API 调用 / HTTP 请求 / 任何技术参数名 | — |
Only tell users: model name · estimated time · credits · result (image/media) · plain-language status.
Estimated Generation Time per Model
| Model | Estimated Time | Poll Every | Send Progress Every |
|---|---|---|---|
| SeeDream 4.5 🌟 | 30~60s | 5s | 20s |
| Nano Banana2 💚 | 20~40s | 5s | 15s |
| Nano Banana Pro | 60~120s | 5s | 30s |
| Midjourney 🎨 | 40~90s | 8s | 25s |
estimated_max_seconds = the upper bound of the range above (e.g. 60 for SeeDream 4.5, 120 for Nano Banana Pro, 90 for Midjourney).
Step 0 — Initial Acknowledgment Reply (Normal Reply) 🆕
⚠️ CRITICAL: This step is NEW in v1.2 and fixes the message ordering bug.
Before doing anything else, reply to the user with a friendly acknowledgment message using your normal reply (not message tool). This reply will automatically appear FIRST in the conversation.
Example acknowledgment messages:
好的!来帮你画一只萌萌的猫咪 🐱
收到!马上为你生成一张 16:9 的风景照 🏔️
OK! Starting image generation with SeeDream 4.5 🎨
Rules:
- Keep it short and warm (< 15 words)
- Match the user's language (Chinese/English)
- Include relevant emoji (🐱/🎨/✨)
- This is your ONLY normal reply — all subsequent updates use
messagetool
Why this matters:
- Normal replies automatically appear FIRST in the conversation thread
messagetool pushes appear in chronological order AFTER your initial reply- This ensures users see: "好的!" → "🎨 开始生成..." → "✅ 成功!" (correct order)
Step 1 — Pre-Generation Notification (Push via message tool)
After Step 0 reply, use the message tool to push a notification immediately to the group/channel:
# Agent implementation
message(
action="send",
target=group_id, # or channel_id for Discord
message="""🎨 开始生成图片,请稍候…
• 模型:[Model Name]
• 预计耗时:[X ~ Y 秒]
• 消耗积分:[N pts]"""
)
User-facing message template:
🎨 开始生成图片,请稍候…
• 模型:[Model Name]
• 预计耗时:[X ~ Y 秒]
• 消耗积分:[N pts]
Cost transparency examples:
- Balanced/default (5-6 pts): "使用 SeeDream 4.5(5 积分,性价比最佳)"
- Premium (>10 pts): "使用 Nano Banana Pro(10-18 积分,最高质量,支持 1K/2K/4K)"
- Budget (user explicit): "使用 Nano Banana2(4 积分,最便宜最快)"
Adapt language to match the user. Chinese →
🎨 开始生成图片,请稍候…/ English →🎨 Starting image generation, please wait…
Step 2 — Progress Updates (Push via message tool)
Implementation:
- Start the generation script in background or use polling loop
- Track elapsed time since start
- Every
[Send Progress Every]seconds (from table above), push a progress update viamessagetool - Stop when task completes (success/failure)
Progress message template:
⏳ 正在生成中… [P]%
已等待 [elapsed]s,预计最长 [max]s
Progress formula:
P = min(95, floor(elapsed_seconds / estimated_max_seconds * 100))
Rules:
- Cap at 95% — never show 100% until the API returns
success - If
elapsed > estimated_max: keep P at 95% and append「稍等,即将完成…」 - Example: elapsed=40s, max=60s → P = min(95, floor(40/60*100)) = min(95, 66) = 66%
When to send progress:
- Short tasks (<20s): No progress needed, skip Step 2
- Medium tasks (20-60s): Send 1-2 updates
- Long tasks (>60s): Send updates every 20-30s
Step 3 — Success Notification (Push image via message tool)
When task status = success, use the message tool to send the generated image directly (not as a text URL):
Agent implementation:
# Get result URL from script output or task detail API
result = get_task_result(task_id)
image_url = result["medias"][0]["url"]
# Build caption
caption = f"""✅ 图片生成成功!
• 模型:[Model Name]
• 耗时:预计 [X~Y]s,实际 [actual]s
• 消耗积分:[N pts]
🔗 原始链接:{image_url}"""
# Add mismatch hint if user pref conflicts with knowledge-ai recommendation
if user_pref_exists and knowledge_recommended_model != used_model:
caption += f"""
💡 提示:当前任务也许用 {knowledge_recommended_model} 也会不错({reason},{cost} pts)"""
# Push image + caption to group/channel
message(
action="send",
target=group_id,
media=image_url, # Feishu/Discord will render the image
caption=caption
)
Mismatch hint example:
✅ 图片生成成功!
• 模型:Midjourney(你的偏好模型)
• 耗时:45s
• 消耗积分:8 pts
🔗 原始链接:https://...
💡 提示:当前任务也许用 SeeDream 4.5 也会不错(写实风格更合适,5 pts)
[图片直接显示在上方]
Important:
- Hint is non-intrusive — does NOT interrupt generation
- Only shown when user pref conflicts with knowledge-ai recommendation
- User can ignore the hint; image is already delivered
Platform-specific notes:
- Feishu:
message(action=send, media=url, caption="...")— caption appears below image - Discord: Image embeds automatically from URL; caption can be in message text
- Telegram: Use
message(action=send, media=url, caption="...")
⚠️ Important: Do NOT send plain text URL like https://cdn.../image.jpg. Users expect to see the actual image rendered.
Step 4 — Failure Notification (Push via message tool)
When task status = failed or any API/network error, push a failure message with alternative suggestions:
Agent implementation:
message(
action="send",
target=group_id,
message="""❌ 图片生成失败
• 原因:[natural_language_error_message]
• 建议改用:
- [Alt Model 1]([特点],[N pts])
- [Alt Model 2]([特点],[N pts])
需要我帮你用其他模型重试吗?"""
)
⚠️ CRITICAL: Error Message Translation
NEVER show technical error messages to users. Always translate API errors into natural language.
API key & credits: 密钥与积分管理入口为 imaclaw.ai(与 imastudio.com 同属 IMA 平台)。Key and subscription management: imaclaw.ai (same IMA platform as imastudio.com).
| Technical Error | ❌ Never Say | ✅ Say Instead (Chinese) | ✅ Say Instead (English) |
|---|---|---|---|
401 Unauthorized 🆕 | Invalid API key / 401 Unauthorized | ❌ API密钥无效或未授权<br>💡 生成新密钥: https://www.imaclaw.ai/imaclaw/apikey | ❌ API key is invalid or unauthorized<br>💡 Generate API Key: https://www.imaclaw.ai/imaclaw/apikey |
4008 Insufficient points 🆕 | Insufficient points / Error 4008 | ❌ 积分不足,无法创建任务<br>💡 购买积分: https://www.imaclaw.ai/imaclaw/subscription | ❌ Insufficient points to create this task<br>💡 Buy Credits: https://www.imaclaw.ai/imaclaw/subscription |
"Invalid product attribute" / "Insufficient points" | Invalid product attribute | 生成参数配置异常,请稍后重试 | Configuration error, please try again later |
Error 6006 (credit mismatch) | Error 6006 | 积分计算异常,系统正在修复 | Points calculation error, system is fixing |
Error 6010 (attribute_id mismatch) | Attribute ID does not match | 模型参数不匹配,请尝试其他模型 | Model parameters incompatible, try another model |
error 400 (bad request, e.g. invalid size) | error 400 / Bad request | 图片参数设置有误,请调整尺寸或比例 | Image parameter error, adjust size or aspect ratio |
resource_status == 2 | Resource status 2 / Failed | 图片生成遇到问题,建议换个模型试试 | Image generation failed, try another model |
status == "failed" (no details) | Task failed | 这次生成没成功,要不换个模型试试? | Generation unsuccessful, try a different model? |
timeout | Task timed out / Timeout error | 生成时间过长已超时,建议用更快的模型 | Generation took too long, try a faster model |
| Network error / Connection refused | Connection refused / Network error | 网络连接不稳定,请检查网络后重试 | Network connection unstable, check network and retry |
| Rate limit exceeded | 429 Too Many Requests / Rate limit | 请求过于频繁,请稍等片刻再试 | Too many requests, please wait a moment |
| Model unavailable | Model not available / 503 Service Unavailable | 当前模型暂时不可用,建议换个模型 | Model temporarily unavailable, try another model |
| Unsupported aspect ratio (Nano Banana Pro) | Parameter not supported | 该模型不支持自定义比例,推荐使用 SeeDream 4.5 | This model doesn't support custom aspect ratios, try SeeDream 4.5 |
Generic fallback (when error is unknown):
- Chinese:
图片生成遇到问题,请稍后重试或换个模型试试 - English:
Image generation encountered an issue, please try again or use another model
Best Practices:
- Focus on user action: Tell users what to do next, not what went wrong technically
- Be reassuring: Use phrases like "建议换个模型试试" instead of "生成失败了"
- Avoid blame: Never say "你的参数有问题" → say "参数需要调整一下"
- Provide alternatives: Always suggest 1-2 alternative models in the failure message
- Image-specific: For aspect ratio errors, recommend SeeDream 4.5 (supports custom ratios)
- 🆕 Include actionable links (v1.0.8+): For 401/4008 errors, provide clickable links to API key generation or credit purchase pages
🆕 Enhanced Error Handling (v1.0.8):
The Reflection mechanism (3 automatic retries) now provides specific, actionable suggestions for common errors:
- 401 Unauthorized: System suggests generating a new API key with clickable link
- 4008 Insufficient Points: System suggests purchasing credits with clickable link
- 500 Internal Server Error: Automatic parameter degradation (size: 4K → 2K → 1K → 512px)
- 6009 No Rule Match: Automatic parameter completion from credit_rules
- 6010 Attribute Mismatch: Automatic credit_rule reselection
- Timeout: Helpful info with dashboard link for background task status
All error handling is automatic and transparent — users receive natural language explanations with next steps.
Failure fallback table:
| Failed Model | First Alt | Second Alt |
|---|---|---|
| SeeDream 4.5 | Nano Banana2(4pts,快速便宜) | Nano Banana Pro(10-18pts,高质量) |
| Nano Banana2 | SeeDream 4.5(5pts,更高质量) | Nano Banana Pro(10-18pts) |
| Nano Banana Pro | SeeDream 4.5(5pts,性价比高) | Nano Banana2(4pts,最便宜) |
| Any / Unknown | SeeDream 4.5(5pts,默认首选) | Nano Banana2(4pts,预算紧张) |
Step 5 — Done (No Further Action Needed) 🆕
v1.2 Change: Step 5 is now simplified.
After completing Steps 0-4:
- ✅ Step 0 already sent your normal reply (appears FIRST in chat)
- ✅ Steps 1-4 pushed all updates via
messagetool (appear in order) - ✅ No further action needed — conversation is complete
Do NOT:
- ❌ Reply again with
NO_REPLY(you already replied in Step 0) - ❌ Send duplicate confirmation messages
- ❌ Use
messagetool to send the same content twice
Why this works:
User: "帮我画一只猫"
↓
[Step 0] Your normal reply: "好的!来帮你画一只萌萌的猫咪 🐱" ← Appears FIRST
↓
[Step 1] message tool push: "🎨 开始生成图片..." ← Appears SECOND
↓
[Step 2] message tool push: "⏳ 正在生成中… 45%" ← (if task takes >20s)
↓
[Step 3] message tool push: "✅ 图片生成成功! [图片]" ← Appears LAST
↓
[Step 5] Done. No further replies.
🎯 Summary: What Changed in v1.2 & v1.3
| Version | Step | Change |
|---|---|---|
| v1.2 | Step 0 | ✅ NEW: Normal reply with acknowledgment (appears FIRST) |
| v1.2 | Step 1 | Use message tool for notification only (not all messages) |
| v1.2 | Step 5 | ✅ FIXED: No further action (already replied in Step 0), no NO_REPLY |
| v1.3 | Step 3 | ✅ NEW: Added 🔗 原始链接:[url] in caption for easy copying |
Root cause of v1.1 bug:
- v1.1 used
messagetool for ALL messages (including acknowledgment) - Then replied
NO_REPLYto suppress normal reply - Result: Acknowledgment appeared LAST (because
messagetool pushes are chronological)
v1.2 fix:
- Step 0 uses normal reply (automatically appears FIRST)
- Steps 1-4 use
messagetool (appear in chronological order) - No
NO_REPLYneeded (already replied in Step 0)
v1.3 enhancement:
- Step 3 caption now includes original image URL
- Users can easily copy/share the link without asking
Complete Example: Correct v1.2 Flow
# User: "帮我画一只可爱的猫咪"
# Step 0: Normal reply (appears FIRST in chat)
# Agent's normal response mechanism automatically handles this
reply_text = "好的!来帮你画一只萌萌的猫咪 🐱"
# (This is your normal LLM response, not a tool call)
# Step 1: Push start notification
message(
action="send",
target="oc_b30b266d43b69674e3ad160de9d13cf2",
message="🎨 开始生成图片,请稍候…\n• 模型:SeeDream 4.5\n• 预计耗时:30~60秒\n• 消耗积分:5 pts"
)
# Background: Start generation
exec(command="python3 ima_image_create.py ...", background=True, sessionId=sid)
# Step 2: Progress updates (if task takes >20s)
# (Poll in background and push updates via message tool)
start_time = time.time()
while not done:
elapsed = int(time.time() - start_time)
if elapsed >= 20 and elapsed % 20 == 0: # Every 20s
progress = min(95, int(elapsed / 60 * 100))
message(
action="send",
target="oc_b30b266d43b69674e3ad160de9d13cf2",
message=f"⏳ 正在生成中… {progress}%\n已等待 {elapsed}s,预计最长 60s"
)
time.sleep(5) # Poll every 5s
# Step 3: Success (push image)
result = get_result(task_id)
message(
action="send",
target="oc_b30b266d43b69674e3ad160de9d13cf2",
media="https://ws.esxscloud.com/.../image.jpeg",
caption=f"✅ 图片生成成功!\n• 模型:SeeDream 4.5\n• 耗时:实际 35s\n• 消耗积分:5 pts\n\n🔗 原始链接:{result['url']}"
)
# Step 5: Done — no further action
# (Do NOT reply again, do NOT use NO_REPLY)
Result in chat (correct order):
[User] 帮我画一只可爱的猫咪
[Agent] 好的!来帮你画一只萌萌的猫咪 🐱 ← Step 0 (normal reply)
[Agent] 🎨 开始生成图片,请稍候… ← Step 1 (message tool)
• 模型:SeeDream 4.5
• 预计耗时:30~60秒
• 消耗积分:5 pts
[Agent] ⏳ 正在生成中… 66% ← Step 2 (message tool, if >20s)
已等待 40s,预计最长 60s
[Agent] ✅ 图片生成成功! ← Step 3 (message tool)
• 模型:SeeDream 4.5
• 耗时:实际 35s
• 消耗积分:5 pts
🔗 原始链接:https://...
[图片]
⚙️ How This Skill Works
For transparency: This skill uses a bundled Python script (scripts/ima_image_create.py) to call the IMA Open API. The script:
- Sends your prompt to IMA's servers (two domains, see below)
- Uses
--user-idonly locally as a key for storing your model preferences - Returns an image URL when generation is complete
🌐 Network Endpoints Used
This skill connects to two domains owned by IMA Studio for complete functionality:
| Domain | Purpose | What's Sent | Authentication |
|---|---|---|---|
api.imastudio.com | Main API (task creation, status polling) | Prompts, model params, task IDs | Bearer token (IMA API key) |
imapi.liveme.com | Image upload service (OSS token generation) | Image files (for i2i tasks), IMA API key | IMA API key + APP_KEY signature |
Why two domains?
api.imastudio.com: IMA's image generation API (handles task orchestration)imapi.liveme.com: IMA's media storage infrastructure (handles large file uploads)- Both services are owned and operated by IMA Studio
Privacy implications:
- Your IMA API key is sent to both domains for authentication
- Image files are uploaded to
imapi.liveme.comto obtain CDN URLs (for image_to_image tasks) - Image generation happens on
api.imastudio.comusing the CDN URLs - For text_to_image tasks (no image input), only
api.imastudio.comis contacted
Security verification:
# List all network endpoints in the code:
grep -n "https://" scripts/ima_image_create.py
# Expected output:
# 60: DEFAULT_BASE_URL = "https://api.imastudio.com"
# 61: DEFAULT_IM_BASE_URL = "https://imapi.liveme.com"
If you're concerned about the two-domain architecture:
- Review IMA Studio's privacy policy at https://imastudio.com/privacy
- Contact IMA technical support to confirm domain ownership: support@imastudio.com
- Use a test/scoped API key first (see security notice below)
⚠️ Credential Security Notice
Your IMA API key is sent to TWO domains:
api.imastudio.com— Main image generation APIimapi.liveme.com— Image upload service (only when using image_to_image tasks)
Both domains are owned by IMA Studio, but if you're concerned about credential exposure:
✅ Best practices:
- Use a test/scoped API key for initial testing (create at https://imastudio.com/api-keys)
- Set a low quota (e.g., 100 credits) for the test key
- Rotate your key after testing if needed
- Contact IMA support to confirm domain ownership: support@imastudio.com
❌ Do NOT:
- Use a production key if you're uncomfortable with the two-domain architecture
- Share your API key with others
- Commit your API key to version control
What gets sent to IMA servers:
- ✅ Your image prompt/description
- ✅ Model selection (SeeDream/Nano Banana/Midjourney)
- ✅ Image parameters (size, quality, aspect ratio, etc.)
- ✅ Image files (for image_to_image tasks, uploaded to
imapi.liveme.com) - ✅ IMA API key (for authentication to both domains)
- ❌ NO user_id (it's only used locally)
What's stored locally:
~/.openclaw/memory/ima_prefs.json- Your model preferences (< 1 KB)~/.openclaw/logs/ima_skills/- Generation logs (auto-deleted after 7 days)
Agent Execution (Internal Reference)
Note for users: You can review the script source at
scripts/ima_image_create.pyanytime.
The agent uses this script to simplify API calls. Network requests go to two IMA Studio domains:api.imastudio.com(API) andimapi.liveme.com(image uploads for i2i tasks).
Use the bundled script internally to ensure correct parameter construction:
# List available models
python3 {baseDir}/scripts/ima_image_create.py \
--api-key $IMA_API_KEY \
--task-type text_to_image \
--list-models
# Generate image
python3 {baseDir}/scripts/ima_image_create.py \
--api-key $IMA_API_KEY \
--task-type text_to_image \
--model-id doubao-seedream-4.5 \
--prompt "a cute puppy running on grass" \
--user-id {user_id} \
--output-json
# Image to image
python3 {baseDir}/scripts/ima_image_create.py \
--api-key $IMA_API_KEY \
--task-type image_to_image \
--model-id doubao-seedream-4.5 \
--prompt "turn into oil painting style" \
--input-images https://example.com/photo.jpg \
--user-id {user_id} \
--output-json
✅ Local images: --input-images accepts both HTTPS URLs and local file paths. Local files are automatically uploaded to IMA CDN by the script (no need to host them first).
The script outputs JSON — parse it to get the result URL and pass it to the user via the UX protocol messages above.
Overview
Call IMA Open API to create AI-generated images. All endpoints require an ima_* API key. The core flow is: query products → create task → poll until done.
🔒 Security & Transparency Policy
This skill is community-maintained and open for inspection.
✅ What Users CAN Do
Full transparency:
- ✅ Review all source code: Check
scripts/ima_image_create.pyandima_logger.pyanytime - ✅ Verify network calls: Network requests go to two IMA Studio domains:
api.imastudio.com(API) andimapi.liveme.com(image uploads for i2i tasks). See "🌐 Network Endpoints Used" section above for full details. - ✅ Inspect local data: View
~/.openclaw/memory/ima_prefs.jsonand log files - ✅ Control privacy: Delete preferences/logs anytime, or disable file writes (see below)
Configuration allowed:
- ✅ Set API key in environment or agent config:
- Environment variable:
export IMA_API_KEY=ima_your_key_here - OpenClaw/MCP config: Add
IMA_API_KEYto agent's environment configuration - Get your key at: https://imastudio.com
- Environment variable:
- ✅ Use scoped/test keys: Test with limited API keys, rotate after testing
- ✅ Disable file writes: Make prefs/logs read-only or symlink to
/dev/null
Data control:
- ✅ View stored data:
cat ~/.openclaw/memory/ima_prefs.json - ✅ Delete preferences:
rm ~/.openclaw/memory/ima_prefs.json(resets to defaults) - ✅ Delete logs:
rm -rf ~/.openclaw/logs/ima_skills/(auto-cleanup after 7 days anyway)
⚠️ Advanced Users: Fork & Modify
If you need to modify this skill for your use case:
- Fork the repository (don't modify the original)
- Update your fork with your changes
- Test thoroughly with limited API keys
- Document your changes for troubleshooting
Note: Modified skills may break API compatibility or introduce security issues. Official support only covers the unmodified version.
❌ What to AVOID (Security Risks)
Actions that could compromise security:
- ❌ Sharing API keys publicly or in skill files
- ❌ Modifying API endpoints to unknown servers
- ❌ Disabling SSL/TLS certificate verification
- ❌ Logging sensitive user data (prompts, IDs, etc.)
- ❌ Bypassing authentication or billing mechanisms
Why this matters:
- API Compatibility: Skill logic aligns with IMA Open API schema
- Security: Malicious modifications could leak credentials or bypass billing
- Support: Modified skills may not be supported
- Community: Breaking changes affect all users
📋 Privacy & Data Handling Summary
What this skill does with your data:
| Data Type | Sent to IMA? | Stored Locally? | User Control |
|---|---|---|---|
| Image prompts | ✅ Yes (required for generation) | ❌ No | None (required) |
| API key | ✅ Yes (authentication header) | ❌ No | Set via env var |
| user_id (optional CLI arg) | ❌ Never (local preference key only) | ✅ Yes (as prefs file key) | Change --user-id value |
| Model preferences | ❌ No | ✅ Yes (~/.openclaw) | Delete anytime |
| Generation logs | ❌ No | ✅ Yes (~/.openclaw) | Auto-cleanup 7 days |
Privacy recommendations:
- Use test/scoped API keys for initial testing
- Note:
--user-idis never sent to IMA servers - it's only used locally as a key for storing preferences in~/.openclaw/memory/ima_prefs.json - Review source code at
scripts/ima_image_create.pyto verify network calls (search forcreate_taskfunction) - Rotate API keys after testing or if compromised
Get your IMA API key: Visit https://imastudio.com to register and get started.
🔧 For Skill Maintainers Only
Version control:
- All changes must go through Git with proper version bumps (semver)
- CHANGELOG.md must document all changes
- Production deployments require code review
File checksums (optional):
# Verify skill integrity
sha256sum SKILL.md scripts/ima_image_create.py
If users report issues, verify file integrity first.
🧠 User Preference Memory
User preferences have highest priority when they exist. But preferences are only saved when users explicitly express model preferences — not from automatic model selection.
Storage: ~/.openclaw/memory/ima_prefs.json
{
"user_{user_id}": {
"text_to_image": {
"model_id": "doubao-seedream-4.5",
"model_name": "SeeDream 4.5",
"credit": 5,
"last_used": "2026-02-26T03:07:27Z"
},
"image_to_image": {
"model_id": "doubao-seedream-4.5",
"model_name": "SeeDream 4.5",
"credit": 5,
"last_used": "2026-02-25T10:00:00Z"
}
}
}
Model Selection Flow (Every Generation)
Step 1: Get knowledge-ai recommendation (if installed)
knowledge_recommended_model = read_ima_knowledge_ai() # e.g., "SeeDream 4.5"
Step 2: Check user preference
user_pref = load_prefs().get(f"user_{user_id}", {}).get(task_type) # e.g., {"model_id": "midjourney", ...}
Step 3: Decide which model to use
if user_pref exists:
use_model = user_pref["model_id"] # Highest priority
else:
use_model = knowledge_recommended_model or fallback_default
Step 4: Check for mismatch (for later hint)
if user_pref exists and knowledge_recommended_model != user_pref["model_id"]:
mismatch = True # Will add hint in success message
When to Write (User Explicit Preference ONLY)
✅ Save preference when user explicitly specifies a model:
| User says | Action |
|---|---|
用XXX / 换成XXX / 改用XXX | Switch to model XXX + save as preference |
以后都用XXX / 默认用XXX / always use XXX | Save + confirm: ✅ 已记住!以后图片生成默认用 [XXX] |
我喜欢XXX / 我更喜欢XXX | Save as preference |
❌ Do NOT save when:
- Agent auto-selects from knowledge-ai → not user preference
- Agent uses fallback default → not user preference
- User says generic quality requests (see "Clear Preference" below) → clear preference instead
When to Clear (User Abandons Preference)
🗑️ Clear preference when user wants automatic selection:
| User says | Action |
|---|---|
用最好的 / 用最合适的 / best / recommended | Clear pref + use knowledge-ai recommendation |
推荐一个 / 你选一个 / 自动选择 | Clear pref + use knowledge-ai recommendation |
用默认的 / 用新的 | Clear pref + use knowledge-ai recommendation |
试试别的 / 换个试试 (without specific model) | Clear pref + use knowledge-ai recommendation |
重新推荐 | Clear pref + use knowledge-ai recommendation |
Implementation:
del prefs[f"user_{user_id}"][task_type]
save_prefs(prefs)
⭐ Model Selection Priority
Selection flow:
- User preference (if exists) → Highest priority, always respect
- ima-knowledge-ai skill (if installed) → Professional recommendation based on task
- Fallback defaults → Use table below (only if neither 1 nor 2 exists)
Important notes:
- User preference is only saved when user explicitly specifies a model (see "When to Write" above)
- Knowledge-ai is always consulted (even when user pref exists) to detect mismatches
- When mismatch detected → add gentle hint in success message (does NOT interrupt generation)
The defaults below are FALLBACK only. User preferences have highest priority, then knowledge-ai recommendations.
Always default to the newest and most popular model. Do NOT default to the cheapest.
| Task | Default Model | model_id | version_id | Cost | Why |
|---|---|---|---|---|---|
| text_to_image | SeeDream 4.5 | doubao-seedream-4.5 | doubao-seedream-4-5-251128 | 5 pts | Latest doubao flagship, photorealistic 4K |
| text_to_image (budget) | Nano Banana2 | gemini-3.1-flash-image | gemini-3.1-flash-image | 4 pts | Fastest and cheapest option |
| text_to_image (premium) | Nano Banana Pro | gemini-3-pro-image | gemini-3-pro-image-preview | 10/10/18 pts | Premium quality, 1K/2K/4K options |
| text_to_image (artistic) | Midjourney 🎨 | midjourney | v6 | 8/10 pts | Artist-level aesthetics, creative styles |
| image_to_image | SeeDream 4.5 | doubao-seedream-4.5 | doubao-seedream-4-5-251128 | 5 pts | Latest, best i2i quality |
| image_to_image (budget) | Nano Banana2 | gemini-3.1-flash-image | gemini-3.1-flash-image | 4 pts | Cheapest option |
| image_to_image (premium) | Nano Banana Pro | gemini-3-pro-image | gemini-3-pro-image-preview | 10 pts | Premium quality |
| image_to_image (artistic) | Midjourney 🎨 | midjourney | v6 | 8/10 pts | Artist-level aesthetics, style transfer |
Selection guide by use case:
- General image generation → SeeDream 4.5 (5pts)
- Custom aspect ratio (16:9, 9:16, 4:3, etc.) → SeeDream 4.5 🌟 or Nano Banana Pro/2/MAX 🆕 (native support)
- Budget-conscious / fast generation → Nano Banana2 (4pts)
- Highest quality with size control (1K/2K/4K) → Nano Banana Pro (text_to_image: 10-18pts, image_to_image: 10pts)
- Artistic/creative styles, illustrations, paintings → Midjourney 🎨 (8-10pts)
- Style transfer / image editing → SeeDream 4.5 (5pts) or Midjourney 🎨 (artistic)
🆕 MAJOR UPDATE: Nano Banana series now has NATIVE aspect_ratio support!
- Nano Banana Pro: ✅ Supports
aspect_ratio(1:1, 16:9, 9:16, 4:3, 3:4) NATIVELY - Nano Banana2: ✅ Supports
aspect_ratio(1:1, 16:9, 9:16, 4:3, 3:4) NATIVELY - Nano Banana MAX: ✅ Supports
aspect_ratio(1:1, 16:9, 9:16, 4:3, 3:4) NATIVELY
When user requests unsupported combinations:
-
Midjourney + aspect_ratio (16:9, etc.): Recommend SeeDream 4.5 or Nano Banana series instead
❌ Midjourney 暂不支持自定义 aspect_ratio(仅支持 1024x1024 方形) ✅ 推荐方案: 1. SeeDream 4.5(支持虚拟参数 aspect_ratio) 2. Nano Banana Pro/2/MAX(原生支持 aspect_ratio) • 支持比例:1:1, 16:9, 9:16, 4:3, 3:4• 成本:5 积分(性价比最佳) • 质量:4K photorealistic
需要我帮你用 SeeDream 4.5 生成吗?
-
Any model + 8K: Inform user no model supports 8K, max is 4K (Nano Banana Pro or SeeDream 4.5)
-
Any model + 7:3 ratio: Non-standard ratio, not supported. Suggest closest supported ratio (e.g., 21:9 for ultra-wide, 2:3 for portrait)
Supported Models
⚠️ Production Environment: 4 image models are currently available in production (as of 2026-02-28).
text_to_image (4 models)
| Name | model_id | version_id | Cost | attribute_id | Size Options |
|---|---|---|---|---|---|
| SeeDream 4.5 🌟 | doubao-seedream-4.5 | doubao-seedream-4-5-251128 | 5 pts | 2341 | Default (adaptive 4k) |
| Nano Banana2 💚 | gemini-3.1-flash-image | gemini-3.1-flash-image-preview | 4/6/10/13 pts | 4400/4401/4402/4403 | 512px (4pts) / 1K (6pts) / 2K (10pts) / 4K (13pts) |
| Nano Banana Pro | gemini-3-pro-image | gemini-3-pro-image-preview | 10/10/18 pts | 2399/2400/2401 | 1K (10pts) / 2K (10pts) / 4K (18pts) |
| Midjourney 🎨 | midjourney | v6 | 8/10 pts | 5451/5452 | 480p (8pts) / 720p (10pts) |
image_to_image (4 models)
| Name | model_id | version_id | Cost | attribute_id | Size Options |
|---|---|---|---|---|---|
| SeeDream 4.5 🌟 | doubao-seedream-4.5 | doubao-seedream-4-5-251128 | 5 pts | 1611 | Default (adaptive 4k) |
| Nano Banana2 💚 | gemini-3.1-flash-image | gemini-3.1-flash-image-preview | 4/6/10/13 pts | 4404/4405/4406/4407 | 512px (4pts) / 1K (6pts) / 2K (10pts) / 4K (13pts) |
| Nano Banana Pro | gemini-3-pro-image | gemini-3-pro-image-preview | 10 pts | 2402/2403/2404 | 1K (10pts) / 2K (10pts) / 4K (18pts) |
| Midjourney 🎨 | midjourney | v6 | 8/10 pts | 5453/5454 | 480p (8pts) / 720p (10pts) |
Recommended Defaults (Based on Production Data)
| Task Type | Default Model | Reason | Cost |
|---|---|---|---|
| text_to_image | SeeDream 4.5 | Latest DouBao flagship, balanced quality/cost | 5 pts |
| text_to_image (budget) | Nano Banana2 | Fastest and cheapest option | 4 pts |
| text_to_image (artistic) | Midjourney 🎨 | Artist-level aesthetics, creative styles | 8-10 pts |
| image_to_image | SeeDream 4.5 | Newest, most stable, cost-effective | 5 pts (attribute_id: 1611) |
| image_to_image (budget) | Nano Banana2 | Cheapest option | 4 pts |
| image_to_image (artistic) | Midjourney 🎨 | Artist-level aesthetics, style transfer | 8-10 pts |
Premium option: Nano Banana Pro — Highest quality with size control (1K/2K/4K), higher cost (10-18 pts for text_to_image, 10 pts for image_to_image).
Model Capabilities (Parameter Support)
⚠️ Critical: Models have varying parameter support. Custom aspect ratios are now supported by multiple models.
| Model | Custom Aspect Ratio | Max Resolution | Size Options | Notes |
|---|---|---|---|---|
| SeeDream 4.5 | ✅ (via virtual params) | 4K (adaptive) | 8 aspect ratios | Supports 1:1, 16:9, 9:16, 4:3, 3:4, 2:3, 3:2, 21:9 (5 pts) |
| Nano Banana2 | ✅ Native support 🆕 | 4K (4096×4096) | 512px/1K/2K/4K + aspect ratios | Supports 1:1, 16:9, 9:16, 4:3, 3:4; size via attribute_id |
| Nano Banana Pro | ✅ Native support 🆕 | 4K (4096×4096) | 1K/2K/4K + aspect ratios | Supports 1:1, 16:9, 9:16, 4:3, 3:4; size via attribute_id |
| Midjourney 🎨 | ❌ (1:1 only) | 1024px (square) | 480p/720p via attribute_id | Fixed 1024x1024, artistic style focus |
Key Capabilities:
- ✅ Aspect ratio control: SeeDream 4.5 (virtual params), Nano Banana Pro/2/MAX (native support)
- ❌ 8K: Not supported by any model (max is 4K)
- ✅ Size control: Nano Banana2, Nano Banana Pro, and Midjourney support multiple size options via different
attribute_ids - ✅ Budget option: Nano Banana2 is the cheapest at 4 pts for 512px, but 4K costs 13pts
- 🎨 Artistic styles: Midjourney excels at creative, artistic, and illustration styles
- 💡 Best value: SeeDream 4.5 at 5pts offers aspect ratio flexibility; Nano Banana2 512px at 4pts for fastest/cheapest
Environment
Base URL: https://api.imastudio.com
Required/recommended headers for all /open/v1/ endpoints:
| Header | Required | Value | Notes |
|---|---|---|---|
Authorization | ✅ | Bearer ima_your_api_key_here | API key authentication |
x-app-source | ✅ | ima_skills | Fixed value — identifies skill-originated requests |
x_app_language | recommended | en / zh | Product label language; defaults to en if omitted |
Authorization: Bearer ima_your_api_key_here
x-app-source: ima_skills
x_app_language: en
⚠️ MANDATORY: Always Query Product List First
CRITICAL: You MUST call
/open/v1/product/listBEFORE creating any task.
Theattribute_idfield is REQUIRED in the create request. If it is0or missing, you get:
"Invalid product attribute"→"Insufficient points"→ task fails completely.
NEVER construct a create request from the model table alone. Always fetch the product first.
Why attribute_id is required
The attribute_id uniquely identifies the exact product variant (model + quality tier). The billing and routing system uses it to:
- Validate the product is purchasable
- Deduct the correct credits via
credit_rules - Route the request to the right backend model
How to get attribute_id
# Step 1: Query product list for the target category
GET /open/v1/product/list?app=ima&platform=web&category=text_to_image
# Step 2: Walk the V2 tree to find your model (type=3 leaf nodes only)
for group in response["data"]:
for version in group.get("children", []):
if version["type"] == "3" and version["model_id"] == target_model_id:
attribute_id = version["credit_rules"][0]["attribute_id"]
credit = version["credit_rules"][0]["points"]
model_version = version["id"] # = version_id
model_name = version["name"]
form_defaults = {f["field"]: f["value"] for f in version["form_config"]}
Quick Reference: Known attribute_ids
⚠️ Production warning: attribute_id and credit values change frequently. Always call /open/v1/product/list at runtime; table below is pre-queried reference (2026-02-27).
text_to_image:
| Model | model_id | attribute_id | credit | Size |
|---|---|---|---|---|
| SeeDream 4.5 🌟 | doubao-seedream-4.5 | 2341 | 5 pts | Default (adaptive 4k) |
| Nano Banana2 (512px) | gemini-3.1-flash-image | 4400 | 4 pts | 512px (512×512) |
| Nano Banana2 (1K) | gemini-3.1-flash-image | 4401 | 6 pts | 1K (1024×1024) |
| Nano Banana2 (2K) | gemini-3.1-flash-image | 4402 | 10 pts | 2K (2048×2048) |
| Nano Banana2 (4K) | gemini-3.1-flash-image | 4403 | 13 pts | 4K (4096×4096) |
| Nano Banana Pro (1K) | gemini-3-pro-image | 2399 | 10 pts | 1K (1024×1024) |
| Nano Banana Pro (2K) | gemini-3-pro-image | 2400 | 10 pts | 2K (2048×2048) |
| Nano Banana Pro (4K) | gemini-3-pro-image | 2401 | 18 pts | 4K (4096×4096) |
image_to_image:
| Model | model_id | attribute_id | credit | Size |
|---|---|---|---|---|
| SeeDream 4.5 🌟 | doubao-seedream-4.5 | 1611 | 5 pts | Default (adaptive 4k) |
| Nano Banana2 (512px) | gemini-3.1-flash-image | 4404 | 4 pts | 512px (512×512) |
| Nano Banana2 (1K) | gemini-3.1-flash-image | 4405 | 6 pts | 1K (1024×1024) |
| Nano Banana2 (2K) | gemini-3.1-flash-image | 4406 | 10 pts | 2K (2048×2048) |
| Nano Banana2 (4K) | gemini-3.1-flash-image | 4407 | 13 pts | 4K (4096×4096) |
| Nano Banana Pro (1K) | gemini-3-pro-image | 2402 | 10 pts | 1K (1024×1024) |
| Nano Banana Pro (2K) | gemini-3-pro-image | 2403 | 10 pts | 2K (2048×2048) |
| Nano Banana Pro (4K) | gemini-3-pro-image | 2404 | 10 pts | 4K (4096×4096) |
⚠️ Note: Production has 3 models (SeeDream 4.5 + Nano Banana2 + Nano Banana Pro). All other models mentioned in older documentation are no longer available.
Core Flow
1. GET /open/v1/product/list?app=ima&platform=web&category=<type>
→ REQUIRED: Get attribute_id, credit, model_version, form_config defaults
[image_to_image only]
2. Upload input image → get public HTTPS URL
→ See "Image Upload" section below
3. POST /open/v1/tasks/create
→ Must include: attribute_id, model_name, model_version, credit, cast, prompt (nested!)
4. POST /open/v1/tasks/detail {task_id: "..."}
→ Poll every 2–5s until medias[].resource_status == 1
→ Extract url from completed media
Common Mistakes (and resulting errors)
| Mistake | Error |
|---|---|
attribute_id is 0 or missing | "Invalid product attribute" → Insufficient points |
attribute_id outdated (production changed) | Same errors; always query product list first |
prompt at outer level instead of parameters.parameters.prompt | Prompt ignored or error |
cast missing from inner parameters | Billing validation failure |
credit wrong / missing | Error 6006 |
model_name or model_version missing | Wrong model routing |
| Skip product list, use hardcoded values | All of the above |
Image Upload (Required for image_to_image)
The IMA Open API does NOT accept raw bytes or base64 images. All input images must be public HTTPS URLs.
Script behavior: --input-images accepts both URLs and local file paths. When you pass a local path, the script automatically uploads the file to IMA CDN (imapi.liveme.com) and uses the returned URL — no separate upload step needed when calling the script.
When a user provides an image (local file, bytes, base64) and you invoke the script with a path or URL, the script handles upload for local paths. If you have bytes/base64, upload first using the IMA presigned URL flow below (or write to a temp file and pass that path).
Two-Step Upload Flow
Step 1: GET /api/rest/oss/getuploadtoken → { ful, fdl }
Step 2: PUT {ful} with raw image bytes
→ use fdl (CDN URL) as input_images value
See ima-all-ai/SKILL.md → "Image Upload" section for the complete implementation.
Quick Reference
# If user provides a URL already → use directly
if source.startswith("https://"):
input_url = source
# If user provides a local file → upload first
else:
token = get_upload_token(uid, ima_token, suffix="jpeg",
content_type="image/jpeg", ...)
upload_image_to_oss(image_bytes, "image/jpeg", token["ful"])
input_url = token["fdl"] # CDN URL → use as input_images
# Then create task
task_id = create_task("image_to_image", prompt, product,
input_images=[input_url], size="4k")
CDN:
https://ima-ga.esxscloud.com/| OSS:zhubite-imagent-bot.oss-us-east-1.aliyuncs.com
Supported Task Types
| category | Capability | Input |
|---|---|---|
text_to_image | Text → Image | prompt |
image_to_image | Image → Image | prompt + input image URL |
Detail API status values
| Field | Type | Values |
|---|---|---|
resource_status | int or null | 0=处理中, 1=可用, 2=失败, 3=已删除;null 当作 0 |
status | string | "pending", "processing", "success", "failed" |
resource_status | status | Action |
|---|---|---|
0 or null | pending / processing | Keep polling |
1 | success (or completed) | Stop when all medias are 1; read url |
1 | failed | Stop, handle error |
2 / 3 | any | Stop, handle error |
Important: Treat
resource_status: nullas 0. Stop only when all medias haveresource_status == 1. Checkstatus != "failed"when rs=1.
API 1: Product List
GET /open/v1/product/list?app=ima&platform=web&category=text_to_image
Returns a V2 tree structure: type=2 nodes are model groups, type=3 nodes are versions (leaves). Only type=3 nodes contain credit_rules and form_config.
[
{
"id": "SeeDream",
"type": "2",
"name": "SeeDream",
"model_id": "",
"children": [
{
"id": "doubao-seedream-4-5-251128",
"type": "3",
"name": "SeeDream 4.5",
"model_id": "doubao-seedream-4.5",
"credit_rules": [
{ "attribute_id": 2341, "points": 5, "attributes": { "default": "enabled" } }
],
"form_config": [
{ "field": "size", "type": "tags", "value": "4k",
"options": [{"label":"2K","value":"2k"}, {"label":"4K","value":"4k"}] }
]
}
]
}
]
How to pick a version for task creation:
- Traverse nodes to find
type=3leaves (versions) - Use
model_idandid(=model_version) from the leaf - Pick
credit_rules[].attribute_idmatching your desired quality/size - Use
form_config[].valueas defaultparametersvalues
API 2: Create Task
POST /open/v1/tasks/create
text_to_image — Verified ✅
No image input. src_img_url: [], input_images: [].
{
"task_type": "text_to_image",
"enable_multi_model": false,
"src_img_url": [],
"parameters": [{
"attribute_id": 2341,
"model_id": "doubao-seedream-4.5",
"model_name": "SeeDream 4.5",
"model_version": "doubao-seedream-4-5-251128",
"app": "ima",
"platform": "web",
"category": "text_to_image",
"credit": 5,
"parameters": {
"prompt": "a beautiful mountain sunset, photorealistic",
"size": "4k",
"n": 1,
"input_images": [],
"cast": {"points": 5, "attribute_id": 2341}
}
}]
}
image_to_image — Verified ✅
{
"task_type": "image_to_image",
"enable_multi_model": false,
"src_img_url": ["https://example.com/input.jpg"],
"parameters": [{
"attribute_id": 1611,
"model_id": "doubao-seedream-4.5",
"model_name": "SeeDream 4.5",
"model_version": "doubao-seedream-4-5-251128",
"app": "ima",
"platform": "web",
"category": "image_to_image",
"credit": 5,
"parameters": {
"prompt": "turn into oil painting style",
"size": "4k",
"n": 1,
"input_images": ["https://example.com/input.jpg","https://example.com/input.jpg"],
"cast": {"points": 5, "attribute_id": 1611}
}
}]
}
⚠️
sizemust be fromform_configoptions (e.g."2k","4k","2048x2048")."adaptive"is NOT valid for SeeDream 4.5 — causes error 400. Top-levelsrc_img_urlandparameters.input_imagesmust both contain the input image URL.
Key fields:
| Field | Required | Description |
|---|---|---|
parameters[].credit | ✅ | Must equal credit_rules[].points. Error 6006 if wrong. |
parameters[].parameters.prompt | ✅ | Prompt must be nested here, NOT at top level. |
parameters[].parameters.cast | ✅ | {"points": N, "attribute_id": N} — mirror of credit. |
parameters[].parameters.n | ✅ | Number of outputs (usually 1). |
parameters[].parameters.input_images | image_to_image | Array of input image URLs. |
top-level src_img_url | image_to_image | Must also contain the input image URL. |
Response: data.id = task ID for polling.
API 3: Task Detail (Poll)
POST /open/v1/tasks/detail
{"task_id": "<id from create response>"}
Poll every 2–5s. Completed response:
{
"id": "task_abc",
"medias": [{
"resource_status": 1,
"url": "https://cdn.../output.jpg",
"format": "jpg",
"width": 1024,
"height": 1024
}]
}
Output fields: url, width, height, format (jpg/png).
FAQ: Parameter Support & Limitations
Q1: Can I generate 16:9 or 7:3 aspect ratio images?
A: ✅ YES! Multiple models now support custom aspect ratios.
✅ Supported aspect ratios:
- SeeDream 4.5: 1:1, 16:9, 9:16, 4:3, 3:4, 2:3, 3:2, 21:9 (via virtual params)
- Nano Banana Pro/2/MAX: 1:1, 16:9, 9:16, 4:3, 3:4 (native support) 🆕
❌ Not supported:
- Midjourney: Fixed 1024×1024 (1:1 only)
- Custom ratios: 7:3, 8:3, or other non-standard ratios are NOT supported by any model
Workarounds for unsupported ratios:
- Use video models (recommended): Generate with video models (e.g., Wan 2.6 text_to_video) that support 16:9, 9:16, 1:1, then extract the first frame as an image.
- Post-processing: Generate a 1:1 image, then crop/extend to desired aspect ratio.
Model recommendation by aspect ratio need:
- Standard ratios (16:9, 9:16, 4:3, 3:4): Nano Banana Pro/2 (native support, no virtual params)
- Extended ratios (2:3, 3:2, 21:9): SeeDream 4.5 only
- Square (1:1): Any model (SeeDream, Nano Banana, or Midjourney)
Q2: How do I generate 4K images with Nano Banana Pro?
A: ✅ Use the size parameter with the correct attribute_id.
Nano Banana Pro supports 3 size options via different credit_rules:
- 1K (1024×1024): 10 pts, attribute_id
2399(default) - 2K (2048×2048): 10 pts, attribute_id
2400 - 4K (4096×4096): 18 pts, attribute_id
2401
Script usage:
python3 ima_image_create.py \
--task-type text_to_image \
--model-id gemini-3-pro-image \
--prompt "your prompt" \
--extra-params '{"size": "4K"}'
The script automatically selects the correct attribute_id (2401) when you specify size: "4K".
Q3: Can I generate 8K images?
A: ❌ No. No model currently supports 8K resolution. The maximum available is:
- Nano Banana Pro: 4K (4096×4096)
- SeeDream 4.5 / 4.0 / 3.0: 4K (adaptive)
- All others: ≤ 1280×1280
Workaround: Generate at maximum resolution (4K), then use external AI upscaling tools (e.g., Real-ESRGAN, Topaz Gigapixel) to upscale to 8K.
Q4: Which models support custom aspect ratios?
A: 🌟 Multiple models now support aspect ratios!
✅ NATIVE support (no virtual params needed):
- Nano Banana Pro: 1:1, 16:9, 9:16, 4:3, 3:4 🆕
- Nano Banana2: 1:1, 16:9, 9:16, 4:3, 3:4 🆕
- Nano Banana MAX: 1:1, 16:9, 9:16, 4:3, 3:4 🆕
✅ Virtual parameter mapping (SeeDream):
- SeeDream 4.5: 1:1, 16:9, 9:16, 4:3, 3:4, 2:3, 3:2, 21:9, 2k, 4k
❌ NOT supported:
- Midjourney: Fixed 1024×1024 (1:1) only
SeeDream 4.5 aspect_ratio support (8 ratios):
1:1→ 2048×2048 (square, 5 pts)16:9→ 2560×1440 (widescreen, 5 pts)9:16→ 1440×2560 (vertical/portrait, 5 pts)4:3→ 2304×1728 (classic, 5 pts)3:4→ 1728×2304 (vertical, 5 pts)2:3→ 1664×2496 (portrait, 5 pts)3:2→ 2496×1664 (landscape, 5 pts)21:9→ 3024×1296 (ultra-wide, 5 pts)2k/4k→ Adaptive resolution (5 pts)
Nano Banana series native support (5 ratios):
1:1,16:9,9:16,4:3,3:4- No virtual params needed, passed directly to API
Usage:
# SeeDream 4.5 (virtual params)
python3 ima_image_create.py \
--task-type text_to_image \
--model-id doubao-seedream-4.5 \
--prompt "beautiful landscape" \
--extra-params '{"aspect_ratio": "16:9"}'
# Nano Banana Pro (native support)
python3 ima_image_create.py \
--task-type text_to_image \
--model-id gemini-3-pro-image \
--prompt "beautiful landscape" \
--extra-params '{"aspect_ratio": "16:9"}'
How it works (virtual param mapping for SeeDream):
- User provides
aspect_ratio: "16:9"as input - Script queries product list and finds
is_ui_virtual=truefield - Applies
value_mapping:aspect_ratio: "16:9"→size: "2560x1440" - API receives actual parameter:
size: "2560x1440"
Nano Banana series: Aspect ratio passed directly, no mapping needed.
Q5: Why does my aspect_ratio parameter get ignored?
A: Two possibilities:
-
Model doesn't support it: Only SeeDream 4.5 and Nano Banana series support custom aspect ratios. Midjourney only supports 1:1 (square).
-
Virtual param not available in production: For SeeDream 4.5, the
is_ui_virtual=truefeature may not be deployed yet. If you get 1:1 square output despite requesting 16:9, the API doesn't have the virtual parameter mapping active.
Solution:
- Use SeeDream 4.5 or Nano Banana Pro/2/MAX for aspect ratio needs
- Use video models with custom aspect ratio, extract first frame
- Post-process: Crop or extend the image manually
Q6: What's the difference between size and resolution?
A:
size: For Nano Banana Pro only. Options: "1K", "2K", "4K". Controls output resolution via differentattribute_ids.resolution: Used in video models (e.g., "1080P", "720P", "4K"). Not applicable to text_to_image models.
Q7: Can I control the aspect ratio after generation?
A: Not directly in this skill. Options:
- Crop: Take the center/top/bottom portion of the square image to get desired ratio.
- Extend (inpainting): Use image editing APIs to extend the image to fill the target aspect ratio.
- Video workaround: Use video models with desired aspect ratio, extract first frame.
Common Mistakes
| Mistake | Fix |
|---|---|
Using attribute_id not from credit_rules | Always fetch product list first |
Placing prompt at param top-level | prompt must be inside parameters[].parameters |
Missing app / platform in parameters | Required — use ima / web |
Wrong credit value | Must exactly match credit_rules[].points (error 6006) |
size: "adaptive" for SeeDream 4.5 i2i | Use values from form_config options only |
Missing image in both src_img_url and input_images | Both fields required for image_to_image |
Python Example
import time
import requests
BASE_URL = "https://api.imastudio.com"
API_KEY = "ima_your_key_here"
HEADERS = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
"x-app-source": "ima_skills",
"x_app_language": "en",
}
def get_products(category: str) -> list:
"""Returns flat list of type=3 version nodes from V2 tree."""
r = requests.get(
f"{BASE_URL}/open/v1/product/list",
headers=HEADERS,
params={"app": "ima", "platform": "web", "category": category},
)
r.raise_for_status()
nodes = r.json()["data"]
versions = []
for node in nodes:
for child in node.get("children") or []:
if child.get("type") == "3":
versions.append(child)
for gc in child.get("children") or []:
if gc.get("type") == "3":
versions.append(gc)
return versions
def create_image_task(task_type: str, prompt: str, product: dict, input_images: list = None, **extra) -> str:
"""Returns task_id. task_type: 'text_to_image' or 'image_to_image'."""
input_images = input_images or []
rule = product["credit_rules"][0]
form_defaults = {f["field"]: f["value"] for f in product.get("form_config", []) if f.get("value") is not None}
nested_params = {
"prompt": prompt,
"n": 1,
"input_images": input_images,
"cast": {"points": rule["points"], "attribute_id": rule["attribute_id"]},
**form_defaults,
}
nested_params.update({k: v for k, v in extra.items() if k in ("size",)})
body = {
"task_type": task_type,
"enable_multi_model": False,
"src_img_url": input_images,
"parameters": [{
"attribute_id": rule["attribute_id"],
"model_id": product["model_id"],
"model_name": product["name"],
"model_version": product["id"],
"app": "ima",
"platform": "web",
"category": task_type,
"credit": rule["points"],
"parameters": nested_params,
}],
}
r = requests.post(f"{BASE_URL}/open/v1/tasks/create", headers=HEADERS, json=body)
r.raise_for_status()
return r.json()["data"]["id"]
def poll(task_id: str, interval: int = 3, timeout: int = 300) -> dict:
deadline = time.time() + timeout
while time.time() < deadline:
r = requests.post(f"{BASE_URL}/open/v1/tasks/detail", headers=HEADERS, json={"task_id": task_id})
r.raise_for_status()
task = r.json()["data"]
medias = task.get("medias", [])
if medias:
if any(m.get("status") == "failed" for m in medias):
raise RuntimeError(f"Task failed: {task_id}")
rs = lambda m: m.get("resource_status") if m.get("resource_status") is not None else 0
if any(rs(m) == 2 for m in medias):
raise RuntimeError(f"Task failed: {task_id}")
if all(rs(m) == 1 for m in medias):
return task
time.sleep(interval)
raise TimeoutError(f"Task timed out: {task_id}")
# text_to_image (SeeDream 4.5)
products = get_products("text_to_image")
task_id = create_image_task("text_to_image", "mountain sunset, photorealistic", products[0])
result = poll(task_id)
print(result["medias"][0]["url"])
# text_to_image with Midjourney (artistic style)
products = get_products("text_to_image")
midjourney = next(p for p in products if p["model_id"] == "midjourney")
task_id = create_image_task("text_to_image", "fantasy castle, impressionist painting style", midjourney)
result = poll(task_id, interval=8) # Midjourney: poll every 8s
print(result["medias"][0]["url"])
# text_to_image with aspect ratio (Nano Banana Pro - native support)
products = get_products("text_to_image")
nano_pro = next(p for p in products if p["model_id"] == "gemini-3-pro-image")
task_id = create_image_task("text_to_image", "beautiful landscape", nano_pro, aspect_ratio="16:9")
result = poll(task_id)
print(result["medias"][0]["url"])
# image_to_image (size must match form_config options, NOT "adaptive")
products = get_products("image_to_image")
seedream_i2i = next(p for p in products if p["model_id"] == "doubao-seedream-4.5")
task_id = create_image_task(
"image_to_image", "turn into oil painting style", seedream_i2i,
input_images=["https://example.com/input.jpg","https://example.com/input.jpg"],
size="4k",
)
result = poll(task_id)
print(result["medias"][0]["url"])
# image_to_image with Midjourney (artistic style transfer)
products = get_products("image_to_image")
midjourney = next(p for p in products if p["model_id"] == "midjourney")
task_id = create_image_task(
"image_to_image", "anime style, vibrant colors", midjourney,
input_images=["https://example.com/portrait.jpg"],
)
result = poll(task_id, interval=8) # Midjourney: poll every 8s
print(result["medias"][0]["url"])
Supported Models & Search Terms
Models: SeeDream 4.5, see dream, Midjourney, MJ, Nano Banana 2, Nano Banana Pro
Capabilities: image generation, text-to-image, image-to-image, AI art, product photos, character design, logo design, poster, social media graphics, t2i, i2i