Meeting To Deal

作者 mondaycom8fdc0b4af07a无许可证收录于 2026年10月8日更新于 2026年10月8日

Turn meeting transcripts into deal updates — key points, commitments, and next steps posted to matching CRM deals automatically. Auto-creates contacts for new attendees. Use when someone says "log my meetings to deals", "update CRM from calls", "what did I commit to in meetings", "sync notetaker", "log this meeting", "I just had a call with [company]", "what did I promise in that meeting", "add notes from today's calls", or "update the deal after my call".

AI 生成的概览

把会议记录转化为 CRM 商机更新,包括要点、承诺、后续步骤,并可选在 monday.com 上创建联系人。

功能
从 monday.com NoteTaker 读取近期会议记录,或使用用户粘贴、指定文件或口头描述的笔记,再通过参会人邮箱、公司域名和标题关键词把每场会议匹配到商机看板上的商机。对匹配成功的商机,它会发布结构化回顾更新,包含要点、承诺事项、待解决问题和阶段信号,并生成当天的同步汇总文档,列出已匹配、多匹配、模糊、未匹配和已跳过的会议。可选功能包括在联系人看板上创建缺失的参会人联系人,以及为七天内到期的承诺发送主动提醒。
适用场景
适用于销售通话或内部商机复盘之后,需要把会议记录归入正确 CRM 商机的场景。适合“把会议记录到商机”“根据通话更新 CRM”“我在会上承诺了什么”这类请求。当没有 NoteTaker 录音时,它也会直接向用户索取会议内容。
运行要求
需要 monday.com MCP 连接器,提供用户上下文、看板、条目、更新、文档、通知以及通用 API 入口等工具,并能访问商机看板和联系人看板。NoteTaker 访问为可选项,没有时由用户手动提供会议内容。该技能不包含脚本。

Meeting to Opportunity

Flow: Trigger → Pull meetings → Match → Synthesize → Publish (α) → Auto-contact (β, opt-in) → Proactive next-step nudges (opt-in).

Input

  • Optional: time window via argument (default = last 24h).
  • Optional: pre-declared mode (Default / Silent / Proactive).

Output

  • α (default): One Meeting recap update per matched deal, summarizing key points + commitments + next steps. Body carries the Generated by Claude · <ISO timestamp> footer + <!-- claude-skill-id: meeting-to-deal --><!-- meeting-id: <id> --> comments. A Meeting sync — <Mon DD> doc lists what was matched, what wasn't, and unresolved attendees.
  • β (Auto-contact, opt-in): New items on the Contacts board for meeting attendees not already in CRM, linked back to the matched deal. Each new contact carries Source = Claude on a status column.
  • Proactive extension: create_notification to deal owner for commitments due this week. Stage column edits and last-touch updates are also OK in Proactive (or in Default with batched confirm) when a clear transition phrase is present in the transcript ("we agreed to move to procurement review", "they signed today"). Surfaced as a single batched plan: "<N> stage transitions detected. Apply all / review each / skip stage edits?". Amount-column writes still forbidden.

Knowledge

  • Meeting → deal matching heuristic (§ Step 4).
  • Update body convention (§ Step 6).
  • Shared artifact conventions (§ Shared patterns).

Tools (MCP)

  • get_user_context — user identity + email domain for filtering meetings and extracting internal_domain.
  • get_notetaker_meetings — recent meetings + transcripts.
  • search / list_workspaces / get_board_info — locate Deals + Contacts boards.
  • get_board_items_page — fetch active deals to match against.
  • get_column_type_info — resolve email/company columns by type.
  • create_update — write the recap onto the matched deal.
  • create_item — β auto-contact on the Contacts board.
  • change_item_column_values — populate the new contact's email + company columns, write Source = Claude on contacts, and apply confirmed stage / last-touch edits on matched deals. Never for amount columns.
  • create_notification — proactive next-step nudges.
  • create_doc — sync summary doc.
  • all_monday_api — escape hatch for connect-board column writes (linking contact ↔ deal). Note: connect-board writes via all_monday_api may fail silently — see Error handling reference.

Cross-skill handoffs

  • From workspace-builder / daily-briefing: suggested as a way to keep deals fresh after a meeting-heavy day.
  • To data-cleanup: if >30% of attendees couldn't be matched, suggest running data-cleanup to clean contact data.
  • To daily-briefing: the synced updates feed tomorrow's brief.

