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, an optional FlowStatus/EntityStatus,
and an optional <Sql> side effect. See Authoring a workflow for the full
element reference.
Three statuses, kept separate
Section titled “Three statuses, kept separate”- 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), stamped on the instance. 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}}. - The record’s own state column — when the Start node declares a
<Binding>, every transition carrying a status also writes it back to the business record (and optionally a remark column), so the row a user sees in a grid never drifts from the flow. UseEntityStatuson a transition when the record’s vocabulary is narrower than the flow’s. Binding is optional — skip it and only the instance moves.
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). Two things start or drive one,
both authored on the source side (the view or wizard), not in the workflow XML:
- A dispatch callback in your SQL — a view’s
<SubmitSql>/<InsertSql>, a row action, or an import’sAfterSqlreturnsSELECT 'startWorkflow' FunctionName, 'MyWorkflow', 'MyEntities', @Id;and the engine executes it server-side, in the same request.transitionEntityWorkflow,transitionWorkflowandworkflowSubmitApprovaldrive an existing instance the same way. See Starting & advancing workflows. - 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.
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 —
see what the context carries.
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.