civitai-orchestration-sdcpp

/home/avalon/.hermes/skills/software-development/civitai-orchestration-sdcpp/SKILL.md · raw

Civitai Orchestration sdcpp

Overview

Civitai Orchestration runs image-generation workflows at https://orchestration.civitai.com. For Stable Diffusion / Z-Image style jobs, the important step type is $type: "imageGen" with input.engine: "sdcpp".

This skill records the working request shapes verified on Alex's VPS with CIVITAI_TOKEN / CIVITAI_API_KEY in /home/avalon/.hermes/.env.

When to Use

Do not use this for Civitai Site API model browsing alone; use the Site API docs/workflows for that.

Auth and Endpoints

Environment:

CIVITAI_TOKEN=...
# or
CIVITAI_API_KEY=...

Base URL:

https://orchestration.civitai.com

Submit:

POST /v2/consumer/workflows?wait=60&whatif=false
Authorization: Bearer <token>
Content-Type: application/json

Poll:

GET /v2/consumer/workflows/{workflowId}
Authorization: Bearer <token>

Use whatif=true first to validate and preview Buzz cost without executing.

Critical Request Shape

All image workflows need a step discriminator:

{
  "allowMatureContent": true,
  "steps": [
    {
      "$type": "imageGen",
      "input": {
        "engine": "sdcpp",
        "ecosystem": "zImage",
        "model": "turbo",
        "operation": "createImage",
        "prompt": "...",
        "width": 1024,
        "height": 1024,
        "steps": 9,
        "cfgScale": 1,
        "quantity": 1
      }
    }
  ]
}

For sdcpp, use these field names:

For Comfy engines, the field names differ (sampler, scheduler, denoiseStrength). Do not mix them.

sdcpp vs Comfy: Which Operations Per Ecosystem

The sdcpp engine does not support createVariant or editImage for SD1/SDXL/Z-Image. Use the correct engine per goal:

Goal Ecosystem Engine Operation Notes
txt2img zImage sdcpp createImage Fast, verified working
txt2img sd1 sdcpp createImage Use checkpoint AIR
txt2img sdxl sdcpp createImage Use checkpoint AIR
txt2img flux1 sdcpp createImage Verified working
txt2img flux2Dev sdcpp createImage Verified working
txt2img flux2Klein sdcpp createImage Simplest Flux, no extra model refs
img2img / remix sd1 comfy createVariant image + denoiseStrength + model AIR URN required
img2img / remix sdxl comfy createVariant image + denoiseStrength + model AIR URN required
img2img / remix flux1 comfy createVariant image + denoiseStrength + model AIR URN required
img2img / remix flux2Dev sdcpp createVariant image + strength
img2img / remix flux2Klein sdcpp createVariant image + strengthsimplest and most reliable reference-image path
inpainting flux2Dev comfy editImage images[] array

Critical: If you try sdcpp + ecosystem: sdxl + operation: createVariant, you get a 400 validation error: "JSON deserialization for type '...SdxlVariantImageGenInput' was missing required properties including: 'model'" — because the schema does not exist. Switch to engine: "comfy".

Flux1 sdcpp createVariant requires extra model refs: Unlike Flux2Dev/Flux2Klein, Flux1 sdcpp createVariant requires diffuserModel, vaeModel, clipLModel, and t5XXLModel AIR URNs. If missing, you get: "JSON deserialization ... was missing required properties including: 'diffuserModel'". Use Flux2Klein for simpler reference-image workflows instead.

Working Flux2Klein sdcpp createVariant (Reference Image → New Scene)

flux2Klein + sdcpp is the simplest reference-image path. Unlike Flux1 sdcpp, it does not require diffuserModel, vaeModel, clipLModel, or t5XXLModel.

{
  "allowMatureContent": true,
  "steps": [{
    "$type": "imageGen",
    "input": {
      "engine": "sdcpp",
      "ecosystem": "flux2Klein",
      "operation": "createVariant",
      "image": "https://image.civitai.com/.../original=true/....jpg",
      "strength": 0.65,
      "prompt": "same characters, now in a luxurious bedroom with silk sheets, warm candlelight",
      "width": 1216,
      "height": 832,
      "sampleMethod": "euler",
      "schedule": "simple",
      "steps": 8,
      "cfgScale": 1,
      "quantity": 1,
      "modelVersion": "4b"
    }
  }]
}

Key: - modelVersion: "4b" or "9b" (default "4b"). Much simpler than Flux1's full model AIRs. - strength: 0.0 = no change, 1.0 = complete change. Default 0.7. - Typical Flux2Klein params from ComfyUI workflows: Euler sampler, 8 steps, CFG 1, 1216×832.

Working Z-Image Turbo

Verified succeeded. Cost: 8 Buzz for 1024², 9 steps.