Step 0: Connector check + NoteTaker availability

Goal: Confirm the monday connector works and detect whether NoteTaker is available. Also extract internal_domain for use in Steps 4–5.

  1. Try mcp__monday__get_user_context. On error → standard install prompt, stop.
  2. Extract internal_domain from the user's email (e.g. "[email protected]" → "monday.com"). Store for Steps 4–5. If email is absent from the response, internal_domain = "monday.com" (safe default).
  3. Try mcp__monday__get_notetaker_meetings({ limit: 1 }).
  4. If NoteTaker returns results → set notetaker_available: true. Continue to Step 1.
  5. If NoteTaker returns auth error, permission error, or empty-by-permission → set notetaker_available: false. Do not stop. The skill will collect meeting content from the user directly in Step 3.

PAUSE: do not write any create_* call before Step 6.


Step 1: Detect mode

  • Default — bundle all writes (recaps + stage edits + last-touch updates + auto-contacts) into a single batched confirm before executing.
  • Silent — skip the batched confirm; β auto-contact still requires explicit opt-in.
  • Proactive — ask once: "Proactive mode will: (a) write recaps to matched deals, (b) auto-create missing contacts, (c) apply stage/last-touch edits when transcripts are unambiguous, (d) notify deal owners on commitments due this week. Amount columns stay untouched. Approve all / review each batch / deny stage edits only?". Cache the choice.

If undeclared, Default.

Hard safety rail regardless of mode: no deletes, no amount-column writes, no cross-workspace moves. Stage transitions are bundled into a batched plan — never written one-off, never silently.


Step 2: Resolve time window

  1. If argument carries a phrase, parse: "today" / "yesterday" / "last N days" / "since YYYY-MM-DD".
  2. Default = last 24h.
  3. If no argument was provided AND 0 meetings are found (or on the very first run with no prior session context), print: "Using last 24h (no window specified). Add 'yesterday', 'last 7 days', or 'since YYYY-MM-DD' to change the range."
  4. If parsed window > 14 days: confirm via AskUserQuestion (large windows produce noisy recaps).

Step 3: Pull meetings

3a — NoteTaker path (notetaker_available: true)

mcp__monday__get_notetaker_meetings({ since: <ISO>, until: <ISO>, limit: 50 }). Cache transcripts + attendees + meeting metadata.

Edge cases:

  • 0 meetings in window: don't stop — fall through to Step 3b to let the user provide meeting content manually. Print: "No NoteTaker meetings found in <window>. You can paste meeting notes or describe what happened instead."
  • >50 meetings: paginate up to 200, then cap and surface sampling note.
  • Tool 429: backoff 3x; on third failure fall through to Step 3b.

3b — Manual input path (notetaker_available: false, OR NoteTaker returned 0 meetings)

Ask the user once via AskUserQuestion:

"No NoteTaker recordings available. How would you like to provide meeting notes?"

  • (a) Paste the transcript or notes here — I'll read them from your next message
  • (b) Point me to a file — provide the path and I'll read it
  • (c) Describe what happened — tell me in free text (attendees, key points, commitments, next steps)
  • (d) Skip — nothing to log right now

If (d) → stop with: "No meetings logged. Run this skill again when you have notes to add."

For (a) / (b) / (c): treat the user-provided content as a single meeting entry. Structure it as:

  • title: first line of the notes, or ask if blank
  • date: today (or extract from notes if mentioned)
  • attendees: extract from notes, or ask once
  • transcript_text: the full provided content

Cache as one entry in meetings[] with source: "manual" and continue to Step 4. The matching and recap flow works identically — the transcript is just from the user's input instead of NoteTaker.


Step 4: Resolve Deals + Contacts boards (Gather)

Resolve the boards directly — this skill is self-contained:

  1. Deals board: get_user_context → scan favorites + relevantBoards for names matching deals|opportunities|pipeline|sales. One candidate → use it; multiple → AskUserQuestion; zero → list_workspaces → search("deal", BOARD). Still zero → degrade per step 4 below.
  2. Contacts board: same pass for contacts|people|leads (only if β auto-contact may run). If Contacts board is missing and mode = Proactive and β was approved, surface a chat-level message before writing the sync doc: "Auto-contact was approved but I couldn't find a Contacts board. Contacts not created. Run /monday-crm:workspace-builder to set one up." Then continue with α recap only.
  3. get_board_info on each. Resolve columns by type:
    • On Deals: email (if present), text company-name, people owner, status stage, numbers value, date last-touch.
    • On Contacts: email, text (or company-link board_relation), phone, people owner.
  4. If Deals board missing entirely: degrade — skip α, write only the sync summary doc with "no Deals board found" header. Suggest /monday-crm:workspace-builder.

