Claude Opus 5.5을(를) SeedRouter에서 사용할 수 있습니다

Claude Code에서 Nano Banana Pro 사용하기: 이미지를 생성하고 편집하는 skill

Claude Code에 Nano Banana Pro skill을 만들어 주는 방법: 요청을 제출하고 작업을 폴링해 이미지를 저장하는 작은 스크립트와, 이름으로 호출하는 SKILL.md.

Markdown으로 읽기

Claude Code는 skill을 통해 Nano Banana Pro로 이미지를 생성하고 편집할 수 있습니다. skill은 SKILL.md 파일과 SeedRouter API를 호출하는 짧은 스크립트가 들어 있는 폴더입니다. /nano-banana-pro를 입력하고 원하는 이미지를 설명하면, Claude가 프롬프트를 쓰고 스크립트를 실행합니다. 스크립트는 요청을 제출하고 작업을 폴링한 뒤 이미지를 프로젝트에 저장합니다. 같은 폴더를 OpenAI Codex에서도 쓸 수 있습니다. SeedRouter는 공식 skill이나 MCP 서버를 제공하지 않으므로, 이 가이드에서 그대로 복사해 쓸 수 있는 skill을 소개합니다. skill 형식은 2026년 9월 29일에 확인한 Anthropic과 OpenAI의 문서를 따릅니다.

Claude Code는 Nano Banana Pro로 어떻게 이미지를 만드나요?

Claude Code는 직접 그림을 그리지 않습니다. 명령을 실행할 수 있으므로, 이미지 API를 호출하는 스크립트를 실행할 수 있습니다. skill을 설치하면 요청 한 번은 다음과 같이 진행됩니다.

  1. skill을 호출하고 이미지를 설명합니다. 예: /nano-banana-pro a hero image for the pricing page.
  2. Claude가 설명을 Nano Banana Pro 프롬프트로 바꾸고, 크기와 비율을 고릅니다.
  3. Claude가 스크립트를 실행합니다. 스크립트는 요청을 POST https://api.seedrouter.ai/v1/images/generations로 보내고 작업 ID를 받습니다.
  4. 스크립트는 이미지가 준비될 때까지 몇 초마다 GET /v1/tasks/{id}를 폴링한 다음, 이미지를 images/ 폴더에 내려받습니다.
  5. Claude가 파일 경로를 알려 주고, 그 이미지를 바로 코드에서 쓸 수도 있습니다.

지침만이 아니라 스크립트를 쓰면 API 호출을 정확하게 유지할 수 있습니다. Claude가 어떤 프롬프트를 쓰든 요청 본문, 폴링 루프, 파일 저장 방식은 매번 같습니다.

시작하기 전에 무엇이 필요한가요?

  • SeedRouter API 키. Claude Code를 실행할 터미널에서 내보내 둡니다.
export SEEDROUTER_API_KEY="your-key"
  • 잔액. 실행할 때마다 유료 요청이 한 번 발생합니다. 새 계정에는 소액의 무료 잔액이 있고, 실패한 요청은 과금되지 않습니다.
  • Python 3. 스크립트는 표준 라이브러리만 쓰므로 따로 설치할 것이 없습니다.

스크립트: 제출, 폴링, 저장

아래 코드를 skill 폴더 안에 scripts/nano_banana_pro.py로 저장합니다.

#!/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()

이 스크립트가 하는 일은 다음과 같습니다.

  • 한 번만 제출합니다. --prompt는 프롬프트 텍스트, --ref는 참조 이미지 URL 추가(여러 장이면 반복해서 지정), --ratio와 --size는 imageConfig 설정입니다. 요청 본문은 Google의 generateContent 형식에 model 필드를 더한 것으로, Nano Banana Pro API 레퍼런스의 정의와 같습니다.
  • 작업이 생성되는 즉시 작업 ID를 출력하고, 그다음에 기다리기 시작합니다.
  • 폴링한 뒤 저장합니다. 작업이 완료되면 모든 이미지를 images/에 내려받고 경로를 출력합니다. 작업이 실패하면 이유를 출력합니다.
  • 다시 제출하지 않고 이어서 확인합니다. 기다리다 시간이 초과되면 --resume <task id>로 같은 작업을 다시 확인합니다. 다시 제출하면 두 번째 유료 요청이 됩니다.
  • User-Agent 헤더를 보냅니다. 이 줄은 지우지 마세요. Python 기본 User-Agent를 거부하는 서버가 있어서, 이 줄이 없으면 다운로드가 403으로 실패할 수 있습니다.