{
  "allowMatureContent": true,
  "steps": [
    {
      "$type": "imageGen",
      "input": {
        "engine": "sdcpp",
        "ecosystem": "zImage",
        "model": "turbo",
        "operation": "createImage",
        "prompt": "a cute robot reading a book in a sunlit library, crisp detailed illustration",
        "negativePrompt": "blurry, low quality",
        "width": 1024,
        "height": 1024,
        "steps": 9,
        "cfgScale": 1,
        "quantity": 1
      }
    }
  ]
}

Notes:

Working Z-Image Base

Verified succeeded. Cost: 20 Buzz for 1024², 20 steps.

{
  "allowMatureContent": true,
  "steps": [
    {
      "$type": "imageGen",
      "input": {
        "engine": "sdcpp",
        "ecosystem": "zImage",
        "model": "base",
        "operation": "createImage",
        "prompt": "a cozy cabin in snowy mountains at sunrise, cinematic, detailed",
        "negativePrompt": "blurry, low quality",
        "width": 1024,
        "height": 1024,
        "steps": 20,
        "cfgScale": 4,
        "quantity": 1
      }
    }
  ]
}

Notes:

Working SD1 / DreamShaper

Verified succeeded. Cost: 4 Buzz for 512², 20 steps.

{
  "allowMatureContent": true,
  "steps": [
    {
      "$type": "imageGen",
      "input": {
        "engine": "sdcpp",
        "ecosystem": "sd1",
        "operation": "createImage",
        "model": "urn:air:sd1:checkpoint:civitai:4384@128713",
        "prompt": "masterpiece, best quality, a cute robot reading a book, studio lighting",
        "negativePrompt": "worst quality, low quality, blurry",
        "width": 512,
        "height": 512,
        "steps": 20,
        "cfgScale": 7,
        "clipSkip": 2,
        "quantity": 1
      }
    }
  ]
}

Important: for SD1/SDXL checkpoints, use checkpoint in AIR URNs, not model:

urn:air:sd1:checkpoint:civitai:<modelId>@<versionId>
urn:air:sdxl:checkpoint:civitai:<modelId>@<versionId>

Using urn:air:sdxl:model:... caused silent worker failures in earlier tests.

Z-Image Turbo with LoRA

Verified succeeded with the NexBlend Z-Image Turbo LoRA.

Working LoRA resource:

model id: 2669120
version id: 2997054
trained word: nexblend
tested AIR: urn:air:zimageturbo:lora:civitai:2669120@2997054

Payload:

{
  "allowMatureContent": true,
  "steps": [
    {
      "$type": "imageGen",
      "input": {
        "engine": "sdcpp",
        "ecosystem": "zImage",
        "model": "turbo",
        "operation": "createImage",
        "prompt": "nexblend, asian fashion model portrait, professional studio photo, elegant outfit, detailed skin texture, soft cinematic lighting",
        "negativePrompt": "blurry, low quality, distorted hands",
        "width": 1024,
        "height": 1024,
        "steps": 9,
        "cfgScale": 1,
        "quantity": 1,
        "loras": {
          "urn:air:zimageturbo:lora:civitai:2669120@2997054": 0.8
        }
      }
    }
  ]
}

Cost preview showed fixed.additionalResources: 1, making total 9 Buzz.

Vision verification: professional Asian fashion-model portrait, high quality.

LoRA AIR Pitfall

For Z-Image Turbo LoRAs, use lowercase/internal ecosystem in the LoRA AIR:

urn:air:zimageturbo:lora:civitai:<modelId>@<versionId>

These variants failed or stalled in tests:

urn:air:zImage:lora:civitai:2669120@2997054      # failed instantly
urn:air:zImageTurbo:lora:civitai:2669120@2997054 # failed instantly
urn:air:zimage:lora:civitai:2669120@2997054      # accepted but hung/processed slowly in test

Best rule: inspect the returned workflow steps[0].input.diffuserModel; for Z-Image Turbo it was urn:air:zimageturbo:checkpoint:..., so LoRAs should use zimageturbo too.

Output Handling

Successful image outputs are under:

workflow.steps[n].output.images[]

Not always under blobs[]. Each image has:

Signed URLs are temporary. For app integration, download immediately and persist to the app's own storage. Never expose signed URLs in logs or chat.

Debugging Recipe

Use a Python or curl script that:

  1. Loads token from env without printing it.
  2. Submits with whatif=true.
  3. If validation passes, submits with whatif=false&wait=60 or wait=0.
  4. Polls every 5-15s until succeeded, failed, or canceled.
  5. Reads output.images[], not just output.blobs[].
  6. Downloads available image URLs immediately.
  7. Redacts all URLs and tokens from logs.

Minimal Python pattern:

