Office hours: Build your self-driving GTM engine·Oct 29, 9:00am PT, onlineRegister→
Cargo
  • PrimitivesData ModelsYour companies, contacts and deals, merged from every sourceContextWhat your team knows, as files every agent readsTerritoriesWho sells where, defined onceMailboxesMailboxes in your reps' names, warmed up and kept under limitsToolsThe actions your agents, plays and reps callAgentsAI that researches, decides and writes, reading your contextPlaysWorkflows that run on a trigger or a schedule, with retriesAppsInternal apps for your reps, hosted on Cargo
    Add-onsChrome ExtensionSell faster, right in your browserButtonTrigger AI agents inside your CRMFormTurn any tool into an embeddable formSlackTag Cargo in Slack. It does the GTM workGitHubPlan on every pull request, deploy on merge
    MoreProjectsDefine your entire GTM in codeCLIUse Cargo from your terminalMCPUse Cargo from Claude and ChatGPTDeveloper resourcesCargo API docs, OpenAPI spec, auth docs, webhooks, MCP serverAPI ReferenceExplore the Cargo APIDocumentationLearn how to use CargoIntegrationsConnected to your entire GTM stack
  • VeriffHow Veriff replaced MuleSoft with Cargo under NetSuite, Stripe and SalesforceAugmentHow Augment Code routes developer sign-ups to reps in under an hourWeights & BiasesHow Weights & Biases ships a new purchase signal in 2 days on CargoSee all
  • Pricing
  • Cookbooks
  • Blog
Sign in
~/crm-hygiene/

A CRM you can trust,without the quarterly cleanup

Duplicates merged, job changes caught and fixes written back on a schedule. Your coding agent builds it in your repo. Cargo runs it and logs every change.

Start building
Northwind Inc.northwind.com
Northwindnorthwind.com
NORTHWIND INCwww.northwind.com
Northwind Inc.Merged
Domainnorthwind.com
OwnerAlice Martin
Contacts14, from 3 records
Same domain and LinkedIn ID

Trusted by GTM teams at

  • Augment Code
  • Weights & Biases
  • Dust
  • WorkOS
  • Braintrust
  • Descript
  • Alaan
  • Engine
  • Scaleway
  • Preply
  • DataDome
  • Oneflow
backed by y combinator

Exact matches merge, the rest wait for a person

Duplicates are found on hard identifiers, never on a company name.

A deduplication play

Searches the live CRM before every merge decision.

Deduplicate accounts
TriggerEditorRecordsMetrics
Daily
CRM accountsHubSpotstart
Find companiesLinkedIn ID, LinkedIn page, domainfind_records
Derive evidenceCluster and pick the survivorderive_evidence
Duplicate scoreOut of 100duplicate_score
Safe to merge?Exact match, no conflictsafe_to_merge
Merge recordsHubSpotmerge_records
Human reviewSlackhuman_review
Merge recordsHubSpotmerge_reviewed
YesNoApproved

Review in Slack

A decline or no answer keeps the records separate.

crm-review
CargoAPP7:02 AM

Review CRM account merge into Northwind (9813472210)

Duplicate score40/100Records to mergeNorthwind LogisticsMatched onLinkedIn page, domainIdentity conflictNoParent/subsidiaryWarning
ApproveDecline
CargoAPP7:03 AM

Review CRM account merge into Globex (9813472871)

Duplicate score30/100Records to mergeGlobex EuropeMatched onDomainIdentity conflictYes
AM
Alice Martin9:18 AM

Northwind approved. Same company, the old record is from an import.

CargoAPPNext day, 7:03 AM

Globex: no answer in 24 hours. The records stay separate.

One key per person, across every tool

Records that share an email, a domain or a LinkedIn ID get one canonical ID, with every source ID kept.

The unified record

The HubSpot contact and the Salesforce contact are one Ada.

Contacts/Ada Lovelace
RecordContactsEvents
work_emailada@northwind.com
linkedin_handleada-lovelace
linkedin_id73619042
account_id8c1f2e9a4b7d
idshubspot__contacts51230987salesforce__contacts003Ab00000QrS45AAE

