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

> Gestisci le sessioni di Krea Agent via HTTP con la tua chiave API: avvia una sessione, attendi la fine di un turno, leggi i risultati e invia follow-up.

Usa la Agent API per assegnare un compito a Krea Agent dalla tua applicazione. Richieste e risposte usano campi JSON in camelCase. L'agente lavora in background mentre la tua applicazione ne legge l'avanzamento e i risultati.

| Endpoint | Scopo |
| - | - |
| [`POST /agent/send-message`](/docs/api-reference/agent/send-agent-message) | Avvia una sessione o invia un turno di follow-up. |
| [`GET /agent/session/{sessionId}`](/docs/api-reference/agent/get-agent-session) | Legge la sessione corrente senza attendere. |
| [`POST /agent/wait-for-session`](/docs/api-reference/agent/wait-for-agent-session) | Attende la fine di un turno, fino a un timeout. |

<Warning>
  L'agente lavora in background. Non fa domande, e le richieste di conferma su costi e permessi vengono approvate automaticamente. Includi tutti i requisiti e i vincoli nel tuo prompt. Rivedi il compito prima di inviarlo.
</Warning>

## Autenticazione, accesso e fatturazione

Invia `Authorization: Bearer KREA_API_KEY` con ogni richiesta a `https://api.krea.ai`. Le chiavi API personali, di servizio e legacy usano l'[autenticazione standard dell'API pubblica](/docs/it/developers/api-keys-and-billing).

Puoi leggere o continuare solo le sessioni di proprietà dell'utente autenticato nel workspace autenticato. Conoscere l'ID di una sessione non dà accesso. Anche i file Krea allegati devono essere accessibili a quell'utente in quel workspace.

<Info>
  I turni dell'agente usano il saldo di unità di calcolo del workspace. **Non** usano il saldo API. Restano validi i diritti del piano Agent e i limiti di messaggi del piano Free. Vedi [Piani, accesso e crediti di Agent](/docs/it/user-guide/agent/plans-and-credits).
</Info>

Ogni risposta include un `url` con cui puoi aprire la sessione nell'app Krea, se disponi dell'accesso appropriato all'account e al workspace.

## Avviare una sessione e attenderne il risultato

Per prima cosa, imposta `KREA_API_KEY` nel tuo ambiente. Scegli Bash con `curl` e `jq`, Python con `requests` oppure Node.js con `fetch` integrato o l'SDK di Krea.

<Steps>
  <Step title="Invia il primo turno">
    Ometti `sessionId` per creare una sessione. Salva il `sessionId` e il `runId` restituiti. La risposta arriva subito con `status: "running"`.
  </Step>

  <Step title="Attendi la fine di questo turno">
    Passa entrambi gli ID a `wait-for-session`. Se `timedOut` è `true`, richiamalo con gli stessi ID. Un timeout non annulla il turno.
  </Step>

  <Step title="Leggi il risultato">
    Controlla `status` quando `finished` è `true`. Esamina `text`, `media` ed eventuali `error`, oppure apri l'`url` restituito.
  </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>

Per Python, installa `requests` con `pip install requests`. Per Node.js, usa Node.js 22+ e salva l'esempio come `example.mjs`. L'esempio con l'SDK richiede `npm install @krea-ai/sdk` e usa `requestRaw` per chiamare gli endpoint HTTP.

Questi esempi inviano un messaggio e attendono fino a cinque minuti. Si fermano in caso di errori HTTP e di turni falliti o annullati. Non ritentano mai un invio automaticamente. Se una richiesta di invio va in timeout, controlla la sessione in Krea prima di inviarla di nuovo: la prima richiesta potrebbe aver già avviato un turno.

Quando il tempo di attesa scade, il turno continua in background. Salva gli ID di sessione e di esecuzione stampati per riprendere l'attesa in seguito.

`timeoutSeconds` è un intero da `1` a `300` e il valore predefinito è `60`. Mantieni il timeout del tuo client HTTP più lungo dell'attesa richiesta. Passa sempre il `runId` più recente quando attendi dopo un invio, così lo stato terminale di un turno precedente non viene scambiato per quello del nuovo turno.

### Leggere senza attendere

Usa `GET /agent/session/{sessionId}` per ottenere un'istantanea della sessione corrente:

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

### Continuare la sessione

