
Agnes Free Image
- 104 installs
- 174 repo stars
- Updated June 1, 2026
- kangarooking/agnes-free-model-skills
Helps with ai & agent building tasks.
About
agnes-free-image is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- agnes-free-image
- AI & Agent Building
- AI-coding skill
Agnes Free Image by the numbers
- 104 all-time installs (skills.sh)
- +6 installs in the week ending Aug 2, 2026 (Skillselion tracking)
- Ranked #4,243 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 2, 2026 (Skillselion catalog sync)
npx skills add https://github.com/kangarooking/agnes-free-model-skills --skill agnes-free-imageAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 104 |
|---|---|
| repo stars | ★ 174 |
| Last updated | June 1, 2026 |
| Repository | kangarooking/agnes-free-model-skills ↗ |
What it does
Helps with ai & agent building tasks.
Files
Agnes Free Image
Use this skill to generate or transform images with agnes-image-2.1-flash.
Credential Rule
Read the API key from the environment. Do not hardcode keys in prompts, scripts, skill files, commits, or shell history.
Preferred variable:
export AGNES_API_KEY="..."The helper also accepts AGNES_TOKEN as a fallback.
Quick Start
Text-to-image:
python3 scripts/agnes_image.py generate \
--prompt "A luminous floating city above a misty canyon at sunrise, cinematic realism" \
--size 1024x768 \
--output-dir ./outputs/agnes-free-imageImage-to-image with a public image URL:
python3 scripts/agnes_image.py generate \
--prompt "Transform the scene into a rain-soaked cyberpunk night while preserving the composition" \
--image-url "https://example.com/input.png" \
--size 1024x768 \
--output-dir ./outputs/agnes-free-imageValidate the request shape without calling the API:
python3 scripts/agnes_image.py generate \
--prompt "A detailed AI workflow dashboard poster, clean editorial style" \
--size 1024x1024 \
--dry-runPrompt Pattern
Use this structure for text-to-image:
[Subject] + [Scene / Environment] + [Style] + [Lighting] + [Composition] + [Quality Requirements]For image-to-image, say both what should change and what should remain unchanged.
Workflow
1. Decide whether the request is text-to-image or image-to-image. 2. Turn vague visual requests into a concrete prompt with subject, environment, style, lighting, composition, and detail level. 3. Use scripts/agnes_image.py generate. Prefer --dry-run first for complex prompts or reference images. 4. Save returned image URLs locally with --output-dir when the response includes downloadable URLs. 5. Read references/api.md when the raw response shape or advanced parameters matter.
Notes
- Endpoint:
POST https://apihub.agnes-ai.com/v1/images/generations - Model:
agnes-image-2.1-flash - Default size in the helper is
1024x768. - For image-to-image, input images must be URL-accessible and are sent under
extra_body.image. - The helper asks for URL responses with
extra_body.response_format: "url".
Reference
Read references/api.md when you need request fields, response handling, or prompt examples from the source docs.
interface:
display_name: "Agnes Free Image"
short_description: "Free Agnes image API helper"
default_prompt: "Use $agnes-free-image to generate an image with the free Agnes image API."
Agnes Free Image API Reference
Source document: outputs/wechat-runs/2026-05-30-agnes-ai-free-api/图片模型文档.md.
Model
- Name:
agnes-image-2.1-flash - Use cases: text-to-image, image-to-image, high-information-density visuals, composition-preserving transformations, marketing creatives, thumbnails, banners, storytelling visuals.
Endpoint
POST https://apihub.agnes-ai.com/v1/images/generations
Authorization: Bearer YOUR_API_KEY
Content-Type: application/jsonRequest Fields
| Field | Type | Required | Notes |
|---|---|---|---|
model | string | yes | Fixed to agnes-image-2.1-flash. |
prompt | string | yes | Text instruction for generation or editing. |
size | string | no | Output size such as 1024x768. |
extra_body | object | no | Advanced workflow parameters. |
extra_body.image | array | no | Input image URLs for image-to-image. |
extra_body.response_format | string | no | Use url to request image URLs. |
Text-To-Image Request
curl https://apihub.agnes-ai.com/v1/images/generations \
-H "Authorization: Bearer $AGNES_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "agnes-image-2.1-flash",
"prompt": "A luminous floating city above a misty canyon at sunrise, cinematic realism",
"size": "1024x768"
}'Image-To-Image Request
curl https://apihub.agnes-ai.com/v1/images/generations \
-H "Authorization: Bearer $AGNES_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "agnes-image-2.1-flash",
"prompt": "Transform the scene into a rain-soaked cyberpunk night with neon reflections while preserving the composition",
"size": "1024x768",
"extra_body": {
"image": ["https://example.com/input-image.png"],
"response_format": "url"
}
}'Prompt Structure
[Subject] + [Scene / Environment] + [Style] + [Lighting] + [Composition] + [Quality Requirements]For image-to-image, specify:
- What should change
- What should remain unchanged
- Composition or subject preservation requirements
High-Density Visuals
For complex visuals, describe:
- Main subject
- Background environment
- Important secondary details
- Style and lighting
- Composition constraints
- Preservation requirements for image-to-image
Notes
- Use
agnes-image-2.1-flashas the model name. - For text-to-image,
modelandpromptare required. - For image-to-image, provide input image URLs under
extra_body.image. - Use
extra_body.response_format: "url"when generated results should be returned as image URLs. - Do not expose temporary API keys in public documentation.
#!/usr/bin/env python3
"""Generate Agnes Image 2.1 Flash images and download URL results."""
from __future__ import annotations
import argparse
import json
import mimetypes
import os
from pathlib import Path
import re
import sys
from typing import Any
from urllib import error, parse, request
API_BASE = os.environ.get("AGNES_API_BASE", "https://apihub.agnes-ai.com").rstrip("/")
MODEL = "agnes-image-2.1-flash"
class ApiError(RuntimeError):
def __init__(self, message: str, status: int | None = None, payload: Any = None):
super().__init__(message)
self.status = status
self.payload = payload
def get_api_key() -> str:
token = os.environ.get("AGNES_API_KEY") or os.environ.get("AGNES_TOKEN")
if not token:
raise SystemExit("Missing API key. Set AGNES_API_KEY, for example: export AGNES_API_KEY='...'")
return token
def parse_json_or_text(raw: str) -> Any:
try:
return json.loads(raw)
except json.JSONDecodeError:
return raw
def extract_error_message(payload: Any) -> str | None:
if isinstance(payload, dict):
err = payload.get("error")
if isinstance(err, dict):
return str(err.get("message") or err.get("type") or err)
if isinstance(err, str):
return err
if payload.get("message"):
return str(payload["message"])
return None
def request_json(method: str, url: str, token: str, payload: dict[str, Any] | None = None) -> dict[str, Any]:
data = None
headers = {"Authorization": f"Bearer {token}"}
if payload is not None:
data = json.dumps(payload, ensure_ascii=False).encode("utf-8")
headers["Content-Type"] = "application/json"
req = request.Request(url, data=data, headers=headers, method=method)
try:
with request.urlopen(req, timeout=180) as resp:
raw = resp.read().decode("utf-8")
except error.HTTPError as exc:
raw = exc.read().decode("utf-8", errors="replace")
parsed = parse_json_or_text(raw)
message = extract_error_message(parsed) or f"HTTP {exc.code}: {raw}"
raise ApiError(message, status=exc.code, payload=parsed) from exc
except error.URLError as exc:
raise ApiError(f"Network error: {exc}") from exc
parsed = parse_json_or_text(raw)
if not isinstance(parsed, dict):
raise ApiError(f"Expected JSON object, got: {raw[:300]}")
if parsed.get("error"):
raise ApiError(extract_error_message(parsed) or "API returned an error", payload=parsed)
return parsed
def validate_size(value: str) -> None:
if re.fullmatch(r"[1-9][0-9]{1,4}x[1-9][0-9]{1,4}", value) is None:
raise SystemExit(f"Invalid size '{value}'. Use a pixel size such as 1024x768.")
def build_payload(args: argparse.Namespace) -> dict[str, Any]:
validate_size(args.size)
payload: dict[str, Any] = {
"model": MODEL,
"prompt": args.prompt,
"size": args.size,
}
if args.image_url:
payload["extra_body"] = {
"image": args.image_url,
"response_format": "url",
}
elif args.response_format:
payload["extra_body"] = {"response_format": args.response_format}
return payload
def collect_urls(value: Any) -> list[str]:
urls: list[str] = []
if isinstance(value, dict):
for key, nested in value.items():
if key in {"url", "image_url"} and isinstance(nested, str) and nested.startswith(("http://", "https://")):
urls.append(nested)
else:
urls.extend(collect_urls(nested))
elif isinstance(value, list):
for item in value:
urls.extend(collect_urls(item))
return urls
def filename_from_url(url: str, index: int) -> str:
parsed = parse.urlparse(url)
name = Path(parsed.path).name
if not name or "." not in name:
ext = mimetypes.guess_extension("image/png") or ".png"
name = f"agnes-image-{index:02d}{ext}"
return name
def download_urls(urls: list[str], output_dir: str) -> list[Path]:
directory = Path(output_dir).expanduser()
directory.mkdir(parents=True, exist_ok=True)
paths: list[Path] = []
for index, url in enumerate(urls, start=1):
path = directory / filename_from_url(url, index)
try:
with request.urlopen(url, timeout=180) as resp:
path.write_bytes(resp.read())
except error.URLError as exc:
print(f"Download failed for {url}: {exc}", file=sys.stderr)
continue
paths.append(path)
return paths
def cmd_generate(args: argparse.Namespace) -> int:
payload = build_payload(args)
url = f"{args.api_base.rstrip('/')}/v1/images/generations"
if args.dry_run:
print(json.dumps({"url": url, "payload": payload}, ensure_ascii=False, indent=2))
return 0
token = get_api_key()
try:
response = request_json("POST", url, token, payload)
except ApiError as exc:
print(f"Agnes API error: {exc}", file=sys.stderr)
if exc.payload is not None:
print(json.dumps(exc.payload, ensure_ascii=False, indent=2), file=sys.stderr)
return 1
print(json.dumps(response, ensure_ascii=False, indent=2))
urls = collect_urls(response)
if args.output_dir and urls:
for path in download_urls(urls, args.output_dir):
print(f"Downloaded: {path}")
elif args.output_dir:
print("No downloadable image URLs found in response.", file=sys.stderr)
return 0
def build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(description="Generate images with Agnes Image 2.1 Flash.")
subparsers = parser.add_subparsers(dest="command", required=True)
generate = subparsers.add_parser("generate", help="Submit an image generation request")
generate.add_argument("--prompt", required=True)
generate.add_argument("--size", default="1024x768")
generate.add_argument("--image-url", action="append", help="Reference image URL for image-to-image; repeatable")
generate.add_argument("--response-format", default="url", choices=["url"])
generate.add_argument("--output-dir", help="Download returned image URLs into this directory")
generate.add_argument("--api-base", default=API_BASE)
generate.add_argument("--dry-run", action="store_true", help="Print request JSON without calling the API")
generate.set_defaults(func=cmd_generate)
return parser
def main() -> int:
parser = build_parser()
args = parser.parse_args()
return args.func(args)
if __name__ == "__main__":
raise SystemExit(main())