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

# Workflow file

> Define the orchestration envelope for a Fabriqa workflow in workflow.yaml.

# Workflow file

`workflow.yaml` is the orchestration envelope for one workflow.

Use it to define:

* workflow identity
* phases
* allowed relation subset
* agents
* artifact references
* connector subscriptions
* workflow shell UI defaults

Do not use `workflow.yaml` for artifact-local meaning such as:

* markdown document sections
* artifact-specific required fields
* bolt-specific execution output rules
* artifact detail metadata

That meaning belongs in artifact schema files.

## Example

```yaml theme={null}
workflow:
  id: product-delivery
  name: Product Delivery
  version: 2.0.0
  description: >
    A planning-to-execution workflow for shipping scoped product changes.
  icon: compass

phases:
  - id: plan
    name: Plan
    agent: planner
  - id: build
    name: Build
    agent: builder
  - id: validate
    name: Validate
    agent: validator

relations:
  allowed:
    - depends_on
    - validates
    - related_to

agents:
  planner: agents/planner.saf
  builder: agents/builder.saf
  validator: agents/validator.saf

artifacts:
  intent: schemas/intent.yaml
  work_item: schemas/work-item.yaml
  run: schemas/run.yaml
  walkthrough: schemas/walkthrough.yaml
  validation_report: schemas/validation-report.yaml

connectors:
  file: connectors/file.yaml

ui:
  sidebar:
    tabs:
      artifacts:
        label: Workflow
      agents:
        label: Agents
    allowed_group_by:
      - type
      - phase
      - status
    default: status
```

## Top-level reference

| Key          | Required | Purpose                                                        |
| ------------ | -------- | -------------------------------------------------------------- |
| `workflow`   | Yes      | Metadata for the workflow                                      |
| `phases`     | Yes      | Ordered execution phases and their default agents              |
| `relations`  | No       | Built-in Fabriqa relation subset allowed in this workflow      |
| `agents`     | Yes      | Agent IDs mapped to SAF file paths                             |
| `artifacts`  | Yes      | Artifact IDs mapped to schema file paths                       |
| `connectors` | No       | Workflow-subscribed connector kinds and their config-file refs |
| `ui`         | No       | Workflow-specific sidebar defaults                             |

## `workflow`

`workflow` contains the workflow's identity and display metadata.

```yaml theme={null}
workflow:
  id: product-delivery
  name: Product Delivery
  version: 2.0.0
  description: Scoped planning and execution workflow
  icon: compass
```

Rules:

* `id`, `name`, and `version` are required.
* `id` must be stable. Treat it like an API identifier.
* `description` and `icon` are optional display metadata.

## `phases`

Phases define the broad lanes of work in the workflow.

```yaml theme={null}
phases:
  - id: plan
    name: Plan
    agent: planner
```

Rules:

* `id`, `name`, and `agent` are required.
* `agent` must reference an entry in `agents`.

Use phases for:

* high-level planning stages
* execution stages
* operations stages

Do not use phases for:

* every fine-grained internal step in an agent prompt
* artifact-specific review states

Artifact-specific states belong in artifact lifecycles.

## `relations`

`relations.allowed` tells Fabriqa which built-in relation labels are valid in this workflow.

```yaml theme={null}
relations:
  allowed:
    - depends_on
    - implements
    - validates
    - supersedes
    - related_to
```

Fabriqa ships with this built-in relation vocabulary:

* `depends_on`
* `implements`
* `validates`
* `supersedes`
* `related_to`

Rules:

* `relations` is optional.
* If `relations.allowed` is omitted, Fabriqa uses the full built-in vocabulary by default.
* If `relations.allowed` is present, it must be a subset of the built-in Fabriqa list.
* Parent-child structure is not declared here. It is derived from `parent` in artifact schema files.
* Relation vocabulary is defined per workflow, not per artifact.
* Agents choose which allowed relation to use for each artifact instance.

Use these relations for graph edges such as:

* dependency links via `depends_on`
* execution or outcome links via `implements`
* evidence links via `validates`
* replacement links via `supersedes`
* loose cross-reference links via `related_to`

Keep this at the workflow level in V1.

Why:

* the relation language should be shared across the whole workflow instance
* the UI can attach stable meaning to the built-in relations
* agents can inspect one workflow-level contract instead of inferring relation meaning per artifact

If we later need tighter controls, Fabriqa can add artifact-level relation constraints on top of the workflow-level subset. That does not need to be part of the first DSL version.

## `agents`

`agents` maps workflow agent IDs to SAF files.

```yaml theme={null}
agents:
  planner: agents/planner.saf
  builder: agents/builder.saf
```

This keeps `workflow.yaml` concise while letting each agent own its own generic kind, tool policy, and prompt file.

