Not a CRM-specific skill, but a methodology for connecting to any CRM via API. Once connected, leave a "connection card" in the project so it can be reused from the next session onward.
Gates (when connecting for the first time, in order)
G1 — Identify the CRM. Ask the user: which CRM? Which task (lead entry/deal management/reporting)? Find that CRM's official API documentation (web search or documentation tool). Do not guess endpoints without documentation.
G2 — Authentication. Priority: API key > Personal Access Token > OAuth2 (last resort for agents). Keys only via env variables (HUBSPOT_API_KEY, PIPEDRIVE_API_TOKEN etc.,
name varies by CRM). Never record key values in files/chats. If the user doesn't know where to issue a key, guide them to that CRM's Settings → API/Integrations path.
G3 — Verify with a minimal read. Check whether the cheapest read call (e.g., listing 1 contact) returns 200. On failure, recheck the authentication method first (header vs Basic vs query param) — it differs per CRM.
G4 — Entity mapping. Use the table below to check this CRM's terminology and align it with the user:
| Concept | HubSpot | Pipedrive | Close | Salesforce | Attio |
|---|---|---|---|---|---|
| Person | contact | person | contact | Contact/Lead | person record |
| Company | company | organization | lead (company-level!) | Account | company record |
| Deal | deal | deal | opportunity | Opportunity | (custom object) |
| Activity/Note | engagement | activity/note | activity | Task/Event | note |
Some CRMs, like Close, use "lead" to mean a company — if you use it without checking terminology, the data ends up in the wrong place.
G5 — Write the connection card. Create CRM.mdat the project root and record: CRM name, base
URL, authentication method + env variable name, list of verified endpoints, entity terminology mapping, pipeline/
stage ID list, custom field IDs, rate limit. The next session reads this card first.
Hard rules (common to all CRMs — all based on real incidents)
- Search before create — search by email/name before creating to prevent duplicates.
- Write with IDs, not labels — stage/status labels overlap across pipelines. Look up the status/stage IDof the intended pipeline and use that.
- Deletion, merging, and bulk updates require user approval — show the count and targets first.
- After a write operation, report a result summary (how many created/updated, record links).
- Bodies containing special characters/emoji should use Python
json.dumps()— inline JSON with curl breaks. - Do not claim "all" without checking pagination (
has_more/cursor/offset). - Check the rate limit in the documentation and throttle bulk operations (default safe value: 5 req/s).
- Do not trust cached IDs — look up pipelines/custom fields live right before writing.
Common task patterns
- Lead inflow → CRM: create form/landing leads as person + company, record the source (utm) in a custom field or note, and confirm the assignee assignment rules with the user.
- CRM → Ad audience: Extract lead email list → into ad platform custom audience (paid-ads skill Section C).
- Meeting briefing: Calendar attendee emails → look up existing records in CRM → combine with external research using the cyrano skill to create a briefing.
- Weekly pipeline report: Aggregate deal count/amount by stage — aggregate by ID, and use label for display only.
When using Airtable/Notion as a CRM
It is simpler than a formal CRM API: read the table/database schema first (apply the entity mapping from G4 to the user schema), and all other hard rules are the same. The option names of the select field are the stage roles — adding options requires approval.