eachlabs-workflows について
eachlabs-workflowsは、EachLabs APIで複数ステップのAIパイプラインを構築・実行するスキルです。並列処理や条件分岐、フォールバック、バージョン管理、バッチ実行に対応します。
主な機能
- 01複数モデルのステップ連携
- 02並列実行と分岐処理
- 03フォールバックモデルの設定
- 04ワークフローバージョンの管理
- 05最大10入力の一括実行
活用シーン
- 01画像・動画・音声・テキスト処理の連携
- 02モデル出力に応じた処理の振り分け
- 03パイプラインからの公開HTTPS API呼び出し
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ eachlabs/ skills --skill eachlabs-workflowsインストール後、Claude Code で/eachlabs-workflowsを入力して読み込まれたか確認します。
同梱ファイルreferences/WORKFLOW-EXAMPLES.md
詳細
EachLabs Workflows
複数のモデルを連携させるマルチステップの AI パイプラインを構築、管理、実行できます。each::workflows は完全無料で利用でき、費用がかかるのは基盤となるモデルの利用料のみです。
認証
Header: Authorization: Bearer <your-api-key>
EACHLABS_API_KEY 環境変数を設定します。キーはeachlabs.aiで取得してください。X-API-Key ヘッダーも使用できます。
ベース URL
https://api.eachlabs.ai
エンドポイント
| メソッド | パス | 説明 |
|---|---|---|
| POST | /v1/workflows | ワークフローを作成します(最初のバージョンも作成されます) |
| GET | /v1/workflows/{workflowID} | バージョンを含むワークフローを取得します(UUID またはスラッグ) |
| PUT | /v1/workflows/{workflowID}/versions/{versionID} | バージョンを作成または更新します |
| POST | /v1/workflows/trigger/{workflowID}/{versionID} | バージョンを実行します |
| POST | /v1/workflows/bulk-trigger/{workflowID}/{versionID} | 1~10 件の入力でバージョンを実行します |
| GET | /v1/workflows/{workflowID}/executions | 実行履歴を一覧表示します(?bulk_id= で一括実行を絞り込みます) |
| GET | /v1/workflows/executions/{executionID} | 実行のステータスと結果を取得します |
ワークフローを使う場面
| タスクの目的… | ワークフローでできること |
|---|---|
| AI 機能を 1 回の呼び出しで提供する | プロンプト、モデル、中間ファイルは each::labs 上に保持され、アプリは入力を送信するだけです |
| アプリをリリースせずに変更する | 新しいバージョンでプロンプトを編集したり、モデルを切り替えたりできます。呼び出し元は同じワークフロー ID を使い続けられます |
| モデルが失敗しても処理を続ける | 最初のモデルでエラーが発生すると、fallback モデルが自動的に実行されます |
| 画像、動画、音声、テキストを組み合わせる | 画像編集を動画モデルにつなぎ、その後、サイズ変更、クリップの結合、音楽の追加を行います |
| 処理を高速化する | 独立したステップ(写真ごと、シーンごとなど)を parallel で実行します |
| AI に処理経路を判断させる | ビジョンモデルに質問し、その後 choice ステップで処理を振り分けます |
| 独自のシステムを使う | ステップから任意の公開 HTTPS API を呼び出し、データの取得や独自コードの実行を行います |
ユーザーが作成したプロンプトを使うモデルが 1 つだけなら、直接予測を行うほうがシンプルです。プロンプトを固定したい場合、フォールバックが必要な場合、または 2 つ目のステップがある場合は、ワークフローを使います。
ワークフローの構築
ステップ 1:ワークフローの作成
curl -X POST https://api.eachlabs.ai/v1/workflows \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $EACHLABS_API_KEY" \
-d '{
"name": "Text to Image Generator",
"definition": {
"input_schema": {
"properties": {
"prompt": { "type": "string", "required": true }
}
},
"steps": [
{
"id": "write_prompt",
"type": "model",
"model": "eachlabs-llm-router",
"params": {
"model": "google/gemini-3.6-flash",
"messages": [
{ "role": "system", "content": "Rewrite the idea as one vivid, detailed image prompt. Reply with the prompt only." },
{ "role": "user", "content": "$.inputs.prompt" }
]
}
},
{
"id": "generate_image",
"type": "model",
"model": "nano-banana-2-text-to-image",
"params": {
"prompt": "$.write_prompt.primary.choices[0].message.content",
"aspect_ratio": "16:9"
}
}
]
}
}'
レスポンスには workflow_id と versions[0].version_id(v1)が含まれます。400 invalid argument が返された場合は、同じ定義を {"definition": {...}} として PUT /v1/workflows/{workflowID}/versions/v1 に送信すると、正確な検証エラーを確認できます。
ステップ 2:ワークフローの実行
curl -X POST https://api.eachlabs.ai/v1/workflows/trigger/{workflowID}/v1 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $EACHLABS_API_KEY" \
-d '{
"inputs": {"prompt": "A lighthouse on a cliff at sunset"}
}'
レスポンス:
{"execution_id": "exec-123", "status": "queued"}
ステップ 3:結果のポーリング
curl https://api.eachlabs.ai/v1/workflows/executions/{executionID} \
-H "Authorization: Bearer $EACHLABS_API_KEY"
レスポンス(一部省略):
{
"execution_id": "exec-123",
"status": "completed",
"output": "https://cdn-us.eachlabs.ai/uploads/3334048f.png",
"step_outputs": {
"write_prompt": {"status": "completed", "primary": {"choices": [{"message": {"content": "A dramatic wide-angle photograph of a lighthouse..."}}]}},
"generate_image": {"status": "completed", "primary": "https://cdn-us.eachlabs.ai/uploads/3334048f.png"}
}
}
実行ステータス:running、completed、failed、cancelled
output は最後のステップの結果です。バージョンで output_mapping を定義している場合、workflow_output に名前付きの出力が格納されます。
作成ルール
以下に従えば、ワークフローは初回で実行できます。
- 値の参照には
$.パスを使用します。$.inputs.<name>、$.<step_id>.primary、$.<step_id>.output、ネストされたフィールド、およびリスト項目にはブラケット表記を使います($.step.output[0])。{{inputs.prompt}}は参照ではなく、リテラルテキストとしてモデルに送られます。 - パラメーターが参照のみで構成されている場合、型(URL、数値、リスト、オブジェクト)は保持されます。より長い文字列の中に参照がある場合は、テキストとして挿入されます。例:
"A portrait of $.inputs.name in neon light"。 primaryは主な結果です。画像モデルと動画モデルではファイル URL、eachlabs-llm-routerではチャット補完(テキストは$.step.primary.choices[0].message.content)、eachlabs-http-stepではレスポンス(JSON フィールドは$.step.primary.output.<field>)です。- プロンプトのようなパラメーター(
prompt、user_prompt、system_prompt、text、content、message、caption、title、description)が$.step.primaryまたは$.step.outputのみで構成されている場合、値は引用符で囲まれた JSON エンコード形式で渡されます。より深いフィールドを参照するか、文章の中に参照を埋め込んでください。 - 分岐内のステップも含め、すべてのステップに一意の
idが必要です。ステップは上から順に実行され、入力と前のステップのみを参照できます。 - 入力は
input_schema.propertiesに指定し、それぞれにtype、required(true/false)、および任意のdefault_valueを設定します。省略可能な入力にはすべてdefault_valueを指定してください。デフォルト値のない省略された入力をステップが参照すると、実行は失敗します。空の値はリストから削除されるため、photo2のデフォルト値が""の場合、["$.inputs.photo1", "$.inputs.photo2"]は写真が1枚でも2枚でも機能します。 - モデルのスラッグとパラメーターは、保存時ではなくステップの実行時に検証されます。
GET https://api.eachlabs.ai/v1/models/{slug}でモデルの入力を確認し、公開前にワークフローを一度実行してください。
ステップの種類
| 種類 | 目的 |
|---|---|
model | モデルを実行します。model(スラッグ)、params、任意の fallback、retry、timeout_seconds を指定します |
parallel | branches[].steps を同時に実行します |
choice | 条件を評価し、condition_met_branch または default_branch を実行します |
pass | 固定の result を返します |
HTTP リクエストと Python コードはステップの種類ではありません。これらは、eachlabs-http-step(以下を参照)および eachlabs-python-step(プライベートベータ)をモデルステップとして実行します。
モデルステップ
{
"id": "restyle",
"type": "model",
"model": "nano-banana-2-edit",
"params": {
"prompt": "Restyle this photo as $.inputs.style. Keep the person's face unchanged.",
"image_urls": ["$.inputs.photo"],
"aspect_ratio": "9:16"
},
"retry": {"max_attempts": 3, "retry_on": ["server_error"]}
}
HTTP 呼び出し
eachlabs-http-step モデルを使って、公開 HTTPS API を呼び出します。パラメーター:url、method、headers、
query_params、body(POST/PUT/PATCH 用の JSON オブジェクト)、timeout_seconds(最大30秒を
推奨)、および fail_on_status("non_2xx" を指定すると、エラーレスポンス時に実行を停止します)。
{
"id": "product",
"type": "model",
"model": "eachlabs-http-step",
"params": {
"url": "https://dummyjson.com/products/$.inputs.product_id",
"method": "GET",
"timeout_seconds": 20,
"fail_on_status": "non_2xx"
}
}
後続のステップでは、JSON 本文を $.product.primary.output.title として読み取ります。認証情報は headers に指定してください
(例:"Authorization": "Bearer <scoped-token>")。アクセスできるのは公開 URL のみです。独自のコードを実行するには、
HTTPS エンドポイントでホストし、そこに POST してください。
並列ステップ
{
"id": "prepare",
"type": "parallel",
"branches": [
{"steps": [{"id": "edit_a", "type": "model", "model": "nano-banana-2-edit", "params": {"prompt": "Full-body photo of this person as a traveler in a sunny old-town street.", "image_urls": ["$.inputs.photo_a"]}}]},
{"steps": [{"id": "edit_b", "type": "model", "model": "nano-banana-2-edit", "params": {"prompt": "Full-body photo of this person as a traveler in a sunny old-town street.", "image_urls": ["$.inputs.photo_b"]}}]}
]
}
後続のステップでは、各分岐のステップをそれぞれの ID で参照します:$.edit_a.primary、$.edit_b.primary。分岐には、順番に実行される複数のステップを含めることができます。
選択ステップ(条件付きルーティング)
{
"id": "portrait",
"type": "choice",
"condition": {
"expression": "$.subject.primary.choices[0].message.content",
"operator": "string_matches",
"value": "*PET*"
},
"condition_met_branch": {
"name": "pet",
"steps": [{"id": "pet_portrait", "type": "model", "model": "nano-banana-2-edit", "params": {"prompt": "A royal oil-painting portrait of this animal wearing a small crown.", "image_urls": ["$.inputs.photo"]}}]
},
"default_branch": {
"name": "person",
"steps": [{"id": "person_portrait", "type": "model", "model": "nano-banana-2-edit", "params": {"prompt": "A royal oil-painting portrait of this person wearing a crown. Keep their face unchanged.", "image_urls": ["$.inputs.photo"]}}]
}
}
選択ステップの後、$.portrait.primary は実行された分岐の結果となり、selected にはその分岐名が格納されます。
条件演算子:
| カテゴリ | 演算子 |
|---|---|
| 比較 | equals、not_equals(型を厳密に比較)、greater_than、less_than、greater_than_or_equal、less_than_or_equal |
| 文字列 | string_equals、string_matches(* はワイルドカードパターン。* がない場合は完全一致が必要です) |
| 存在 | exists/is_not_null(フィールドが存在する)、is_null/not_exists(フィールドが存在し、null である) |
| 論理 | and、or、not |
in と not_in はサポートされていません。equals 条件を or と組み合わせてください。
{"or": [
{"expression": "$.inputs.format", "operator": "equals", "value": "mp4"},
{"expression": "$.inputs.format", "operator": "equals", "value": "webm"}
]}
パスステップ
{"id": "config", "type": "pass", "result": {"style": "cinematic"}}
result 内の $. 参照は解決されません。後続のステップでは、そのフィールドを $.config.style として読み取ります。
パラメーターの参照
| 参照 | 値 | 例 |
|---|---|---|
$.inputs.<name> | ワークフロー入力 | $.inputs.prompt |
$.<step_id>.primary | ステップの主な結果 | $.restyle.primary |
$.<step_id>.output | ステップの全結果 | $.restyle.output |
$.<step_id>.primary.<field> | オブジェクト結果のフィールド | $.product.primary.output.title |
$.<choice_id>.primary | 実行された分岐の結果 | $.portrait.primary |
条件では、expression 内で同じパスを使用します。
フォールバックの設定
{
"id": "restyle",
"type": "model",
"model": "nano-banana-2-edit",
"params": {"prompt": "Restyle this photo as $.inputs.style.", "image_urls": ["$.inputs.photo"]},
"fallback": {
"enabled": true,
"model": "gpt-image-v2-edit",
"params": {"prompt": "Restyle this photo as $.inputs.style.", "image_urls": ["$.inputs.photo"]}
}
}
プライマリモデルが失敗すると、独自の params を使用してフォールバックが実行され、その結果が $.restyle.primary になります。実行の step_outputs では、restyle_fallback.fallback.reason は primary_failed または not_triggered です。
バージョン管理
各バージョンには完全な定義が保存されるため、呼び出し元が以前のバージョンを使い続けている間にワークフローを変更できます。特定のバージョンを実行するには、/v1/workflows/trigger/{workflowID}/{versionID} を使用します。バージョンに locked: true を設定すると、それ以降の変更を防止できます。
バージョンの作成/更新
curl -X PUT https://api.eachlabs.ai/v1/workflows/{workflowID}/versions/v2 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $EACHLABS_API_KEY" \
-d '{
"definition": {
"input_schema": {
"properties": {
"prompt": { "type": "string", "required": true },
"aspect_ratio": { "type": "string", "required": false, "default_value": "16:9" }
}
},
"steps": [
{
"id": "write_prompt",
"type": "model",
"model": "eachlabs-llm-router",
"params": {
"model": "google/gemini-3.6-flash",
"messages": [
{ "role": "system", "content": "Rewrite the idea as one vivid, detailed image prompt. Reply with the prompt only." },
{ "role": "user", "content": "$.inputs.prompt" }
]
}
},
{
"id": "generate_image",
"type": "model",
"model": "nano-banana-2-text-to-image",
"params": {
"prompt": "$.write_prompt.primary.choices[0].message.content",
"aspect_ratio": "$.inputs.aspect_ratio"
}
}
]
},
"output_mapping": { "image": "$.generate_image.primary" }
}'
v2 の実行では、画像が workflow_output.image として返されます。省略されたフィールドには、保存済みの値が引き継がれます。
一括トリガー
1 回の API 呼び出しで複数の入力(最大 10 件)を処理します。
curl -X POST https://api.eachlabs.ai/v1/workflows/bulk-trigger/{workflowID}/v1 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $EACHLABS_API_KEY" \
-d '{
"inputs": [
{"prompt": "A red bicycle against a white wall"},
{"prompt": "A blue bicycle against a white wall"}
]
}'
レスポンスには bulk_id と、入力ごとの execution_id が含まれます。GET /v1/workflows/{workflowID}/executions?bulk_id={bulk_id} でバッチの一覧を取得できます。一部の実行が失敗する場合があります。
Webhook
トリガーに webhook_url(および任意で webhook_secret)を追加すると、ポーリングの代わりに結果を受信できます。
curl -X POST https://api.eachlabs.ai/v1/workflows/trigger/{workflowID}/v1 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $EACHLABS_API_KEY" \
-d '{
"inputs": {"prompt": "A lighthouse on a cliff at sunset"},
"webhook_url": "https://your-server.com/webhook",
"webhook_secret": "your-secret"
}'
Webhook の本文は、実行レスポンスと同じ形式です。配信は約 10 秒間隔で最大 3 回試行されます。webhook_secret を設定すると、各配信には X-Webhook-Signature: sha256=<hex> が含まれます。ここで <hex> は、シークレットをキーとして <X-Webhook-Timestamp>.<raw body> に対して計算した HMAC-SHA256 の小文字 16 進数表記です。sha256= のプレフィックスを含むヘッダー値全体と比較し、再シリアライズした JSON ではなく、リクエストの生バイト列をハッシュしてください(Webhook 署名の検証)。
each::sense を使ったワークフロービルダー
each::sense のワークフローエンドポイントを使い、自然言語でワークフローを作成することもできます。
curl -X POST https://eachsense-agent.core.eachlabs.run/workflow \
-H "Content-Type: application/json" \
-H "X-API-Key: $EACHLABS_API_KEY" \
-d '{
"message": "Create a workflow that generates an image and then upscales it",
"stream": true,
"session_id": "my-session"
}'
既存のワークフローを更新するには、workflow_id と version_id を含めてください。
ワークフローの参照例
references/WORKFLOW-EXAMPLES.md では、エンドツーエンドで実行できる 8 つの完全なワークフローを紹介しています。1 枚の写真へのエフェクト適用、スタイル変更後のアニメーション化、LLM が作成したプロンプト、音楽付きの 2 枚の写真、信頼性の高いビジョン呼び出し、HTTP API のデータ、AI によるルーティング、並列シーンです。