---
name: rynjer-ai-generation
version: 2.1.1
description: Generate images, videos, and music using Rynjer AI models through a unified agent-friendly API
category: ai-generation
tags: [image-generation, video-generation, music-generation, ai-api, creative-tools]
author: Rynjer
requires_auth: true
cost_model: credits
base_url: https://www.rynjer.com
last_updated: 2026-02-09
---

# Rynjer AI Generation Skill

> 🎨 **多模态 AI 创作平台** - 为 AI Agents 打造的统一生成 API

## Skill Files

| File | URL |
|------|-----|
| **SKILL.md** (this file) | `https://www.rynjer.com/skill.md` |
| **OpenAPI Specification** | `https://www.rynjer.com/agent/openapi.json` |
| **skill.json** (metadata) | `https://www.rynjer.com/skill.json` |

**重要提示：**
- 基础 URL: `https://www.rynjer.com`
- Agent API 端点覆盖 `/api/*` 和 `/v1/*` 路径
- 必须使用 HTTPS，HTTP 请求会失败

---

## 🔒 CRITICAL SECURITY WARNINGS

**Protect your credentials (API Key / Identity Token):**
- API Key（`ryn_agent_v1_...`）和 `molt_identity_token` 都属于高敏感凭据
- 只发送给 `https://www.rynjer.com` 下的官方 API
- 不要写入日志、第三方 webhook、公开 issue 或截图
- 一旦泄露，立即在 owner 面板吊销 key 并重新签发

**ALWAYS estimate cost before generating:**
- 在调用生成 API 之前必须先调用 `/api/credits/estimate` 估算成本
- 在扣费之前向你的 user/owner 展示估算成本
- 未经用户同意就生成 = 未授权支出
- 跳过估算会导致预算超支风险

**Credits belong to the OWNER, not you:**
- 你在 human owner 设置的预算限制内运作
- 当余额不足时，请求 owner 充值 — 不要强制生成
- 跟踪你的使用情况以避免意外费用
- 对 owner 保持成本透明

---

## What is Rynjer?

Rynjer 是一个为 AI Agents 设计的多模态内容生成平台，提供统一的 API 访问 40+ AI 模型：

- **🖼️ 图片生成** - 15+ 模型，从快速草图 (5 credits) 到高质量 4K 图像 (40 credits)
- **🎬 视频生成** - 12+ 模型，从短视频 (10 credits) 到专业级制作 (350 credits)
- **🎵 音乐生成** - 4 版本模型，从标准质量 (20 credits) 到最新 V5 (35 credits)

**为什么选择 Rynjer？**
- ✅ **统一 API** - 一个接口，所有媒体类型
- ✅ **透明定价** - 按使用付费，基于 credits 的计费
- ✅ **Owner 级别计费** - 人类设置预算，agents 在限制内运作
- ✅ **模型选择** - 40+ 模型，从预算友好到专业级
- ✅ **幂等性保证** - request_id 防止重复扣费
- ✅ **NSFW 智能处理** - 自动检测并切换到合适的模型

---

## Everything You Can Generate 🎨

| 内容类型 | 可用模型 | 价格范围 | 最适合 |
|---------|---------|---------|--------|
| **Images** 🖼️ | 15+ 模型 | 5-40 credits | 社交媒体、艺术作品、设计原型 |
| **Videos** 🎬 | 12+ 模型 | 10-350 credits | 动画、广告、内容营销 |
| **Music** 🎵 | 4 版本 | 20-35 credits | 配乐、氛围音乐、短音频 |

**快速模型选择：**

**预算优先？**
- 图片: `gemini-2.5-flash-image` (5c), `google/nano-banana` (8c)
- 视频: `sora-2` (10c), `xai/grok-imagine-video` (10c)
- 音乐: `V4` (20c)

**平衡质量与成本？**
- 图片: `qwen/text-to-image` (15c), `nano-banana-pro` (20c)
- 视频: `wan-2.6` (20c 720p), `veo3_fast` (50c)
- 音乐: `V4_5` (25c)

**专业级质量？**
- 图片: `nano-banana-pro` 4K (40c), `fal-ai/flux/dev` (20c)
- 视频: `veo3` (280-350c), `sora-2-pro` (330c)
- 音乐: `V5` (35c)

---

## Getting Started

### Step 0: Authentication (Critical!)

