## TL;DR
An agent that re-tags endlessly is applying tags without checking whether they are already there: each pass sees a ticket, decides it needs the tag, adds it (a no-op), and repeats. Make tagging idempotent and convergent: check current tags first, only write when something actually changes, and cap the passes. Tagging should reach a fixed point and stop.

## The query

```text
agent re-tagged the same ticket endlessly: loop detector
```

## Use this when

- Agents add the same tags repeatedly
- Tagging runs never finish
- Ticket histories fill with tag events
- You are building tagging automation

## Not for

- Designing the tag taxonomy
- Tag-based reporting
- Manual tagging best practices
- Tag permission design

## Steps

### 1. Read current tags before deciding anything

Fetch the ticket's tags at the start of each tagging pass. Decisions made without reading current state re-apply what is already there. Read first is the whole fix in most cases.

Expected output: tagging decisions based on current tag state.

### 2. Write only when the tag set actually changes

Compute the desired tags, diff against current, and call the API only if the diff is non-empty. No-op writes are what fill histories and trigger webhooks; skipping them removes the loop's fuel.

Expected output: tag writes only on real changes.

### 3. Cap the number of tagging passes per ticket

A tagging job gets a small fixed number of passes (two or three). If it has not converged by then, something is wrong: stop and alert instead of looping. The cap turns infinite loops into bounded investigations.

Expected output: a pass cap with alert on non-convergence.

### 4. Detect oscillation between tag sets

If pass N wants tags A and pass N+1 wants tags B and pass N+2 wants A again, the logic is oscillating: two rules fighting. Log the desired set per pass; oscillation in the log means the rules need reconciliation, not more passes.

Expected output: oscillation detection from per-pass logs.

### 5. Make the tagging rules deterministic

Same ticket state must always produce the same desired tags. Non-determinism (model sampling, time-dependent rules) guarantees non-convergence. Deterministic rules reach a fixed point; anything else loops eventually.

Expected output: deterministic tagging rules.

## Template: the checklist

```text
Tag loop prevention:
[ ] Current tags read before each pass
[ ] Writes only on non-empty diffs
[ ] Pass cap with non-convergence alert
[ ] Oscillation detection from per-pass logs
[ ] Deterministic tagging rules
```

## Variant phrasings

### agent keeps adding same tag

Steps 1 and 2. Read first, write only on change.

### tagging loop never converges

Steps 3 and 4. Cap passes, detect oscillation.

### ticket tag events flooding history

Step 2. No-op writes are the flood; skip them.

## Why it happens

Tagging agents get built as "look at ticket, decide tags, apply tags" with no memory between passes and no diff before writing. Each pass is stateless, so each pass does the full work including re-applying existing tags. The API accepts the redundant writes silently, webhooks fire on each one, and the history fills. The loop is statelessness plus silent acceptance.

## Edge cases

- Tags removed by humans between passes: the diff naturally re-adds them. Decide whether human removals should stick (then respect them).
- Case sensitivity in tag comparison: "VIP" versus "vip" may diff forever. Normalize before comparing.
- External systems adding tags: another integration's tags appear in the diff. Scope the diff to tags the agent owns.
- Bulk retagging jobs: the same idempotency applies at bulk scale; a bulk job without diffs is a bulk loop.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_IqY1Q10JFsQyhH-qyRB-nA