Each referenced SAF file declares:

* `agent.id`
* `agent.name`
* `agent.kind`
* `system_prompt`
* `tools`

## `artifacts`

`artifacts` maps artifact type IDs to schema files.

```yaml theme={null}
artifacts:
  intent: schemas/intent.yaml
  walkthrough: schemas/walkthrough.yaml
```

Rules:

* Artifact IDs must match `artifact.id` in each schema file.
* Artifact parent-child relationships are derived from the schema files, not declared here.

## `connectors`

`connectors` subscribes the workflow to built-in Fabriqa connector kinds.

```yaml theme={null}
connectors:
  file: connectors/file.yaml
```

Fabriqa owns the connector kinds and their runtime behavior.

Examples of built-in connector kinds:

* `file`
* `linear`
* `jira`

Rules:

* `connectors` is optional.
* Each entry points to a connector-specific config file.
* The workflow definition describes static mapping only.
* Workspace-level enable or disable state is not stored in the workflow definition.
* Connection selection, target workspace project selection, and other runtime settings live in Fabriqa after the workflow is activated on a workspace.
* Adding a new connector kind requires product implementation in Fabriqa.

Use connectors to:

* project artifacts into files
* map workflow artifacts into external systems
* keep workflow-specific field mapping close to the workflow definition

Do not treat connector output as the source of truth. The source of truth is still the artifact record plus its schema.

### Definition vs runtime settings

Keep these concerns separate:

* Workflow DSL:
  * which connector kinds this workflow supports
  * how artifact types map into a connector
  * which templates or field mappings the connector uses
* Fabriqa workspace runtime:
  * whether a connector is enabled for this workspace instance
  * which account or connection is used
  * which workspace project or target location is selected
  * sync state and operational settings

### File connector example

```yaml theme={null}
# workflow.yaml
connectors:
  file: connectors/file.yaml
```

```yaml theme={null}
# connectors/file.yaml
kind: file

artifacts:
  intent:
    template: templates/intent.md.tmpl
    filename: intents/{{ artifact.display_id }}.md
  walkthrough:
    template: templates/walkthrough.md.tmpl
    filename: walkthroughs/{{ artifact.display_id }}.md
```

The file connector config describes how to serialize artifacts. The actual target workspace project and export root are chosen later in Fabriqa when the workflow is active in a workspace.

### Future platform connector example

```yaml theme={null}
# workflow.yaml
connectors:
  linear: connectors/linear.yaml
```

```yaml theme={null}
# connectors/linear.yaml
kind: linear

objects:
  work_item:
    target: issue
    fields:
      title: title
      description: description
      status: state
      tags: labels
```

This keeps platform-specific mappings in the workflow definition while leaving authentication, team selection, and sync runtime to Fabriqa.

## `ui`

`ui` controls workflow-specific sidebar defaults.

Use it to define:

* sidebar tab labels
* sidebar grouping options and default

Fabriqa owns the other major workflow surfaces in V1:

* a workflow dashboard
* root artifact viewer tabs
* contextual artifact tree navigation

```yaml theme={null}
ui:
  sidebar:
    allowed_group_by:
      - type
      - phase
      - status
    default: status
```

Keep the UI config light. It should not duplicate artifact structure that already lives in artifact schema files.

### Product-defined surfaces

Fabriqa renders three workflow surfaces in V1:

* a global sidebar
* a workflow dashboard
* root artifact viewer tabs

The workflow author does not configure dashboard tabs or explorer tabs in the DSL.

```text theme={null}
+----------------------+--------------------------------------------------------------+
| Sidebar              | Main workspace area                                          |
|                      |                                                              |
| [Artifacts] [Agents] | [Dashboard] [Artifact Viewer tabs...]                        |
| Group by: Status     |                                                              |
|                      | Dashboard                                                    |
| Draft                | +------------+------------+-------------+                    |
|   INT-001            | | Draft      | In review  | Approved    |                    |
|   STORY-003          | | cards...   | cards...   | cards...    |                    |
| Approved             | +------------+------------+-------------+                    |
|   BOLT-002           |                                                              |
|                      | Artifact viewer                                             |
|                      | +--------------------------------+ +----------------------+ |
|                      | | Selected artifact document     | | Context rail         | |
|                      | | markdown page + meta row       | | tree, relations,     | |
|                      | | no duplicate child lists       | | chats, activity      | |
|                      | +--------------------------------+ +----------------------+ |
+----------------------+--------------------------------------------------------------+
```

Use the surfaces like this:

* the sidebar is the global entry point across the active workflow instance
* the dashboard is the status-oriented overview across workflow artifacts
* the artifact viewer is the contextual deep-work surface for one root context at a time

### Artifact viewer UX contract