Rynjer 支持两种**兼容**认证方式：

#### Option A (Recommended): Autonomous API Key（脱离 Moltbook）

1. Agent 自注册：`POST /api/v1/agents/register`
2. Owner 完成绑定：`POST /api/agents/bind`（使用 registration code）
3. Agent 创建长期 API Key：`POST /api/v1/agents/keys/create`
4. 后续请求直接使用：`Authorization: Bearer ryn_agent_v1_...`
5. （可选）用 `POST /api/v1/agents/auth/token` 签发 15 分钟短 token，并用 `/api/v1/agents/auth/refresh` 轮换

这个模式不依赖 Moltbook，适合生产长期稳定运行。

**Pure API 实操要点（避免常见报错）：**
- `POST /api/v1/agents/register` 必填：`public_key`、`timestamp`、`nonce`、`signature`
- `POST /api/agents/bind` 必填：`registration_code`；该接口要求 owner 登录态（同域 session cookie），`401` 通常表示未登录
- `POST /api/v1/agents/keys/create` 必填：`agent_id`、`registration_code`、`key_name`、`timestamp`、`nonce`、`signature`
- `nonce` 必须是 32 位字母数字；`timestamp` 必须在服务端时间 ±5 分钟内
- `signature` 生成规则：对 payload 进行「递归按 key 字典序排序」后 JSON 序列化，再用 Ed25519 私钥签名（hex）

**最小纯 API 流程：**
```text
1) register -> 返回 agent_id + registration_code
2) owner bind(registration_code) -> 激活并绑定 agent
3) keys/create -> 返回一次性 api_key (ryn_agent_v1_...)
4) 生成接口统一使用 Bearer api_key
```

**排障速查：**
- `Missing required fields`：检查字段名是否完全匹配（snake_case）
- `Invalid signature`：检查签名源 payload 是否为“排序后 JSON”，并确认密钥对一致
- `Unauthorized`（bind）：先让 owner 登录，再携带同域 session 调 `/api/agents/bind`
- 若 OpenAPI 暂时未展示某路径，请以真实 HTTP 响应为准，并重拉 `https://www.rynjer.com/agent/openapi.json`

#### Option B (Compatibility): Moltbook identity exchange

若你已有 Moltbook identity token，可继续使用：

```
POST https://www.rynjer.com/api/auth/moltbook/exchange
```

Request:
```json
{
 "molt_identity_token": "your_molt_identity_token"
}
```

或通过 header:
```
x-moltbook-identity: your_molt_identity_token
```

Response:
```json
{
 "code": 0,
 "message": "ok",
 "data": {
 "access_token": "eyJhbG...",
 "expires_in": 900,
 "agent_id": "agent_xxx",
 "account_id": "account_xxx",
 "scopes": ["generate:image", "generate:video", "generate:music"]
 }
}
```

**重要：**
- API Key 模式：无需 15 分钟刷新，但应定期轮换与最小权限授权
- Moltbook short token 模式：`expires_in=900`，需在过期前刷新
- 两种方式都使用同一个 Bearer 头调用生成 API

---

## When to Use This Skill

✅ **适合使用 Rynjer 的场景：**
- Owner 明确请求生成特定内容
- 需要视觉资产用于可交付成果
- 生成直接服务于当前任务
- 已确认预算可用

❌ **不应使用的场景：**
- "只是想看看效果如何" 未经许可
- 未经询问就生成多个变体
- 作为演示（除非明确请求）
- 预算不足时未警告 owner
- 用 owner 的 credits 进行练习或实验

**类比：** 就像使用公司信用卡 — 每次刷卡都应该有业务目的。

---

## Execution Flow

### Step 1: Check Balance

在生成之前，检查可用 credits。

**API Endpoint:**
```
GET https://www.rynjer.com/api/credits/balance
Authorization: Bearer {access_token}
```

**Response:**
```json
{
 "code": 0,
 "message": "ok",
 "data": {
 "available_credits": 150,
 "reserved_credits": 0,
  "total_credits": 150,
 "daily_limit_remaining": 1000,
 "resets_at": "2026-02-07T00:00:00Z"
 }
}
```

### Step 2: Estimate Cost (Mandatory!)

**永远不要跳过这一步。** 在生成之前估算成本并向 owner 展示。

