Runbooks/Workflows

Mesh workflows

A mesh workflow reacts to a change. It starts either when an object joins or leaves a Composer group, or when chosen attributes of an object change. The workflow can then send an email, call a webhook, set attributes on the object, or add or remove the object from another group. Workflows are an Enterprise feature.

This runbook covers what a workflow is, the four steps and their fields, branches, step outputs, how a webhook is signed and verified, what happens when a step fails, and how to operate runs from the console.

What a workflow is

A workflow has four parts.

PartWhat it is
TriggerOne of two kinds. A Composer rule trigger has a rule and a direction: In fires when an object enters the rule’s group, Out fires when an object leaves it. An Attribute change trigger has an object type and one or more attributes, and fires when any of those attributes changes on an object of that type.
ConditionOptional. An expression in the rules language that is evaluated against the object. If it is false, the run ends as Skipped and no step runs.
StepsAn ordered list of one or more of the four step types below, optionally split by If/else branches. Steps run one after another.
EnabledA disabled workflow matches nothing. Runs already in flight finish.

For a Composer rule trigger, the Composer group is the set, and the workflow reacts to the object moving into or out of that set. Every membership change the Composer makes is recorded, whether it comes from an import, from the Evaluate button on a rule, or from the engine’s periodic reconciliation pass. Each recorded change produces one run for each enabled workflow that matches it, and each change is handled exactly once.

Two kinds of membership change do not trigger workflows. Deleting a Composer rule removes its group and edges without recording any transitions. Erasing an object and orphan cleanup also record nothing.

Membership added or removed by a workflow’s own group step is not a Composer change either, so workflows do not chain through group membership. They can chain only through attribute writes that change a Composer rule’s criteria (see Loops and bursts).

Which changes a workflow reacts to

A workflow only reacts to changes that are recent and that happened after it was enabled.

If the Composer rule that a workflow points at is deleted, the workflow is disabled and the editor shows that its trigger is missing. The workflow itself is kept. An attribute-change workflow has no such dependency, and it stays enabled if its object type is later removed in Settings. It then starts no runs for that type. An enabled workflow cannot be saved until a valid type is chosen (“Object type not found”); saving it disabled is allowed and shows a warning, so you can switch it off or park it.

Attribute-change trigger

An attribute-change workflow names an object type, such as Person, and one or more attributes, such as department and manager. It runs once for each change to any of those attributes on an object of that type. A change that touches several watched attributes at once produces one run that lists all of them.

What counts as a change. A change is any of the following, judged on the value the mesh shows for the attribute:

A second source confirming the value the mesh already shows is not a change. If one source drops its copy while another still holds the same value, the attribute has not changed either. Writes that leave the value as it was record nothing, so a step that sets an attribute to the value it already has does not start further runs.

Every writer counts. It does not matter how the value changed. The following all produce changes that attribute workflows can react to:

The run records where the change came from, such as an import from a named connector, another workflow, or the person who edited the group.

Sensitive attributes are reported by name only. If an attribute is classified above Internal sensitivity, the run records that it changed but not the old or new value. Any attribute whose name contains “password” or “pwd” is treated the same way, so pwdLastSet shows no values. Wherever a value would appear, in a run, an email or a webhook, you see <sensitive> or a null instead. You can still watch a sensitive attribute; the designer warns you so that you know the values stay hidden. Very long values are cut at 1,000 characters.

A first import can start many runs. When you enable an attribute-change workflow and a connector then imports many new objects for the first time, each new object counts as a first value and so starts a run. If the workflow sees more events than the burst threshold within the burst window (500 within 10 minutes by default), its runs are created as Held and nothing fires until you release or cancel them. See Loops and bursts.

Editing the trigger re-arms the workflow. Changes to attributes are recorded whether or not any workflow watches them, and changes older than 24 hours are never acted on. So when you change a workflow’s trigger (its kind, object type, watched attributes, Composer rule or direction), the workflow starts again from that moment and sees only changes that happen after you save. It is not back-filled with earlier changes, so widening a trigger never replays the past day. Editing the name, condition, steps or loop guards does not re-arm it.

