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

# Agent API

> Gestiona sesiones de Krea Agent por HTTP con tu clave de API: inicia una sesión, espera a que termine un turno, lee sus resultados y envía seguimientos.

Usa la Agent API para encargarle una tarea a Krea Agent desde tu propia aplicación. Las solicitudes y respuestas usan campos JSON en camelCase. El agente trabaja en segundo plano mientras tu aplicación lee su progreso y sus resultados.

| Endpoint | Propósito |
| - | - |
| [`POST /agent/send-message`](/docs/api-reference/agent/send-agent-message) | Inicia una sesión o envía un turno de seguimiento. |
| [`GET /agent/session/{sessionId}`](/docs/api-reference/agent/get-agent-session) | Lee la sesión actual sin esperar. |
| [`POST /agent/wait-for-session`](/docs/api-reference/agent/wait-for-agent-session) | Espera a que termine un turno, hasta un tiempo límite. |

<Warning>
  El agente trabaja en segundo plano. No hace preguntas, y las solicitudes de confirmación de costos y permisos se aprueban automáticamente. Incluye todos los requisitos y restricciones en tu prompt. Revisa la tarea antes de enviarla.
</Warning>

## Autenticación, acceso y facturación

Envía `Authorization: Bearer KREA_API_KEY` con cada solicitud a `https://api.krea.ai`. Las claves de API personales, de servicio y heredadas usan la [autenticación estándar de la API pública](/docs/es/developers/api-keys-and-billing).

Solo puedes leer o continuar sesiones que pertenezcan al usuario autenticado en el workspace autenticado. Conocer el ID de una sesión no otorga acceso. Los archivos de Krea adjuntos también deben ser accesibles para ese usuario en ese workspace.

<Info>
  Los turnos del agente usan el saldo de unidades de cómputo del workspace. **No** usan el saldo de API. Los derechos del plan de Agent y los límites de mensajes del plan Free siguen aplicándose. Consulta [Planes, acceso y créditos de Agent](/docs/es/user-guide/agent/plans-and-credits).
</Info>

Cada respuesta incluye una `url` con la que puedes abrir la sesión en la app de Krea si tienes el acceso adecuado a la cuenta y al workspace.

## Iniciar una sesión y esperar su resultado

Primero, define `KREA_API_KEY` en tu entorno. Elige Bash con `curl` y `jq`, Python con `requests` o Node.js con `fetch` integrado o el SDK de Krea.

<Steps>
  <Step title="Envía el primer turno">
    Omite `sessionId` para crear una sesión. Guarda el `sessionId` y el `runId` devueltos. La respuesta llega de inmediato con `status: "running"`.
  </Step>

  <Step title="Espera a que termine este turno">
    Pasa ambos IDs a `wait-for-session`. Si `timedOut` es `true`, vuelve a llamarlo con los mismos IDs. Agotar el tiempo de espera no cancela el turno.
  </Step>

  <Step title="Lee el resultado">
    Comprueba `status` cuando `finished` sea `true`. Revisa `text`, `media` y cualquier `error`, o abre la `url` devuelta.
  </Step>
</Steps>