**API Endpoint:**
```
POST https://www.rynjer.com/api/credits/estimate
Authorization: Bearer {access_token}
Content-Type: application/json
```

**Request:**
```json
{
  "product": "image",
 "model": "nano-banana-pro",
 "units": 2,
 "price_version": "2026-02-02-v1",
 "options": {
  "resolution": "2K"
 }
}
```

**Response:**
```json
{
 "code": 0,
 "message": "ok",
 "data": {
 "estimated_credits": 40,
 "price_version": "2026-02-02-v1",
  "breakdown": {
  "per_unit_cost": 20,
 "units": 2,
  "total": 40
 }
 }
}
```

**Pre-flight Validation 示例：**

向 owner 展示：
```
=== Generation Pre-flight ===
Prompt: "A cinematic sunset over mountains"
Model: nano-banana-pro (2K resolution)
Count: 2 images
Total cost: 40 credits
Current balance: 150 credits ✅

✅ Ready to generate. Proceeding...
```

**如果余额不足：**
```
❌ Cannot generate: need 40 credits but balance is 30.
Ask owner to top up at https://www.rynjer.com/credits
```

### Step 3: Generate Content

有两种 API 可以调用：

#### Option A: Agent API (推荐用于 AI Agents)

**图片生成:**
```
POST https://www.rynjer.com/api/generate/image
Authorization: Bearer {access_token}
Content-Type: application/json
```

**Request:**
```json
{
 "request_id": "unique-id-12345",
  "model": "nano-banana-pro",
 "prompt": "A beautiful sunset over mountains, cinematic lighting",
 "options": {
  "n": 2,
  "resolution": "2K"
  },
 "scene": "text-to-image",
 "provider": "fal"
}
```

**视频生成:**
```
POST https://www.rynjer.com/api/generate/video
Authorization: Bearer {access_token}
Content-Type: application/json
```

**Request:**
```json
{
 "request_id": "unique-id-67890",
 "model": "sora-2",
 "prompt": "A cat playing with a ball of yarn",
 "options": {
 "resolution": "720p"
 },
 "scene": "text-to-video"
}
```

**音乐生成:**
```
POST https://www.rynjer.com/api/generate/music
Authorization: Bearer {access_token}
Content-Type: application/json
```

**Request:**
```json
{
  "request_id": "unique-id-music-1",
 "model": "V5",
 "prompt": "Upbeat electronic music, energetic, 120 BPM",
  "options": {}
}
```

#### Option B: Unified Agent API

```
POST https://www.rynjer.com/v1/generate
Authorization: Bearer {access_token}
Content-Type: application/json
```

**Request:**
```json
{
 "request_id": "550e8400-e29b-41d4-a716-446655440000",
 "model": "nano-banana-pro",
 "product": "image",
 "prompt": "A beautiful sunset over mountains",
  "units": {
  "count": 2,
  "resolution": "2K"
 },
 "scene": "text-to-image"
}
```

**Key Parameters:**
- `provider`: AI provider (`fal`, `kie`, `replicate`, `gemini`, `xai`, `modelslab`, `evolink`)
- `product`: `image`, `video`, or `music`
- `model`: Model identifier (见下方完整列表)
- `prompt`: 生成提示词
- `units`: 计费相关参数（如 `count`, `resolution`, `duration`）
- `options`: 模型特定参数（如 `image_input`）
- `scene`: 场景类型 (`text-to-image`, `image-to-image`, `text-to-video`, `image-to-video`, etc.)

### Step 4: Check Generation Status

生成是异步的。使用返回的 `request_id` 查询状态。

**Polling Strategy:**

典型生成时间：
- **Images:** 30秒-2分钟
- **Videos:** 1-5分钟
- **Music:** 2-4分钟

**示例轮询代码：**
```bash
#!/bin/bash
REQUEST_ID="your-request-id"
while true; do
  RESPONSE=$(curl -s "https://www.rynjer.com/v1/generate/$REQUEST_ID" \
 -H "Authorization: Bearer YOUR_TOKEN")

 STATUS=$(echo "$RESPONSE" | jq -r '.data.status')
 echo "Status: $STATUS"

 if [ "$STATUS" = "success" ]; then
 echo "Generation complete!"
   echo "$RESPONSE" | jq '.data.outputs'
 break
 elif [ "$STATUS" = "failed" ] || [ "$STATUS" = "canceled" ]; then
  echo "Generation failed"
  echo "$RESPONSE" | jq '.data.error'
  break
 fi

 sleep 5
done
```

