> ## Documentation Index
> Fetch the complete documentation index at: https://docs.unpod.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Flows (legacy)

> Author flow graphs - the legacy / compliance path. Flows run compiled on the Playbook engine by default; opt into the original graph runtime with engine="flow".

<Note>
  **Flows are the legacy authoring surface.** The default engine is the
  [Playbook](/superdialog/playbooks) runtime, and a flow graph **runs compiled
  onto it by default** - `Playbook.load` detects flow JSON and converts it
  (`compile_flow`). Reach for a hand-authored graph when you need an enumerable,
  lintable spec for **compliance** or **strict determinism**. New conversational
  agents should start with [Thinking in Playbooks](/superdialog/thinking-in-playbooks).
</Note>

## What is a Flow?

A `Flow` is a directed graph: nodes (states) connected by edges (transitions), with metadata at each node (prompts, tool references, slot definitions). It's the static definition of what your dialog can do.

By default, `DialogMachine` runs a flow **compiled onto the Playbook engine** -
you pass the flow and get checkpoint semantics for free. To run the **original
graph runtime** (one `turn()` at a time, every transition authored), pass
`engine="flow"`:

```python theme={null}
from superdialog import DialogMachine, Flow

# Default: flow JSON is compiled and run on the Playbook engine
agent = DialogMachine(Flow.load("kyc.json"), llm="anthropic/claude-haiku-4-5")

# Legacy graph runtime (opt-in)
dm = DialogMachine(Flow.load("kyc.json"), llm="anthropic/claude-haiku-4-5", engine="flow")
```

<Frame>
  <img src="https://mintcdn.com/unpodai/9OLw2S-v9psMSqik/images/diagrams/superdialog-flow-graph.svg?fit=max&auto=format&n=9OLw2S-v9psMSqik&q=85&s=7f22c104753216bd9971b0139dcf3afb" alt="SuperDialog flow graph diagram showing states connected by conditional edges, including fallback and retry paths." width="1672" height="941" data-path="images/diagrams/superdialog-flow-graph.svg" />
</Frame>

## Building from a prompt

The fastest way to get started. `create_dialog_flow` makes one LLM call and generates the graph for you.

```python theme={null}
import asyncio
from superdialog import create_dialog_flow

flow = asyncio.run(create_dialog_flow(
    prompt="Confirm KYC. Ask the customer for the last 4 digits of their Aadhaar. Confirm their date of birth. Thank them on completion.",
    llm="openai/gpt-5.1",
))
flow.save("kyc.json")
```

Tips for prompts:

* Describe the goal and each step in plain language
* Mention what data you need to collect (slots)
* Describe any branching logic ("if they decline, escalate to an agent")

## Building by hand

For precise control over graph structure, construct nodes and edges directly:

```python theme={null}
from superdialog.flow import Flow, Node, Edge

flow = Flow(
    nodes=[
        Node(id="greet", prompt="Greet the customer and ask how you can help."),
        Node(id="collect_name", prompt="Ask for the customer's full name."),
        Node(id="done", prompt="Thank the customer and confirm the details.", terminal=True),
    ],
    edges=[
        Edge(from_node="greet", to_node="collect_name", condition="customer_responded"),
        Edge(from_node="collect_name", to_node="done", condition="name_collected"),
    ],
)
flow.save("manual.json")
```

## Saving and loading

Flows support JSON and YAML formats - commit them to source control alongside your code.

```python theme={null}
from superdialog import Flow

# Save as JSON
flow.save("flows/kyc.json")

# Load - auto-detects format from extension
flow = Flow.load("flows/kyc.json")
flow = Flow.load("flows/kyc.yaml")

# Explicit format loaders
flow = Flow.from_json_file("flows/kyc.json")
flow = Flow.from_yaml_file("flows/kyc.yaml")

# Load from string
flow = Flow.from_json_string(json_str)
flow = Flow.from_yaml_string(yaml_str)

# Load from dict
flow = Flow.from_config(config_dict)
```

### React Flow editor support

Flows exported from the React Flow visual editor (camelCase JSON) are automatically detected and normalized:

```python theme={null}
# Works directly - no manual conversion needed
flow = Flow.load("flows/kyc-react-flow-export.json")
```

## Multiple flows with FlowSet

A `FlowSet` holds several named flows. Use it when a conversation may branch across distinct sub-flows (e.g. main flow → escalation, billing, or FAQ).

<Note>
  `FlowSet` and `switch_flow` are **graph-engine features** - construct the machine
  with `engine="flow"`. On the Playbook engine, use multiple `journeys` and advance
  rules instead (see [Playbooks](/superdialog/playbooks)).
</Note>

```python theme={null}
from superdialog import FlowSet, DialogMachine

flowset = FlowSet({
    "main": main_flow,
    "escalation": escalation_flow,
    "billing": billing_flow,
})

dm = DialogMachine(flowset, llm="openai/gpt-4.1-mini", engine="flow")
```

Switch flows at runtime:

```python theme={null}
# Reset state on switch (default)
dm.switch_flow("escalation")

# Keep conversation history
dm.switch_flow("billing", preserve_memory=True)
```

## Validating and inspecting flows

Use the legacy `flow` CLI sub-tree to lint and visualise a flow graph:

```bash theme={null}
# Check graph structure for errors
superdialog flow lint kyc.json

# Render a Mermaid diagram
superdialog flow draw kyc.json

# Re-generate a flow graph from a prompt (legacy; `superdialog generate`
# writes a playbook instead)
superdialog flow generate "Confirm KYC." --llm openai/gpt-5.1 --output kyc.json

# Run the original graph runtime in the REPL
superdialog chat kyc.json --mode flow
```

## Migrating a flow to a playbook

A flow already runs on the Playbook engine by default. To make the conversion
explicit - and to keep authoring in the playbook format going forward - compile
it:

```bash theme={null}
# Compile flow JSON to a playbook YAML you can edit
superdialog playbook compile kyc.json

# Or compile-and-run in one step
superdialog playbook run kyc.json
```

```python theme={null}
from superdialog import Flow
from superdialog.playbook import compile_flow, coverage_report

flow = Flow.load("kyc.json")
pb = compile_flow(flow)                 # single-journey "main" playbook
report = coverage_report(flow, pb)      # lossless proof
assert not report.unmapped_nodes
assert not report.unmapped_edges
assert not report.unmapped_actions
```

`compile_flow` is lossless by construction; `coverage_report` lists anything
that didn't map (any entry is a compiler bug). Run it in CI next to the compiled
artifact. See the [API Reference](/superdialog/api-reference#migrating-flows)
for the full mapping table.

## Flow versioning

Because flows are plain JSON files, they work naturally with git:

```bash theme={null}
git diff flows/kyc.json      # see what changed
git log flows/kyc.json       # see history
git blame flows/kyc.json     # see who changed what
```

Pin a specific flow version by checking out a commit hash - useful for A/B testing different flow designs against the same eval corpus.
