> ## Documentation Index
> Fetch the complete documentation index at: https://docs.youka.io/llms.txt
> Use this file to discover all available pages before exploring further.

# AI 에이전트

> Youka CLI 또는 API를 호출하는 에이전트를 위한 운영 규칙과 워크플로 패턴

Youka는 에이전트가 구동하도록 설계되었습니다. 모든 CLI 명령은 기계가 읽을 수 있는 JSON 엔벨로프를 반환하고, 모든 쓰기 작업은 멱등성 키를 지원하며, 공개 API는 동일한 의미 체계로 동일한 표면을 노출합니다. 이 페이지는 Youka를 워크플로에 연결하기 전에 에이전트 작성자가 알아야 할 운영 규칙을 모아둡니다.

## 시작하기

에이전트를 처음 설정한다면, 먼저 Youka CLI를 설치한 다음 Youka karaoke 스킬을 설치하세요:

```bash theme={null}
npm install -g @youka/cli
npx skills add https://github.com/youka-io/skills --skill youka-karaoke
```

이렇게 하면 CLI로 구동되는 готов된(기성) Youka 스킬이 에이전트에 제공됩니다. 설치가 끝나면 아래의 워크플로 패턴을 사용해 가라오케 비디오를 만들고, 스타일을 커스터마이즈하고, MP4 파일을 안전하게 내보낼 수 있습니다.

### 에이전트에 프롬프트 주기

CLI와 스킬을 설치한 뒤에는, 에이전트에 다음처럼 직접 작업을 지시할 수 있습니다:

<CodeGroup>
  ```text local-file theme={null}
  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.
  ```

  ```text url theme={null}
  Use Youka to create a karaoke video from https://example.com/song.mp4. If URL dependencies are missing, install them first. Then transcribe the lyrics automatically, use a clean karaoke subtitle style, export the final video, and save it as ./karaoke.mp4.
  ```
</CodeGroup>

## 운영 규칙

<CardGroup cols={2}>
  <Card title="항상 --json 사용" icon="code">
    CLI에서는 항상 `--json`을 전달하세요. API에서는 항상 `Accept:
            application/json`을 설정하세요. 사람이 읽는 출력은 절대 파싱하지 마세요.
  </Card>

  <Card title="항상 멱등성 키 전송" icon="rotate">
    모든 쓰기 작업에는 안정적인 멱등성 키를 포함해야 하며, 타임아웃 이후 재시도하더라도 작업이 중복 생성되지 않고 원래 결과를 반환해야 합니다.
  </Card>

  <Card title="영속 상태를 다시 읽기" icon="database">
    오래된 변경 응답을 신뢰하지 마세요. 종료(terminal)된 작업 이후에는 최종 상태를 얻기 위해 프로젝트 또는 익스포트를 다시 읽으세요.
  </Card>

  <Card title="백오프로 폴링" icon="hourglass">
    2–3초 간격으로 시작하세요. 긴 작업은 지수적으로 백오프하세요.
    429 응답을 준수하세요.
  </Card>
</CardGroup>

## 출력 계약

`--json` 모드에서 모든 CLI 명령은 stdout에 정확히 하나의 엔벨로프를 출력합니다.

성공:

```json theme={null}
{
  "schemaVersion": "1",
  "ok": true,
  "data": { "id": "prj_abc123", "title": "My Song" }
}
```

실패:

```json theme={null}
{
  "schemaVersion": "1",
  "ok": false,
  "error": {
    "code": "CONFLICT",
    "message": "A request with this Idempotency-Key is already in progress.",
    "retryable": true
  }
}
```

종료 코드:

| Code | Meaning                        | Retry?                |
| ---- | ------------------------------ | --------------------- |
| `0`  | 성공.                            | N/A                   |
| `1`  | 런타임 오류(네트워크, API, 렌더링).        | `error.retryable` 확인. |
| `2`  | 잘못된 입력(잘못된 플래그, 읽을 수 없는 페이로드). | 아니오 — 입력을 수정하세요.      |

## 엔드-투-엔드 워크플로