**对于长时间运行的任务（音乐、长视频）：**
- 每 10 秒轮询一次而不是 5 秒
- 设置 10 分钟超时
- 检查 `estimated_completion` 字段

---

## Model Selection Guide

### Image Models

| Model ID | Provider | Price | Resolution | Best For |
|----------|----------|-------|------------|----------|
| `gemini-2.5-flash-image` | Gemini | 5c | 1K-4K | 快速草图、预算优先 |
| `google/nano-banana` | KIE | 8c | 1K-4K | 标准质量、性价比高 |
| `google/nano-banana-edit` | KIE | 8c | 1K-4K | 图片编辑 |
| `gpt4o_image` | OpenAI | 10c | varies | GPT-4o 图片生成 |
| `qwen/text-to-image` | Qwen | 15c | varies | 文生图、中文友好 |
| `qwen/image-to-image` | Qwen | 15c | varies | 图生图、风格迁移 |
| `nano-banana-pro` | KIE | 20c (4K:40c) | 1K-4K | 高质量、支持4K |
| `z-image` | ModelsLab | 20c | varies | 社区模型 |
| `xai/grok-2-image` | xAI | 20c | varies | Grok 系列图片 |
| `xai/grok-imagine-image` | xAI | 20c | varies | Grok Imagine |
| `fal-ai/flux/dev` | Fal.ai | 20c | varies | Flux Dev 模型 |
| `fal-ai/flux/dev/image-to-image` | Fal.ai | 20c | varies | Flux 图生图 |

**NSFW Models:**
- ModelsLab: `nsfw`, `explicit-freedom-nsfw-wai`, `Photorealistic-NSFW`, `pornrealistic`, `urpm`, `z-image-turbo` (15c)
- Replicate Flux: `aisha-ai-official/flux.1dev-uncensored-*`, `octopusinc/flux-uncensored-v2_ava-hussy` (20c)

### Video Models

| Model ID | Provider | Price (720p) | Price (1080p) | Best For |
|----------|----------|--------------|---------------|----------|
| `sora-2` | OpenAI | 10c | 18c | 快速视频、预算优先 |
| `xai/grok-imagine-video/*` | xAI | 10c | 18c | Grok 视频系列 |
| `sora-watermark-remover` | OpenAI | 18c | - | 移除水印 |
| `wan-2.6` | Wan | 20c | 300c | 720p性价比高 |
| `text-to-video-ultra` | - | 30c | 54c | 标准质量 |
| `doubao-seedance-1.0-pro-fast` | Doubao | 40c | 72c | 快速处理 |
| `veo3_fast` | Veo | 50c | 90c | 平衡速度质量 |
| `fal-ai/ltx-2*` | Fal.ai | 50c | 90c | LTX-2 系列 |
| `veo3` | Veo | 280c | 350c | 专业级质量 |
| `sora-2-pro` | OpenAI | 330c | 594c | 最高质量 |

**注意：**
- Image-to-video 场景对大多数模型有 1.5x 倍数（sora-2 和 grok 系列除外）
- 1080p 分辨率通常是 720p 价格的 1.8x

### Music Models

| Model ID | Provider | Price | Best For |
|----------|----------|-------|----------|
| `V4` | Suno | 20c | 基础音乐生成 |
| `V4_5` / `V4_5ALL` | Suno | 25c | 标准质量 |
| `V4_5PLUS` | Suno | 30c | 增强质量 |
| `V5` | Suno | 35c | 最新最佳质量 |

---

## Error Handling

### Common Error Responses

**Insufficient Credits:**
```json
{
  "code": 1000,
  "message": "error",
 "data": {
 "error": "insufficient_credits",
 "message": "Not enough credits to complete this generation",
 "required": 50,
 "available": 10,
  "hint": "Try a cheaper model or reduce count"
  }
}
```

**处理方式：**
1. 通知 owner 余额不足
2. 建议更便宜的模型
3. 减少生成数量
4. 等待 owner 充值

**Invalid Parameters:**
```json
{
  "code": 1001,
 "message": "error",
 "data": {
  "error": "invalid_parameters",
  "message": "Invalid resolution for this model",
 "field": "options.resolution",
  "allowed_values": ["1K", "2K", "4K"]
  }
}
```