<CodeGroup>
  ```bash cURL theme={"theme":{"light":"github-light-default","dark":"vesper"}}
  set -euo pipefail
  : "${KREA_API_KEY:?Set your Krea API key}"

  START=$(curl --fail-with-body --silent --show-error --max-time 60 \
    https://api.krea.ai/agent/send-message \
    -H "Authorization: Bearer $KREA_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "prompt": "Create three square product images for a ceramic coffee mug on a neutral studio background. Use no text or logos.",
      "name": "Coffee mug campaign"
    }')

  SESSION_ID=$(printf '%s' "$START" | jq -er '.sessionId')
  RUN_ID=$(printf '%s' "$START" | jq -er '.runId')
  printf '%s' "$START" | jq -r '.url'

  DEADLINE=$((SECONDS + 300))

  while (( SECONDS < DEADLINE - 10 )); do
    WAIT_SECONDS=$((DEADLINE - SECONDS - 10))
    if (( WAIT_SECONDS > 60 )); then WAIT_SECONDS=60; fi
    WAIT_BODY=$(jq -n --arg sessionId "$SESSION_ID" --arg runId "$RUN_ID" \
      --argjson timeoutSeconds "$WAIT_SECONDS" \
      '{sessionId: $sessionId, runId: $runId, timeoutSeconds: $timeoutSeconds}')
    RESULT=$(curl --fail-with-body --silent --show-error --max-time "$((WAIT_SECONDS + 10))" \
      https://api.krea.ai/agent/wait-for-session \
      -H "Authorization: Bearer $KREA_API_KEY" \
      -H "Content-Type: application/json" \
      -d "$WAIT_BODY")
    printf '%s' "$RESULT" | jq '{status, finished, timedOut, text, media, error, url}'
    if printf '%s' "$RESULT" | jq -e '.finished' > /dev/null; then
      if printf '%s' "$RESULT" | jq -e '.status == "completed"' > /dev/null; then
        exit 0
      fi
      printf '%s' "$RESULT" | jq -r '"Turn ended: \(.status). \(.error // "No error details")"' >&2
      exit 1
    fi
  done

  printf 'Wait budget exhausted; the turn continues. Resume waiting with sessionId=%s runId=%s\n' \
    "$SESSION_ID" "$RUN_ID" >&2
  exit 1
  ```

  ```python Python theme={"theme":{"light":"github-light-default","dark":"vesper"}}
  import json
  import os
  import time
  import requests

  api = "https://api.krea.ai"
  headers = {"Authorization": f"Bearer {os.environ['KREA_API_KEY']}"}

  response = requests.post(
      f"{api}/agent/send-message",
      headers=headers,
      json={
          "prompt": "Create three square product images for a ceramic coffee mug on a neutral studio background. Use no text or logos.",
          "name": "Coffee mug campaign",
      },
      timeout=60,
  )
  response.raise_for_status()
  start = response.json()
  session_id, run_id = start["sessionId"], start["runId"]
  print(start["url"])

  deadline = time.monotonic() + 300
  while True:
      wait_seconds = min(60, int(deadline - time.monotonic()) - 10)
      if wait_seconds < 1:
          raise TimeoutError(
              "Wait budget exhausted; the turn continues. Resume waiting with "
              f"sessionId={session_id} runId={run_id}"
          )
      response = requests.post(
          f"{api}/agent/wait-for-session",
          headers=headers,
          json={
              "sessionId": session_id,
              "runId": run_id,
              "timeoutSeconds": wait_seconds,
          },
          timeout=wait_seconds + 10,
      )
      response.raise_for_status()
      result = response.json()
      print(json.dumps(result, indent=2))
      if result["finished"]:
          if result["status"] != "completed":
              raise RuntimeError(
                  f"Turn ended: {result['status']}. {result.get('error', 'No error details')}"
              )
          break
  ```

  ```javascript Node.js theme={"theme":{"light":"github-light-default","dark":"vesper"}}
  import { performance } from "node:perf_hooks";

  const token = process.env.KREA_API_KEY;
  if (!token) throw new Error("Set your Krea API key");
  const api = "https://api.krea.ai";

  async function post(path, body, timeoutMs) {
    const response = await fetch(`${api}${path}`, {
      method: "POST",
      headers: {
        Authorization: `Bearer ${token}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify(body),
      signal: AbortSignal.timeout(timeoutMs),
    });
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${await response.text()}`);
    }
    return response.json();
  }

  const start = await post("/agent/send-message", {
    prompt: "Create three square product images for a ceramic coffee mug on a neutral studio background. Use no text or logos.",
    name: "Coffee mug campaign",
  }, 60_000);
  const { sessionId, runId } = start;
  console.log(start.url);

  const deadline = performance.now() + 300_000;
  while (true) {
    const timeoutSeconds = Math.min(60, Math.floor((deadline - performance.now()) / 1000) - 10);
    if (timeoutSeconds < 1) {
      throw new Error(
        `Wait budget exhausted; the turn continues. Resume waiting with sessionId=${sessionId} runId=${runId}`,
      );
    }
    const result = await post("/agent/wait-for-session", {
      sessionId,
      runId,
      timeoutSeconds,
    }, (timeoutSeconds + 10) * 1000);
    console.log(JSON.stringify(result, null, 2));
    if (result.finished) {
      if (result.status !== "completed") {
        throw new Error(`Turn ended: ${result.status}. ${result.error ?? "No error details"}`);
      }
      break;
    }
  }
  ```

  ```javascript Node.js (SDK) theme={"theme":{"light":"github-light-default","dark":"vesper"}}
  import { performance } from "node:perf_hooks";
  import { Krea } from "@krea-ai/sdk";

  const token = process.env.KREA_API_KEY;
  if (!token) throw new Error("Set your Krea API key");
  const krea = new Krea({ apiKey: token });

  const start = await krea.requestRaw("/agent/send-message", {
    method: "POST",
    retry: false,
    signal: AbortSignal.timeout(60_000),
    body: {
      prompt: "Create three square product images for a ceramic coffee mug on a neutral studio background. Use no text or logos.",
      name: "Coffee mug campaign",
    },
  });
  const { sessionId, runId } = start;
  console.log(start.url);

  const deadline = performance.now() + 300_000;
  while (true) {
    const timeoutSeconds = Math.min(60, Math.floor((deadline - performance.now()) / 1000) - 15);
    if (timeoutSeconds < 1) {
      throw new Error(
        `Wait budget exhausted; the turn continues. Resume waiting with sessionId=${sessionId} runId=${runId}`,
      );
    }
    const result = await krea.requestRaw("/agent/wait-for-session", {
      method: "POST",
      retry: false,
      signal: AbortSignal.timeout((timeoutSeconds + 15) * 1000),
      body: { sessionId, runId, timeoutSeconds },
    });
    console.log(JSON.stringify(result, null, 2));
    if (result.finished) {
      if (result.status !== "completed") {
        throw new Error(`Turn ended: ${result.status}. ${result.error ?? "No error details"}`);
      }
      break;
    }
  }
  ```