An attribute run always executes with the old and new values it recorded, even if the attribute has changed again since. The later change has its own run, queued behind it for the same object. This is different from a Composer rule run, which is cancelled when its transition no longer holds.

Trigger values

Every run, whatever its trigger, can read the following values in the condition, in step fields and in email templates. The Available values picker in the designer lists them with the right spelling.

ValueComposer rule runAttribute-change run
trigger.kindcomposerTransitionattributeChange
trigger.originWhat caused the membership change: Import, Evaluate, Reconcile or WorkflowWhat wrote the value: Import, Workflow, SelfService, Composer, Uniqueness or Manual (a Run now)
trigger.originNameEmptyA connector name, a workflow name or a user name
trigger.occurredUtcWhen the change happenedWhen the change happened
trigger.attributesNot setThe watched attributes that changed, joined with ;, in the order the workflow lists them
trigger.changed.<name>.oldNot setThe previous value, or empty for a first value
trigger.changed.<name>.newNot setThe new value, or empty when cleared
trigger.changed.<name>.kindNot setAdded, Changed or Removed

<name> is the attribute’s name as the workflow spells it. Sensitive attributes give <sensitive> for old and new. For an attribute-change run the group values (workflow.transition, workflow.groupId, workflow.groupDisplayName and group.*) are not set.

An email template can describe the change:

{{displayName}}'s manager changed from
{{trigger.changed.manager.old}} → {{trigger.changed.manager.new}}.

A condition can limit the workflow to some of the changes:

Equals(attr("trigger.changed.department.new"), "Finance")

An attribute name that contains characters other than letters, digits and underscores, such as ms-ds-x, cannot be used as a {{…}} token. Reach it with attr("trigger.changed.ms-ds-x.new") instead.

Order of execution and the “still holds” rule

Runs for the same object execute one at a time, in the order they were created. A run does not start while an older run for the same object is queued, running or waiting to retry.

Before every attempt, a Composer rule run checks that its transition still holds. Attribute-change runs skip this check. See the section on the attribute-change trigger. For an In run the object must still be in the trigger group. For an Out run it must still be out of it. If not, the run ends as Cancelled with the reason “transition superseded”. This stops a delayed “removed” run from undoing the “added” run that followed it.

If the object no longer exists when a run is reached, the run ends as Cancelled with the reason “object no longer exists”.

Steps in a run execute in the order listed. A later step never runs while an earlier one is failing or waiting to retry.

The four steps

A fifth step, Run PowerShell script, runs your own script and is described after the webhook step. It is delivered as a step package, like the custom steps you can add yourself. See custom steps.

Add or remove from a group

Fields: Action (Add or Remove) and the group. The group can be any group in the mesh: a Composer group, a self-service group or an imported one.

Set attributes

Fields: a list of attribute name and value pairs. The value is an expression in the rules language, so a literal text value must be quoted, for example "Contractor". An expression that yields nothing clears the attribute.

Send email

Fields: To (one or more recipients), Subject and Body.

TokenReplaced with
{{workflow.name}}The workflow’s name.
{{workflow.transition}}In or Out.
{{group.displayName}}The trigger group’s display name.
{{object.id}}The mesh object’s id.
{{attributeName}}The object’s attribute of that name, for example {{displayName}}.

Call a webhook

Fields: URL, Attributes to send, Allow private network addresses, and an optional static header.

Private networks

By default a webhook cannot reach loopback, link-local, private (RFC 1918) or unique-local addresses. The host name is resolved and every address is checked on every attempt, so a later DNS change cannot slip past the check made when you saved. A literal IP address in the URL is checked the same way. Tick Allow private network addresses on the step to send to an internal receiver.

Request

IdentityMesh sends an HTTP POST with Content-Type: application/json and this body:

{
  "event": {
    "runId": "6f0c3b1e-0a44-4f5e-9c7a-1d2e3f405162",
    "workflowId": "b2a91c55-77d3-4c10-8f0e-5a6b7c8d9e01",
    "workflowName": "Joiner onboarding",
    "transition": "In",
    "occurredUtc": "2026-10-25T14:03:11.0000000Z",
    "group": { "id": "9d1e2f30-4a5b-6c7d-8e9f-0a1b2c3d4e5f", "displayName": "All employees" },
    "trigger": {
      "kind": "composerTransition",
      "origin": "Import",
      "originName": null,
      "occurredUtc": "2026-10-25T14:03:11.0000000Z",
      "attributes": [],
      "changes": []
    }
  },
  "object": {
    "id": "0c1d2e3f-4a5b-6c7d-8e9f-a0b1c2d3e4f5",
    "objectType": "person",
    "attributes": { "displayName": "Ada Lovelace" }
  }
}

transition is In or Out. occurredUtc is when the membership change happened.

The trigger object describes what started the run. kind is composerTransition or attributeChange. origin and originName say what caused it, and attributes and changes are empty for a Composer rule run. For an attribute-change run, transition and group are null, attributes lists the watched attributes that changed, and changes has one entry for each:

"trigger": {
  "kind": "attributeChange",
  "origin": "Import",
  "originName": "Workday",
  "occurredUtc": "2026-10-25T14:03:11.0000000Z",
  "attributes": ["department", "manager"],
  "changes": [
    { "name": "department", "kind": "Changed", "old": "Finance", "new": "Sales", "sensitive": false },
    { "name": "manager", "kind": "Added", "old": null, "new": "ada.lovelace", "sensitive": false }
  ]
}

Every entry carries sensitive. A sensitive attribute appears with "old": null, "new": null and "sensitive": true.

HeaderValue
X-IdentityMesh-Delivery{runId}/{stepIndex}/{attempt}. The same delivery can arrive more than once; use this to deduplicate.
X-IdentityMesh-TimestampThe send time as Unix seconds.
X-IdentityMesh-Signaturesha256= followed by the lowercase hex HMAC-SHA256 of the timestamp, a full stop and the raw request body, keyed with the workflow’s secret.

The signed text is timestamp + "." + body, using the exact bytes received. Parse the JSON only after the signature has been verified.

Signing secret

Each workflow has one signing secret, shared by all its webhook steps. It is created the first time you save a workflow that calls a webhook, and it is shown once, right after that save. It cannot be read again, so copy it into the receiver at once. You can replace it later with Rotate signing secret, which also shows the new value once. Rotating replaces the secret immediately; update the receiver at the same time. If the console reports that the secret cannot be read on this host, rotate it again.

Verifying a delivery

This Python function verifies a delivery. It rejects deliveries older than five minutes to limit replay, and compares in constant time.

import hashlib, hmac, time

def verify(secret: bytes, headers: dict, body: bytes, max_age=300) -> bool:
    ts = headers["X-IdentityMesh-Timestamp"]
    if abs(time.time() - int(ts)) > max_age:
        return False
    signed = ts.encode() + b"." + body
    expected = "sha256=" + hmac.new(secret, signed, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, headers["X-IdentityMesh-Signature"])

The secret is the value shown when it was generated. Use it exactly as displayed, with its text UTF-8 encoded to bytes.

How the answer is read

AnswerResult
2xxSuccess.
408, 425, 429, 5xx, or a network error or timeoutRetried on the schedule below.
Any other 4xxFails without retrying.
3xxFails without retrying; redirects are not followed.

Answer quickly with a 2xx and do the real work afterwards. A slow receiver that times out is retried, and the receiver then sees the same delivery again.

Run a PowerShell script

This step runs a PowerShell script on the Admin API host, as the Admin API service account, with values taken from the object that started the run. Use it when a task needs a command that IdentityMesh does not have a step for, such as giving a new account a mailbox. It appears in the designer palette as Run PowerShell script.