정석(캐노니컬) 에이전트 워크플로는 다음과 같습니다: 프로젝트 생성, 대기, 익스포트, 결과 다운로드. 아래는 CLI와 SDK 구현을 모두 포함한 전체 패턴입니다.

<CodeGroup>
  ```bash CLI theme={null}
  # 1. 프로젝트를 생성하고 stems + lyrics sync가 끝날 때까지 대기
  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. 익스포트를 시작하고 완료될 때까지 대기
  EXPORT_JSON=$(youka export create "$PROJECT_ID" \
    --resolution 1080p \
    --quality high \
    --wait \
    --download \
    --output ./karaoke.mp4 \
    --idempotency-key "export-$PROJECT_ID-v1" \
    --json)

  echo "완료:" "$(echo "$EXPORT_JSON" | jq -r '.data.fileUrl')"
  ```

  ```ts SDK theme={null}
  import { YoukaClient, YoukaRequestError, YoukaTaskError } from "@youka/ko/sdk";

  const client = new YoukaClient({ apiKey: process.env.YOUKA_API_KEY! });

  async function createAndExport() {
    // 1. 프로젝트를 생성하고 stems + lyrics sync를 대기
    const created = await client.projects.create(
      {
        source: { type: "path", path: "./song.mp3" },
        lyricsSource: { type: "transcribe", language: "en" },
      },
      { idempotencyKey: "create-song-2026-04-08-001" },
    );

    const { project } = await client.projects.wait(created);

    // 2. 익스포트를 시작하고 완료될 때까지 대기
    const exportResult = await client.exports.create(
      project.id,
      { resolution: "1080p", quality: "high" },
      { idempotencyKey: `export-${project.id}-v1` },
    );

    const finalized = await client.exports.wait(exportResult);

    // 3. 파일 다운로드
    await client.exports.download(finalized, {
      output: "./karaoke.mp4",
    });
  }

  createAndExport().catch((error) => {
    if (error instanceof YoukaRequestError && error.retryable) {
      // 동일한 멱등성 키로 재시도
    }
    if (error instanceof YoukaTaskError) {
      console.error("작업 실패:", error.code, error.task.error);
    }
    throw error;
  });
  ```
</CodeGroup>

## 폴링 가이드

대부분의 쓰기 작업은 SDK에서 operation handle을 반환합니다. `client.projects.wait(...)` 및 `client.exports.wait(...)`를 우선 사용하고, 명시적으로 저수준 task 접근이 필요할 때만 `client.tasks.*`로 내려가세요.

| Job type                             | Recommended initial interval | Max wait |
| ------------------------------------ | ---------------------------- | -------- |
| Project create (stems + lyrics sync) | 3 s                          | 15 min   |
| Stem separation only                 | 3 s                          | 10 min   |
| Lyrics sync only                     | 2 s                          | 5 min    |
| Export render                        | 3 s                          | 30 min   |

CLI에서는 `--wait`가 폴링을 대신 처리합니다. SDK에서는 wait helper가 기본으로 2 s 간격을 사용하며 `pollIntervalMs`를 받습니다.

<Tip>
  429 응답을 준수하세요. 레이트 리밋이 걸리면 `Retry-After`
  헤더(없으면 30 s) 이상으로 백오프하세요.
</Tip>

## 멱등성 키

모든 생성 및 업데이트 작업은 멱등성 키를 지원합니다. 규칙:

* 논리적 변경(mutation) 단위로 **안정적이고, 유일하며, 결정적인** 키를 사용하세요. 좋음: `create-song-${sourceHash}`. 나쁨: 재시도마다 새 UUID 생성.
* 재시도에서는 **동일한** 키를 재사용하세요. 서버는 재전송을 인식하고 원래 결과를 반환합니다.
* 키는 계정 단위로 스코프되며 24시간 후 만료됩니다.
* 서버가 `IDEMPOTENT_REPLAY_IN_PROGRESS`(HTTP 202)를 반환하면 원래 요청이 아직 실행 중입니다. 기다린 다음 동일한 키로 재시도하세요.

예시 패턴:

