Claude Opus 5.5 đã có trên SeedRouter

Nano Banana Pro trong Claude Code: một skill tạo và chỉnh sửa ảnh

Trang bị cho Claude Code một skill Nano Banana Pro: một script nhỏ gửi yêu cầu, truy vấn tác vụ và lưu ảnh, cùng một tệp SKILL.md để gọi theo tên.

Đọc dạng Markdown

Claude Code có thể tạo và chỉnh sửa ảnh bằng Nano Banana Pro thông qua một skill: một thư mục chứa tệp SKILL.md và một script ngắn gọi SeedRouter API. Bạn gõ /nano-banana-pro và mô tả hình ảnh; Claude viết prompt và chạy script, còn script gửi yêu cầu, truy vấn tác vụ và lưu ảnh vào dự án của bạn. Cùng một thư mục đó cũng dùng được trong OpenAI Codex. SeedRouter không cung cấp skill hay máy chủ MCP chính thức, vì vậy hướng dẫn này đưa bạn một skill để sao chép. Định dạng skill tuân theo tài liệu của Anthropic và OpenAI, kiểm tra ngày 29 tháng 9 năm 2026.

Claude Code tạo ảnh bằng Nano Banana Pro như thế nào?

Bản thân Claude Code không vẽ ảnh. Nó chạy lệnh, nên có thể chạy một script gọi API tạo ảnh. Khi đã có skill, một yêu cầu diễn ra như sau:

  1. Bạn gọi skill và mô tả hình ảnh, ví dụ /nano-banana-pro a hero image for the pricing page.
  2. Claude chuyển mô tả của bạn thành prompt Nano Banana Pro và chọn kích thước, tỷ lệ khung hình.
  3. Claude chạy script. Script gửi yêu cầu tới POST https://api.seedrouter.ai/v1/images/generations và nhận về một ID tác vụ.
  4. Script truy vấn GET /v1/tasks/{id} vài giây một lần cho đến khi ảnh sẵn sàng, rồi tải ảnh về thư mục images/.
  5. Claude báo cho bạn đường dẫn tệp và sau đó có thể dùng ảnh ngay trong code của bạn.

Dùng script thay vì chỉ dùng chỉ dẫn giúp các lần gọi API luôn chính xác: thân yêu cầu, vòng lặp truy vấn và cách lưu tệp lần nào cũng giống nhau, bất kể Claude viết prompt ra sao.

Cần chuẩn bị gì trước khi bắt đầu?

  • Một khóa API SeedRouter, được export trong terminal mà bạn dùng để khởi động Claude Code:
export SEEDROUTER_API_KEY="your-key"
  • Tín dụng. Mỗi lần chạy là một yêu cầu tính phí. Tài khoản mới có sẵn một khoản số dư miễn phí nhỏ, và yêu cầu thất bại không bị tính phí.
  • Python 3. Script chỉ dùng thư viện chuẩn, nên không cần cài thêm gì.

Script: gửi, truy vấn và lưu

Lưu đoạn sau thành scripts/nano_banana_pro.py trong thư mục skill:

#!/usr/bin/env python3
import argparse
import json
import os
import pathlib
import sys
import time
import urllib.error
import urllib.request

API = "https://api.seedrouter.ai/v1"
AGENT = "nano-banana-pro-skill/1.0"
MIME = {
    ".jpg": "image/jpeg",
    ".jpeg": "image/jpeg",
    ".png": "image/png",
    ".webp": "image/webp",
    ".heic": "image/heic",
    ".heif": "image/heif",
}
RATIOS = ["1:1", "2:3", "3:2", "3:4", "4:3", "4:5", "5:4", "9:16", "16:9", "21:9"]


def call(method, path, body=None):
    request = urllib.request.Request(
        API + path,
        data=None if body is None else json.dumps(body).encode(),
        method=method,
        headers={
            "Authorization": "Bearer " + os.environ["SEEDROUTER_API_KEY"],
            "Content-Type": "application/json",
            "User-Agent": AGENT,
        },
    )
    try:
        with urllib.request.urlopen(request, timeout=60) as response:
            return json.load(response)
    except urllib.error.HTTPError as error:
        sys.exit(f"HTTP {error.code}: {error.read().decode()}")


