CRM enrichment from calls: every call updates your CRM for you
Every customer call auto-populates your CRM with the people, the priorities, the personal context, and the real next step. Your sales team opens a record that's already filled in.
What you'll have when you're done
A short prompt and a small script that run after every customer call. The call ends, the transcript lands, and a structured record gets drafted straight from what was said: who was on the call and their role, what the company is actually trying to do this quarter, the personal context someone let slip, the concerns they raised, and the next step you agreed to. You review it, and it writes to your CRM.
Every customer conversation becomes a structured record your whole team can act on, and nobody does data entry. The rep who takes the next call walks in already knowing the champion, the blocker, and the kid who just started kindergarten. The record stops being the thing everyone means to update and never does.
Nobody updates the CRM and everybody knows it
CRM hygiene is the one thing every sales org agrees on and almost nobody does. I'd get off a good call with a clear read on the account: who actually decides, what they care about, the one objection I'd have to clear. I'd be totally sure I'd update the record while it was fresh. Then the next call would start. Then a fire somewhere else. Then it'd be a week later, the detail I needed was gone, and I'd type "good call, following up" into the notes field and move on. Or leave it blank.
Each blank record cost the next person who touched the account. The rep walks into the follow-up cold, asks a question the customer already answered, and the customer quietly downgrades how seriously they take us. Multiply that across a quarter of calls and the forecast stops being a read on reality and starts being a guess.
I tried the obvious fixes. A CRM-hygiene rule for the team. A Friday block on everyone's calendar for "update your deals." None of it worked (it was the most-ignored line in every pipeline review, because the work was real and the payoff was somebody else's). The problem was never that people don't care. The problem is that the context lives in the conversation, and the conversation is over by the time anyone sits down to log it.
The transcript still has all of it. The prompt pulls it into the shape your CRM wants. The call ends, one prompt reads the transcript and returns a clean record, you glance at it, and it lands in your CRM with the customer's own quotes attached.
What you need first
- The [Granola][1] → markdown pipeline already running. This workflow runs on the meeting library the pipeline produces. If you haven't set it up yet, do [Granola → markdown][2] first. Thirty minutes. Comes back when done.
- Claude Code installed and pointed at the folder your Granola transcripts land in. Free tier handles the extraction; the script in Step 3 is where you'll add a key.
- API access to your CRM. HubSpot, Pipedrive, Attio, Salesforce, or whatever you run. You'll need an API key or token with permission to update records. If you've never made one, that's fine. Claude walks you through generating it in Step 3.
- One or two well-filled records from your CRM, as a format reference. Optional, but it's how the output matches your team's conventions instead of a generic shape. Five minutes to export them as text.
Step-by-step
Step 1Save the enrichment prompt
The prompt is the load-bearing block. Save it once so every call can run the same logic without retyping.
mkdir -p ~/.claude/prompts
touch ~/.claude/prompts/crm-enrich.md
Paste the prompt below into that file. You'll tune it over the first few calls, then stop touching it.
Read the customer call transcript: {transcript_path}.
Output JSON in this exact shape for CRM enrichment:
{
"contact": {
"name": "...",
"role": "...",
"company": "...",
"personal_context": ["kid's name, a hobby, a recent move, anything personal they mentioned"]
},
"company_context": {
"current_priorities": ["..."],
"team_size": "...",
"tools_mentioned": ["..."]
},
"deal_signal": {
"stage": "...",
"next_step": "...",
"concerns_raised": ["..."],
"champion_or_blocker": "who's pushing this internally, who's resisting, and how you can tell"
},
"source_meeting": "{transcript_path}",
"source_quotes": ["verbatim quotes from the transcript that support each field above"]
}
Rules:
- Only fill a field you can back with a verbatim source quote. If the call
doesn't say it, leave the field empty. Don't infer past the transcript.
- Match the person to the meeting's attendee list. Don't guess names.
- Flag anything sensitive I should think twice about storing (health, family
details, anything said in confidence) under a separate "review_before_storing"
list instead of writing it straight into personal_context.
Step 2Run it on a real call and read the JSON
Open Claude Code in your notes folder:
cd ~/notes
claude
Paste the prompt from Step 1, replacing {transcript_path} with the path to a recent customer call. Claude reads the transcript and returns the JSON.
Read the JSON before you trust it. Three checks:
- Does every filled field have a real source quote under it? If a claim has no quote, Claude inferred it. Cut it or push back, and tighten the "don't infer" rule.
- Is the contact matched to someone who was actually on the call? Cross-check against the attendee list.
- Did anything personal land in
personal_contextthat should be inreview_before_storinginstead? This is the field you'll watch most.
Tuning happens here, on your laptop, before anything touches the CRM.
Step 3Get Claude to write the script that posts to your CRM
You don't write the integration yourself. Open Claude Code and ask:
Write a small script that takes the JSON from ~/.claude/prompts/crm-enrich.md
and updates the matching contact and deal in {your CRM} via its API.
- Match on the contact's email if present, otherwise on name + company.
- Map current_priorities, concerns_raised, and next_step to the deal record.
- Map personal_context to the contact's notes, but skip anything in the
review_before_storing list (I'll add those by hand).
- If no matching record exists, create one and tag it "from-call" so I can
find new records to verify.
Use the API token at ~/.config/crm-token. Save the script to
~/scripts/crm-enrich.py and make it executable. Walk me through generating
the token first.
Claude writes the script, tells you where to get the API token, and explains the one or two fields it wasn't sure how to map. You generate the token, drop it in the file path it asks for, and run the script once against the JSON from Step 2 to confirm one record updates cleanly. Twenty minutes, most of it spent finding the token settings in your CRM.
Step 4Keep a human gate on the sensitive fields
This is the step that keeps the workflow from becoming a liability. A customer call is full of things you're glad to know and shouldn't necessarily file: a health issue, a tense co-founder dynamic, something said off the record. The prompt already routes those to a review_before_storing list instead of writing them in. The script skips that list on purpose.
So the rule is simple. The deal facts auto-write. The personal and sensitive context you eyeball first. Once a week, or after any call that got candid, open the review_before_storing items and decide one by one what belongs in the record and what stays in your head. It takes two minutes and it's the difference between a CRM your team trusts and one that gets you a very awkward conversation.
Step 5Make it one move after every call
You don't want to be assembling this after a call. Two ways to make it frictionless:
Option A · One saved command (lowest effort). After Granola finishes the transcript, open Claude Code and say: "Run ~/.claude/prompts/crm-enrich.md against the latest file in ~/notes/granola/, show me the JSON, then run ~/scripts/crm-enrich.py once I say go." You see the record, approve it, it posts. Ten seconds of typing. Most CEOs live here.
Option B · A Claude Code [Routine][3] (fully automated). Get Claude to set up a Routine that watches your Granola folder, and whenever a transcript tagged as a customer call lands, runs the prompt and the script, posting the deal facts and holding the review_before_storing items in a file you check weekly. Set it once and the records fill themselves in while you're still walking back to your desk.
How you'll know it's working
The signal comes from the people who open the records, not from you.
The first time a rep opens an account and finds the personal context they didn't know to ask about, this workflow has earned its keep. They mention the kid starting school, the customer is surprised anyone remembered, and the call is warmer for it. The source quotes are doing the work. Nobody has to take your word for what was said because the customer's own words are sitting in the record.
The second signal is your pipeline review. You stop spending the first ten minutes reconstructing where each deal actually stands, because the records already say. The forecast stops being a guess and starts being a read you can defend.
When it breaks
The wrong person gets tagged. Two people from the same company on the call, or a name that matches two contacts. Fix: the prompt's "match to the attendee list" rule is the first guard; add the meeting's attendee list to the prompt explicitly, and have the script match on email before name. The "from-call" tag on new records lets you catch a bad create before it spreads.
Fields show up with no quote behind them. Claude inferred a priority or a concern the customer never stated. Fix: the
source_quotessection is the receipt. If a field has no quote, cut it and tighten "don't infer past the transcript." After a few calls of tuning, this drops to near zero.Something sensitive lands in the record. The reason Step 4 exists. If personal or confidential detail is writing straight into the CRM, the
review_before_storingrouting isn't firing. Strengthen the prompt rule with examples of what counts as sensitive, and re-run on a past call to confirm it now routes correctly.The CRM API rejects the write. Rate limits, a required field your script didn't fill, or a permissions gap on the token. Fix: have Claude read the error and adjust. For volume, batch the writes into one nightly run instead of one per call.
You stop running it after a week. The usual silent failure. The fix is to remove the friction: Step 5, Option A so it's one command, or Option B so it's zero. A workflow you have to reassemble after every call doesn't survive a busy quarter.
Where this fits in your harness
This is the back half of the customer-facing layer of your [harness][4]. The [Granola → markdown pipeline][2] made every conversation searchable. This workflow takes the same customer call and turns it into the structured record your sales team runs on, with no data entry between the conversation and the CRM.
The siblings most relevant to this workflow:
- [Customer call to follow-up or spec][5] · the front half of the same call. That workflow drafts the follow-up email and the product spec; this one fills in the CRM. Run all three off one transcript and a single call pays off three ways: the relationship, the product, and the record.
- [Ask your meeting history anything][6] · the query layer over everything. Once your calls are enriching the CRM, you can also ask across all of them at once ("what concerns came up most in the deals we lost last quarter?") instead of one record at a time.
See the [Granola pillar][7] for the full pipeline and the other workflows that compound on top.
[1]: /workflows/what-is-granola [2]: /workflows/granola-to-markdown [3]: /workflows/claude-routines [4]: /workflows/what-is-a-harness [5]: /workflows/customer-call-to-followup [6]: /workflows/ask-your-meeting-history [7]: /blog/granola-for-ceos-highest-roi-ai-install
Get three workflows like this every Thursday
The Thursday 3 is a free weekly email. Three workflows that put you in the top 1% of CEOs. 90-second read. Every card links back to a step-by-step guide like this one.
Get the newsletter →The architecture behind this workflow.
Two operator's manuals for the same job, run two different ways. OpenCLAW for the always-on agent harness; Claude Code for the focused-work CLI. Pick one, or get the bundle for $149.
Browse the books · $99 each