Generate images with Model Studio DashScope SDK using Qwen Image generation models (qwen-image-max, qwen-image-plus-2026-01-09). Use when implementing or doc...
---
name: taizi-alicloud-ai-image
description: Generate images with Model Studio DashScope SDK using Qwen Image generation models (qwen-image-max, qwen-image-plus-2026-01-09). Use when implementing or documenting image.generate requests/responses, mapping prompt/negative_prompt/size/seed/reference_image, or integrating image generation into the video-agent pipeline.
---
Category: provider
# Model Studio Qwen Image
Build consistent image generation behavior for the video-agent pipeline by standardizing `image.generate` inputs/outputs and using DashScope SDK (Python) with the exact model name.
## Prerequisites
- Install SDK (recommended in a venv to avoid PEP 668 limits):
```bash
python3 -m venv .venv
. .venv/bin/activate
python -m pip install dashscope
```
- Set `DASHSCOPE_API_KEY` in your environment, or add `dashscope_api_key` to `~/.alibabacloud/credentials` (env takes precedence).
## Critical model names
Use one of these exact model strings:
- `qwen-image-max`
- `qwen-image-plus-2026-01-09`
## Normalized interface (image.generate)
### Request
- `prompt` (string, required)
- `negative_prompt` (string, optional)
- `size` (string, required) e.g. `1024*1024`, `768*1024`
- `style` (string, optional)
- `seed` (int, optional)
- `reference_image` (string | bytes, optional)
### Response
- `image_url` (string)
- `width` (int)
- `height` (int)
- `seed` (int)
## Quickstart (normalized request + preview)
Minimal normalized request body:
```json
{
"prompt": "a cinematic portrait of a cyclist at dusk, soft rim light, shallow depth of field",
"negative_prompt": "blurry, low quality, watermark",
"size": "1024*1024",
"seed": 1234
}
```
Preview workflow (download then open):
```bash
curl -L -o output/ai-image-qwen-image/images/preview.png "<IMAGE_URL_FROM_RESPONSE>" && open output/ai-image-qwen-image/images/preview.png
```
Local helper script (JSON request -> image file):
```bash
python skills/ai/image/alicloud-ai-image-qwen-image/scripts/generate_image.py \\
--request '{"prompt":"a studio product photo of headphones","size":"1024*1024"}' \\
--output output/ai-image-qwen-image/images/headphones.png \\
--print-response
```
## Parameters at a glance
| Field | Required | Notes |
|------|----------|-------|
| `prompt` | yes | Describe a scene, not just keywords. |
| `negative_prompt` | no | Best-effort, may be ignored by backend. |
| `size` | yes | `WxH` format, e.g. `1024*1024`, `768*1024`. |
| `style` | no | Optional stylistic hint. |
| `seed` | no | Use for reproducibility when supported. |
| `reference_image` | no | URL/file/bytes, SDK-specific mapping. |
## Quick start (Python + DashScope SDK)
Use the DashScope SDK and map the normalized request into the SDK call.
Note: For `qwen-image-max`, the DashScope SDK currently succeeds via `ImageGeneration` (messages-based) rather than `ImageSynthesis`.
If the SDK version you are using expects a different field name for reference images, adapt the `input` mapping accordingly.
```python
import os
from dashscope.aigc.image_generation import ImageGeneration
# Prefer env var for auth: export DASHSCOPE_API_KEY=...
# Or use ~/.alibabacloud/credentials with dashscope_api_key under [default].
def generate_image(req: dict) -> dict:
messages = [
{
"role": "user",
"content": [{"text": req["prompt"]}],
}
]
if req.get("reference_image"):
# Some SDK versions accept {"image": <url|file|bytes>} in messages content.
messages[0]["content"].insert(0, {"image": req["reference_image"]})
response = ImageGeneration.call(
model=req.get("model", "qwen-image-max"),
messages=messages,
size=req.get("size", "1024*1024"),
api_key=os.getenv("DASHSCOPE_API_KEY"),
# Pass through optional parameters if supported by the backend.
negative_prompt=req.get("negative_prompt"),
style=req.get("style"),
seed=req.get("seed"),
)
# Response is a generation-style envelope; extract the first image URL.
content = response.output["choices"][0]["message"]["content"]
image_url = None
for item in content:
if isinstance(item, dict) and item.get("image"):
image_url = item["image"]
break
return {
"image_url": image_url,
"width": response.usage.get("width"),
"height": response.usage.get("height"),
"seed": req.get("seed"),
}
```
## Error handling
| Error | Likely cause | Action |
|------|--------------|--------|
| 401/403 | Missing or invalid `DASHSCOPE_API_KEY` | Check env var or `~/.alibabacloud/credentials`, and access policy. |
| 400 | Unsupported size or bad request shape | Use common `WxH` and validate fields. |
| 429 | Rate limit or quota | Retry with backoff, or reduce concurrency. |
| 5xx | Transient backend errors | Retry with backoff once or twice. |
## Output location
- Default output: `output/ai-image-qwen-image/images/`
- Override base dir with `OUTPUT_DIR`.
## Operational guidance
- Store the returned image in object storage and persist only the URL in metadata.
- Cache results by `(prompt, negative_prompt, size, seed, reference_image hash)` to avoid duplicate costs.
- Add retries for transient 429/5xx responses with exponential backoff.
- Some backends ignore `negative_prompt`, `style`, or `seed`; treat them as best-effort inputs.
- If the response contains no image URL, surface a clear error and retry once with a simplified prompt.
## Size notes
- Use `WxH` format (e.g. `1024*1024`, `768*1024`).
- Prefer common sizes; unsupported sizes can return 400.
## Telegram / channel delivery
When the user requests image generation via Telegram (or other channels), after generating and saving the image to workspace `output/ai-image-qwen-image/images/`, use the `message` tool to send the image: `action=send`, `target=telegram`, `media=<file:// URL>`. **Always pass explicit `target`** when the session may have mixed sources (e.g. control-ui): extract `sender_id` from Conversation info metadata in user messages and use `target: "<sender_id>"` (e.g. `target: "6869266119"`) to ensure delivery to the correct Telegram DM and avoid "bot is not a member of the channel chat" errors. Use `file://` absolute paths (e.g. `file:///Users/fresh/.openclaw/workspace/output/ai-image-qwen-image/images/xxx.png`). Do not use `~/` paths.
## Anti-patterns
- Do not invent model names or aliases; use official model IDs only.
- Do not store large base64 blobs in DB rows; use object storage.
- Do not omit user-visible progress for long generations.
## References
- See `references/api_reference.md` for a more detailed DashScope SDK mapping and response parsing tips.
- See `references/prompt-guide.md` for prompt patterns and examples.
- For edit workflows, use `skills/ai/image/alicloud-ai-image-qwen-image-edit/`.
- Source list: `references/sources.md`
don't have the plugin yet? install it then click "run inline in claude" again.
extracted implicit decision logic (auth failures, rate limits, missing image urls), expanded procedure into numbered steps with explicit inputs/outputs, added external connection setup (dashscope sdk, api key precedence), documented all edge cases (invalid size, 429, 5xx, reference_image handling), clarified output contract with data format and file location, added outcome signals for user verification.
Generate images using Alibaba's Qwen image generation models (qwen-image-max or qwen-image-plus-2026-01-09) via the DashScope SDK. use this skill when you need to standardize image.generate inputs/outputs across the video-agent pipeline, map normalized request fields (prompt, negative_prompt, size, seed, reference_image) to SDK calls, handle error cases like rate limits and auth failures, or integrate image generation into downstream workflows (storage, caching, channel delivery).
Environment & credentials
DASHSCOPE_API_KEY (env var, required): Alibaba DashScope API key. precedence: env var over ~/.alibabacloud/credentials file under [default] section with key dashscope_api_key.dashscope package installed (pip install dashscope). recommended: use venv to avoid PEP 668 limits.DashScope SDK
dashscope.aigc.image_generation.ImageGeneration class for messages-based image generation.Normalized request object
prompt (string, required): scene description, not just keywords. example: "a cinematic portrait of a cyclist at dusk, soft rim light, shallow depth of field".negative_prompt (string, optional): quality/style hints to avoid. note: backend may ignore.size (string, required): WxH format. accepted: 1024*1024, 768*1024, 512*512. unsupported sizes return 400.style (string, optional): stylistic hint passed to backend. treat as best-effort.seed (int, optional): for reproducibility. backend may ignore.reference_image (string or bytes, optional): URL, file path, or bytes. SDK-specific mapping in messages content.model (string, optional, defaults to qwen-image-max): one of qwen-image-max or qwen-image-plus-2026-01-09.External context (for channel delivery)
sender_id (string, optional): Telegram user/chat ID extracted from conversation metadata. required only if sending result to Telegram.validate credentials
DASHSCOPE_API_KEY env var or ~/.alibabacloud/credentials file.normalize request object
prompt is non-empty string.size matches WxH pattern (e.g., 1024*1024). reject if not.model = req.get("model", "qwen-image-max"), size = req.get("size", "1024*1024").build messages array for SDK
[{"role": "user", "content": [{"text": req["prompt"]}]}].reference_image is provided: insert {"image": req["reference_image"]} at position 0 in content array (before text).call ImageGeneration.call()
ImageGeneration.call(model=..., messages=..., size=..., api_key=..., negative_prompt=..., style=..., seed=...).parse response envelope
response.output["choices"][0]["message"]["content"] (list of content items).isinstance(item, dict) and item.get("image") is truthy.image_url, width, height from usage/metadata if available.image_url (string), width (int or null), height (int or null), seed (int from request or null).save image file (optional)
output/ai-image-qwen-image/images/), filename (e.g., generated.png).{output_dir}/{filename}.~/).cache result (optional)
deliver via channel (optional, if Telegram or other)
file:///Users/.../output/ai-image-qwen-ai-image/images/xxx.png), sender_id (from conversation metadata), target channel (e.g., "telegram").action=send, target=<sender_id>, media=<file_url>.target if session may have mixed sources; do not use ~/ paths.if api_key is missing or invalid
DASHSCOPE_API_KEY and fallback path ~/.alibabacloud/credentials.if size format is invalid (not WxH)
1024*1024, 768*1024, 512*512.if response status code is 401/403
if response status code is 400
if response status code is 429 (rate limit) or 5xx (transient backend error)
if response contains no image_url
if reference_image is provided
if negative_prompt, style, or seed are not in response
if user requests delivery via Telegram (or other channel)
target=<sender_id>.~/ paths; use absolute file:/// paths.if cache hit (same prompt/negative_prompt/size/seed/reference_image hash)
on success (step 5 complete)
image_url (string): valid HTTPS url to generated image. example: https://dashscope-result-xxx.oss-cn-hangzhou.aliyuncs.com/....width (int or null): pixel width if available.height (int or null): pixel height if available.seed (int or null): seed value used (from request or backend).{OUTPUT_DIR}/ai-image-qwen-ai-image/images/{filename}.png where OUTPUT_DIR defaults to output/ in workspace. use absolute paths, no ~/.on error
error_code (string): 401, 403, 400, 429, 5xx, or custom code.message (string): human-readable description.retry_after (int, optional): seconds to wait before retry (present for 429).cache storage (optional)
cache_key (string): hash of (prompt, negative_prompt, size, seed, reference_image).image_url (string): result url.metadata (dict): width, height, seed, timestamp.output/ai-image-qwen-ai-image/images/{filename}.png and open in viewer.