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

# Agentes de IA

> Reglas operativas y patrones de flujo de trabajo para agentes que llaman a la CLI o la API de Youka

Youka está diseñado para ser controlado por agentes. Cada comando de la CLI devuelve un sobre JSON legible por máquina, cada escritura admite claves de idempotencia, y la API pública expone la misma superficie con la misma semántica. Esta página recopila las reglas operativas que necesita un autor de agentes antes de conectar Youka a un flujo de trabajo.

## Primeros pasos

Si estás configurando un agente por primera vez, instala primero la CLI de Youka y luego instala la skill de karaoke de Youka:

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

Eso le da al agente una skill de Youka lista para usar respaldada por la CLI. Una vez instalada, usa los patrones de flujo de trabajo de abajo para crear videos de karaoke, personalizar el estilo y exportar archivos MP4 de forma segura.

### Indícale a tu agente

Después de instalar la CLI y la skill, puedes darle a tu agente una tarea directa como esta:

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

## Reglas operativas

<CardGroup cols={2}>
  <Card title="Usa siempre --json" icon="code">
    En la CLI, pasa siempre `--json`. En la API, establece siempre `Accept:
            application/json`. Nunca analices la salida para humanos.
  </Card>

  <Card title="Envía siempre una clave de idempotencia" icon="rotate">
    Cada escritura debe llevar una clave de idempotencia estable para que los reintentos tras un timeout
    devuelvan el resultado original en lugar de duplicar el trabajo.
  </Card>

  <Card title="Vuelve a leer el estado duradero" icon="database">
    No confíes en respuestas de mutación obsoletas. Tras una tarea terminal, vuelve a leer el
    proyecto o la exportación para obtener el estado final.
  </Card>

  <Card title="Haz polling con backoff" icon="hourglass">
    Empieza con un intervalo de 2–3 segundos. Aplica backoff exponencial para trabajos largos.
    Respeta las respuestas 429.
  </Card>
</CardGroup>

## Contrato de salida

Cada comando de la CLI en modo `--json` escribe exactamente un sobre en stdout.

Éxito:

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

Fallo:

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

Códigos de salida:

| Code | Meaning                                              | Retry?                       |
| ---- | ---------------------------------------------------- | ---------------------------- |
| `0`  | Éxito.                                               | N/A                          |
| `1`  | Error en tiempo de ejecución (red, API, render).     | Comprueba `error.retryable`. |
| `2`  | Entrada inválida (flags erróneos, payload ilegible). | No — corrige la entrada.     |

## Flujo de trabajo de extremo a extremo

El flujo de trabajo canónico para un agente es: crear un proyecto, esperar, exportar, descargar el resultado. Aquí está el patrón completo con implementaciones tanto de la CLI como del SDK.

<CodeGroup>
  ```bash CLI theme={null}
  # 1. Crea el proyecto y espera a que terminen los stems + la sincronización de letras
  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. Inicia y espera una exportación
  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/es/sdk";

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

  async function createAndExport() {
    // 1. Crea el proyecto y espera a los stems + la sincronización de letras
    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. Inicia y espera una exportación
    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. Descarga el archivo
    await client.exports.download(finalized, {
      output: "./karaoke.mp4",
    });
  }

  createAndExport().catch((error) => {
    if (error instanceof YoukaRequestError && error.retryable) {
      // Reintenta con las mismas claves de idempotencia
    }
    if (error instanceof YoukaTaskError) {
      console.error("Task failed:", error.code, error.task.error);
    }
    throw error;
  });
  ```
</CodeGroup>

## Guía de polling

La mayoría de las escrituras devuelven handles de operación en el SDK. Prefiere `client.projects.wait(...)` y `client.exports.wait(...)`, y baja a `client.tasks.*` solo cuando necesites explícitamente acceso de bajo nivel a tareas.

| Job type                                                | Recommended initial interval | Max wait |
| ------------------------------------------------------- | ---------------------------- | -------- |
| Creación de proyecto (stems + sincronización de letras) | 3 s                          | 15 min   |
| Solo separación de stems                                | 3 s                          | 10 min   |
| Solo sincronización de letras                           | 2 s                          | 5 min    |
| Render de exportación                                   | 3 s                          | 30 min   |

