> ## 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.

# Agents IA

> Règles d’exploitation et patterns de workflow pour des agents appelant la CLI ou l’API Youka

Youka est conçu pour être piloté par des agents. Chaque commande de la CLI renvoie une enveloppe JSON lisible par machine, chaque écriture prend en charge des clés d’idempotence, et l’API publique expose la même surface avec la même sémantique. Cette page rassemble les règles d’exploitation dont un auteur d’agent a besoin avant de connecter Youka à un workflow.

## Bien démarrer

Si vous configurez un agent pour la première fois, installez d’abord la CLI Youka, puis installez la skill karaoke Youka :

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

Cela fournit à l’agent une skill Youka prête à l’emploi, adossée à la CLI. Une fois installée, utilisez les patterns de workflow ci-dessous pour créer des vidéos de karaoké, personnaliser le style et exporter des fichiers MP4 en toute sécurité.

### Donnez une consigne à votre agent

Après avoir installé la CLI et la skill, vous pouvez donner à votre agent une tâche directe comme celle-ci :

<CodeGroup>
  ```text local-file theme={null}
  Utilise Youka pour créer une vidéo karaoké à partir de /path/to/song.mp3. Transcris les paroles en anglais, utilise un style de sous-titres karaoké épuré, exporte la vidéo finale en 1080p et enregistre-la sous ./karaoke.mp4.
  ```

  ```text url theme={null}
  Utilise Youka pour créer une vidéo karaoké à partir de https://example.com/song.mp4. Si des dépendances d’URL manquent, installe-les d’abord. Puis transcris les paroles automatiquement, utilise un style de sous-titres karaoké épuré, exporte la vidéo finale et enregistre-la sous ./karaoke.mp4.
  ```
</CodeGroup>

## Règles d’exploitation

<CardGroup cols={2}>
  <Card title="Toujours utiliser --json" icon="code">
    Dans la CLI, passez toujours `--json`. Dans l’API, définissez toujours `Accept:
            application/json`. Ne parsez jamais la sortie destinée aux humains.
  </Card>

  <Card title="Toujours envoyer une clé d’idempotence" icon="rotate">
    Chaque écriture doit inclure une clé d’idempotence stable, afin que les relances après un timeout renvoient le résultat d’origine au lieu de dupliquer le travail.
  </Card>

  <Card title="Relire l’état durable" icon="database">
    Ne faites pas confiance à des réponses de mutation potentiellement obsolètes. Après une tâche terminale, relisez le projet ou l’export pour obtenir l’état final.
  </Card>

  <Card title="Sonder avec backoff" icon="hourglass">
    Commencez avec un intervalle de 2–3 secondes. Appliquez un backoff exponentiel pour les traitements longs.
    Respectez les réponses 429.
  </Card>
</CardGroup>

## Contrat de sortie

Chaque commande de la CLI en mode `--json` écrit exactement une enveloppe sur stdout.

Succès :

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

Échec :

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

Codes de sortie :

| Code | Signification                                       | Relancer ?                  |
| ---- | --------------------------------------------------- | --------------------------- |
| `0`  | Succès.                                             | N/A                         |
| `1`  | Erreur d’exécution (réseau, API, rendu).            | Vérifiez `error.retryable`. |
| `2`  | Entrée invalide (mauvais flags, payload illisible). | Non — corrigez l’entrée.    |

## Workflow de bout en bout

Le workflow canonique d’un agent est : créer un projet, attendre, exporter, télécharger le résultat. Voici le pattern complet avec des implémentations CLI et SDK.

