Automation · Playbook 01

Draft intro / congratulatory outreach.

When a founder lands on the Outreach List, draft the right email in the right partner's voice — congrats-on-the-raise if they raised in the last two months, normal intro otherwise — and drop it in that partner's Outlook drafts with a Slack ping. Never auto-send.

Sourcing

Helper code snippet

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

Reference build

A founder lands on the Outreach List and the flow has to answer two things before it writes a word: which partner is reaching out, and do we have something to congratulate them on. If the company raised in the last two months, the email leads with the round; otherwise it's a normal intro. Either way, the draft lands in the right partner's Outlook with a Slack ping — never sent automatically.

The branching exists so we don't look like we missed the news. A generic "hey" to a founder who just announced a Series B reads worse than no email at all.

Flow
01 · Trigger
Attio: list_entry_created on the Outreach List
Someone adds a Person to the outreach queue. Everything downstream is keyed off that one event.
02 · Find the Person
Attio find-record on People (by parent record id)
Pulls the Person's full attribute set — name, email, current company link, congratulations flag, email_founder partner field.
03 · Gate · email on file?
Branch on Person.email_addresses icontains '@'
Cheapest possible early exit. If there's no email, we don't research, draft, or queue anything.
Path D · Email present → continue
Continue to enrichment, recency math, and drafting (steps 04–12).
Path E · No email → stop
Outlook → Dan
Subject: Dan's Outreach Failed. Body: founder name + Attio record id. Triage by hand.
04 · Resolve company
Attio find-record on Companies (from Person.current_company)
Need the company's name + description for research, and last_funding_date for the recency check.
05 · Re-read the list entry
Attio find-list-entry on the Outreach List
Pulls the list-entry attributes: congratulations ('Send email' or empty) and email_founder (the requesting partner).
06 · Recency math
Inline JS: months between last_funding_date and today
diffMonths = (today − last_funding_date) / 30.44. Returns outreach_type = 'congrats' if ≤ 2, otherwise 'normal'.
07 · Research the company
OpenAI gpt-5.2-chat-latest
One-paragraph factual description of the startup and the space it plays in. No opinions, no email tone — just substrate for the drafter.
08 · Template branch
Branch on (congratulations + outreach_type)
Path F: outreach_type = normal → use the normal intro template. Path G: congratulations = 'Send email' AND outreach_type = 'congrats' → use the congrats template.
09 · Partner router
Branch on email_founder ∈ {Austin · Shaw · Drew · Mark · Dan · Brian}
One branch per partner. Each branch carries that partner's voice prompt, their Outlook account, and their Slack DM target.
Branch · Austin
Claude · draft body
claude-sonnet-4-6 with Austin's voice + company research + founder context. Body only — no subject.
Outlook · create draft
In Austin's account. Subject templated: Congrats on the raise — {Company} // {Firm}.
Slack · DM Austin
"Just drafted an email to the {Company} founder — check your drafts."
Branch · Shaw
Claude · draft body
claude-sonnet-4-6 with Shaw's voice + company research + founder context. Body only — no subject.
Outlook · create draft
In Shaw's account. Subject templated: Congrats on the raise — {Company} // {Firm}.
Slack · DM Shaw
"Just drafted an email to the {Company} founder — check your drafts."
Branch · Drew
Claude · draft body
claude-sonnet-4-6 with Drew's voice + company research + founder context. Body only — no subject.
Outlook · create draft
In Drew's account. Subject templated: Congrats on the raise — {Company} // {Firm}.
Slack · DM Drew
"Just drafted an email to the {Company} founder — check your drafts."
Branch · Mark
Claude · draft body
claude-sonnet-4-6 with Mark's voice + company research + founder context. Body only — no subject.
Outlook · create draft
In Mark's account. Subject templated: Congrats on the raise — {Company} // {Firm}.
Slack · DM Mark
"Just drafted an email to the {Company} founder — check your drafts."
Branch · Dan
Claude · draft body
claude-sonnet-4-6 with Dan's voice + company research + founder context. Body only — no subject.
Outlook · create draft
In Dan's account. Subject templated: Congrats on the raise — {Company} // {Firm}.
Slack · DM Dan
"Just drafted an email to the {Company} founder — check your drafts."
Branch · Brian
Claude · draft body
claude-sonnet-4-6 with Brian's voice + company research + founder context. Body only — no subject.
Outlook · create draft
In Brian's account. Subject templated: Congrats on the raise — {Company} // {Firm}.
Slack · DM Brian
"Just drafted an email to the {Company} founder — check your drafts."

What the flow writes

Nothing ever leaves the building automatically. The flow writes a draft in the partner's mailbox and tells them it's there.

PathOutputShape
G · congratsOutlook draftIn the requesting partner's mailbox. Subject: Congrats on the raise — {Company} // {Firm}. Body: Claude-written, partner-flavored, references the round.
F · normalOutlook draftIn the requesting partner's mailbox. Subject templated for an intro (no fundraise reference). Body: Claude-written intro with company context.
G / FSlack DMDirect message to the partner: founder name + company + "check your drafts." Closes the loop.
E · no emailOutlook emailTo: Dan. Body: founder name + Attio record id. Triggers a manual lookup, no draft is queued.

Gotchas

The risky parts are timing (a stale 'congrats' is embarrassing), gating (don't waste tokens on records with no email), and tone (each partner sounds like themselves).

  • 01Two questions, not one. The flow decides (a) which template to use — congrats vs. normal — and (b) which partner is sending. Those are independent: a 'congrats' email from Drew looks nothing like a 'normal' email from Austin. Collapse them into one branch and the prompt has to know everything; split them and each branch stays small.
  • 02Recency is measured in months, not 'recent'. The inline JS subtracts last_funding_date from today, divides by 30.44, and returns 'congrats' if ≤ 2. Two months is the window where 'congrats on the raise' still reads as timely; outside it you sound like you just learned about it, which is worse than not mentioning it at all.
  • 03Two gates have to both agree before drafting. The 'congrats' branch only fires when the partner has explicitly marked the record with congratulations = 'Send email' AND the math says the round is fresh. Either one alone isn't enough — partners sometimes mark old rounds, and fresh rounds aren't always worth congratulating.
  • 04Email presence is checked before anything expensive runs. If the Person has no email on file, the flow stops early and emails Dan with the record id and the founder's name. No research call, no LLM tokens spent, no Outlook draft sitting in a void. Failures are cheap; successes earn their cost.
  • 05Research and drafting are split across two models on purpose. GPT-5.2 writes a one-paragraph factual description of the company; Claude takes that paragraph plus the partner's voice and writes the email. Same prompt-shape for every partner, different writer underneath — the research never has to know who's sending.
  • 06Partner routing is a hard-coded allowlist, not a lookup. Austin · Shaw · Drew · Mark · Dan · Brian each get their own branch. Adding a partner means adding a branch with their prompt, their Outlook account, and their Slack DM. It's intentional: each partner's tone is calibrated by hand and not derived from a profile field.
  • 07The draft is created, never sent. Outlook gets a draft in the partner's account; Slack pings the partner that it's there. The human reads it, edits it, hits send. Auto-send on a fundraise congrats is exactly the kind of automation that ends up screenshotted on LinkedIn.
  • 08Subject line is templated, body is generated. Subject is always 'Congrats on the raise — {Company} // {Firm}' (or its normal-outreach equivalent). The model writes only the body and is explicitly told not to include a subject line — so it can't accidentally override the templated one downstream.

Swap matrix

Every layer is replaceable. The two non-negotiables are a CRM that can fire on list-entry creation and a draft surface that accepts an API-created draft without sending it.