Claude에게 맡기기 전에 스크립트만 따로 테스트할 수 있습니다.

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

skill 본체: SKILL.md에는 무엇을 쓰나요?

Claude Code 문서는 skill을 SKILL.md 파일이 있는 디렉터리로 설명합니다. "--- 표시 사이의 YAML 프런트매터는 언제 skill을 쓸지 Claude에게 알려 주고, markdown 본문은 skill이 실행될 때 Claude가 따르는 지침입니다." scripts/ 폴더 같은 보조 파일은 그 옆에 둡니다.

같은 폴더에 아래 내용을 SKILL.md로 저장합니다.

---
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.

여기서 중요한 필드는 두 가지입니다.

  • disable-model-invocation: true는 오직 사용자만 skill을 시작할 수 있게 합니다. Claude Code 문서는 이 설정을 "부작용이 있거나 실행 시점을 직접 통제하고 싶은 워크플로"에 권합니다. 실행할 때마다 비용이 들므로, Claude가 스스로 판단해 이미지를 생성해서는 안 됩니다.
  • ${CLAUDE_SKILL_DIR}는 skill 자신의 폴더로 바뀌므로, skill을 어디에 설치하든 스크립트가 제대로 실행됩니다.

skill은 어디에 두고, 어떻게 실행하나요?

Claude Code는 주로 두 곳에서 skill을 불러옵니다.

위치경로사용 범위
개인~/.claude/skills/nano-banana-pro/이 컴퓨터의 모든 프로젝트
프로젝트.claude/skills/nano-banana-pro/현재 저장소. 커밋하면 팀과 공유됩니다

완성된 폴더는 다음과 같습니다.

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

SEEDROUTER_API_KEY를 설정한 터미널에서 Claude Code를 실행하고, skill 이름 뒤에 원하는 내용을 입력합니다.

/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가 프롬프트와 옵션을 보여 주고 사용자가 승인하면, 이미지가 images/에 저장됩니다. 명령을 미리 허용해 두지 않았다면 Claude Code는 스크립트를 실행하기 전에 권한도 요청합니다. 비용이 발생하기 전의 두 번째 확인 절차입니다.

프롬프트 자체에 대해서는 Nano Banana Pro 프롬프트 가이드에서 구조, 이미지 속 텍스트, 참조 이미지를 더 자세히 다룹니다.

Codex에서도 같은 Nano Banana Pro skill을 쓸 수 있나요?

네. 두 도구 모두 개방형 Agent Skills 표준을 따릅니다. OpenAI의 Codex 문서에 따르면 skill은 "SKILL.md 파일과 선택적인 스크립트, 참고 자료가 있는 디렉터리"이며, 이 파일에는 "name과 description이 반드시 있어야" 합니다. 위의 skill에는 둘 다 있습니다.

Codex는 다른 폴더에서 skill을 찾습니다.

위치경로
개인~/.agents/skills/nano-banana-pro/
저장소.agents/skills/nano-banana-pro/

폴더를 그곳에 복사하거나 심볼릭 링크를 만드세요. 두 도구 모두 심볼릭 링크로 연결된 skill 폴더를 지원합니다. Codex에서는 /skills를 실행하거나 $nano-banana-pro를 입력해 호출합니다.

