| name | rules-rule-obj-flow |
| description | The primary authoring guide for Flow rules (Rule-Obj-Flow). Load this first before any examples. |
Prerequisite: Load methodology-rule-authoring first
Authoring Notes
Identity constraints
pyFlowType must always equal pyRuleName. pyWorkClass must always equal
pyClassName. These are enforced by the server and will cause save failures
if mismatched.
Flow naming
Flow names (pyRuleName / pyFlowType) cannot contain hyphens (-).
Use PascalCase or underscores. The server's KeyValidate activity rejects
names with hyphens.
Navigation map fields
pyFromTasks, pyEndingActivities, and pyStartActivity are
auto-regenerated by the Validate activity on every save. However, they may
be required in the initial create payload for the server to accept the
rule. Include them when creating a new flow; on subsequent updates they will
be overwritten by the server.
Empty class values
Use "" (empty string) for blank class entries in pyPagesAndClasses and
shape pyClassName. Do not use $None or $none — the OnBeforeDisplay
activity normalizes those to "".
Expression decision limitations
EXPRESSION-type Decision shapes (pyDecisionClass: "EXPRESSION") only accept
a bare property reference in pyImplementation (e.g., .DoNotAttachCorrespondence,
.ResolutionStatus). The property is evaluated as a boolean at runtime.
Not valid in pyImplementation:
- Function calls:
pxIsBlank(.pyRouteTo) — rejected by the expression parser
- Operator expressions:
.pyLabel == "" — not supported for EXPRESSION decisions
EXPRESSION decisions use Status connectors (pyConditionType: "Status") with
pyExpression: "true" or "false", not When/Else connectors.
For operator-based branching, use a Data-MO-Gateway-DataXOR decision with When
connectors. When connectors accept both named When rules (e.g., RunningConversionUtility)
and inline property comparisons (e.g., .pyAssignedOperator != "").
pyExpressionGadget is absent from all observed production flows and should not be
included when creating EXPRESSION decisions via the API.
ScreenFlow differences
ScreenFlow flows (pyCategory: "ScreenFlow" or "ScreenFlowStandard") use
a different Start shape class (Data-MO-Event-Start-StartScreenFlow vs
Data-MO-Event-Start), a different start shape template
(pyFromMODefName: "Start" with pyMOId: "Start62"), ScreenFlow
assignments (Data-MO-Activity-Assignment-WorkAction), and ScreenFlow
subprocesses (Data-MO-Activity-SubProcess-ScreenflowProcess with
pySubProcessCategory: "ScreenFlow"). See the flow-screenflow,
flow-shape-start-screenflow, flow-shape-assignment-screenflow, and
flow-shape-subprocess-screenflow examples.
Per-shape category stamps
Every shape carries a shape-level pyCategory that varies by flow category:
| Flow category | Shape-level pyCategory | Shape-level pyFlowType |
|---|
| FlowStandard | "FlowStandard" on all shapes | not set |
| ScreenFlow (modern) | "ScreenFlow" on Start/Assignment/Utility; "ScreenFlowStandard" on End | "ScreenFlowStandard" on End only |
| ScreenFlow (legacy 2013-imported) | absent on all shapes | absent on all shapes |
Per-shape boilerplate fields by category
FlowStandard non-Start/non-End shapes carry pyBaseClass (the work class) and pyUseCaseWorkType (short case-type name). Start and End shapes omit both. ScreenFlow shapes do not carry these fields.
pyTicketShapes also differs:
| Flow category | Start | Non-Start, non-End | End |
|---|
| FlowStandard | [] | [{ "pxObjClass": "Data-MO-Event-Exception", "pyMOName": "" }] | [{ "pxObjClass": "Data-MO-Event-Exception", "pyMOName": "" }] |
| ScreenFlow | [] | [] | [{ "pxObjClass": "Data-MO-Event-Exception", "pyMOName": "" }] |
Shape Types
Shape name prefixes
The numeric suffix is assigned sequentially. Gaps are normal (e.g., END52 does not mean 52 shapes). Uniqueness within the flow is the only requirement.
| Prefix | Shape Type | Category |
|---|
Start1 | Start (FlowStandard) | Start |
Start62 | Start (ScreenFlow) | Start |
Assignment1, Assignment2, … | Assignment — routes work to a worklist/workbasket | Assignment |
AssignmentSF1, AssignmentSF2, … | Screen flow assignment — one wizard step | Assignment |
Utility1, Utility2, … | Utility — runs an activity | Utility |
SubProcess1, SubProcess2, … | Sub-process — calls another flow | Sub-process |
SubProcessSF1, SubProcessSF2, … | Screen flow sub-process | Sub-process |
GenerativeAISubProcess1, GenerativeAISubProcess2, … | Agent — invokes an AI Agent rule | Agent |
Decision1, Decision2, … | Decision/router — branches on a condition | Decision |
GenerativeAI1, GenerativeAI2, … | GenAI shape — invokes an AI connector | GenAI |
SPLITFOREACH1, SPLITFOREACH2, … | Split-for-each — iterate and spawn parallel branches | Parallel |
FORK1, FORK2, … | Fork — split into parallel branches | Parallel |
SPLITJOIN1, SplitSplitJoin1, JoinSplitJoin1, … | Split-join gateway | Parallel |
Wait1, Wait2, … | Wait — pauses until a condition or timer | Wait |
End1, END52, END66, FLOWEND | End — terminates the flow | End |
Unsupported shape types
If the user requests a shape type that does not appear in the table above or in the pxObjClass ↔ pyFromMODefName mapping below, stop immediately and inform the user that the requested shape type is not supported. Do not attempt to author it. List the supported shape types from the table above so the user can choose an alternative.
If the current flow has pyCategory: "ScreenFlow", Approval and Agent shapes are not supported because ScreenFlow flows can only call other ScreenFlows as subprocesses.
pxObjClass ↔ pyFromMODefName mapping
pyFromMODefName | pxObjClass | Description |
|---|
Start | Data-MO-Event-Start (FlowStandard) / Data-MO-Event-Start-StartScreenFlow (ScreenFlow) | Entry point |
End | Data-MO-Event-End | Terminal point |
Assignment | Data-MO-Activity-Assignment | User task (FlowStandard) |
AssignmentSF | Data-MO-Activity-Assignment-WorkAction | Screen flow assignment |
Utility | Data-MO-Activity-Utility | Automated activity step |
SubProcess | Data-MO-Activity-SubProcess | Calls another flow |
Spinoff | Data-MO-Activity-SubProcess-Spinoff | Explicit spin-off — forks execution onto another flow in parallel. Uses both pySpinOff: "true" AND the dedicated subclass (both required). |
GenerativeAISubProcess | Data-MO-Activity-SubProcess-GenerativeAI | Agent smart shape — invokes a Rule-AI-Agent via pzAsyncAgent |
Decision | Data-MO-Gateway-Decision | Branching gateway |
GenerativeAI | Data-MO-Activity-Utility-GenerativeAI | AI connector invocation |
AskAQuestion | Data-MO-Activity-SubProcess-Conversation-Question | Conversation-flow question step (ConversationFlow only) |
SendAMessage | Data-MO-Activity-SubProcess-Conversation-Message | Conversation-flow message step (ConversationFlow only) |
ConversationFlow shapes. AskAQuestion / SendAMessage are supported when paired with pyStructureType: "ConversationFlow" — the pxObjClass is the Data-MO-Activity-SubProcess-Conversation-* subclass family.
Legacy-only — do not author. Spin / SpinEnd (Data-MO-Gateway-Spin / Data-MO-Gateway-SpinEnd) are Visio-era shapes. For spin-off patterns use Data-MO-Activity-SubProcess-Spinoff with pyFromMODefName: "Spinoff".
Common shape fields
Every shape carries these regardless of type:
| Field | Description |
|---|
pyMOId | Unique shape ID (also the PageGroup key in pyShapes) |
pyMOName | Display name on the canvas |
pyClassName | Class context for the shape |
pyFromMODefName | Shape template type |
pyCoordX / pyCoordY | Canvas coordinates |
pyWidth / pyHeight | Shape dimensions |
pyLane | Swim-lane identifier |
pyAuditNote | Audit/history note |
pyCallParams | Shape-level parameter key/value pairs |
Start and End shapes use pyMOName: "Start" / "End" on legacy flows; modern Process Modeler may write "" or the pyMOId instead. On recreation, preserve the server's value. On fresh authoring, either convention is acceptable.
Flow-level pyParameters convention
When a flow declares input parameters, the rule-level pyParameters list carries one Embed-MethodParams row per parameter. This convention differs from shape-embedded parameter rows:
| Convention | Where | pyParametersParamInOut | pyParametersParamReq |
|---|
Rule-level pyParameters | top-level flow rule | "" | "-1" |
| Notify smart-shape embedded | shape pzRuleParameters | "IN" | "0" |
| Approval-bundle embedded | SubProcess pzRuleParameters | "" | "" |
| Plain-activity Utility embedded | shape pzRuleParameters[1] | "IN" | "" |
When a flow declares no parameters, emit a single empty placeholder row with pyParametersParamName: "" and all other fields blank.
Rule-level Fields by Structure-Type — Canonical Matrix
The single highest-leverage cross-reference in this skill. Eight
pyStructureType family-values (or explicit absence) each write a
different rule-level field signature. Use this table to answer: "given
this structure-type, what rule-level fields do I write, and with what
values?" Cells contain the canonical value, (absent) if the field
is not emitted at all, (varies) for context-dependent values
documented elsewhere, or a back-pointer to the authoritative
section. The eight columns are the eight observed family-values
including BPMN (pyStructureType field fully absent — its identity
signal is pyCategory: "BPMN") and Stub (skeletal flows).
| Field | Linear | Simple | Multi | ConversationFlow | ScreenFlow | ProcessFlow | BPMN | Stub |
|---|
pyStructureType | "Linear" | "Simple" | "Multi" | "ConversationFlow" | "ScreenFlow"; also "Multi" for branching ScreenFlow | "Simple" on shipped flows | (absent) — field omitted entirely | "Linear" |
pySuggestedStructureType | (absent) | (absent) | (absent) | "ConversationFlow" | (absent) | (absent) | (absent) | (absent) |
pyCategory | "FlowStandard" | "FlowStandard" | "ScreenFlowStandard" | "ConversationFlow" | "ScreenFlowStandard" — or self-rule-name override | "ProcessFlow" | "BPMN" | "FlowStandard" |
pyFlowType | self-register pyRuleName | pyRuleName or "FlowStandard" | pyRuleName or taxonomy | "FlowStandard" (decoupled) | self-rule wins over "ScreenFlowStandard" default | "FlowStandard" | "FlowStandard" (decoupled) | "FlowStandard" |
pyPageRTE | (absent) | (absent) | (absent) | { pxObjClass: "Embed-RTE-Conversation" } | (absent) | (absent) | (absent) | (absent) |
pyCustomFields.pyGalleryType | "CaseManagementGallery" when self-registering | (varies — palette self-registration) | (varies) | (absent — see for ConversationFlow custom-fields cluster) | (varies) | (absent) | (absent) | (absent) |
pyCustomFields other | sparse | sparse | sparse | rich — 17-field cluster | sparse | sparse | sparse | sparse |
pyTaskInfo rollup | shape-level only | shape-level only | shape-level only | shape-level only | shape-level only | shape-level only | shape-level + top-level rollup | empty placeholder |
pyUseCaseLinks | rollup of action shapes | rollup | rollup | rollup including AskAQuestion / SendAMessage with parent-class pxLinkedClassTo | rollup with screen-flow assignment labels | rollup with parent-class for Spinoff | rollup with parent-class for SplitForEach | empty |
pyContexts | PrimaryPath / AlternatePath | same | same | same | same | same | same | same |
pyModifiers (rule-level) | [] | [] | [] | [] | [] | [] | populated — ticket wiring (/72/74) | [] |
pyStencils | [] | [] | [] | [] | [] | [] | populated — annotation shapes | [] |
pyCoveredBy / pyCoveredByCount | [] / "0" | [] / "0" | [] / "0" | [] / "0" | [] / "0" | [] / "0" | populated when sub-case spin-off | [] / "0" |
pxNamedPageReferences | as needed | as needed | as needed | as needed | as needed | as needed | as needed | as needed |
pyRuleParamsStreamName | (absent) | populated when Utility smart-shape with embedded params | same | populated for Conversation-Question shapes | same | same | same | (absent) |
pyParameters (rule-level placeholder) | placeholder row | placeholder row | placeholder row | placeholder row | placeholder row | populated when flow has declared params | placeholder row | placeholder row |
Author-default cluster (~25 fields: pyShowGrid, pyModelerGridModeON, pySkipNewHarness, pyInterface, pyInterfaceHolder = "Process Engine", pyHistoryObject, etc.) | author defaults | same | same | + 17-field modeler-UI cluster | same | same | same | same |
pyTaskStatusXml | empty shell | same | same | same | same | same | same | empty shell |
pyEndingActivities | populated when End shape carries activity | same | same | preserves legacy pyMOId literal e.g. "END52" | same | same | same | populated |
pyNextAssignment TTFF quad | (absent on stubs) | as needed | as needed | quad populated for ConversationFlow | as needed | as needed | as needed | (absent) |
| Shape coordinates | modeler pixels ("60".."540") | modeler pixels (modern); fractional inches 0.0..10.0 on legacy | modeler pixels | modeler pixels | modeler pixels | fractional inches 0.0..10.0 | modeler pixels | modeler pixels |
Connector waypoints (pyConnectorPoints) | always pixels | always pixels | always pixels | always pixels | always pixels | always pixels (even when shapes are inches) | always pixels | always pixels |
Reading the matrix
- BPMN is the only structure-type where the
pyStructureType field is fully absent — not "", not null, not present. The identity signal is pyCategory: "BPMN" alone.
- ConversationFlow is the only structure-type that emits
pySuggestedStructureType and pyPageRTE.
- ProcessFlow is the only structure-type with shape-level fractional-inch coordinates. Connector waypoints stay in pixels even on ProcessFlow.
- ScreenFlow is the only structure-type where a self-registering rule name OVERRIDES the taxonomy default for
pyFlowType.
- Tickets / annotations / sub-case rollup (
pyModifiers / pyStencils / pyCoveredBy) populate only on canvas-modeled flows that wire those features — independent of structure-type taxonomy.
Cross-references
- ConversationFlow 17-field custom-fields cluster: see
rule-level-fields.
References
Whenever editing a flow, to ensure you understand the full context, load one or more of these skills
| Skill | Description |
|---|
blueprint-stub-discovery | Load when working with a BluePrint-generated app to find stub shapes that need wiring |
flow-creation-workflow | Load when creating a brand-new flow from scratch |
adding-steps-workflow | Load when adding a new shape to an existing flow |
enhancing-steps-workflow | Load when modifying what an existing flow shape does — changing its backing rule without adding or removing shapes |
flowaction-wiring-patterns | Load when creating or configuring a FlowAction for a flow's Assignment shape — view connection and field pitfalls |
canvas-structure | Load when updating an existing flow's shapes or connectors — field sync rules and deep-merge |
shapes-start-end | Load when authoring Start or End shapes in a flow — field subsets, ScreenFlow Start variant, and Change-to-Stage End wiring |
legacy-shape-ids | Load when updating or recreating a pre-2020 imported flow that uses semantic shape IDs like FLOWEND or Fork592 instead of modern auto-generated IDs |
shapes-subprocess | Load when authoring a SubProcess or Spinoff shape in a flow — shape fields, parameter passing, Spinoff subclass, and Annotation shapes |
| top-level-rollups | Load when a flow needs rule-level summary lists that mirror shape-level data — pyUseCaseLinks, pyCoveredBy, pyTaskInfo, pxDataReferences |
| rule-level-fields | Load when copying or recreating a flow and encountering unfamiliar rule-level fields |
| shapes-assignment | Load when authoring an Assignment shape in a flow — routing fields, BPMN differences, ticket wiring |
| routing-assignment | Load when configuring who a flow's Assignment routes work to — current operator, worklist, or workbasket |
| shapes-utility | Load when authoring a Utility shape in a flow — smart-shape variants (data transform, notification, change-to-stage), plain-activity wiring, and variant differences |
| shapes-decision | Load when authoring a Decision shape in a flow (any variant) — required fields, connector wiring, type-specific gotchas |
| shapes-genai | Load when authoring a GenerativeAI shape in a flow — pxConnectToGenerativeAI wiring, pyGenAIPage sub-page, placeholder vs configured differences |
| shapes-parallel | Load when authoring parallel execution in a flow — SplitForEach iteration, SplitJoin parallel branches, Fork shapes, and pyFromTasks wiring |
| connectors-and-mo-id-naming | Load when wiring connectors between flow shapes — condition types, expressions, likelihoods, naming |
| routing-decision | Load when a flow's Decision shape has multiple outgoing branches — ordering, pyFromTasks mirroring, multi-destination keying |
| flow-schema-vs-modeler-validation | Load when a shape passes schema validation but renders incorrectly in Process Modeler — verification approach and common symptoms |
Verification Checklists
Schema-tolerated vs modeler-significant fields: See
flow-schema-vs-modeler-validation — schema validation alone is not
sufficient for flow shapes; fields the schema accepts may not render in
Process Modeler.
Run the relevant checklist after creating or updating a flow.
After creating a new flow
After adding a step
After enhancing a step
After wiring a Notification step (4-rule bundle)
After wiring a GenAI step (2-rule bundle)
After wiring a Utility (Data Transform) step
Reflection format
For each rule in a bundle, record:
what worked: instance key confirmed; pyRuleFormStatus: Good; expected fields present
what failed: Bad/Warning status; stubs; missing references; or "none"
next fix: corrective action for each failure; or "none"
Dependent rule detection
For any rule that fails its checklist item, call get-rule with detail="full" on its pzInsKey and inspect references and pxDependencies to identify downstream rules that may also need updating. Report all failing rules and their dependents before returning.
Examples
Example descriptions follow the pattern: Shape type → Shape type (variant) → Shape type. Lead with the flow topology, then a short sentence on when to use the example. Use the shape type names from the "Shape Name Prefixes" table above; add a parenthetical variant only when the specific sub-type matters (e.g., Assignment (worklist), Utility (data transform), SubProcess (approval)).
Rule-level
| Skill | Description | References |
|---|
flow-stub | Start → End. Smallest valid FlowStandard create payload | |
flow-screenflow | Start → Assignment (ScreenFlow) → End. Minimal valid ScreenFlow create payload | shapes-start-end |
flow-sparse-update | Use when adding a shape to an existing flow via deep-merge update | canvas-structure |
flow-sparse-update-single-field | Use when updating a single field on an existing flow shape | canvas-structure |
flow-assignment-step | Start → Assignment (worklist) → End. Use when creating a flow that routes work to an operator worklist with a flow action | shapes-assignment, routing-assignment, flowaction-wiring-patterns |
flow-conversation-flow-template | Start → SubProcess (AskAQuestion) → End. Use when creating a ConversationFlow | rule-level-fields |
flow-decision-step | Start → Decision (DataXOR) → End, End. Use when creating a flow that branches on a property comparison with WHEN/ELSE connectors | shapes-decision, routing-decision |
flow-fork-split-join | Start → Decision → SplitJoin (SubProcess) → Decision (multi-destination) → End. Use when creating a flow with parallel branches | shapes-parallel, routing-decision |
flow-genai-step | Start → Utility (GenerativeAI) → End. Use when wiring a generative AI connector into a flow | shapes-genai |
flow-loopback-cascading-approval | Start → Utility → Decision → SubProcess (approval) → Utility → Decision (loopback) → End. Use when creating a cascading approval flow | connectors-and-mo-id-naming, routing-decision, shapes-subprocess |
flow-notify-smart-shape | Start → Utility (notification) → End. Use when wiring a notification smart-shape into a flow | shapes-utility |
flow-split-foreach-subcase | Start → Assignment (workbasket) → Utility → SplitForEach → SubProcess → End. Use when creating a BPMN flow that iterates a list and spawns sub-cases | shapes-parallel |
flow-subprocess-approval | Start → SubProcess (approval) → End. Use when wiring a pxApproval subprocess into a flow | shapes-subprocess |
flow-utility-change-to-stage | Start → Utility (change-to-stage) → End. Use when creating a flow that transitions to a different case stage | shapes-utility |
flow-utility-data-transform | Start → Utility (data transform) → End. Use when wiring a data transform smart-shape into a flow | shapes-utility |
flow-utility-plain-activity | Start → Utility (plain activity) → End. Use when wiring a plain activity into a flow | shapes-utility |
Shape-level
| Skill | Shape type | Description | References |
|---|
flow-shape-start | Start | Use when adding a Start shape as the entry point of a FlowStandard flow | shapes-start-end |
flow-shape-start-screenflow | Start (screen flow) | Use when adding a Start (screen flow) shape as the entry point of a ScreenFlow | shapes-start-end |
flow-shape-end | End | Use when adding an End shape as the terminal point of a flow | shapes-start-end |
flow-shape-assignment-worklist | Assignment (worklist) | Use when adding an Assignment (worklist) shape to a flow | shapes-assignment, routing-assignment |
flow-shape-assignment-workbasket | Assignment (workbasket) | Use when adding an Assignment (workbasket) shape to a flow | shapes-assignment, routing-assignment |
flow-shape-assignment-screenflow | Assignment (ScreenFlow) | Use when adding an Assignment (ScreenFlow) shape. Shows FlowAction wiring for a screen flow step | shapes-assignment, flowaction-wiring-patterns |
flow-shape-utility-activity | Utility (activity) | Use when adding a Utility (activity) shape that calls an activity directly | shapes-utility |
flow-shape-utility-data-transform | Utility (data transform) | Use when adding a Utility (data transform) shape that runs a data transform via pzRunDataTransform | shapes-utility |
flow-shape-utility-data-transform-screenflow | Utility (data transform, ScreenFlow) | Use when adding a Utility (data transform) shape to a ScreenFlow — ScreenFlow category stamps and verified Modeler-compatible fields | shapes-utility |
flow-shape-utility-notification | Utility (notification) | Use when adding a Utility (notification) shape that sends a notification via pzNotifyWrapper | shapes-utility |
flow-shape-generative-ai | Utility (generative AI) | Use when adding a Utility (generative AI) shape that invokes a Rule-Connect-GenerativeAI connector | shapes-genai, shapes-utility |
flow-shape-subprocess | SubProcess | Use when adding a SubProcess shape that calls another flow within the current case | shapes-subprocess |
flow-shape-subprocess-screenflow | SubProcess (screen flow) | Use when adding a SubProcess (screen flow) shape that calls another screen flow within the current case | shapes-subprocess |
flow-shape-agent | Agent | Use when adding an Agent smart shape that invokes a Rule-AI-Agent via pzAsyncAgent | shapes-subprocess |
flow-shape-decision-expression | Decision (expression) | Use when adding a Decision (expression) shape to a flow that branches on a boolean property reference | shapes-decision, routing-decision, connectors-and-mo-id-naming |
flow-shape-decision-table | Decision (decision table) | Use when adding a Decision (decision table) shape to a flow that branches via a decision table | shapes-decision, routing-decision, connectors-and-mo-id-naming |
flow-shape-decision-tree | Decision (decision tree) | Use when adding a Decision (decision tree) shape to a flow that branches via a decision tree | shapes-decision, routing-decision, connectors-and-mo-id-naming |
flow-shape-decision-fork | Decision (fork) | Use when adding a Decision (fork) shape to a flow that branches on a property value | shapes-decision, routing-decision, connectors-and-mo-id-naming |
flow-shape-decision-map-value | Decision (map value) | Use when adding a Decision (map value) shape to a flow that branches via a map value lookup | shapes-decision, routing-decision, connectors-and-mo-id-naming |
flow-shape-decision-predictive-model | Decision (predictive model) | Use when adding a Decision (predictive model) shape to a flow that branches on a model propensity score | shapes-decision, routing-decision, connectors-and-mo-id-naming |
flow-shape-decision-scorecard | Decision (scorecard) | Use when adding a Decision (scorecard) shape to a flow that branches on a weighted score | shapes-decision, routing-decision, connectors-and-mo-id-naming |
flow-shape-wait-timer | Wait (timer) | Use when adding a Wait (timer) shape that pauses flow execution until a timer fires | shapes-assignment, routing-assignment |
flow-shape-send-a-message | SubProcess (send a message) | Use when adding a SubProcess (send a message) shape to a ConversationFlow | shapes-subprocess |
flow-shape-connector-status | Connector (status) | Use when adding a Status connector to a flow Decision shape that fires on a specific result | connectors-and-mo-id-naming, shapes-decision |
flow-shape-connector-else | Connector (else) | Use when adding a default Else connector to a flow Decision shape | connectors-and-mo-id-naming, shapes-decision |
Component-level
| Skill | Description | References |
|---|
flow-local-action | Use when wiring a FlowAction to a flow via a pyLocalActions entry | flowaction-wiring-patterns |