---
title: 'Tutorial: Import an existing YAML manifest'
path: tutorials/import-yaml
status: published
---

# Tutorial: Import an existing YAML manifest

Turn a hand-written ScaiCore YAML manifest (or one ScaiFlow emitted previously) into a flow you can edit visually.

## Why

Sometimes a Core gets bootstrapped outside ScaiFlow — a team starts with `vim manifest.yaml`, deploys via `curl`, then later wants the canvas UX. The `scaiflow import` command rehydrates the YAML back into a flow JSON.

## CLI

```bash
scaiflow import my-manifest.yaml --out my-flow.flow.json
```

Output:

- A flow JSON file conforming to the v2 schema.
- Auto-layout — nodes stacked 120 px apart in the YAML step order.
- For ScaiFlow-emitted YAML: lossless reconstruction (every step carries `meta.{node_id, node_kind, node_label, node_config}` so the original tree is rebuildable byte-for-byte).
- For hand-edited YAML: best-effort — unrecognized steps land under `metadata.unknown_steps` for you to inspect.

If you omit `--out`, the JSON is printed to stdout.

## Then in the canvas

Save the flow JSON file. In the canvas toolbar:

- **Import** → pick the JSON file. The flow opens as an unsaved local-only flow.
- **Save** (the canvas's Save) — persists it to your tenant as a new flow.

## What round-trips losslessly

ScaiFlow-emitted YAML carries enough metadata under per-step `meta:` keys to reconstruct the original flow JSON identically:

```yaml
steps:
  - llm_turn: "Classify intent"
    meta:
      node_id: node_classify
      node_kind: llm_flexible
      node_label: "Classify Intent"
      node_config: { goal: "...", model: "fast", output_schema: {...} }
```

Plus the multi-model registry under `core.scaiflow_meta.models`, source linkage under `core.scaiflow_meta.{source_id, source_version, scaicore_target}`, and publish intents under `core.scaiflow_meta.{publish_as_model, model_visibility_group_ids}`.

A canvas → YAML → canvas round-trip produces an identical flow.

## What's lossy

Hand-edited YAML (no `meta:`):

- **Unknown step keywords** (`llm_turn: "..."` with no `meta`) — preserved as `metadata.unknown_steps[]` entries in the imported flow JSON. You can manually translate them to canvas node kinds.
- **Models** — if there's no `scaiflow_meta.models`, the importer lifts the single `core.model: "<provider>/<model>"` into a one-entry `models: [{role: "primary", ...}]`. Multi-model registries can't be recovered from a single-string field.
- **Conditional branching** — if the YAML uses `branch:` placeholder steps without `meta`, branch wiring is lost. The importer adds the nodes but you'll have to re-wire conditional edges by hand.

## Common workflow: edit YAML, deploy via canvas

```bash
# 1. Edit the YAML directly (e.g. to add a new step inline-fast)
vim my-core.yaml

# 2. Import back to a flow
scaiflow import my-core.yaml --out my-flow.flow.json

# 3. Open in canvas, save, deploy via the UI
```

## Common workflow: take a canvas flow off-line

```bash
# 1. Export from the canvas (toolbar → Export)
#    → my-flow.flow.json

# 2. Compile to YAML for editing
scaiflow compile my-flow.flow.json --out my-core.yaml

# 3. Edit, deploy directly via curl
curl -X POST "${SCAIGRID_HOST}/v1/modules/scaicore/cores" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/yaml" \
  --data-binary @my-core.yaml

# 4. Later, re-import the edited YAML back to canvas if you want
scaiflow import my-core.yaml --out my-flow-v2.flow.json
```

## Next

- **[CLI reference](../reference/cli)** — full `import` command options.
- **[Concepts: Compilation targets](../concepts/ir-and-compilation-targets)** — YAML vs. IR vs. `.scai` text.
