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

# Anatomy of a workflow

> The top-level shape of a workflow — and the terminal output node that closes every path.

Every workflow is a JSON object with five top-level concerns: metadata, parameters, nodes, edges, and the run context that those nodes share at execution time.

## Top-level shape

```jsonc theme={null}
{
  "id": "wf-...",
  "name": "...",
  "description": "...",
  "status": "draft" | "active" | "archived",
  "version": 2,
  "createdAt": "...",
  "updatedAt": "...",
  "createdBy": "...",
  "parameters": [ ... ],
  "nodes": [ ... ],
  "edges": [ ... ]
}
```

See [Variables & templating](/workflows/variables-templating) for how `parameters` and node outputs are referenced. See [Node reference](/workflows/nodes/overview) for the per-node `data` schemas.

## Terminal output nodes

Every path through a workflow ends in an `output` node. The output carries:

* a **label** (`APPROVED`, `REJECTED`, `IN_REVIEW`, `REPORTED_TO_REGULATOR`, …) — surfaces as the terminal state in the audit log.
* a **schema** — explicit list of fields written into the final decision record.
* an optional **`returnAllFields`** boolean — if true, the entire run context is persisted with the decision; otherwise only the declared schema fields.

```jsonc theme={null}
{
  "id": "out-approved",
  "type": "output",
  "data": {
    "label": "APPROVED",
    "returnAllFields": false,
    "schema": [
      { "name": "case_id",          "type": "string",  "required": true },
      { "name": "decision",         "type": "string",  "required": true },
      { "name": "risk_score",       "type": "integer", "required": true },
      { "name": "risk_band",        "type": "string",  "required": true }
    ]
  }
}
```

A workflow can have multiple terminal outputs — one per resolution class. Common shapes:

| Workflow type              | Typical terminals                                         |
| -------------------------- | --------------------------------------------------------- |
| Onboarding (KYC / KYB)     | `APPROVED`, `IN_REVIEW`, `REJECTED`                       |
| Transaction monitoring     | `APPROVED`, `BLOCKED`, `REPORTED_TO_REGULATOR`            |
| Lifecycle webhook consumer | `case_updated`                                            |
| Sub-flow                   | Single named outcome (`link_delivered`, `case_closed`, …) |

`returnAllFields: true` is used for sub-flows that pass their entire context downstream and for audit-heavy terminals (KYB approvals, regulator submissions) that benefit from the full evidence pack on the decision. Otherwise prefer an explicit `schema` — the decision record stays compact and the audit export bundles read better.
