## TL;DR
Re-scanning the same 200 messages means progress state is fiction: the sync that should advance the cursor fails, the agent falls back to the start, and nothing marks messages as done. The loop is stable because every step is locally reasonable. Fix the state: persist processed message ids with their verdicts in durable storage, commit progress per batch only after the sync step succeeds, and make the agent skip any id already holding a final verdict.

```text
agent loop detected: re-scanning the same 200 quarantined messages after a failed sync
```

## Use this when
- Each run processes an identical leading set of quarantined messages.
- Verdicts for the same messages are written repeatedly.

## Not for this skill when
- The agent is configured for a full sweep each run by design. Then the cost is expected; change the design brief first.
- Messages change state in quarantine, so some re-checking is intended. Limit it to status checks, not full analysis.

## Steps
1. Compare message ids processed across two runs and confirm the overlap set and its size. Verify: the repeated set is identified precisely.
2. Trace the sync step that should persist progress and find where it fails or is never committed. Verify: the broken state write is located.
3. Move progress to durable storage keyed by message id with verdict and timestamp, written per batch. Verify: a process kill mid-run preserves completed batches.
4. Add a start-of-run filter that drops ids with final verdicts from the work queue. Verify: a test run over the same data processes zero repeats.
5. Run two consecutive sweeps over the quarantine. Verify: the second sweep processes only genuinely new or changed items.

## Variant phrasings
### agent rescans same messages progress state not saved
The progress state variant.
### idempotent triage processed message ids deduplication
The idempotency variant.

Compatibility: Agent frameworks with durable key-value or database state, Exchange quarantine and Graph message identifiers.

## Why it happens
Agents loop on state bugs more than on logic bugs. If completion is recorded in memory, or in a sync that silently fails, the system has no yesterday, and every morning starts at the same 200 messages forever.

## Edge cases / pitfalls
- Quarantine message ids can change on some operations. Store a secondary stable key such as the internet message id.
- Keep a small overlap allowance for safety, but log it; silent overlap hides state bugs.
- A loop detector that counts repeated ids across runs catches this class early. Add one.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_YE1TLmjOpXDyEQmFIJGRsA