What counts as a match

Each source maps its columns to references like email.

ContactsUnification
Mode*
Integration
Custom
Disabled

Configuration

Unification type
Contact
Unique columns*
email
Email
hs_linkedin_url
LinkedIn Handle

Pick the columns that uniquely identify a record in this model.

Save

Catch the records that went stale

People change jobs and rows stop being refreshed. A schedule finds both.

Job changes

Each contact comes back moved, left, no change or unknown.

Enabled
Check job changes
TriggerEditorRecordsMetrics
Search...
4/4 nodesFilter5/5 statusesAll versionsAll batchesAll dates
2,418 records
Startstart
Detect job changedetect_job_change
Moved or left?changed
Update contactupdate_contact
Grace Hopper
moved: Contoso
Yes
Contact updated
Ada Lovelace
no_change
No
Alan Turing
left
Yes
Marked as left
Katherine Johnson
unknown
No
Hedy Lamarr
Running...
Default

Freshness stamps

Every write records when it happened, so stale rows are one filter away.

Contacts
2 hours ago
All records
1 filterSort312 records3/3 columns
email+2
cargo_last_enriched_at
cargo_enrichment_status
Add column
joan@fabrikam.com
Apr 2nd, 2026
succeeded
linus@initech.com
May 19th, 2026
succeeded
radia@globex.com
Jun 7th, 2026
succeeded
barbara@contoso.com
Jul 30th, 2026
succeeded
cargo_last_enriched_at is before Aug 7th, 2026
Add group
ApplyReset
Filling blank fields? See enrichment

Rules in your repo, every change on record

Your coding agent writes the plays as TypeScript. Cargo runs them and logs each record they touch.

The play, in code

Reviewed in a pull request, deployed disabled until a pilot passes.

$ cargo-ai project add cookbook/crm-deduplication
// infra/plays/deduplicate-accounts.ts
if (
score.score >= automaticMergeScore &&
evidence.autoEligible
) {
uses.crm.mergeRecords({
objectType: "companies",
primaryId: evidence.primaryId,
idsToMerge: evidence.idsToMerge,
});
}
// ...
export const deduplicateAccounts = definePlay(
"deduplicate_accounts", {
model: crmAccounts,
workflow: deduplicateCrmAccount,
limit: 15,
isEnabled: false,
changeKinds: ["added", "updated"],
schedule: { type: "cron", cron: "0 7 * * *" },
});

Every run

Open any record to see each step it took and what it wrote.

Traces
All triggers4/4 statusesLast 7 days
1,204 traces
Record
Trigger
Spans
User
Duration
Started at
Finished at
Credits
Northwind
Deduplicate accounts
5 spans50
1.84s
Nov 3rd, 2026 07:00:04
Nov 3rd, 2026 07:00:06
0
Contoso
Deduplicate accounts
4 spans40
1.12s
Nov 3rd, 2026 07:00:07
Nov 3rd, 2026 07:00:08
0
Grace Hopper
Check job changes
3 spans30
3.40s
Nov 3rd, 2026 06:00:12
Nov 3rd, 2026 06:00:15
1
Fabrikam
Deduplicate accounts
4 spans31
0.96s
Nov 3rd, 2026 07:00:09
Nov 3rd, 2026 07:00:10
0
Alan Turing
Check job changes
3 spans30
2.87s
Nov 3rd, 2026 06:00:16
Nov 3rd, 2026 06:00:19
1
Initech
Deduplicate accounts
5 spans50
1.71s
Nov 3rd, 2026 07:00:11
Nov 3rd, 2026 07:00:13
0
Katherine Johnson
Check job changes
3 spans30
3.05s
Nov 3rd, 2026 06:00:20
Nov 3rd, 2026 06:00:23
1
Globex
Deduplicate accounts
5 spans50
1.93s
Nov 3rd, 2026 07:00:14
Nov 3rd, 2026 07:00:16
0
Mary Jackson
Check job changes
3 spans30
2.64s
Nov 3rd, 2026 06:00:24
Nov 3rd, 2026 06:00:27
1
Adatum
Deduplicate accounts
4 spans40
1.08s
Nov 3rd, 2026 07:00:17
Nov 3rd, 2026 07:00:18
0

