Borago Board logo Borago Board

Home / Docs / Reference

Flows reference

How a Borago Board flow works. How its steps are analysed, where code runs, the guards, every schedule, task hooks, run records.

A flow is a few steps written in plain language, joined in order, that run on a schedule, when a task reaches a column, or when Run is pressed. When the flow is saved, a model reads the steps once and decides which are ordinary logic, writing the code for those, and which need a model each time. The code runs inside the project's container, never inside the app. Flows belong to a project and are reached from the project's Flows button.

Why a flow is not a task

A task pays for a full agent run and does the work slightly differently each time. Most of what people want automated is one model call and a few lines of logic, so a flow splits the work by kind.

Kind of stepWhat it isCost per run
CodeDeterministic. Reshaping data, arithmetic, dates, an HTTP call, reading a file, running a commandNothing. The code is written once at analysis and re-runs identically for ever
AINeeds judgement. Summarising, classifying, drafting, deciding on contentOne model call
DataNeither. A constant, a URL, some reference textNothing

A flow is not a general workflow engine. There are no loops, no conditional branches, no parallel steps and no sub-flows. A generated code step cannot be edited by hand. A flow cannot be shared between projects.

The analysis

PropertyValue
When it runsIn the background, after a save that changed the steps, on the desktop app. The edit lands at once and the editor follows the analysis live
What it doesReads the whole flow and decides, step by step, whether a step can run as plain code, needs a model, or only carries data, and writes the code for the steps that can run as code
The role it usesThe project's Flows role in the project's AI Roles tab. Unset, its service is the pre-run review role's, then the task runner's. Its model is the review role's only when both are on that service, otherwise that service's cheap default. It is the only role that writes code which later executes
A step the model did not mentionBecomes an inert data step, with a warning
A failed analysisNever blocks the save. The flow stays saved and usable, and the reason is shown on the flow
StalenessThe analysis remembers the steps it was made from. Editing a step's text or label makes it stale. Moving a card on the canvas does not
The buttonsAnalyse when the flow is unanalysed or stale, Re-analyse otherwise. A flow edited in the browser or on the phone is saved without analysis and reads Edited since analysis until it is analysed on the desktop

The list page shows one of five badges per flow: Not analysed yet, an analysing badge while the model reads it, Analysis failed, Edited since analysis and Ready. Not analysed is deliberately not the same as analysed and found nothing to do.

Where generated code runs

Every code step runs inside the project's Docker container, through the same command path the agent's own commands take. The code was written by a model from a sentence a person typed, so it is never run in the app's own process, where it would have the person's files, database and keychain. The project's environment variables are available to it at that moment, exactly as for a task run, the terminal and a script. If the project has no running container, the code step fails and the run fails with it.

Guards

A flow is the first thing in the app that runs with nobody watching, so the guards are the design.

GuardRule
No overlapping runsA flow that is already running does not start again. A 15-minute flow that takes 20 minutes never accumulates workers
A changed flow must be re-analysedA stale analysis blocks the run. The editor greys out Run on the keystroke and the desktop refuses it, because code written for text that has since changed is the failure that looks like success
Per-step ceiling120 seconds. A hung step does not hold a scheduled run open all night
Per-run ceiling600 seconds, after which the run is stopped
Due flows start in turnA flow starts within a minute of its due time. When several are due at once they start a few at a time
Off until switched onA new flow, and a copy of a flow, arrives switched off. It runs by itself only once On is ticked on the list page
Missed windows are never caught upA laptop shut for three days runs an hourly flow once, at the next due time, not 72 times. The one exception is the every-N-minutes schedule, which after a gap longer than one period runs once, now
A failed step skips what depends on itSteps that never depended on the failed one still run. The dependent ones are recorded as skipped, which reads differently from failed
No steps, or an invalid graphThe run is refused and recorded as blocked

A refusal produces a run record marked blocked rather than a bare error, because a scheduled flow that quietly declines to run is the thing nobody can debug.

Schedules

The trigger is chosen on the flow's page under When it runs. Quick choices come first, then Or set it exactly with a kind and its fields.

