Flow introduction

Flows are the core of lensless — configurable pipelines that chain multiple computation steps into a single, reusable workflow. You can keep them private for your own use or publish them publicly for anyone to run (and pay for).

What is a Flow?

A Flow is a sequence of steps, each performing a specific action:

Every Flow has:

  1. Schema-based input — a JSON Schema that defines what the user provides.
  2. Step definitions — the list of steps describing what to do and in what order.
  3. UI configuration — how the form and results are presented.

Fields overview

titlestringrequired

A human-readable title for your Flow. Displayed on the Flow page and in dashboards.

descriptionstringrequired

Short text explaining what your Flow does. Also shown on the Flow page.

publicboolean

Whether the Flow is publicly accessible. Public Flows can be run by anyone with the link and can have a price set.

runPricenumber (4–200)

Price charged per run if the Flow is public, in the currency specified by runPriceCurrency.

runPriceCurrencystring

ISO currency code for the runPrice (e.g., "USD", "EUR", "BRL").

payoutMethodstring: Wallet | Connect

How you receive money from paid Flow runs. "Wallet" credits your organization balance; "Connect" pays out via your connected payout account.

inputobject (JSON Schema)

Describes the user input form. See Flow Input & Form for details.

stepsarray

The sequence of computation steps. Each step has an id, type, and parameters. See Steps for details.

storeobject

A global object available to all steps during a run. Useful for static data like prompt lists or configuration values that multiple steps need.

uiobject

Controls how the Flow page looks and how results are displayed. See UI Configuration and Results & Widgets.

slugstring

A unique identifier for the Flow URL. If not provided, one is auto-generated. Must be unique across all Flows.

Example Flow

Here’s a Flow that takes user photos and a recipe type, trains a model, generates images, and zips everything:

{
  title: 'You with different recipes!',
  description: 'Train a model using photos of yourself and generate images with different recipes!',
  public: true,
  runPrice: 12,
  runPriceCurrency: 'USD',
  input: {
    type: 'object',
    required: ['userDatasetId'],
    properties: {
      recipeType: {
        type: 'string',
        title: 'Recipe type',
        placeholder: 'Homemade Japanese dishes',
      },
      userDatasetId: {
        type: 'string',
        title: 'Your photos',
        dataset: true,
      },
    },
  },
  steps: [
    {
      id: 'recipesGenerator',
      type: 'ObjectGenerator',
      parameters: {
        description: 'You are an experienced chef. Generate creative recipes.',
        input: '$.input.recipeType',
        schema: {
          type: 'object',
          required: ['recipes'],
          properties: {
            recipes: {
              type: 'array',
              items: {
                type: 'object',
                properties: {
                  name: { type: 'string' },
                  imagePrompt: { type: 'string' },
                },
              },
            },
          },
        },
      },
    },
    {
      id: 'recipeModelTrainer',
      type: 'ModelGenerator',
      parameters: {
        datasetId: '$.input.userDatasetId',
        settings: {
          baseModel: 'stable-diffusion-v1-5/stable-diffusion-v1-5',
          epochs: 50,
          resolution: 1024,
        },
      },
    },
    {
      id: 'recipeImageGenerator',
      type: 'ImageGenerator',
      parameters: {
        trainingId: '$.results.recipeModelTrainer.id',
        baseModel: 'stable-diffusion-v1-5/stable-diffusion-v1-5',
        images: [
          [
            '@Map($.results.recipesGenerator.recipes)',
            {
              prompt: '$$.imagePrompt',
              negativePrompt: 'blurry, low quality',
              steps: 25,
            },
          ],
        ],
      },
    },
    {
      id: 'zipOutput',
      type: 'Zipper',
      parameters: {
        sources: ['recipeImageGenerator', 'recipesGenerator'],
      },
    },
  ],
}

When this Flow runs, it:

  1. Asks the user for a recipe type and a dataset of photos.
  2. Generates a list of recipes with the ObjectGenerator.
  3. Trains a custom model on the user’s photos.
  4. Generates images using the trained model and recipe prompts.
  5. Zips everything for easy download.

Key concepts

Public vs. private Flows

  • Private Flows: Only you and your organization can access and run these. Costs deduct from your organization balance.
  • Public Flows: Anyone with the URL can run them. You can set a price per run and receive payouts.

Store

The store is a global object defined in your Flow configuration that’s available to all steps during a run. It’s useful for static data that multiple steps need — like a list of prompts or shared configuration:

{
  store: {
    styles: ['cyberpunk', 'watercolor', 'oil painting'],
    negativePrompt: 'blurry, low quality, deformed',
  },
  steps: [
    {
      id: 'imageGen',
      type: 'ImageGenerator',
      parameters: {
        images: [
          [
            '@Map($.store.styles)',
            {
              prompt: '$$',
              negativePrompt: '$.store.negativePrompt',
            },
          ],
        ],
      },
    },
  ],
}

Results

Steps can read from each other’s results using JSON Path, like $.results.previousStepId.field. The user sees a final set of widgets after the run completes (images, JSON objects, downloadable zip, etc.). See Results & Widgets.

Costs and billing

Each step has an associated cost that deducts from the organization balance. When a Flow is public and has a price, external users pay via Stripe and you receive the payout. See Billing for the full pricing table.

Last updated on March 19, 2026