```ts theme={null}
const key = `create-${sha256(sourceBytes)}`;

try {
  return await client.projects.create(body, { idempotencyKey: key });
} catch (error) {
  if (error instanceof YoukaRequestError && error.retryable) {
    // 동일한 키로 안전하게 재시도 가능
    return await client.projects.create(body, { idempotencyKey: key });
  }
  throw error;
}
```

전체 계약은 [API idempotency](/ko/api/idempotency)를 참고하세요.

## 오류 복구

`error.code`와 `error.retryable`을 기준으로 분기하세요. 흔한 케이스:

| Code                                  | Cause                  | Action                                   |
| ------------------------------------- | ---------------------- | ---------------------------------------- |
| `INVALID_REQUEST`                     | 요청 바디가 스키마 검증에 실패했습니다. | 페이로드를 수정하세요. 재시도 없음.                     |
| `UNAUTHORIZED`                        | API 키가 없거나 유효하지 않습니다.  | 호출자에게 전달하세요. 재시도 없음.                     |
| `NOT_FOUND`                           | 리소스가 없거나 접근 권한이 없습니다.  | 재시도 없음.                                  |
| `CONFLICT` (409)                      | 버전 충돌 또는 멱등성 충돌.       | 동일한 멱등성 키로 재시도하세요.                       |
| `TOO_MANY_REQUESTS` (429)             | 레이트 리밋.                | `Retry-After` 또는 30 s 기준으로 백오프하세요.       |
| `INTERNAL_SERVER_ERROR` (500)         | 일시적인 서버 장애.            | 백오프와 함께 최대 3회 재시도하세요.                    |
| `IDEMPOTENT_REPLAY_IN_PROGRESS` (202) | 이전 요청이 아직 실행 중입니다.     | 기다렸다가 동일한 키로 재시도하세요.                     |
| `TASK_FAILED`                         | 비동기 작업이 실패로 종료되었습니다.   | `error.task.error`를 호출자에게 전달하세요. 재시도 없음. |
| `TASK_TIMED_OUT`                      | 비동기 작업이 제한 시간을 초과했습니다. | 1회 재시도는 안전합니다.                           |

## 변경 가능한 필드 찾기

프리셋을 변경하기 전에 프리셋 스키마를 가져와서 모델이 유효한 필드와 값 타입을 알 수 있도록 하세요:

<CodeGroup>
  ```bash CLI theme={null}
  # Preset body schema
  youka preset schema --json
  ```

  ```ts SDK theme={null}
  import { KaraokePresetSchema } from "@youka/ko/sdk";

  const presetSchema = KaraokePresetSchema.toJSONSchema();
  ```
</CodeGroup>

프로젝트 설정의 경우, 먼저 현재 프로젝트 설정을 읽은 다음 `youka project settings <id> --body ...`를 통해 최소한의 업데이트 바디만 제출하는 방식을 권장합니다.

에이전트 세션당 한 번만 가져오고 결과를 캐시하세요.

## 병렬 에이전트

여러 에이전트가 동일 계정에 대해 동시에 실행될 때:

* 멱등성 키를 에이전트 ID와 논리적 변경 둘 다에 스코프하세요: `agent-${agentId}-create-${sourceHash}`. 이렇게 하면 한 에이전트의 재시도가 다른 에이전트의 새 요청과 충돌하는 것을 방지합니다.
* 읽기 작업은 제한 없이 수행하세요 — `GET` 요청은 비용이 저렴하고 부작용이 없습니다.
* 정렬된 익스포트 히스토리가 필요하다면 프로젝트별로 `POST /projects/{projectId}/exports`에 대해 단일 큐를 사용하세요. 그렇지 않으면 익스포트가 순서 없이 도착할 수 있습니다.

## 다음 단계

* [CLI global options](/ko/cli/global-options) — 에이전트가 사용할 수 있는 모든 플래그
* [SDK errors](/ko/sdk/errors) — 전체 오류 클래스 레퍼런스
* [API async jobs](/ko/api/async-jobs) — 폴링 계약
* [API idempotency](/ko/api/idempotency) — 멱등성 계약
