## TL;DR
The agent's existence check failed silently (or raced the add), so it added a person who was already in the cadence and got a 422. Treat the 422 as the answer: the person is in the cadence, move on. Then fix the check to query cadence membership by person id and make the add idempotent.

```text
salesloft API 'person already exists in cadence' 422  -  agent double-adding after a failed check
```

## Steps
1. Read the 422 response and confirm the person id it refers to. That is the membership record the check missed.
   Expected: you have the person id and the cadence id from the error.
2. Verify the person is actually in the cadence by fetching the cadence's membership for that person id.
   Expected: the membership record exists, confirming the 422 was correct.
3. Change the agent to treat this 422 as success-with-no-op: log "already in cadence" and continue instead of erroring.
   Expected: the same run retried tomorrow does not fail.
4. Fix the existence check itself: query membership by person id (not email), and handle the case where the check request fails by assuming nothing, not by assuming absent.
   Expected: the check stops producing false absences.
5. If two agent instances run concurrently, add a short lock or a single-writer rule around cadence adds so they cannot race each other.
   Expected: no more double-adds from parallel runs.

## Use this when
- The agent checks membership, finds nothing, adds, and gets 'person already exists in cadence'.
- Retried runs fail on people the first run already added.
- Two agent instances process overlapping lead lists.

## Not for this skill when
- The error is 'cadence not found' (a different lookup problem).
- The person genuinely is not in the cadence and the 422 is wrong (escalate to support).
- The failure is a 401, 403, or 429.

## Variant phrasings
- "salesloft person already in cadence 422 double add"
- "salesloft add to cadence race condition"
- "salesloft membership check missed existing person"

## Why it happens
Membership checks usually search by email while the add path resolves to a person id, and the two can disagree (stale search index, case differences, a check request that errored and was treated as "not found"). The 422 is the server-side dedupe catching what the client-side check missed. Trusting a failed check as "absent" is the bug.

## Edge cases
- A failed check (timeout, 500) must never be read as "not a member". Retry the check or skip the add.
- The person may be in the cadence under a merged duplicate record. Resolve merges before re-adding.
- Logging the 422 as success keeps metrics honest: count it as a skip, not a new add.

## Provenance

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