The step is itself a step package. It is installed in the Steps folder beside the Admin API (C:\Program Files\IdentityMesh\api\Steps\), it is signed, and it is listed in the Step packages table under Settings → Workflows like any package you add yourself. That table is a good first look at how packages are shown. If Run PowerShell script is missing from the designer palette, open the table and check the PowerShell package: its status and, if it is rejected, the reason shown under it say what to fix.

A saved Run PowerShell script step on an install that does not have the package fails its runs as an unknown step type, until the package is deployed.

Fields:

FieldWhat it does
Script sourceFile (default) runs a script from the scripts folder. Inline runs script text typed into the step.
Script fileFor File: the file name only, such as Enable-HybridMailbox.ps1. No folders, drive letters or ... The file must exist in the scripts folder when you save, and the error lists the files it did find.
ScriptFor Inline: the script text, up to 64 KB, in a code-sized box.
PowerShell versionWindowsPowerShell (default) runs powershell.exe, version 5.1. PowerShell7 runs pwsh.exe, which must be installed and on the PATH of the host; saving fails with “pwsh.exe was not found on the host” otherwise. Exchange tools are most reliable on 5.1.
Script parametersA list of script parameter names, each with an expression.
Run-as user name and Run-as passwordOptional. Passed to the script as its -Credential parameter.
Success exit codesComma-separated. Default 0.
Exit codes that fail without retryComma-separated. Empty by default.
TimeoutSeconds the script may run, from 5 to 3600. Default 300.

File and inline scripts

A File script lives in the scripts folder, by default C:\ProgramData\IdentityMesh\Scripts. Only administrators can write there. An administrator copies each script into the folder by hand; the console never uploads scripts. The service account can read and run them but not change them.

An Inline script is stored in the workflow, so anyone who can edit workflows can change what runs as the service account. For that reason inline scripts are off until an administrator turns on Allow inline scripts under Settings → Workflows. With the switch off, a saved inline step fails validation with “Inline scripts are disabled. An administrator can enable them under Settings → Workflows.” and a run that reaches one fails without retrying, with the same message. Turning the switch off does not delete saved workflows. It only stops those steps validating and running.

Parameters

Each entry in Script parameters names one of the script’s parameters and gives an expression in the rules language. The step evaluates the expression against the object and passes the result to the script as text, the same way Set attributes renders a value. A literal value is a quoted string, such as "contoso.mail.onmicrosoft.com", and an attribute is attr("sAMAccountName").

The script declares matching param() entries as usual. A parameter the script does not declare fails the run, the same as it would on a command line.

The credential

When you set both a Run-as user name and a Run-as password, the script receives a [PSCredential] in its -Credential parameter, so the script must declare one. The password is stored as a secret on the step and shown only as a mask. It is handed to the script’s process over its input stream. It is never on the command line, in an environment variable or in a file, and any appearance of it in the captured output is replaced with <secret>. If you leave both blank the script runs as the service account, and a script that opens a Kerberos session uses that account’s identity.

Exit codes and retries

The step classifies the script’s exit code.

Exit codeResult
In Success exit codes (default 0)The step succeeds.
In Exit codes that fail without retryThe run fails at once and is not retried.
Any other valueThe step fails and is retried on the normal schedule.

The exit code is the one the script sets with an explicit exit N. A script that throws exits with 1 and its error message becomes the failure message. A native command that fails inside the script does not count unless the script passes its code on with exit $LASTEXITCODE. A script that does not finish within the timeout is stopped, together with any processes it started, and the step is retried.

The failure message is the last 500 characters of the script’s error output, with secrets removed, or “The script exited with code N.” when there was none.

Outputs

OutputContains
exitCodeThe exit code.
successtrue or false.
durationMsHow long the script ran.
stdoutEverything the script wrote to its output and information streams.
stderrIts error output.
scriptHashThe SHA-256 of the exact script bytes that ran, so the run record shows which version of a file was used.
result.<name>Each top-level property of the script’s result object.