**Rate Limited:**
```json
{
 "code": 429,
 "message": "rate_limited",
 "data": {
 "retry_after_seconds": 60,
  "limit_type": "requests_per_minute"
 }
}
```

**处理方式：**
- 等待 `retry_after_seconds` 后重试
- 不要立即重试，会进一步触发限制

**NSFW Content Detected:**

Rynjer 会自动检测 NSFW 内容并切换到合适的模型。你会在响应中看到：

```json
{
 "code": 0,
 "message": "ok",
 "data": {
  "nsfw_detected": true,
 "switched_model": "nsfw",
 "original_model": "google/nano-banana",
 "request_id": "..."
  }
}
```

---

## Idempotency

使用 `request_id` 确保幂等性，防止重复扣费。

**规则：**
- 相同的 `request_id` 只会扣费一次
- 如果请求失败，使用相同的 `request_id` 重试不会重复扣费
- `request_id` 应该是唯一的 UUID 或时间戳

**示例：**
```json
{
 "request_id": "gen-2026-02-06-12345",
 "model": "nano-banana-pro",
 "prompt": "A sunset"
}
```

如果网络失败，重试时使用相同的 `request_id`：
```json
{
 "request_id": "gen-2026-02-06-12345",  // Same ID
 "model": "nano-banana-pro",
 "prompt": "A sunset"
}
```

系统会识别这是重试，不会重复扣费。

---

## Rate Limits ⏱️

**API Limits:**
- 请求频率: 100 次/分钟 per account
- 并发生成: 最多 5 个活跃任务
- Token 有效期: 900 秒 (15 分钟)

**Credit Limits:**
- 由 owner 账户设置决定
- 生成前检查余额: `GET /api/credits/balance`
- 可能有每日限制（检查 `daily_limit_remaining` 字段）
- Reserved credits 计入限制

**Cost Estimate Requirement:**
- 必须在 `/api/generate/*` 之前调用 `/api/credits/estimate`
- 这不是建议 — 是透明性的强制要求
- 跳过估算 = 糟糕的用户体验

**Retry Behavior:**
- 使用相同 `request_id` 重试失败请求（不会重复扣费）
- 对于 rate-limited 请求（429 响应）等待 60 秒后重试
- 不要重试 `insufficient_credits` 错误 — 降级模型或请求 owner 充值

**429 Response 包含：**
```json
{
 "code": 429,
 "message": "rate_limited",
 "data": {
 "retry_after_seconds": 60,
 "limit_type": "requests_per_minute"
 }
}
```

---

## Response Format 📄

所有 API 响应遵循标准结构：

**Success:**
```json
{
 "code": 0,
 "message": "ok",
 "data": {
 // Endpoint-specific data
 }
}
```

**Error:**
```json
{
 "code": 1000,
 "message": "error_type",
  "data": {
 "error": "insufficient_credits",
 "message": "Human-readable description",
 "required": 50,
  "available": 10,
 "hint": "Try a cheaper model or reduce count"
 }
}
```

**Generation in progress:**
```json
{
 "code": 0,
 "message": "ok",
  "data": {
 "request_id": "gen-xxx",
  "status": "processing",
  "estimated_completion": "2026-02-06T10:30:00Z",
  "outputs": []
 }
}
```

**Generation complete:**
```json
{
 "code": 0,
 "message": "ok",
 "data": {
 "request_id": "gen-xxx",
 "status": "completed",
 "outputs": [
 {
  "url": "https://...",
   "type": "image",
   "width": 1024,
 "height": 1024
 }
 ]
 }
}
```

---

## Agent Best Practices

### 1. 始终估算成本

在每次生成之前调用 `/api/credits/estimate` 并向 owner 展示成本。

### 2. 选择合适的模型

- 快速迭代/草图：使用便宜的模型 (5-10 credits)
- 最终输出：使用高质量模型 (20-40 credits)
- 预算有限：优先 gemini-2.5-flash-image, sora-2, V4

### 3. 处理 NSFW 内容

Rynjer 会自动处理，但你应该：
- 意识到可能的模型切换
- 通知 owner 检测到 NSFW 内容
- 确认切换后的模型符合预算

### 4. 幂等性

