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

> API 키로 HTTP를 통해 Krea Agent 세션을 시작하고, 턴 완료를 기다려 결과를 읽고, 후속 메시지를 보내는 방법을 안내합니다.

Agent API를 사용하면 자체 애플리케이션에서 Krea Agent에 작업을 맡길 수 있습니다. 요청과 응답은 camelCase JSON 필드를 사용합니다. 에이전트는 백그라운드에서 작업하며, 애플리케이션은 그 진행 상황과 결과를 읽습니다.

| 엔드포인트 | 용도 |
| - | - |
| [`POST /agent/send-message`](/docs/api-reference/agent/send-agent-message) | 세션을 시작하거나 후속 턴을 제출합니다. |
| [`GET /agent/session/{sessionId}`](/docs/api-reference/agent/get-agent-session) | 기다리지 않고 현재 세션을 읽습니다. |
| [`POST /agent/wait-for-session`](/docs/api-reference/agent/wait-for-agent-session) | 타임아웃까지 턴이 끝나기를 기다립니다. |

<Warning>
  에이전트는 백그라운드에서 작업합니다. 질문을 하지 않으며, 비용 및 권한 확인 요청은 자동으로 승인됩니다. 모든 요구 사항과 제약 조건을 프롬프트에 포함하세요. 제출하기 전에 작업 내용을 검토하세요.
</Warning>

## 인증, 액세스 및 청구

`https://api.krea.ai`로 보내는 모든 요청에 `Authorization: Bearer KREA_API_KEY`를 포함하세요. 개인, 서비스 및 레거시 API 키는 표준 [공개 API 인증](/docs/ko/developers/api-keys-and-billing)을 사용합니다.

인증된 워크스페이스에서 인증된 호출자가 소유한 세션만 읽거나 이어갈 수 있습니다. 세션 ID를 안다고 해서 액세스 권한이 부여되지는 않습니다. Krea 파일 첨부도 해당 워크스페이스에서 해당 호출자가 액세스할 수 있어야 합니다.

<Info>
  에이전트 턴은 워크스페이스의 컴퓨트 유닛 잔액을 사용합니다. API 잔액은 **사용하지 않습니다**. 에이전트 플랜 권한과 Free 플랜 메시지 한도는 그대로 적용됩니다. [에이전트 플랜, 액세스 및 크레딧](/docs/ko/user-guide/agent/plans-and-credits)을 참조하세요.
</Info>

각 응답에는 `url`이 포함되어 있으며, 적절한 계정 및 워크스페이스 액세스 권한이 있으면 이 URL로 Krea 앱에서 세션을 열 수 있습니다.

## 세션을 시작하고 결과 기다리기

먼저 환경에 `KREA_API_KEY`를 설정하세요. `curl`과 `jq`를 사용하는 Bash, `requests`를 사용하는 Python, 또는 내장 `fetch`나 Krea SDK를 사용하는 Node.js 중에서 선택하세요.

<Steps>
  <Step title="첫 번째 턴 제출">
    세션을 만들려면 `sessionId`를 생략하세요. 반환된 `sessionId`와 `runId`를 저장하세요. 응답은 `status: "running"`과 함께 즉시 반환됩니다.
  </Step>

  <Step title="이 턴 기다리기">
    두 ID를 모두 `wait-for-session`에 전달하세요. `timedOut`이 `true`이면 같은 ID로 다시 호출하세요. 타임아웃이 발생해도 턴은 취소되지 않습니다.
  </Step>

  <Step title="결과 읽기">
    `finished`가 `true`이면 `status`를 확인하세요. `text`, `media` 및 `error`가 있는지 살펴보거나, 반환된 `url`을 여세요.
  </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>

Python의 경우 `pip install requests`로 `requests`를 설치하세요. Node.js의 경우 Node.js 22 이상을 사용하고 예제를 `example.mjs`로 저장하세요. SDK 예제는 `npm install @krea-ai/sdk`가 필요하며, `requestRaw`를 사용해 HTTP 엔드포인트를 호출합니다.

이 예제들은 메시지 하나를 제출하고 최대 5분 동안 기다립니다. HTTP 오류가 발생하거나 턴이 실패 또는 취소되면 중단됩니다. 전송을 자동으로 재시도하지 않습니다. 전송 요청이 타임아웃되면 다시 제출하기 전에 Krea에서 세션을 확인하세요. 첫 번째 요청이 이미 턴을 시작했을 수 있습니다.

대기 시간 예산이 소진되어도 턴은 백그라운드에서 계속 진행됩니다. 나중에 대기를 재개할 수 있도록 출력된 세션 ID와 실행 ID를 저장하세요.

`timeoutSeconds`는 `1`에서 `300` 사이의 정수이며 기본값은 `60`입니다. HTTP 클라이언트 타임아웃은 요청한 대기 시간보다 길게 설정하세요. 전송 후 기다릴 때는 항상 최신 `runId`를 전달하여, 이전 턴의 종료 상태를 새 턴의 상태로 오인하지 않도록 하세요.

### 기다리지 않고 읽기

`GET /agent/session/{sessionId}`를 사용해 현재 세션의 스냅샷을 가져오세요:

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

### 세션 이어가기

턴이 끝나면 해당 `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')
```

세션은 한 번에 하나의 턴만 실행합니다. 턴이 실행 중일 때 다른 메시지를 보내면 `code: "conflict"`와 함께 `409`가 반환됩니다.

## 입력 및 첨부 파일