</CodeGroup>

Para Python, instala `requests` con `pip install requests`. Para Node.js, usa Node.js 22+ y guarda el ejemplo como `example.mjs`. El ejemplo del SDK requiere `npm install @krea-ai/sdk` y usa `requestRaw` para llamar a los endpoints HTTP.

Estos ejemplos envían un mensaje y esperan hasta cinco minutos. Se detienen ante errores HTTP y turnos fallidos o cancelados. Nunca reintentan un envío automáticamente. Si una solicitud de envío agota su tiempo de espera, revisa la sesión en Krea antes de volver a enviarla; es posible que la primera solicitud ya haya iniciado un turno.

Cuando se agota el tiempo de espera, el turno continúa en segundo plano. Guarda los IDs de sesión y de ejecución que se imprimen para reanudar la espera más tarde.

`timeoutSeconds` es un entero de `1` a `300` y su valor predeterminado es `60`. Mantén el tiempo de espera de tu cliente HTTP por encima de la espera solicitada. Pasa siempre el `runId` más reciente al esperar después de un envío, para que el estado terminal de un turno anterior no se confunda con el del nuevo turno.

### Leer sin esperar

Usa `GET /agent/session/{sessionId}` para obtener una instantánea de la sesión actual:

```bash cURL theme={"theme":{"light":"github-light-default","dark":"vesper"}}
curl --fail-with-body --silent --show-error \
  "https://api.krea.ai/agent/session/$SESSION_ID" \
  -H "Authorization: Bearer $KREA_API_KEY"
```

### Continuar la sesión

Cuando termine el turno, envía otro mensaje con su `sessionId`:

```bash cURL theme={"theme":{"light":"github-light-default","dark":"vesper"}}
FOLLOW_UP=$(curl --fail-with-body --silent --show-error \
  https://api.krea.ai/agent/send-message \
  -H "Authorization: Bearer $KREA_API_KEY" \
  -H "Content-Type: application/json" \
  -d "$(jq -n --arg sessionId "$SESSION_ID" \
    '{sessionId: $sessionId, prompt: "Make a landscape variation of the first image."}')")

# Use this new runId in the next wait-for-session request.
RUN_ID=$(printf '%s' "$FOLLOW_UP" | jq -er '.runId')
```

Una sesión ejecuta un turno a la vez. Enviar otro mensaje mientras hay un turno en curso devuelve `409` con `code: "conflict"`.

## Entradas y archivos adjuntos

`send-message` acepta estos campos. Consulta la [referencia](/docs/api-reference/agent/send-agent-message) para ver el enum completo de modelos y los esquemas.