If the last object the script outputs is a hashtable or an object with properties, it is also returned as the result. A script that ends with @{ MailboxGuid = $guid; PrimarySmtpAddress = $smtp } publishes steps.<key>.result.MailboxGuid and steps.<key>.result.PrimarySmtpAddress, which a later step reads. stdout and stderr are each cut at 64 KB with a marker at the end. As for every step, only 50 outputs are kept and each value is cut at 500 characters.

Execution policy

IdentityMesh starts PowerShell with the execution policy set to Bypass for that one process, so ordinary scripts run whatever the host’s policy is. A Group Policy that sets the policy to AllSigned overrides that, and then PowerShell refuses any script that is not signed, including every inline script and every file you did not sign. The step fails without retrying, and the message reads:

File ...\inline.ps1 cannot be loaded. The file ...\inline.ps1 is not digitally signed. You cannot run this script on the current system.

On such a host, sign your scripts with a certificate the host trusts and use the File source. Inline scripts cannot be signed, so they cannot run there.

Example: a hybrid mailbox for a new AD account

The Step SDK kit includes a sample script, Enable-HybridMailbox.ps1. It opens a remote session to your on-premises Exchange server, waits up to 60 seconds for the new account to be visible to Exchange, and runs Enable-RemoteMailbox with the routing address <alias>@<your routing domain>. Running it again for an account that already has a remote mailbox changes nothing. It returns MailboxGuid and PrimarySmtpAddress, and exits with code 3 if the account is still missing after the wait.

  1. Copy Enable-HybridMailbox.ps1 from the Step SDK kit’s scripts folder into the scripts folder on the Admin API host.

  2. Create a workflow with an Attribute change trigger. Choose the object type that holds your AD users and watch the AD anchor attribute, objectGUID.

    The trigger fires at the right moment, and that moment is later than you might expect. Exporting the account to AD does not change the object in the mesh. The workflow fires when the next AD import, delta or full, reads the account back and flows objectGUID onto the mesh object for the first time. The delay between creating the account and the mailbox is therefore the interval of your AD import schedule.

  3. Add a Run PowerShell script step and give it the key mailbox. Set Script source to File and Script file to Enable-HybridMailbox.ps1. Leave PowerShell version on WindowsPowerShell.

  4. Under Script parameters add:

    NameValue
    SamAccountNameattr("sAMAccountName")
    UserPrincipalNameattr("userPrincipalName")
    RemoteRoutingDomain"contoso.mail.onmicrosoft.com"
    ExchangeUri"http://exch01.corp.contoso.com/PowerShell/"

    Use your own routing domain and Exchange address.

  5. Set Run-as user name and Run-as password to an account that can manage recipients in Exchange, or leave them blank to use the service account.

  6. Set Exit codes that fail without retry to 3. A missing account then fails the run at once, instead of retrying for two hours.

  7. Add a Set attributes step after it that writes attr("steps.mailbox.result.MailboxGuid") to the attribute of your choice, and run Validate.

  8. Use Run now against a test user, check the run detail page for the step’s stdout and result.MailboxGuid, then enable the workflow.

If a retry runs the script again after Exchange did create the mailbox, nothing is duplicated, because the script returns the existing mailbox. Write your own scripts the same way, because the step can run a script more than once (see Interrupted steps).

To go beyond scripts, and ship a step as a compiled, signed package with its own form, see Custom workflow steps.

The designer

The workflow designer: a palette of steps on the left, a canvas with a trigger card, a webhook step and an If/else branch with Then and Else lanes in the middle, and the selected step's properties on the right

The workflow designer (preview rendering; some field names and expression syntax differ in the product)

New workflow and Edit on the Workflows page open a full-page designer. Drag steps from the palette on the left onto the canvas, or use the + button on any connection. Select a card to edit it in the properties panel on the right. The admin guide describes every control in its Workflows section.