Al termine del turno, invia un altro messaggio con il relativo `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 sessione esegue un turno alla volta. Inviare un altro messaggio mentre un turno è in corso restituisce `409` con `code: "conflict"`.

## Input e allegati

`send-message` accetta questi campi. Consulta il [riferimento](/docs/api-reference/agent/send-agent-message) per l'enum completo dei modelli e gli schemi.

| Campo | Comportamento |
| - | - |
| `sessionId` | UUID facoltativo. Omettilo per una nuova sessione; includilo per continuare una sessione di tua proprietà. |
| `prompt` | Stringa di massimo 100.000 caratteri. Valore predefinito: `""`. È richiesto un prompt non vuoto o almeno un allegato. |
| `attachments` | Fino a 20 allegati. Valore predefinito: `[]`. Ciascuno richiede `url` e può includere `name` e `contentType`. |
| `model` | ID facoltativo dell'LLM dell'agente. Omettilo per usare Auto. Un modello fissato deve essere incluso nel piano del workspace. |
| `effort` | Facoltativo: `fast`, `default`, `high` o `xhigh`. Le nuove sessioni usano `default` come predefinito; omettilo per mantenere l'effort di una sessione esistente. |
| `name` | Nome facoltativo della sessione, solo per nuove sessioni. Gli spazi iniziali e finali vengono rimossi; non può essere vuoto e può contenere fino a 120 caratteri. |
| `desktopAppId` | UUID facoltativo che identifica un'app desktop connessa. Esegue questo turno all'interno di quell'app. L'app deve essere disponibile per l'utente autenticato e il workspace. |

L'`url` di un allegato accetta un URL HTTP(S) accessibile o un URI autorizzato di Krea Files, come `file:550e8400-e29b-41d4-a716-446655440000`. I campi facoltativi `name` e `contentType` sono stringhe non vuote, senza spazi iniziali e finali, di massimo 255 caratteri. I percorsi locali dell'utente e gli ID `file_` di OpenAI non sono supportati. Trasferisci prima il file vero e proprio: un ID nel testo del prompt non ne trasferisce il contenuto.

L'agente non eredita la conversazione né gli allegati della tua applicazione. Allega i file di riferimento che non sono accessibili in altro modo. Non è necessario ripetere gli URL utilizzabili già presenti nel prompt, nel contesto Krea esistente o nei file precedenti della sessione.

## Risultati della sessione

`send-message` restituisce `sessionId`, `threadId`, `runId`, `status` (sempre `"running"`) e `url`.

`GET /agent/session/{sessionId}` e `wait-for-session` restituiscono la seguente vista della sessione. Solo `wait-for-session` aggiunge il campo obbligatorio `timedOut`.

| Campo | Significato |
| - | - |
| `sessionId`, `threadId` | Identificatori della sessione e del thread radice. |
| `runId` | Identificatore del turno corrente, quando disponibile. |
| `status` | `not_started`, `running`, `completed`, `failed` o `cancelled`. |
| `finished` | `true` per un turno terminale. Se in un'attesa viene fornito `runId`, il turno terminale deve anche corrispondere a quell'ID. |
| `text` | Testo dell'ultimo messaggio dell'assistente. |
| `media` | Array dei contenuti multimediali prodotti dalla sessione. L'ordine non è significativo. |
| `error` | Testo di errore facoltativo della sessione. |
| `url` | Link alla sessione nell'app Krea. |
| `timedOut` | Solo nelle risposte di attesa: `true` se la scadenza è trascorsa prima della fine del turno richiesto. |

Ogni elemento di `media` può rappresentare una generazione (`jobId` e `mediaKind` facoltativo: `image`, `video`, `audio` o `3d`), un contenuto multimediale ri-ospitato (`url`, con `mimeType` facoltativo) o un file Krea (`uri`, `name`, `mimeType`). Recupera i dettagli della generazione tramite `GET /jobs/{jobId}`. Puoi riutilizzare l'URI di un file Krea come allegato oppure aprire l'`url` della sessione per vederne i file. I contenuti multimediali possono comparire mentre il turno è ancora in corso.

## Errori

Gli errori degli endpoint usano `{ "error": "...", "code": "...", "allowedModels": ["..."] }`. Solo `error` è obbligatorio. Un turno che fallisce dopo l'invio compare invece come `status: "failed"` in una risposta di sessione riuscita.

| Stato HTTP | Significato |
| - | - |
| `400` | Corpo JSON non valido. |
| `401` | Autenticazione mancante o non valida. |
| `402` | Saldo di unità di calcolo insufficiente nel workspace (`compute_limit`) o limite di messaggi del piano Free raggiunto (`free_message_limit`). |
| `403` | Il modello fissato non rientra nei tuoi diritti (`model_not_entitled`); `allowedModels` elenca gli ID consentiti. |
| `404` | La sessione non esiste o non è accessibile (`not_found`), oppure un file Krea allegato non esiste o non è accessibile (`attachment_not_found`). |
| `409` | Un turno è già in corso (`conflict`). |
| `422` | Input non valido, oppure l'app desktop selezionata non è disponibile. |


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