Write follow-up emails after meetings by analyzing call transcripts and notes from the Obsidian Regal/Granola/ folder. Triggers on requests like "write a follow-up email", "draft meeting follow-up", "send follow-up from meeting", "email after call", or "/fu". Uses Obsidian MCP to read meeting transcripts, with automatic filesystem fallback when Obsidian is not running.
Generate short, casual, action-oriented follow-up emails from meeting transcripts stored in Obsidian.
Style: Follow all rules in the writing-style skill, including pyramid principle document structure. No em dashes, no emojis, concise and direct. Regal's brand standard is confident, enterprise-ready, and intentional (see brand-guidelines.md). Match that tone in all follow-ups.
Note: If Obsidian MCP is unavailable, apply the filesystem fallback defined in Phase 1 to read these files, or skip org context loading if the vault path is unknown.
Read Regal/org-context/org-context.md from Obsidian (obsidian_get_file_contents) for Regal product overview, terminology, and key metrics.
For deeper context, also read these sub-files from Obsidian:
Regal/org-context/product.md — platform capabilities and use cases to reference in emailsRegal/org-context/differentiators.md — positioning, proof points, competitive landscapeRegal/org-context/sales-process.md — deal stages, pricing, engagement modelRegal/org-context/use-cases.md — use cases by function (inbound/outbound/operational) with customer proof pointsReference these to inform email tone and terminology.
Read EXAMPLES.md for concrete input/output pairs showing correct and incorrect follow-up emails. Study these patterns before reading transcripts.
| File | Purpose |
|---|---|
| EXAMPLES.md | Input/output pairs for correct and incorrect follow-up emails |
| references/transcript-discovery.md | Fallback cascade for transcript discovery (on-demand Clari fetch, tool comparison) |
tools/references/email-links.md | DocSend collateral, developer docs, platform URLs, placeholder rules |
Regal/org-context/case-studies.md (Obsidian) | Industry-matched case study URLs (Quick Lookup table) |
Use these specialized agents by name with the Task tool (subagent_type):
| Agent | Role in Email Follow-Up | max_turns | Condition |
|---|---|---|---|
transcript-locator | Discover transcript locations for the account | 7 | When 2+ transcripts exist OR user did not specify transcript location |
transcript-analyzer | Read and extract structured data from locator-discovered transcripts, full-read latest transcript | 10 | Gated on transcript-locator results |
google-workspace-researcher | Find prior email threads with the prospect. Prevents repeating points already covered. Informs Q3: "What do they already know?" | 8 | Optional: when prospect email is known and email continuity matters |
slack-researcher | Search for recent internal deal context, follow-up commitments, team discussions. Helps answer Q4: "What work have I done since the call?" | 8 | Optional: when deliverables or internal context would strengthen the email |
obsidian-analyzer | Deep-read account Context.md for deal background, contacts, timeline | 6 | Optional: when account has existing research docs |
Each agent knows its tools and behavioral constraints. When dispatching:
Delegate to sub-agents when:
Read directly in main context:
ALWAYS:
/tmp/meeting-followup/<account-slug>/ before dispatchingNEVER:
run_in_background: true (MCP tools are unavailable in background sub-agents)Temp directory: /tmp/meeting-followup/<account-slug>/
| Agent | Output File |
|---|---|
transcript-locator | transcript-locator.md |
transcript-analyzer | transcript-analyzer.md (structured extraction) + transcript-analyzer-latest-transcript.md (full raw content of most recent) |
google-workspace-researcher | google-workspace-researcher.md |
slack-researcher | slack-researcher.md |
obsidian-analyzer | obsidian-analyzer.md |
Reading pattern after agents return:
Load MCP tools once at the start. Call ToolSearch('+obsidian'), ToolSearch('+claude-memory'), and ToolSearch('+workspace-mcp draft') in parallel at the beginning of Phase 1. Do NOT call ToolSearch again later for these tools.
Read these files directly in the main context (small files, needed before any agent dispatch):
obsidian_get_file_contents calls (do NOT use obsidian_batch_get_file_contents for org-context files; the combined content exceeds token limits and causes overflow errors):
Regal/org-context/org-context.mdRegal/org-context/product.mdRegal/org-context/differentiators.mdRegal/org-context/sales-process.mdRegal/org-context/use-cases.mdtools/references/email-links.md from the repo for link resolution (DocSend collateral, developer docs, platform URLs, placeholder rules)Regal/org-context/case-studies.md from Obsidian for industry-matched case study URLs (Quick Lookup table)If Obsidian MCP is unavailable, apply the filesystem fallback: vault root at OBSIDIAN_VAULT=/Users/nick.yebra/Library/Mobile Documents/iCloud~md~obsidian/Documents/Core Vault. Use Read, Glob, and Bash with this path prefix.
Large file handling: If obsidian_get_file_contents or obsidian_batch_get_file_contents returns ANY token limit error, do NOT retry the same call. Instead, retry with offset: 0, limit: 500 lines. For transcripts, reading the first 500 lines is sufficient since enrichment data from get_meeting already covers action items and signals. For org-context files that are too large, skip the oversized file and proceed with the others.
If the user specified a transcript location (e.g., "the transcript is in Regal/Accounts/ABT Electronics"), go there directly. Read the file and skip to Phase 2b.
If no location specified, use a three-step discovery sequence. Run Step A first; if it returns results, skip Steps B and C.
Path naming conventions differ by folder:
AAA-Life, "Ascend Learning" → Ascend-Learning). Paths with spaces will 404.Regal/Accounts/Ascend Learning/). Do NOT hyphenate the Accounts folder path.Use find_transcript for unified search across SQLite, enriched sidecars, and raw Granola files in a single call:
ToolSearch('+transcript-pipeline')
mcp__transcript-pipeline__find_transcript({ query: "<account name>", days: 7 })
If results are returned: pick the most recent match and call get_meeting(meeting_id) to retrieve the full record including enrichment data (action items, deal signals, risks, participants). Use the enrichment data to inform the email draft: action items become follow-up bullets, deal signals inform tone and urgency, risks flag what to address proactively. Skip Steps B and C and proceed to Phase 2b.
NEVER read the raw Granola file after
get_meetingreturns enrichment data. The enrichment data is sufficient. Reading the raw file is redundant and frequently hits the 10K token limit (raw transcripts are often 15K+ tokens). This rule applies even if you found the Granola path in Step A results.
If no results, attempt an on-demand Clari fetch (see references/transcript-discovery.md for the full fallback cascade including SF-ID resolution and search_account_calls). If the transcript-pipeline is unavailable (connection error) or the on-demand fetch returns nothing, proceed to Step B.
Search Obsidian in this exact order. All three steps are MANDATORY. Do NOT skip the top-level listing.
Regal/Granola-Enriched/ (ALWAYS check this first). Enriched files mirror the raw Granola directory structure but include action items, deal signals, risks, and participants extracted by the pipeline. Search Regal/Granola-Enriched/{account-slug}/ for account-specific enriched transcripts. If found, prefer these over raw files.Regal/Granola/ (list as a separate obsidian_list_files_in_dir call). Scan ALL returned filenames for the account name or keywords. Granola frequently places transcripts here with titles that do NOT match the account subfolder pattern (e.g., Room-for-Ascend-Regal-AI-Agent-Demo.md, Ascend-Regal-AI-Agent-Demo.md). Do not assume only Untitled_*.md files live here. Skip files that already have an enriched sidecar in Granola-Enriched/.Regal/Granola/{account-slug}/): List this last. Skip files that already have enriched sidecars.Regal/Accounts/{company name}/Meeting Transcripts/): List here for additional transcripts not in Granola, using original spacing.After collecting all candidate transcripts from Steps A-C, sort by date (created_at or updated_at). Default to the most recent transcript. If the most recent transcript is more than 48 hours old and the user did not specify which meeting, confirm with the user before drafting: "The most recent transcript I found is from [date]. Is this the meeting you want to follow up on?"
Route based on what was found:
transcript-locator then transcript-analyzer per Phase 3. Do NOT read multiple transcripts directly in the main context; delegate to keep context clean.Create the temp directory first: rm -rf /tmp/meeting-followup/<account-slug> && mkdir -p /tmp/meeting-followup/<account-slug>
Dispatch up to 4 agents in a SINGLE message. Each dispatch prompt includes the account name, key contact names, Output Persistence block with /tmp file path, Source URL Guidance, and what you already know (to prevent duplicate effort).
Dispatch prompt templates:
Wave 1: transcript-locator (always dispatched first in multi-transcript path):
Discover all transcript locations for [Account Name]. Key contacts: [names]. Frontmatter tag hints for pre-filtering: folder/[account-slug], person/[contact1-slug], person/[contact2-slug]
Output Persistence: Write discovered transcript paths and metadata to: /tmp/meeting-followup/[account-slug]/transcript-locator.md
If the Write tool fails with "File has not been read yet", Read the target path first, then Write again. If it fails for any other reason, return your FULL findings as text instead (do NOT summarize).
WRITE EARLY: After your first 2-3 successful research calls, IMMEDIATELY write your current findings to the output file. Do NOT wait until all research is complete. Continue researching and UPDATE the file with additional findings. To update: Read the output file first, then use Edit to append or Write to replace. The initial write is your insurance against output loss. A partial file is infinitely better than no file.
For every finding, include the vault-relative path (e.g., Regal/Granola/filename.md).
Locator failure handling (three-state):
Wave 2: transcript-analyzer (gated on locator success, dispatched with other agents):
Read and extract structured data from ALL transcripts discovered by the locator for [Account Name]. Key contacts: [names]. Locator output: /tmp/meeting-followup/[account-slug]/transcript-locator.md
RECENCY MODE: email-followup Sort all discovered transcripts by date. Full-read the LATEST transcript and write its raw content to the latest-transcript file. For older transcripts, extract focused structured data (promises, next steps, pain points) only.
Output Persistence: Primary output file: /tmp/meeting-followup/[account-slug]/transcript-analyzer.md Latest transcript file: /tmp/meeting-followup/[account-slug]/transcript-analyzer-latest-transcript.md
If the Write tool fails with "File has not been read yet", Read the target path first, then Write again. If it fails for any other reason, return your FULL findings as text instead (do NOT summarize).
WRITE EARLY: After your first 2-3 successful research calls, IMMEDIATELY write your current findings to the output file. Do NOT wait until all research is complete. Continue researching and UPDATE the file with additional findings. To update: Read the output file first, then use Edit to append or Write to replace. The initial write is your insurance against output loss. A partial file is infinitely better than no file.
For every finding, include the vault-relative path (e.g., Regal/Granola/filename.md).
Dispatch transcript-analyzer in the same message as google-workspace-researcher, slack-researcher, and obsidian-analyzer (up to 4 agents total per message).
google-workspace-researcher (when prospect email is known):
Search Gmail for prior email threads with [Contact Name] ([email]). Find the most recent 3-5 email exchanges. Extract: what topics were already covered, what was promised, what questions were asked.
Already known from Phase 2: [Account confirmed: yes/no, transcript found: yes/no with source, enrichment data: available/none, key contacts identified: list names]
Output Persistence: Write complete findings to: /tmp/meeting-followup/[account-slug]/google-workspace-researcher.md After writing, return a 2-3 paragraph summary only. If Write fails, return full findings as text.
If the Write tool fails with "File has not been read yet", Read the target path first, then Write again. If it fails for any other reason, return your FULL findings as text instead (do NOT summarize).
WRITE EARLY: After your first 2-3 successful research calls, IMMEDIATELY write your current findings to the output file. Do NOT wait until all research is complete. Continue researching and UPDATE the file with additional findings. To update: Read the output file first, then use Edit to append or Write to replace. The initial write is your insurance against output loss. A partial file is infinitely better than no file.
slack-researcher (when internal context would help):
Search Slack for recent discussions about [Account Name]. Look for: follow-up commitments, deliverables shared, internal deal context, team discussions about the account. Also search the #ai-demo-requests channel for the account's custom demo agent phone number. Focus on messages from the past 2 weeks.
Already known from Phase 2: [Account confirmed: yes/no, transcript found: yes/no with source, enrichment data: available/none, key contacts identified: list names]
Output Persistence: Write complete findings to: /tmp/meeting-followup/[account-slug]/slack-researcher.md After writing, return a 2-3 paragraph summary only. If Write fails, return full findings as text.
If the Write tool fails with "File has not been read yet", Read the target path first, then Write again. If it fails for any other reason, return your FULL findings as text instead (do NOT summarize).
WRITE EARLY: After your first 2-3 successful research calls, IMMEDIATELY write your current findings to the output file. Do NOT wait until all research is complete. Continue researching and UPDATE the file with additional findings. To update: Read the output file first, then use Edit to append or Write to replace. The initial write is your insurance against output loss. A partial file is infinitely better than no file.
obsidian-analyzer (when account has research docs):
Read files in Regal/Accounts/[Account Name]/. Extract: deal background, key contacts with roles, timeline, recent activity, open action items.
Already known from Phase 2: [Account confirmed: yes/no, transcript found: yes/no with source, enrichment data: available/none, key contacts identified: list names]
Output Persistence: Write complete findings to: /tmp/meeting-followup/[account-slug]/obsidian-analyzer.md After writing, return a 2-3 paragraph summary only. If Write fails, return full findings as text.
If the Write tool fails with "File has not been read yet", Read the target path first, then Write again. If it fails for any other reason, return your FULL findings as text instead (do NOT summarize).
WRITE EARLY: After your first 2-3 successful research calls, IMMEDIATELY write your current findings to the output file. Do NOT wait until all research is complete. Continue researching and UPDATE the file with additional findings. To update: Read the output file first, then use Edit to append or Write to replace. The initial write is your insurance against output loss. A partial file is infinitely better than no file.
After all agents return, read output files from /tmp/meeting-followup/<account-slug>/:
transcript-analyzer-latest-transcript.md (primary drafting source: full raw content of the most recent meeting)transcript-analyzer.md (structured extraction across all meetings: promises, next steps, pain points)Apply the reading pattern from Sub-Agent Output Persistence: file exists -> read it, file missing but result >500 chars -> use result, both missing -> note gap.
Call search_memories (MCP tool) with the account name and limit: 3. NEVER pass a limit above 3. This surfaces prior observations about communication preferences, past email feedback, and deal context. If unavailable or no results, proceed without. If the result exceeds the token limit and gets persisted to a file, do NOT read the file. Skip memory context entirely and proceed.
Answer four questions before writing anything. These determine the entire email.
Then apply the right approach:
Follow all rules in the Email Guidelines section below. Apply the writing-style skill rules including pyramid principle document structure.
Present ONLY the clean email in a clear To / CC / Subject / Body format that is easy to copy-paste. Do NOT include the pre-draft decision, reasoning notes, or internal analysis in the output. The user should see nothing except the finished email. Include a short, specific subject line (e.g., "Next steps from our call" or "Follow-up: integration timeline"). If multiple distinct recipients need different action items, draft separate emails.
Gmail draft creation: When the user confirms the email or asks to draft it in Gmail, ALWAYS use body_format: "html" with draft_gmail_message. Plain text (body_format: "plain") strips all formatting: no bold, no clickable links, no bullet structure. Convert the email to HTML before sending: use <b> for bold headers, <ul>/<li> for bullets, <a href="..."> for links, <br> for line breaks, and <p> for paragraphs. Always set include_signature: true.
Structure: Choose the right pattern based on Question 4 (deliverables):
NEVER lead with a recap of what was discussed. NEVER lead with what Regal can do. Lead with what you have built or what happens next.
Tone: Short and casual. Action-oriented, not discussion-focused.
Subject lines: Keep under 8 words. Lead with the purpose, not the meeting name.
Link resolution: Resolve all links from tools/references/email-links.md and case-studies.md. NEVER use a placeholder for a link that exists in either file.
https://www.regal.ai/privatetour).case-studies.md. Use the actual Link column URL. Only include public or sales-approved entries (never internal).#ai-demo-requests Slack channel for the account's demo agent phone number before using a placeholder. Dispatch slack-researcher with an explicit instruction to search this channel. Only use [Insert DEMO NUMBER] if Slack search returns nothing.[Insert LINK to recording], [Insert DATE].Handling MY promises (things I said I would do):
Handling THEIR promises (things others said they would do):
Proactive collateral: Don't just include links discussed on the call. Proactively include relevant resources using email-links.md and case-studies.md:
Shareable is public or sales-approved. Use the actual URL, One-liner for context, and Top Metric for impact.Formatting rules:
Banned words and phrases (always enforced):
Multiple recipients: If attendees have different action items, ask the user whether to draft one group email or separate emails. Default to one email with people's names inline next to their items.
After presenting the email, ALWAYS include this line at the end of your response:
Run
/track-tasksto extract and track action items from this meeting.
This is a required step, not optional. Do not skip it even if the email is short or the meeting had few action items.