def submit(args):
    parts = [{"text": args.prompt}]
    for url in args.ref:
        suffix = pathlib.PurePosixPath(url.split("?")[0]).suffix.lower()
        if suffix not in MIME:
            sys.exit(f"Cannot tell the image type of {url}; use a .jpg, .png, .webp, .heic or .heif URL.")
        parts.append({"fileData": {"mimeType": MIME[suffix], "fileUri": url}})
    image_config = {}
    if args.ratio:
        image_config["aspectRatio"] = args.ratio
    if args.size:
        image_config["imageSize"] = args.size
    generation_config = {"responseModalities": ["IMAGE"]}
    if image_config:
        generation_config["imageConfig"] = image_config
    body = {
        "model": args.model,
        "contents": [{"role": "user", "parts": parts}],
        "generationConfig": generation_config,
    }
    return call("POST", "/images/generations", body)["id"]


def wait(task_id, out_dir, timeout):
    deadline = time.monotonic() + timeout
    while time.monotonic() < deadline:
        task = call("GET", "/tasks/" + task_id)
        if task["status"] == "completed":
            out_dir.mkdir(parents=True, exist_ok=True)
            extension = "jpg" if task["output"]["output_format"] == "jpeg" else task["output"]["output_format"]
            for index, image in enumerate(task["output"]["data"]):
                path = out_dir / f"{task_id}-{index}.{extension}"
                download = urllib.request.Request(image["url"], headers={"User-Agent": AGENT})
                with urllib.request.urlopen(download, timeout=120) as response:
                    path.write_bytes(response.read())
                print(path)
            return
        if task["status"] == "failed":
            sys.exit(f"Task {task_id} failed: {task['error']['message']}")
        time.sleep(3)
    sys.exit(f"Task {task_id} is still processing. Resume with --resume {task_id}")


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--prompt")
    parser.add_argument("--ref", action="append", default=[])
    parser.add_argument("--ratio", choices=RATIOS)
    parser.add_argument("--size", choices=["1K", "2K", "4K"])
    parser.add_argument("--model", default="gemini-3-pro-image",
                        choices=["gemini-3-pro-image", "gemini-3-pro-image-official"])
    parser.add_argument("--out", default="images")
    parser.add_argument("--timeout", type=int, default=600)
    parser.add_argument("--resume")
    args = parser.parse_args()
    if args.resume:
        task_id = args.resume
    elif args.prompt:
        task_id = submit(args)
        print(f"task {task_id}", file=sys.stderr)
    else:
        parser.error("--prompt or --resume is required")
    wait(task_id, pathlib.Path(args.out), args.timeout)


if __name__ == "__main__":
    main()

Script này làm những việc sau:

  • Chỉ gửi một lần. --prompt là nội dung prompt, --ref thêm URL một ảnh tham chiếu (lặp lại để thêm nhiều ảnh), còn --ratio và --size đặt imageConfig. Thân yêu cầu là định dạng generateContent của Google cộng thêm trường model, đúng như tài liệu tham khảo API Nano Banana Pro quy định.
  • In ra ID tác vụ ngay khi tác vụ được tạo, trước khi chờ.
  • Truy vấn rồi mới lưu. Khi tác vụ hoàn thành, script tải từng ảnh về images/ và in ra từng đường dẫn. Khi tác vụ thất bại, script in ra lý do.
  • Tiếp tục thay vì gửi lại. Nếu hết thời gian chờ, --resume <task id> sẽ kiểm tra lại đúng tác vụ đó. Gửi lần thứ hai sẽ là một yêu cầu tính phí thứ hai.
  • Gửi kèm header User-Agent. Hãy giữ dòng này: một số máy chủ từ chối User-Agent mặc định của Python, và thiếu nó thì việc tải ảnh có thể thất bại với lỗi 403.

Bạn có thể chạy thử riêng script trước khi để Claude dùng:

python3 scripts/nano_banana_pro.py --prompt "A ceramic teapot on a linen tablecloth, soft window light" --ratio 16:9 --size 2K

Bản thân skill: SKILL.md chứa gì?

