## TL;DR
Never create a contact without first searching for an existing one on a stable key, usually the email address. Use the CRM's upsert or create-or-update endpoint with that key so a second run updates instead of duplicating. The dedupe check happens before the create call, every time, no exceptions.

```text
agent created duplicate HubSpot contacts because dedupe key was missing
```

## Use this when
- the CRM has two or more contacts for the same person
- reruns of the agent create fresh contacts
- no lookup happens before the create call

## Not for this skill when
- duplicates came from a CSV import (dedupe the file first)
- you need to merge existing duplicates (use the CRM merge tool)
- the contact data itself is wrong (fix the source)

## Steps
1. Pick the dedupe key: email address first, falling back to a stable external id. Verify: the key is documented and every run uses the same one.
2. Before creating, search the CRM for the key. Verify: a known contact returns exactly one match.
3. If a match exists, update it; only create when there is no match. Verify: running the agent twice on the same input adds zero contacts.
4. Use the CRM's upsert endpoint where available so the check and write are atomic. Verify: concurrent runs do not both create.
5. Log every create with the dedupe key value for later audit. Verify: you can trace any contact back to the run that made it.

### Tool/version compatibility
HubSpot, Salesforce, and most CRMs expose search plus upsert. The pattern is the same everywhere.

## Why it happens
The agent's flow is gather data, create contact, with no lookup step. Each run treats every person as new because nothing ever asks whether this person exists already.

## Edge cases / pitfalls
- Email addresses change; keep the external id as the long-term key and email as the lookup.
- Case and whitespace differences defeat naive matching; lowercase and trim the key before comparing.
- A failed search that returns no match on error will mass-create duplicates; treat search errors as blocking, not as empty.

## Variant phrasings
### CRM filled with duplicate contacts after agent runs
Short version: create without lookup.
### Every rerun added the same contacts again
Short version: missing dedupe key on create.

## Provenance

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