An automation can trigger itself in a loop. This happens when one of its record-producing actions writes to the collection it triggers on. For example, a trigger on app.bsky.feed.post with a "Post to Bluesky" action, or a record action whose target collection matches the trigger lexicon. Each write shows up as a new Jetstream event, the event matches the same automation, and it runs again.
Since #28, the automation form shows a warning for this case (draftSelfTriggerTarget in app/islands/action-editors/registry.ts). The warning appears when the action's target collection equals the trigger lexicon and the trigger listens for that kind of write: create, or update for patch-record. It is advisory only. Nothing on the server prevents the loop, so the only backstop is the rate limiter auto-disabling the automation once it hits its per-second, per-minute or per-hour limit.
Expected
A record written by an automation's own action should not fire that same automation again. Other automations watching that collection should still see the write.
Possible approaches
- Remember the URIs or rkeys an automation wrote recently, and skip matching events for those records in that automation only (in
lib/jetstream/consumer.ts). - Tag each write with the automation that made it, and drop events that automation produced.
- Leave it to the rate limiter and the form warning, and document that it's by design.
Open questions
- Should a condition that already breaks the loop make the guard unnecessary? Or should the guard always apply?
- How long should "recently written" be remembered? The answer has to hold up across restarts and Jetstream replay.
Done when
- A self-write can't re-fire the same automation.
- Other automations still receive the write.
- Tests cover both cases.
Queued: the loop will work on this version of the issue.
loop:queued cid=bafyreiac443sqyoxchwvluhln6h436zdodr6ag4mxnbu2fbpgxrni4rctu