Fabriqa owns the artifact viewer layout in V1.

The workflow author does not configure this in DSL, but should understand the product behavior:

* the document stays on the left as the primary reading surface
* markdown sections render through Fabriqa's markdown renderer in read-only mode
* metadata appears as a compact row under the title rather than large cards or chips
* child artifacts do not repeat inside the document body because hierarchy already lives in the tree
* the right rail holds contextual information for the selected artifact:
  * root tree
  * relations
  * linked chats
  * activity, collapsed by default
* the right rail is collapsible and resizable using Fabriqa's shared separator styling

The goal is a clean reading experience, closer to a markdown preview than an admin form.

### Root artifact viewer behavior

The root artifact viewer is not authored in `workflow.yaml`. Fabriqa derives it from artifact hierarchy and phases.

When the user opens an artifact from the sidebar or dashboard:

1. Fabriqa starts at the selected artifact.
2. It walks up the parent chain.
3. It stops at the first ancestor whose parent is in a different phase, or at the top root if there is no phase boundary.
4. That ancestor becomes the viewer root.
5. Fabriqa opens or focuses the viewer tab for that root artifact instance and auto-selects the originally clicked artifact in the tree.

Why this works:

* planning trees usually resolve to the top planning root such as an `intent` or `prd`
* execution outputs usually resolve to their execution anchor such as a `bolt` or `run`
* the product can show one coherent context tab instead of opening a new tab for every child artifact

Example behavior:

* click a planning `story` under an `intent` tree: Fabriqa opens the `intent` viewer and selects the `story`
* click a `walkthrough` under a construction `bolt`: Fabriqa opens the `bolt` viewer and selects the `walkthrough`

```text theme={null}
Click STORY-014 in sidebar
  -> resolve viewer root
  -> INT-002 viewer tab
  -> tree highlights STORY-014

Click WALKTHROUGH-003 in dashboard
  -> resolve viewer root
  -> BOLT-007 viewer tab
  -> tree highlights WALKTHROUGH-003
```

### `ui.sidebar.allowed_group_by`

`allowed_group_by` selects which built-in Fabriqa sidebar grouping modes are available in this workflow.

```yaml theme={null}
sidebar:
  allowed_group_by:
    - type
    - phase
    - status
  default: status
```

Important rule:

* these values are selected from a predefined Fabriqa list
* `allowed_group_by` is optional; if you omit it, Fabriqa shows all built-in grouping modes
* `default` selects the initial grouping from that predefined list or allowed subset
* workflow authors cannot invent new grouping keys here

Fabriqa currently provides this built-in grouping vocabulary:

* `type`
* `phase`
* `status`

Rules:

* `allowed_group_by` is optional. If omitted, Fabriqa can expose the full built-in list.
* `default` should be one of the `allowed_group_by` values when you provide the subset.
* the workflow definition chooses which built-in grouping modes are available
* the user can later switch between those allowed modes in the UI

Why this shape:

* `allowed_group_by` makes it clear this is a subset of product-defined options
* it matches the same subset language used by `relations.allowed`
* it avoids noisy per-option booleans such as `type_grouping_visible: true`

## How Fabriqa loads `workflow.yaml`

<Steps>
  <Step title="Load workflow envelope">
    Fabriqa reads `workflow.yaml` first to establish the workflow ID, phases, allowed relations, connector subscriptions, and sidebar UI metadata.
  </Step>

  <Step title="Load referenced files">
    Fabriqa resolves every referenced agent file, artifact schema file, and connector config file.
  </Step>

  <Step title="Build the artifact graph">
    Parent-child relationships are derived from each artifact schema file and indexed into the workflow definition.
  </Step>

  <Step title="Drive rendering and validation">
    JSON Schema validates artifact payloads. Artifact-local `document` and `lifecycle` metadata drive the artifact experience, while workflow-level `ui` provides sidebar defaults and Fabriqa derives dashboard and root-viewer behavior from the workflow structure.
  </Step>
</Steps>

## Continue reading

<CardGroup cols={2}>
  <Card title="Workflow DSL overview" icon="compass" href="/workflows/workflow-dsl">
    Go back to the Workflow DSL overview.
  </Card>

  <Card title="Artifact schemas" icon="scroll-text" href="/workflows/workflow-dsl-artifact-schemas">
    Continue into the artifact model, document sections, and lifecycles.
  </Card>

  <Card title="Agents and connectors" icon="sparkles" href="/workflows/workflow-dsl-agents-and-connectors">
    See how SAF files, prompts, and templates complete the workflow definition.
  </Card>

  <Card title="Workflow glossary" icon="book-open" href="/workflows/workflow-glossary">
    Review core workflow terms while authoring.
  </Card>
</CardGroup>