알아 둘 차이점이 두 가지 있습니다.

  • 스크립트 경로. ${CLAUDE_SKILL_DIR}는 Claude Code의 치환 변수입니다. Codex는 각 skill의 파일 경로를 모델에 보여 주므로 SKILL.md 옆의 scripts/nano_banana_pro.py를 찾을 수 있지만, 엉뚱한 경로를 실행하면 스크립트 위치를 알려 주세요.
  • 자동 호출. disable-model-invocation은 Claude Code의 필드입니다. Codex에서 같은 효과를 내려면 skill 폴더에 agents/openai.yaml 파일을 두고 policy 아래에 allow_implicit_invocation: false를 설정합니다. 그러면 Codex는 사용자가 호출할 때만 skill을 실행합니다.

스크립트가 api.seedrouter.ai에 접속하려면 네트워크 접근이 필요합니다. 에이전트가 네트워크가 막힌 샌드박스에서 실행된다면, 해당 세션에서 네트워크 접근을 허용하세요.

프로젝트에 이미 있는 이미지는 어떻게 편집하나요?

Nano Banana Pro는 참조 이미지를 바탕으로 편집하는데, API는 참조 이미지를 공개 URL로만 받습니다. 디스크에 있는 파일은 먼저 자신의 스토리지 버킷 같은 곳에 올린 뒤 --ref로 넘겨야 합니다.

생성된 이미지는 이미 호스팅되어 있습니다. 완료된 작업은 이미지를 URL로 돌려주기 때문입니다. 결과를 더 다듬으려면 그 URL을 참조 이미지로 다시 넘기고 원하는 변경 사항을 적으세요.

/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는 이전 이미지의 URL을 --ref로 다시 쓰고, 무엇을 그대로 둘지 밝힌 편집 프롬프트를 작성합니다. 턴 사이에 모델 자체의 맥락을 유지하는 멀티턴 편집이 필요하다면, 이전 턴을 다시 보내는 방법이 API 레퍼런스에 나와 있습니다. 위 스크립트는 한 번에 한 턴씩 보냅니다.

이미 코딩 에이전트에서 GPT Image 2를 쓰고 있다면, Codex와 Claude Code에서 GPT Image 2 사용하기에서 그 설정을 다룹니다. 그쪽은 에이전트에 붙여 넣는 프롬프트가 중심입니다.

자주 묻는 질문

SeedRouter 공식 Nano Banana Pro skill이나 MCP 서버가 있나요?

없습니다. SeedRouter는 제공하지 않습니다. 이 가이드의 skill은 사용자가 소유하고 자유롭게 고칠 수 있는 평범한 폴더이며, 사용자의 키로 공개 API를 호출합니다.

스크립트는 왜 이미지를 기다리지 않고 폴링하나요?

SeedRouter에서 Nano Banana Pro 요청은 작업입니다. 제출하면 작업 ID가 돌아오고, 작업이 완료되면 이미지가 나옵니다. 폴링을 쓰면 연결이 짧게 유지되고, 기다리다 중단되더라도 작업 ID는 계속 유효합니다.

같은 skill을 Nano Banana 2에도 쓸 수 있나요?

네, 몇 군데만 고치면 됩니다. 스크립트의 --model 기본값과 선택지를 gemini-3.1-flash-image로 바꾸고, --size 선택지에 512를 추가하세요. 이 크기는 Nano Banana 2는 지원하지만 Pro는 지원하지 않습니다. 모델 비교는 Nano Banana 2 vs Pro vs 2 Lite를 참고하세요.

skill을 불러오기만 해도 비용이 드나요?

아니요. Claude가 SKILL.md를 읽는 것만으로는 SeedRouter에서 비용이 발생하지 않습니다. 스크립트를 한 번 실행할 때마다 요청 한 번으로 모델 페이지의 요금이 부과되며, 실패한 작업은 과금되지 않습니다.

Claude Code에서 이미지 생성 시작하기

폴더를 만들고 키를 내보낸 뒤, 작은 이미지로 먼저 /nano-banana-pro를 시험해 보세요. 현재 가격은 Nano Banana Pro 페이지에, 모든 요청 필드는 API 레퍼런스에 있습니다.

관련 가이드