# 작업

> AI 어시스턴트에서 Nodaro 작업을 확인하고, 기다리고, 나열하고, 평가하고, 진단합니다. 작업 엔벨로프, 상태, 보류된 작업, 재시도 가능한 실패, 대체 모델도 다룹니다.

Source: https://nodaro.ai/ko/docs/mcp/tools/jobs

**작업 도구**를 사용하면 어시스턴트가 Nodaro가 대신 처리하는 작업을 추적할 수 있습니다. 거의 모든 생성 도구는 작업을 시작하고 그 ID를 바로 반환합니다. `get_job`과 `wait_for_job`은 작업이 언제 끝나고 결과가 어디에 있는지 알려 줍니다. `list_jobs`는 최근 작업을 나열하고 필터링하며, `rate_job`은 결과를 평가하고, `diagnose_run`은 실패 원인을 설명합니다. 어느 도구도 크레딧이 들지 않습니다.

## 작업 상태
| 상태 | 의미 |
| --- | --- |
| `pending`, `queued`, `processing` | 작업이 대기 중이거나 실행 중입니다. 계속 확인하세요. |
| `pending_review` | 결과는 있지만, 배포 환경이 사람의 검토를 위해 보류하고 있습니다. 계속 확인하고, 작업을 절대 다시 실행하지 마세요. |
| `completed` | 작업이 완료되었습니다. `outputUrl`과 `outputData`에 결과가 있습니다. |
| `failed` | 작업이 실패했습니다. `retryable`과 `guidance`를 읽으세요. |
| `cancelled` | 작업이 취소되었습니다. |

보류된 작업은 검토자가 승인하면 `completed`로, 거부하면 정책상의 이유와 함께 `failed`로 끝납니다. MCP `tasks` API로 작업을 추적하는 클라이언트에는 보류된 작업이 `input_required`로 보입니다. 결정은 검토자의 몫이므로 사용자에게 새 매개변수를 요청하지 마세요.

## 작업 엔벨로프
`get_job`과 `wait_for_job`은 같은 구조화된 결과인 작업 엔벨로프를 반환합니다. `get_asset`도 `input`과 두 크레딧 값을 뺀 같은 결과를 반환합니다.