| Campo | Comportamiento |
| - | - |
| `sessionId` | UUID opcional. Omítelo para una sesión nueva; inclúyelo para continuar una sesión propia. |
| `prompt` | Cadena de hasta 100,000 caracteres. Valor predeterminado: `""`. Se requiere un prompt no vacío o al menos un archivo adjunto. |
| `attachments` | Hasta 20 archivos adjuntos. Valor predeterminado: `[]`. Cada uno necesita `url` y puede incluir `name` y `contentType`. |
| `model` | ID opcional del LLM del agente. Omítelo para usar Auto. Un modelo fijado debe estar incluido en el plan del workspace. |
| `effort` | Opcional: `fast`, `default`, `high` o `xhigh`. Las sesiones nuevas usan `default` de forma predeterminada; omítelo para conservar el esfuerzo de una sesión existente. |
| `name` | Nombre opcional de la sesión, solo para sesiones nuevas. Se recortan los espacios, no puede estar vacío y admite hasta 120 caracteres. |
| `desktopAppId` | UUID opcional que identifica una app de escritorio conectada. Ejecuta este turno dentro de esa app. La app debe estar disponible para el usuario autenticado y el workspace. |

La `url` de un archivo adjunto acepta una URL HTTP(S) accesible o un URI autorizado de Krea Files, como `file:550e8400-e29b-41d4-a716-446655440000`. Los campos opcionales `name` y `contentType` son cadenas no vacías, con los espacios recortados, de hasta 255 caracteres. No se admiten rutas locales del usuario ni IDs `file_` de OpenAI. Transfiere primero el archivo real; un ID en el texto del prompt no transfiere su contenido.

El agente no hereda la conversación ni los archivos adjuntos de tu aplicación. Adjunta los archivos de referencia que no sean accesibles de otra forma. No necesitas repetir las URLs utilizables que ya estén en el prompt, en el contexto existente de Krea o en archivos anteriores de la sesión.

## Resultados de la sesión

`send-message` devuelve `sessionId`, `threadId`, `runId`, `status` (siempre `"running"`) y `url`.

`GET /agent/session/{sessionId}` y `wait-for-session` devuelven la siguiente vista de la sesión. Solo `wait-for-session` añade el campo obligatorio `timedOut`.

| Campo | Significado |
| - | - |
| `sessionId`, `threadId` | Identificadores de la sesión y del hilo raíz. |
| `runId` | Identificador del turno actual, cuando está disponible. |
| `status` | `not_started`, `running`, `completed`, `failed` o `cancelled`. |
| `finished` | `true` para un turno terminal. Si se proporciona `runId` en una espera, el turno terminal también debe coincidir con ese ID. |
| `text` | Texto del mensaje más reciente del asistente. |
| `media` | Array de contenido multimedia producido por la sesión. El orden no es significativo. |
| `error` | Texto de error opcional de la sesión. |
| `url` | Enlace a la sesión en la app de Krea. |
| `timedOut` | Solo en respuestas de espera: `true` si el plazo venció antes de que terminara el turno solicitado. |

Cada elemento de `media` puede representar una generación (`jobId` y `mediaKind` opcional: `image`, `video`, `audio` o `3d`), contenido multimedia realojado (`url`, con `mimeType` opcional) o un archivo de Krea (`uri`, `name`, `mimeType`). Obtén los detalles de la generación mediante `GET /jobs/{jobId}`. Puedes reutilizar el URI de un archivo de Krea como archivo adjunto o abrir la `url` de la sesión para ver sus archivos. El contenido multimedia puede aparecer mientras el turno sigue en curso.

## Errores

Los errores de los endpoints usan `{ "error": "...", "code": "...", "allowedModels": ["..."] }`. Solo `error` es obligatorio. Un turno que falla después de enviarse aparece, en cambio, como `status: "failed"` en una respuesta de sesión exitosa.

| Estado HTTP | Significado |
| - | - |
| `400` | Cuerpo JSON mal formado. |
| `401` | Autenticación ausente o no válida. |
| `402` | Saldo de unidades de cómputo insuficiente en el workspace (`compute_limit`) o se alcanzó el límite de mensajes del plan Free (`free_message_limit`). |
| `403` | El modelo fijado no está incluido en tus derechos (`model_not_entitled`); `allowedModels` enumera los IDs permitidos. |
| `404` | La sesión no existe o no es accesible (`not_found`), o un archivo de Krea adjunto no existe o no es accesible (`attachment_not_found`). |
| `409` | Ya hay un turno en curso (`conflict`). |
| `422` | Entrada no válida, o la app de escritorio seleccionada no está disponible. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.