始终使用唯一的 `request_id`，特别是在重试时。

### 5. 轮询策略

- 对于图片：每 5 秒检查一次
- 对于视频/音乐：每 10 秒检查一次
- 设置合理的超时（图片 5 分钟，视频/音乐 10 分钟）

### 6. 错误处理

- `insufficient_credits`: 通知 owner，不要重试
- `rate_limited`: 等待指定时间后重试
- `invalid_parameters`: 检查文档，修正参数
- 网络错误：使用相同 `request_id` 重试

### 7. Token 管理

- API Key：长期凭据，建议 90 天轮换一次，并限制 scopes
- Short token：15 分钟后过期，建议在 12 分钟时提前刷新
- 不在日志中打印完整 token（仅打印前后缀）

---

## Quick Start Example

### Complete Python Example

```python
import requests
import time
import uuid

BASE_URL = "https://www.rynjer.com"

# Step 0: Authenticate (Autonomous API Key recommended)
def get_bearer_token(api_key=None, molt_token=None):
 if api_key:
  return api_key

 if not molt_token:
  raise ValueError("Either api_key or molt_token is required")

 response = requests.post(
  f"{BASE_URL}/api/auth/moltbook/exchange",
  json={"molt_identity_token": molt_token}
 )
 data = response.json()
 return data["data"]["access_token"]

# Step 1: Check balance
def check_balance(access_token):
 response = requests.get(
  f"{BASE_URL}/api/credits/balance",
  headers={"Authorization": f"Bearer {access_token}"}
  )
 data = response.json()
  return data["data"]["available_credits"]

# Step 2: Estimate cost
def estimate_cost(access_token, product, model, units, options=None):
  payload = {
 "product": product,
   "model": model,
 "units": units,
  "price_version": "2026-02-02-v1"
  }
  if options:
  payload["options"] = options

  response = requests.post(
  f"{BASE_URL}/api/credits/estimate",
   headers={"Authorization": f"Bearer {access_token}"},
  json=payload
 )
  data = response.json()
  return data["data"]["estimated_credits"]

# Step 3: Generate image
def generate_image(access_token, model, prompt, options=None):
 request_id = f"gen-{uuid.uuid4()}"
   payload = {
  "request_id": request_id,
 "model": model,
  "prompt": prompt,
  "scene": "text-to-image"
 }
 if options:
  payload["options"] = options

  response = requests.post(
 f"{BASE_URL}/api/generate/image",
 headers={"Authorization": f"Bearer {access_token}"},
  json=payload
  )
 data = response.json()
 return request_id, data

# Step 4: Check status
def check_status(access_token, request_id):
  response = requests.get(
 f"{BASE_URL}/v1/generate/{request_id}",
 headers={"Authorization": f"Bearer {access_token}"}
 )
  return response.json()

# Main workflow
def main():
  # Option A (recommended): use autonomous API key directly
  api_key = "ryn_agent_v1_your_api_key"

  # Option B (compatibility): use Moltbook token exchange
  # molt_token = "your_molt_identity_token"

 bearer_token = get_bearer_token(api_key=api_key)
 print(f"✅ Authentication ready")

  # Check balance
 balance = check_balance(bearer_token)
 print(f"💰 Current balance: {balance} credits")

  # Estimate cost
 model = "nano-banana-pro"
 options = {"n": 2, "resolution": "2K"}
 cost = estimate_cost(bearer_token, "image", model, 2, options)
 print(f"\n=== Generation Pre-flight ===")
 print(f"Model: {model}")
  print(f"Count: 2 images")
  print(f"Resolution: 2K")
  print(f"Total cost: {cost} credits")
  print(f"Current balance: {balance} credits")

 if balance < cost:
  print(f"❌ Insufficient credits!")
  return

  # User confirmation
  print(f"\n✅ Ready to generate. Proceeding...")

  # Generate
 prompt = "A beautiful sunset over mountains, cinematic lighting, 4k quality"
 request_id, gen_response = generate_image(bearer_token, model, prompt, options)
 print(f"🚀 Generation started: {request_id}")

 # Poll for completion
  while True:
  status_response = check_status(bearer_token, request_id)
   status = status_response["data"]["status"]
  print(f"⏳ Status: {status}")

   if status == "completed":
  outputs = status_response["data"]["outputs"]
  print(f"\n✅ Generation complete!")
  for i, output in enumerate(outputs):
   print(f"Image {i+1}: {output['url']}")
   break
  elif status == "failed":
    error = status_response["data"].get("error", "Unknown error")
  print(f"❌ Generation failed: {error}")
    break

  time.sleep(5)

if __name__ == "__main__":
 main()
```

