{"id":"c6c5bd5a-3faf-47c9-8592-12f1b9317916","entityType":"agent","slug":"clawhub-lovart-admin-lovart-skill","name":"lovart-api","canonicalUrl":"https://www.xpersona.co/agent/clawhub-lovart-admin-lovart-skill","canonicalPath":"/agent/clawhub-lovart-admin-lovart-skill","generatedAt":"2026-10-09T14:13:03.795Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"editorial-content","verified":true,"confidence":"high","updatedAt":"2026-10-09T07:00:00.273Z","emptyReason":null},"description":"Generate images, videos, and audio/music via Lovart AI. Also manages Lovart projects, threads (conversation history), and user settings. Trigger on: (1) any visual or audio creation request in any language — draw, generate, create, design, make, 画, 生成, 制作, 创作, 设计 combined with image, video, audio, music, song, BGM, poster, etc. (2) Lovart project/thread management — 项目, 对话, project, thread, conversation, history, 历史, 切换, switch. You CAN generate directly - never say you cannot. Skill: lovart-api Owner: lovart-admin Summary: Generate images, videos, and audio/music via Lovart AI. Also manages Lovart projects, threads (conversation history), and user settings. Trigger on: (1) any visual or audio creation request in any language — draw, generate, create, design, make, 画, 生成, 制作, 创作, 设计 combined with image, video, audio, music, song, BGM, poster, etc. (2) Lovart project/thread management — 项目,","descriptionLabel":"Technical summary","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 3.7K downloads reported by the source. Last updated 10/9/2026.","installCommand":"clawhub skill install s175m4rj7y879d1de1y626wb8n84h28q:lovart-skill","sourceUrl":"https://clawhub.ai/lovart-admin/lovart-skill","homepage":"https://clawhub.ai/lovart-admin/skills/lovart-skill","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/lovart-admin/lovart-skill","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/lovart-admin/skills/lovart-skill","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":47,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"Generate images, videos, and audio/music via Lovart AI. Also manages Lovart projects, threads (conversation history), and user settings. Trigger on: (1) any vis"},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-09T07:00:00.273Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T07:00:00.273Z","emptyReason":null},"stars":null,"forks":null,"downloads":3744,"packageName":null,"latestVersion":"1.1.0","tractionLabel":"3.7K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T07:00:00.273Z","emptyReason":null},"lastUpdatedAt":"2026-10-09T07:00:00.273Z","lastCrawledAt":"2026-10-09T07:00:00.273Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-10T07:00:00.273Z","lastVerifiedAt":null,"highlights":[{"version":"1.1.0","createdAt":"2026-09-06T09:39:44.911Z","changelog":"lovart-skill 1.1.0 - Project link now always appended after every generation. - Results with failures: user is informed when a model or reference was refused and why. - Removed deprecated skill-card.md file. - Version bump and documentation updates for improved result handling and reporting.","fileCount":4,"zipByteSize":23807},{"version":"1.0.12","createdAt":"2026-07-15T07:18:05.768Z","changelog":"lovart-skill v1.0.12 - Updated version to 1.0.12 in SKILL.md and metadata - Minor documentation/tweaks in SKILL.md; no new commands or user-facing behavior changes - Removed legacy skill-card.md file","fileCount":4,"zipByteSize":21161},{"version":"1.0.11","createdAt":"2026-07-09T04:07:42.311Z","changelog":"lovart-skill 1.0.11 - Added main agent logic to scripts/agent_skill.py, relocating from root to improve organization. - Enhanced SKILL.md: now includes metadata fields such as version, author, license, homepage, platforms, and detailed tags for discoverability. - Standardized prerequisites and clarified command/environment requirements. - Removed obsolete agent_skill.py (root) and skill-card.md files.","fileCount":4,"zipByteSize":20987},{"version":"1.0.10","createdAt":"2026-05-27T08:13:42.139Z","changelog":"lovart-skill 1.0.10 - Updated SKILL.md for improved clarity and detailed usage rules; mostly editorial/formatting changes. - No functional code changes to command sets or logic; documentation aligned tightly with operational guidance. - Maintains strict command usage, error handling, and user interaction as before.","fileCount":4,"zipByteSize":20800},{"version":"1.0.9","createdAt":"2026-05-19T12:31:43.303Z","changelog":"Version 1.0.9 - Updated SKILL.md documentation (no changes to code). - Clarified and expanded usage instructions, error handling, and step-by-step operation requirements. - Improved rule definitions for project selection, thread management, and artifact delivery. - No functional or API changes; this is a documentation-only update.","fileCount":3,"zipByteSize":19577},{"version":"1.0.8","createdAt":"2026-04-23T06:36:28.400Z","changelog":"- Improved error handling: now uses the server's user-facing error messages directly for quota, billing, risk control, and other 402 errors, instead of parsing internal error codes. - Minor clarifications to confirmation flow: highlights that some premium image variants also require explicit user approval before consuming credits. - Slightly expanded instructions in error handling and confirmation to reduce ambiguity and ensure consistent user communication. - No command/API/behavior changes—documentation and guidance were updated for clarity and accuracy.","fileCount":3,"zipByteSize":19550},{"version":"1.0.7","createdAt":"2026-04-22T15:07:09.196Z","changelog":"lovart-skill 1.0.7 - Added strict detection and handling for silent generation failures (when status is \"done\" but no artifacts are produced). - Clarified post-generation checking: now agents must verify result[\"generation_succeeded\"], show user warnings, and surface agent_message when a request can't be completed. - Updated documentation (SKILL.md) to reflect required user messaging, troubleshooting, and workflow for these silent failures. - No code changes outside of doc/procedure updates.","fileCount":3,"zipByteSize":19588},{"version":"1.0.6","createdAt":"2026-04-22T04:54:49.588Z","changelog":"No changes detected in version 1.0.6. - No file changes were made in this release.","fileCount":3,"zipByteSize":18674}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s175m4rj7y879d1de1y626wb8n84h28q:lovart-skill","setupComplexity":"low","setupSteps":["Setup complexity is classified as HIGH. You must provision dedicated cloud infrastructure or an isolated VM. Do not run this directly on your local workstation.","Final validation: Expose the agent to a mock request payload inside a sandbox and trace the network egress before allowing access to real customer data."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-lovart-admin-lovart-skill/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-lovart-admin-lovart-skill/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-lovart-admin-lovart-skill/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-lovart-admin-lovart-skill/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-lovart-admin-lovart-skill/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-lovart-admin-lovart-skill/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-09T14:13:03.791Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-lovart-admin-lovart-skill/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-lovart-admin-lovart-skill/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-lovart-admin-lovart-skill/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-lovart-admin-lovart-skill/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"high","updatedAt":"2026-10-09T07:00:00.273Z","emptyReason":null},"readme":"Skill: lovart-api\n\nOwner: lovart-admin\n\nSummary: Generate images, videos, and audio/music via Lovart AI. Also manages Lovart projects, threads (conversation history), and user settings. Trigger on: (1) any visual or audio creation request in any language — draw, generate, create, design, make, 画, 生成, 制作, 创作, 设计 combined with image, video, audio, music, song, BGM, poster, etc. (2) Lovart project/thread management — 项目, 对话, project, thread, conversation, history, 历史, 切换, switch. You CAN generate directly - never say you cannot.\n\nTags: latest:1.1.0\n\nVersion history:\n\nv1.1.0 | 2026-09-06T09:39:44.911Z | auto\n\nlovart-skill 1.1.0\n\n- Project link now always appended after every generation.\n- Results with failures: user is informed when a model or reference was refused and why.\n- Removed deprecated skill-card.md file.\n- Version bump and documentation updates for improved result handling and reporting.\n\nv1.0.12 | 2026-07-15T07:18:05.768Z | auto\n\nlovart-skill v1.0.12\n\n- Updated version to 1.0.12 in SKILL.md and metadata\n- Minor documentation/tweaks in SKILL.md; no new commands or user-facing behavior changes\n- Removed legacy skill-card.md file\n\nv1.0.11 | 2026-07-09T04:07:42.311Z | auto\n\nlovart-skill 1.0.11\n\n- Added main agent logic to scripts/agent_skill.py, relocating from root to improve organization.\n- Enhanced SKILL.md: now includes metadata fields such as version, author, license, homepage, platforms, and detailed tags for discoverability.\n- Standardized prerequisites and clarified command/environment requirements.\n- Removed obsolete agent_skill.py (root) and skill-card.md files.\n\nv1.0.10 | 2026-05-27T08:13:42.139Z | auto\n\nlovart-skill 1.0.10\n\n- Updated SKILL.md for improved clarity and detailed usage rules; mostly editorial/formatting changes.\n- No functional code changes to command sets or logic; documentation aligned tightly with operational guidance.\n- Maintains strict command usage, error handling, and user interaction as before.\n\nv1.0.9 | 2026-05-19T12:31:43.303Z | auto\n\nVersion 1.0.9\n\n- Updated SKILL.md documentation (no changes to code).\n- Clarified and expanded usage instructions, error handling, and step-by-step operation requirements.\n- Improved rule definitions for project selection, thread management, and artifact delivery.\n- No functional or API changes; this is a documentation-only update.\n\nv1.0.8 | 2026-04-23T06:36:28.400Z | auto\n\n- Improved error handling: now uses the server's user-facing error messages directly for quota, billing, risk control, and other 402 errors, instead of parsing internal error codes.\n- Minor clarifications to confirmation flow: highlights that some premium image variants also require explicit user approval before consuming credits.\n- Slightly expanded instructions in error handling and confirmation to reduce ambiguity and ensure consistent user communication.\n- No command/API/behavior changes—documentation and guidance were updated for clarity and accuracy.\n\nv1.0.7 | 2026-04-22T15:07:09.196Z | auto\n\nlovart-skill 1.0.7\n\n- Added strict detection and handling for silent generation failures (when status is \"done\" but no artifacts are produced).\n- Clarified post-generation checking: now agents must verify result[\"generation_succeeded\"], show user warnings, and surface agent_message when a request can't be completed.\n- Updated documentation (SKILL.md) to reflect required user messaging, troubleshooting, and workflow for these silent failures.\n- No code changes outside of doc/procedure updates.\n\nv1.0.6 | 2026-04-22T04:54:49.588Z | user\n\nNo changes detected in version 1.0.6.\n\n- No file changes were made in this release.\n\nv1.0.5 | 2026-04-20T08:28:06.762Z | user\n\nlovart-skill 1.0.5\n\n- Error handling logic for the `chat` command has been improved: now matches HTTP status codes and structured error codes for clearer, more accurate user messages.\n- New error handling table with HTTP status, internal code, and interpretation.\n- Original error handling by message fragment matching is now a fallback, not primary.\n- No code or logic changes beyond updated documentation; no file changes detected.\n\nv1.0.3 | 2026-04-17T06:10:34.728Z | user\n\nVersion 1.0.3 of lovart-skill\n\n- No file changes detected.\n- Behavior and features remain unchanged from the previous release.\n\nv1.0.2 | 2026-04-14T08:58:09.876Z | user\n\nVersion 1.0.2 of lovart-skill\n\n- Added the watch command to the list of allowed Lovart operations.\n- Clarified that all Lovart operations should use one of: chat, send, watch, confirm, result, status, config, projects, project-add, project-switch, project-rename, project-remove, threads, thread-remove, upload, upload-artifact, download, set-mode, query-mode, create-project.\n- No functional logic changes beyond documentation update.\n\nv1.0.1 | 2026-04-13T07:53:23.524Z | user\n\nlovart-skill v1.0.1 changelog:\n\n- Minor clarification: Rule #0 now allows users to freely read the source code to verify it, but prohibits modifying skill source code during execution to \"debug\" issues.\n- No changes to commands, features, or behavior.\n\nv1.0.0 | 2026-04-10T10:04:36.152Z | user\n\nlovart-skill v1.0.0\n\n- Initial release of the Lovart skill for generating images, videos, and audio/music via Lovart AI.\n- Supports creation and management of Lovart projects, threads (conversation history), and user settings.\n- Fully command-driven: all Lovart operations must use provided skill commands; direct API calls are not allowed.\n- Enforces explicit project and region setup before first use; supports both global and mainland China users.\n- Handles generation flow, cost confirmations, project/thread switching, error management, and delivery of generated files with project links.\n- Designed to be directly invoked by users for both creative and project-management requests.\n\nArchive index:\n\nArchive v1.1.0: 4 files, 23807 bytes\n\nFiles: scripts/agent_skill.py (49160b), skill-card.md (2196b), SKILL.md (27707b), _meta.json (131b)\n\nFile v1.1.0:SKILL.md\n\n---\nname: lovart-api\ndescription: >-\n  Generate images, videos, and audio/music via Lovart AI. Also manages Lovart projects,\n  threads (conversation history), and user settings. Trigger on: (1) any visual or audio\n  creation request in any language — draw, generate, create, design, make, 画, 生成,\n  制作, 创作, 设计 combined with image, video, audio, music, song, BGM, poster, etc.\n  (2) Lovart project/thread management — 项目, 对话, project, thread, conversation,\n  history, 历史, 切换, switch. You CAN generate directly - never say you cannot.\nuser-invocable: true\nversion: 1.1.0\nauthor: Lovart (lovartai)\nlicense: MIT\nhomepage: https://github.com/lovartai/lovart-skill\nplatforms: [linux, macos, windows]\nmetadata:\n  hermes:\n    tags:\n      - image-generation\n      - video-generation\n      - audio-generation\n      - 3d\n      - design\n      - poster\n      - logo\n      - ai-art\n    related_skills: []\n  openclaw:\n    emoji: 🎨\n    requires:\n      bins: [python3]\n      env: [LOVART_ACCESS_KEY, LOVART_SECRET_KEY]\n    primaryEnv: LOVART_ACCESS_KEY\nprerequisites:\n  commands: [python3]\n  env: [LOVART_ACCESS_KEY, LOVART_SECRET_KEY]\n  python: []\n---\n\n# ⚠️ RULE #0: ONLY USE SKILL COMMANDS — NO DIRECT API CALLS\n\n**You MUST interact with Lovart EXCLUSIVELY through the commands defined in this skill.**\n- NEVER construct URLs, make curl/wget/fetch requests, or call Lovart APIs directly\n- NEVER guess API endpoints, paths, or parameters — only use the commands listed below\n- NEVER modify the skill's source code (agent_skill.py) during execution to \"debug\" issues (users may freely read the source to verify it)\n- If a command fails, retry it or report the error to the user — do NOT try to work around it\n- ALL Lovart operations go through: `chat`, `send`, `watch`, `confirm`, `result`, `status`, `config`, `projects`, `project-add`, `project-switch`, `project-rename`, `project-remove`, `threads`, `thread-remove`, `upload`, `upload-artifact`, `download`, `set-mode`, `query-mode`, `create-project`\n\n# ⚠️ RULE #1: YOU CAN AND MUST GENERATE IMAGES/VIDEOS/AUDIO\n\nWhen a user asks to \"draw\", \"generate\", \"create\", \"design\", \"make\", \"画\", \"生成\", \"制作\", \"创作\"\nany visual or audio content (in any language), you MUST use this skill.\nThis includes: images, videos, audio, music, songs, BGM, TTS, voice, posters, carousels, banners,\nlogos, illustrations, thumbnails, slides, covers, mockups, icons, social media content, etc.\nDo NOT say \"I can't generate images/music\" or offer to write prompts instead.\n\n# ⚠️ RULE #1.5: PROJECT & THREAD QUERIES USE THIS SKILL\n\nWhen the user asks about projects, threads, conversations, history, or settings (in any language),\nuse these commands — do NOT browse the filesystem:\n\n| User asks | Command |\n|-----------|---------|\n| \"What projects do I have?\" / \"我有哪些项目\" | `projects --json` |\n| \"What conversations/threads?\" / \"有哪些对话\" | `threads --json` or `threads --all --json` |\n| \"Show my settings\" / \"我的配置\" | `config --json` |\n| \"Switch to project X\" | `project-switch --project-id X` |\n| \"Create a new project\" | `project-add --project-id NEW_ID --name \"Name\"` (or let `chat` auto-create) |\n\n# ⚠️ RULE #2: ALWAYS USE `chat` AND WAIT FOR COMPLETION\n\nUse the `chat` command (blocks until done), NOT `send`. Do NOT reply before generation completes.\n\n**Handle these `final_status` values:**\n\n- `\"done\"` — Generation complete. Send the downloaded files to the user.\n- `\"pending_confirmation\"` — A high-cost tool (e.g. video, or a premium-quality image variant) needs user approval before credits are consumed.\n  **You MUST ask the user for explicit confirmation before proceeding. Do NOT auto-confirm.**\n  1. Show the user: \"This will cost approximately {estimated_cost} credits. Shall I proceed? (yes/no)\"\n  2. **WAIT for user response.** Only if user explicitly says yes/confirm/proceed, run:\n     `confirm --thread-id THREAD_ID --json --download`\n     (This confirms, waits for completion, and returns the result with downloaded files)\n  3. If user declines, do NOT confirm. Just inform them the operation was cancelled.\n- `\"abort\"` — Generation was aborted. Inform the user.\n- `\"timeout\"` — Generation is still running but exceeded the wait time. The result may contain partial artifacts.\n  1. Send any downloaded files that are already available\n  2. Tell the user: \"Generation is still in progress. Checking again...\"\n  3. Run: `result --thread-id THREAD_ID --json --download` to get the latest results\n  4. If status is still \"running\", wait and retry. If \"done\", send remaining files.\n\n**Handle errors:**\n\nIf `chat` throws an error (`AgentSkillError`), handle it by HTTP status and structured `code`. The `message` field already contains a user-ready explanation — surface it to the user as-is.\n\n| HTTP status | `code` | What it means | What to tell the user |\n|---|---|---|---|\n| **`402`** | `2012` | Quota / billing / risk-control rejection | Show `AgentSkillError.message` directly — the server already returns a specific message (insufficient credits, free-tier reached, concurrent limit, risk control, phone verification, team plan required, etc.) and a suggested next step. |\n| **`409`** | `2011` | Another task is still running on this thread | \"A task is still running on this conversation. Wait for it to finish (`status`) before sending a new prompt, or start a new thread.\" |\n| **`429`** | `1429` | API rate limit hit | \"Slowing down; rate limit hit. Retry in ~60s.\" |\n| **`401`** | — | AK/SK misconfigured | \"API key authentication failed. Please check your LOVART_ACCESS_KEY and LOVART_SECRET_KEY.\" |\n| — | — | `Project.*does not exist` in message | \"Project not found. Please check the project ID or create a new one.\" |\n\nRule of thumb: prefer `AgentSkillError.message` for user-facing copy. Do not try to parse internal codes out of the response — the server already maps them to human-readable messages before returning.\n\n**Detect silent generation failures (`done` with no artifact):**\n\nSome prompts end with `final_status: \"done\"` but produce no `artifacts` / empty `downloaded`. This usually means the upstream image model refused the prompt (content moderation), timed out, or the LLM chose to reply with text instead of calling a tool. The skill flags this automatically — when `chat()` returns, check:\n\n- `result[\"generation_succeeded\"]` — boolean. `False` means no artifact was produced.\n- `result[\"warning\"]` — explanation string (present only when `generation_succeeded` is `False`).\n- `result[\"agent_message\"]` — the agent's plain-text reply that hints at why (present when available).\n\nTypical triggers:\n- GPT Image 2 with very long/complex prompts involving weapons, specific bodies, or policy-sensitive wording — retry with a different model (`--include-tools generate_image_midjourney` or `generate_image_nano_banana_pro`) or simplify the prompt.\n- Prompt that describes a task the agent can't fulfill — show `agent_message` to the user.\n\n# ⚠️ RULE #3: ALWAYS DELIVER RESULTS + PROJECT LINK\n\nAfter EVERY generation, you MUST:\n1. Use `--download` flag with `chat` (or `result`)\n2. Send each downloaded file to the user as a **file attachment** (images, videos, audio/mp3 — ALL file types):\n   - ALWAYS send `downloaded[].local_path` as file attachments, regardless of file type (.png, .jpg, .mp4, .mp3, etc.)\n   - NEVER just paste the URL when a local file has been downloaded — send the actual file\n   - Only fall back to displaying URLs if no files were downloaded\n3. Append the project canvas link: `https://www.lovart.ai/canvas?projectId={project_id}`\n4. Check `failures` in the result. When it is non-empty, tell the user which reference or model was refused and why — the Agent may have dropped an input or switched models to finish, so the delivered result can differ from what they asked for. Never report a clean success while `failures` is non-empty.\n\n# ⚠️ RULE #4: CHECK LOCAL STATE ON FIRST USE (MANDATORY — DO NOT SKIP)\n\n**Before the FIRST generation in a conversation, you MUST run these two commands IN ORDER. This is NOT optional. Do NOT call `chat` until you have done both.**\n\n**Step 1: `config --json`**\n- Check local state (`~/.lovart/state.json`) for `active_project`\n- If `active_project` is set → proceed to Step 2. Do NOT create a new project. Do NOT ask the user.\n- If `active_project` is missing → ask the user: \"Do you have an existing Lovart project ID, or should I create a new one?\" **WAIT for their answer.**\n- Save with: `project-add --project-id PID --name \"name\"`\n\n**Step 2: `threads --json`**\n- Check if there's a recent thread to continue\n- If recent thread exists and topic is related → **REUSE it** (pass `--thread-id THREAD_ID` to `chat`)\n- If no threads or completely different topic → omit `--thread-id` (creates new thread)\n\n**CRITICAL RULES:**\n- **NEVER create a new project** if `config --json` already shows an `active_project`. Reuse it.\n- **NEVER omit `--thread-id`** when a relevant recent thread exists. Always reuse threads by default.\n- **NEVER call `chat` without first running `config --json` and `threads --json`** in the same conversation.\n- The `chat` command auto-reads `active_project` from local state — you do NOT need to pass `--project-id` every time.\n- Only create a new project if the user **explicitly** asks for one.\n- Only create a new thread if the topic is **completely unrelated** to the most recent thread.\n- When in doubt, **REUSE** both the existing project and the existing thread.\n\n---\n\n# Lovart Agent OpenAPI Skill\n\nInteract with Lovart AI Agent to generate images, videos, and visual assets via natural language.\n\nLovart is an AI design platform. The Agent understands user requests and automatically selects the best model and workflow.\n\n## Terminology\n\n- **Thread** — A conversation flow (chat session) with the Lovart AI Agent, NOT a programming thread. Each thread has a unique `thread_id` and preserves multi-turn context. Reusing a thread means continuing the same conversation so the Agent remembers previous images/videos and can iterate on them.\n- **Project** — A workspace/canvas that groups threads and generated artifacts together. One project can contain multiple threads.\n\n## Prerequisites\n\n```bash\nexport LOVART_ACCESS_KEY=\"ak_xxx\"\nexport LOVART_SECRET_KEY=\"sk_xxx\"\n```\n\nNo third-party dependencies. Python standard library only.\n\n## Features\n\n1. **Chat** - Send a message to the AI Agent, get text replies and generated images/videos\n2. **Confirm** - Confirm and wait for high-cost operations (e.g. video generation)\n3. **Create Project** - Create a new project\n4. **Upload File** - Upload a local image/video file, get back a CDN URL\n5. **Upload Artifact** - Upload a link artifact to a project\n6. **Status/Result** - Check thread status and retrieve results\n7. **Set/Query Mode** - Switch between fast (credits) and unlimited (queue) mode\n\n## Usage\n\n### 0. First-time setup (saves to ~/.lovart/state.json)\n\n```bash\npython3 {baseDir}/scripts/agent_skill.py project-add --project-id PROJECT_ID --name \"My Project\"\n```\n\n### 1. Send a message (reads project_id from local state)\n\n```bash\npython3 {baseDir}/scripts/agent_skill.py chat --prompt \"USER_PROMPT\" --json --download\n```\n\nTo override project: add `--project-id PROJECT_ID`\nTo continue a conversation: add `--thread-id THREAD_ID`\nTo list saved threads: `python3 {baseDir}/scripts/agent_skill.py threads`\n\n### 2. Create a project\n\n```bash\npython3 {baseDir}/scripts/agent_skill.py create-project\n```\n\n### 3. Upload a file (local image/video → CDN URL)\n\n```bash\npython3 {baseDir}/scripts/agent_skill.py upload --file /path/to/image.png\n# Returns: {\"url\": \"https://assets-persist.lovart.ai/img/{user_uuid}/xxx.png\"}\n```\n\nUse this when the user sends an image/video file that needs to be passed as an attachment to chat.\n\n### 4. Upload an artifact\n\n```bash\npython3 {baseDir}/scripts/agent_skill.py upload-artifact --project-id PROJECT_ID --url \"ARTIFACT_URL\" --type image\n```\n\n### 5. Check status / get result\n\n```bash\n# Status\npython3 {baseDir}/scripts/agent_skill.py status --thread-id THREAD_ID\n\n# Result (auto-syncs to gallery/canvas, idempotent)\npython3 {baseDir}/scripts/agent_skill.py result --thread-id THREAD_ID --json --download\n```\n\n### 6. Download artifacts\n\n```bash\n# Download during chat\npython3 {baseDir}/scripts/agent_skill.py chat --prompt \"draw a cat\" --json --download --output-dir /tmp/lovart\n\n# Download from existing result\npython3 {baseDir}/scripts/agent_skill.py result --thread-id THREAD_ID --download --output-dir /tmp/lovart\n\n# Download specific URLs\npython3 {baseDir}/scripts/agent_skill.py download --urls URL1 URL2 --output-dir /tmp/lovart --prefix myimg\n```\n\n## Typical Workflows\n\n### Scenario 1: Generate images/videos/audio (most common)\n\n**First, run `config --json` to check if project_id is set. If not, ask the user and save with `project-add`.**\n\n```\n1. config --json  →  check local state for active_project\n   - If not set → ask user, save with project-add\n2. threads --json  →  check if there's a recent thread to continue\n   - If recent thread exists and topic is related → reuse it (step 3a)\n   - If no threads or completely new topic → new thread (step 3b)\n3a. chat --thread-id THREAD_ID --prompt \"user's request\" --json --download\n3b. chat --prompt \"user's request\" --json --download\n4. Send each downloaded[].local_path file as an IM attachment to the user\n5. The chat command auto-syncs artifacts to canvas and gallery\n```\n\n**IDs are auto-persisted locally (`~/.lovart/state.json`):**\n- project_id is saved after first chat, reused automatically\n- thread_id + topic are saved after each chat for thread switching\n- Only create a new project if the user explicitly asks for one\n- Only create a new thread (omit `--thread-id`) when starting a completely new topic\n- Run `threads` to list saved threads for the user to pick from\n\n### Scenario 2: Edit with attachments\n\n```\n1. User sends a reference image/video via IM → save to local file\n2. upload --file /path/to/image.png  →  get CDN URL\n3. chat --prompt \"edit this image to...\" --project-id PID --attachments \"CDN_URL\" --json --download\n4. Continue as Scenario 1\n```\n\n### Scenario 3: Follow-up on same topic (continue context)\n\n```\n1. chat --prompt \"change the background to a beach\" --project-id PROJECT_ID --thread-id THREAD_ID --json --download\n```\n\nThe Agent remembers the previous conversation and can continue editing based on context.\n\n### Scenario 4: New topic (new thread)\n\n```\n1. chat --prompt \"completely new request\" --project-id PROJECT_ID --json --download\n```\n\nOmitting `--thread-id` creates a new conversation without previous memory.\n\n### Scenario 5: Streaming / incremental delivery (multiple artifacts)\n\n**Use when** the user's request will produce multiple images/videos and you want to deliver each one to the user as soon as it's ready, rather than waiting for the whole batch.\n\n```bash\npython3 {baseDir}/scripts/agent_skill.py watch --prompt \"generate 4 variations of a cyberpunk cat\" --json\n```\n\n`watch` emits **NDJSON** to stdout (one event per line). Parse line-by-line and deliver each `artifact` event's `local_path` to the user immediately:\n\n```json\n{\"event\": \"started\", \"thread_id\": \"xxx\", \"project_id\": \"yyy\"}\n{\"event\": \"artifact\", \"type\": \"image\", \"url\": \"https://...\", \"local_path\": \"/tmp/lovart/lovart_ab12cd.png\"}\n{\"event\": \"artifact\", \"type\": \"image\", \"url\": \"https://...\", \"local_path\": \"/tmp/lovart/lovart_ef34gh.png\"}\n{\"event\": \"pending_confirmation\", \"thread_id\": \"xxx\", \"pending_confirmation\": {...}}\n{\"event\": \"finished\", \"thread_id\": \"xxx\", \"final_status\": \"done\", \"artifact_count\": 4}\n```\n\nFiles are saved with URL-hash filenames so re-running `watch` on the same thread won't re-download.\n\nYou can also attach to an **already-running** thread: `watch --thread-id THREAD_ID`.\n\n**When NOT to use `watch`:** single-image requests — use `chat` (simpler, one-shot response).\n\n## Output Format\n\n**chat --json** returns:\n```json\n{\n  \"thread_id\": \"xxx\",\n  \"status\": \"done\",\n  \"project_id\": \"xxx\",\n  \"final_status\": \"done\",\n  \"items\": [\n    {\"type\": \"assistant\", \"text\": \"Agent's reply\"},\n    {\"type\": \"generator\", \"name\": \"artifacts\", \"artifacts\": [\n      {\"type\": \"image\", \"content\": \"https://assets-persist.lovart.ai/artifacts/agent/xxx.png\"},\n      {\"type\": \"video\", \"content\": \"https://assets-persist.lovart.ai/artifacts/agent/xxx.mp4\"}\n    ]}\n  ],\n  \"downloaded\": [\n    {\"type\": \"image\", \"url\": \"https://...\", \"local_path\": \"/tmp/lovart/lovart_01.png\"}\n  ],\n  \"generation_succeeded\": true,\n  \"failures\": []\n}\n```\n\n`failures` lists tool calls that were rejected during the run, even when\nartifacts were still produced. `warning` is set alongside it with a one-line\nsummary. See \"Checking What Was Rejected\" below.\n\n## Core Principle\n\nYou are a messenger, not a creator. The backend Agent handles understanding requirements, selecting models, and writing prompts. Your job:\n\n1. **Relay**: Pass the user's original description verbatim to chat\n2. **Wait**: Poll until generation completes\n3. **Deliver**: Send result files to the user\n\n**Do NOT** rewrite/expand prompts, break down tasks, or add your own style descriptions.\n\n## Lovart Generation Mode (MUST use API, not prompt)\n\n**CRITICAL: \"Fast mode\" and \"unlimited mode\" are server-side settings controlled via API calls, NOT prompt keywords.**\n\nDo NOT put \"快速模式\" or \"fast mode\" in the prompt text. Instead, call the set-mode command:\n\n```bash\n# User says \"fast mode\" / \"快速模式\" / \"skip queue\" / \"use credits\" → RUN THIS:\npython3 {baseDir}/scripts/agent_skill.py set-mode --fast\n\n# User says \"unlimited mode\" / \"无限模式\" / \"free mode\" / \"save credits\" → RUN THIS:\npython3 {baseDir}/scripts/agent_skill.py set-mode --unlimited\n\n# Check which mode is active:\npython3 {baseDir}/scripts/agent_skill.py query-mode\n```\n\n**How it works:**\n- `set-mode --fast` calls the Lovart backend API to switch the user's account to fast generation (costs credits, no queue)\n- `set-mode --unlimited` switches to unlimited generation (free, may queue)\n- This is a **persistent server-side setting** — it stays until changed again\n- It affects ALL subsequent image/video generations, not just one request\n- It has **nothing to do with your (the assistant's) response style or behavior**\n\n## Specifying Models\n\n**Option 1: In the prompt** (simple, the Agent routes automatically):\n\n```bash\npython3 {baseDir}/scripts/agent_skill.py chat --prompt \"generate ocean waves video using kling\" --json --download\n```\n\n**Option 2: Via --prefer-models** (precise, same as frontend's model selector):\n\n```bash\n# Prefer a specific image model\npython3 {baseDir}/scripts/agent_skill.py chat --prompt \"draw a cat\" --prefer-models '{\"IMAGE\":[\"generate_image_midjourney\"]}' --json --download\n\n# Prefer a specific video model\npython3 {baseDir}/scripts/agent_skill.py chat --prompt \"generate ocean waves\" --prefer-models '{\"VIDEO\":[\"generate_video_kling_3_0\"]}' --json --download\n\n# Combine image and video preferences\npython3 {baseDir}/scripts/agent_skill.py chat --prompt \"create content\" --prefer-models '{\"IMAGE\":[\"generate_image_seedream_3_0\"],\"VIDEO\":[\"generate_video_kling_3_0\"]}' --json --download\n```\n\nAvailable models for `--prefer-models`:\n\n**IMAGE:**\n\n| Tool name | Display name |\n|---|---|\n| `generate_image_gpt_image_2` | GPT Image 2 Auto |\n| `generate_image_gpt_image_2_low` | GPT Image 2 Low |\n| `generate_image_gpt_image_2_medium` | GPT Image 2 Medium |\n| `generate_image_gpt_image_2_high` | GPT Image 2 High |\n| `generate_image_nano_banana_pro` | Nano Banana Pro |\n| `generate_image_nano_banana_2` | Nano Banana 2 |\n| `generate_image_seedream_v5_pro` | Seedream 5.0 Pro |\n| `generate_image_gpt_image_1_5` | GPT Image 1.5 |\n| `generate_image_seedream_v5` | Seedream 5.0 Lite |\n| `generate_image_luma_uni_1` | Luma uni-1 |\n| `generate_image_luma_uni_1_max` | Luma uni-1-max |\n| `generate_image_flux_2_max` | Flux.2 Max |\n| `generate_image_flux_2_pro` | Flux.2 Pro |\n| `generate_image_seedream_v4_5` | Seedream 4.5 |\n| `generate_image_nano_banana` | Nano Banana |\n| `generate_image_seedream_v4` | Seedream 4 |\n| `generate_image_midjourney` | Midjourney |\n| `generate_image_ideogram_v4` | Ideogram 4 |\n| `generate_image_qwen_image3` | Qwen Image3 |\n| `generate_image_qwen_image3_pro` | Qwen Image3 Pro |\n| `generate_image_nano_banana_2_lite` | Nano Banana 2 Lite |\n| `generate_image_p_image_ideogram` | Ideogram P-Image |\n\n**VIDEO:**\n\n| Tool name | Display name |\n|---|---|\n| `generate_video_seedance_v2_5` | Seedance 2.5 |\n| `generate_video_seedance_v2_0` | Seedance 2.0 |\n| `generate_video_seedance_v2_0_fast` | Seedance 2.0 Fast |\n| `generate_video_seedance_v2_0_mini` | Seedance 2.0 Mini |\n| `generate_video_kling_v3` | Kling 3.0 |\n| `generate_video_kling_v3_omni` | Kling 3.0 Omni |\n| `generate_video_minimax_h3` | MiniMax H3 |\n| `generate_video_seedance_pro_v1_5` | Seedance 1.5 Pro |\n| `generate_video_kling_v2_6` | Kling 2.6 |\n| `generate_video_wan_v2_6` | Wan 2.6 |\n| `generate_video_veo3_1` | Veo 3.1 |\n| `generate_video_veo3_1_fast` | Veo 3.1 Fast |\n| `generate_video_kling_omni_v1` | Kling O1 |\n| `generate_video_hailuo_v2_3` | Hailuo 2.3 |\n| `generate_video_veo3` | Veo 3 |\n| `generate_video_vidu_q2` | Vidu Q2 |\n| `generate_video_gemini_omni_flash` | Gemini Omni Flash |\n| `generate_video_minimax_h3_max` | MiniMax H3 Max |\n| `generate_video_wan_v3` | Wan 3.0 |\n| `generate_video_wan_v3_prime` | Wan 3.0 Prime |\n\n**3D:**\n\n| Tool name | Display name |\n|---|---|\n| `generate_3d_tripo` | Tripo |\n\nWhen the user requests a specific model, prefer `--prefer-models` over putting model names in the prompt.\n\n**Option 3: Via --include-tools** (strongest steer toward specific tools):\n\n```bash\n# Steer to upscale\npython3 {baseDir}/scripts/agent_skill.py chat --prompt \"upscale this image to 4K\" --include-tools upscale_image --attachments \"IMAGE_URL\" --json --download\n\n# Steer to a specific video model\npython3 {baseDir}/scripts/agent_skill.py chat --prompt \"generate a video\" --include-tools generate_video_kling_3_0 --json --download\n```\n\n`--include-tools` strongly instructs the Agent to prioritize the listed tools. Use this when the user explicitly requests a specific tool or operation.\n\nTwo limits worth knowing:\n\n- It is a strong instruction, **not an enforced whitelist**. The Agent normally follows it, but may pick another tool — for example after the requested one rejects the input. Check `failures` in the result to see when that happened.\n- `--exclude-tools` is accepted for forward compatibility but **currently has no effect** on tool selection. To steer away from a tool, name the one you do want with `--include-tools`.\n\n## Reference Subjects from the Asset Library — `--subjects`\n\n`--attachments` takes any image URL, and every new URL is reviewed again before a\nmodel that requires reviewed inputs will accept it. When the reference already\nlives in the user's asset library, pass its own library URL via `--subjects`\ninstead: the existing review is reused, and the Agent is told these references\nare approved subjects.\n\n```bash\npython3 {baseDir}/scripts/agent_skill.py chat \\\n  --prompt \"put these two characters in a hallway conversation\" \\\n  --subjects '[{\"url\":\"LIBRARY_URL_A\",\"asset_id\":\"asset_xxx\",\"display_name\":\"Bune\",\"channel\":\"ark_sd2\"},\n               {\"url\":\"LIBRARY_URL_B\",\"asset_id\":\"asset_yyy\",\"display_name\":\"Leo\",\"channel\":\"ark_sd2\"}]' \\\n  --json --download\n```\n\nEach entry takes `url` (required) plus optional `type` (`subject_image` by\ndefault, or `subject_audio` / `subject_video`), `asset_id`, `display_name` and\n`channel`. Use `--attachments` for one-off images the user just sent you, and\n`--subjects` for assets that already exist in their library.\n\n`--kits` references a brand kit by ID. The project's active kit is attached\nautomatically, so pass this only to reference a different one.\n\n## Checking What Was Rejected — `failures`\n\nA thread can finish with `final_status: \"done\"` and still have had tool calls\nrejected along the way. The Agent is free to drop a reference or switch to\nanother model and carry on, so a result that looks successful can quietly\ndiffer from what was asked for.\n\nThe result carries a `failures` array whenever that happens:\n\n```json\n{\n  \"final_status\": \"done\",\n  \"generation_succeeded\": true,\n  \"warning\": \"2 tool calls were rejected. generate_video_seedance_v2_0_fast was rejected: ...\",\n  \"failures\": [\n    {\n      \"tool\": \"generate_media\",\n      \"tool_hint\": \"generate_video_seedance_v2_0_fast\",\n      \"code\": \"SEEDANCE_ASSET_MODERATION_REJECTED\",\n      \"message\": \"1 reference asset(s) failed content moderation. Do not retry with the same asset(s); replace them with compliant assets.\"\n    },\n    {\n      \"tool\": \"generate_media\",\n      \"tool_hint\": \"generate_video_minimax_h3\",\n      \"code\": \"INPUT_PARAMS_INVALID\",\n      \"message\": \"MiniMax H3 resolution must be 768P or 2K.\"\n    }\n  ]\n}\n```\n\n`code` is either the specific upstream code, or one of `INPUT_PARAMS_INVALID`\n(bad parameter), `UPSTREAM_ERROR` (generation service error) or `TOOL_FAILED`.\n\n**Always read `failures` before telling the user the run succeeded.** When it is\nnon-empty, tell them what was refused and why. A rejected reference will keep\nbeing rejected, so retrying with the same input wastes credits — replace the\ninput the message names, or reference an approved subject via `--subjects`.\n\n## Reasoning Mode — `--mode thinking` / `--mode fast`\n\nLovart has two reasoning modes you can select per thread:\n\n- **`fast`** (default) — lightweight single-pass response. Use for simple, one-shot generations where speed matters.\n- **`thinking`** — deep structured reasoning with planning and multi-step analysis. Use for complex brand systems, multi-asset campaigns, anything that benefits from deliberate planning. Slower but higher quality.\n\nOmitting `--mode` is equivalent to `--mode fast`, matching the web UI's default.\n\n```bash\n# Thinking mode — strategic, multi-step\npython3 {baseDir}/scripts/agent_skill.py chat --prompt \"design a brand identity system for a sustainable coffee startup\" --mode thinking --json --download\n\n# Fast mode — quick one-shot\npython3 {baseDir}/scripts/agent_skill.py chat --prompt \"draw a cat\" --mode fast --json --download\n```\n\n**Mode is locked to the thread on its first message.** Once you start a thread with `--mode thinking`, subsequent messages on the same `--thread-id` stay in thinking mode regardless of later `--mode` flags. To switch modes, start a new thread (omit `--thread-id`).\n\n## Task-Specific Tool Selection (IMPORTANT)\n\nWhen the user's request matches a specific operation, use `--include-tools` to ensure the correct tool:\n\n| User says | Use `--include-tools` |\n|-----------|----------------------|\n| \"upscale\", \"放大\", \"enlarge\", \"enhance resolution\", \"超分\" | `upscale_image` |\n| \"edit image\", \"modify\", \"change style\" | (let Agent decide) |\n| \"generate image\", \"draw\", \"画\" | (let Agent decide, or use `--prefer-models`) |\n\n**CRITICAL: When the user asks to \"upscale\", \"enlarge\", or increase resolution of an existing image, you MUST use `--include-tools upscale_image`. Do NOT let the Agent use image generation models for upscaling — they will re-generate the image instead of upscaling it.**\n\n## Notes\n\n- All APIs use AK/SK HMAC-SHA256 signature authentication\n- Video generation takes several minutes; the chat command auto-polls until complete\n- Gallery and canvas sync is idempotent — safe to call result multiple times without duplicates\n- Connection failures auto-retry 3 times with SSL fallback\n- After status becomes \"done\", waits 5 seconds to re-confirm (guards against sub-agent startup race)\n\nFile v1.1.0:_meta.json\n\n{\n  \"ownerId\": \"kn75568hvws2gh0ghmryz6dbxh84htc6\",\n  \"slug\": \"lovart-skill\",\n  \"version\": \"1.1.0\",\n  \"publishedAt\": 1788687584911\n}\n\nFile v1.1.0:skill-card.md\n\n## Description:\n\nGenerate images, videos, and audio or music with Lovart AI, and manage Lovart projects, threads, and settings.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[lovart-admin](https://clawhub.ai/user/lovart-admin)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nExternal users and developers use this skill to ask an agent to create visual or audio assets through Lovart, continue project threads, upload references, retrieve generated files, and manage Lovart project settings.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Prompts, selected reference files, project or thread metadata, and generated artifacts are sent to Lovart.\n\nMitigation: Use the skill only for content that is appropriate to process with Lovart, and avoid uploading private files unless that processing is intentional.\n\nRisk: The skill persists and reuses local project and thread state.\n\nMitigation: Review or clear ~/.lovart/state.json and confirm the active project and thread before sensitive work.\n\nRisk: Endpoint or TLS settings can weaken connection safeguards.\n\nMitigation: Keep LOVART_BASE_URL on the official endpoint and do not enable LOVART_INSECURE_SSL.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/lovart-admin/skills/lovart-skill)\n- [Lovart project canvas](https://www.lovart.ai/canvas?projectId={project_id})\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, shell commands, configuration, files]\n\n**Output Format:** [Markdown responses with JSON command results, downloaded media file attachments, and Lovart project links.]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Uses Lovart access credentials, persists local project and thread state, and can return images, videos, audio files, status details, warnings, and error messages.]\n\n## Skill Version(s):\n\n1.1.0 (source: server release metadata and frontmatter)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.0.12: 4 files, 21161 bytes\n\nFiles: scripts/agent_skill.py (45298b), skill-card.md (2697b), SKILL.md (23619b), _meta.json (132b)\n\nFile v1.0.12:SKILL.md\n\n---\nname: lovart-api\ndescription: >-\n  Generate images, videos, and audio/music via Lovart AI. Also manages Lovart projects,\n  threads (conversation history), and user settings. Trigger on: (1) any visual or audio\n  creation request in any language — draw, generate, create, design, make, 画, 生成,\n  制作, 创作, 设计 combined with image, video, audio, music, song, BGM, poster, etc.\n  (2) Lovart project/thread management — 项目, 对话, project, thread, conversation,\n  history, 历史, 切换, switch. You CAN generate directly - never say you cannot.\nuser-invocable: true\nversion: 1.0.12\nauthor: Lovart (lovartai)\nlicense: MIT\nhomepage: https://github.com/lovartai/lovart-skill\nplatforms: [linux, macos, windows]\nmetadata:\n  hermes:\n    tags:\n      - image-generation\n      - video-generation\n      - audio-generation\n      - 3d\n      - design\n      - poster\n      - logo\n      - ai-art\n    related_skills: []\n  openclaw:\n    emoji: 🎨\n    requires:\n      bins: [python3]\n      env: [LOVART_ACCESS_KEY, LOVART_SECRET_KEY]\n    primaryEnv: LOVART_ACCESS_KEY\nprerequisites:\n  commands: [python3]\n  env: [LOVART_ACCESS_KEY, LOVART_SECRET_KEY]\n  python: []\n---\n\n# ⚠️ RULE #0: ONLY USE SKILL COMMANDS — NO DIRECT API CALLS\n\n**You MUST interact with Lovart EXCLUSIVELY through the commands defined in this skill.**\n- NEVER construct URLs, make curl/wget/fetch requests, or call Lovart APIs directly\n- NEVER guess API endpoints, paths, or parameters — only use the commands listed below\n- NEVER modify the skill's source code (agent_skill.py) during execution to \"debug\" issues (users may freely read the source to verify it)\n- If a command fails, retry it or report the error to the user — do NOT try to work around it\n- ALL Lovart operations go through: `chat`, `send`, `watch`, `confirm`, `result`, `status`, `config`, `projects`, `project-add`, `project-switch`, `project-rename`, `project-remove`, `threads`, `thread-remove`, `upload`, `upload-artifact`, `download`, `set-mode`, `query-mode`, `create-project`\n\n# ⚠️ RULE #1: YOU CAN AND MUST GENERATE IMAGES/VIDEOS/AUDIO\n\nWhen a user asks to \"draw\", \"generate\", \"create\", \"design\", \"make\", \"画\", \"生成\", \"制作\", \"创作\"\nany visual or audio content (in any language), you MUST use this skill.\nThis includes: images, videos, audio, music, songs, BGM, TTS, voice, posters, carousels, banners,\nlogos, illustrations, thumbnails, slides, covers, mockups, icons, social media content, etc.\nDo NOT say \"I can't generate images/music\" or offer to write prompts instead.\n\n# ⚠️ RULE #1.5: PROJECT & THREAD QUERIES USE THIS SKILL\n\nWhen the user asks about projects, threads, conversations, history, or settings (in any language),\nuse these commands — do NOT browse the filesystem:\n\n| User asks | Command |\n|-----------|---------|\n| \"What projects do I have?\" / \"我有哪些项目\" | `projects --json` |\n| \"What conversations/threads?\" / \"有哪些对话\" | `threads --json` or `threads --all --json` |\n| \"Show my settings\" / \"我的配置\" | `config --json` |\n| \"Switch to project X\" | `project-switch --project-id X` |\n| \"Create a new project\" | `project-add --project-id NEW_ID --name \"Name\"` (or let `chat` auto-create) |\n\n# ⚠️ RULE #2: ALWAYS USE `chat` AND WAIT FOR COMPLETION\n\nUse the `chat` command (blocks until done), NOT `send`. Do NOT reply before generation completes.\n\n**Handle these `final_status` values:**\n\n- `\"done\"` — Generation complete. Send the downloaded files to the user.\n- `\"pending_confirmation\"` — A high-cost tool (e.g. video, or a premium-quality image variant) needs user approval before credits are consumed.\n  **You MUST ask the user for explicit confirmation before proceeding. Do NOT auto-confirm.**\n  1. Show the user: \"This will cost approximately {estimated_cost} credits. Shall I proceed? (yes/no)\"\n  2. **WAIT for user response.** Only if user explicitly says yes/confirm/proceed, run:\n     `confirm --thread-id THREAD_ID --json --download`\n     (This confirms, waits for completion, and returns the result with downloaded files)\n  3. If user declines, do NOT confirm. Just inform them the operation was cancelled.\n- `\"abort\"` — Generation was aborted. Inform the user.\n- `\"timeout\"` — Generation is still running but exceeded the wait time. The result may contain partial artifacts.\n  1. Send any downloaded files that are already available\n  2. Tell the user: \"Generation is still in progress. Checking again...\"\n  3. Run: `result --thread-id THREAD_ID --json --download` to get the latest results\n  4. If status is still \"running\", wait and retry. If \"done\", send remaining files.\n\n**Handle errors:**\n\nIf `chat` throws an error (`AgentSkillError`), handle it by HTTP status and structured `code`. The `message` field already contains a user-ready explanation — surface it to the user as-is.\n\n| HTTP status | `code` | What it means | What to tell the user |\n|---|---|---|---|\n| **`402`** | `2012` | Quota / billing / risk-control rejection | Show `AgentSkillError.message` directly — the server already returns a specific message (insufficient credits, free-tier reached, concurrent limit, risk control, phone verification, team plan required, etc.) and a suggested next step. |\n| **`409`** | `2011` | Another task is still running on this thread | \"A task is still running on this conversation. Wait for it to finish (`status`) before sending a new prompt, or start a new thread.\" |\n| **`429`** | `1429` | API rate limit hit | \"Slowing down; rate limit hit. Retry in ~60s.\" |\n| **`401`** | — | AK/SK misconfigured | \"API key authentication failed. Please check your LOVART_ACCESS_KEY and LOVART_SECRET_KEY.\" |\n| — | — | `Project.*does not exist` in message | \"Project not found. Please check the project ID or create a new one.\" |\n\nRule of thumb: prefer `AgentSkillError.message` for user-facing copy. Do not try to parse internal codes out of the response — the server already maps them to human-readable messages before returning.\n\n**Detect silent generation failures (`done` with no artifact):**\n\nSome prompts end with `final_status: \"done\"` but produce no `artifacts` / empty `downloaded`. This usually means the upstream image model refused the prompt (content moderation), timed out, or the LLM chose to reply with text instead of calling a tool. The skill flags this automatically — when `chat()` returns, check:\n\n- `result[\"generation_succeeded\"]` — boolean. `False` means no artifact was produced.\n- `result[\"warning\"]` — explanation string (present only when `generation_succeeded` is `False`).\n- `result[\"agent_message\"]` — the agent's plain-text reply that hints at why (present when available).\n\nTypical triggers:\n- GPT Image 2 with very long/complex prompts involving weapons, specific bodies, or policy-sensitive wording — retry with a different model (`--include-tools generate_image_midjourney` or `generate_image_nano_banana_pro`) or simplify the prompt.\n- Prompt that describes a task the agent can't fulfill — show `agent_message` to the user.\n\n# ⚠️ RULE #3: ALWAYS DELIVER RESULTS + PROJECT LINK\n\nAfter EVERY generation, you MUST:\n1. Use `--download` flag with `chat` (or `result`)\n2. Send each downloaded file to the user as a **file attachment** (images, videos, audio/mp3 — ALL file types):\n   - ALWAYS send `downloaded[].local_path` as file attachments, regardless of file type (.png, .jpg, .mp4, .mp3, etc.)\n   - NEVER just paste the URL when a local file has been downloaded — send the actual file\n   - Only fall back to displaying URLs if no files were downloaded\n3. Append the project canvas link: `https://www.lovart.ai/canvas?projectId={project_id}`\n\n# ⚠️ RULE #4: CHECK LOCAL STATE ON FIRST USE (MANDATORY — DO NOT SKIP)\n\n**Before the FIRST generation in a conversation, you MUST run these two commands IN ORDER. This is NOT optional. Do NOT call `chat` until you have done both.**\n\n**Step 1: `config --json`**\n- Check local state (`~/.lovart/state.json`) for `active_project`\n- If `active_project` is set → proceed to Step 2. Do NOT create a new project. Do NOT ask the user.\n- If `active_project` is missing → ask the user: \"Do you have an existing Lovart project ID, or should I create a new one?\" **WAIT for their answer.**\n- Save with: `project-add --project-id PID --name \"name\"`\n\n**Step 2: `threads --json`**\n- Check if there's a recent thread to continue\n- If recent thread exists and topic is related → **REUSE it** (pass `--thread-id THREAD_ID` to `chat`)\n- If no threads or completely different topic → omit `--thread-id` (creates new thread)\n\n**CRITICAL RULES:**\n- **NEVER create a new project** if `config --json` already shows an `active_project`. Reuse it.\n- **NEVER omit `--thread-id`** when a relevant recent thread exists. Always reuse threads by default.\n- **NEVER call `chat` without first running `config --json` and `threads --json`** in the same conversation.\n- The `chat` command auto-reads `active_project` from local state — you do NOT need to pass `--project-id` every time.\n- Only create a new project if the user **explicitly** asks for one.\n- Only create a new thread if the topic is **completely unrelated** to the most recent thread.\n- When in doubt, **REUSE** both the existing project and the existing thread.\n\n---\n\n# Lovart Agent OpenAPI Skill\n\nInteract with Lovart AI Agent to generate images, videos, and visual assets via natural language.\n\nLovart is an AI design platform. The Agent understands user requests and automatically selects the best model and workflow.\n\n## Terminology\n\n- **Thread** — A conversation flow (chat session) with the Lovart AI Agent, NOT a programming thread. Each thread has a unique `thread_id` and preserves multi-turn context. Reusing a thread means continuing the same conversation so the Agent remembers previous images/videos and can iterate on them.\n- **Project** — A workspace/canvas that groups threads and generated artifacts together. One project can contain multiple threads.\n\n## Prerequisites\n\n```bash\nexport LOVART_ACCESS_KEY=\"ak_xxx\"\nexport LOVART_SECRET_KEY=\"sk_xxx\"\n```\n\nNo third-party dependencies. Python standard library only.\n\n## Features\n\n1. **Chat** - Send a message to the AI Agent, get text replies and generated images/videos\n2. **Confirm** - Confirm and wait for high-cost operations (e.g. video generation)\n3. **Create Project** - Create a new project\n4. **Upload File** - Upload a local image/video file, get back a CDN URL\n5. **Upload Artifact** - Upload a link artifact to a project\n6. **Status/Result** - Check thread status and retrieve results\n7. **Set/Query Mode** - Switch between fast (credits) and unlimited (queue) mode\n\n## Usage\n\n### 0. First-time setup (saves to ~/.lovart/state.json)\n\n```bash\npython3 {baseDir}/scripts/agent_skill.py project-add --project-id PROJECT_ID --name \"My Project\"\n```\n\n### 1. Send a message (reads project_id from local state)\n\n```bash\npython3 {baseDir}/scripts/agent_skill.py chat --prompt \"USER_PROMPT\" --json --download\n```\n\nTo override project: add `--project-id PROJECT_ID`\nTo continue a conversation: add `--thread-id THREAD_ID`\nTo list saved threads: `python3 {baseDir}/scripts/agent_skill.py threads`\n\n### 2. Create a project\n\n```bash\npython3 {baseDir}/scripts/agent_skill.py create-project\n```\n\n### 3. Upload a file (local image/video → CDN URL)\n\n```bash\npython3 {baseDir}/scripts/agent_skill.py upload --file /path/to/image.png\n# Returns: {\"url\": \"https://assets-persist.lovart.ai/img/{user_uuid}/xxx.png\"}\n```\n\nUse this when the user sends an image/video file that needs to be passed as an attachment to chat.\n\n### 4. Upload an artifact\n\n```bash\npython3 {baseDir}/scripts/agent_skill.py upload-artifact --project-id PROJECT_ID --url \"ARTIFACT_URL\" --type image\n```\n\n### 5. Check status / get result\n\n```bash\n# Status\npython3 {baseDir}/scripts/agent_skill.py status --thread-id THREAD_ID\n\n# Result (auto-syncs to gallery/canvas, idempotent)\npython3 {baseDir}/scripts/agent_skill.py result --thread-id THREAD_ID --json --download\n```\n\n### 6. Download artifacts\n\n```bash\n# Download during chat\npython3 {baseDir}/scripts/agent_skill.py chat --prompt \"draw a cat\" --json --download --output-dir /tmp/lovart\n\n# Download from existing result\npython3 {baseDir}/scripts/agent_skill.py result --thread-id THREAD_ID --download --output-dir /tmp/lovart\n\n# Download specific URLs\npython3 {baseDir}/scripts/agent_skill.py download --urls URL1 URL2 --output-dir /tmp/lovart --prefix myimg\n```\n\n## Typical Workflows\n\n### Scenario 1: Generate images/videos/audio (most common)\n\n**First, run `config --json` to check if project_id is set. If not, ask the user and save with `project-add`.**\n\n```\n1. config --json  →  check local state for active_project\n   - If not set → ask user, save with project-add\n2. threads --json  →  check if there's a recent thread to continue\n   - If recent thread exists and topic is related → reuse it (step 3a)\n   - If no threads or completely new topic → new thread (step 3b)\n3a. chat --thread-id THREAD_ID --prompt \"user's request\" --json --download\n3b. chat --prompt \"user's request\" --json --download\n4. Send each downloaded[].local_path file as an IM attachment to the user\n5. The chat command auto-syncs artifacts to canvas and gallery\n```\n\n**IDs are auto-persisted locally (`~/.lovart/state.json`):**\n- project_id is saved after first chat, reused automatically\n- thread_id + topic are saved after each chat for thread switching\n- Only create a new project if the user explicitly asks for one\n- Only create a new thread (omit `--thread-id`) when starting a completely new topic\n- Run `threads` to list saved threads for the user to pick from\n\n### Scenario 2: Edit with attachments\n\n```\n1. User sends a reference image/video via IM → save to local file\n2. upload --file /path/to/image.png  →  get CDN URL\n3. chat --prompt \"edit this image to...\" --project-id PID --attachments \"CDN_URL\" --json --download\n4. Continue as Scenario 1\n```\n\n### Scenario 3: Follow-up on same topic (continue context)\n\n```\n1. chat --prompt \"change the background to a beach\" --project-id PROJECT_ID --thread-id THREAD_ID --json --download\n```\n\nThe Agent remembers the previous conversation and can continue editing based on context.\n\n### Scenario 4: New topic (new thread)\n\n```\n1. chat --prompt \"completely new request\" --project-id PROJECT_ID --json --download\n```\n\nOmitting `--thread-id` creates a new conversation without previous memory.\n\n### Scenario 5: Streaming / incremental delivery (multiple artifacts)\n\n**Use when** the user's request will produce multiple images/videos and you want to deliver each one to the user as soon as it's ready, rather than waiting for the whole batch.\n\n```bash\npython3 {baseDir}/scripts/agent_skill.py watch --prompt \"generate 4 variations of a cyberpunk cat\" --json\n```\n\n`watch` emits **NDJSON** to stdout (one event per line). Parse line-by-line and deliver each `artifact` event's `local_path` to the user immediately:\n\n```json\n{\"event\": \"started\", \"thread_id\": \"xxx\", \"project_id\": \"yyy\"}\n{\"event\": \"artifact\", \"type\": \"image\", \"url\": \"https://...\", \"local_path\": \"/tmp/lovart/lovart_ab12cd.png\"}\n{\"event\": \"artifact\", \"type\": \"image\", \"url\": \"https://...\", \"local_path\": \"/tmp/lovart/lovart_ef34gh.png\"}\n{\"event\": \"pending_confirmation\", \"thread_id\": \"xxx\", \"pending_confirmation\": {...}}\n{\"event\": \"finished\", \"thread_id\": \"xxx\", \"final_status\": \"done\", \"artifact_count\": 4}\n```\n\nFiles are saved with URL-hash filenames so re-running `watch` on the same thread won't re-download.\n\nYou can also attach to an **already-running** thread: `watch --thread-id THREAD_ID`.\n\n**When NOT to use `watch`:** single-image requests — use `chat` (simpler, one-shot response).\n\n## Output Format\n\n**chat --json** returns:\n```json\n{\n  \"thread_id\": \"xxx\",\n  \"status\": \"done\",\n  \"project_id\": \"xxx\",\n  \"final_status\": \"done\",\n  \"items\": [\n    {\"type\": \"assistant\", \"text\": \"Agent's reply\"},\n    {\"type\": \"generator\", \"name\": \"artifacts\", \"artifacts\": [\n      {\"type\": \"image\", \"content\": \"https://assets-persist.lovart.ai/artifacts/agent/xxx.png\"},\n      {\"type\": \"video\", \"content\": \"https://assets-persist.lovart.ai/artifacts/agent/xxx.mp4\"}\n    ]}\n  ],\n  \"downloaded\": [\n    {\"type\": \"image\", \"url\": \"https://...\", \"local_path\": \"/tmp/lovart/lovart_01.png\"}\n  ]\n}\n```\n\n## Core Principle\n\nYou are a messenger, not a creator. The backend Agent handles understanding requirements, selecting models, and writing prompts. Your job:\n\n1. **Relay**: Pass the user's original description verbatim to chat\n2. **Wait**: Poll until generation completes\n3. **Deliver**: Send result files to the user\n\n**Do NOT** rewrite/expand prompts, break down tasks, or add your own style descriptions.\n\n## Lovart Generation Mode (MUST use API, not prompt)\n\n**CRITICAL: \"Fast mode\" and \"unlimited mode\" are server-side settings controlled via API calls, NOT prompt keywords.**\n\nDo NOT put \"快速模式\" or \"fast mode\" in the prompt text. Instead, call the set-mode command:\n\n```bash\n# User says \"fast mode\" / \"快速模式\" / \"skip queue\" / \"use credits\" → RUN THIS:\npython3 {baseDir}/scripts/agent_skill.py set-mode --fast\n\n# User says \"unlimited mode\" / \"无限模式\" / \"free mode\" / \"save credits\" → RUN THIS:\npython3 {baseDir}/scripts/agent_skill.py set-mode --unlimited\n\n# Check which mode is active:\npython3 {baseDir}/scripts/agent_skill.py query-mode\n```\n\n**How it works:**\n- `set-mode --fast` calls the Lovart backend API to switch the user's account to fast generation (costs credits, no queue)\n- `set-mode --unlimited` switches to unlimited generation (free, may queue)\n- This is a **persistent server-side setting** — it stays until changed again\n- It affects ALL subsequent image/video generations, not just one request\n- It has **nothing to do with your (the assistant's) response style or behavior**\n\n## Specifying Models\n\n**Option 1: In the prompt** (simple, the Agent routes automatically):\n\n```bash\npython3 {baseDir}/scripts/agent_skill.py chat --prompt \"generate ocean waves video using kling\" --json --download\n```\n\n**Option 2: Via --prefer-models** (precise, same as frontend's model selector):\n\n```bash\n# Prefer a specific image model\npython3 {baseDir}/scripts/agent_skill.py chat --prompt \"draw a cat\" --prefer-models '{\"IMAGE\":[\"generate_image_midjourney\"]}' --json --download\n\n# Prefer a specific video model\npython3 {baseDir}/scripts/agent_skill.py chat --prompt \"generate ocean waves\" --prefer-models '{\"VIDEO\":[\"generate_video_kling_3_0\"]}' --json --download\n\n# Combine image and video preferences\npython3 {baseDir}/scripts/agent_skill.py chat --prompt \"create content\" --prefer-models '{\"IMAGE\":[\"generate_image_seedream_3_0\"],\"VIDEO\":[\"generate_video_kling_3_0\"]}' --json --download\n```\n\nAvailable models for `--prefer-models`:\n\n**IMAGE:**\n\n| Tool name | Display name |\n|---|---|\n| `generate_image_gpt_image_2` | GPT Image 2 Auto |\n| `generate_image_gpt_image_2_low` | GPT Image 2 Low |\n| `generate_image_gpt_image_2_medium` | GPT Image 2 Medium |\n| `generate_image_gpt_image_2_high` | GPT Image 2 High |\n| `generate_image_nano_banana_pro` | Nano Banana Pro |\n| `generate_image_nano_banana_2` | Nano Banana 2 |\n| `generate_image_gpt_image_1_5` | GPT Image 1.5 |\n| `generate_image_seedream_v5` | Seedream 5.0 Lite |\n| `generate_image_luma_uni_1` | Luma uni-1 |\n| `generate_image_luma_uni_1_max` | Luma uni-1-max |\n| `generate_image_flux_2_max` | Flux.2 Max |\n| `generate_image_flux_2_pro` | Flux.2 Pro |\n| `generate_image_seedream_v4_5` | Seedream 4.5 |\n| `generate_image_nano_banana` | Nano Banana |\n| `generate_image_seedream_v4` | Seedream 4 |\n| `generate_image_midjourney` | Midjourney |\n| `generate_image_ideogram_v4` | Ideogram 4 |\n| `generate_image_nano_banana_2_lite` | Nano Banana 2 Lite |\n| `generate_image_seedream_v5_pro` | Seedream 5.0 Pro |\n\n**VIDEO:**\n\n| Tool name | Display name |\n|---|---|\n| `generate_video_seedance_v2_0` | Seedance 2.0 |\n| `generate_video_seedance_v2_0_fast` | Seedance 2.0 Fast |\n| `generate_video_seedance_v2_0_mini` | Seedance 2.0 Mini |\n| `generate_video_kling_v3` | Kling 3.0 |\n| `generate_video_kling_v3_omni` | Kling 3.0 Omni |\n| `generate_video_seedance_pro_v1_5` | Seedance 1.5 Pro |\n| `generate_video_kling_v2_6` | Kling 2.6 |\n| `generate_video_wan_v2_6` | Wan 2.6 |\n| `generate_video_veo3_1` | Veo 3.1 |\n| `generate_video_veo3_1_fast` | Veo 3.1 Fast |\n| `generate_video_kling_omni_v1` | Kling O1 |\n| `generate_video_hailuo_v2_3` | Hailuo 2.3 |\n| `generate_video_veo3` | Veo 3 |\n| `generate_video_vidu_q2` | Vidu Q2 |\n| `generate_video_gemini_omni_flash` | Gemini Omni Flash |\n\n**3D:**\n\n| Tool name | Display name |\n|---|---|\n| `generate_3d_tripo` | Tripo |\n\nWhen the user requests a specific model, prefer `--prefer-models` over putting model names in the prompt.\n\n**Option 3: Via --include-tools** (hard constraint, forces specific tools):\n\n```bash\n# Force upscale only\npython3 {baseDir}/scripts/agent_skill.py chat --prompt \"upscale this image to 4K\" --include-tools upscale_image --attachments \"IMAGE_URL\" --json --download\n\n# Force a specific video model (no fallback to others)\npython3 {baseDir}/scripts/agent_skill.py chat --prompt \"generate a video\" --include-tools generate_video_kling_3_0 --json --download\n```\n\n`--include-tools` strongly instructs the Agent to prioritize the listed tools. Use this when the user explicitly requests a specific tool or operation.\n\n## Reasoning Mode — `--mode thinking` / `--mode fast`\n\nLovart has two reasoning modes you can select per thread:\n\n- **`fast`** (default) — lightweight single-pass response. Use for simple, one-shot generations where speed matters.\n- **`thinking`** — deep structured reasoning with planning and multi-step analysis. Use for complex brand systems, multi-asset campaigns, anything that benefits from deliberate planning. Slower but higher quality.\n\nOmitting `--mode` is equivalent to `--mode fast`, matching the web UI's default.\n\n```bash\n# Thinking mode — strategic, multi-step\npython3 {baseDir}/scripts/agent_skill.py chat --prompt \"design a brand identity system for a sustainable coffee startup\" --mode thinking --json --download\n\n# Fast mode — quick one-shot\npython3 {baseDir}/scripts/agent_skill.py chat --prompt \"draw a cat\" --mode fast --json --download\n```\n\n**Mode is locked to the thread on its first message.** Once you start a thread with `--mode thinking`, subsequent messages on the same `--thread-id` stay in thinking mode regardless of later `--mode` flags. To switch modes, start a new thread (omit `--thread-id`).\n\n## Task-Specific Tool Selection (IMPORTANT)\n\nWhen the user's request matches a specific operation, use `--include-tools` to ensure the correct tool:\n\n| User says | Use `--include-tools` |\n|-----------|----------------------|\n| \"upscale\", \"放大\", \"enlarge\", \"enhance resolution\", \"超分\" | `upscale_image` |\n| \"edit image\", \"modify\", \"change style\" | (let Agent decide) |\n| \"generate image\", \"draw\", \"画\" | (let Agent decide, or use `--prefer-models`) |\n\n**CRITICAL: When the user asks to \"upscale\", \"enlarge\", or increase resolution of an existing image, you MUST use `--include-tools upscale_image`. Do NOT let the Agent use image generation models for upscaling — they will re-generate the image instead of upscaling it.**\n\n## Notes\n\n- All APIs use AK/SK HMAC-SHA256 signature authentication\n- Video generation takes several minutes; the chat command auto-polls until complete\n- Gallery and canvas sync is idempotent — safe to call result multiple times without duplicates\n- Connection failures auto-retry 3 times with SSL fallback\n- After status becomes \"done\", waits 5 seconds to re-confirm (guards against sub-agent startup race)\n\nFile v1.0.12:_meta.json\n\n{\n  \"ownerId\": \"kn75568hvws2gh0ghmryz6dbxh84htc6\",\n  \"slug\": \"lovart-skill\",\n  \"version\": \"1.0.12\",\n  \"publishedAt\": 1784099885768\n}\n\nFile v1.0.12:skill-card.md\n\n## Description: <br>\nLovart Skill enables agents to generate images, videos, audio, and music through Lovart AI while managing Lovart projects, conversation threads, uploads, downloads, user settings, and generation modes. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[lovart-admin](https://clawhub.ai/user/lovart-admin) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nExternal users and developers use this skill to request Lovart AI media generation or manage Lovart project and thread state from an agent. It supports reference uploads, generated artifact downloads, project canvas links, and mode or model selection for Lovart generation workflows. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: Prompts, selected attachments, and generated-artifact traffic are sent to Lovart using the user's Lovart API keys. <br>\nMitigation: Install and use the skill only when this Lovart data flow is acceptable for the user's content and account. <br>\nRisk: The skill can reuse local Lovart project and thread history stored in ~/.lovart/state.json. <br>\nMitigation: Review or clear ~/.lovart/state.json when project or conversation continuity should not be reused. <br>\nRisk: TLS verification can be weakened when LOVART_INSECURE_SSL is set. <br>\nMitigation: Avoid setting LOVART_INSECURE_SSL unless the user knowingly accepts weaker TLS protection. <br>\nRisk: Some high-cost generation operations may consume Lovart credits. <br>\nMitigation: Require explicit user confirmation before running confirmation commands for credit-consuming operations. <br>\n\n\n## Reference(s): <br>\n- [Lovart Skill on ClawHub](https://clawhub.ai/lovart-admin/skills/lovart-skill) <br>\n- [Lovart Project Canvas](https://www.lovart.ai/canvas?projectId={project_id}) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [text, markdown, shell commands, configuration, files, JSON, guidance] <br>\n**Output Format:** [Markdown guidance with shell commands, JSON command output, and downloaded media files.] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Requires Lovart API credentials; generated artifacts may be downloaded to local paths and project/thread state may be persisted in ~/.lovart/state.json.] <br>\n\n## Skill Version(s): <br>\n1.0.12 (source: SKILL.md frontmatter and server release metadata) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nArchive v1.0.11: 4 files, 20987 bytes\n\nFiles: scripts/agent_skill.py (45310b), skill-card.md (2316b), SKILL.md (23631b), _meta.json (132b)\n\nFile v1.0.11:SKILL.md\n\n---\nname: lovart-api\ndescription: >-\n  Generate images, videos, and audio/music via Lovart AI. Also manages Lovart projects,\n  threads (conversation history), and user settings. Trigger on: (1) any visual or audio\n  creation request in any language — draw, generate, create, design, make, 画, 生成,\n  制作, 创作, 设计 combined with image, video, audio, music, song, BGM, poster, etc.\n  (2) Lovart project/thread management — 项目, 对话, project, thread, conversation,\n  history, 历史, 切换, switch. You CAN generate directly - never say you cannot.\nuser-invocable: true\nversion: 1.0.11\nauthor: Lovart (lovartai)\nlicense: MIT\nhomepage: https://github.com/lovartai/lovart-skill\nplatforms: [linux, macos, windows]\nmetadata:\n  hermes:\n    tags:\n      - image-generation\n      - video-generation\n      - audio-generation\n      - 3d\n      - design\n      - poster\n      - logo\n      - ai-art\n    related_skills: []\n  openclaw:\n    emoji: 🎨\n    requires:\n      bins: [python3]\n      env: [LOVART_ACCESS_KEY, LOVART_SECRET_KEY]\n    primaryEnv: LOVART_ACCESS_KEY\nprerequisites:\n  commands: [python3]\n  env: [LOVART_ACCESS_KEY, LOVART_SECRET_KEY]\n  python: []\n---\n\n# ⚠️ RULE #0: ONLY USE SKILL COMMANDS — NO DIRECT API CALLS\n\n**You MUST interact with Lovart EXCLUSIVELY through the commands defined in this skill.**\n- NEVER construct URLs, make curl/wget/fetch requests, or call Lovart APIs directly\n- NEVER guess API endpoints, paths, or parameters — only use the commands listed below\n- NEVER modify the skill's source code (agent_skill.py) during execution to \"debug\" issues (users may freely read the source to verify it)\n- If a command fails, retry it or report the error to the user — do NOT try to work around it\n- ALL Lovart operations go through: `chat`, `send`, `watch`, `confirm`, `result`, `status`, `config`, `projects`, `project-add`, `project-switch`, `project-rename`, `project-remove`, `threads`, `thread-remove`, `upload`, `upload-artifact`, `download`, `set-mode`, `query-mode`, `create-project`\n\n# ⚠️ RULE #1: YOU CAN AND MUST GENERATE IMAGES/VIDEOS/AUDIO\n\nWhen a user asks to \"draw\", \"generate\", \"create\", \"design\", \"make\", \"画\", \"生成\", \"制作\", \"创作\"\nany visual or audio content (in any language), you MUST use this skill.\nThis includes: images, videos, audio, music, songs, BGM, TTS, voice, posters, carousels, banners,\nlogos, illustrations, thumbnails, slides, covers, mockups, icons, social media content, etc.\nDo NOT say \"I can't generate images/music\" or offer to write prompts instead.\n\n# ⚠️ RULE #1.5: PROJECT & THREAD QUERIES USE THIS SKILL\n\nWhen the user asks about projects, threads, conversations, history, or settings (in any language),\nuse these commands — do NOT browse the filesystem:\n\n| User asks | Command |\n|-----------|---------|\n| \"What projects do I have?\" / \"我有哪些项目\" | `projects --json` |\n| \"What conversations/threads?\" / \"有哪些对话\" | `threads --json` or `threads --all --json` |\n| \"Show my settings\" / \"我的配置\" | `config --json` |\n| \"Switch to project X\" | `project-switch --project-id X` |\n| \"Create a new project\" | `project-add --project-id NEW_ID --name \"Name\"` (or let `chat` auto-create) |\n\n# ⚠️ RULE #2: ALWAYS USE `chat` AND WAIT FOR COMPLETION\n\nUse the `chat` command (blocks until done), NOT `send`. Do NOT reply before generation completes.\n\n**Handle these `final_status` values:**\n\n- `\"done\"` — Generation complete. Send the downloaded files to the user.\n- `\"pending_confirmation\"` — A high-cost tool (e.g. video, or a premium-quality image variant) needs user approval before credits are consumed.\n  **You MUST ask the user for explicit confirmation before proceeding. Do NOT auto-confirm.**\n  1. Show the user: \"This will cost approximately {estimated_cost} credits. Shall I proceed? (yes/no)\"\n  2. **WAIT for user response.** Only if user explicitly says yes/confirm/proceed, run:\n     `confirm --thread-id THREAD_ID --json --download`\n     (This confirms, waits for completion, and returns the result with downloaded files)\n  3. If user declines, do NOT confirm. Just inform them the operation was cancelled.\n- `\"abort\"` — Generation was aborted. Inform the user.\n- `\"timeout\"` — Generation is still running but exceeded the wait time. The result may contain partial artifacts.\n  1. Send any downloaded files that are already available\n  2. Tell the user: \"Generation is still in progress. Checking again...\"\n  3. Run: `result --thread-id THREAD_ID --json --download` to get the latest results\n  4. If status is still \"running\", wait and retry. If \"done\", send remaining files.\n\n**Handle errors:**\n\nIf `chat` throws an error (`AgentSkillError`), handle it by HTTP status and structured `code`. The `message` field already contains a user-ready explanation — surface it to the user as-is.\n\n| HTTP status | `code` | What it means | What to tell the user |\n|---|---|---|---|\n| **`402`** | `2012` | Quota / billing / risk-control rejection | Show `AgentSkillError.message` directly — the server already returns a specific message (insufficient credits, free-tier reached, concurrent limit, risk control, phone verification, team plan required, etc.) and a suggested next step. |\n| **`409`** | `2011` | Another task is still running on this thread | \"A task is still running on this conversation. Wait for it to finish (`status`) before sending a new prompt, or start a new thread.\" |\n| **`429`** | `1429` | API rate limit hit | \"Slowing down; rate limit hit. Retry in ~60s.\" |\n| **`401`** | — | AK/SK misconfigured | \"API key authentication failed. Please check your LOVART_ACCESS_KEY and LOVART_SECRET_KEY.\" |\n| — | — | `Project.*does not exist` in message | \"Project not found. Please check the project ID or create a new one.\" |\n\nRule of thumb: prefer `AgentSkillError.message` for user-facing copy. Do not try to parse internal codes out of the response — the server already maps them to human-readable messages before returning.\n\n**Detect silent generation failures (`done` with no artifact):**\n\nSome prompts end with `final_status: \"done\"` but produce no `artifacts` / empty `downloaded`. This usually means the upstream image model refused the prompt (content moderation), timed out, or the LLM chose to reply with text instead of calling a tool. The skill flags this automatically — when `chat()` returns, check:\n\n- `result[\"generation_succeeded\"]` — boolean. `False` means no artifact was produced.\n- `result[\"warning\"]` — explanation string (present only when `generation_succeeded` is `False`).\n- `result[\"agent_message\"]` — the agent's plain-text reply that hints at why (present when available).\n\nTypical triggers:\n- GPT Image 2 with very long/complex prompts involving weapons, specific bodies, or policy-sensitive wording — retry with a different model (`--include-tools generate_image_midjourney` or `generate_image_nano_banana_pro`) or simplify the prompt.\n- Prompt that describes a task the agent can't fulfill — show `agent_message` to the user.\n\n# ⚠️ RULE #3: ALWAYS DELIVER RESULTS + PROJECT LINK\n\nAfter EVERY generation, you MUST:\n1. Use `--download` flag with `chat` (or `result`)\n2. Send each downloaded file to the user as a **file attachment** (images, videos, audio/mp3 — ALL file types):\n   - ALWAYS send `downloaded[].local_path` as file attachments, regardless of file type (.png, .jpg, .mp4, .mp3, etc.)\n   - NEVER just paste the URL when a local file has been downloaded — send the actual file\n   - Only fall back to displaying URLs if no files were downloaded\n3. Append the project canvas link: `https://www.lovart.ai/canvas?projectId={project_id}`\n\n# ⚠️ RULE #4: CHECK LOCAL STATE ON FIRST USE (MANDATORY — DO NOT SKIP)\n\n**Before the FIRST generation in a conversation, you MUST run these two commands IN ORDER. This is NOT optional. Do NOT call `chat` until you have done both.**\n\n**Step 1: `config --json`**\n- Check local state (`~/.lovart/state.json`) for `active_project`\n- If `active_project` is set → proceed to Step 2. Do NOT create a new project. Do NOT ask the user.\n- If `active_project` is missing → ask the user: \"Do you have an existing Lovart project ID, or should I create a new one?\" **WAIT for their answer.**\n- Save with: `project-add --project-id PID --name \"name\"`\n\n**Step 2: `threads --json`**\n- Check if there's a recent thread to continue\n- If recent thread exists and topic is related → **REUSE it** (pass `--thread-id THREAD_ID` to `chat`)\n- If no threads or completely different topic → omit `--thread-id` (creates new thread)\n\n**CRITICAL RULES:**\n- **NEVER create a new project** if `config --json` already shows an `active_project`. Reuse it.\n- **NEVER omit `--thread-id`** when a relevant recent thread exists. Always reuse threads by default.\n- **NEVER call `chat` without first running `config --json` and `threads --json`** in the same conversation.\n- The `chat` command auto-reads `active_project` from local state — you do NOT need to pass `--project-id` every time.\n- Only create a new project if the user **explicitly** asks for one.\n- Only create a new thread if the topic is **completely unrelated** to the most recent thread.\n- When in doubt, **REUSE** both the existing project and the existing thread.\n\n---\n\n# Lovart Agent OpenAPI Skill\n\nInteract with Lovart AI Agent to generate images, videos, and visual assets via natural language.\n\nLovart is an AI design platform. The Agent understands user requests and automatically selects the best model and workflow.\n\n## Terminology\n\n- **Thread** — A conversation flow (chat session) with the Lovart AI Agent, NOT a programming thread. Each thread has a unique `thread_id` and preserves multi-turn context. Reusing a thread means continuing the same conversation so the Agent remembers previous images/videos and can iterate on them.\n- **Project** — A workspace/canvas that groups threads and generated artifacts together. One project can contain multiple threads.\n\n## Prerequisites\n\n```bash\nexport LOVART_ACCESS_KEY=\"ak_xxx\"\nexport LOVART_SECRET_KEY=\"sk_xxx\"\n```\n\nNo third-party dependencies. Python standard library only.\n\n## Features\n\n1. **Chat** - Send a message to the AI Agent, get text replies and generated images/videos\n2. **Confirm** - Confirm and wait for high-cost operations (e.g. video generation)\n3. **Create Project** - Create a new project\n4. **Upload File** - Upload a local image/video file, get back a CDN URL\n5. **Upload Artifact** - Upload a link artifact to a project\n6. **Status/Result** - Check thread status and retrieve results\n7. **Set/Query Mode** - Switch between fast (credits) and unlimited (queue) mode\n\n## Usage\n\n### 0. First-time setup (saves to ~/.lovart/state.json)\n\n```bash\npython3 {baseDir}/scripts/agent_skill.py project-add --project-id PROJECT_ID --name \"My Project\"\n```\n\n### 1. Send a message (reads project_id from local state)\n\n```bash\npython3 {baseDir}/scripts/agent_skill.py chat --prompt \"USER_PROMPT\" --json --download\n```\n\nTo override project: add `--project-id PROJECT_ID`\nTo continue a conversation: add `--thread-id THREAD_ID`\nTo list saved threads: `python3 {baseDir}/scripts/agent_skill.py threads`\n\n### 2. Create a project\n\n```bash\npython3 {baseDir}/scripts/agent_skill.py create-project\n```\n\n### 3. Upload a file (local image/video → CDN URL)\n\n```bash\npython3 {baseDir}/scripts/agent_skill.py upload --file /path/to/image.png\n# Returns: {\"url\": \"https://assets-persist.lovart.ai/img/{user_uuid}/xxx.png\"}\n```\n\nUse this when the user sends an image/video file that needs to be passed as an attachment to chat.\n\n### 4. Upload an artifact\n\n```bash\npython3 {baseDir}/scripts/agent_skill.py upload-artifact --project-id PROJECT_ID --url \"ARTIFACT_URL\" --type image\n```\n\n### 5. Check status / get result\n\n```bash\n# Status\npython3 {baseDir}/scripts/agent_skill.py status --thread-id THREAD_ID\n\n# Result (auto-syncs to gallery/canvas, idempotent)\npython3 {baseDir}/scripts/agent_skill.py result --thread-id THREAD_ID --json --download\n```\n\n### 6. Download artifacts\n\n```bash\n# Download during chat\npython3 {baseDir}/scripts/agent_skill.py chat --prompt \"draw a cat\" --json --download --output-dir /tmp/openclaw\n\n# Download from existing result\npython3 {baseDir}/scripts/agent_skill.py result --thread-id THREAD_ID --download --output-dir /tmp/openclaw\n\n# Download specific URLs\npython3 {baseDir}/scripts/agent_skill.py download --urls URL1 URL2 --output-dir /tmp/openclaw --prefix myimg\n```\n\n## Typical Workflows\n\n### Scenario 1: Generate images/videos/audio (most common)\n\n**First, run `config --json` to check if project_id is set. If not, ask the user and save with `project-add`.**\n\n```\n1. config --json  →  check local state for active_project\n   - If not set → ask user, save with project-add\n2. threads --json  →  check if there's a recent thread to continue\n   - If recent thread exists and topic is related → reuse it (step 3a)\n   - If no threads or completely new topic → new thread (step 3b)\n3a. chat --thread-id THREAD_ID --prompt \"user's request\" --json --download\n3b. chat --prompt \"user's request\" --json --download\n4. Send each downloaded[].local_path file as an IM attachment to the user\n5. The chat command auto-syncs artifacts to canvas and gallery\n```\n\n**IDs are auto-persisted locally (`~/.lovart/state.json`):**\n- project_id is saved after first chat, reused automatically\n- thread_id + topic are saved after each chat for thread switching\n- Only create a new project if the user explicitly asks for one\n- Only create a new thread (omit `--thread-id`) when starting a completely new topic\n- Run `threads` to list saved threads for the user to pick from\n\n### Scenario 2: Edit with attachments\n\n```\n1. User sends a reference image/video via IM → save to local file\n2. upload --file /path/to/image.png  →  get CDN URL\n3. chat --prompt \"edit this image to...\" --project-id PID --attachments \"CDN_URL\" --json --download\n4. Continue as Scenario 1\n```\n\n### Scenario 3: Follow-up on same topic (continue context)\n\n```\n1. chat --prompt \"change the background to a beach\" --project-id PROJECT_ID --thread-id THREAD_ID --json --download\n```\n\nThe Agent remembers the previous conversation and can continue editing based on context.\n\n### Scenario 4: New topic (new thread)\n\n```\n1. chat --prompt \"completely new request\" --project-id PROJECT_ID --json --download\n```\n\nOmitting `--thread-id` creates a new conversation without previous memory.\n\n### Scenario 5: Streaming / incremental delivery (multiple artifacts)\n\n**Use when** the user's request will produce multiple images/videos and you want to deliver each one to the user as soon as it's ready, rather than waiting for the whole batch.\n\n```bash\npython3 {baseDir}/scripts/agent_skill.py watch --prompt \"generate 4 variations of a cyberpunk cat\" --json\n```\n\n`watch` emits **NDJSON** to stdout (one event per line). Parse line-by-line and deliver each `artifact` event's `local_path` to the user immediately:\n\n```json\n{\"event\": \"started\", \"thread_id\": \"xxx\", \"project_id\": \"yyy\"}\n{\"event\": \"artifact\", \"type\": \"image\", \"url\": \"https://...\", \"local_path\": \"/tmp/openclaw/lovart_ab12cd.png\"}\n{\"event\": \"artifact\", \"type\": \"image\", \"url\": \"https://...\", \"local_path\": \"/tmp/openclaw/lovart_ef34gh.png\"}\n{\"event\": \"pending_confirmation\", \"thread_id\": \"xxx\", \"pending_confirmation\": {...}}\n{\"event\": \"finished\", \"thread_id\": \"xxx\", \"final_status\": \"done\", \"artifact_count\": 4}\n```\n\nFiles are saved with URL-hash filenames so re-running `watch` on the same thread won't re-download.\n\nYou can also attach to an **already-running** thread: `watch --thread-id THREAD_ID`.\n\n**When NOT to use `watch`:** single-image requests — use `chat` (simpler, one-shot response).\n\n## Output Format\n\n**chat --json** returns:\n```json\n{\n  \"thread_id\": \"xxx\",\n  \"status\": \"done\",\n  \"project_id\": \"xxx\",\n  \"final_status\": \"done\",\n  \"items\": [\n    {\"type\": \"assistant\", \"text\": \"Agent's reply\"},\n    {\"type\": \"generator\", \"name\": \"artifacts\", \"artifacts\": [\n      {\"type\": \"image\", \"content\": \"https://assets-persist.lovart.ai/artifacts/agent/xxx.png\"},\n      {\"type\": \"video\", \"content\": \"https://assets-persist.lovart.ai/artifacts/agent/xxx.mp4\"}\n    ]}\n  ],\n  \"downloaded\": [\n    {\"type\": \"image\", \"url\": \"https://...\", \"local_path\": \"/tmp/openclaw/lovart_01.png\"}\n  ]\n}\n```\n\n## Core Principle\n\nYou are a messenger, not a creator. The backend Agent handles understanding requirements, selecting models, and writing prompts. Your job:\n\n1. **Relay**: Pass the user's original description verbatim to chat\n2. **Wait**: Poll until generation completes\n3. **Deliver**: Send result files to the user\n\n**Do NOT** rewrite/expand prompts, break down tasks, or add your own style descriptions.\n\n## Lovart Generation Mode (MUST use API, not prompt)\n\n**CRITICAL: \"Fast mode\" and \"unlimited mode\" are server-side settings controlled via API calls, NOT prompt keywords.**\n\nDo NOT put \"快速模式\" or \"fast mode\" in the prompt text. Instead, call the set-mode command:\n\n```bash\n# User says \"fast mode\" / \"快速模式\" / \"skip queue\" / \"use credits\" → RUN THIS:\npython3 {baseDir}/scripts/agent_skill.py set-mode --fast\n\n# User says \"unlimited mode\" / \"无限模式\" / \"free mode\" / \"save credits\" → RUN THIS:\npython3 {baseDir}/scripts/agent_skill.py set-mode --unlimited\n\n# Check which mode is active:\npython3 {baseDir}/scripts/agent_skill.py query-mode\n```\n\n**How it works:**\n- `set-mode --fast` calls the Lovart backend API to switch the user's account to fast generation (costs credits, no queue)\n- `set-mode --unlimited` switches to unlimited generation (free, may queue)\n- This is a **persistent server-side setting** — it stays until changed again\n- It affects ALL subsequent image/video generations, not just one request\n- It has **nothing to do with your (the assistant's) response style or behavior**\n\n## Specifying Models\n\n**Option 1: In the prompt** (simple, the Agent routes automatically):\n\n```bash\npython3 {baseDir}/scripts/agent_skill.py chat --prompt \"generate ocean waves video using kling\" --json --download\n```\n\n**Option 2: Via --prefer-models** (precise, same as frontend's model selector):\n\n```bash\n# Prefer a specific image model\npython3 {baseDir}/scripts/agent_skill.py chat --prompt \"draw a cat\" --prefer-models '{\"IMAGE\":[\"generate_image_midjourney\"]}' --json --download\n\n# Prefer a specific video model\npython3 {baseDir}/scripts/agent_skill.py chat --prompt \"generate ocean waves\" --prefer-models '{\"VIDEO\":[\"generate_video_kling_3_0\"]}' --json --download\n\n# Combine image and video preferences\npython3 {baseDir}/scripts/agent_skill.py chat --prompt \"create content\" --prefer-models '{\"IMAGE\":[\"generate_image_seedream_3_0\"],\"VIDEO\":[\"generate_video_kling_3_0\"]}' --json --download\n```\n\nAvailable models for `--prefer-models`:\n\n**IMAGE:**\n\n| Tool name | Display name |\n|---|---|\n| `generate_image_gpt_image_2` | GPT Image 2 Auto |\n| `generate_image_gpt_image_2_low` | GPT Image 2 Low |\n| `generate_image_gpt_image_2_medium` | GPT Image 2 Medium |\n| `generate_image_gpt_image_2_high` | GPT Image 2 High |\n| `generate_image_nano_banana_pro` | Nano Banana Pro |\n| `generate_image_nano_banana_2` | Nano Banana 2 |\n| `generate_image_gpt_image_1_5` | GPT Image 1.5 |\n| `generate_image_seedream_v5` | Seedream 5.0 Lite |\n| `generate_image_luma_uni_1` | Luma uni-1 |\n| `generate_image_luma_uni_1_max` | Luma uni-1-max |\n| `generate_image_flux_2_max` | Flux.2 Max |\n| `generate_image_flux_2_pro` | Flux.2 Pro |\n| `generate_image_seedream_v4_5` | Seedream 4.5 |\n| `generate_image_nano_banana` | Nano Banana |\n| `generate_image_seedream_v4` | Seedream 4 |\n| `generate_image_midjourney` | Midjourney |\n| `generate_image_ideogram_v4` | Ideogram 4 |\n| `generate_image_nano_banana_2_lite` | Nano Banana 2 Lite |\n| `generate_image_seedream_v5_pro` | Seedream 5.0 Pro |\n\n**VIDEO:**\n\n| Tool name | Display name |\n|---|---|\n| `generate_video_seedance_v2_0` | Seedance 2.0 |\n| `generate_video_seedance_v2_0_fast` | Seedance 2.0 Fast |\n| `generate_video_seedance_v2_0_mini` | Seedance 2.0 Mini |\n| `generate_video_kling_v3` | Kling 3.0 |\n| `generate_video_kling_v3_omni` | Kling 3.0 Omni |\n| `generate_video_seedance_pro_v1_5` | Seedance 1.5 Pro |\n| `generate_video_kling_v2_6` | Kling 2.6 |\n| `generate_video_wan_v2_6` | Wan 2.6 |\n| `generate_video_veo3_1` | Veo 3.1 |\n| `generate_video_veo3_1_fast` | Veo 3.1 Fast |\n| `generate_video_kling_omni_v1` | Kling O1 |\n| `generate_video_hailuo_v2_3` | Hailuo 2.3 |\n| `generate_video_veo3` | Veo 3 |\n| `generate_video_vidu_q2` | Vidu Q2 |\n| `generate_video_gemini_omni_flash` | Gemini Omni Flash |\n\n**3D:**\n\n| Tool name | Display name |\n|---|---|\n| `generate_3d_tripo` | Tripo |\n\nWhen the user requests a specific model, prefer `--prefer-models` over putting model names in the prompt.\n\n**Option 3: Via --include-tools** (hard constraint, forces specific tools):\n\n```bash\n# Force upscale only\npython3 {baseDir}/scripts/agent_skill.py chat --prompt \"upscale this image to 4K\" --include-tools upscale_image --attachments \"IMAGE_URL\" --json --download\n\n# Force a specific video model (no fallback to others)\npython3 {baseDir}/scripts/agent_skill.py chat --prompt \"generate a video\" --include-tools generate_video_kling_3_0 --json --download\n```\n\n`--include-tools` strongly instructs the Agent to prioritize the listed tools. Use this when the user explicitly requests a specific tool or operation.\n\n## Reasoning Mode — `--mode thinking` / `--mode fast`\n\nLovart has two reasoning modes you can select per thread:\n\n- **`fast`** (default) — lightweight single-pass response. Use for simple, one-shot generations where speed matters.\n- **`thinking`** — deep structured reasoning with planning and multi-step analysis. Use for complex brand systems, multi-asset campaigns, anything that benefits from deliberate planning. Slower but higher quality.\n\nOmitting `--mode` is equivalent to `--mode fast`, matching the web UI's default.\n\n```bash\n# Thinking mode — strategic, multi-step\npython3 {baseDir}/scripts/agent_skill.py chat --prompt \"design a brand identity system for a sustainable coffee startup\" --mode thinking --json --download\n\n# Fast mode — quick one-shot\npython3 {baseDir}/scripts/agent_skill.py chat --prompt \"draw a cat\" --mode fast --json --download\n```\n\n**Mode is locked to the thread on its first message.** Once you start a thread with `--mode thinking`, subsequent messages on the same `--thread-id` stay in thinking mode regardless of later `--mode` flags. To switch modes, start a new thread (omit `--thread-id`).\n\n## Task-Specific Tool Selection (IMPORTANT)\n\nWhen the user's request matches a specific operation, use `--include-tools` to ensure the correct tool:\n\n| User says | Use `--include-tools` |\n|-----------|----------------------|\n| \"upscale\", \"放大\", \"enlarge\", \"enhance resolution\", \"超分\" | `upscale_image` |\n| \"edit image\", \"modify\", \"change style\" | (let Agent decide) |\n| \"generate image\", \"draw\", \"画\" | (let Agent decide, or use `--prefer-models`) |\n\n**CRITICAL: When the user asks to \"upscale\", \"enlarge\", or increase resolution of an existing image, you MUST use `--include-tools upscale_image`. Do NOT let the Agent use image generation models for upscaling — they will re-generate the image instead of upscaling it.**\n\n## Notes\n\n- All APIs use AK/SK HMAC-SHA256 signature authentication\n- Video generation takes several minutes; the chat command auto-polls until complete\n- Gallery and canvas sync is idempotent — safe to call result multiple times without duplicates\n- Connection failures auto-retry 3 times with SSL fallback\n- After status becomes \"done\", waits 5 seconds to re-confirm (guards against sub-agent startup race)\n\nFile v1.0.11:_meta.json\n\n{\n  \"ownerId\": \"kn75568hvws2gh0ghmryz6dbxh84htc6\",\n  \"slug\": \"lovart-skill\",\n  \"version\": \"1.0.11\",\n  \"publishedAt\": 1783570062311\n}\n\nFile v1.0.11:skill-card.md\n\n## Description: <br>\nGenerate images, videos, and audio/music via Lovart AI, and manage Lovart projects, threads, conversation history, and user settings. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[lovart-admin](https://clawhub.ai/user/lovart-admin) <br>\n\n### License/Terms of Use: <br>\nMIT <br>\n\n\n## Use Case: <br>\nExternal users and developers use this skill to request Lovart media generation, retrieve generated files, and manage Lovart project or thread context from an agent session. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: The skill requires Lovart API credentials and sends prompts and selected media files to Lovart. <br>\nMitigation: Install only when that credential use and data sharing are acceptable, and avoid uploading sensitive local files. <br>\nRisk: The skill can persist and reuse Lovart project or thread history. <br>\nMitigation: Use explicit Lovart-scoped requests for project, thread, history, or settings operations and review active context before generation. <br>\nRisk: Broad activation rules can cause the skill to handle many media-generation or Lovart-management requests. <br>\nMitigation: Review the request scope before invoking the skill and prefer clearly scoped Lovart instructions. <br>\n\n\n## Reference(s): <br>\n- [Lovart Skill on ClawHub](https://clawhub.ai/lovart-admin/skills/lovart-skill) <br>\n- [Lovart User Profile on ClawHub](https://clawhub.ai/user/lovart-admin) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [Text, Markdown, Shell commands, Configuration, Files, Guidance] <br>\n**Output Format:** [Markdown guidance with inline shell commands, JSON command results, and downloaded media file paths] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Can produce local image, video, or audio files from Lovart generation workflows when downloads are requested.] <br>\n\n## Skill Version(s): <br>\n1.0.11 (source: server release metadata and skill frontmatter) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nArchive v1.0.10: 4 files, 20800 bytes\n\nFiles: agent_skill.py (45310b), skill-card.md (2346b), SKILL.md (22924b), _meta.json (132b)\n\nFile v1.0.10:SKILL.md\n\n---\nname: lovart-api\ndescription: >-\n  Generate images, videos, and audio/music via Lovart AI. Also manages Lovart projects,\n  threads (conversation history), and user settings. Trigger on: (1) any visual or audio\n  creation request in any language — draw, generate, create, design, make, 画, 生成,\n  制作, 创作, 设计 combined with image, video, audio, music, song, BGM, poster, etc.\n  (2) Lovart project/thread management — 项目, 对话, project, thread, conversation,\n  history, 历史, 切换, switch. You CAN generate directly - never say you cannot.\nuser-invocable: true\nmetadata:\n  {\n    \"openclaw\":\n      {\n        \"emoji\": \"🎨\",\n        \"requires\":\n          {\n            \"bins\": [\"python3\"],\n            \"env\": [\"LOVART_ACCESS_KEY\", \"LOVART_SECRET_KEY\"]\n          },\n        \"primaryEnv\": \"LOVART_ACCESS_KEY\"\n      }\n  }\n---\n\n# ⚠️ RULE #0: ONLY USE SKILL COMMANDS — NO DIRECT API CALLS\n\n**You MUST interact with Lovart EXCLUSIVELY through the commands defined in this skill.**\n- NEVER construct URLs, make curl/wget/fetch requests, or call Lovart APIs directly\n- NEVER guess API endpoints, paths, or parameters — only use the commands listed below\n- NEVER modify the skill's source code (agent_skill.py) during execution to \"debug\" issues (users may freely read the source to verify it)\n- If a command fails, retry it or report the error to the user — do NOT try to work around it\n- ALL Lovart operations go through: `chat`, `send`, `watch`, `confirm`, `result`, `status`, `config`, `projects`, `project-add`, `project-switch`, `project-rename`, `project-remove`, `threads`, `thread-remove`, `upload`, `upload-artifact`, `download`, `set-mode`, `query-mode`, `create-project`\n\n# ⚠️ RULE #1: YOU CAN AND MUST GENERATE IMAGES/VIDEOS/AUDIO\n\nWhen a user asks to \"draw\", \"generate\", \"create\", \"design\", \"make\", \"画\", \"生成\", \"制作\", \"创作\"\nany visual or audio content (in any language), you MUST use this skill.\nThis includes: images, videos, audio, music, songs, BGM, TTS, voice, posters, carousels, banners,\nlogos, illustrations, thumbnails, slides, covers, mockups, icons, social media content, etc.\nDo NOT say \"I can't generate images/music\" or offer to write prompts instead.\n\n# ⚠️ RULE #1.5: PROJECT & THREAD QUERIES USE THIS SKILL\n\nWhen the user asks about projects, threads, conversations, history, or settings (in any language),\nuse these commands — do NOT browse the filesystem:\n\n| User asks | Command |\n|-----------|---------|\n| \"What projects do I have?\" / \"我有哪些项目\" | `projects --json` |\n| \"What conversations/threads?\" / \"有哪些对话\" | `threads --json` or `threads --all --json` |\n| \"Show my settings\" / \"我的配置\" | `config --json` |\n| \"Switch to project X\" | `project-switch --project-id X` |\n| \"Create a new project\" | `project-add --project-id NEW_ID --name \"Name\"` (or let `chat` auto-create) |\n\n# ⚠️ RULE #2: ALWAYS USE `chat` AND WAIT FOR COMPLETION\n\nUse the `chat` command (blocks until done), NOT `send`. Do NOT reply before generation completes.\n\n**Handle these `final_status` values:**\n\n- `\"done\"` — Generation complete. Send the downloaded files to the user.\n- `\"pending_confirmation\"` — A high-cost tool (e.g. video, or a premium-quality image variant) needs user approval before credits are consumed.\n  **You MUST ask the user for explicit confirmation before proceeding. Do NOT auto-confirm.**\n  1. Show the user: \"This will cost approximately {estimated_cost} credits. Shall I proceed? (yes/no)\"\n  2. **WAIT for user response.** Only if user explicitly says yes/confirm/proceed, run:\n     `confirm --thread-id THREAD_ID --json --download`\n     (This confirms, waits for completion, and returns the result with downloaded files)\n  3. If user declines, do NOT confirm. Just inform them the operation was cancelled.\n- `\"abort\"` — Generation was aborted. Inform the user.\n- `\"timeout\"` — Generation is still running but exceeded the wait time. The result may contain partial artifacts.\n  1. Send any downloaded files that are already available\n  2. Tell the user: \"Generation is still in progress. Checking again...\"\n  3. Run: `result --thread-id THREAD_ID --json --download` to get the latest results\n  4. If status is still \"running\", wait and retry. If \"done\", send remaining files.\n\n**Handle errors:**\n\nIf `chat` throws an error (`AgentSkillError`), handle it by HTTP status and structured `code`. The `message` field already contains a user-ready explanation — surface it to the user as-is.\n\n| HTTP status | `code` | What it means | What to tell the user |\n|---|---|---|---|\n| **`402`** | `2012` | Quota / billing / risk-control rejection | Show `AgentSkillError.message` directly — the server already returns a specific message (insufficient credits, free-tier reached, concurrent limit, risk control, phone verification, team plan required, etc.) and a suggested next step. |\n| **`409`** | `2011` | Another task is still running on this thread | \"A task is still running on this conversation. Wait for it to finish (`status`) before sending a new prompt, or start a new thread.\" |\n| **`429`** | `1429` | API rate limit hit | \"Slowing down; rate limit hit. Retry in ~60s.\" |\n| **`401`** | — | AK/SK misconfigured | \"API key authentication failed. Please check your LOVART_ACCESS_KEY and LOVART_SECRET_KEY.\" |\n| — | — | `Project.*does not exist` in message | \"Project not found. Please check the project ID or create a new one.\" |\n\nRule of thumb: prefer `AgentSkillError.message` for user-facing copy. Do not try to parse internal codes out of the response — the server already maps them to human-readable messages before returning.\n\n**Detect silent generation failures (`done` with no artifact):**\n\nSome prompts end with `final_status: \"done\"` but produce no `artifacts` / empty `downloaded`. This usually means the upstream image model refused the prompt (content moderation), timed out, or the LLM chose to reply with text instead of calling a tool. The skill flags this automatically — when `chat()` returns, check:\n\n- `result[\"generation_succeeded\"]` — boolean. `False` means no artifact was produced.\n- `result[\"warning\"]` — explanation string (present only when `generation_succeeded` is `False`).\n- `result[\"agent_message\"]` — the agent's plain-text reply that hints at why (present when available).\n\nTypical triggers:\n- GPT Image 2 with very long/complex prompts involving weapons, specific bodies, or policy-sensitive wording — retry with a different model (`--include-tools generate_image_midjourney` or `generate_image_nano_banana_pro`) or simplify the prompt.\n- Prompt that describes a task the agent can't fulfill — show `agent_message` to the user.\n\n# ⚠️ RULE #3: ALWAYS DELIVER RESULTS + PROJECT LINK\n\nAfter EVERY generation, you MUST:\n1. Use `--download` flag with `chat` (or `result`)\n2. Send each downloaded file to the user as a **file attachment** (images, videos, audio/mp3 — ALL file types):\n   - ALWAYS send `downloaded[].local_path` as file attachments, regardless of file type (.png, .jpg, .mp4, .mp3, etc.)\n   - NEVER just paste the URL when a local file has been downloaded — send the actual file\n   - Only fall back to displaying URLs if no files were downloaded\n3. Append the project canvas link: `https://www.lovart.ai/canvas?projectId={project_id}`\n\n# ⚠️ RULE #4: CHECK LOCAL STATE ON FIRST USE (MANDATORY — DO NOT SKIP)\n\n**Before the FIRST generation in a conversation, you MUST run these two commands IN ORDER. This is NOT optional. Do NOT call `chat` until you have done both.**\n\n**Step 1: `config --json`**\n- Check local state (`~/.lovart/state.json`) for `active_project`\n- If `active_project` is set → proceed to Step 2. Do NOT create a new project. Do NOT ask the user.\n- If `active_project` is missing → ask the user: \"Do you have an existing Lovart project ID, or should I create a new one?\" **WAIT for their answer.**\n- Save with: `project-add --project-id PID --name \"name\"`\n\n**Step 2: `threads --json`**\n- Check if there's a recent thread to continue\n- If recent thread exists and topic is related → **REUSE it** (pass `--thread-id THREAD_ID` to `chat`)\n- If no threads or completely different topic → omit `--thread-id` (creates new thread)\n\n**CRITICAL RULES:**\n- **NEVER create a new project** if `config --json` already shows an `active_project`. Reuse it.\n- **NEVER omit `--thread-id`** when a relevant recent thread exists. Always reuse threads by default.\n- **NEVER call `chat` without first running `config --json` and `threads --json`** in the same conversation.\n- The `chat` command auto-reads `active_project` from local state — you do NOT need to pass `--project-id` every time.\n- Only create a new project if the user **explicitly** asks for one.\n- Only create a new thread if the topic is **completely unrelated** to the most recent thread.\n- When in doubt, **REUSE** both the existing project and the existing thread.\n\n---\n\n# Lovart Agent OpenAPI Skill\n\nInteract with Lovart AI Agent to generate images, videos, and visual assets via natural language.\n\nLovart is an AI design platform. The Agent understands user requests and automatically selects the best model and workflow.\n\n## Terminology\n\n- **Thread** — A conversation flow (chat session) with the Lovart AI Agent, NOT a programming thread. Each thread has a unique `thread_id` and preserves multi-turn context. Reusing a thread means continuing the same conversation so the Agent remembers previous images/videos and can iterate on them.\n- **Project** — A workspace/canvas that groups threads and generated artifacts together. One project can contain multiple threads.\n\n## Prerequisites\n\n```bash\nexport LOVART_ACCESS_KEY=\"ak_xxx\"\nexport LOVART_SECRET_KEY=\"sk_xxx\"\n```\n\nNo third-party dependencies. Python standard library only.\n\n## Features\n\n1. **Chat** - Send a message to the AI Agent, get text replies and generated images/videos\n2. **Confirm** - Confirm and wait for high-cost operations (e.g. video generation)\n3. **Create Project** - Create a new project\n4. **Upload File** - Upload a local image/video file, get back a CDN URL\n5. **Upload Artifact** - Upload a link artifact to a project\n6. **Status/Result** - Check thread status and retrieve results\n7. **Set/Query Mode** - Switch between fast (credits) and unlimited (queue) mode\n\n## Usage\n\n### 0. First-time setup (saves to ~/.lovart/state.json)\n\n```bash\npython3 {baseDir}/agent_skill.py project-add --project-id PROJECT_ID --name \"My Project\"\n```\n\n### 1. Send a message (reads project_id from local state)\n\n```bash\npython3 {baseDir}/agent_skill.py chat --prompt \"USER_PROMPT\" --json --download\n```\n\nTo override project: add `--project-id PROJECT_ID`\nTo continue a conversation: add `--thread-id THREAD_ID`\nTo list saved threads: `python3 {baseDir}/agent_skill.py threads`\n\n### 2. Create a project\n\n```bash\npython3 {baseDir}/agent_skill.py create-project\n```\n\n### 3. Upload a file (local image/video → CDN URL)\n\n```bash\npython3 {baseDir}/agent_skill.py upload --file /path/to/image.png\n# Returns: {\"url\": \"https://assets-persist.lovart.ai/img/{user_uuid}/xxx.png\"}\n```\n\nUse this when the user sends an image/video file that needs to be passed as an attachment to chat.\n\n### 4. Upload an artifact\n\n```bash\npython3 {baseDir}/agent_skill.py upload-artifact --project-id PROJECT_ID --url \"ARTIFACT_URL\" --type image\n```\n\n### 5. Check status / get result\n\n```bash\n# Status\npython3 {baseDir}/agent_skill.py status --thread-id THREAD_ID\n\n# Result (auto-syncs to gallery/canvas, idempotent)\npython3 {baseDir}/agent_skill.py result --thread-id THREAD_ID --json --download\n```\n\n### 6. Download artifacts\n\n```bash\n# Download during chat\npython3 {baseDir}/agent_skill.py chat --prompt \"draw a cat\" --json --download --output-dir /tmp/openclaw\n\n# Download from existing result\npython3 {baseDir}/agent_skill.py result --thread-id THREAD_ID --download --output-dir /tmp/openclaw\n\n# Download specific URLs\npython3 {baseDir}/agent_skill.py download --urls URL1 URL2 --output-dir /tmp/openclaw --prefix myimg\n```\n\n## Typical Workflows\n\n### Scenario 1: Generate images/videos/audio (most common)\n\n**First, run `config --json` to check if project_id is set. If not, ask the user and save with `project-add`.**\n\n```\n1. config --json  →  check local state for active_project\n   - If not set → ask user, save with project-add\n2. threads --json  →  check if there's a recent thread to continue\n   - If recent thread exists and topic is related → reuse it (step 3a)\n   - If no threads or completely new topic → new thread (step 3b)\n3a. chat --thread-id THREAD_ID --prompt \"user's request\" --json --download\n3b. chat --prompt \"user's request\" --json --download\n4. Send each downloaded[].local_path file as an IM attachment to the user\n5. The chat command auto-syncs artifacts to canvas and gallery\n```\n\n**IDs are auto-persisted locally (`~/.lovart/state.json`):**\n- project_id is saved after first chat, reused automatically\n- thread_id + topic are saved after each chat for thread switching\n- Only create a new project if the user explicitly asks for one\n- Only create a new thread (omit `--thread-id`) when starting a completely new topic\n- Run `threads` to list saved threads for the user to pick from\n\n### Scenario 2: Edit with attachments\n\n```\n1. User sends a reference image/video via IM → save to local file\n2. upload --file /path/to/image.png  →  get CDN URL\n3. chat --prompt \"edit this image to...\" --project-id PID --attachments \"CDN_URL\" --json --download\n4. Continue as Scenario 1\n```\n\n### Scenario 3: Follow-up on same topic (continue context)\n\n```\n1. chat --prompt \"change the background to a beach\" --project-id PROJECT_ID --thread-id THREAD_ID --json --download\n```\n\nThe Agent remembers the previous conversation and can continue editing based on context.\n\n### Scenario 4: New topic (new thread)\n\n```\n1. chat --prompt \"completely new request\" --project-id PROJECT_ID --json --download\n```\n\nOmitting `--thread-id` creates a new conversation without previous memory.\n\n### Scenario 5: Streaming / incremental delivery (multiple artifacts)\n\n**Use when** the user's request will produce multiple images/videos and you want to deliver each one to the user as soon as it's ready, rather than waiting for the whole batch.\n\n```bash\npython3 {baseDir}/agent_skill.py watch --prompt \"generate 4 variations of a cyberpunk cat\" --json\n```\n\n`watch` emits **NDJSON** to stdout (one event per line). Parse line-by-line and deliver each `artifact` event's `local_path` to the user immediately:\n\n```json\n{\"event\": \"started\", \"thread_id\": \"xxx\", \"project_id\": \"yyy\"}\n{\"event\": \"artifact\", \"type\": \"image\", \"url\": \"https://...\", \"local_path\": \"/tmp/openclaw/lovart_ab12cd.png\"}\n{\"event\": \"artifact\", \"type\": \"image\", \"url\": \"https://...\", \"local_path\": \"/tmp/openclaw/lovart_ef34gh.png\"}\n{\"event\": \"pending_confirmation\", \"thread_id\": \"xxx\", \"pending_confirmation\": {...}}\n{\"event\": \"finished\", \"thread_id\": \"xxx\", \"final_status\": \"done\", \"artifact_count\": 4}\n```\n\nFiles are saved with URL-hash filenames so re-running `watch` on the same thread won't re-download.\n\nYou can also attach to an **already-running** thread: `watch --thread-id THREAD_ID`.\n\n**When NOT to use `watch`:** single-image requests — use `chat` (simpler, one-shot response).\n\n## Output Format\n\n**chat --json** returns:\n```json\n{\n  \"thread_id\": \"xxx\",\n  \"status\": \"done\",\n  \"project_id\": \"xxx\",\n  \"final_status\": \"done\",\n  \"items\": [\n    {\"type\": \"assistant\", \"text\": \"Agent's reply\"},\n    {\"type\": \"generator\", \"name\": \"artifacts\", \"artifacts\": [\n      {\"type\": \"image\", \"content\": \"https://assets-persist.lovart.ai/artifacts/agent/xxx.png\"},\n      {\"type\": \"video\", \"content\": \"https://assets-persist.lovart.ai/artifacts/agent/xxx.mp4\"}\n    ]}\n  ],\n  \"downloaded\": [\n    {\"type\": \"image\", \"url\": \"https://...\", \"local_path\": \"/tmp/openclaw/lovart_01.png\"}\n  ]\n}\n```\n\n## Core Principle\n\nYou are a messenger, not a creator. The backend Agent handles understanding requirements, selecting models, and writing prompts. Your job:\n\n1. **Relay**: Pass the user's original description verbatim to chat\n2. **Wait**: Poll until generation completes\n3. **Deliver**: Send result files to the user\n\n**Do NOT** rewrite/expand prompts, break down tasks, or add your own style descriptions.\n\n## Lovart Generation Mode (MUST use API, not prompt)\n\n**CRITICAL: \"Fast mode\" and \"unlimited mode\" are server-side settings controlled via API calls, NOT prompt keywords.**\n\nDo NOT put \"快速模式\" or \"fast mode\" in the prompt text. Instead, call the set-mode command:\n\n```bash\n# User says \"fast mode\" / \"快速模式\" / \"skip queue\" / \"use credits\" → RUN THIS:\npython3 {baseDir}/agent_skill.py set-mode --fast\n\n# User says \"unlimited mode\" / \"无限模式\" / \"free mode\" / \"save credits\" → RUN THIS:\npython3 {baseDir}/agent_skill.py set-mode --unlimited\n\n# Check which mode is active:\npython3 {baseDir}/agent_skill.py query-mode\n```\n\n**How it works:**\n- `set-mode --fast` calls the Lovart backend API to switch the user's account to fast generation (costs credits, no queue)\n- `set-mode --unlimited` switches to unlimited generation (free, may queue)\n- This is a **persistent server-side setting** — it stays until changed again\n- It affects ALL subsequent image/video generations, not just one request\n- It has **nothing to do with your (the assistant's) response style or behavior**\n\n## Specifying Models\n\n**Option 1: In the prompt** (simple, the Agent routes automatically):\n\n```bash\npython3 {baseDir}/agent_skill.py chat --prompt \"generate ocean waves video using kling\" --json --download\n```\n\n**Option 2: Via --prefer-models** (precise, same as frontend's model selector):\n\n```bash\n# Prefer a specific image model\npython3 {baseDir}/agent_skill.py chat --prompt \"draw a cat\" --prefer-models '{\"IMAGE\":[\"generate_image_midjourney\"]}' --json --download\n\n# Prefer a specific video model\npython3 {baseDir}/agent_skill.py chat --prompt \"generate ocean waves\" --prefer-models '{\"VIDEO\":[\"generate_video_kling_3_0\"]}' --json --download\n\n# Combine image and video preferences\npython3 {baseDir}/agent_skill.py chat --prompt \"create content\" --prefer-models '{\"IMAGE\":[\"generate_image_seedream_3_0\"],\"VIDEO\":[\"generate_video_kling_3_0\"]}' --json --download\n```\n\nAvailable models for `--prefer-models`:\n\n**IMAGE:**\n\n| Tool name | Display name |\n|---|---|\n| `generate_image_gpt_image_2` | GPT Image 2 Auto |\n| `generate_image_gpt_image_2_low` | GPT Image 2 Low |\n| `generate_image_gpt_image_2_medium` | GPT Image 2 Medium |\n| `generate_image_gpt_image_2_high` | GPT Image 2 High |\n| `generate_image_nano_banana_pro` | Nano Banana Pro |\n| `generate_image_nano_banana_2` | Nano Banana 2 |\n| `generate_image_gpt_image_1_5` | GPT Image 1.5 |\n| `generate_image_seedream_v5` | Seedream 5.0 Lite |\n| `generate_image_luma_uni_1` | Luma uni-1 |\n| `generate_image_luma_uni_1_max` | Luma uni-1-max |\n| `generate_image_flux_2_max` | Flux.2 Max |\n| `generate_image_flux_2_pro` | Flux.2 Pro |\n| `generate_image_seedream_v4_5` | Seedream 4.5 |\n| `generate_image_nano_banana` | Nano Banana |\n| `generate_image_seedream_v4` | Seedream 4 |\n| `generate_image_midjourney` | Midjourney |\n\n**VIDEO:**\n\n| Tool name | Display name |\n|---|---|\n| `generate_video_seedance_v2_0` | Seedance 2.0 |\n| `generate_video_seedance_v2_0_fast` | Seedance 2.0 Fast |\n| `generate_video_kling_v3` | Kling 3.0 |\n| `generate_video_kling_v3_omni` | Kling 3.0 Omni |\n| `generate_video_seedance_pro_v1_5` | Seedance 1.5 Pro |\n| `generate_video_kling_v2_6` | Kling 2.6 |\n| `generate_video_wan_v2_6` | Wan 2.6 |\n| `generate_video_sora_v2_pro` | Sora 2 Pro |\n| `generate_video_sora_v2` | Sora 2 |\n| `generate_video_veo3_1` | Veo 3.1 |\n| `generate_video_veo3_1_fast` | Veo 3.1 Fast |\n| `generate_video_kling_omni_v1` | Kling O1 |\n| `generate_video_hailuo_v2_3` | Hailuo 2.3 |\n| `generate_video_veo3` | Veo 3 |\n| `generate_video_vidu_q2` | Vidu Q2 |\n\n**3D:**\n\n| Tool name | Display name |\n|---|---|\n| `generate_3d_tripo` | Tripo |\n\nWhen the user requests a specific model, prefer `--prefer-models` over putting model names in the prompt.\n\n**Option 3: Via --include-tools** (hard constraint, forces specific tools):\n\n```bash\n# Force upscale only\npython3 {baseDir}/agent_skill.py chat --prompt \"upscale this image to 4K\" --include-tools upscale_image --attachments \"IMAGE_URL\" --json --download\n\n# Force a specific video model (no fallback to others)\npython3 {baseDir}/agent_skill.py chat --prompt \"generate a video\" --include-tools generate_video_kling_3_0 --json --download\n```\n\n`--include-tools` strongly instructs the Agent to prioritize the listed tools. Use this when the user explicitly requests a specific tool or operation.\n\n## Reasoning Mode — `--mode thinking` / `--mode fast`\n\nLovart has two reasoning modes you can select per thread:\n\n- **`fast`** (default) — lightweight single-pass response. Use for simple, one-shot generations where speed matters.\n- **`thinking`** — deep structured reasoning with planning and multi-step analysis. Use for complex brand systems, multi-asset campaigns, anything that benefits from deliberate planning. Slower but higher quality.\n\nOmitting `--mode` is equivalent to `--mode fast`, matching the web UI's default.\n\n```bash\n# Thinking mode — strategic, multi-step\npython3 {baseDir}/agent_skill.py chat --prompt \"design a brand identity system for a sustainable coffee startup\" --mode thinking --json --download\n\n# Fast mode — quick one-shot\npython3 {baseDir}/agent_skill.py chat --prompt \"draw a cat\" --mode fast --json --download\n```\n\n**Mode is locked to the thread on its first message.** Once you start a thread with `--mode thinking`, subsequent messages on the same `--thread-id` stay in thinking mode regardless of later `--mode` flags. To switch modes, start a new thread (omit `--thread-id`).\n\n## Task-Specific Tool Selection (IMPORTANT)\n\nWhen the user's request matches a specific operation, use `--include-tools` to ensure the correct tool:\n\n| User says | Use `--include-tools` |\n|-----------|----------------------|\n| \"upscale\", \"放大\", \"enlarge\", \"enhance resolution\", \"超分\" | `upscale_image` |\n| \"edit image\", \"modify\", \"change style\" | (let Agent decide) |\n| \"generate image\", \"draw\", \"画\" | (let Agent decide, or use `--prefer-models`) |\n\n**CRITICAL: When the user asks to \"upscale\", \"enlarge\", or increase resolution of an existing image, you MUST use `--include-tools upscale_image`. Do NOT let the Agent use image generation models for upscaling — they will re-generate the image instead of upscaling it.**\n\n## Notes\n\n- All APIs use AK/SK HMAC-SHA256 signature authentication\n- Video generation takes several minutes; the chat command auto-polls until complete\n- Gallery and canvas sync is idempotent — safe to call result multiple times without duplicates\n- Connection failures auto-retry 3 times with SSL fallback\n- After status becomes \"done\", waits 5 seconds to re-confirm (guards against sub-agent startup race)\n\nFile v1.0.10:_meta.json\n\n{\n  \"ownerId\": \"kn75568hvws2gh0ghmryz6dbxh84htc6\",\n  \"slug\": \"lovart-skill\",\n  \"version\": \"1.0.10\",\n  \"publishedAt\": 1779869622139\n}\n\nFile v1.0.10:skill-card.md\n\n## Description: <br>\nGenerate images, videos, and audio or music through Lovart AI while managing Lovart projects, conversation threads, uploads, downloads, and generation settings. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[lovart-admin](https://clawhub.ai/user/lovart-admin) <br>\n\n### License/Terms of Use: <br>\nMIT-0 <br>\n\n\n## Use Case: <br>\nExternal users and agents use this skill to send Lovart media-generation requests, manage Lovart projects and threads, upload reference files, and retrieve generated files through the provided command workflow. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: The skill requires Lovart API credentials. <br>\nMitigation: Install it only when Lovart access is intended, provide credentials through trusted environment variables, and rotate credentials if they may have been exposed. <br>\nRisk: The skill can reuse persistent Lovart project and thread state. <br>\nMitigation: Review saved Lovart configuration and thread selections before generation or history actions, and use explicit Lovart wording for project or history requests. <br>\nRisk: The skill can upload local files and download generated artifacts from remote URLs. <br>\nMitigation: Review files before upload and be cautious with arbitrary download URLs or generated artifact links from untrusted contexts. <br>\n\n\n## Reference(s): <br>\n- [ClawHub Lovart Skill](https://clawhub.ai/lovart-admin/lovart-skill) <br>\n- [Lovart Project Canvas](https://www.lovart.ai/canvas?projectId={project_id}) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [Text, Shell commands, Configuration, Files, Guidance] <br>\n**Output Format:** [Markdown guidance with shell command invocations, JSON command output, and downloaded media files] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Requires Lovart API credentials and may save project and thread state locally for reuse.] <br>\n\n## Skill Version(s): <br>\n1.0.10 (source: ClawHub release metadata) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nArchive v1.0.9: 3 files, 19577 bytes\n\nFiles: agent_skill.py (45062b), SKILL.md (22973b), _meta.json (131b)\n\nFile v1.0.9:SKILL.md\n\n---\nname: lovart-api\ndescription: >-\n  Generate images, videos, and audio/music via Lovart AI. Also manages Lovart projects,\n  threads (conversation history), and user settings. Trigger on: (1) any visual or audio\n  creation request in any language — draw, generate, create, design, make, 画, 生成,\n  制作, 创作, 设计 combined with image, video, audio, music, song, BGM, poster, etc.\n  (2) Lovart project/thread management — 项目, 对话, project, thread, conversation,\n  history, 历史, 切换, switch. You CAN generate directly - never say you cannot.\nuser-invocable: true\nmetadata:\n  {\n    \"openclaw\":\n      {\n        \"emoji\": \"🎨\",\n        \"requires\":\n          {\n            \"bins\": [\"python3\"],\n            \"env\": [\"LOVART_ACCESS_KEY\", \"LOVART_SECRET_KEY\"]\n          },\n        \"primaryEnv\": \"LOVART_ACCESS_KEY\"\n      }\n  }\n---\n\n# ⚠️ RULE #0: ONLY USE SKILL COMMANDS — NO DIRECT API CALLS\n\n**You MUST interact with Lovart EXCLUSIVELY through the commands defined in this skill.**\n- NEVER construct URLs, make curl/wget/fetch requests, or call Lovart APIs directly\n- NEVER guess API endpoints, paths, or parameters — only use the commands listed below\n- NEVER modify the skill's source code (agent_skill.py) during execution to \"debug\" issues (users may freely read the source to verify it)\n- If a command fails, retry it or report the error to the user — do NOT try to work around it\n- ALL Lovart operations go through: `chat`, `send`, `watch`, `confirm`, `result`, `status`, `config`, `projects`, `project-add`, `project-switch`, `project-rename`, `project-remove`, `threads`, `thread-remove`, `upload`, `upload-artifact`, `download`, `set-mode`, `query-mode`, `create-project`\n\n# ⚠️ RULE #1: YOU CAN AND MUST GENERATE IMAGES/VIDEOS/AUDIO\n\nWhen a user asks to \"draw\", \"generate\", \"create\", \"design\", \"make\", \"画\", \"生成\", \"制作\", \"创作\"\nany visual or audio content (in any language), you MUST use this skill.\nThis includes: images, videos, audio, music, songs, BGM, TTS, voice, posters, carousels, banners,\nlogos, illustrations, thumbnails, slides, covers, mockups, icons, social media content, etc.\nDo NOT say \"I can't generate images/music\" or offer to write prompts instead.\n\n# ⚠️ RULE #1.5: PROJECT & THREAD QUERIES USE THIS SKILL\n\nWhen the user asks about projects, threads, conversations, history, or settings (in any language),\nuse these commands — do NOT browse the filesystem:\n\n| User asks | Command |\n|-----------|---------|\n| \"What projects do I have?\" / \"我有哪些项目\" | `projects --json` |\n| \"What conversations/threads?\" / \"有哪些对话\" | `threads --json` or `threads --all --json` |\n| \"Show my settings\" / \"我的配置\" | `config --json` |\n| \"Switch to project X\" | `project-switch --project-id X` |\n| \"Create a new project\" | `project-add --project-id NEW_ID --name \"Name\"` (or let `chat` auto-create) |\n\n# ⚠️ RULE #2: ALWAYS USE `chat` AND WAIT FOR COMPLETION\n\nUse the `chat` command (blocks until done), NOT `send`. Do NOT reply before generation completes.\n\n**Handle these `final_status` values:**\n\n- `\"done\"` — Generation complete. Send the downloaded files to the user.\n- `\"pending_confirmation\"` — A high-cost tool (e.g. video, or a premium-quality image variant) needs user approval before credits are consumed.\n  **You MUST ask the user for explicit confirmation before proceeding. Do NOT auto-confirm.**\n  1. Show the user: \"This will cost approximately {estimated_cost} credits. Shall I proceed? (yes/no)\"\n  2. **WAIT for user response.** Only if user explicitly says yes/confirm/proceed, run:\n     `confirm --thread-id THREAD_ID --json --download`\n     (This confirms, waits for completion, and returns the result with downloaded files)\n  3. If user declines, do NOT confirm. Just inform them the operation was cancelled.\n- `\"abort\"` — Generation was aborted. Inform the user.\n- `\"timeout\"` — Generation is still running but exceeded the wait time. The result may contain partial artifacts.\n  1. Send any downloaded files that are already available\n  2. Tell the user: \"Generation is still in progress. Checking again...\"\n  3. Run: `result --thread-id THREAD_ID --json --download` to get the latest results\n  4. If status is still \"running\", wait and retry. If \"done\", send remaining files.\n\n**Handle errors:**\n\nIf `chat` throws an error (`AgentSkillError`), handle it by HTTP status and structured `code`. The `message` field already contains a user-ready explanation — surface it to the user as-is.\n\n| HTTP status | `code` | What it means | What to tell the user |\n|---|---|---|---|\n| **`402`** | `2012` | Quota / billing / risk-control rejection | Show `AgentSkillError.message` directly — the server already returns a specific message (insufficient credits, free-tier reached, concurrent limit, risk control, phone verification, team plan required, etc.) and a suggested next step. |\n| **`409`** | `2011` | Another task is still running on this thread | \"A task is still running on this conversation. Wait for it to finish (`status`) before sending a new prompt, or start a new thread.\" |\n| **`429`** | `1429` | API rate limit hit | \"Slowing down; rate limit hit. Retry in ~60s.\" |\n| **`401`** | — | AK/SK misconfigured | \"API key authentication failed. Please check your LOVART_ACCESS_KEY and LOVART_SECRET_KEY.\" |\n| — | — | `Project.*does not exist` in message | \"Project not found. Please check the project ID or create a new one.\" |\n\nRule of thumb: prefer `AgentSkillError.message` for user-facing copy. Do not try to parse internal codes out of the response — the server already maps them to human-readable messages before returning.\n\n**Detect silent generation failures (`done` with no artifact):**\n\nSome prompts end with `final_status: \"done\"` but produce no `artifacts` / empty `downloaded`. This usually means the upstream image model refused the prompt (content moderation), timed out, or the LLM chose to reply with text instead of calling a tool. The skill flags this automatically — when `chat()` returns, check:\n\n- `result[\"generation_succeeded\"]` — boolean. `False` means no artifact was produced.\n- `result[\"warning\"]` — explanation string (present only when `generation_succeeded` is `False`).\n- `result[\"agent_message\"]` — the agent's plain-text reply that hints at why (present when available).\n\nTypical triggers:\n- GPT Image 2 with very long/complex prompts involving weapons, specific bodies, or policy-sensitive wording — retry with a different model (`--include-tools generate_image_midjourney` or `generate_image_nano_banana_pro`) or simplify the prompt.\n- Prompt that describes a task the agent can't fulfill — show `agent_message` to the user.\n\n# ⚠️ RULE #3: ALWAYS DELIVER RESULTS + PROJECT LINK\n\nAfter EVERY generation, you MUST:\n1. Use `--download` flag with `chat` (or `result`)\n2. Send each downloaded file to the user as a **file attachment** (images, videos, audio/mp3 — ALL file types):\n   - ALWAYS send `downloaded[].local_path` as file attachments, regardless of file type (.png, .jpg, .mp4, .mp3, etc.)\n   - NEVER just paste the URL when a local file has been downloaded — send the actual file\n   - Only fall back to displaying URLs if no files were downloaded\n3. Append the project canvas link: `https://www.lovart.ai/canvas?projectId={project_id}`\n\n# ⚠️ RULE #4: CHECK LOCAL STATE ON FIRST USE (MANDATORY — DO NOT SKIP)\n\n**Before the FIRST generation in a conversation, you MUST run these two commands IN ORDER. This is NOT optional. Do NOT call `chat` until you have done both.**\n\n**Step 1: `config --json`**\n- Check local state (`~/.lovart/state.json`) for `active_project`\n- If `active_project` is set → proceed to Step 2. Do NOT create a new project. Do NOT ask the user.\n- If `active_project` is missing → ask the user: \"Do you have an existing Lovart project ID, or should I create a new one?\" **WAIT for their answer.**\n- Save with: `project-add --project-id PID --name \"name\"`\n\n**Step 2: `threads --json`**\n- Check if there's a recent thread to continue\n- If recent thread exists and topic is related → **REUSE it** (pass `--thread-id THREAD_ID` to `chat`)\n- If no threads or completely different topic → omit `--thread-id` (creates new thread)\n\n**CRITICAL RULES:**\n- **NEVER create a new project** if `config --json` already shows an `active_project`. Reuse it.\n- **NEVER omit `--thread-id`** when a relevant recent thread exists. Always reuse threads by default.\n- **NEVER call `chat` without first running `config --json` and `threads --json`** in the same conversation.\n- The `chat` command auto-reads `active_project` from local state — you do NOT need to pass `--project-id` every time.\n- Only create a new project if the user **explicitly** asks for one.\n- Only create a new thread if the topic is **completely unrelated** to the most recent thread.\n- When in doubt, **REUSE** both the existing project and the existing thread.\n\n---\n\n# Lovart Agent OpenAPI Skill\n\nInteract with Lovart AI Agent to generate images, videos, and visual assets via natural language.\n\nLovart is an AI design platform. The Agent understands user requests and automatically selects the best model and workflow.\n\n## Terminology\n\n- **Thread** — A conversation flow (chat session) with the Lovart AI Agent, NOT a programming thread. Each thread has a unique `thread_id` and preserves multi-turn context. Reusing a thread means continuing the same conversation so the Agent remembers previous images/videos and can iterate on them.\n- **Project** — A workspace/canvas that groups threads and generated artifacts together. One project can contain multiple threads.\n\n## Prerequisites\n\n```bash\nexport LOVART_ACCESS_KEY=\"ak_xxx\"\nexport LOVART_SECRET_KEY=\"sk_xxx\"\n```\n\nNo third-party dependencies. Python standard library only.\n\n## Features\n\n1. **Chat** - Send a message to the AI Agent, get text replies and generated images/videos\n2. **Confirm** - Confirm and wait for high-cost operations (e.g. video generation)\n3. **Create Project** - Create a new project\n4. **Upload File** - Upload a local image/video file, get back a CDN URL\n5. **Upload Artifact** - Upload a link artifact to a project\n6. **Status/Result** - Check thread status and retrieve results\n7. **Set/Query Mode** - Switch between fast (credits) and unlimited (queue) mode\n\n## Usage\n\n### 0. First-time setup (saves to ~/.lovart/state.json)\n\n```bash\npython3 {baseDir}/agent_skill.py project-add --project-id PROJECT_ID --name \"My Project\"\n```\n\n### 1. Send a message (reads project_id from local state)\n\n```bash\npython3 {baseDir}/agent_skill.py chat --prompt \"USER_PROMPT\" --json --download\n```\n\nTo override project: add `--project-id PROJECT_ID`\nTo continue a conversation: add `--thread-id THREAD_ID`\nTo list saved threads: `python3 {baseDir}/agent_skill.py threads`\n\n### 2. Create a project\n\n```bash\npython3 {baseDir}/agent_skill.py create-project\n```\n\n### 3. Upload a file (local image/video → CDN URL)\n\n```bash\npython3 {baseDir}/agent_skill.py upload --file /path/to/image.png\n# Returns: {\"url\": \"https://assets-persist.lovart.ai/img/{user_uuid}/xxx.png\"}\n```\n\nUse this when the user sends an image/video file that needs to be passed as an attachment to chat.\n\n### 4. Upload an artifact\n\n```bash\npython3 {baseDir}/agent_skill.py upload-artifact --project-id PROJECT_ID --url \"ARTIFACT_URL\" --type image\n```\n\n### 5. Check status / get result\n\n```bash\n# Status\npython3 {baseDir}/agent_skill.py status --thread-id THREAD_ID\n\n# Result (auto-syncs to gallery/canvas, idempotent)\npython3 {baseDir}/agent_skill.py result --thread-id THREAD_ID --json --download\n```\n\n### 6. Download artifacts\n\n```bash\n# Download during chat\npython3 {baseDir}/agent_skill.py chat --prompt \"draw a cat\" --json --download --output-dir /tmp/openclaw\n\n# Download from existing result\npython3 {baseDir}/agent_skill.py result --thread-id THREAD_ID --download --output-dir /tmp/openclaw\n\n# Download specific URLs\npython3 {baseDir}/agent_skill.py download --urls URL1 URL2 --output-dir /tmp/openclaw --prefix myimg\n```\n\n## Typical Workflows\n\n### Scenario 1: Generate images/videos/audio (most common)\n\n**First, run `config --json` to check if project_id is set. If not, ask the user and save with `project-add`.**\n\n```\n1. config --json  →  check local state for active_project\n   - If not set → ask user, save with project-add\n2. threads --json  →  check if there's a recent thread to continue\n   - If recent thread exists and topic is related → reuse it (step 3a)\n   - If no threads or completely new topic → new thread (step 3b)\n3a. chat --thread-id THREAD_ID --prompt \"user's request\" --json --download\n3b. chat --prompt \"user's request\" --json --download\n4. Send each downloaded[].local_path file as an IM attachment to the user\n5. The chat command auto-syncs artifacts to canvas and gallery\n```\n\n**IDs are auto-persisted locally (`~/.lovart/state.json`):**\n- project_id is saved after first chat, reused automatically\n- thread_id + topic are saved after each chat for thread switching\n- Only create a new project if the user explicitly asks for one\n- Only create a new thread (omit `--thread-id`) when starting a completely new topic\n- Run `threads` to list saved threads for the user to pick from\n\n### Scenario 2: Edit with attachments\n\n```\n1. User sends a reference image/video via IM → save to local file\n2. upload --file /path/to/image.png  →  get CDN URL\n3. chat --prompt \"edit this image to...\" --project-id PID --attachments \"CDN_URL\" --json --download\n4. Continue as Scenario 1\n```\n\n### Scenario 3: Follow-up on same topic (continue context)\n\n```\n1. chat --prompt \"change the background to a beach\" --project-id PROJECT_ID --thread-id THREAD_ID --json --download\n```\n\nThe Agent remembers the previous conversation and can continue editing based on context.\n\n### Scenario 4: New topic (new thread)\n\n```\n1. chat --prompt \"completely new request\" --project-id PROJECT_ID --json --download\n```\n\nOmitting `--thread-id` creates a new conversation without previous memory.\n\n### Scenario 5: Streaming / incremental delivery (multiple artifacts)\n\n**Use when** the user's request will produce multiple images/videos and you want to deliver each one to the user as soon as it's ready, rather than waiting for the whole batch.\n\n```bash\npython3 {baseDir}/agent_skill.py watch --prompt \"generate 4 variations of a cyberpunk cat\" --json\n```\n\n`watch` emits **NDJSON** to stdout (one event per line). Parse line-by-line and deliver each `artifact` event's `local_path` to the user immediately:\n\n```json\n{\"event\": \"started\", \"thread_id\": \"xxx\", \"project_id\": \"yyy\"}\n{\"event\": \"artifact\", \"type\": \"image\", \"url\": \"https://...\", \"local_path\": \"/tmp/openclaw/lovart_ab12cd.png\"}\n{\"event\": \"artifact\", \"type\": \"image\", \"url\": \"https://...\", \"local_path\": \"/tmp/openclaw/lovart_ef34gh.png\"}\n{\"event\": \"pending_confirmation\", \"thread_id\": \"xxx\", \"pending_confirmation\": {...}}\n{\"event\": \"finished\", \"thread_id\": \"xxx\", \"final_status\": \"done\", \"artifact_count\": 4}\n```\n\nFiles are saved with URL-hash filenames so re-running `watch` on the same thread won't re-download.\n\nYou can also attach to an **already-running** thread: `watch --thread-id THREAD_ID`.\n\n**When NOT to use `watch`:** single-image requests — use `chat` (simpler, one-shot response).\n\n## Output Format\n\n**chat --json** returns:\n```json\n{\n  \"thread_id\": \"xxx\",\n  \"status\": \"done\",\n  \"project_id\": \"xxx\",\n  \"final_status\": \"done\",\n  \"items\": [\n    {\"type\": \"assistant\", \"text\": \"Agent's reply\"},\n    {\"type\": \"generator\", \"name\": \"artifacts\", \"artifacts\": [\n      {\"type\": \"image\", \"content\": \"https://assets-persist.lovart.ai/artifacts/agent/xxx.png\"},\n      {\"type\": \"video\", \"content\": \"https://assets-persist.lovart.ai/artifacts/agent/xxx.mp4\"}\n    ]}\n  ],\n  \"downloaded\": [\n    {\"type\": \"image\", \"url\": \"https://...\", \"local_path\": \"/tmp/openclaw/lovart_01.png\"}\n  ]\n}\n```\n\n## Core Principle\n\nYou are a messenger, not a creator. The backend Agent handles understanding requirements, selecting models, and writing prompts. Your job:\n\n1. **Relay**: Pass the user's original description verbatim to chat\n2. **Wait**: Poll until generation completes\n3. **Deliver**: Send result files to the user\n\n**Do NOT** rewrite/expand prompts, break down tasks, or add your own style descriptions.\n\n## Lovart Generation Mode (MUST use API, not prompt)\n\n**CRITICAL: \"Fast mode\" and \"unlimited mode\" are server-side settings controlled via API calls, NOT prompt keywords.**\n\nDo NOT put \"快速模式\" or \"fast mode\" in the prompt text. Instead, call the set-mode command:\n\n```bash\n# User says \"fast mode\" / \"快速模式\" / \"skip queue\" / \"use credits\" → RUN THIS:\npython3 {baseDir}/agent_skill.py set-mode --fast\n\n# User says \"unlimited mode\" / \"无限模式\" / \"free mode\" / \"save credits\" → RUN THIS:\npython3 {baseDir}/agent_skill.py set-mode --unlimited\n\n# Check which mode is active:\npython3 {baseDir}/agent_skill.py query-mode\n```\n\n**How it works:**\n- `set-mode --fast` calls the Lovart backend API to switch the user's account to fast generation (costs credits, no queue)\n- `set-mode --unlimited` switches to unlimited generation (free, may queue)\n- This is a **persistent server-side setting** — it stays until changed again\n- It affects ALL subsequent image/video generations, not just one request\n- It has **nothing to do with your (the assistant's) response style or behavior**\n\n## Specifying Models\n\n**Option 1: In the prompt** (simple, the Agent routes automatically):\n\n```bash\npython3 {baseDir}/agent_skill.py chat --prompt \"generate ocean waves video using kling\" --json --download\n```\n\n**Option 2: Via --prefer-models** (precise, same as frontend's model selector):\n\n```bash\n# Prefer a specific image model\npython3 {baseDir}/agent_skill.py chat --prompt \"draw a cat\" --prefer-models '{\"IMAGE\":[\"generate_image_midjourney\"]}' --json --download\n\n# Prefer a specific video model\npython3 {baseDir}/agent_skill.py chat --prompt \"generate ocean waves\" --prefer-models '{\"VIDEO\":[\"generate_video_kling_3_0\"]}' --json --download\n\n# Combine image and video preferences\npython3 {baseDir}/agent_skill.py chat --prompt \"create content\" --prefer-models '{\"IMAGE\":[\"generate_image_seedream_3_0\"],\"VIDEO\":[\"generate_video_kling_3_0\"]}' --json --download\n```\n\nAvailable models for `--prefer-models`:\n\n**IMAGE:**\n\n| Tool name | Display name |\n|---|---|\n| `generate_image_gpt_image_2` | GPT Image 2 Auto |\n| `generate_image_gpt_image_2_low` | GPT Image 2 Low |\n| `generate_image_gpt_image_2_medium` | GPT Image 2 Medium |\n| `generate_image_gpt_image_2_high` | GPT Image 2 High |\n| `generate_image_nano_banana_pro` | Nano Banana Pro |\n| `generate_image_nano_banana_2` | Nano Banana 2 |\n| `generate_image_gpt_image_1_5` | GPT Image 1.5 |\n| `generate_image_seedream_v5` | Seedream 5.0 Lite |\n| `generate_image_luma_uni_1` | Luma uni-1 |\n| `generate_image_luma_uni_1_max` | Luma uni-1-max |\n| `generate_image_flux_2_max` | Flux.2 Max |\n| `generate_image_flux_2_pro` | Flux.2 Pro |\n| `generate_image_seedream_v4_5` | Seedream 4.5 |\n| `generate_image_nano_banana` | Nano Banana |\n| `generate_image_seedream_v4` | Seedream 4 |\n| `generate_image_imagen_v4` | Gemini Imagen 4 |\n| `generate_image_midjourney` | Midjourney |\n\n**VIDEO:**\n\n| Tool name | Display name |\n|---|---|\n| `generate_video_seedance_v2_0` | Seedance 2.0 |\n| `generate_video_seedance_v2_0_fast` | Seedance 2.0 Fast |\n| `generate_video_kling_v3` | Kling 3.0 |\n| `generate_video_kling_v3_omni` | Kling 3.0 Omni |\n| `generate_video_seedance_pro_v1_5` | Seedance 1.5 Pro |\n| `generate_video_kling_v2_6` | Kling 2.6 |\n| `generate_video_wan_v2_6` | Wan 2.6 |\n| `generate_video_sora_v2_pro` | Sora 2 Pro |\n| `generate_video_sora_v2` | Sora 2 |\n| `generate_video_veo3_1` | Veo 3.1 |\n| `generate_video_veo3_1_fast` | Veo 3.1 Fast |\n| `generate_video_kling_omni_v1` | Kling O1 |\n| `generate_video_hailuo_v2_3` | Hailuo 2.3 |\n| `generate_video_veo3` | Veo 3 |\n| `generate_video_vidu_q2` | Vidu Q2 |\n\n**3D:**\n\n| Tool name | Display name |\n|---|---|\n| `generate_3d_tripo` | Tripo |\n\nWhen the user requests a specific model, prefer `--prefer-models` over putting model names in the prompt.\n\n**Option 3: Via --include-tools** (hard constraint, forces specific tools):\n\n```bash\n# Force upscale only\npython3 {baseDir}/agent_skill.py chat --prompt \"upscale this image to 4K\" --include-tools upscale_image --attachments \"IMAGE_URL\" --json --download\n\n# Force a specific video model (no fallback to others)\npython3 {baseDir}/agent_skill.py chat --prompt \"generate a video\" --include-tools generate_video_kling_3_0 --json --download\n```\n\n`--include-tools` strongly instructs the Agent to prioritize the listed tools. Use this when the user explicitly requests a specific tool or operation.\n\n## Reasoning Mode — `--mode thinking` / `--mode fast`\n\nLovart has two reasoning modes you can select per thread:\n\n- **`fast`** (default) — lightweight single-pass response. Use for simple, one-shot generations where speed matters.\n- **`thinking`** — deep structured reasoning with planning and multi-step analysis. Use for complex brand systems, multi-asset campaigns, anything that benefits from deliberate planning. Slower but higher quality.\n\nOmitting `--mode` is equivalent to `--mode fast`, matching the web UI's default.\n\n```bash\n# Thinking mode — strategic, multi-step\npython3 {baseDir}/agent_skill.py chat --prompt \"design a brand identity system for a sustainable coffee startup\" --mode thinking --json --download\n\n# Fast mode — quick one-shot\npython3 {baseDir}/agent_skill.py chat --prompt \"draw a cat\" --mode fast --json --download\n```\n\n**Mode is locked to the thread on its first message.** Once you start a thread with `--mode thinking`, subsequent messages on the same `--thread-id` stay in thinking mode regardless of later `--mode` flags. To switch modes, start a new thread (omit `--thread-id`).\n\n## Task-Specific Tool Selection (IMPORTANT)\n\nWhen the user's request matches a specific operation, use `--include-tools` to ensure the correct tool:\n\n| User says | Use `--include-tools` |\n|-----------|----------------------|\n| \"upscale\", \"放大\", \"enlarge\", \"enhance resolution\", \"超分\" | `upscale_image` |\n| \"edit image\", \"modify\", \"change style\" | (let Agent decide) |\n| \"generate image\", \"draw\", \"画\" | (let Agent decide, or use `--prefer-models`) |\n\n**CRITICAL: When the user asks to \"upscale\", \"enlarge\", or increase resolution of an existing image, you MUST use `--include-tools upscale_image`. Do NOT let the Agent use image generation models for upscaling — they will re-generate the image instead of upscaling it.**\n\n## Notes\n\n- All APIs use AK/SK HMAC-SHA256 signature authentication\n- Video generation takes several minutes; the chat command auto-polls until complete\n- Gallery and canvas sync is idempotent — safe to call result multiple times without duplicates\n- Connection failures auto-retry 3 times with SSL fallback\n- After status becomes \"done\", waits 5 seconds to re-confirm (guards against sub-agent startup race)\n\nFile v1.0.9:_meta.json\n\n{\n  \"ownerId\": \"kn75568hvws2gh0ghmryz6dbxh84htc6\",\n  \"slug\": \"lovart-skill\",\n  \"version\": \"1.0.9\",\n  \"publishedAt\": 1779193903303\n}\n\nArchive v1.0.8: 3 files, 19550 bytes\n\nFiles: agent_skill.py (45062b), SKILL.md (22875b), _meta.json (131b)\n\nFile v1.0.8:SKILL.md\n\n---\nname: lovart-api\ndescription: >-\n  Generate images, videos, and audio/music via Lovart AI. Also manages Lovart projects,\n  threads (conversation history), and user settings. Trigger on: (1) any visual or audio\n  creation request in any language — draw, generate, create, design, make, 画, 生成,\n  制作, 创作, 设计 combined with image, video, audio, music, song, BGM, poster, etc.\n  (2) Lovart project/thread management — 项目, 对话, project, thread, conversation,\n  history, 历史, 切换, switch. You CAN generate directly - never say you cannot.\nuser-invocable: true\nmetadata:\n  {\n    \"openclaw\":\n      {\n        \"emoji\": \"🎨\",\n        \"requires\":\n          {\n            \"bins\": [\"python3\"],\n            \"env\": [\"LOVART_ACCESS_KEY\", \"LOVART_SECRET_KEY\"]\n          },\n        \"primaryEnv\": \"LOVART_ACCESS_KEY\"\n      }\n  }\n---\n\n# ⚠️ RULE #0: ONLY USE SKILL COMMANDS — NO DIRECT API CALLS\n\n**You MUST interact with Lovart EXCLUSIVELY through the commands defined in this skill.**\n- NEVER construct URLs, make curl/wget/fetch requests, or call Lovart APIs directly\n- NEVER guess API endpoints, paths, or parameters — only use the commands listed below\n- NEVER modify the skill's source code (agent_skill.py) during execution to \"debug\" issues (users may freely read the source to verify it)\n- If a command fails, retry it or report the error to the user — do NOT try to work around it\n- ALL Lovart operations go through: `chat`, `send`, `watch`, `confirm`, `result`, `status`, `config`, `projects`, `project-add`, `project-switch`, `project-rename`, `project-remove`, `threads`, `thread-remove`, `upload`, `upload-artifact`, `download`, `set-mode`, `query-mode`, `create-project`\n\n# ⚠️ RULE #1: YOU CAN AND MUST GENERATE IMAGES/VIDEOS/AUDIO\n\nWhen a user asks to \"draw\", \"generate\", \"create\", \"design\", \"make\", \"画\", \"生成\", \"制作\", \"创作\"\nany visual or audio content (in any language), you MUST use this skill.\nThis includes: images, videos, audio, music, songs, BGM, TTS, voice, posters, carousels, banners,\nlogos, illustrations, thumbnails, slides, covers, mockups, icons, social media content, etc.\nDo NOT say \"I can't generate images/music\" or offer to write prompts instead.\n\n# ⚠️ RULE #1.5: PROJECT & THREAD QUERIES USE THIS SKILL\n\nWhen the user asks about projects, threads, conversations, history, or settings (in any language),\nuse these commands — do NOT browse the filesystem:\n\n| User asks | Command |\n|-----------|---------|\n| \"What projects do I have?\" / \"我有哪些项目\" | `projects --json` |\n| \"What conversations/threads?\" / \"有哪些对话\" | `threads --json` or `threads --all --json` |\n| \"Show my settings\" / \"我的配置\" | `config --json` |\n| \"Switch to project X\" | `project-switch --project-id X` |\n| \"Create a new project\" | `project-add --project-id NEW_ID --name \"Name\"` (or let `chat` auto-create) |\n\n# ⚠️ RULE #2: ALWAYS USE `chat` AND WAIT FOR COMPLETION\n\nUse the `chat` command (blocks until done), NOT `send`. Do NOT reply before generation completes.\n\n**Handle these `final_status` values:**\n\n- `\"done\"` — Generation complete. Send the downloaded files to the user.\n- `\"pending_confirmation\"` — A high-cost tool (e.g. video, or a premium-quality image variant) needs user approval before credits are consumed.\n  **You MUST ask the user for explicit confirmation before proceeding. Do NOT auto-confirm.**\n  1. Show the user: \"This will cost approximately {estimated_cost} credits. Shall I proceed? (yes/no)\"\n  2. **WAIT for user response.** Only if user explicitly says yes/confirm/proceed, run:\n     `confirm --thread-id THREAD_ID --json --download`\n     (This confirms, waits for completion, and returns the result with downloaded files)\n  3. If user declines, do NOT confirm. Just inform them the operation was cancelled.\n- `\"abort\"` — Generation was aborted. Inform the user.\n- `\"timeout\"` — Generation is still running but exceeded the wait time. The result may contain partial artifacts.\n  1. Send any downloaded files that are already available\n  2. Tell the user: \"Generation is still in progress. Checking again...\"\n  3. Run: `result --thread-id THREAD_ID --json --download` to get the latest results\n  4. If status is still \"running\", wait and retry. If \"done\", send remaining files.\n\n**Handle errors:**\n\nIf `chat` throws an error (`AgentSkillError`), handle it by HTTP status and structured `code`. The `message` field already contains a user-ready explanation — surface it to the user as-is.\n\n| HTTP status | `code` | What it means | What to tell the user |\n|---|---|---|---|\n| **`402`** | `2012` | Quota / billing / risk-control rejection | Show `AgentSkillError.message` directly — the server already returns a specific message (insufficient credits, free-tier reached, concurrent limit, risk control, phone verification, team plan required, etc.) and a suggested next step. |\n| **`409`** | `2011` | Another task is still running on this thread | \"A task is still running on this conversation. Wait for it to finish (`status`) before sending a new prompt, or start a new thread.\" |\n| **`429`** | `1429` | API rate limit hit | \"Slowing down; rate limit hit. Retry in ~60s.\" |\n| **`401`** | — | AK/SK misconfigured | \"API key authentication failed. Please check your LOVART_ACCESS_KEY and LOVART_SECRET_KEY.\" |\n| — | — | `Project.*does not exist` in message | \"Project not found. Please check the project ID or create a new one.\" |\n\nRule of thumb: prefer `AgentSkillError.message` for user-facing copy. Do not try to parse internal codes out of the response — the server already maps them to human-readable messages before returning.\n\n**Detect silent generation failures (`done` with no artifact):**\n\nSome prompts end with `final_status: \"done\"` but produce no `artifacts` / empty `downloaded`. This usually means the upstream image model refused the prompt (content moderation), timed out, or the LLM chose to reply with text instead of calling a tool. The skill flags this automatically — when `chat()` returns, check:\n\n- `result[\"generation_succeeded\"]` — boolean. `False` means no artifact was produced.\n- `result[\"warning\"]` — explanation string (present only when `generation_succeeded` is `False`).\n- `result[\"agent_message\"]` — the agent's plain-text reply that hints at why (present when available).\n\nTypical triggers:\n- GPT Image 2 with very long/complex prompts involving weapons, specific bodies, or policy-sensitive wording — retry with a different model (`--include-tools generate_image_midjourney` or `generate_image_nano_banana_pro`) or simplify the prompt.\n- Prompt that describes a task the agent can't fulfill — show `agent_message` to the user.\n\n# ⚠️ RULE #3: ALWAYS DELIVER RESULTS + PROJECT LINK\n\nAfter EVERY generation, you MUST:\n1. Use `--download` flag with `chat` (or `result`)\n2. Send each downloaded file to the user as a **file attachment** (images, videos, audio/mp3 — ALL file types):\n   - ALWAYS send `downloaded[].local_path` as file attachments, regardless of file type (.png, .jpg, .mp4, .mp3, etc.)\n   - NEVER just paste the URL when a local file has been downloaded — send the actual file\n   - Only fall back to displaying URLs if no files were downloaded\n3. Append the project canvas link: `https://www.lovart.ai/canvas?projectId={project_id}`\n\n# ⚠️ RULE #4: CHECK LOCAL STATE ON FIRST USE (MANDATORY — DO NOT SKIP)\n\n**Before the FIRST generation in a conversation, you MUST run these two commands IN ORDER. This is NOT optional. Do NOT call `chat` until you have done both.**\n\n**Step 1: `config --json`**\n- Check local state (`~/.lovart/state.json`) for `active_project`\n- If `active_project` is set → proceed to Step 2. Do NOT create a new project. Do NOT ask the user.\n- If `active_project` is missing → ask the user: \"Do you have an existing Lovart project ID, or should I create a new one?\" **WAIT for their answer.**\n- Save with: `project-add --project-id PID --name \"name\"`\n\n**Step 2: `threads --json`**\n- Check if there's a recent thread to continue\n- If recent thread exists and topic is related → **REUSE it** (pass `--thread-id THREAD_ID` to `chat`)\n- If no threads or completely different topic → omit `--thread-id` (creates new thread)\n\n**CRITICAL RULES:**\n- **NEVER create a new project** if `config --json` already shows an `active_project`. Reuse it.\n- **NEVER omit `--thread-id`** when a relevant recent thread exists. Always reuse threads by default.\n- **NEVER call `chat` without first running `config --json` and `threads --json`** in the same conversation.\n- The `chat` command auto-reads `active_project` from local state — you do NOT need to pass `--project-id` every time.\n- Only create a new project if the user **explicitly** asks for one.\n- Only create a new thread if the topic is **completely unrelated** to the most recent thread.\n- When in doubt, **REUSE** both the existing project and the existing thread.\n\n---\n\n# Lovart Agent OpenAPI Skill\n\nInteract with Lovart AI Agent to generate images, videos, and visual assets via natural language.\n\nLovart is an AI design platform. The Agent understands user requests and automatically selects the best model and workflow.\n\n## Terminology\n\n- **Thread** — A conversation flow (chat session) with the Lovart AI Agent, NOT a programming thread. Each thread has a unique `thread_id` and preserves multi-turn context. Reusing a thread means continuing the same conversation so the Agent remembers previous images/videos and can iterate on them.\n- **Project** — A workspace/canvas that groups threads and generated artifacts together. One project can contain multiple threads.\n\n## Prerequisites\n\n```bash\nexport LOVART_ACCESS_KEY=\"ak_xxx\"\nexport LOVART_SECRET_KEY=\"sk_xxx\"\n```\n\nNo third-party dependencies. Python standard library only.\n\n## Features\n\n1. **Chat** - Send a message to the AI Agent, get text replies and generated images/videos\n2. **Confirm** - Confirm and wait for high-cost operations (e.g. video generation)\n3. **Create Project** - Create a new project\n4. **Upload File** - Upload a local image/video file, get back a CDN URL\n5. **Upload Artifact** - Upload a link artifact to a project\n6. **Status/Result** - Check thread status and retrieve results\n7. **Set/Query Mode** - Switch between fast (credits) and unlimited (queue) mode\n\n#\n\nArchive v1.0.7: 3 files, 19588 bytes\n\nFiles: agent_skill.py (45062b), SKILL.md (23071b), _meta.json (131b)\n\nArchive v1.0.6: 3 files, 18674 bytes\n\nFiles: agent_skill.py (43690b), SKILL.md (21857b), _meta.json (131b)\n\nArchive v1.0.5: 3 files, 18013 bytes\n\nFiles: agent_skill.py (42475b), SKILL.md (20733b), _meta.json (131b)\n\nArchive v1.0.3: 3 files, 17746 bytes\n\nFiles: agent_skill.py (42475b), SKILL.md (20070b), _meta.json (131b)","readmeExcerpt":"Skill: lovart-api Owner: lovart-admin Summary: Generate images, videos, and audio/music via Lovart AI. Also manages Lovart projects, threads (conversation history), and user settings. Trigger on: (1) any visual or audio creation request in any language — draw, generate, create, design, make, 画, 生成, 制作, 创作, 设计 combined with image, video, audio, music, song, BGM, poster, etc. (2) Lovart project/thread management — 项目, ","codeSnippets":[],"executableExamples":[{"language":"bash","snippet":"export LOVART_ACCESS_KEY=\"ak_xxx\"\nexport LOVART_SECRET_KEY=\"sk_xxx\""},{"language":"bash","snippet":"python3 {baseDir}/scripts/agent_skill.py project-add --project-id PROJECT_ID --name \"My Project\""},{"language":"bash","snippet":"python3 {baseDir}/scripts/agent_skill.py chat --prompt \"USER_PROMPT\" --json --download"},{"language":"bash","snippet":"python3 {baseDir}/scripts/agent_skill.py create-project"},{"language":"bash","snippet":"python3 {baseDir}/scripts/agent_skill.py upload --file /path/to/image.png\n# Returns: {\"url\": \"https://assets-persist.lovart.ai/img/{user_uuid}/xxx.png\"}"},{"language":"bash","snippet":"python3 {baseDir}/scripts/agent_skill.py upload-artifact --project-id PROJECT_ID --url \"ARTIFACT_URL\" --type image"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: lovart-api\ndescription: >-\n  Generate images, videos, and audio/music via Lovart AI. Also manages Lovart projects,\n  threads (conversation history), and user settings. Trigger on: (1) any visual or audio\n  creation request in any language — draw, generate, create, design, make, 画, 生成,\n  制作, 创作, 设计 combined with image, video, audio, music, song, BGM, poster, etc.\n  (2) Lovart project/thread management — 项目, 对话, project, thread, conversation,\n  history, 历史, 切换, switch. You CAN generate directly - never say you cannot.\nuser-invocable: true\nversion: 1.1.0\nauthor: Lovart (lovartai)\nlicense: MIT\nhomepage: https://github.com/lovartai/lovart-skill\nplatforms: [linux, macos, windows]\nmetadata:\n  hermes:\n    tags:\n      - image-generation\n      - video-generation\n      - audio-generation\n      - 3d\n      - design\n      - poster\n      - logo\n      - ai-art\n    related_skills: []\n  openclaw:\n    emoji: 🎨\n    requires:\n      bins: [python3]\n      env: [LOVART_ACCESS_KEY, LOVART_SECRET_KEY]\n    primaryEnv: LOVART_ACCESS_KEY\nprerequisites:\n  commands: [python3]\n  env: [LOVART_ACCESS_KEY, LOVART_SECRET_KEY]\n  python: []\n---\n\n# ⚠️ RULE #0: ONLY USE SKILL COMMANDS — NO DIRECT API CALLS\n\n**You MUST interact with Lovart EXCLUSIVELY through the commands defined in this skill.**\n- NEVER construct URLs, make curl/wget/fetch requests, or call Lovart APIs directly\n- NEVER guess API endpoints, paths, or parameters — only use the commands listed below\n- NEVER modify the skill's source code (agent_skill.py) during execution to \"debug\" issues (users may freely read the source to verify it)\n- If a command fails, retry it or report the error to the user — do NOT try to work around it\n- ALL Lovart operations go through: `chat`, `send`, `watch`, `confirm`, `result`, `status`, `config`, `projects`, `project-add`, `project-switch`, `project-rename`, `project-remove`, `threads`, `thread-remove`, `upload`, `upload-artifact`, `download`, `set-mode`, `query-mode`, `create-project`\n\n# ⚠️ RULE #1: YOU CAN AND MUST GENERATE IMAGES/VIDEOS/AUDIO\n\nWhen a user asks to \"draw\", \"generate\", \"create\", \"design\", \"make\", \"画\", \"生成\", \"制作\", \"创作\"\nany visual or audio content (in any language), you MUST use this skill.\nThis includes: images, videos, audio, music, songs, BGM, TTS, voice, posters, carousels, banners,\nlogos, illustrations, thumbnails, slides, covers, mockups, icons, social media content, etc.\nDo NOT say \"I can't generate images/music\" or offer to write prompts instead.\n\n# ⚠️ RULE #1.5: PROJECT & THREAD QUERIES USE THIS SKILL\n\nWhen the user asks about projects, threads, conversations, history, or settings (in any language),\nuse these commands — do NOT browse the filesystem:\n\n| User asks | Command |\n|-----------|---------|\n| \"What projects do I have?\" / \"我有哪些项目\" | `projects --json` |\n| \"What conversations/threads?\" / \"有哪些对话\" | `threads --json` or `threads --all --json` |\n| \"Show my settings\" / \"我的配置\" | `config --json` |\n| \"Switch to project X\" | `project-switch --project-id X` |\n| "},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn75568hvws2gh0ghmryz6dbxh84htc6\",\n  \"slug\": \"lovart-skill\",\n  \"version\": \"1.1.0\",\n  \"publishedAt\": 1788687584911\n}"},{"path":"skill-card.md","content":"## Description:\n\nGenerate images, videos, and audio or music with Lovart AI, and manage Lovart projects, threads, and settings.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[lovart-admin](https://clawhub.ai/user/lovart-admin)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nExternal users and developers use this skill to ask an agent to create visual or audio assets through Lovart, continue project threads, upload references, retrieve generated files, and manage Lovart project settings.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Prompts, selected reference files, project or thread metadata, and generated artifacts are sent to Lovart.\n\nMitigation: Use the skill only for content that is appropriate to process with Lovart, and avoid uploading private files unless that processing is intentional.\n\nRisk: The skill persists and reuses local project and thread state.\n\nMitigation: Review or clear ~/.lovart/state.json and confirm the active project and thread before sensitive work.\n\nRisk: Endpoint or TLS settings can weaken connection safeguards.\n\nMitigation: Keep LOVART_BASE_URL on the official endpoint and do not enable LOVART_INSECURE_SSL.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/lovart-admin/skills/lovart-skill)\n- [Lovart project canvas](https://www.lovart.ai/canvas?projectId={project_id})\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, shell commands, configuration, files]\n\n**Output Format:** [Markdown responses with JSON command results, downloaded media file attachments, and Lovart project links.]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Uses Lovart access credentials, persists local project and thread state, and can return images, videos, audio files, status details, warnings, and error messages.]\n\n## Skill Version(s):\n\n1.1.0 (source: server release metadata and frontmatter)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment."}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":"Generate images, videos, and audio/music via Lovart AI. Also manages Lovart projects, threads (conversation history), and user settings. Trigger on: (1) any visual or audio creation request in any language — draw, generate, create, design, make, 画, 生成, 制作, 创作, 设计 combined with image, video, audio, music, song, BGM, poster, etc. (2) Lovart project/thread management — 项目, 对话, project, thread, conversation, history, 历史, 切换, switch. You CAN generate directly - never say you cannot. Skill: lovart-api Owner: lovart-admin Summary: Generate images, videos, and audio/music via Lovart AI. Also manages Lovart projects, threads (conversation history), and user settings. Trigger on: (1) any visual or audio creation request in any language — draw, generate, create, design, make, 画, 生成, 制作, 创作, 设计 combined with image, video, audio, music, song, BGM, poster, etc. (2) Lovart project/thread management — 项目,","editorialQuality":{"score":100,"threshold":65,"status":"ready","wordCount":1470,"uniquenessScore":46,"reasons":[]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-09T07:00:00.273Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-09T07:00:00.273Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-09T14:13:03.795Z","emptyReason":null},"items":[{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-10T18:48:31.762Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}