Triggers
Triggers decide when a workflow runs: on a schedule, when something happens in nullplatform, when an external system calls in, or by hand. A workflow can have several, and whatever a trigger produces (a webhook body, a platform event, the values you typed in the run dialog) reaches your steps as ${{ workflow.inputs.* }}.
Triggers go live on activation
Triggers register when you activate a workflow, never when you save it. Activation provisions everything the trigger needs: the schedule starts firing, the webhook URL gets minted, the notification channel gets created. Deactivating removes all of it at once. Until you activate, a saved workflow is only a definition and has no side effects.
When a workflow has more than one trigger, say a nightly schedule plus a manual "run now", the first step they share needs join_strategy: any so that either trigger can reach it on its own.
Run on a schedule
A cron trigger takes a five-field cron expression and an optional IANA timezone (UTC by default):
- id: start_cron
type: trigger
plugin_type: cron
name: "Nightly scan"
config:
schedule: "0 3 * * *"
timezone: "America/Argentina/Buenos_Aires"
Each tick starts exactly one run and passes the scheduled time to your steps as ${{ workflow.inputs.firedAt }}. If a run is still going when the next tick arrives, that tick is skipped instead of queuing up.
Run on nullplatform events
Nullplatform-native triggers start workflows from things happening in your organization: action item events (created, updated, commented), checklist items being dispatched, deployment lifecycles, and scope lifecycles (create, update, delete, and more). On activation they create the notification channel and its server-side filters for you; you don't configure anything by hand. You get one channel per active alias, each pointed at that alias's own endpoint, so activating staging next to live gives you two independent subscriptions rather than one shared feed.
- id: trigger
type: trigger
plugin_type: np-action-item-trigger
name: "Action item events"
config:
pathPrefix: np-rightsizing-events
mode: start
nrn: "organization=${{ vars.NP_ORGANIZATION_ID }}"
labelFilters:
workflow_type: rightsizing
Filters keep your workflow from waking up for events it doesn't care about: by NRN, by labels, by category, by priority, or by specific actions. The label, priority, and category filters run server-side only when actions is limited to events on the action item itself (created, updated, resolved, and the like). If the trigger also listens to comment or suggestion events, or leaves actions open, the channel stays broad and the trigger applies those filters after delivery, because the event payload carries the comment or suggestion rather than the item.
The notification channel is created with the session of whoever activates the workflow. Activate with an identity that's allowed to manage notification channels.
There are also failure triggers: on-error fires when a step or workflow fails, and execution-failed-trigger fires when any execution in your organization ends in failure, optionally filtered to one workflow. They're how you build recovery and alerting workflows.
Run from a webhook or from Slack
A webhook trigger turns your workflow into an HTTP endpoint, which is how systems outside nullplatform start a run: your CI, your ticketing system, a cloud provider's event bus, an internal service that knows when something relevant happened. You declare the path and method, and activation creates the public URL. Optionally, the trigger verifies an HMAC signature on the payload and validates the body against a JSON schema before your steps see it.
The URL identifies the workflow and the alias that was activated, so every active alias is its own endpoint. live and staging are different URLs pointing at different versions, so you can point a copy of the calling system at a new version while the current one keeps serving. Two things to plan for: the URL carries an opaque token, so copy it from the active triggers list in the API or the editor instead of building it yourself, and re-activating creates a new token, so whatever calls in needs the new URL.
Bodies are capped at 1 MB. When a caller has more data than that, have it post a reference and let the workflow fetch the rest; see limits.
A Slack trigger starts a workflow from a mention, a message matching a pattern, a reaction, or a slash command. Redeliveries are deduplicated automatically, so a retried Slack event never starts a run twice.
Run by hand
A manual trigger declares typed inputs, and the RUN dialog renders those inputs as a form:
- id: start_manual
type: trigger
plugin_type: manual
name: "Run scan now"
config:
description: "Runs the scan immediately."
inputs:
due_days:
type: number
required: false
description: "Due date offset in days for created action items"
placeholder: "14"
Your steps read the submitted values as ${{ workflow.inputs.due_days }}. One thing to know: an input's default is hint text for the form, and it is not applied at runtime. For a constant that needs a real value at runtime, declare a workflow variable with initialValue instead.
Next steps
- Nodes: what runs after the trigger fires
- Runs and versions: activation and what it provisions
- Limits: payload sizes, step timeouts, and how to stay under them
- Detect and roll out AMI updates: cron and manual triggers working together in a real suite