Comfy API v2 はバージョン管理されています。v2 内の変更は追加的なものに限られ、互換性を損なう変更は v3 で行われます。問題はフィードバックから報告してください。
comfy-sdk(PyPI)と @comfyorg/sdk(npm)は、2つの異なるサービスと通信する2つのクライアントを提供します。メソッド名は両者で重複して登場し(run、submit、events)、それぞれで意味が異なるため、スニペットをコピーする前に、それがどちらのクライアントを構築するものかを確認してください。
どちらのサーフェスも他方をラップしておらず、あなたの Comfy ワークスペースで作成した1つの APIキーが両方で機能します。
2つの言語では Router サーフェスの公開の仕方が異なります。Python では
Comfy() が両方を担います。Router には client.models.run(...)、Cloud には client.workflows / client.assets / client.jobs です。TypeScript ではこれらは意図的に似た名前を持つ別々のエクスポートです。comfy(小文字、モジュールレベルの名前空間)が comfy.models を持ち、一方 Comfy(クラス)は Cloud クライアントであり .models を持ちません。- BlenderやKritaなど、別のアプリケーション内でコンテンツを生成するプラグイン
- ユーザーに代わって生成を実行するコンシューマー向けアプリ
- バッチパイプライン。たとえば、ビデオの全フレームに1つのワークフローを実行するなど
- 同時に多くのワークフローを処理する必要があるバックエンドサービス
これらのSDKは、ComfyUIを外部から操作します。ComfyUIの内部で実行されるカスタムノードやフロントエンド拡張機能を記述している場合は、代わりにカスタムノードの開発を参照してください。これらは別のAPIセットです。
インストール
現在のリリース: 0.5.0。 PyPI の
comfy-sdk と npm の @comfyorg/sdk は同時にリリースされ、バージョン番号を共有します。最新版をインストールする(pip install comfy-sdk、npm install @comfyorg/sdk)か、正確なピン留めではなく範囲を指定してください。この 2 つのエコシステムではその書き方が異なります。comfy-sdk>=0.5 は下限であり、それ以降のマイナーバージョンも受け入れます。一方 @comfyorg/sdk@^0.5 は 0.5.x に対する npm の互換範囲で、0.6.0 には到達しないため、新しいマイナーバージョンがリリースされたときはキャレット範囲を引き上げる必要があります。npm 側でも以降のマイナーバージョンを追跡したい場合は @comfyorg/sdk@>=0.5.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 Cloud ではまだサポートされていません。
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()を2回呼ぶと、2回の送信、2つのジョブ、2回の課金になる。submit()を素朴にfor attempt in range(3)で囲むのはリトライではなく二重請求だ。 - 再利用されたキーは拒否され、再生されない。 リトライを冪等にするには独自の
idempotency_key(TypeScript ではidempotencyKey)を渡すが、同じキーでの2回目のリクエストは最初のジョブを返す代わりに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 を必要とする。だからこそ、送信が戻った瞬間に id を記録することが、これを復旧可能にしている。POST /api/v2/jobs におけるキー契約の全体については Comfy API v2 を参照。
Comfy Router の
Idempotency-Key は 異なる 動作をする。Router ではキーは使い捨てトークンではなく再生ハンドルである。同じキーでキュー中の送信を再送すると、2つ目をキューに入れる代わりにオリジナルのリクエストを返す。キューの冪等性と課金 と Router のリトライ結果 を参照。2つのサーフェスはヘッダー名を共有しているだけで、契約は共有していない。ジョブの実行を監視する
job.events() は、ジョブの状態のライブストリームを提供します。ノードとステップの進捗、プレビューフレーム、各出力がコミットされた瞬間のデータを取得できます。接続が切断された場合は、自動的に再接続されます。
Preview.to_pil() にはオプションの Pillow extra が必要です: pip install "comfy-sdk[pil]"。
result() は、完了したジョブを返します。実行に失敗した場合は、ノードレベルの詳細情報を含む JobFailed を送出します。完全なイベントカタログについては、お使いの言語の SDK README を参照してください。
events() は subscribe() ではない
似た名前のものが 2 つのサーフェスにまたがって 3 つ存在し、このページで扱うのはそのうちの 1 つだけです。
Comfy Cloud クライアントに
subscribe() はなく、どこにも job.subscribe() はありません。subscribe に相当する Cloud の機能は run() です。送信し、終了状態を待ちます。
ストリームはライブフィードであり、再生可能なログではありません。進捗を表示するためのものであり、結果の取得に依存するためのものではありません。ジョブのポーリングこそが信頼できる情報源であり、run()、wait()、result() は自動的にポーリングにフォールバックします。理由については、設計ノート を参照してください。
出力を生成元のワークフローまで遡る
出力には、それを生成したジョブのIDが保持されています。そのため、サイドテーブルを保持しなくても、ファイルから逆方向に遡ることができます。None(TypeScriptではundefined)になります。
ジョブから、その背後にあるワークフローを取得できます。これは、このプロセス内で送信したものではなく、IDで再水和されたジョブでも機能します。
formatで分岐してください。 返ってくる形状は、ジョブがどのように送信されたかによって決まり、リクエストごとに制御できるものではありません。
SDKを通じて送信したジョブは常に
apiを返します。v2送信にはバージョン固定フィールドがまだないためです。この動作は将来変更されます。判別子が用意されているのは、コード側の変更が不要になるようにするためです。
ジョブにラベルを付けて後で見つける
ラベルは、ジョブを送信するときに付けるキーと値の組です。たとえばclient: acme や project: spring です。ラベルを使うと、ジョブがどのクライアントやプロジェクトのために実行されたかを記録できます。そうすれば、ジョブ ID の対応表を自前で持たなくても、1 つのクライアントのジョブを一覧できます。ラベルとジョブ一覧には、現在の SDK リリース(インストールのバージョン注記に記載されているもの)が必要です。
ラベルは Comfy API デプロイに送信したジョブで使えます。そのため、ベースURLの選択で示したとおり、COMFY_BASE_URL をデプロイのアドレスに設定してください。Comfy Cloud は現時点ではラベルを受け付けず、ジョブ一覧には 501 とコード not_implemented を返します。セルフホストの comfy-api-proxy もラベルを保持しません。proxy 独自の metadata フィールドは 1 つのテキスト文字列なので、ラベルのマップを拒否します。proxy のジョブ一覧はラベルによる絞り込みを無視するため、そこではラベルを指定した SDK の一覧呼び出しはジョブを 1 件も返さず、HTTP で同じフィルターを送るとすべてのジョブが返ります。
制限:
- 1 つのジョブに付けられるラベルは最大 16 個です。
- キーは 1〜40 文字で、使える文字は英字、数字、
_、-、.です。 - 値は最大 256 バイト(UTF-8)の文字列です。
- ラベルはジョブの送信時に設定され、後から変更できません。
422、コード metadata_invalid で失敗し、ジョブは作成されません。エラーメッセージには、違反したキーが示されます。ラベルが 16 個を超える場合は、その数が示されます。SDK 自体は制限を確認しません。サーバーのコードとメッセージを含むエラーを送出します。
送信時に metadata を渡します。ジョブを読み戻すと、ラベルが付いています。
metadata は空です。
1 つのクライアントのジョブを見つけるには、ラベルで絞り込んでジョブを一覧します。一覧に含まれるのは、ベースURLのデプロイに送信したジョブだけです。結果は新しい順に返り、反復するにつれて SDK が次のページを取得します。
client.jobs.get(job.id) で ID からジョブを読み取ってください。
HTTP で使う
POST /api/v2/jobs の本文で metadata を送ります。
GET /api/v2/jobs は、ラベルごとに 1 つの metadata[<key>]=<value> クエリパラメーターで絞り込みます。-g フラグを付けると、curl は角かっこをパターンとして解釈しません。
next_cursor が含まれます。次のページを取得するには、それを cursor として、同じ metadata[...] フィルターと一緒に渡します。フィルターなしで送ったカーソルは、絞り込まれていないジョブを返します。ページサイズは limit で設定します(最大 500)。
400、コード invalid_metadata_filter で失敗します。ジョブと一覧のすべてのフィールドについては、Comfy API v2 リファレンスを参照してください。
SDK が現在対応している範囲
最初のバージョンは、1つのことをきちんと行います。ワークフローを実行して結果を取得することです。- アセット: ファイル、バイト、ストリーム、または URL から入力ハンドルを作成します。ハンドルは遅延評価され、コンテンツアドレス方式のため、同じ入力で再実行しても再アップロードされません。
- 送信: API 形式のグラフを送信します。送信は冪等であり、キューが満杯の場合も、限られた予算内で自動的に再試行されます。
- 実行:
wait()でポーリングするか、events()でリアルタイムの進捗を追跡します。 - 出力: ディスクに書き込む、メモリにバッファリングする、バイト範囲を取得する、または短期間有効なダウンロード URL を取得します。
getDownloadUrl()は、APIキーなしで誰でも読み取れる署名付き URL を返し、有効期間はおよそ 6 時間です。保存する前に 出力 URL とその有効期間 を読んでください。後で出力を表示し続けるには、バイトを再ホストするか、必要に応じて URL を再発行します。 - トレーサビリティ: すべての出力には、それを生成したジョブの ID が含まれ、ジョブからその背後にあるワークフローを取得することもできます。
- アセットの削除: アップロードしたアセットを、ハンドルまたは ID で削除します。
- エラー: 生のステータスコードではなく、
JobFailed、Unauthorized、InsufficientCredits、QueueFullなどの型付き例外。 - キャンセル: 実行中のジョブをキャンセルできます。TypeScript では、任意の呼び出しで
AbortSignalも受け付けます。
Comfy クライアントと、同じインターフェースを持つ AsyncComfy クライアントの両方が用意されています。TypeScript は非同期のみです。
このバージョンには含まれないもの: 保存したワークフローの管理、モデルライブラリ、ノードのイントロスペクション、名前付きワークフローパラメータ。設計ノート では、なぜ API サーフェスがこのように小さく始まるのかを説明しています。
リファレンス
SDK の README は、各言語の完全なリファレンスです。認証、アセット、エラー、および低レベルのエスケープハッチを含みます。Python SDK
comfy-sdk を PyPI で公開。同期・非同期クライアント。TypeScript SDK
@comfyorg/sdk を npm で公開。型付き・非同期、低レベルクライアントを備えています。Comfy API v2 リファレンス
両方のSDKの基盤となるHTTP API。任意の言語から直接使用できます。
設計ノート
このAPIが存在する理由、既存のComfyUI APIとの関係、今後の予定。
Comfy Router
同じパッケージのもう一つのサーフェス: Flux、Veo、Gemini などのパートナーモデルに対して
comfy.models.run を実行します。フィードバック
SDK と API へのフィードバックをお待ちしています。使いにくい点、見つけられなかった情報、回避策が必要だったことをお知らせください。 扱いにくい点、期待していたのに見つからなかったもの、回避策で対応せざるを得なかったことを報告してください。私たちのDiscordの#developer-platformチャンネルがその報告の場所です。
別の言語のファーストパーティ SDK が必要な場合は、そこでその旨をお伝えください。両方の SDK は同じ文書化された HTTP 契約に基づいているため、今日の時点であらゆる言語が API と通信できますが、どこに需要があるのかを把握したいと考えています。