Nembl
Workflows
Subprocess Workflows

Subprocess Workflows

A Subprocess phase runs another published workflow as a nested child. The parent phase waits for the child to complete (or be cancelled), then continues along the outgoing transition that matches the child's exit handler.

Use subprocesses when the same chunk of process appears in multiple parent workflows — background checks, access provisioning, approval chains, domain-specific validation — and you want to maintain it in one place.

When to Use a Subprocess

SituationWhy subprocess helps
Same approval chain in multiple workflowsEdit once, applies everywhere
Complex sub-process that clutters the parent canvasCollapses to a single visible node
Process owned by a different teamTeam owns and publishes their subprocess; parent workflows compose it
Conditional deep flows (e.g. different validation per product line)Parent picks which subprocess to run; child handles the details

Rule of thumb: if more than one workflow needs the exact same sequence of phases, it's a candidate.

Making a Workflow Reusable as a Subprocess

A workflow must be marked reusable before other workflows can link to it. Open the workflow's detail page → Interface card → toggle Reusable. Reusable workflows expose three pieces of contract:

  • isReusable — gate that allows other workflows to link to this one
  • inputSchema — declared inputs the child expects (name, type, required/optional, description)
  • outputSchema — declared outputs the child guarantees on each END phase (name, type, description)

The schemas are authored in the Interface card alongside the reusability flag. Parents see these schemas in the Subprocess phase editor and the variable-mapping UI uses them to type-check input and output mappings.

Why explicit schemas? Phase 45 introduced typed input/output contracts so parents can map variables with autocomplete + validation, and so the editor can warn when a parent maps a value of the wrong type into a child input. Schemas are stored on the WorkflowVersion, so changing them is part of publishing a new version — never a silent change underneath running parents.

Configuring a Subprocess Phase

Drag Subprocess from the phase palette onto the canvas. In the property panel:

Linked workflow + version

  • Linked workflow — any reusable published workflow in your company
  • Linked version — pin to a specific version (e.g. v3) or to LATEST
  • Switching the linked workflow or version mid-design triggers a cross-version compatibility check: the editor highlights any input/output mappings in your parent that no longer match the new child's inputSchema / outputSchema, so you can fix them before saving.

Input mapping