Tài liệu của Claude Code mô tả skill là một thư mục có tệp SKILL.md: "YAML frontmatter nằm giữa các dấu --- cho Claude biết khi nào dùng skill, và nội dung markdown là các chỉ dẫn Claude làm theo khi skill chạy." Các tệp hỗ trợ, như thư mục scripts/, nằm ngay bên cạnh.

Lưu nội dung sau thành SKILL.md trong cùng thư mục:

---
name: nano-banana-pro
description: Generate or edit an image with Nano Banana Pro (gemini-3-pro-image) through the SeedRouter API and save it into the project. Use when the user asks for an image, illustration, icon, poster or edit of an existing image.
argument-hint: "[what the image should show]"
disable-model-invocation: true
---

Create an image for this request: $ARGUMENTS

1. Write one prompt in full sentences: subject, framing, action, setting and style. Put any text that must appear in the image in double quotes and say where it goes. For an edit, say what changes and what must stay the same.
2. Choose --ratio from 1:1, 2:3, 3:2, 3:4, 4:3, 4:5, 5:4, 9:16, 16:9, 21:9 and --size from 1K, 2K, 4K (4K only for print).
3. Reference images must be public HTTPS URLs ending in .jpg, .png, .webp, .heic or .heif, passed with --ref. If the user points to a local file, ask for a public URL instead. Never send base64.
4. Show the user the prompt and options, and wait for approval. Each run is a paid request.
5. Run: python3 ${CLAUDE_SKILL_DIR}/scripts/nano_banana_pro.py --prompt "..." [--ratio R] [--size S] [--ref URL]
6. If it stops with "still processing", run it again with --resume and the same task ID. Never submit the same request twice.
7. Report the saved file paths. If the task failed, explain the reason and suggest a change to the prompt.

Có hai trường quan trọng ở đây:

  • disable-model-invocation: true nghĩa là chỉ bạn mới có thể khởi động skill. Tài liệu của Claude Code khuyên dùng nó cho "các quy trình có tác dụng phụ hoặc bạn muốn tự kiểm soát thời điểm chạy". Mỗi lần chạy đều tốn tiền, nên Claude không được tự ý quyết định tạo ảnh.
  • ${CLAUDE_SKILL_DIR} được thay bằng thư mục của chính skill, nên script chạy được dù bạn cài skill ở đâu.

Đặt skill ở đâu và chạy như thế nào?

Claude Code tải skill chủ yếu từ hai nơi:

Vị tríĐường dẫnDùng được ở
Cá nhân~/.claude/skills/nano-banana-pro/Mọi dự án của bạn trên máy này
Dự án.claude/skills/nano-banana-pro/Repository này; commit lên để chia sẻ với nhóm

Thư mục hoàn chỉnh trông như sau:

nano-banana-pro/
├── SKILL.md
└── scripts/
    └── nano_banana_pro.py

Khởi động Claude Code trong terminal đã đặt SEEDROUTER_API_KEY, rồi gõ tên skill kèm theo điều bạn muốn:

/nano-banana-pro a 16:9 hero image for the pricing page: a calm desk with a laptop, a notebook and a cup of tea, soft morning light, muted green palette, no text

Claude hiển thị prompt và các tùy chọn, bạn duyệt, và ảnh sẽ nằm trong images/. Trừ khi bạn đã cho phép lệnh đó từ trước, Claude Code còn hỏi quyền trước khi chạy script, tức là một lớp kiểm tra thứ hai trước khi bị tính phí.

Về bản thân prompt, hướng dẫn prompt Nano Banana Pro đi sâu hơn vào cấu trúc, chữ trong ảnh và ảnh tham chiếu.

Codex có dùng được cùng skill Nano Banana Pro không?

Có. Cả hai công cụ đều tuân theo tiêu chuẩn mở Agent Skills. Tài liệu Codex của OpenAI cho biết skill "là một thư mục có tệp SKILL.md cùng các script và tài liệu tham khảo tùy chọn", và tệp đó "phải có name và description", điều mà skill ở trên đều có.

Codex tìm skill ở các thư mục khác:

Vị tríĐường dẫn
Cá nhân~/.agents/skills/nano-banana-pro/
Repository.agents/skills/nano-banana-pro/

Sao chép thư mục vào đó, hoặc tạo một symlink trỏ tới nó; cả hai công cụ đều hỗ trợ thư mục skill dạng symlink. Trong Codex, chạy /skills hoặc gõ $nano-banana-pro để gọi skill.

