Recognizing the loop shape
The most common loop is a single workflow that both listens to and writes to the same object. A Record updated trigger fires. The workflow then runs an Update record block on that same record. The update satisfies the trigger, which fires the workflow again.Scoping the trigger
The first guard is to stop the trigger from watching the attribute the workflow writes. A Record updated trigger left unscoped fires on every change to any attribute. That means any write you make loops straight back into it. To break the chain at the source, scope the trigger to a single attribute, and never write that attribute from inside the workflow. Configure the trigger so its watched attribute and its written attributes never overlap.
Because the workflow updates
last_touched_at and the trigger only watches owner, the write can never re-fire the trigger, and the loop cannot start.
Adding an early filter
The second guard catches the case where you cannot fully separate the watched and written attributes. An early Filter checks who made the change. It lets human edits through and stops the run when the workflow itself authored the change. Filter onUpdated by so a workflow-authored update no longer satisfies the trigger.
Place the filter immediately after the trigger, before any write block.
A run started by Priya Sharma editing the record passes the filter and continues. A run started by the workflow’s own write fails the filter and stops, so the loop ends after a single free, no-op pass. A stopped filter is not an error. It is the guard doing its job.
Guarding against duplicate writes
Loops are not the only re-run hazard. Retries, manual re-runs, and overlapping triggers can all execute a workflow twice on the same record. So for every write, ask one question: what happens if this runs twice? A second pass that creates another task, adds another list entry, or enrolls the contact again produces silent duplicates rather than an obvious loop. The cure is idempotency. An idempotent write is designed so a second run changes nothing. For records, the Create or update record block matches on a unique attribute and updates the existing record instead of creating a duplicate.
Run this twice for
jane@acme.com and the second pass updates the record found by the first, so you end with one person, not two. That match-or-create behavior is called an upsert. Tasks, list entries, and sequence enrollments have no built-in upsert. For those, add a Filter that first checks whether the task, entry, or enrollment already exists. Or stamp processed records with a workflow_processed_at timestamp and skip records that already carry one.
Limiting blast radius while testing
The cheapest insurance is to make a misbehaving workflow small before it can grow. A Record command trigger adds a manual Run workflow button instead of firing automatically. You can then run a risky workflow on one record at a time and watch the result before swapping in an automatic trigger. For workflows that fan out over many records, the Loop block’s Limit input caps how many iterations run. Set a low Limit on any loop while you are still testing.
With the Limit set to 3, a loop that should touch 200 deals touches only 3 on each test run. A bad filter or a self-triggering write then costs three operations instead of two hundred. Raise the Limit only once a full trace in the run viewer looks correct. The new engine removed per-workflow credit caps, so the Loop Limit and a scoped trigger are your real spend controls, not a cap setting.
Responding to a runaway
When a loop is already running, stop the bleeding first and diagnose second. The order matters. Every second the workflow stays live, it bills for another pass.1
Disable or archive the workflow
Disabling stops new runs; in-progress runs still complete. This halts the loop before you investigate anything.
2
Open the Runs tab and read the loop path
The Runs tab lists every execution and the credits each one consumed, so you can confirm the loop and measure the cost.
3
Identify the write that re-triggered the workflow
Trace from the trigger to the write block whose output satisfies the trigger again. That overlap is the loop.
4
Add a guard
Scope the trigger off the written attribute, or add an early Filter on
Updated by → Type → is not → Workflow.5
Test on one record before republishing
Re-run the workflow on a single record through a Record command trigger and confirm in the run viewer that it fires exactly once.
See also
- Record updated
- Filter
- Loops & processing many records
- Runs, debugging & publishing
- Credits & pricing explained
Source: Attio Workflows block library and Attio Workflows triggers. Last reviewed against the Attio Help Center, June 2026.