Workflows: overview
A workflow is a state machine that drives approvals and automation over your data. You author it
once in a *.workflow.xml file (or draw it in the visual designer), and the engine walks a record
through a graph of nodes connected by transitions — pausing for human approvals, firing
notifications, running SQL, and stamping a business status as it goes.
Workflows are versioned and company-scoped, and every run is bound to a single entity — most often a wizard’s submitted form response, or a row created by a view.
The state-machine model
Section titled “The state-machine model”A workflow is a directed graph. Nodes are the states; transitions are the edges between them.
┌─────────────────────────┐ │ Start │ └────────────┬────────────┘ │ Submit ▼ ┌─────────────────────────┐ │ Action · notify Purch. │ └────────────┬────────────┘ │ ToReview ▼ ┌─────────────────────────┐ │ Approval · review │ └──────┬───────────┬──────┘ Approved Rejected ▼ ▼ ┌─────────────────────────┐ │ End │ └─────────────────────────┘Node types
Section titled “Node types”The engine recognises seven node types (the NodeType enum). Only some pause the flow; the rest
auto-advance.
| Type | Purpose | Advances |
|---|---|---|
| Start | Entry point; every workflow needs exactly one. | Auto — fires its single outgoing transition on start. |
| Approval | Waits for one or more people to approve/reject. | Pauses until the approval gate is satisfied. |
| Action | Runs a side effect — a notification or SQL. | Auto — executes, then follows its single outgoing transition. |
| Decision | Branches on transition Expressions. |
Auto — takes the first passing outgoing transition (by Order). |
| Assignment | Sets the instance’s assigned role/user. | Auto. |
| Standard | A generic waypoint / manual task. | Waits for an external transition. |
| End | Terminal; marks the instance Completed. |
Terminal. |
A transition carries From, To, an optional human Label, an optional guard Expression, an
Order (for Decision branching), a RequireComment flag, and an optional FlowStatus. See
Authoring a workflow for the full element reference.
Two statuses, kept separate
Section titled “Two statuses, kept separate”Every instance tracks two independent status fields:
- Lifecycle
Status— the engine’s own state:Active,Completed, orCancelled. - Business
FlowStatus— a free-text label your workflow chooses (e.g.Awaiting Purchasing Approval,Approved,Rejected). It is sticky: a transition only overwrites it when it carries a non-emptyFlowStatus, so it persists across transitions that leave it blank. It shows in the Workflow Instances grid and is available to guards as@FlowStatusand to notification templates as{{FlowStatus}}.
How an entity or wizard enters a workflow
Section titled “How an entity or wizard enters a workflow”An instance is always bound to one entity — (EntityType, EntityId). There are two hooks that start
or drive a workflow, both authored on the source side (the wizard or view), not in the workflow XML:
- Wizard Terminal handoff — a wizard’s Terminal node names a
WorkflowNameand starts it bound toWizardFormResponse, passing the wizard’s collected fields (and anySetVariablevalues) as the workflow context. - View hooks — a table/form view can declare
<WorkflowStartup>(start a workflow after a successful insert, over the new row) or<WorkflowTransition>(fire a transition after a submit). See SQL & view hooks.
The starting context becomes the instance’s ContextData (JSON). Every @variable in it is visible
to transition expressions, approval resolution, action SQL parameters, and notification templates.
Approvals and SLA at a glance
Section titled “Approvals and SLA at a glance”- Approvals create pending records that approvers act on through the built-in Pending
Approvals list and the
WF_ApprovalForm— no custom form needed. TheApprovalConfigType(Any/Sequential/Parallel) decides when the gate is satisfied. See Engine, approvals & SLA. - SLA blocks (
<Sla TimeoutMinutes Escalation ReminderMinutes>) declare deadlines on Approval nodes and a background hosted service polls for breaches. See the same page for the current implementation status.
A small annotated example
Section titled “A small annotated example”<Workflow Name="ProductApproval" Slug="product-approval" Label="Product Approval" EntityType="WizardFormResponse" Category="Inventory"> <Nodes> <Node Key="Start" Type="Start" Label="Start"> <Position X="30" Y="20" Width="140" Height="80" /> </Node>
<!-- Action node: fires an in-app notification, then auto-advances --> <Node Key="NotifyPurchasing" Type="Action" Label="Notify Purchasing"> <Position X="10" Y="200" /> <ActionConfig> <ActionType>AppNotification</ActionType> <Payload><To>Role:Purchasing</To> <Message>New product request "{{ProductName}}" is awaiting review.</Message></Payload> </ActionConfig> </Node>
<!-- Approval node: pauses until a Purchasing member decides --> <Node Key="PurchasingReview" Type="Approval" Label="Purchasing Review"> <Position X="360" Y="200" /> <Sla TimeoutMinutes="1440" Escalation="Notify" ReminderMinutes="720" /> <ApprovalConfig> <Type>Any</Type> <Approvers> <Approver Type="Role" Value="Purchasing" /> </Approvers> <OnApprove Transition="Approved" /> <OnReject Transition="Rejected" /> </ApprovalConfig> </Node>
<Node Key="End" Type="End" Label="Done"> <Position X="1030" Y="370" Width="160" Height="80" /> </Node> </Nodes>
<Transitions> <Transition From="Start" To="NotifyPurchasing" Label="Submit" Order="1" FlowStatus="Pending Review" /> <Transition From="NotifyPurchasing" To="PurchasingReview" Label="ToReview" FlowStatus="Under Review" /> <Transition From="PurchasingReview" To="End" Label="Approved" FlowStatus="Approved" /> <Transition From="PurchasingReview" To="End" Label="Rejected" RequireComment="true" FlowStatus="Rejected" /> </Transitions></Workflow>The full worked samples are ProductApproval.workflow.xml and PurchaseOrderApproval.workflow.xml
in sample/Inventory/models/workflows/.
Where to go next
Section titled “Where to go next”- Authoring a workflow — the complete
*.workflow.xmlelement and attribute reference. - Engine, approvals & SLA — how the engine executes, resolves approvers, and runs actions.
- Versioning & company scoping — version pinning and per-company flows.