<CodeGroup>
  ```bash CLI theme={null}
  # 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')"
  ```

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

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

  async function createAndExport() {
    // 1. Create the project and wait for 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. Start and wait for an export
    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. Download the file
    await client.exports.download(finalized, {
      output: "./karaoke.mp4",
    });
  }

  createAndExport().catch((error) => {
    if (error instanceof YoukaRequestError && error.retryable) {
      // Retry with the same idempotency keys
    }
    if (error instanceof YoukaTaskError) {
      console.error("Task failed:", error.code, error.task.error);
    }
    throw error;
  });
  ```
</CodeGroup>

## Conseils de polling

La plupart des écritures renvoient des handles d’opération dans le SDK. Préférez `client.projects.wait(...)` et `client.exports.wait(...)`, et ne descendez vers `client.tasks.*` que lorsque vous avez explicitement besoin d’un accès bas niveau aux tâches.

| Type de job                               | Intervalle initial recommandé | Attente max |
| ----------------------------------------- | ----------------------------- | ----------- |
| Création de projet (stems + sync paroles) | 3 s                           | 15 min      |
| Séparation des stems uniquement           | 3 s                           | 10 min      |
| Sync des paroles uniquement               | 2 s                           | 5 min       |
| Rendu d’export                            | 3 s                           | 30 min      |

Dans la CLI, `--wait` gère le polling pour vous. Dans le SDK, les helpers d’attente utilisent un intervalle de 2 s par défaut et acceptent `pollIntervalMs`.

<Tip>
  Respectez les réponses 429. En cas de rate limit, appliquez un backoff d’au moins la valeur de l’en-tête `Retry-After`
  (ou 30 s s’il est absent).
</Tip>

## Clés d’idempotence

Chaque opération de création et de mise à jour prend en charge une clé d’idempotence. Règles :

* Utilisez une clé **stable, unique, déterministe** par mutation logique. Bien : `create-song-${sourceHash}`. Mauvais : un nouvel UUID à chaque relance.
* Réutilisez la **même** clé lors des relances. Le serveur reconnaît la relecture et renvoie le résultat d’origine.
* Les clés sont limitées au compte et expirent après 24 heures.
* Si le serveur renvoie `IDEMPOTENT_REPLAY_IN_PROGRESS` (HTTP 202), la requête d’origine est encore en cours. Attendez et relancez avec la même clé.

Pattern d’exemple :

```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) {
    // Safe to retry with the same key
    return await client.projects.create(body, { idempotencyKey: key });
  }
  throw error;
}
```

Voir [API idempotency](/fr/api/idempotency) pour le contrat complet.

## Récupération d’erreurs

Branchez en fonction de `error.code` et `error.retryable`. Les cas courants :

| Code                                  | Cause                                                 | Action                                                    |
| ------------------------------------- | ----------------------------------------------------- | --------------------------------------------------------- |
| `INVALID_REQUEST`                     | Le body de requête a échoué la validation de schéma.  | Corrigez le payload. Pas de relance.                      |
| `UNAUTHORIZED`                        | Clé API manquante ou invalide.                        | Remontez au demandeur. Pas de relance.                    |
| `NOT_FOUND`                           | La ressource n’existe pas ou vous n’y avez pas accès. | Pas de relance.                                           |
| `CONFLICT` (409)                      | Conflit de version ou collision d’idempotence.        | Relancez avec la même clé d’idempotence.                  |
| `TOO_MANY_REQUESTS` (429)             | Rate limit.                                           | Backoff selon `Retry-After` ou 30 s.                      |
| `INTERNAL_SERVER_ERROR` (500)         | Panne serveur transitoire.                            | Relancez jusqu’à 3 fois avec backoff.                     |
| `IDEMPOTENT_REPLAY_IN_PROGRESS` (202) | Requête précédente encore en cours.                   | Attendez et relancez avec la même clé.                    |
| `TASK_FAILED`                         | La tâche async s’est terminée en échec.               | Remontez `error.task.error` au demandeur. Pas de relance. |
| `TASK_TIMED_OUT`                      | La tâche async a dépassé son budget.                  | Relance possible une fois en toute sécurité.              |

## Découvrir les champs modifiables

Avant de modifier des presets, récupérez le schéma de preset afin que le modèle connaisse les champs valides et les types de valeurs :

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

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

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

Pour les paramètres de projet, préférez lire d’abord les paramètres actuels du projet, puis soumettre un body de mise à jour minimal via `youka project settings <id> --body ...`.

Récupérez-le une fois par session d’agent et mettez le résultat en cache.

## Agents en parallèle

Lorsque plusieurs agents s’exécutent en concurrence sur le même compte :

* Scopez les clés d’idempotence à la fois à l’identité de l’agent **et** à la mutation logique : `agent-${agentId}-create-${sourceHash}`. Cela évite qu’une relance d’un agent entre en collision avec une nouvelle requête d’un autre agent.
* Gardez les lectures sans limite — les requêtes `GET` sont peu coûteuses et sans effets de bord.
* Utilisez une seule file pour `POST /projects/{projectId}/exports` par projet si vous avez besoin d’un historique d’exports ordonné. Sinon, les exports peuvent arriver dans le désordre.

## Et ensuite

* [CLI global options](/fr/cli/global-options) — tous les flags disponibles pour les agents
* [SDK errors](/fr/sdk/errors) — référence complète des classes d’erreurs
* [API async jobs](/fr/api/async-jobs) — le contrat de polling
* [API idempotency](/fr/api/idempotency) — le contrat d’idempotence