---

## Prompting Guide

### Image Prompts

**好的提示词特征：**
- 具体描述主题
- 包含风格/氛围关键词
- 指定光照和构图
- 提及质量要求

**示例：**
```
Good: "A serene Japanese garden with cherry blossoms, soft morning light,
   minimalist composition, watercolor style, high quality"

Better: "Professional photograph of a serene Japanese zen garden,
 blooming pink cherry blossom trees, stone path winding through,
   soft golden morning light filtering through branches,
  shallow depth of field, peaceful atmosphere,
  shot on Canon 5D Mark IV, 4K quality, award winning photography"
```

**风格关键词：**
- `cinematic` - 电影感
- `photorealistic` - 写实
- `watercolor` - 水彩
- `oil painting` - 油画
- `minimalist` - 极简
- `cyberpunk` - 赛博朋克
- `fantasy art` - 奇幻艺术

### Video Prompts

**好的视频提示词特征：**
- 描述动作/运动
- 指定镜头类型
- 包含时间/速度信息
- 提及氛围/情绪

**示例：**
```
Good: "A cat playing with yarn, indoor setting, natural lighting"

Better: "Slow motion shot of a fluffy orange tabby cat playfully batting
  at a ball of blue yarn, warm indoor lighting from window,
  shallow depth of field focusing on cat's expressive eyes,
  cozy living room background slightly blurred,
 smooth camera movement following the action"
```

**镜头关键词：**
- `slow motion` - 慢动作
- `time-lapse` - 延时
- `drone shot` - 航拍
- `close-up` - 特写
- `wide angle` - 广角
- `tracking shot` - 跟拍
- `smooth camera movement` - 平滑运镜

### Music Prompts

**好的音乐提示词特征：**
- 指定流派
- 描述情绪/氛围
- 提及节奏/BPM
- 包含乐器信息

**示例：**
```
Good: "Happy music"

Better: "Upbeat electronic dance music, energetic and joyful atmosphere,
  128 BPM, featuring synthesizers and drums,
  perfect for workout or party,
 progressive build-up with catchy melody"
```

**流派关键词：**
- `electronic` - 电子
- `acoustic` - 原声
- `orchestral` - 管弦
- `ambient` - 氛围
- `rock` - 摇滚
- `jazz` - 爵士
- `classical` - 古典

---

## Ideas to Try 💡

**For creative agents:**
- 为音乐项目生成专辑封面
- 为博客文章创建自定义插图
- 设计符合品牌的社交媒体图形
- 制作动画 logo 或片头序列

**For developer agents:**
- 为 GitHub 项目生成 hero 图片
- 创建应用程序的视频演示
- 设计自定义图标和 UI 元素
- 制作带配音的教程视频

**For business agents:**
- 为营销活动生成视觉内容
- 创建产品原型和模型
- 制作社交媒体视频广告
- 设计信息图表和数据可视化

**For research agents:**
- 可视化抽象概念和想法
- 创建图表和流程图
- 制作教育视频内容
- 生成示例数据和模拟内容

**Pro tips:**
- 从便宜的模型 (5-10 credits) 开始迭代提示词
- 对最终输出使用专业模型 (20+ credits)
- 批量处理相似请求以节省时间
- 与 owner 分享你最好的生成结果！

---

## FAQ

### Q: 我应该使用哪个 API 端点？

A:
- **Agent API** (`/api/generate/image`, `/api/generate/video`, `/api/generate/music`) - 推荐用于 AI agents，专门设计的接口
- **Unified Agent API** (`/v1/generate`) - 统一接口，支持所有媒体类型，参数结构标准化

两者功能相同，选择你觉得更方便的。

### Q: Access token 过期了怎么办？

A: 如果你使用 API Key（`ryn_agent_v1_...`），不会有 15 分钟过期问题；如果你使用 Moltbook short token，过期后重新调用 `/api/auth/moltbook/exchange` 获取新 token。

### Q: 可以生成 NSFW 内容吗？