Có hai điểm khác biệt cần biết:

  • Đường dẫn script. ${CLAUDE_SKILL_DIR} là biến thay thế của Claude Code. Codex liệt kê đường dẫn tệp của từng skill cho mô hình, nên nó có thể tìm thấy scripts/nano_banana_pro.py nằm cạnh SKILL.md; nếu nó chạy sai đường dẫn, hãy chỉ cho nó vị trí của script.
  • Tự động gọi. disable-model-invocation là một trường của Claude Code. Cách tương đương trong Codex là đặt tệp agents/openai.yaml trong thư mục skill với allow_implicit_invocation: false dưới policy, để Codex chỉ chạy skill khi bạn gọi.

Script cần quyền truy cập mạng để kết nối tới api.seedrouter.ai. Nếu agent của bạn chạy trong sandbox không có mạng, hãy cho phép truy cập mạng cho phiên đó.

Làm sao chỉnh sửa những ảnh đã có trong dự án?

Nano Banana Pro chỉnh sửa dựa trên ảnh tham chiếu, và API chỉ nhận ảnh tham chiếu dưới dạng URL công khai. Một tệp trên ổ đĩa của bạn cần được lưu trữ ở đâu đó trước, chẳng hạn trong bucket lưu trữ của riêng bạn, rồi mới truyền vào bằng --ref.

Ảnh được tạo ra thì đã được lưu trữ sẵn: mỗi tác vụ hoàn thành đều trả về ảnh dưới dạng URL. Để tinh chỉnh một kết quả, hãy truyền lại URL đó làm ảnh tham chiếu cùng với thay đổi bạn muốn:

/nano-banana-pro edit the last image: keep the desk and the laptop, change the tea cup to a glass of water, and make the light warmer

Claude dùng lại URL của ảnh trước qua --ref và viết một prompt chỉnh sửa nói rõ phần nào giữ nguyên. Với chỉnh sửa nhiều lượt mà mô hình giữ được ngữ cảnh riêng giữa các lượt, tài liệu tham khảo API giải thích cách gửi lại các lượt trước; script ở trên mỗi lần chỉ gửi một lượt.

Nếu bạn đã dùng GPT Image 2 từ một coding agent, GPT Image 2 trong Codex và Claude Code trình bày cách thiết lập đó, vốn xoay quanh một prompt bạn dán vào agent.

Câu hỏi thường gặp

SeedRouter có skill hay máy chủ MCP chính thức cho Nano Banana Pro không?

Không. SeedRouter không cung cấp. Skill trong hướng dẫn này là một thư mục bình thường thuộc về bạn và bạn có thể sửa, nó gọi API công khai bằng khóa của bạn.

Vì sao script truy vấn tác vụ thay vì chờ ảnh trả về?

Trên SeedRouter, yêu cầu Nano Banana Pro là tác vụ: gửi đi sẽ nhận về một ID tác vụ, và ảnh có khi tác vụ hoàn thành. Truy vấn giúp mỗi kết nối đều ngắn, và nếu việc chờ bị gián đoạn thì ID tác vụ vẫn còn hiệu lực.

Có dùng cùng skill này cho Nano Banana 2 được không?

Được, chỉ cần sửa một chút. Đổi giá trị mặc định và các lựa chọn của --model trong script thành gemini-3.1-flash-image, rồi thêm 512 vào các lựa chọn của --size, một kích thước Nano Banana 2 hỗ trợ còn Pro thì không. Nano Banana 2 vs Pro vs 2 Lite so sánh các mô hình.

Tải skill có tốn phí không?

Không. Việc Claude đọc SKILL.md không tốn gì trên SeedRouter. Mỗi lần chạy script là một yêu cầu, được tính theo mức giá trên trang mô hình, và tác vụ thất bại không bị tính phí.

Bắt đầu tạo ảnh từ Claude Code

Tạo thư mục, export khóa của bạn và thử /nano-banana-pro với một ảnh nhỏ trước. Giá hiện tại có trên trang Nano Banana Pro, còn mọi trường của yêu cầu có trong tài liệu tham khảo API.

Hướng dẫn liên quan