Onboard a new customer
TL;DR sequence
crm_find_contactby email — avoid duplicates.- If miss:
crm_create_contactwith email + name + as much structured detail as you have. - Optionally:
crm_create_companyand link viacrm_update_contactcompanyId. crm_log_activityfor the source touchpoint (signup, demo, inbound email, etc.).crm_set_ai_summarywith a 2–4 sentence summary of who they are and why they matter — this powers downstream prioritization.
Step 1 — dedupe
Always check first:
{ "name": "crm_find_contact", "arguments": { "email": "vita@acme.com" } }
Returns null if no match, or the contact DTO. Do not call crm_create_contact without checking — duplicate emails are allowed at the schema level (so two real people at the same shared inbox can coexist) but consolidating fragments of one human across rows is painful later.
Step 2 — create
{
"name": "crm_create_contact",
"arguments": {
"email": "vita@acme.com",
"name": "Vita Soto",
"title": "Head of Ops",
"phone": "+1-555-0100",
"metadata": { "source": "signup", "utm_campaign": "spring-launch" }
}
}
Email + name are the two fields that make the contact useful. Title and phone are nice-to-have. metadata is a free-form jsonb bucket — use it for source attribution, lifecycle stage, anything else that doesn't fit a column.
Step 3 — company linkage (when relevant)
For B2B flows, attach the contact to a company so account-level reporting works:
{ "name": "crm_create_company", "arguments": { "name": "Acme Corp", "domain": "acme.com" } }
Then:
{ "name": "crm_update_contact", "arguments": { "id": "<contactId>", "companyId": "<companyId>" } }
If a company with the same domain already exists, the create call returns it instead of erroring — safe to call repeatedly.
Step 4 — log the touchpoint
crm_log_activity is your main "what happened" event store:
{
"name": "crm_log_activity",
"arguments": {
"contactId": "<contactId>",
"type": "signup",
"summary": "Signed up via the Spring Launch landing page; selected Pro plan.",
"metadata": { "plan": "pro", "trial_days": 14 }
}
}
Step 5 — seed the AI summary
This is the highest-leverage call. The summary surfaces in conversation views, on the contact card, and feeds reports:
{
"name": "crm_set_ai_summary",
"arguments": {
"contactId": "<contactId>",
"summary": "Vita runs ops at Acme Corp (50-person logistics SaaS). Just signed up for Pro after attending our spring webinar. Cited integration with their ticketing system as the deciding factor."
}
}
Keep it factual, short, and dense with names + numbers. Avoid platitudes ("interested in solutions") — the summary is what other agents read first when triaging this contact.
Idempotency notes
crm_create_contactwith a duplicate email creates a second row. Alwayscrm_find_contactfirst.crm_create_companywith a duplicatedomainreturns the existing company.crm_log_activityis fire-and-forget — duplicate logs are noise but not corruption.crm_set_ai_summaryoverwrites; multiple calls is fine.
What good looks like
A well-onboarded contact has: email, name, title, company link, one activity row capturing how they arrived, and an AI summary you'd be happy to read in 6 months.