Workflow Automation Trigger Guide
Triggers define when a Workflow Automation flow activates. They are the first argument to wfa.trigger() and fall into three categories:
- Record triggers -- activate on record events (create/update)
- Scheduled triggers -- activate on time-based schedules (daily, weekly, repeat, etc.)
- Application triggers -- activate on application events (inbound email, SLA, service catalog, knowledge management, remote table query)
Every flow requires exactly one trigger. Subflows do not have triggers.
For requirement-phrasing → trigger-family mapping, see the Flow Guide → Temporal Requirements Analysis.
Triggers Overview
| Type | Key Triggers | Use For |
|---|---|---|
| Record | created, updated, createdOrUpdated | Data changes |
| Scheduled | daily, weekly, monthly, repeat, runOnce | Time-based tasks |
| Application | inboundEmail, slaTask, serviceCatalog, knowledgeManagement, remoteTableQuery | App events |
Triggers by Use Case
| Use Case | Trigger Type | Example Scenario |
|---|---|---|
| New record automation | trigger.record.created | Auto-assign incidents when created |
| Record change detection | trigger.record.updated | Escalate priority when incident updated |
| Either create or update | trigger.record.createdOrUpdated | Audit logging for new or modified records |
| Daily maintenance tasks | trigger.scheduled.daily | Cleanup old records every morning |
| Regular interval checks | trigger.scheduled.repeat | Check system status every 15 minutes |
| Email-based workflows | trigger.application.inboundEmail | Parse support emails and create tickets |
Common Best Practices
These apply across all trigger families. Trigger-specific advice is called out per trigger below.
- Filter at the trigger level -- use the
condition/email_conditions/target_tableparameters with encoded query syntax (e.g.,"priority=1^assignment_groupISEMPTY") so unneeded records never enter the flow. Use^(AND),^OR(OR),ISEMPTY,ISNOTEMPTY. - Default to background execution -- set
run_flow_in: 'background'(where supported) to avoid blocking the user transaction. Use'foreground'only for synchronous validation. - Scheduled triggers have no trigger data -- use
lookUpRecordswith date-range conditions inside the body (e.g.,sys_created_onRELATIVELE@dayofweek@ago@7). - Schedule in UTC -- always pass the timezone explicitly:
Time({ hours: 2, minutes: 0, seconds: 0 }, "UTC"). Off-peak hours (2-5 AM UTC) minimize system impact. - Use
max_resultsfor batching -- prevents timeouts when scheduled flows process large datasets. - Avoid recursive triggers and update loops -- a flow that updates the same record/field it triggered on can re-trigger itself. Add state checks or flags.
Record Triggers
Record triggers fire in response to record lifecycle events (create, update, or both).
For API signatures, configuration parameters, output fields, and changed_fields structure, see the Trigger API → trigger.record.
trigger.record.created
Fires when a new record is created in the specified table.
When to Use
- Auto-assign records on creation (e.g., assign incidents to on-call teams)
- Provision related resources (welcome email, default tasks, workspace setup)
- Kick off approval workflows for high-value records
Best Practices
run_on_extended: 'false'(default) -- avoids duplicate executions when the same record matches both a base table and a child table
Important Notes
- Fires after the record is inserted (sys_id exists, all fields populated)
- Trigger data accessible via
params.trigger.current - Multiple flows can trigger on the same table; execution order isn't guaranteed
- Background triggers fire after the transaction commits; foreground triggers fire during the transaction
Example
wfa.trigger(
trigger.record.created,
{ $id: Now.ID["incident_created_trigger"] },
{
table: "incident",
condition: "priority=1^active=true",
run_flow_in: "background"
}
)
trigger.record.updated
Fires when an existing record is modified.
When to Use
- Notify or escalate on field changes (priority, state, assigned_to)
- React to state transitions (resolved, closed, cancelled)
- Proceed with downstream work after an approval is granted
Trigger Strategy Options
| Value | Fires | Use for |
|---|---|---|
'once' | Once per transaction | Simple notifications |
'unique_changes' | Once per unique field-change set (⭐ recommended) | Most field-change-driven workflows |
'every' | Every time condition is met | Audit/event-log style flows |
'always' | Every update regardless of conditions | Use sparingly -- can cause many runs |
Best Practices
- Prefer
trigger_strategy: 'unique_changes'to avoid duplicate executions while still reacting to field changes
Important Notes
- Trigger provides NEW values (post-update) on
params.trigger.current-- there is no.previousfield per record value, butchanged_fieldscarries before/after - Condition is evaluated against the new record values
- Trigger strategy applies to updates only -- creates always fire once
Example
wfa.trigger(
trigger.record.updated,
{ $id: Now.ID["incident_updated_trigger"] },
{
table: "incident",
condition: "priority=1",
run_flow_in: "background",
trigger_strategy: "unique_changes"
}
)
Consuming changed_fields: iterate inside the flow body with wfa.flowLogic.forEach(wfa.dataPill(params.trigger.changed_fields, "array.object"), ...) -- each element has field_name, previous_value, current_value, etc. (see the Trigger API).
trigger.record.createdOrUpdated
Fires when a record is either created or updated.
When to Use
- Data synchronization where create and update logic is identical
- Compliance/validation rules applied uniformly to all writes
- Audit logging that captures both creates and updates
Best Practices
- Ensure the condition makes sense for both events -- a condition that only applies to creates (or updates) is a signal you want a separate trigger instead
Important Notes
params.trigger.changed_fieldsis empty array for creates and populated for updates -- use this to branch when behavior differs- Trigger strategy applies to updates only -- creates always fire once
- Fires more frequently than separate created/updated triggers -- tighter conditions help manage volume
Example
wfa.trigger(
trigger.record.createdOrUpdated,
{ $id: Now.ID["incident_event_trigger"] },
{
table: "incident",
condition: "priority=1^ORpriority=2",
run_flow_in: "background",
trigger_strategy: "once"
}
)
Distinguishing create vs. update in the body: use params.trigger.changed_fields -- empty array → create; populated array → update. Branch with wfa.flowLogic.if({ condition: ${wfa.dataPill(params.trigger.changed_fields, "string")}ISNOTEMPTY }, ...).
Scheduled Triggers
Scheduled triggers fire on time-based schedules. They do not have access to record data -- use actions like lookUpRecords to query data within the flow body. Time and Duration are available globally; do not import them.
For API signatures, configuration parameters, output fields, and Time/Duration helper specifications, see the Trigger API → trigger.scheduled.
trigger.scheduled.daily
Executes once per day at a specific time.
When to Use
- Daily summary reports
- Nightly data cleanup (archive closed records, purge stale data)
- Batch processing (bulk updates, external system sync)
Important Notes
- Missed executions are skipped -- no automatic retry if the system is down at the scheduled time
- The flow must be active at the scheduled time
- Actual execution may be delayed by minutes under load
Example
wfa.trigger(
trigger.scheduled.daily,
{ $id: Now.ID["daily_trigger"] },
{
time: Time({ hours: 2, minutes: 0, seconds: 0 }, "UTC")
}
)
trigger.scheduled.weekly
Executes once per week on a specific day and time.
When to Use
- Weekly reports (metrics, team performance, executive summaries)
- Weekly maintenance (archive old records, cleanup stale data)
- Data warehouse / external-system sync
Best Practices
day_of_weekranges 1=Mon ... 7=Sun. Pick the appropriate day for the workload -- Monday for reports covering the previous week; weekend days for off-peak processing.
Important Notes
- The week is computed in UTC --
day_of_week: 1is UTC Monday regardless of caller timezone
Example
wfa.trigger(
trigger.scheduled.weekly,
{ $id: Now.ID["weekly_trigger"] },
{
day_of_week: 1, // 1=Mon ... 7=Sun
time: Time({ hours: 9, minutes: 0, seconds: 0 }, "UTC")
}
)
trigger.scheduled.monthly
Executes once per month on a specific day and time.
When to Use
- Monthly billing (generate invoices, statements)
- Compliance / audit reports
- Period-close financial processing
Best Practices
day_of_monthedge cases -- values >28 may not exist every month. Ifday_of_monthexceeds the month length, the flow runs on the last day of that month (e.g., day 31 → Feb 28/29). Use 1-28 for consistent execution.
Important Notes
- Monthly failures have outsized business impact -- always include error notifications or escalation steps
- Use date-range conditions in
lookUpRecordssuch assys_created_onONLast month@javascript:gs.beginningOfLastMonth()@javascript:gs.endOfLastMonth()