Pipelines

Pipelines let you chain MCP tools into sequential workflows. The output of one tool feeds the input of the next. Active pipelines are automatically exposed as MCP tools and A2A skills.

Creating a pipeline

Dashboard

Navigate to Pipelines in the sidebar. Click Create Pipeline, enter a name and description, then use the visual builder to add steps.

API

curl -X POST https://api.fold.run/pipelines \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "summarize-and-translate",
    "description": "Summarize text then translate to Spanish",
    "steps": [
      { "id": "step_1", "tool_name": "summarize", "function_id": "fn_abc", "position": 0 },
      { "id": "step_2", "tool_name": "translate", "function_id": "fn_xyz", "position": 1 }
    ],
    "input_schema": {
      "type": "object",
      "properties": { "text": { "type": "string" } }
    }
  }'

Pipeline status

Status Description
draft Pipeline is being built. Can be executed for testing but not exposed via MCP/A2A.
active Pipeline is live. Auto-registered as pipeline:{name} MCP tool and A2A skill.
archived Pipeline is disabled. Cannot be executed.

Input mapping

Each step can map its input from three sources:

Source Format Example
Pipeline input $input.fieldName $input.text
Previous step output $steps.step_id.fieldName $steps.step_1.summary
Literal value literal:value literal:es

If no input_mapping is specified, the entire output of the previous step (or the pipeline input for the first step) is passed through.

Example

{
  "steps": [
    {
      "id": "step_1",
      "tool_name": "summarize",
      "function_id": "fn_abc",
      "position": 0,
      "input_mapping": { "text": "$input.text" }
    },
    {
      "id": "step_2",
      "tool_name": "translate",
      "function_id": "fn_xyz",
      "position": 1,
      "input_mapping": {
        "text": "$steps.step_1.summary",
        "target_language": "literal:es"
      }
    }
  ]
}

Executing a pipeline

curl -X POST https://api.fold.run/pipelines/pipe_abc/execute \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "input": { "text": "Long article to process..." } }'

The response includes the final output and per-step results:

{
  "id": "run_xyz",
  "pipeline_id": "pipe_abc",
  "status": "completed",
  "output": { "translated": "Resumen en espanol..." },
  "step_results": [
    { "step_id": "step_1", "tool_name": "summarize", "status": "success", "duration_ms": 120 },
    { "step_id": "step_2", "tool_name": "translate", "status": "success", "duration_ms": 85 }
  ],
  "duration_ms": 205
}

MCP and A2A integration

Active pipelines are automatically registered as:

  • MCP tool: pipeline:{name} — callable via your /.well-known/mcp endpoint
  • A2A skill: pipeline:{name} — callable via tasks/send or tasks/sendSubscribe at /_a2a/

Agents see pipelines alongside individual tools in the MCP tool list and Agent Card skills.

Visual builder

The dashboard includes a React Flow-based visual builder at Pipelines > {pipeline name}:

  • Drag tools from the palette on the right
  • Steps are displayed vertically with animated connections
  • Click a step to configure its input mapping
  • Use the action bar to Save, toggle Active/Draft, and run test executions

Run history

Each pipeline execution is recorded. View run history at Pipelines > {pipeline name} or via the API:

GET /pipelines/{id}/runs       # List runs
GET /pipelines/runs/{runId}    # Get specific run

API reference

Method Path Description
GET /pipelines List pipelines
POST /pipelines Create pipeline
GET /pipelines/:id Get pipeline
PUT /pipelines/:id Update pipeline (bumps version)
DELETE /pipelines/:id Delete pipeline
POST /pipelines/:id/execute Execute pipeline
GET /pipelines/:id/runs List runs
GET /pipelines/runs/:runId Get run details

Parallel groups

Steps with the same parallel_group value in consecutive positions run concurrently instead of sequentially. Steps without a parallel_group run one at a time as before.

{
  "steps": [
    { "id": "s1", "tool_name": "fetch-data", "function_id": "fn_1", "position": 0 },
    { "id": "s2", "tool_name": "enrich-a", "function_id": "fn_2", "position": 1, "parallel_group": "enrich" },
    { "id": "s3", "tool_name": "enrich-b", "function_id": "fn_3", "position": 2, "parallel_group": "enrich" },
    { "id": "s4", "tool_name": "merge", "function_id": "fn_4", "position": 3 }
  ]
}

In this example, steps s2 and s3 run in parallel after s1 completes. Step s4 runs after both parallel steps finish. The output of a parallel group is an object keyed by step ID: { "s2": <output>, "s3": <output> }.

Use $steps.s2.field or $steps.s3.field in the input mapping of subsequent steps to reference individual parallel step outputs.

Limits

  • Maximum 20 steps per pipeline
  • Pipeline name must match ^[a-z0-9][a-z0-9-]*$ (max 63 characters)
  • Parallel groups must contain consecutive steps with the same parallel_group value