# Branches and decisions

> Building flows · https://spoletta.com/docs/branches

A flow branches on the state of an object. Whoever sets the state, an agent, a person or a rule, decides which processes run next. This page builds a ticket triage that takes one of two paths and rejoins.

*Diagram: Classify reviews the Ticket and decides bug, so Attempt fix runs. Summarize needs only one of Spec and Fix.*

## An agent picks the branch

1.  **Give the object its states**
    
    Right-click *Ticket* and **Add state** twice: `bug` and `feature`.
    
2.  **Have an agent review it**
    
    Add an agent *Classify* that takes Ticket, and link it back to Ticket itself (not a state). Select that link and press **Decide a state** to tick both states. Because Classify takes Ticket too, it is a **review**: Ticket keeps the content the person entered and only gains a state.
    
3.  **Start each branch from a state**
    
    Drag from the `bug` pill's handle onto *Attempt fix*, and from `feature` onto *Write spec*. These are **event** links: each process runs when Ticket enters its state.
    

> **Note:** The prompt says what tells the states apart: *Decide whether the Ticket reports a bug (something that used to work, or should work, doesn't) or asks for a feature.* The engine adds the states to choose from.

## Rejoining the branches

Summarize takes both Spec and Fix, but only one of them is ever generated. Left alone it would wait forever and the run would end without a summary. Two ways to rejoin:

### A quorum

Set **Needs** in Summarize's settings to `1`. It runs once one of what it takes exists. This is the simplest rejoin when the branches are triggered by events.

### Conditions

Alternatively, make the branches **conditions**, so the branch not taken is *skipped* and its output is settled as absent. Summarize then runs with whichever exists, no quorum needed.

A condition is checked as soon as its process is ready, so it must be on an object that only exists once the decision is made. Ticket won't do: it exists, in no state, from the moment the person enters it. Have Classify generate a separate *Triage* object in the state it decides, link both branches from Triage's states, select each link and choose **only if in it**. Both branches also take Ticket plainly, for its content.

OPL:

```text
Classify yields Triage as bug or feature, deciding which.
Attempt fix occurs if Triage is bug, and is skipped otherwise.
Write spec occurs if Triage is feature, and is skipped otherwise.
Summarize takes Fix.
Summarize takes Spec.
```

> **Event or condition?:** Prefer conditions when a branch is decided once, and events when an object can enter a state many times, as in [review loops](https://spoletta.com/docs/loops.md).

## Branching on a value with rules

Scripts and Sentry steps can't decide a state, and sometimes the branch is just arithmetic. Give the states [rules](https://spoletta.com/docs/states.md#rules) instead. A *Health* object with states `down` (`status != 200`), `slow` (`ms > 2000`) and `fine` (`ms <= 2000`) comes out in the first state whose rule holds, and the processes linked from those states run. It also turns an agent's numeric judgement into a branch, such as `confidence >= 0.8`.

## Fanning in: several opinions

A quorum also gathers votes. Ask three agents, each with a different **Model**, whether a migration is safe; each yields its own verdict with states `safe` and `unsafe`. The process that runs the migration takes the Migration plus each verdict through a condition on `safe`, with **Needs** set to `3`.

> **Count everything a quorum counts:** Inputs count towards a quorum once they exist and hold their conditions. The Migration always counts, so *needs 3* means “the Migration plus two safe verdicts”. A quorum of 2 would run on a single safe verdict.