Step 5: Match meetings → deals (Synthesize)

Goal: For each meeting, find the single best matching deal — or flag it as unmatched.

internal_domain was extracted in Step 0. Use it throughout this step in place of hard-coded @monday.com checks.

For each meeting:

  1. Extract signals: attendee emails (excluding @<internal_domain> addresses), company names from email domains, meeting title keywords.
  2. Pull active deals (Pass A from daily-briefing — non-Won/Lost), limit: 500.
  3. Score candidates:
    • +5 per attendee email matching a deal's email column.
    • +3 per attendee email domain matching a deal's company-name column (case-insensitive substring).
    • +2 if meeting title contains a deal name (≥3 contiguous chars match).
    • +1 if deal owner is a meeting attendee — only when ALL non-internal attendees are from @<internal_domain> (i.e. purely internal meeting). This signal is intentionally narrow: a deal owner being on an external sales call is expected and not a reliable match signal; it only carries weight for internal deal-review meetings where ownership is the strongest available signal.
  4. Pick the top score if it's ≥5 AND beats the second-best by ≥3. Otherwise flag as ambiguous (multiple candidates) or unmatched (no candidate ≥5).
  5. Multi-deal meetings: if top two candidates are within 2 points and both ≥5, flag as multi-match — write the recap to both deals with a header line "Meeting also discussed: <other deal>".

Edge cases:

  • Internal-only meetings (all attendees @<internal_domain>) and no deal-name title match: skip (likely standup), log to summary doc as "skipped: internal-only".
  • Personal-meetings filter: skip meetings tagged 1:1 (no transcript content of CRM relevance).

Step 6: Synthesize the recap (Synthesize)

For each matched meeting, compose a structured recap from the transcript:

  • Key points (3–5 bullets, factual — what was discussed).
  • Commitments made (who → what → by when, parsed from "I'll send you...", "we'll follow up by...", "next week we...").
  • Open questions (statements ending with ? or signaled by "we need to figure out", "TBD").
  • Stage transition signal: if transcript contains procurement / legal / contract / close phrases, propose a stage change. Mark each as confidence: high|low based on (a) explicit phrase ("we agreed to <stage>", "signed today") = high, (b) inferred ("seems like they're ready for legal review") = low. Only high transitions enter the batched plan; low ones surface as text recommendations.

Deal-side metadata lookup: pull current stage + value + close date for context (single get_board_items_page filtered to the matched item ID).


Step 7: Publish α — per-deal recap (Publish)

For each matched meeting + deal pair:

  1. Idempotency check: Use all_monday_api with the following query pattern to scan existing updates on the deal item:

    graphql
    { items_by_id(ids: [<dealId>]) { updates(limit: 50) { body } } }

    Walk the body of each returned update and check for both <!-- claude-skill-id: meeting-to-deal --> and <!-- meeting-id: <id> -->. If a match is found → use all_monday_api to update that existing update's body; do not post a duplicate.

    Note: mcp__monday__search cannot search update bodies — always use all_monday_api items_by_id for this check.

  2. create_update({ itemId: <dealId>, body: <recap markdown> }).

  3. Update body shape:

markdown
# Meeting recap — <meeting title>*<meeting date> · <duration>m · <attendee count> attendees*
## Key points- ...
## Commitments- <person> → <commitment> (due <date or "open">)
## Open questions- ...
## Stage signal<"applied: <old> → <new>" if the batched plan included it> OR <text recommendation if low-confidence> OR "no stage change">
---<!-- claude-skill-id: meeting-to-deal --><!-- meeting-id: <noteTakerMeetingId> -->Generated by Claude · <ISO timestamp> · run `/monday-crm:meeting-to-deal` to refresh.

Batched confirm (Default mode)

