comfy-sdk(PyPI)와 @comfyorg/sdk(npm)는 서로 다른 두 서비스와 통신하는 두 개의 클라이언트를 제공합니다. 메서드 이름이 양쪽에서 겹치지만(run, submit, events) 각각 다른 의미를 가지므로, 스니펫을 복사하기 전에 그 코드가 어떤 클라이언트를 만드는지 확인하세요.
어느 표면도 다른 쪽을 감싸지 않으며, Comfy 워크스페이스에서 생성한 API 키 하나로 둘 다 사용할 수 있습니다.
두 언어는 Router 표면을 서로 다르게 노출합니다. Python에서는
Comfy() 하나가 둘 다 담당합니다. Router에는 client.models.run(...), Cloud에는 client.workflows / client.assets / client.jobs를 사용합니다. TypeScript에서는 의도적으로 비슷한 이름을 가진 별도의 export입니다. comfy(소문자, 모듈 수준 네임스페이스)에는 comfy.models가 있고, Comfy(클래스)는 Cloud 클라이언트이며 .models가 없습니다.- Blender나 Krita와 같은 다른 애플리케이션 내부에서 콘텐츠를 생성하는 플러그인
- 사용자를 대신하여 생성 작업을 실행하는 소비자 앱
- 배치 파이프라인, 예를 들어 비디오의 모든 프레임에 워크플로 하나를 실행하는 경우
- 한 번에 많은 워크플로를 동시에 실행해야 하는 백엔드 서비스
이 SDK는 ComfyUI를 외부에서 구동합니다. ComfyUI 내부에서 실행되는 커스텀 노드나 프런트엔드 확장 프로그램을 작성하는 경우에는 커스텀 노드 개발을 대신 참조하세요. 이들은 별도의 API 집합입니다.
설치
현재 릴리스: 0.4.0. PyPI의
comfy-sdk와 npm의 @comfyorg/sdk는 함께 릴리스되며 동일한 버전 번호를 공유합니다. 최신 버전을 설치하거나(pip install comfy-sdk, npm install @comfyorg/sdk), 정확한 고정 대신 범위를 지정하세요. 두 생태계는 이를 다르게 표기합니다. comfy-sdk>=0.4는 하한이며 이후 마이너 버전을 허용하지만, @comfyorg/sdk@^0.4는 0.4.x에 대한 npm의 호환 범위로 0.5.0 직전에서 멈추므로, 새 마이너 버전이 나오면 캐럿 범위를 올려야 합니다. npm 쪽도 이후 마이너 버전을 따라가게 하려면 @comfyorg/sdk@>=0.4.0을 사용하세요. 이 안내가 뒤처져 있다면 레지스트리 페이지가 우선입니다.빠른 시작
입력 이미지를 업로드하고 워크플로를 실행한 다음 결과를 디스크에 기록합니다.workflow_api.json은 API 형식으로 저장된 워크플로입니다. "10"과 "9"는 해당 파일의 노드 ID로, 입력 이미지를 받는 노드와 결과를 가져올 출력 노드를 나타냅니다.
에셋 핸들은 지연 방식으로 동작합니다. photo.png는 로컬에서 해시되며 서버에 해당 바이트가 없을 때만 업로드되므로, 동일한 입력으로 다시 실행해도 비용이 들지 않습니다.
run()은 작업을 제출하고 터미널 상태에 도달할 때까지 대기합니다. 실행되는 동안 다른 작업을 수행하려면 submit()을 대신 사용하고 이벤트 스트림을 확인하세요.
대신 자체 ComfyUI를 대상으로 실행하려면 COMFY_BASE_URL을 설정하고 키를 제거하세요. 아래를 참조하세요.
기본 URL 선택
기본 URL은 생성자 인자가 아닌
COMFY_BASE_URL 환경 변수에서 가져옵니다:
http(s) URL이어야 합니다. 설정되지 않았거나 비어 있으면 Comfy Cloud를 의미합니다. 따라서 클라이언트 자체는 어디서나 동일합니다:
초기 빌드에서 업그레이드하시나요?
Comfy("<url>", "<key>")는 이제 COMFY_BASE_URL을 설정한 상태의 Comfy(api_key="<key>")입니다. api_key는 키워드 전용이므로, 이전의 위치 기반 호출은 URL을 키로 조용히 읽어들이는 대신 TypeError를 발생시킵니다.Comfy Cloud
즉시 사용할 수 있습니다. API 키를 생성하여 클라이언트에 전달하세요.API 액세스에는 유료 Comfy Cloud 구독이 필요합니다. 무료 티어에는 포함되지 않습니다. 동시에 실행할 수 있는 작업 수는 티어에 따라 다릅니다. 병렬 실행를 참조하세요.
Comfy API 배포
개발자 플랫폼을 통해 배포한 워크플로에는 자체 엔드포인트가 제공됩니다.COMFY_BASE_URL을 해당 엔드포인트로 지정하고 Comfy Cloud와 동일하게 API 키를 사용하세요. 이 가이드의 모든 내용이 동일하게 작동합니다.
Comfy API 배포는 Build에 포함된 모델과 커스텀 노드를 사용하여 여러 워크플로를 실행할 수 있습니다. 각 작업에 대해 get_workflow()는 format: "api"를 가지며 실행된 그래프를 .graph 속성에 담은 워크플로 응답을 반환합니다.
자체 ComfyUI
베타 기간 동안 v2 API는 ComfyUI와 함께 실행되는 작은 오픈소스 서비스인 comfy-api-proxy가 제공합니다. 설치하고 실행한 다음COMFY_BASE_URL="http://127.0.0.1:8189"를 설정하세요:
제출 재시도: 멱등성 키
submit()과 run()은 제출할 때마다 Idempotency-Key를 전송하며, 이 키에 대한 Comfy API v2 계약은 중복 시 거부이며, 기록 후 재생이 아닙니다. submit을 재시도 루프로 감싸기 전에 이 내용을 먼저 읽어 보세요.
- 호출할 때마다 새 키가 발급됩니다. 같은 워크플로로
submit()을 두 번 호출하면 제출 두 번, 작업 두 개, 청구 두 번입니다.submit()을 감싼 순진한for attempt in range(3)는 재시도가 아니라 이중 청구입니다. - 재사용한 키는 재생되지 않고 거부됩니다. 재시도를 멱등하게 만들려면 직접
idempotency_key(TypeScript에서는idempotencyKey)를 전달하세요. 그러면 해당 키를 사용한 두 번째 요청은 첫 번째 작업을 반환하는 대신422 idempotency_key_reuse로 실패합니다. SDK는IdempotencyKeyReuse를 발생시킵니다. 이는 “멱등 재시도”가 보통 의미하는 것과 반대이므로 명시적으로 처리해야 합니다. - 복구 방법은 다시 제출하는 것이 아니라 작업을 찾아가는 것입니다.
IdempotencyKeyReuse가 발생하면 첫 번째 시도가 작업을 생성했을 가능성이 충분히 있습니다.client.jobs.get(job_id)로 해당 작업을 가져오세요. 이 조회에는 이미 저장해 둔 id가 필요하므로, 제출이 반환된 뒤 실패 전에 id를 영속화한 경우에만 복구할 수 있습니다. id가 기록되기 전에 연결이 끊어졌다면 조회할 대상도, 자동 복구도 없습니다. 아래 예제는 점유된 키로 다시 제출하는 대신 수동 처리를 위해 예외를 다시 발생시킵니다. - 제출이 확실히 실패하면 키가 해제됩니다. 검증 오류, 크레딧 부족으로 인한 거부, 실행 대기열 가득 참으로 인한 거부는 작업을 생성하지 않고 키를 해제하므로, 그 키로 다시 제출해도 괜찮습니다. 모호한 실패(읽기 타임아웃, 요청 도중 끊긴 연결) 이후에는 키가 계속 점유된 상태로 남습니다. 다시 제출하지 말고 작업을 찾으세요.
- 키는 24시간 후 만료되며, 비어 있지 않은 출력 가능 ASCII여야 하고 길이 제한을 넘지 않아야 합니다. 유효하지 않은 키는 요청이 전송되기 전에
ValueError를 발생시키므로, 명시적인""가 조용히 발급된 키로 대체되는 일은 없습니다.
client.jobs.get(job_id)는 SDK의 재수화 경로이며 id가 필요합니다. 그래서 submit이 반환되는 순간 id를 기록하는 것이 이 복구를 가능하게 하는 핵심입니다. POST /api/v2/jobs의 전체 키 계약은 Comfy API v2를 참고하세요.
Comfy Router의
Idempotency-Key는 다르게 동작합니다. Router에서 이 키는 일회용 토큰이 아니라 재생 핸들입니다. 같은 키로 대기 중인 제출을 다시 보내면 두 번째 요청을 실행 대기열에 넣는 대신 원래 요청을 반환합니다. 큐 전송과 Router 재시도 결과를 참고하세요. 이 두 표면은 계약이 아니라 헤더 이름만 공유합니다.작업 실행 보기
job.events()는 작업 상태의 라이브 스트림을 제공합니다. 노드와 단계 진행 상황, 미리보기 프레임, 그리고 각 출력이 커밋되는 순간을 보여줍니다. 연결이 끊어지면 자동으로 다시 연결됩니다.
Preview.to_pil()에는 선택적 Pillow extra가 필요합니다: pip install "comfy-sdk[pil]".
result()는 완료된 작업을 반환하거나, 실행이 실패한 경우 노드 수준의 세부 정보와 함께 JobFailed를 발생시킵니다. 전체 이벤트 카탈로그는 해당 언어의 SDK README를 참조하세요.
events()는 subscribe()가 아닙니다
두 인터페이스에 걸쳐 이름이 비슷한 세 가지가 존재하며, 이 페이지에 나오는 것은 그중 하나뿐입니다.
Comfy Cloud 클라이언트에는
subscribe()가 없으며, 어디에도 job.subscribe()는 없습니다. subscribe에 해당하는 클라우드 버전은 run()입니다: 제출하고 터미널 상태를 기다립니다.
스트림은 재생 가능한 로그가 아니라 실시간 피드입니다. 결과를 위해 의존할 수 있도록 존재하는 것이 아니라, 진행 상황을 표시하기 위해 존재합니다. 작업을 폴링하는 것이 가장 신뢰할 수 있는 정보이며, run(), wait(), result()는 자동으로 폴링을 사용합니다. 그 이유는 설계 노트를 참조하세요.
출력을 해당 워크플로까지 역추적하기
출력에는 해당 출력을 생성한 작업의 id가 담겨 있으므로, 별도의 보조 테이블을 유지하지 않고도 파일에서 시작해 작업까지 역추적할 수 있습니다.None(TypeScript: undefined)이며, 이는 해당 에셋을 생성한 작업이 없기 때문입니다.
작업에서는 해당 작업의 기반이 된 워크플로를 요청할 수 있습니다. 이 기능은 이 프로세스에서 제출한 것이 아니라 id로 복원한 작업에서도 작동합니다:
format으로 분기하세요. 반환되는 형태는 작업이 제출된 방식에 따라 달라지며, 요청별로 제어할 수 있는 항목에 따라 달라지지 않습니다:
SDK를 통해 제출하는 작업은 항상
api를 반환합니다. v2 제출에는 아직 버전 고정 필드가 없기 때문입니다. 이는 변경될 예정입니다. 판별자가 있는 이유는 코드가 변경되지 않아도 되도록 하기 위해서입니다.
현재 SDK가 다루는 범위
첫 번째 버전은 한 가지 작업을 제대로 수행합니다. 워크플로를 실행하고 결과를 돌려받는 것입니다.- 에셋. 파일, 바이트, 스트림 또는 URL에서 입력 핸들을 생성합니다. 핸들은 지연(lazy) 방식이며 콘텐츠 주소 기반이므로 동일한 입력으로 다시 실행해도 다시 업로드되지 않습니다.
- 제출. API 형식의 그래프를 제출합니다. 제출은 멱등적이며, 실행 대기열이 가득 찬 경우 제한된 예산 내에서 자동으로 재시도됩니다.
- 실행.
wait()으로 폴링하거나events()를 통해 실시간 진행 상황을 추적합니다. - 출력. 디스크에 쓰거나, 메모리에 버퍼링하거나, 바이트 범위를 가져오거나, 단기 다운로드 URL을 받을 수 있습니다.
getDownloadUrl()은 API 키 없이 누구나 읽을 수 있는 서명된 URL을 반환하며, 약 6시간 동안 유효합니다. URL을 저장하기 전에 출력 URL과 유효 기간을 먼저 읽어보세요. 나중에도 출력을 계속 보여주려면 바이트를 다시 호스팅하거나 필요할 때 URL을 다시 발급받아야 합니다. - 추적 가능성. 모든 출력에는 해당 출력을 생성한 작업의 ID가 포함되며, 작업은 그 뒤에 있는 워크플로를 반환할 수 있습니다.
- 에셋 삭제. 업로드한 에셋을 핸들이나 ID로 제거할 수 있습니다.
- 오류. 원시 상태 코드 대신
JobFailed,Unauthorized,InsufficientCredits,QueueFull과 같은 타입화된 예외를 제공합니다. - 취소. 실행 중인 작업을 취소할 수 있습니다. TypeScript는 추가로 모든 호출에서
AbortSignal을 허용합니다.
Comfy 클라이언트와 AsyncComfy 클라이언트를 모두 제공합니다. TypeScript는 비동기 전용입니다.
이 버전에는 포함되지 않는 것: 저장된 워크플로 관리, 모델 라이브러리, 노드 인트로스펙션, 명명된 워크플로 파라미터. 설계 노트에서 API 표면이 이렇게 작게 시작하는 이유를 설명합니다.
참조
SDK README는 인증, 에셋, 오류, 그리고 저수준 이스케이프 해치를 포함하여 각 언어에 대한 전체 참조 자료입니다.Python SDK
PyPI의
comfy-sdk. 동기 및 비동기 클라이언트를 제공합니다.TypeScript SDK
npm의
@comfyorg/sdk. 타입이 지정된 비동기 클라이언트와 저수준 클라이언트를 제공합니다.Comfy API v2 참조
두 SDK의 기반이 되는 HTTP API입니다. 어떤 언어에서든 직접 사용할 수 있습니다.
설계 노트
이 API가 존재하는 이유, 기존 ComfyUI API와의 관계, 그리고 앞으로의 계획을 설명합니다.
Comfy Router
같은 패키지의 또 다른 표면입니다. Flux, Veo, Gemini 같은 파트너 모델에 대해
comfy.models.run을 실행합니다.피드백
SDK는 아직 1.0 이전입니다. 메서드 이름, 클라이언트 형태, 이벤트 카탈로그, 오류 분류 체계, 에셋 처리 방식은 모두 여전히 바뀔 수 있으며, API 표면은 앞으로 몇 주 안에 안정화될 예정입니다. 일단 안정화되고 나면 장기 지원 약정 때문에 변경할 수 있는 범위가 제한됩니다. 어색한 부분, 기대했지만 찾지 못한 부분, 그리고 우회해서 해결해야 했던 부분을 알려주세요. 저희 Discord의#developer-platform 채널이 그런 피드백을 보내실 곳입니다.
다른 언어로 된 퍼스트파티 SDK를 원하신다면 그곳에서 말씀해 주세요. 두 SDK 모두 동일한 문서화된 HTTP 계약을 기반으로 하므로 어떤 언어든 오늘날 API와 통신할 수 있지만, 저희는 수요가 어디에 있는지 알고 싶습니다.