Branches

An If/else branch sends a run down one of two paths. It sits between steps and holds a condition written in the same rules language as the workflow condition. The condition is evaluated when the run reaches the branch.

If a branch’s condition cannot be evaluated, that is a retryable failure. The run waits and tries again on the normal schedule (1, 5, 15, 60 and 60 minutes, see Failure and retry), and becomes Failed after the fifth retry. While the branch is failed or waiting, an operator can use Skip step on it, which takes the Else arm (see Operator actions).

A condition can read the outputs of earlier steps, as in this example that continues only for contractors:

Equals(attr("steps.hrWebhook.body.type"), "contractor")

Step outputs

Every step publishes a small set of outputs when it finishes. Later branch conditions and templates read them as steps.<key>.<output>. <key> is the step’s identifier, shown in the designer. It is derived from the step’s name and you can edit it. Keys start with a letter or underscore, contain only letters, digits and underscores, and are unique within the workflow.

Use an output in a condition with attr("steps.<key>.<output>"), or in any template field, such as an email subject or body, with double braces:

Webhook answered {{steps.hrWebhook.statusCode}}
StepOutputs
Add or remove from a groupchanged, action, groupId, groupDisplayName, exported
Set attributeswritten, count
Send emailrecipients, count
Call a webhookstatusCode, success, durationMs, body (the response text)

When a webhook answers with JSON, each value in the answer is also published as body.<path>. Objects use dotted names and arrays use numbers, so body.items.0.id is the id of the first item in items.

Some rules apply to every step:

Outputs are visible to everyone who can read runs. If a webhook’s answer carries secrets, those values are shown to them too, so do not point a webhook at an endpoint that returns credentials.

Failure and retry

A step that fails with a retryable error is attempted again after a delay. The delays are fixed:

RetryWait before it
11 minute
25 minutes
315 minutes
460 minutes
560 minutes

After the fifth retry fails, or at once for a failure that cannot be retried, the run becomes Failed and shows the reason. That is about two hours and twenty minutes from first attempt to final failure. Every attempt keeps its own result, so you can see exactly which attempt failed and why.

Run statuses

StatusMeaning
QueuedWaiting to be picked up.
RunningA step is executing.
WaitingBetween retry attempts.
HeldStopped by the burst guard, waiting for an operator.
CompletedEvery step succeeded.
SkippedThe condition was false.
CancelledCancelled by an operator, or superseded, or the object is gone.
FailedA step failed and will not be retried. Needs attention.

Operator actions

These need the workflows.execute permission.

ActionAvailable onEffect
RetryFailedStarts the run again from the step that failed, with a fresh set of attempts.
Skip stepFailed, WaitingMarks the current step skipped and continues with the next. When the step that failed is an If/else branch whose condition could not be evaluated, skipping takes the Else arm.
CancelQueued, Waiting, Failed, HeldEnds the run as Cancelled.
Release all / Cancel allHeld runs of one workflowReleases the held runs to the queue, or cancels them all.
Run now against an objectA workflowStarts a real run for a chosen object. A Composer rule workflow asks for a direction. An attribute-change workflow asks for pretend old and new values for each watched attribute, and needs at least one change. It sends the email, calls the webhook and writes the mesh exactly as a triggered run would, so the console asks you to confirm first.
Pause / ResumeAll workflowsStops runs being started or continued. Changes are still recorded, but changes older than 24 hours are not acted on after you resume.

A Failed run stays flagged until someone retries, skips or cancels it. Cancelling is how you acknowledge a failure you do not intend to fix.

Interrupted steps

If the service restarts after a step did its work but before the result was saved, that step is run again once its lease expires, about five minutes later. Group and attribute steps are safe to repeat. An email step may send the same email twice. A webhook may be delivered twice, which is why every delivery carries X-IdentityMesh-Delivery.

Loops and bursts

Three guards stop a workflow from running away.