Before any write, print a single plan: "I'll write: <N> recaps · <S> stage edits (high-confidence only) · <L> last-touch updates · <C> new contacts. <U> meetings unmatched (will list separately). <K> low-confidence stage signals will surface as text only. Proceed? (yes / show plan in detail / no)."

If user picks "show plan in detail":

  1. List all stage transitions by name: <deal name> · <old stage> → <new stage> for every planned stage edit.
  2. Show one example recap (the first deal).
  3. Then confirm: "Apply all? (yes / skip stage edits / no)".

Never per-deal confirms beyond that.

Auto-contact cap warning: If unmatched-attendee count > 25, add to the confirm message: "<N> new contacts detected (> 25 cap). I'll create 25 and add the rest to a review-list doc. Proceed?" (e.g. "31 new contacts detected (> 25 cap). I'll create 25 and add the rest to a review-list doc. Proceed?")


Step 8: β — auto-create missing contacts (opt-in)

Goal: Don't make the user manually add every meeting attendee to Contacts.

Only runs if mode = Proactive (option a) OR Default-mode user opts in at Step 7 confirm (added prompt: "+ create N missing contacts on Contacts board?").

For each unique attendee email not found on the Contacts board:

  1. create_item({ boardId: <contactsBoard>, itemName: "<First Last>", groupId: "new" }).
  2. change_item_column_values to populate email, company (from email domain), and Source = Claude on the board's source/status column. If no source/status column exists, prompt the user once: "Add a Source status column on Contacts so we can flag plugin-created records? (yes / skip)". If skipped, contacts are still created but source isn't tracked.
  3. Link the new contact to the matched deal via the board_relation column using all_monday_api. If this call fails (connect-board writes can fail silently), log the contact as "contact created, deal link pending — set manually" in the sync doc rather than stopping. Do not retry silently.

Cap at 25 contacts per run. Above that, batch into a review-list doc rather than creating silently. (Flag this at Step 7 confirm time — see auto-contact cap warning above.)


Step 9: Proactive next-step nudges (opt-in)

Only runs if mode = Proactive AND session-level approval was given.

For commitments parsed in Step 6 with a parseable due-date within next 7 days:

  • create_notification({ userId: <deal owner>, text: "Commitment due <date> on <deal>: <commitment>" }).
  • If create_notification requires an itemId: use the sync doc's item ID (from Step 10's create_doc return value). Do not pin the notification to an arbitrary deal item when the doc covers cross-deal commitments.