Cookbooks that keep a CRM clean

Deduplication and identifier fill, ready to install in your repo.

CD

CRM deduplication

Deduplicate CRM accounts and contacts and keep them duplicate-free.

CE

CRM enrichment

Clean up and enrich a messy CRM.

See all cookbooks

Frequently Asked Questions

Can't find the answer here? Contact our team.

Enrichment fills fields. CRM hygiene keeps the records themselves right over time: one record per company and person, current jobs, and a log of every change. The two work in order. The crm-enrichment cookbook fills missing identifiers into blank fields only, then crm-deduplication merges on them, because a record with no identifier cannot be matched. For filling fields, see enrichment.
On hard identifiers, never on a name. Accounts match on LinkedIn company ID, LinkedIn company page and a non-generic domain. Contacts match on LinkedIn person ID, LinkedIn URL, exact email and exact phone. The play searches the live CRM before every decision, scores the evidence and picks a survivor by a fixed policy. Only exact, conflict-free matches merge on their own.
It goes to a person. The play posts a review request in Slack with the duplicate score, the records involved and any conflict it found, such as a parent and subsidiary pair. Approve and the records merge. Decline, or leave it unanswered for a day, and they stay separate.
HubSpot, Salesforce and Attio, through each connector's native merge action. The crm-deduplication cookbook is a worked HubSpot example; for Salesforce or Attio your coding agent adapts the connector, record IDs, search and merge steps together. Pipedrive connects for search, update and upsert, but has no merge action in Cargo.
With the Detect job change action, which returns moved, left, no change or unknown for each contact, plus the updated person for anyone who moved. Your coding agent puts it in a play over your CRM contacts on a schedule and writes the result back. There is no packaged cookbook for this one yet; the track-job-changes skill gives your agent the call.
As often as the play's schedule says. The deduplication cookbook runs daily and picks up records that were added or updated. Plays deploy disabled and pilot on at most 15 records before you widen them. Every run is recorded per record, with each step it took and what it wrote back, so a merge can always be traced to the evidence behind it.

Build the self-driving GTM engine

Your coding agents build it on Cargo.Or our team builds, operates and improves it with you.

Start building
Cargo
Backed byY CombinatorSOC 2 Type IICertified
LinkedinX

Product

Data ModelsContextTerritoriesMailboxesToolsAI AgentsPlaysAppsIntegrationsPricing

Add-ons

Chrome extensionButtonFormSlackGitHub

Build

DocsDeveloper resourcesCargo API docsCargo OpenAPI specCargo auth docsCargo webhooksCargo MCP serverProjectsClaude CodeCodexCursorAll coding agents

Resources

ReportsBlogCustomer storiesCookbooksEnrichmentRoutingSignalsScoringCRM hygieneAd audiencesGTM skillsGTM EngineeringGlossaryCompareCargo x ClayCargo x WorkatoCargo x n8nCargo x DeeplineCargo x DefaultCargo x LeanDataCargo x UnifyCargo x ValleyCargo x Gojiberry

Company

ManifestoCommunityEventsJobsPartners DirectoryPartner Program

Legal

SecurityTerms of servicePrivacy PolicyRefundsDPASupport
© 2026 Cargo
 ////////    ///////    ////////     ////////    ///////
///         ///   ///   ///   ///   ///         ///   ///
///         ///   ///   ///   ///   ///         ///   ///
///         /////////   ////////    ///  ////   ///   ///
///         ///   ///   /// ///     ///   ///   ///   ///
///         ///   ///   ///  ///    ///   ///   ///   ///
 ////////   ///   ///   ///   ///    ///////     ///////

$ npm install -g @cargo-ai/cli