| 필드 | 담는 내용 |
| --- | --- |
| `jobId`, `jobType` | 작업 ID와 작업의 종류 |
| `status`, `progress` | 위의 상태와 실행 중의 진행률 |
| `assetKind` | `image`, `video`, `audio` 중 하나. 텍스트나 데이터 결과에서는 null |
| `outputUrl` | 완성된 이미지, 동영상, 오디오 |
| `width`, `height` | 작업이 기록한 경우 출력의 크기(픽셀). 아래를 참고하세요 |
| `outputData` | 녹취록, 정렬, 분석 같은 구조화된 출력 |
| `input` | 모델에 실제로 보낸 내용(아래 참조) 또는 null |
| `errorMessage` | 실패한 작업의 오류 |
| `credits` | 작업이 접수될 때 예약된 크레딧. 이 금액은 바뀌지 않습니다 |
| `creditsCharged` | 예약이 정산된 뒤 작업에 든 비용(텍스트 페이로드의 `data`에서는 `credits_charged`). 아래 참조 |
| `createdAt`, `startedAt`, `completedAt` | 타임스탬프 |
| `retryable`, `guidance`, `suggestedProvider` | 실패, 취소, 보류된 작업에서: 같은 요청이 성공할 수 있는지, 무엇을 할지 알려 주는 한 문장, 그리고 대체 모델이 있을 때 그 모델 |
| `preview` | 미리 보기 품질로 만든 [**EDL 적용**](https://nodaro.ai/docs/nodes/video/apply-edl) 렌더에서 `true`이며, 이때 `outputData.quality`는 `"proxy"`입니다. 최종본이 아니라 검토용 비공개 720p 편집본입니다 |

`creditsCharged`는 `credits`보다 적을 수 있습니다. 예약이 환불되면 `0`이고, 작업이 아직 실행 중이거나 작업이 자체적으로 아무것도 예약하지 않았으면 `null`입니다. 예를 들어 888크레딧을 예약하고 444크레딧으로 정산된 작업은 `credits: 888`, `creditsCharged: 444`로 표시됩니다.

`width`와 `height`는 Nodaro가 크기를 기록하기 시작한 뒤 완료된 이미지 작업과, **이미지 오버레이**, **동영상 오버레이**, **동영상 마스크**, **마스크 합성** 작업에 있습니다. 이미지라면 EXIF 회전을 적용한, 저장된 `outputUrl`의 크기입니다. 다음 단계의 화면 비율을 고를 때 읽으세요. 이미지를 여러 장 만든 작업에는 `outputData.images`도 있으며, 이미지마다 `{ url, width, height }`가 들어 있습니다.

`input`은 요청 중 공개해도 안전한 일부로, 모델이 받은 내용을 확인하기에 충분합니다. 이 목록에 없는 것은 포함되지 않습니다.

- `prompt`: 피커, 피사체, 레퍼런스가 반영된 뒤 최종적으로 만들어진 프롬프트. `userPrompt`: 내가 직접 쓴 문장.
- `negativePrompt`, 그리고 `direction`과 `subject` 피커의 ID.
- `provider`, `model`, `duration`, `resolution`, `aspectRatio`.
- `imageUrl`, `endFrameUrl`, 그리고 레퍼런스 이미지, 동영상, 오디오의 URL.
- 작업의 `type`.

## `get_job`
내 작업 하나를 ID로 가져와 작업 엔벨로프로 반환합니다. 작업이 끝날 때까지 5~10초마다 확인할 때 사용하세요.

**권한:** `jobs:read`. **크레딧:** 무료.

| 매개변수 | 타입 | 설명 |
| --- | --- | --- |
| `job_id` | string | **필수.** 생성 도구가 반환한 ID입니다. |

**반환값:** 작업 엔벨로프입니다.

## `wait_for_job`
내 작업 하나가 끝날 때까지 기다린 다음 작업 엔벨로프를 반환합니다. `get_job`을 짧은 간격으로 반복해서 호출하는 대신 사용하세요.

**권한:** `jobs:read`. **크레딧:** 무료.

| 매개변수 | 타입 | 설명 |
| --- | --- | --- |
| `job_id` | string | **필수.** 기다릴 작업입니다. |
| `timeout_s` | integer | 기다릴 시간(초)으로, 최대 45입니다. 기본값은 `45`입니다. 120까지의 값도 받지만, 그래도 45초만 기다립니다. |

**반환값:** 작업 엔벨로프입니다. MCP 클라이언트는 자체 기준으로, 흔히 60초에 도구 호출을 끝내므로, 각 호출은 45초 안에 응답합니다. 그때 작업이 아직 실행 중이면 상태는 `timeout`이며, 작업의 `progress`, `jobType`, `createdAt`, `startedAt`이 함께 옵니다. 이는 오류가 아닙니다. 같은 `job_id`로 `wait_for_job`을 다시 호출하세요. 대기는 멈춘 지점에서 이어지고 작업에는 영향이 없으므로, 생성을 다시 실행하지 마세요. 동영상은 2~10분 걸릴 수 있으므로 여러 번 호출하게 됩니다. 또는 `get_job`으로 5~10초마다 폴링하세요. 보류된 작업은 즉시 `pending_review`로 응답합니다.

## `list_jobs`
최근 작업을 상태, 종류, 출력 URL, 오류, 크레딧, 타임스탬프가 담긴 구조화된 데이터로 나열합니다. “어제 실패한 생성은 몇 개인가요?” 같은 질문에 사용하세요. 사용자가 결과를 보고 싶어 하면 그리드를 보여 주는 [`browse_gallery`](https://nodaro.ai/docs/mcp/tools/gallery-and-assets#browse_gallery)를 사용하세요.

**권한:** `jobs:read`. **크레딧:** 무료.

| 매개변수 | 타입 | 설명 |
| --- | --- | --- |
| `kinds` | array | 포함할 미디어 종류로, `image`, `video`, `audio` 중 원하는 것을 넣습니다. 기본값은 `["image", "video"]`이므로 요청하지 않으면 오디오는 빠집니다. |
| `status` | string 또는 array | 내 작업에만 적용됩니다. 상태 하나 또는 상태 목록입니다. `pending`, `queued`, `processing`, `pending_review`, `completed`, `failed`, `cancelled`. |
| `types` | array | 내 작업에만 적용됩니다. 작업 타입 1~20개로, 작업을 만든 경로입니다. 예: `generate-image`, `llm-structured`. |
| `favorited` | boolean | 내 작업에만 적용됩니다. `true`는 내가 즐겨찾기한 작업을, `false`는 나머지를 남깁니다. |
| `rating` | string | 내 작업에만 적용됩니다. `good`, `bad`, `rated`(평가가 있는 모든 작업) 또는 `unrated`입니다. |
| `scope` | string | 내 작업이면 `mine`(기본값), 다른 사용자의 최근 공개 결과면 `public`입니다. |
| `limit` | integer | 1~200입니다. 기본값은 `50`입니다. |
| `cursor` | string | 이전 페이지의 `next_cursor`입니다. |

**반환값:** 작업 한 페이지와 다음 페이지를 위한 `next_cursor`입니다.

공개 범위는 공개 갤러리가 보여 주는 것을 `browse_gallery`와 같은 검토 기준으로 나열하며, 다른 크리에이터의 id는 절대 담지 않습니다. 어느 범위에서든 한 페이지의 작업이 `limit`보다 적으면서도 `next_cursor`가 있을 수 있습니다. `null`이 될 때까지 계속 따라가세요.

내 작업에서 필터는 `GET /v1/jobs`와 같은 방식으로 동작하며 AND로 결합됩니다. `types`를 지정하면 기본 `kinds`가 해제되므로, `llm-structured` 초안처럼 미디어가 없는 작업도 나열됩니다. 미디어만 남기려면 `kinds`도 함께 지정하세요. `types`, `favorited`, `rating`은 `scope: "public"`과 함께 쓰면 거부됩니다.

내 작업마다 `favorited`(`true` 또는 `false`)와 `rating`(`"good"`, `"bad"` 또는 `null`)이 있습니다. 잠시 읽을 수 없을 때는 둘 다 빠지며, 이는 `false`가 아니라 알 수 없음을 뜻합니다. 공개 범위의 행에는 둘 다 없습니다.

내 작업마다 접수될 때 예약된 금액인 `credits`(바뀌지 않음)와, 예약이 정산된 뒤 든 비용인 `credits_charged`가 있습니다. 작업은 예약액보다 적게 정산될 수 있으며, 나머지는 잔액으로 돌아갑니다. 예약이 환불되면 `credits_charged`는 `0`이고, 작업이 아직 실행 중이면 `null`입니다. 작업 비용의 합계를 내려면 `credits`가 아니라 `credits_charged`를 합산하세요. 공개 범위의 행에는 `credits_charged`가 없습니다.

내 작업에는 내 **EDL 적용** 렌더도 출력 종류에 따라 들어갑니다. 편집본은 `video`에, 믹스는 `audio`에 들어갑니다. 미리 보기에는 `preview: true`가 있습니다. 공개 범위에는 **EDL 적용** 렌더가 나열되지 않습니다.

## `rate_job`
내 작업 하나를 `good` 또는 `bad`로 평가하거나 평가를 지웁니다. 작업에는 평가가 하나만 있으며, 소유자만 평가할 수 있습니다. 다른 사람의 작업이나 작업이 아닌 ID는 “찾을 수 없음”으로 응답합니다.

**권한:** `assets:write`. **크레딧:** 무료.

| 매개변수 | 타입 | 설명 |
| --- | --- | --- |
| `job_id` | string | **필수.** 내 작업 중 하나입니다. |
| `rating` | string 또는 null | **필수.** `good` 또는 `bad`, 평가를 지우려면 `null`입니다. |

**반환값:** `{ data: { jobId, rating } }`. 평가는 이 값으로 필터링할 수 있는 `list_jobs`와 `GET /v1/jobs`에 표시됩니다.

## `diagnose_run`
워크플로 실행이나 단일 작업이 실패한 이유를 설명합니다. 두 ID 중 어느 것이든 넘기면 됩니다. 도구는 먼저 워크플로 실행으로 찾아보고, 없으면 작업으로 찾습니다.

**권한:** `jobs:read`. **크레딧:** 무료.

| 매개변수 | 타입 | 설명 |
| --- | --- | --- |
| `id` | string | **필수.** 워크플로 실행 ID 또는 작업 ID입니다. |

**반환값:** 워크플로 실행이면 모든 노드와 각 노드의 작업 ID, 타입, 상태(`nodes`)입니다. 실행의 노드와 작업 ID를 연결해 주는 도구는 이것뿐입니다. 실패한 노드마다 오류 메시지, 모델, 실제로 청구된 크레딧(`creditsActual`), 실패 분류, 해결 방법에 대한 힌트도 함께 담깁니다.

| 실패 분류 | 의미 |
| --- | --- |
| `content_policy` | 안전 필터가 프롬프트나 결과를 차단했습니다 |
| `validation` | 설정이나 입력이 받아들여지지 않았습니다 |
| `rate_limited` | 요청이 요청 한도에 걸렸습니다 |
| `timeout` | 실행이 너무 오래 걸렸습니다 |
| `post_processing` | 모델은 결과를 넘겼지만, 그 뒤의 단계가 실패했습니다 |
| `provider_error` | 모델의 서비스가 오류를 반환했습니다 |
| `unknown` | 오류가 위의 어느 분류에도 해당하지 않습니다 |

분류는 오류 문구로 추정한 것이므로 참고용으로 보세요. 예약된 크레딧은 `post_processing`을 제외한 모든 분류에서 자동으로 환불됩니다. `post_processing`의 경우 모델이 이미 작업을 마쳐 결과를 넘겼기 때문입니다.

완료된 실행은 [`get_app_run`](https://nodaro.ai/docs/mcp/tools/gallery-and-assets#get_app_run)처럼 `outcome`도 알려 주며, 값은 `"succeeded"` 또는 `"nothing_new"`입니다. 입력에 아무것도 도달하지 않아 실행에서 건너뛴 노드에는 `skipReason: "empty_input"`이 있습니다. 새로운 것을 찾지 못한 실행에는 설명할 실패가 없습니다. 잘못된 것은 없고, 처리할 것이 없었을 뿐입니다.

## 작업이 실패했을 때
1. **`retryable`을 읽으세요.** `false`는 같은 요청을 바꾸지 않고 보내면 다시 실패한다는 뜻입니다. 콘텐츠 정책으로 차단되었거나, 모델이 설정과 입력 미디어의 조합을 거부했을 때 이렇게 됩니다.
2. **`suggestedProvider`를 따르세요.** 안전 필터가 결과를 차단했고 카탈로그에 대체 모델이 있으면, 작업이 그 모델을 알려 줍니다. 다른 모델을 짐작해서 고르지 말고 같은 프롬프트와 레퍼런스를 그 모델로 실행하세요.
3. **모델이 요청을 거부했다면 요청을 바꾸세요.** 모델이 이 설정을 거부했다는 오류는 길이, 화면 비율, 해상도 또는 레퍼런스 파일이 그 모델에 맞지 않는다는 뜻입니다. 이를 바꾸거나, [`list_models`](https://nodaro.ai/docs/mcp/tools/models-and-credits#list_models)의 기능 사양에서 그 조합을 허용하는 모델을 고르세요.
4. **나머지는 다시 시도하세요.** 모델 서비스의 일시적인 오류는 문구가 검증 문제처럼 보여도 `retryable` 상태로 남습니다.

더 많은 해결 방법은 [문제 해결](https://nodaro.ai/docs/mcp/troubleshooting)에 있습니다.

## 자주 묻는 질문

### 어시스턴트는 Nodaro 작업을 얼마나 자주 폴링해야 하나요?

get_job으로 5~10초마다 확인하거나, 호출마다 최대 45초 동안 기다리는 wait_for_job을 사용하세요. 이미지는 보통 1분 안에, 동영상은 2~10분 안에 완료됩니다.

### pending_review는 무슨 뜻인가요?

배포 환경이 결과를 공개하기 전에 검토하며, 지금 사람이 이 결과를 확인하고 있다는 뜻입니다. 실패가 아닙니다. 작업을 계속 확인하고 절대 다시 실행하지 마세요. 중복된 작업도 보류되기 때문입니다.

### 작업이 실패하면 어시스턴트는 어떻게 해야 하나요?

작업의 retryable과 guidance를 읽으세요. retryable이 false이면 설정이나 입력을 바꾼 다음 다시 시도하세요. suggestedProvider가 있으면 같은 프롬프트와 레퍼런스를 그 모델로 실행하세요.

### 작업 도구는 크레딧이 드나요?

아니요. 이 도구들은 이미 있는 작업의 상태를 읽을 뿐입니다. 크레딧은 작업을 시작하는 도구만 사용합니다.
