Skip to main content

What are workflows?

You've seen two ways to make a Powerhouse system react to something. An editor reacts to a person. A processor reacts to the operation log — but it's code you write, review, build and deploy, and changing it means another release.

A workflow is the third way. Something happens, and a chain of steps runs. The difference is that you assemble it from blocks in Connect rather than writing it, so the person who understands the process can change it without waiting on a deploy.

A workflow is a document​

A workflow is not a config file or a row in the runtime's database. It's a Powerhouse document of type powerhouse/workflow, living in a drive alongside your other documents. So it inherits what every document gets: an operation log of every edit, sync across s, history you can replay, and the same permissions model.

Editing a workflow in Connect dispatches operations. Two people can edit one. You can see who changed a step and when.

A workflow document holds two copies of the workflow. The draft is what you edit. The published copy is a snapshot the draft takes when you publish. Triggers and runs use the published copy, so an edit reaches production only when someone publishes it, and a workflow that was never published can't be enabled.

The parts​

trigger ──▶ step ──▶ branch ──true──▶ step ──▶ step
└───false──▶ step

The trigger is the one thing that starts a run. A workflow has exactly one — a new row appearing in an external service, a webhook delivery, a schedule, or a document event on the reactor itself. A workflow with no trigger is a draft that can't do anything yet.

Steps are the work. Each names one action belonging to one piece, which you'll meet in the next lesson, plus the configuration that action needs. A step's config can refer to the trigger payload and to earlier steps' output, which is how data moves down the chain. A step marked skip is passed over at run time: it records a null output and the run continues on its next port.

Edges connect steps, and each leaves its source through a named port. A plain step has a next port; a branch has true and false; any step also has an error port, so you can route a failure somewhere useful instead of just failing the run.

Decisions are made by a branch step rather than by clever expressions on the edges: the expression language is deliberately a lookup, not a small programming language, so {{steps.check.output.severity}} resolves a value but {{a == b}} does not compare anything. The authoring reference has the syntax and the branch block.

Variables are named values a workflow carries, read as {{variables.<key>}}. A variable can be typed (TEXT, NUMBER, BOOLEAN or JSON), and its value is coerced when a run starts. A SECRET variable holds a reference to a stored secret and resolves to the secret's value at run time.

What a run is​

When a trigger fires, the runtime starts a run and walks the published graph. Each run records the version of the published workflow it executed, so a run you inspect next month tells you what the workflow looked like then, not now.

A run ends SUCCEEDED or FAILED. Each step runs once, and a step that runs past its timeoutSeconds fails. A failed run can be rerun: the steps that succeeded replay from the run journal, and execution restarts at the step that failed.

Workflow or processor?​

Both react to things happening, and there's real overlap. The useful split:

Reach for a processorReach for a workflow
Changing it meansa code change and a deployediting a document in Connect
Good atfolding many operations into a read model, computed views, anything needing a real functioncalling services, moving data between them, decisions a reader can follow
Who owns ita developerwhoever owns the process

A workflow can't call a function you wrote — if a step needs a calculation, that calculation has to live somewhere a workflow can reach: in a reducer, behind a mutation, or inside an action of a piece your package ships. That last option is the subject of the Building a piece tutorial, and it's what makes workflows extensible rather than limited to what ships in the box.

Where the parts run​

Two halves, and they're switched on separately:

  • The runtime lives in the reactor (Switchboard). It watches triggers, starts runs and executes steps. Turn it on with workflows.enabled in powerhouse.config.json.
  • Workflow Studio lives in Connect — the canvas you author on, plus the list of workflows, connections and runs. Turn it on with connect.app.workflowsEnabled.
{
"workflows": { "enabled": true },
"connect": { "app": { "workflowsEnabled": true } }
}

Both default to off. They're independent: a headless reactor can run workflows with no Connect at all, and an operator can switch the runtime on with PH_WORKFLOWS_ENABLED instead — see Configure environment.

QuizA workflow has been running in production for a month. Someone edits one of its steps. What happens to the runs that already finished?

Next: where the blocks in those steps actually come from.