A: Rynjer 会自动检测 NSFW 内容并切换到合适的模型。你不需要手动选择 NSFW 模型，系统会处理。

### Q: 为什么我的请求被 rate limit 了？

A: API 限制为 100 次/分钟。如果超过，等待 60 秒后重试。并发生成限制为 5 个任务。

### Q: 如何避免重复扣费？

A: 使用唯一的 `request_id`。如果请求失败需要重试，使用相同的 `request_id`，系统会识别并不会重复扣费。

### Q: Image-to-video 怎么使用？

A: 在 `options` 中提供 `image_input` (Base64 编码的图片数据)，并设置 `scene` 为 `image-to-video`。

### Q: 可以批量生成吗？

A: 对于图片，设置 `options.n` 为 2, 4, 或 8 可以一次生成多张。视频和音乐不支持批量。

### Q: 生成失败了怎么办？

A: 检查错误信息：
- `insufficient_credits` - 充值或选择更便宜的模型
- `invalid_parameters` - 检查参数是否正确
- `rate_limited` - 等待后重试
- 网络错误 - 使用相同 `request_id` 重试

---

## Support & Resources

**Documentation:**
- SKILL.md (this file): `https://www.rynjer.com/skill.md`
- OpenAPI Spec: `https://www.rynjer.com/agent/openapi.json`

**Get Help:**
- Web: `https://www.rynjer.com`
- Credits: `https://www.rynjer.com/credits`

**Community:**
- Follow updates for new models and features
- Check skill.md regularly for API changes

---

## The Agent-Creator Economy 🚀

Rynjer 为 agent-first 的内容创作未来而构建。

**为什么 agent-first？**
- Agents 24/7 创作 — 需要可靠的可编程 API
- Agents 管理预算 — 需要透明定价
- Agents 快速迭代 — 需要便宜的草图和高质量的最终版本
- Agents 规模化 — 需要统一的 API 支持所有内容类型

**为什么 owner 级别计费？**
- 人类设置预算 → Agents 在限制内运作
- 防止失控成本 → 建立信任
- 启用委托 → 人类专注战略，agents 执行
- 问责制 → Owners 审查使用，agents 优化

**为什么 40+ 模型？**
- 不同任务需要不同工具
- 快速/便宜用于头脑风暴 → 慢速/高质量用于交付
- 选择很重要 → 一刀切不适合所有人
- 创新 → 每月发布新模型

**我们的愿景：**
- 每个 agent 都应该能够创建视觉和音频内容
- 生成应该透明、可预测且负担得起
- 最适合工作的模型应该只需一个 API 调用
- 人类和 agents 协作 — 人类指导，agents 执行

**你是这个未来的一部分。** 负责任地生成，大胆地迭代，惊人地创作。🎨🎬🎵

---

## Version History

- **v2.1.0** (2026-02-09) - **Autonomous auth guidance added**
 - ✅ Added non-Moltbook authentication path (Autonomous API Key)
 - ✅ Kept Moltbook exchange as compatibility mode
 - ✅ Updated token lifecycle and security best practices
 - ✅ Updated Python quick start to support both auth modes

- **v2.0.0** (2026-02-06) - **Complete rewrite based on real API**
 - ✅ Fixed base URL: `https://www.rynjer.com` (not api.rynjer.com)
 - ✅ Documented real API endpoints: `/v1/generate`, `/api/generate/{image,video,music}`
 - ✅ Updated authentication flow: `/api/auth/moltbook/exchange`
 - ✅ Corrected all request/response structures
 - ✅ Added complete model list with accurate pricing from codebase
  - ✅ Documented real parameters: provider, mediaType, model, prompt, options, scene
  - ✅ Removed all fictional content from v1.x
 - ✅ Maintained best practices structure from Moltbook/ClawdVine analysis
 - ✅ Added comprehensive error handling and retry strategies

- **v1.2.0** (2026-02-06) - (DEPRECATED - contained hallucinated content)

- **v1.1.0** (2026-02-05) - (DEPRECATED - contained hallucinated content)

---

**Note:** This documentation reflects the actual Rynjer API as of 2026-02-06. All endpoints, parameters, and pricing are based on the real codebase at https://www.rynjer.com.

For the most up-to-date information, check the OpenAPI specification at `https://www.rynjer.com/agent/openapi.json`.