Hard rail: never write commitments to amount columns. Notifications only for proactive nudges (stage edits already handled in Step 7's batched plan, not here).

If >20 nudges queued, batch into one This week's commitments doc (with <!-- claude-skill-id: meeting-to-deal --> in body) and notify once with a link to the doc.


Step 10: Sync summary doc + close the loop

create_doc (idempotent — same-day update-in-place):

markdown
# Meeting sync — <Mon DD>
## Matched (<N>)- <meeting title> → <deal name> (<deal url>)
## Multi-match (<N>)- <meeting title> → <deal A> + <deal B>
## Ambiguous (<N>)- <meeting title> — candidates: <deal A>, <deal B> — review and re-run with explicit deal ID
## Unmatched (<N>)- <meeting title> — attendees: <emails> — no matching deal. Suggest creating one.
## Skipped (<N>)- <meeting title> — internal-only, no CRM relevance
## Contacts created (<N>)- <name> (<email>) → linked to <deal>
## Contacts pending manual link (<N>)- <name> (<email>) — contact created, deal link pending — set manually
---Generated by Claude · <ISO timestamp>

One-line chat summary: Synced <N> meetings to <M> deals. <K> unmatched, <L> contacts created. Doc: <url>.


Shared patterns

  • No prefix on titles. Findability via Generated by Claude footer + <!-- claude-skill-id: meeting-to-deal --> comment in update/doc bodies; Source = Claude on contact items.
  • Embedded meeting-id comment + skill-id comment for idempotency — search-and-update, never duplicate.
  • Safety rail. No deletes, no amount-column writes, no cross-workspace moves. Stage edits go through the batched plan; low-confidence transitions stay as text recommendations only.
  • Type-based column resolution for non-English boards.
  • Batched confirms (Step 7) — never per-meeting prompts.
  • Internal-only meeting filter — skips standups, 1:1s, retro meetings.
  • internal_domain from Step 0 used throughout for internal/external attendee classification — not hard-coded to @monday.com.
  • Skill-id comment uses legacy name meeting-to-opportunity — kept for backward compatibility with existing updates/docs carrying <!-- claude-skill-id: meeting-to-opportunity -->. The skill's invocation name is /monday-crm:meeting-to-deal.

Output template

Per-deal recap (create_update body)

markdown
# Meeting recap — Quarterly Review — Acme Corp*Jun 14, 2026 · 45m · 4 attendees*
## Key points- Discussed Q3 expansion scope — 3 additional seats requested- Budget approved internally at Acme, pending procurement sign-off- Timeline: targeting signed contract by end of June
## Commitments- Sarah (Acme) → send updated SOW (due Jun 18)- Kevin (us) → schedule legal review call (due Jun 20)
## Open questions- Will Acme need SSO configured before go-live?- Multi-year discount structure not yet agreed
## Stage signalApplied: Discovery → Proposal (high confidence — "we agreed to move to procurement review")
---<!-- claude-skill-id: meeting-to-opportunity --><!-- meeting-id: ntm_abc123def456 -->Generated by Claude · 2026-06-15T09:00:00Z · run `/monday-crm:meeting-to-deal` to refresh.

Sync summary doc

markdown
# Meeting sync — Jun 15
## Matched (2)- Quarterly Review — Acme Corp → Acme Corp — Q3 expansion (https://monday.com/boards/...)- Demo follow-up — Beta Industries → Beta Industries — pilot (https://monday.com/boards/...)
## Unmatched (1)- Internal team standup — attendees: all @monday.com — skipped (internal-only)
## Contacts created (1)- Mike Chen ([email protected]) → linked to Acme Corp — Q3 expansion
---Generated by Claude · 2026-06-15T09:00:00Z

Chat one-liner:

Synced 2 meetings to 2 deals. 1 skipped (internal). 1 contact created. Doc: [url].

Error handling reference

FailureBehavior
Connector missingStep 0 stops; print install link.
NoteTaker unavailableStep 3b: ask user for manual input — paste, file, or free-text description.
0 meetings in window (NoteTaker worked)Step 3b fallback — prompt for manual input.
No Deals boardStep 4 degrades — sync doc only, suggest workspace-builder.
Ambiguous match (≥2 candidates within 2 points)Skip the write; log to sync doc as "ambiguous".
Idempotency hit (same meeting-id in update)Update existing content, don't duplicate.
429 on get_notetaker_meetings or create_updateBackoff 3x; halt on third with retry message.
Contacts board missing (β approved, Proactive mode)Surface chat message before sync doc: "Auto-contact was approved but I couldn't find a Contacts board. Contacts not created. Run /monday-crm:workspace-builder to set one up." Continue with α recap.
Contacts board missing (β not triggered)Skip β; log "no Contacts board" once in sync doc.
connect-boards write via all_monday_api failsSkip link; log in sync doc as "contact created, deal link pending — set manually".
Transcript empty / NoteTaker still processingSkip that meeting; surface in sync doc as "transcript pending".
Cross-board permission errorSkip just that deal/contact; continue with the rest.

Completion criteria

  • Step 0 (connector + NoteTaker) ran and passed. internal_domain extracted.
  • Each matched deal got at most one new (or one updated) recap update (verified via all_monday_api items_by_id update-body scan).
  • Every recap body carries <!-- claude-skill-id: meeting-to-deal --> + <!-- meeting-id: <id> --> + Generated by Claude footer.
  • Sync summary doc exists (or printed to chat on failure).
  • Safety rail held: no deletes, no amount-column writes, no cross-workspace moves.
  • Stage edits (if any) ran inside the Step 7 batched plan; all stage transitions listed by name in "show plan in detail"; low-confidence transitions stayed as text only.
  • Contacts created (if β ran) carry Source = Claude; failed deal links logged in sync doc as "pending — set manually".
  • Auto-contact cap warning shown at confirm time if unmatched attendees > 25.
  • Notifications (if Proactive) pinned to sync doc item ID, not arbitrary deal items.

来源与署名

来源:mondaycom/mcp位于plugins/monday-crm/skills/meeting-to-deal提交8fdc0b4

许可证: 无许可证

内容归原作者所有。SourceWeft 从公开仓库中收录这些内容。

举报或申请下架