Skip to main content
Youka is designed to be driven by agents. Every CLI command returns a machine-readable JSON envelope, every write supports idempotency keys, and the public API exposes the same surface with the same semantics. This page collects the operating rules an agent author needs before wiring Youka into a workflow.

Get started

If you’re setting up an agent for the first time, install the Youka CLI first, then install the Youka karaoke skill:
npm install -g @youka/cli
npx skills add https://github.com/youka-io/skills --skill youka-karaoke
That gives the agent a ready-made Youka skill backed by the CLI. Once that’s installed, use the workflow patterns below to create karaoke videos, customize the style, and export MP4 files safely.

Prompt your agent

After installing the CLI and skill, you can give your agent a direct task like this:
Use Youka to create a karaoke video from /path/to/song.mp3. Transcribe the lyrics in English, use a clean karaoke subtitle style, export the final video in 1080p, and save it as ./karaoke.mp4.

Operating rules

Always use --json

On the CLI, always pass --json. In the API, always set Accept: application/json. Never parse human output.

Always send an idempotency key

Every write should carry a stable idempotency key so retries after a timeout return the original result instead of duplicating work.

Re-read durable state

Don’t trust stale mutation responses. After a terminal task, re-read the project or export to get the final state.

Poll with backoff

Start with a 2–3 second interval. Exponentially back off for long jobs. Respect 429 responses.

Output contract

Every CLI command in --json mode writes exactly one envelope to stdout. Success:
{
  "schemaVersion": "1",
  "ok": true,
  "data": { "id": "prj_abc123", "title": "My Song" }
}
Failure:
{
  "schemaVersion": "1",
  "ok": false,
  "error": {
    "code": "CONFLICT",
    "message": "A request with this Idempotency-Key is already in progress.",
    "retryable": true
  }
}
Exit codes:
CodeMeaningRetry?
0Success.N/A
1Runtime error (network, API, rendering).Check error.retryable.
2Invalid input (bad flags, unreadable payload).No — fix the input.

End-to-end workflow

The canonical agent workflow is: create a project, wait, export, download the result. Here’s the full pattern with both CLI and SDK implementations.
# 1. Create the project and wait for stems + lyrics sync to finish
PROJECT_JSON=$(youka project create ./song.mp3 \
  --mode transcribe \
  --lang en \
  --wait \
  --idempotency-key "create-song-2026-04-08-001" \
  --json)

PROJECT_ID=$(echo "$PROJECT_JSON" | jq -r '.data.projectId')

# 2. Start and wait for an export
EXPORT_JSON=$(youka export create "$PROJECT_ID" \
  --resolution 1080p \
  --quality high \
  --wait \
  --download \
  --output ./karaoke.mp4 \
  --idempotency-key "export-$PROJECT_ID-v1" \
  --json)

echo "Done:" "$(echo "$EXPORT_JSON" | jq -r '.data.fileUrl')"

Polling guidance

Most writes return operation handles in the SDK. Prefer client.projects.wait(...) and client.exports.wait(...), and drop to client.tasks.* only when you explicitly need low-level task access.
Job typeRecommended initial intervalMax wait
Project create (stems + lyrics sync)3 s15 min
Stem separation only3 s10 min
Lyrics sync only2 s5 min
Export render3 s30 min
On the CLI, --wait handles polling for you. On the SDK, the wait helpers use a 2 s interval by default and accept pollIntervalMs.
Respect 429 responses. On rate limits, back off by at least the Retry-After header (or 30 s if absent).

Idempotency keys

Every create and update operation supports an idempotency key. Rules:
  • Use a stable, unique, deterministic key per logical mutation. Good: create-song-${sourceHash}. Bad: a fresh UUID per retry.
  • Reuse the same key across retries. The server recognizes the replay and returns the original result.
  • Keys are scoped per-account and expire after 24 hours.
  • If the server returns IDEMPOTENT_REPLAY_IN_PROGRESS (HTTP 202), the original request is still running. Wait and retry with the same key.
Example pattern:
const key = `create-${sha256(sourceBytes)}`;

try {
  return await client.projects.create(body, { idempotencyKey: key });
} catch (error) {
  if (error instanceof YoukaRequestError && error.retryable) {
    // Safe to retry with the same key
    return await client.projects.create(body, { idempotencyKey: key });
  }
  throw error;
}
See API idempotency for the full contract.

Error recovery

Branch on error.code and error.retryable. The common cases:
CodeCauseAction
INVALID_REQUESTRequest body failed schema validation.Fix the payload. No retry.
UNAUTHORIZEDMissing or invalid API key.Surface to the caller. No retry.
NOT_FOUNDResource doesn’t exist or you lack access.No retry.
CONFLICT (409)Version conflict or idempotency collision.Retry with the same idempotency key.
TOO_MANY_REQUESTS (429)Rate limit.Back off by Retry-After or 30 s.
INTERNAL_SERVER_ERROR (500)Transient server failure.Retry up to 3 times with backoff.
IDEMPOTENT_REPLAY_IN_PROGRESS (202)Prior request still running.Wait and retry with the same key.
TASK_FAILEDThe async task ended in failure.Surface error.task.error to the caller. No retry.
TASK_TIMED_OUTThe async task exceeded its budget.Safe to retry once.

Discovering mutable fields

Before mutating presets, fetch the preset schema so the model knows the valid fields and value types:
# Preset body schema
youka preset schema --json
For project settings, prefer reading the current project settings first, then submitting a minimal update body through youka project settings <id> --body .... Fetch once per agent session and cache the result.

Parallel agents

When multiple agents run concurrently against the same account:
  • Scope idempotency keys to both the agent identity and the logical mutation: agent-${agentId}-create-${sourceHash}. This prevents one agent’s retry from colliding with another agent’s fresh request.
  • Keep reads unbounded — GET requests are cheap and have no side effects.
  • Use a single queue for POST /projects/{projectId}/exports per project if you need ordered export history. Otherwise exports may arrive out of order.

What’s next