chapter.guide / swarm / run 025

Email Followup Templates

2026-05-14  ·  PASS  · Bookmark this page: /swarm/025-email-followup-templates.html

Assignment

Design an automated email follow-up system that fires after cold calls (Salesfinity) or discovery calls (Fireflies), classifies signal + side, and threads a draft on the deal page for human polish → Gmail send.

Subset: `pure-strategy` — no contact discovery needed; no independent audit-quality (conductor ran maker-checker inline due to context constraints)

Roster

architectwriterquarterbacklistenerdrapermarket-analyst

What we found

65% of the infrastructure already exists. Both webhook listeners (Salesfinity for cold calls, Fireflies for discovery meetings) are built and verified. The email draft generator, Gmail OAuth, template loader, extraction pipeline, and feature permission system are all live. The missing pieces are: (1) the 10 email templates themselves, (2) a signal classifier that routes calls to the right template, (3) wiring the webhooks to trigger the pipeline, and (4) a deal-page UI that shows threaded drafts for review + send.

Why this matters

Every sales call that ends without a same-day follow-up email loses momentum. The current process requires Ewing to manually remember what was said, open Gmail, and write the email from scratch. This system turns a 15-minute manual task into a 30-second review-and-send, and it runs on every call without exception.

Where we agreed

All six agents agreed on the core architecture: webhook → classify → extract → template select → draft to Supabase → deal page UI → Gmail push. All agreed the existing pieces should be extended, not replaced. All agreed signal classification should happen server-side via Claude (Haiku for cold calls, Sonnet for discovery transcripts).

Where we disagreed

Template granularity: Writer created 10 full templates (5 signals × 2 sides). Market-analyst wanted 200+ field extraction per template. Draper wanted emotional routing rules. Resolution: templates stay at 10 variants, extraction stays scoped to 15-20 merge fields that templates actually use, emotional context lives in the voice_prompt frontmatter (already there).

Table design: Architect proposed a new `followup_signals` table. Draper proposed `follow_up_drafts`. Resolution: extend the existing `email_drafts` table with `signal_type`, `side`, and `source_type` columns. No new table — one query surface is better than two.

What surprised us

  • The `email_drafts.deal_id` column is NOT NULL, which means cold-call followups (where no deal exists yet) can't be stored without a schema change.
  • `gmail-drafts.ts` only supports text/plain. All the templates generate HTML. Needs multipart MIME.
  • `listTemplates()` doesn't recurse subdirectories, so the flat layout in `templates/email/` is actually correct — don't reorganize into folders.
  • `TemplateFrontmatter` type in the template loader drops `side` and `signal_type` during coercion — the YAML parser reads them but `coerce()` discards unknown fields.

What we'd do differently

  • Run the "what already exists" search as a formal Phase 0 checklist, not an ad-hoc discovery during Phase 1
  • For plan-then-handoff assignments, skip the full 10-template content draft and produce structural stubs — Mark will rewrite the content anyway

Currency events

From → ToActionMultiplierBaseScoreNotes
architect → writerDiscovered gmail-drafts.ts HTML gap that affects template design1x33Writer's HTML templates depend on this fix
listener → quarterbackSurfaced edge cases (no-deal cold calls, DNC suppression) that became tasks1x22Prevented post-build rework
draper → writerVoice prompts and no-go rules shaped template tone2x24Direct quality lift on all 10 templates

Cross-system gaps

FlaggerAffectedGapRecommended change
architectwebhook routesSalesfinity webhook ends after `call_log` upsert — no followup triggerAdd `triggerFollowupPipeline(callLogId)` call after line 177 in salesfinity/route.ts
architectwebhook routesFireflies webhook ends after `saveExtractions()` — no followup triggerAdd `triggerFollowupPipeline(meetingId)` call after line 204 in fireflies/route.ts
writeremail-templates.ts`TemplateFrontmatter` type missing `side` and `signal_type` fieldsAdd optional fields to type + coerce() function
quarterbackemail-templates.ts`listTemplates()` only reads flat directory, no subdirectory supportTemplates use flat layout — not a bug, but document this constraint
architectgmail-drafts.tsOnly text/plain MIME — templates are HTMLAdd multipart/alternative with text/plain + text/html parts
architect0010_deal_tracker.sql`email_drafts.deal_id` is NOT NULL — cold-call drafts have no dealMigration to ALTER COLUMN deal_id DROP NOT NULL