The Subprocess editor reads the child's inputSchema and renders a row per declared input. For each child input you map a source from the parent's tier-aware variable references:

  • phase.* — variables produced earlier in this parent phase or this phase's outputs
  • instance.* — instance-scoped variables (the parent's running state)
  • system.* — Nembl-reserved system variables (requestId, requesterEmail, etc.)
  • global.* — company-global constants

Required child inputs must have a source; optional inputs can be left blank to use the child's declared default. Type compatibility is checked at editor save time.

Output mapping + handler blocks (per-END outputProjection)

Children can have multiple END phases, each representing a distinct outcome (Approved / Rejected / Failed / Cancelled). On the parent side, the Subprocess phase has one handler block per outgoing transition, and each handler block has its own outputProjection that maps from the child's outputs (as guaranteed by the END the child reached) back to the parent's variables.

Subprocess phase: "Background Check"
├── Handler: Approved
│   outputProjection:
│     instance.bgCheckResult ← child.outcome
│     instance.bgCheckRef    ← child.referenceNumber
│   → Transition: "Continue Onboarding"

├── Handler: Rejected
│   outputProjection:
│     instance.bgCheckResult ← child.outcome
│     instance.bgCheckReason ← child.failureReason
│   → Transition: "Send Decline Notice"

└── Handler: Cancelled (no outputProjection — short-circuit)
    → Transition: "Restart Onboarding"

This means different exit handlers can pull different child variables back to the parent, with type-safety guaranteed by the child's outputSchema for that specific END phase.

Runtime Behavior

Launch

When the parent instance reaches the Subprocess phase:

  1. Nembl resolves which child version to start (pinned or LATEST at activation time)
  2. Nembl applies the input mapping to build the child's starting variables
  3. A new WorkflowInstance is created for the linked workflow
  4. The child records parentInstanceId and parentPhaseId so it knows where to report back
  5. The parent waits — the subprocess phase stays active while the child is active

Transitions on completion

When the child reaches an END phase, it emits nembl.workflow.subprocess.complete with the END's name. The parent's Subprocess phase:

  1. Selects the handler block matching the END name (or the default-unlabeled handler if no specific match)
  2. Runs that handler's outputProjection to copy child outputs to parent variables
  3. Fires the handler's outgoing transition

If no handler matches the child's END name and there's no default handler, the parent stalls with an error — the editor catches this at design time.

Parent/child visibility

In the instance viewer:

  • The parent shows its current Subprocess phase with a "Running subprocess" indicator and a deep link to the child instance
  • The child shows a "Subprocess of parent title" badge and a deep link to the parent

Both parties can be navigated independently.

Cancellation Cascade

When a parent is cancelled:

  • If the parent has a Cancel node, the parent routes there; active children are NOT cancelled yet — this allows Resume Workflow to abort the cancellation and pick up where it left off.
  • When the parent's cancellation finalizes (all cleanup tasks complete, or no Cancel node exists), all active children are cancelled via cascading nembl.workflow.cancel events.
  • Children that were already completed stay completed — only active children are affected.

When a child is cancelled directly:

  • The child finalizes as CANCELLED
  • It emits nembl.workflow.subprocess.complete with name Cancelled
  • The parent's Subprocess phase runs the Cancelled handler (if present) or the default handler

Design tip: always provide a Cancelled handler on any Subprocess phase so the parent can handle child cancellations gracefully.

Variable Tier Namespaces

Variables in subprocess workflows live in tier-aware namespaces. This affects what's writable from inside the child:

NamespaceOwnerWritable from child?
phase.*Per-phase scratchYes (current phase)
instance.*The child's instanceYes
system.*Nembl-reservedNo (read-only)
global.*Company-globalNo (read-only)

The parent's variables are never directly writable by the child — only by the parent's outputProjection after the child completes. This isolation prevents children from mutating parent state mid-flight.

Common Patterns

Shared approval chain

Parent workflows like "New Hire Onboarding" and "Contractor Onboarding" both need a manager-approval subprocess. Build one reusable Manager Approval workflow with a single APPROVAL phase plus distinct Approved and Rejected END phases, declare its inputSchema (the candidate, the request type) and outputSchema (the approver, the decision timestamp), then link it from each parent. Change the approver or the SLA once; every parent benefits.

Per-product-line validation

A parent Customer Returns workflow uses a DECISION phase on productLine to route to one of three Subprocess phases, each linked to a product-line-specific validation workflow. The parent stays clean; product teams own their own validation rules + interfaces.

Reusable cleanup

An IT workflow's Cancel node launches a "Cleanup: Release Resources" subprocess instead of listing dozens of cleanup tasks inline. The cleanup workflow declares a minimal inputSchema (the ticket ID) and is maintained by the IT team separately from the customer-facing workflows that invoke it.

Limits

  • No recursion detection: a subprocess can link to a workflow that eventually links back to itself. Keep an eye on it, or you'll spawn instances until you hit your instance quota.
  • Depth is technically unlimited but keep nesting modest (2–3 levels) for readability and observability.
  • All children of a cancelled parent finalize with status CANCELLED — there's no "keep child running after parent cancels" flag.

Troubleshooting

  • Parent waits forever — the child is stuck. Check the child's current phase; responsible parties there may have been notified but haven't acted. Resolve at the child level.
  • Handler doesn't fire — the child completed with an END name that doesn't match any handler on the Subprocess phase, and there's no default handler. Add the missing handler (check the child's END phase names) or add a default fallback.
  • Outputs not visible on parent — verify the handler that fired has the right outputProjection mappings, and that the child's outputSchema actually declares those output names. The editor's compatibility check catches this at design time.
  • Editor warns about input mapping after version switch — the new child version's inputSchema differs from the previous one. Update your mappings before saving.
  • Cancelled parent but child kept running — this should not happen; it indicates the cancel finalization didn't propagate to the child. Check the Audit Trail for the parent's cancellation events.

Related