En la CLI, `--wait` gestiona el polling por ti. En el SDK, los helpers de espera usan un intervalo de 2 s por defecto y aceptan `pollIntervalMs`.

<Tip>
  Respeta las respuestas 429. En límites de tasa, aplica backoff al menos según el encabezado `Retry-After`
  (o 30 s si no está presente).
</Tip>

## Claves de idempotencia

Cada operación de creación y actualización admite una clave de idempotencia. Reglas:

* Usa una clave **estable, única y determinista** por mutación lógica. Bien: `create-song-${sourceHash}`. Mal: un UUID nuevo por reintento.
* Reutiliza la **misma** clave en los reintentos. El servidor reconoce la repetición y devuelve el resultado original.
* Las claves están acotadas por cuenta y expiran tras 24 horas.
* Si el servidor devuelve `IDEMPOTENT_REPLAY_IN_PROGRESS` (HTTP 202), la solicitud original sigue ejecutándose. Espera y reintenta con la misma clave.

Patrón de ejemplo:

```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) {
    // Es seguro reintentar con la misma clave
    return await client.projects.create(body, { idempotencyKey: key });
  }
  throw error;
}
```

Consulta [API idempotency](/es/api/idempotency) para ver el contrato completo.

## Recuperación de errores

Ramifica en `error.code` y `error.retryable`. Los casos comunes:

| Code                                  | Cause                                                      | Action                                                      |
| ------------------------------------- | ---------------------------------------------------------- | ----------------------------------------------------------- |
| `INVALID_REQUEST`                     | El body de la solicitud no pasó la validación del esquema. | Corrige el payload. Sin reintento.                          |
| `UNAUTHORIZED`                        | Falta la API key o es inválida.                            | Muéstralo al solicitante. Sin reintento.                    |
| `NOT_FOUND`                           | El recurso no existe o no tienes acceso.                   | Sin reintento.                                              |
| `CONFLICT` (409)                      | Conflicto de versión o colisión de idempotencia.           | Reintenta con la misma clave de idempotencia.               |
| `TOO_MANY_REQUESTS` (429)             | Límite de tasa.                                            | Aplica backoff según `Retry-After` o 30 s.                  |
| `INTERNAL_SERVER_ERROR` (500)         | Fallo transitorio del servidor.                            | Reintenta hasta 3 veces con backoff.                        |
| `IDEMPOTENT_REPLAY_IN_PROGRESS` (202) | La solicitud anterior sigue ejecutándose.                  | Espera y reintenta con la misma clave.                      |
| `TASK_FAILED`                         | La tarea asíncrona terminó en fallo.                       | Muéstrale `error.task.error` al solicitante. Sin reintento. |
| `TASK_TIMED_OUT`                      | La tarea asíncrona excedió su presupuesto.                 | Es seguro reintentar una vez.                               |

## Descubrimiento de campos mutables

Antes de mutar presets, obtiene el esquema del preset para que el modelo conozca los campos válidos y los tipos de valor:

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

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

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

Para la configuración del proyecto, es preferible leer primero la configuración actual del proyecto y luego enviar un body de actualización mínimo mediante `youka project settings <id> --body ...`.

Obténlo una vez por sesión del agente y cachea el resultado.

## Agentes en paralelo

Cuando varios agentes se ejecutan de forma concurrente contra la misma cuenta:

* Acota las claves de idempotencia tanto a **la identidad del agente** como a la mutación lógica: `agent-${agentId}-create-${sourceHash}`. Esto evita que el reintento de un agente colisione con la solicitud nueva de otro agente.
* Mantén las lecturas sin restricciones — las solicitudes `GET` son baratas y no tienen efectos secundarios.
* Usa una sola cola para `POST /projects/{projectId}/exports` por proyecto si necesitas un historial de exportaciones ordenado. De lo contrario, las exportaciones pueden llegar fuera de orden.

## Qué sigue

* [CLI global options](/es/cli/global-options) — todas las flags disponibles para agentes
* [SDK errors](/es/sdk/errors) — referencia completa de clases de error
* [API async jobs](/es/api/async-jobs) — el contrato de polling
* [API idempotency](/es/api/idempotency) — el contrato de idempotencia
