# Flows Overview

> Visual workflows that chain apps together.

**URL:** https://inference.sh/docs/flows/overview
**Last updated:** 2026-09-20

---

**Visual workflows that chain apps together.**

Flows let you build multi-step processes without code. Connect apps, map data between them, and create powerful pipelines.

---

## Why Flows?

Some tasks need multiple steps:

- **Image Pipeline**: Generate → Upscale → Remove Background → Resize
- **Content Creation**: Research → Write → Edit → Format
- **Data Processing**: Extract → Transform → Analyze → Report

Instead of running each app manually, build a flow once and run it with one click.

---

## Creating a Flow

### From the Workspace

1. Go to [Flows](https://app.inference.sh/flows)
2. Click **New Flow**
3. The visual editor opens

### The Editor

```
┌───────────────┬──────────────────────────────────────────────────┐
│               │                                                   │
│   Nodes       │                   Canvas                          │
│               │                                                   │
│   ┌─────────┐ │    ┌───────┐     ┌───────┐     ┌───────┐        │
│   │ + Input │ │    │ Input │ ──▶ │ App A │ ──▶ │Output │        │
│   └─────────┘ │    └───────┘     └───────┘     └───────┘        │
│               │                                                   │
│   ┌─────────┐ │                                                   │
│   │ + App   │ │                                                   │
│   └─────────┘ │                                                   │
│               │                                                   │
│   ┌─────────┐ │                                                   │
│   │ + Output│ │                                                   │
│   └─────────┘ │                                                   │
│               │                                                   │
└───────────────┴──────────────────────────────────────────────────┘
```

### Building Step by Step

1. **Add an Input node** — Define what the flow accepts
2. **Add App nodes** — Drag apps from the sidebar
3. **Connect nodes** — Click and drag between ports
4. **Map data** — Configure how outputs flow to inputs
5. **Add an Output node** — Define what the flow returns

---

## Connecting Apps

### Visual Connections

Drag from an output port to an input port:

```
┌──────────────┐          ┌──────────────┐
│  Image Gen   │          │   Upscale    │
│              │          │              │
│      image ──┼──────────┼──▶ image     │
└──────────────┘          └──────────────┘
```

### Data Mapping

Click a node to configure how data flows:

```yaml
# Upscale node receives:
image: "{{image_gen.output.image}}"   # From previous app
scale: 2                               # Static value
```

### Mapping Syntax

| Pattern | Example | Description |
|---------|---------|-------------|
| Previous output | `{{app_name.output.field}}` | Data from another node |
| Flow input | `{{input.field}}` | Data from flow input |
| Static value | `"hello"` or `42` | Fixed value |
| Nested | `{{app.output.data.nested}}` | Access nested fields |

---

## Example: Image Enhancement Flow

### The Flow

```
Upload Image ──▶ Upscale (2x) ──▶ Enhance Colors ──▶ Download
```

### Configuration

**Input Node:**
- `image` (file) — The image to enhance

**Upscale Node:**
- App: `esrgan`
- Input: `image` ← `{{input.image}}`
- Input: `scale` ← `2`

**Enhance Node:**
- App: `color-enhance`
- Input: `image` ← `{{upscale.output.image}}`
- Input: `saturation` ← `1.2`

**Output Node:**
- `result` ← `{{enhance.output.image}}`

### Running

1. Click **Run**
2. Upload an image
3. Watch each step execute
4. Download the enhanced result

---

## Run via API

Trigger a saved flow from code without deploying it as an app.

API and CLI runs use the flow's published version when one exists, and the current draft otherwise. `flow_version_id` on the run shows which version ran.

**CLI** — `belt flow run <ref>` with optional JSON input and `-f` to stream progress. `<ref>` is `namespace/name` or a flow ID. Input resolves from `--input`, a positional argument, or piped stdin (in that order):

```bash
belt flow run myteam/voice-pipeline --input '{"text":"hello"}' -f
belt flow run abc123 '{"text":"hello"}' -f              # short ID; positional input
echo '{"text":"hello"}' | belt flow run myteam/voice-pipeline -f   # stdin
belt flow runs
belt flow run-get <run-id> -f
```

→ [CLI setup — JSON input](/docs/extend/cli-setup#running-apps)

→ [CLI setup — Flows](/docs/extend/cli-setup#flows-cli)

**REST** — `POST /flowruns` with the flow ID and inputs (requires `flows:execute` scope):

```bash
curl -X POST https://api.inference.sh/flowruns \
  -H "Authorization: Bearer inf_your_key" \
  -H "Content-Type: application/json" \
  -d '{"flow":"flow_abc123","input":{"image":"file_abc"}}'
```

The response includes a `task_id` — use the [Tasks API](/docs/api/rest/tasks) for status, logs, and cost. Stream per-step updates with `GET /flowruns/{id}/stream` or `GET /flowruns/{id}/tasks/stream`.

**JavaScript SDK:**

```typescript
const run = await client.flowRuns.create('flow_abc123', { image: 'file_abc' });
```

→ [Flow Runs API](/docs/api/rest/flow-runs) — list, cancel, clone, and SSE streams

If you **deploy the flow as an app**, callers use `POST /run` with the app ref instead — see [Deploying Flows as Apps](#deploying-flows-as-apps) and [Running Apps](/docs/apps/running).

---

## Flows as Agent Tools

Flows become powerful agent tools. Add a flow to an agent just like an app:

```
You: Enhance this photo and make it ready for Instagram

Agent: I'll use the image-enhancement flow to process your photo.
       [Running image-enhancement flow...]
       
       Done! Here's your enhanced image, optimized for Instagram.
```

The agent sees the flow as a single tool, but it executes all the steps.

---

## Deploying Flows as Apps

Turn your flow into a versioned app:

1. Open your flow
2. Click **Deploy as App**
3. Configure:
   - Name
   - Description
   - Category
4. Click **Deploy**

Now your flow:
- Has its own API endpoint
- Can be versioned
- Appears in the Grid
- Can be used by anyone (if public)

---

## Flow Execution

When a flow runs:

```
┌─────────────────────────────────────────────────────────────┐
│  Flow: image-enhancement                                     │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  ● Input          ✓ Complete                                │
│    └─ image uploaded                                        │
│                                                              │
│  ● Upscale        ✓ Complete (12s)                          │
│    └─ 512x512 → 1024x1024                                   │
│                                                              │
│  ● Enhance        ◐ Running...                              │
│    └─ Applying color enhancement                            │
│                                                              │
│  ○ Output         ○ Pending                                 │
│                                                              │
└─────────────────────────────────────────────────────────────┘
```

Each step shows:
- Status (pending, running, complete, failed)
- Duration
- Logs and progress

In the v2 flow editor, utility nodes (gate, selector, merge, constant) create no task. The editor reads a node's status from its task in `node_tasks` when it has one, and from `node_statuses` on the flow run otherwise (see [Flow Runs API: Per-node progress](/docs/api/rest/flow-runs#per-node-progress)).

| Node | Run-time feedback |
|------|-------------------|
| **Utility nodes** | Border follows status: purple while ready or running, green when completed, red when failed or cancelled, grey when blocked |
| **Gate** | Status pill reads **passed** when the condition was true and **blocked** when it was false |
| **Constant**, **Merge** | Preview of `node_outputs[nodeId].value` (for example `→ 42`). The merge preview is cut at 80 characters |

The output panel shows the flow's output when it arrives, and a loader while the run is in progress without output. When the run ends without output:

| Flow run status | Output panel |
|-----------------|--------------|
| Completed | **no output yet** (for example, the output mappings point at a blocked branch) |
| Failed | **flow error** with the run's error message |
| Cancelled | **flow cancelled** |

---

## Tips

### Start Simple

Begin with 2-3 apps, then expand:

```
❌ Don't: Build a 10-step flow immediately
✓ Do: Start with 2 apps, test, add more
```

### Name Nodes Clearly

```
❌ Don't: step1 → step2 → step3
✓ Do: generate_image → upscale → remove_bg
```

### Test Each Connection

Run the flow after adding each new node to catch issues early.

---

## What's Next?

- [**Agents**](/docs/agents/overview) — Use flows as agent tools
- [**API & SDK**](/docs/api/overview) — Run flows programmatically
- [**Extending Apps**](/docs/extend/extending-apps) — Build custom apps for your flows