Loop guard settings

The chain depth and the rate per object are set on each workflow, in the Loop guards section of the designer, and replace any fixed value. Each workflow can have its own limits.

SettingRangeDefault
Max chain depth1 to 205
Max runs per object per hour1 to 1,00020

Existing workflows use the defaults. The guard messages show the numbers you configured. A workflow that watches the attribute its own step sets does not chain when the step writes the value that is already there. A workflow that flips a value back and forth stops at its depth limit. The burst threshold and window are not per workflow and are set under Tuning, below.

Operations page

The Operations page has a Workflows card.

Card colourMeaning
RedAt least one run is Failed.
AmberRuns are retrying or Held, or the workflow worker has not reported for over three minutes while workflows are enabled.
GreenNothing needs attention.
UnknownWorkflows are not enabled or are paused, or the install is not Enterprise.

A red Workflows card makes the overall banner amber, not red, because a failed webhook is not a broken audit chain. The card links to the Runs tab filtered to Failed runs.

Retention

Run history is kept for 90 days by default. This is the Retention.WorkflowRunDays setting, which sits with the other retention settings; 0 keeps runs forever. Only Completed, Skipped and Cancelled runs are removed, together with their step results. Failed runs are never purged, so a failure nobody has acknowledged stays visible. Cancel a failed run to let it age out.

The record of membership changes that workflows read is tidied automatically a few days after it has been processed. For the other retention windows see audit retention.

Settings → Workflows

Settings → Workflows is a tab on the Roles page, in the same group as System. Anyone with the roles.read permission can open it, and changing the switch needs roles.write. A user who can only view sees the page with the switch disabled.

ItemWhat it is
Allow inline scriptsOff by default. When it is off, a Run PowerShell script step cannot use a script typed into the designer, and a saved inline step fails validation and its runs fail without retrying. Turning it on lets anyone with workflows.write run script text as the service account, so leave it off unless you need it. The change is recorded in the administrator audit trail with who made it. Save applies it at once; no restart.
Scripts folderRead-only. The folder the File source reads, C:\ProgramData\IdentityMesh\Scripts by default.
Per-run folderRead-only. Where each running script gets its own temporary working folder. IdentityMesh removes it when the run ends.
Step packagesThe custom step packages found in the steps folder, with each package’s version, publisher, and a status of Loaded or Rejected. A rejected package shows the reason. A Verification line says whether signatures are required and lists the allowed publishers.
Download Step SDKDownloads the kit for building your own steps. The button is hidden when the server was installed without the kit.

The Step packages table and the download button show only to users who also have workflows.read. A hint under the table reminds you that new packages are picked up when the service restarts. To build and install a package, see Custom workflow steps.

If you leave the tab with an unsaved change to the switch, the console asks you to confirm.

Permissions and licence

PermissionAllows
workflows.readView workflows, runs and status.
workflows.writeCreate, edit and delete workflows, validate them, and rotate secrets and headers.
workflows.executeRetry, skip, cancel, release held runs, run now, pause and resume.

Built-in roles:

Rolereadwriteexecute
Adminyesyesyes
Operatoryesnoyes
Vieweryesnono
Usernonono

Mesh workflows require the Enterprise tier. On any other tier the API answers 403 “Enterprise tier required” and the workflow worker does not run. Every create, edit, delete, secret rotation and run action is recorded in the administrator audit trail; the signing secret is never written to it.

The tables workflows need are created by the installer’s database step.

Tuning

These optional settings in the Admin API’s appsettings.json change the worker’s limits. The defaults suit most installs.

SettingDefaultMeaning
Workflows:Parallelism4Runs executed at once, from 1 to 16.
Workflows:TransitionMaxAgeHours24Changes older than this are never acted on.
Workflows:BurstThreshold500Events for one workflow within the burst window before its runs are Held.
Workflows:BurstWindowMinutes10The length of the sliding burst window, in minutes.

Troubleshooting