`send-message`는 다음 필드를 받습니다. 전체 모델 enum과 스키마는 [레퍼런스](/docs/api-reference/agent/send-agent-message)를 참조하세요.

| 필드 | 동작 |
| - | - |
| `sessionId` | 선택 사항인 UUID. 새 세션이면 생략하고, 소유한 세션을 이어가려면 포함하세요. |
| `prompt` | 최대 100,000자의 문자열. 기본값은 `""`입니다. 비어 있지 않은 프롬프트 또는 하나 이상의 첨부 파일이 필요합니다. |
| `attachments` | 최대 20개의 첨부 파일. 기본값은 `[]`입니다. 각 항목에는 `url`이 필요하며 `name`과 `contentType`을 포함할 수 있습니다. |
| `model` | 선택 사항인 에이전트 LLM ID. Auto를 사용하려면 생략하세요. 고정한 모델은 워크스페이스 플랜에 포함되어 있어야 합니다. |
| `effort` | 선택 사항: `fast`, `default`, `high` 또는 `xhigh`. 새 세션의 기본값은 `default`이며, 기존 세션의 effort를 유지하려면 생략하세요. |
| `name` | 선택 사항인 세션 이름으로, 새 세션에만 적용됩니다. 앞뒤 공백이 제거되며, 비어 있지 않고 최대 120자여야 합니다. |
| `desktopAppId` | 연결된 데스크톱 앱을 식별하는 선택 사항인 UUID. 이 턴을 해당 앱 안에서 실행합니다. 앱은 인증된 호출자와 워크스페이스에서 사용 가능해야 합니다. |

첨부 파일 `url`에는 액세스 가능한 HTTP(S) URL 또는 `file:550e8400-e29b-41d4-a716-446655440000` 같은 승인된 Krea Files URI를 사용할 수 있습니다. 선택 사항인 `name`과 `contentType`은 앞뒤 공백이 제거된, 비어 있지 않은 최대 255자의 문자열입니다. 호출자 로컬 경로와 OpenAI `file_` ID는 지원되지 않습니다. 먼저 실제 파일을 전송하세요. 프롬프트 텍스트에 ID를 넣는다고 해서 파일 내용이 전송되지는 않습니다.

에이전트는 애플리케이션의 대화나 첨부 파일을 물려받지 않습니다. 달리 액세스할 수 없는 레퍼런스 파일은 첨부하세요. 프롬프트에 포함된 사용 가능한 URL, 기존 Krea 컨텍스트, 이전 세션 파일은 다시 첨부할 필요가 없습니다.

## 세션 결과

`send-message`는 `sessionId`, `threadId`, `runId`, `status`(항상 `"running"`), `url`을 반환합니다.

`GET /agent/session/{sessionId}`와 `wait-for-session`은 다음 세션 뷰를 반환합니다. `wait-for-session`만 필수 필드인 `timedOut`을 추가합니다.

| 필드 | 의미 |
| - | - |
| `sessionId`, `threadId` | 세션 및 루트 스레드 식별자. |
| `runId` | 사용 가능한 경우, 현재 턴 식별자. |
| `status` | `not_started`, `running`, `completed`, `failed` 또는 `cancelled`. |
| `finished` | 종료된 턴이면 `true`. 대기 요청에 `runId`를 지정한 경우, 종료된 턴이 해당 ID와도 일치해야 합니다. |
| `text` | 최신 어시스턴트 메시지 텍스트. |
| `media` | 세션에서 생성된 미디어 배열. 순서는 의미가 없습니다. |
| `error` | 세션에 대한 선택적 오류 텍스트. |
| `url` | Krea 앱의 세션 링크. |
| `timedOut` | 대기 응답 전용: 요청한 턴이 끝나기 전에 기한이 지나면 `true`. |

각 `media` 항목은 생성물(`jobId` 및 선택 사항인 `mediaKind`: `image`, `video`, `audio` 또는 `3d`), 재호스팅된 미디어(`url`, 선택 사항인 `mimeType` 포함), 또는 Krea 파일(`uri`, `name`, `mimeType`)을 나타낼 수 있습니다. 생성 세부 정보는 `GET /jobs/{jobId}`로 가져오세요. Krea 파일 URI는 첨부 파일로 재사용하거나, 세션의 `url`을 열어 파일을 확인할 수 있습니다. 미디어는 턴이 아직 실행 중일 때도 나타날 수 있습니다.

## 오류

엔드포인트 오류는 `{ "error": "...", "code": "...", "allowedModels": ["..."] }` 형식을 사용합니다. `error`만 필수입니다. 제출 후 실패한 턴은 대신 성공한 세션 응답에서 `status: "failed"`로 나타납니다.

| HTTP 상태 | 의미 |
| - | - |
| `400` | 잘못된 형식의 JSON 본문. |
| `401` | 인증 누락 또는 잘못된 인증. |
| `402` | 워크스페이스의 컴퓨트 유닛 잔액 부족(`compute_limit`) 또는 Free 플랜 메시지 한도 도달(`free_message_limit`). |
| `403` | 고정한 모델에 대한 권한 없음(`model_not_entitled`). `allowedModels`에 허용된 ID가 나열됩니다. |
| `404` | 세션이 없거나 액세스할 수 없음(`not_found`), 또는 Krea 파일 첨부가 없거나 액세스할 수 없음(`attachment_not_found`). |
| `409` | 이미 진행 중인 턴이 있음(`conflict`). |
| `422` | 잘못된 입력, 또는 선택한 데스크톱 앱을 사용할 수 없음. |


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