mcpField
E
eachlabs-workflows

eachlabs-workflows

github.com/eachlabsAgent 工作流44208 次安装今天更新
代码仓库

关于 eachlabs-workflows

eachlabs-workflows 用于通过 EachLabs API 构建和运行多步 AI 工作流,适合组合模型步骤的开发者。支持并行与条件分支、回退模型、版本管理和批量执行。

主要功能

  1. 01串联多个模型步骤
  2. 02并行运行或按分支执行
  3. 03配置回退模型
  4. 04管理工作流版本
  5. 05单次触发最多 10 个输入

适用场景

  1. 01组合图像、视频、音频和文本步骤
  2. 02根据模型输出选择处理路径
  3. 03在流程中调用公共 HTTPS API

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/eachlabs/skills --skill eachlabs-workflows

安装后在 Claude Code 中输入/eachlabs-workflows确认已加载。

附带文件references/WORKFLOW-EXAMPLES.md

详细介绍

EachLabs 工作流

构建、管理和执行由多个模型串联而成的多步骤 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 或 slug)及其版本
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 功能提示词、模型和中间文件都保留在 each::labs 上;应用只需发送输入
无需发布应用即可进行更改在新版本中编辑提示词或更换模型;调用方使用的 workflow ID 不变
模型故障时仍能继续运行第一个模型出错时,自动运行 fallback 模型
组合图像、视频、音频和文本将图像编辑串联到视频模型中,然后调整大小、合并片段或添加音乐
加快运行速度使用 parallel 并行运行独立步骤(每张照片或每个场景对应一个步骤)
让 AI 决定路径向视觉模型提问,然后通过 choice 步骤进行路由
使用自己的系统在步骤中调用任意公开 HTTPS API,以获取数据或运行自己的代码

只使用一个模型和用户编写的提示词时,直接进行预测会更简单。当提示词已固定、需要回退方案或存在第二个步骤时,再使用工作流。

构建工作流

步骤 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 会包含具名输出。

编写规则

遵循以下规则,工作流即可一次运行成功:

  1. 使用 $. 路径引用值:$.inputs.<name>、$.<step_id>.primary、$.<step_id>.output、嵌套字段,以及用于列表项的方括号($.step.output[0])。{{inputs.prompt}} 不是引用;它会作为字面文本发送给模型。
  2. 如果参数恰好是一个引用,则保留其类型(URL、数字、列表、对象)。如果引用嵌在更长的字符串中,则会作为文本插入:"A portrait of $.inputs.name in neon light"。
  3. primary 是主要结果:图像和视频模型返回文件 URL,eachlabs-llm-router 返回聊天补全内容(文本位于 $.step.primary.choices[0].message.content),eachlabs-http-step 返回响应(JSON 字段位于 $.step.primary.output.<field>)。
  4. 如果类似提示词的参数(prompt、user_prompt、system_prompt、text、content、message、caption、title、description)恰好是 $.step.primary 或 $.step.output,则该值会以 JSON 编码并用引号括起。请引用更深层的字段,或将引用嵌入句子中。
  5. 每个步骤(包括分支内的步骤)都需要唯一的 id。步骤按从上到下的顺序运行,且只能引用输入和更早执行的步骤。
  6. 输入放在 input_schema.properties 中,每个输入都要有 type、required(true/false)以及可选的 default_value。每个可选输入都必须设置 default_value:如果某个步骤引用了未提供且没有默认值的输入,运行就会失败。空值会从列表中移除,因此当 photo2 的默认值为 "" 时,["$.inputs.photo1", "$.inputs.photo2"] 可以在只有一张或两张照片的情况下正常工作。
  7. 模型 slug 和参数会在步骤运行时检查,而非保存时检查。使用 GET https://api.eachlabs.ai/v1/models/{slug} 查看模型的输入,并在发布前运行一次工作流。

步骤类型

类型用途
model运行模型:model(slug)、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 返回。省略的字段会保留其已存储的值。

批量触发

在单次 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 请求体的结构与执行响应相同。最多会尝试投递 3 次,每次间隔约 10 秒。设置 webhook_secret 后,每次投递都会携带 X-Webhook-Signature: sha256=<hex>,其中 <hex> 是以密钥为键、对 <X-Webhook-Timestamp>.<raw body> 计算得到的小写十六进制 HMAC-SHA256。请与整个标头值进行比较(包括 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,其中包含八个完整工作流,每个工作流都经过端到端运行:单张照片特效、先重新设计再制作动画、由 LLM 编写的提示词、两张照片配乐、可靠的视觉调用、HTTP API 数据、AI 路由和并行场景。

评论

支持 Markdown