Quick choiceWhat it sets
ManuallyOnly when Run is pressed
Every 15 minutesEvery 15 minutes
HourlyEvery hour at minute 0
Daily at 09:00Every day at 09:00
Weekly on MondayEvery Monday at 09:00
Monthly on the 1stThe first day of every month at 09:00
When any task is DoneWhen any task in the project reaches Done
When any task is BlockedWhen any task in the project reaches Blocked
Exact kindFields
Only when I press RunNone
Every N minutesEvery (minutes), at least 1
Every hourMinute
Every dayHour and Minute
Every weekDay (the weekday), Hour and Minute
Every monthDay of the month (1-28), Hour and Minute
When a task moves to a columnColumn (any of the board's six columns) and Which task, either Any task in this project or one task named by its number and title

Times are the local time of the machine that runs the flow, because that machine is the desktop and the person who wrote "every day at 09:00" is sitting at it. What is stored is a real instant, and a daylight-saving change lands on the right wall-clock time. A machine that changes time zone re-derives its next run from the new local calendar. A task-column trigger and the manual trigger have no next time on the clock. The list page shows the next due time beside a switched-on flow.

Task hooks

A task reaching a column can start a flow from two directions, and both are one mechanism.

DirectionWhere it is setWhat starts
The flow watches the boardThe flow's trigger When a task moves to a columnEvery switched-on flow watching that column, narrowed to one task when Which task names one
The task names its hooksThe task's hooks field, on the create form, the inline editor and the task's edit mode. Collapsed by defaultThe flows and project scripts the task names for Done or Blocked. A task's own hooks are limited to those two columns and to 10 entries per column
RuleDetail
What counts as a moveA person dragging the card, and a run ending. Both count the same way
No change, no hookSaving a task's title while it sits in Done fires nothing
Once per flowA flow both watching the column and named by the task runs once
Only where it can runHooks fire on the desktop, which has the model and the container. The cloud applying a synced status change starts nothing
Hooks follow the taskThe task's hooks sync with the task. A named flow is identified by an id that is the same on every device
A deleted scriptIts entry stays on the task, so the hook reads as pointing at a removed script rather than as never having existed

What a run records

FieldValue
StatusRunning, ok, error, blocked or canceled. Blocked means the run could not start, and is a different thing from a step failing
What started itManual, or schedule. A task hook counts as schedule
Per stepIts label, its kind, ok or error or skipped, how long it took, its output and any error
The outputThe last step's output
The errorThe first failing step's error, or the reason the run was refused
CostThe estimated cost of the run's model calls
HistoryThe newest 50 runs per flow. Older ones are deleted for good

Run records stay on the machine that produced them. The flow itself syncs, so every device sees the steps, the schedule, the switch and the last outcome with its time. Only the transcripts stay local. That is the one place a flow differs from a task, whose runs do sync, and the reason is that a scheduler produces rows nobody asked for. Stop on the flow's page ends a running flow, which is recorded as canceled.

The failure notification

A run that ends in error or blocked raises a Flow failed notification, titled with the flow's name and either "failed" or "could not run", with the error as its body. A click opens the project's flows page. It is its own kind because a flow has no other surface while it fails every hour with nobody watching. See Notifications reference.

Which model a flow uses

WhatModel
The analysisThe project's Flows role. Unset, the service is the pre-run review role's, then the task runner's. The model is the review role's only when both are on that service, otherwise that service's cheap default
An AI stepThe same, unless the step names its own service and model in its Project default and Service default pickers. A step that names a service and no model gets that service's default model
A model from the wrong provider on a stepDiscarded rather than sent, so a stale override left behind by a service change cannot fail the step on every tick

Surfaces

SurfaceCan
Desktop appEverything. Create, edit, analyse, switch on, run, stop, read history, delete
Browser on the local networkThe same, since it is served by the desktop
Cloud browser and phoneCreate, edit, switch on and off, copy, delete, and read the schedule and the last outcome. Run and Analyse are shown and disabled with the reason, since both need the container and the model on the desktop. A run is not relayed to the desktop

Related: Flows, A nightly job with a flow, Notifications reference, Containers, The terminal, scripts and the file browser.

Source as Markdown: /docs/reference/flows.md · Updated 2026-10-07 · Was this right? Tell us