import os, requests, time

TOKEN = os.environ["CIVITAI_TOKEN"]
BASE = "https://orchestration.civitai.com/v2/consumer/workflows"
HEADERS = {"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"}

payload = {"allowMatureContent": True, "steps": [{"$type": "imageGen", "input": {...}}]}
r = requests.post(BASE, params={"whatif": "true", "wait": 0}, headers=HEADERS, json=payload)
r.raise_for_status()

r = requests.post(BASE, params={"whatif": "false", "wait": 0}, headers=HEADERS, json=payload)
r.raise_for_status()
workflow = r.json()
wid = workflow["id"]

while workflow["status"] in {"scheduled", "pending", "processing", "unassigned"}:
    time.sleep(10)
    workflow = requests.get(f"{BASE}/{wid}", headers=HEADERS).json()

for step in workflow.get("steps", []):
    images = (step.get("output") or {}).get("images") or []
    for image in images:
        if image.get("available") and image.get("url"):
            data = requests.get(image["url"]).content
            # write/upload data; do not log signed URL

Common Pitfalls

  1. Wrong AIR type: SD1/SDXL checkpoints should use checkpoint, not model.

  2. Wrong Z-Image LoRA ecosystem: Use zimageturbo for Z-Image Turbo LoRA AIRs, not zImage or zImageTurbo.

  3. Gallery URLs vs single image URLs: Civitai URLs like https://civitai.red/images/<postId> are gallery posts containing multiple images (often 50–100). The API GET /api/v1/images?ids=<postId> returns an items array. Filter by baseModel, prompt content, or modelVersionIds to find the specific image you want. Do not assume the first item is the right one.

  4. Looking only for blobs[]: sdcpp image output appeared in output.images[].

  5. Assuming wait=60 always returns terminal state: Z-Image Turbo took ~58s in one test and returned processing; poll after submit.

  6. Mixing engine parameter names: sdcpp uses sampleMethod / schedule; Comfy uses sampler / scheduler.

  7. Using SDXL clipSkip: SDXL docs say clipSkip is invalid. Use it only for SD1 if needed.

  8. Silent failures: Bad resources can fail instantly with errors: [] and debit+credit refund. Check transactions, jobs[].status, and normalized input.

  9. sdcpp does NOT support img2img for SD1/SDXL/Z-Image: Use engine: "comfy" with operation: "createVariant" for remixes. For Flux ecosystems, use flux2Klein or flux2Dev with sdcpp — the simplest reference-image path. See references/flux2klein-createVariant.md.

  10. Blocking inline polls for hours: Civitai queues are often very slow. Inline scripts will time out. Submit with wait=0, then poll asynchronously via cron or a background process. See references/async-polling-and-queue-behavior.md and scripts/check_civitai_workflows.py.

  11. Civitai image API ids lookup returns wrong image: GET /api/v1/images?ids=<imageId> returns a gallery/post with 50–100 items, not the specific image. The first item is often completely unrelated. Do not use this endpoint for metadata extraction. Use bulk feeds, direct image URLs, or upload local images to blob storage. See references/civitai-image-api-id-lookup-pitfall.md.

  12. civitai.red gallery URLs are post IDs, not image IDs: URLs like https://civitai.red/images/<id> resolve to galleries containing multiple images. The ids parameter on the Site API returns the same post for many different IDs. Always filter bulk results or use direct image.civitai.com URLs.

Verified Workflow Results (Session Log)

From live testing (June 2026):

Succeeded: - 6621915-20260603011327874 — Flux2Klein createImage, 3 Buzz, output nsfwLevel: r - 6621915-20260603011339232 — Flux2Klein createVariant (uploaded reference → new scene), 3 Buzz, output nsfwLevel: pg13 (not explicit — Civitai may moderate or the prompt wasn't strong enough) - 6621915-20260602234936834 — Z-Image Turbo no LoRA, 8 Buzz - 6621915-20260602235037058 — Z-Image Base no LoRA, 20 Buzz - 6621915-20260602235123246 — SD1/DreamShaper, 4 Buzz - 6621915-20260602235313207 — Z-Image Turbo + NexBlend LoRA, 9 Buzz - 6621915-20260603004705697 — Adult NSFW hardcore, eventually succeeded after hours in queue

Failed: - 6621915-20260603010749753 — Comfy SDXL createVariant (cyberpunk remix): failed after 23 min, cost 0 (refunded), output.errors: [], job.result: None. Silent failure with no diagnostic message. - LoRA AIR variants zImage/zImageTurbo for NexBlend: instant failure with errors: [].

Key Discovery: Flux2Klein sdcpp createVariant is the simplest confirmed working reference-image path on Civitai Orchestration. Comfy SDXL createVariant silently fails with empty errors.

References

Verification Checklist