Automation · Playbook 02

Capture call transcripts into CRM company records.

Every call your team takes lands on the right company record, fully transcribed and summarized, without a partner copying notes.

Diligence

Helper code snippet

Reusable code that powers a step inside this automation — loop bodies, parsers, routers, and other glue.

  • Call Transcript → CRM Note (Zapier glue)
    JavaScript · call_transcript_notes.js

    Five Zapier 'Run JavaScript' steps that turn a finished call recording into a clean, attendee-tagged note posted back to the CRM — transcript pagination, recording URL, and an externals-first participant block.

Reference build

A working reference build that runs in production. The moment a recorded call finishes and the transcript lands in the meetings system, the orchestrator pulls the full paginated transcript, resolves attendees, drafts structured internal call notes via LLM, gates them through a substance filter, and writes the same note onto every company in the CRM that was linked to the meeting — fan-out included. No partner copy-paste, no "did anyone write that up?".

Vendors below are our choices. The flow is roles-not-vendors; every layer swaps cleanly.

Flow
01 · Trigger
Meeting recording ready (webhook from CRM/notetaker)
Fires once the recording + first transcript chunk are available against the meeting record
02 · Fetch meeting
GET /meetings/{meeting_id}
Pulls title, participant emails, call_recording_id, and the linked_records array (companies attached to this meeting)
03 · Filter participants
Workspace-email filter
Split participants by firm domain — used downstream to exclude internal attendees from the LLM output
04 · Enrich externals
Resolve external attendees → People record → LinkedIn
Per-email lookup against the CRM People object + LinkedIn attribute; name-normalized dedup; externals sorted before internals
05 · Get recording URL
GET /meetings/{id}/call_recordings/{id}
Pulls the shareable web_url for the recording so the final note can link straight to playback
06 · Fetch full transcript
Paginate /call_recordings/{id}/transcript
Cursor-walk every page, concatenate, insert a newline before each [hh:mm:ss] speaker turn, convert to <br> for HTML output
07 · Draft notes
LLM #1 — generate exhaustive internal call notes
GPT-5.2 with a strict HTML contract: <b> only on the four section titles (Key Insights · Diligence Notes · Decisions & Agreements · Next Steps), <ul>/<li> bullets, transcript-grounded, no GI-internal chatter
08 · Substance gate
LLM #2 — Yes/No: is this worth sending?
Small cheap model judges whether the notes contain real business substance vs. a 3-minute mis-recording
09 · Filter
Stop unless gate = Yes
Kill the run before any write. No company record gets polluted with junk notes.
10 · Sanitize
LLM #3 — strip stray Markdown
Final pass that removes any Markdown the notes model leaked. The CRM note field renders HTML but mangles Markdown.
Loop — repeat step 11 for every linked company on the meeting (cap 500)
↻ per iteration
11 · Write note
POST /objects/companies/{id}/notes
Creates the same note on every linked company. Title: 'Call Notes: {meeting title}'. Same note, multiple homes — joint diligence, follow-ons, and partner intros all stay in sync.

Fields produced along the way

Stable intermediate shape — every step downstream knows what to expect, even when the call had zero substance and the run terminates early.

FieldWhat it holds
meeting_titleTitle of the meeting from the calendar / transcript source
participantsFull attendee list (emails) pulled from the meeting record
workspace_emailsSubset of participants on the firm's own email domain
external_attendeesName + email + LinkedIn for non-firm attendees (used in the notes header)
linked_companiesCompany record IDs already linked to the meeting in CRM — the fan-out targets
raw_transcriptFull transcript, paginated and concatenated, with newline before each [hh:mm:ss] speaker turn
recording_web_urlShareable link to the call recording, embedded into the note
internal_call_notesStructured HTML notes: Key Insights · Diligence Notes · Decisions & Agreements · Next Steps
substance_gateYes/No flag from a small LLM — 'No' kills the run before any write happens

Gotchas

The things you only learn by running this in anger across a year of calls.

  • 01Pagination is non-optional: the transcript endpoint cursors through pages. A naive one-call fetch silently truncates long calls — diligence calls are the ones most likely to overflow and the ones you most need complete.
  • 02Substance gate before write: a small/cheap LLM judges whether the notes are real ('Yes'/'No'). Filters out 3-minute mis-recordings, bots-only rooms, and 'sorry, wrong link' starts. Without it, the company record gets polluted with junk notes the partners learn to ignore.
  • 03Workspace-vs-external split: filter participants by firm domain so the notes only profile the OTHER side of the table. Internal attendees and internal scheduling chatter are explicitly excluded from the LLM output.
  • 04Participants enrichment loop: each external email is resolved to a People record, then to LinkedIn via attribute-values, with name-normalized dedup. Avoids 'Jane Smith' and 'jane smith' both showing up in the header.
  • 05Output contract is HTML, not Markdown: notes are written as <b>, <br>, <ul>, <li> only — the CRM note field renders HTML but mangles Markdown. A final pass strips any stray Markdown the model leaked.
  • 06Fan-out via loop step: one transcript can map to multiple linked companies (joint diligence, follow-on, partner intros). The loop creates the same note on each one — single source of truth, multiple homes.
  • 07Iteration cap = 500: hard guard against runaway loops on a malformed linked_records payload.

Swap matrix

Every layer is replaceable. The orchestrator owns the wiring so the notetaker, the CRM, and the LLM all move independently.