You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs(automation): document the time-relative trigger (#1874) (#3241)
Adds the declarative time-relative trigger to the two hand-written author-facing surfaces: skills/objectstack-automation/SKILL.md (a Time-relative triggers section, framed as the replacement for the date-equality-on-record-change anti-pattern) and content/docs/automation/flows.mdx (a Time-relative flow example). The auto-generated reference and package README landed with the feature (#3230).
Copy file name to clipboardExpand all lines: skills/objectstack-automation/SKILL.md
+42-1Lines changed: 42 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -55,7 +55,7 @@ parallel. Flows are the primary automation building block in ObjectStack.
55
55
|:-----|:------------|
56
56
|`autolaunched`| Runs without user interaction — triggered by events, APIs, or other flows |
57
57
|`screen`| Interactive — presents UI screens to the user (wizards, forms) |
58
-
|`schedule`| Runs on a cron schedule (daily cleanup, weekly reports) |
58
+
|`schedule`| Runs on a cron schedule (daily cleanup, weekly reports) — or a **per-record date sweep** via `config.timeRelative`, see *Time-relative triggers*|
59
59
|`record_change`| Fires automatically on record create/update/delete (bind via the `start` node's `triggerType`) |
60
60
|`api`| Invoked explicitly via the API / `engine.execute()`, **or** bound as an inbound **webhook**: `POST /api/v1/automation/hooks/:flowName/:hookId` (see *Inbound webhook triggers* below) |
61
61
@@ -509,6 +509,47 @@ read at runtime, not Zod-validated):
509
509
> value after. (Salesforce-flavor `OLD` / `NEW` were removed in M9.5 and now
510
510
> evaluate to `null`.) See [objectstack-formula](../objectstack-formula/SKILL.md).
511
511
512
+
### Time-relative triggers — scheduled per-record date sweep
513
+
514
+
**Don't** express "act N days before/after a date" (renewal reminders, "expiring
515
+
soon", overdue sweeps) as a `record_change` flow gated on date-equality
516
+
(`end_date == daysFromNow(60)`) — that predicate is only evaluated when the
517
+
record *happens to change*, so unattended it almost never fires. Use a
518
+
**declarative time-relative trigger**: a `schedule`-type flow whose `start` node
519
+
carries a **`timeRelative`** descriptor is swept on a schedule (daily by default)
520
+
and launched **once per record** whose date field falls in the window. The record
521
+
is on the context, so the start `condition` and `{record.*}` interpolation work
522
+
exactly as for a record-change flow — and because the window is evaluated every
523
+
day, a threshold is never missed.
524
+
525
+
```typescript
526
+
{
527
+
name: 'renewal_alert',
528
+
type: 'schedule',
529
+
runAs: 'system', // a sweep has no trigger user — elevate explicitly
530
+
nodes: [{
531
+
id: 'start', type: 'start',
532
+
config: {
533
+
timeRelative: {
534
+
object: 'contracts',
535
+
dateField: 'end_date',
536
+
offsetDays: [60, 30, 7], // fire exactly at T-60 / T-30 / T-7
537
+
// — or — withinDays: 30 // "expiring within 30 days" (negative = overdue lookback)
538
+
filter: { status: 'active' }, // optional, ANDed with the date window
539
+
// maxRecords: 1000 // optional per-sweep cap (default 1000)
540
+
},
541
+
// schedule: cron`0 8 * * *` // optional sweep cadence; omit for daily 08:00 UTC
542
+
},
543
+
}, /* …downstream nodes, connected via `edges` */],
544
+
}
545
+
```
546
+
547
+
Exactly one of `offsetDays` (discrete T-minus days) or `withinDays` (a range;
548
+
negative = overdue) is required. Ships in `@objectstack/trigger-schedule` —
549
+
needs `requires: ['automation', 'triggers']`**plus `'job'`** (the sweep cadence
0 commit comments