Workflows Reference
This page lists the workflow identifiers, contracts, and limits used by the dashboard, API, Terraform, and automation clients. For a task-oriented introduction, see the Workflows guide.
The authenticated GET /v1/workflows/catalog response is the canonical contract for the triggers,
scope fields, actions, parameters, outputs, and graph nodes available to the current organization. The
catalog accounts for the installed edition and enabled capabilities; clients should use it instead of
hard-coding the lists below.
Triggers
Common triggers
| Identifier | Starts a run when |
|---|---|
alert.triggered | Moneat fires an alert lifecycle event |
alert.resolved | Moneat resolves an alert episode |
monitor.alerted | A telemetry monitor enters an alerting state |
monitor.recovered | A telemetry monitor recovers |
uptime.down | An uptime monitor reports a failure |
uptime.up | An uptime monitor recovers |
synthetic.failed | A synthetic test fails |
synthetic.passed | A synthetic test passes |
incident.created | An incident is created |
incident.resolved | An incident is resolved |
incident.role_changed | An incident response role changes |
security.signal | Moneat creates a security signal |
manual | An authorized operator starts a run |
api | An authenticated client submits a typed input payload |
webhook | A request passes the workflow's signature verification |
schedule | An enabled schedule reaches an occurrence |
Incident and routing triggers
Additional incident response and deterministic alert routing triggers include:
- Incident changes:
incident.lifecycle_changed,incident.status_changed,incident.severity_changed,incident.field_changed,incident.update_published,incident.action_changed,incident.follow_up_changed,incident.escalation_changed,incident.participant_changed,incident.message_received,incident.post_incident_started, andincident.acknowledged - Routing decisions:
alert.route_matched,alert.group_created,alert.group_updated,alert.group_decision,incident.triage_accepted,incident.triage_declined, andincident.triage_merged
A published version can declare multiple compatible triggers. Every run records the trigger context that admitted it. Fields that are not present in every selected trigger are rejected where the graph requires a shared, unambiguous type.
Alert context
The catalog supplies the complete scope for each trigger. Frequently used alert references include:
| Reference | Type or meaning |
|---|---|
alert.title | Alert title |
alert.description | Alert description |
alert.priority | Priority from P0 through P5 |
alert.status | Firing or resolved state |
alert.source | Telemetry source |
alert.deduplication_key | Stable identity of the underlying condition |
alert.episode_key | Identity of the current alert episode |
alert.notification_sequence | Notification number within the episode |
alert.notification_kind | Initial, reminder, or resolved notification |
alert.opened_at | Time the episode opened |
alert.last_seen_at | Last time the episode was observed as active |
alert.url | Link to the alert in Moneat |
organization.id | Organization identifier |
Dashboard alerts also expose alert.dashboard.title, alert.widget.title, alert.condition,
alert.threshold, and alert.current_value.
Conditions and schemas
Conditions support nested and, or, and not groups, equality and membership, regular expressions,
numeric comparisons, date/time comparisons, null predicates, and supported changed-from/changed-to
predicates. Operators are checked against the reference type during validation.
Equality and membership do not match a missing value unless a null predicate is used. Ordering and regular-expression operators reject missing or incompatible values.
{
"operator": "and",
"children": [
{"operator": "eq", "reference": "alert.priority", "value": "P1"},
{"operator": "contains", "reference": "telemetry.service.name", "value": "checkout"}
]
}Use input_schema for workflows started manually, through the API, by signed webhook, or as a
subflow. Inputs and step outputs preserve bounded strings, numbers, booleans, objects, arrays,
timestamps, and resource references. Secrets are not available to expressions; connector actions
receive credentials only through protected connection parameters.
Actions
Notifications
| Identifier | Result |
|---|---|
notification.email_org | Email verified organization members |
notification.slack | Post to the configured Slack alert channel |
notification.discord | Post to the configured Discord alert channel |
Telemetry and Moneat resources
| Category | Identifiers and primary outputs |
|---|---|
| Logs | moneat.logs.search (logs: Object), moneat.logs.aggregate (aggregate: Object) |
| Metrics | moneat.metrics.query (metrics: Object) |
| Traces | moneat.traces.search (traces: Array), moneat.span.get (span: Object) |
| Issues | moneat.issues.list (issues: Array), moneat.issues.get (issue: Object) |
| Status pages | statuspage.update (status_page: Object), statuspage.incident.create (incident: Object) |
| Alerts | alert.silence (silence: Object) |
| On-call | oncall.page (alert_id, incident_id: ResourceReference), oncall.incident.declare (incident_id: ResourceReference), oncall.incident.action.create (action_id: ResourceReference), oncall.incident.investigate (investigation_id: ResourceReference, status: String, created: Boolean) |
On-call actions require the Enterprise on-call bridge. Their resource outputs use opaque resource identifiers.
Incident response
Incident response actions include:
- Participation and roles:
incident.invite_user,incident.invite_group,incident.participant.add,incident.observer.add,incident.role.assign,incident.role.claim,incident.role.unassign, andincident.role.handover - Actions and follow-ups:
incident.action.create,incident.action.update,incident.action.claim,incident.action.reassign,incident.action.complete,incident.action.cancel,incident.follow_up.create,incident.follow_up.update,incident.follow_up.accept,incident.follow_up.complete, andincident.follow_up.cancel - Lifecycle and coordination:
incident.update.publish,incident.acknowledge,incident.request_decision,incident.timeline.add,incident.resolve,incident.close,incident.cancel, andincident.reopen - Status and chat:
incident.status_page.create,incident.status_page.update,incident.status_page.resolve, andincident.slack.message
Execution requires the corresponding incident response capabilities and access.
Connectors and egress
| Identifier | Primary outputs |
|---|---|
connector.jira.create_issue | issue_id: ResourceReference, issue_key: String, url: String |
connector.github.create_issue | issue_id: ResourceReference, issue_number: Number, url: String |
connector.pagerduty.trigger_incident | incident_id: ResourceReference, incident_number: String, status: String, url: String |
connector.servicenow.create_incident | incident_id: ResourceReference, incident_number: String, url: String |
Connector actions require an authorized workflow connection. Delivery keys make confirmed provider operations idempotent across retries.
The http.request and transform.graaljs actions are available only when
WORKFLOWS_EGRESS_ENABLED=true on an isolated egress deployment. Unavailable editions,
entitlements, connections, or permissions fail closed during validation or execution.
Control nodes
| Identifier | Purpose |
|---|---|
condition.if | Choose between true and false branches |
condition.switch | Choose among named cases |
control.sleep | Pause for a duration |
control.wait_until | Wait for a correlated event or timeout |
control.for_each | Iterate over a bounded collection |
control.while | Repeat while a bounded condition matches |
control.approval | Wait for an eligible operator's decision |
control.parallel | Start bounded parallel branches |
control.join | Join branches using the configured policy |
control.subflow | Run a pinned published workflow version |
control.break | Leave the current loop |
control.continue | Start the next loop iteration |
Only action nodes can originate error edges. Graph cycles are rejected except inside bounded loop
bodies. Parallel joins support all, any, quorum, and timeout behavior. Recursive subflows,
protected values, missing outputs, incompatible mappings, and unbounded fan-out are rejected.
Limits
| Area | Limit |
|---|---|
| Conditions | 32 per node |
| Expression depth | 8 levels |
| Children per expression group | 32 |
| Condition value length | 4,096 characters |
| Parallel branches | 16 |
| Loop items or while iterations | 2,000 |
| Iteration concurrency | 32; default 1 |
| Subflow depth | 8 |
| Subflow input/output mappings | 64 entries |
| Wait correlation | 8 fields, 512 characters per value |
| Buffered wait signals | 16 per correlation key |
| Draft sample fields | 128 |
| Draft test payload | 128 KiB |
| Run-history page size | 100 results |
Schedules
A schedule contains an id, cron expression, IANA timezone, enabled flag, missed_run_policy,
overlap_policy, and max_concurrency.
Daylight-saving transitions use the named timezone. Overlap policies are reject, queue, replace,
and bounded_parallel. Queued occurrences are promoted in creation order, and bounded parallelism
never exceeds max_concurrency.
Terraform exposes schedules through schedules_json:
schedules_json = jsonencode([{
id = "maintenance"
cron = "0 2 * * 0"
timezone = "America/New_York"
missed_run_policy = "skip"
overlap_policy = "queue"
max_concurrency = 1
}])Signed webhooks
Read signing metadata from GET /v1/workflows/{workflowId}/webhook-signing. Sign the exact raw body
with HMAC-SHA256, prefix the hexadecimal signature with sha256=, and send it in
X-Moneat-Workflow-Signature. Use X-Moneat-Webhook-Event as the delivery identity.
body='{"incident_id":"<incident-uuid>","reason":"maintenance"}'
signature=$(printf '%s' "$body" | openssl dgst -sha256 -hmac "$SIGNING_SECRET" -hex | sed 's/^.* //')
curl -X POST "https://api.moneat.io/v1/workflows/<workflow-uuid>/webhook" \
-H 'Content-Type: application/json' \
-H "X-Moneat-Workflow-Signature: sha256=$signature" \
-H 'X-Moneat-Webhook-Event: maintenance-<uuid>' \
--data "$body"Execution and recovery
Execution history uses these outcomes: running, succeeded, failed, cancelled, dead_letter,
deduplicated, and rate_limited. Deduplicated and rate-limited admissions retain their reason and
identity without counting as successful executions.
Instance recovery routes use public workflow and run UUIDs:
| Operation | Route |
|---|---|
| Retry | POST /v1/workflows/{workflowId}/instances/{runId}/retry |
| Resume | POST /v1/workflows/{workflowId}/instances/{runId}/resume |
| Replay | POST /v1/workflows/{workflowId}/instances/{runId}/replay |
| Move to dead letter | POST /v1/workflows/{workflowId}/instances/{runId}/dead-letter |
| Cancel | PUT /v1/workflows/{workflowId}/instances/{runId}/cancel |
Retry, resume, replay, and dead-letter commands require an idempotency key or receive a server-generated one. Replaying uses the original immutable version without reusing the source run's progress.
Versions and access
Editing a published workflow creates a draft. Publishing creates an immutable version; active runs stay on the version that admitted them. Administrators can restore an older version into a new draft.
Workflow access is organization-scoped. Owners and grants provide Viewer, Runner, and Editor access. Service-principal grants authorize non-human subflow execution. Connections separately control metadata visibility, action use, and administration. Approval eligibility is checked against current membership and private-incident visibility when the response arrives.
Terraform
The Terraform provider exposes workflows through moneat_workflow. Use trigger_names,
input_schema_json, schedules_json, and graph_json. Workflow owners are computed by the server,
and connector credentials are never stored in workflow state.
Updates are pinned to the version read during refresh. A concurrent edit returns a conflict and requires Terraform to refresh before planning again.
Return to the Workflows guide for the dashboard workflow and a first notification example.