Draft the monthly LP update from the team WhatsApp group, enriched with facts from email, deduped against prior sends. Use when the user asks to write the investor update, LP update, monthly update, or says "time for the LP update". Produces a Superhuman/Gmail draft plus a local markdown archive. Never sends.
Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.
Quelldateien prüfen
Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Ein direkter Befehl überspringt den Prüf-Prompt. Prüfen Sie die Quelle, bevor Sie ihn ausführen.
Draft the monthly LP update from the team WhatsApp group, enriched with facts from email, deduped against prior sends. Use when the user asks to write the investor update, LP update, monthly update, or says "time for the LP update". Produces a Superhuman/Gmail draft plus a local markdown archive. Never sends.
Monthly LP Update
Assemble the periodic LP update from whatever sources a fund actually uses, and hand back a
draft. Assembly is the job; the writing is the easy part.
Two pluggable things, both defined in config.md:
Roster sources — who is in the portfolio. A hand-written list, a CRM, Airtable,
Notion, a spreadsheet, a public portfolio page, or your own prior updates.
Signal sources — where news about them shows up. WhatsApp groups, Slack channels,
founder update emails, forwarded updates, a running doc.
Plus one fixed pair:
updates/ + ledger.jsonl — the format and the memory. What the update looks
like, and what you already told LPs.
Every source normalizes to the same record before triage, so nothing downstream cares
where a fact came from:
trust is set per source in config and decides how a fact may be used.
Tier
Meaning
Example
primary
The company's own written words
A founder's monthly investor update email
team
A partner stated it
A GP pasting Acme at $12.3M ARR into the group
mention
Someone referred to it
"heard Acme closed 🎉"
primary and team figures are quotable. mention never is — it only tells you where to
go looking. When two tiers disagree, primary wins and you note the discrepancy in Stage 5.
THE INVARIANT
No number reaches the draft unless it was explicitly stated by a human — in the chat,
in an email thread, or in a Stage 5 answer. Never inferred.
The distinction is stated vs. inferred, and it cuts across every source:
Usable (primary). A founder's own update email says the round closed at $14M. Best
possible source. Cite the thread.
Usable (team). A GP pastes Acme at $12.3M ARR, 110% NRR into the group. Use it,
and record who posted it and when.
NOT usable (mention). "Acme closed the round 🎉" — this licenses you to go look
for the round size. It never licenses you to state one.
NOT usable. Anything you derived, estimated, annualized, or computed. If the number
isn't written somewhere verbatim, it doesn't exist.
Violating this is the only way this skill can actually damage the user. Everything else is
a bad draft they'll edit.
Hard rules
⚠️ The compose tool can deliver mail. Superhuman's create_or_update_draft has been
observed delivering a type: "new" message that was never passed to send_draft. Do not
trust "it's only a draft." Before calling it, confirm with the user in that moment, and
only ever pass content that would be acceptable if it left immediately.
Never send deliberately. Stage 7 aims to produce a draft. Any intentional send is a
separate explicit confirmation on that specific message.
Never invent a fund-level number. Deployment, reserves, new investments, portfolio
marks — these come from Stage 5 questions only.
Cap Stage 5 at 6 questions. If you have more, drop the lowest-confidence items and
say in the draft what you dropped.
Never silently drop a candidate. Uncertain → it goes in the question round.
Read config.md first. Everything fund-specific lives there. Do not hardcode names,
companies, or recipients into this file.
Tool resolution
MCP prefixes vary by install. Resolve tools with ToolSearch before Stage 0:
WhatsApp tools come from verygoodplugins/whatsapp-mcp — search whatsapp list_messages
if the prefix is unknown. Superhuman drafting: search create_or_update_draft.
Read config.md. If it has unfilled TODO markers, stop and ask for them.
Read state.json for last_run. Absent → default to one period back from today.
Resolve the roster from roster_sources, in the order listed. Merge: a company
named by any source is in the roster; per field, the first source that has a value wins.
Report the merge (47 companies: 40 from HubSpot, 5 from manual, 2 from prior updates).
Resolve every signal source. For each, confirm it's reachable and note its fund
and trust.
Report what is and isn't available before doing any work:
A source that fails is never skipped silently. Say which one, and ask whether to
proceed without it. A missing source is a missing slice of the portfolio, and it looks
identical to a quiet month.
Stage 1 — Harvest
Pull from every configured signal source over the window and normalize each item to the
common record. Tag fund and trust from the source config; carry both through every
later stage.
Source adapters
type
How to harvest
Notes
whatsapp
list_messages on the group JID
Match on JID, never name. Bridge must be running
slack
conversations.history on the channel via a Slack MCP
Threads count — pull replies too
email_query
Mail search over a subject/sender pattern
e.g. subject:"Investor Update"
email_label
Mail search scoped to a label/folder
For funds that file founder updates
email_forwards
Mail search for forwards from a teammate
from:colleague subject:Fwd + the pattern
gdoc
Read the doc, diff against last run
Treat each new bullet as one item
Founder update emails are the highest-value source most funds already have and don't
use. They arrive on a cadence with subjects like {Company} Investor Update - {Month}
or {Company} Monthly Update | {Month}, and they contain the founder's own numbers. Set
them trust: primary. Where a teammate forwards them, harvest the forward — the original
body is intact inside it.
If volume strains context, harvest one source at a time and triage each (Stage 2) before
fetching the next. Carry only the candidate list forward, not the raw text.
Stage 2 — Triage
Classify every message into exactly one bucket:
portfolio-signal — something happened at a company on the roster (round, hire, launch,
customer, metric, press, trouble)
fund-signal — something about the fund itself (a new investment, an exit, an LP matter)
noise — everything else
Match portfolio signals against company_roster in config, including the aliases listed
there. A signal you can't attribute to a roster company is not noise — it may be a new
investment. Keep it, tag it unattributed.
fund comes from the source, never inferred from the company. If a company shows up under
two different fund labels in one window, that is a follow-on: keep both, flag it, and say
so in the draft rather than merging them.
Merge across sources per company before Stage 3. A single company will often appear in
three places in one window — its own update email (primary), a partner's summary in chat
(team), and a passing Slack mention (mention). Collapse them into one candidate holding
all three, ordered by trust. Where they conflict on a number, keep both values and send the
conflict to Stage 5; never quietly average or pick the newer one.
confidence is high / medium / low: how sure you are that this is a reportable event
rather than chatter about one.
If the group is an editorial thread, treat it as one. Many funds run the update as a
round-robin: someone posts a kickoff like "who has updates for the LP email?" and the
team replies with submissions. Where kickoff_pattern is set in config, treat the matching
message as the start of the reporting window and every reply to it as a submission rather
than a passing mention.
Expect real figures pasted inline. Capture them verbatim with the poster and date; they
are usable per THE INVARIANT.
Also capture the team's own editorial calls — they are instructions, not noise:
"we did X last time" → already reported, skip
"we can close the loop there" → a follow-up to a prior entry, not a new one
"still confidential" → hold, do not report
"save it for next month when we really know how it went" → defer
Cross-check these against ledger.jsonl. Where the team's memory and the ledger disagree,
surface the conflict in Stage 5 rather than picking a side.
Stage 3 — Enrich the gaps
Stage 1 already harvested the configured sources. This stage is a targeted search for
candidates that arrived without quotable numbers — typically the mention-tier ones.
Skip any candidate that already has a primary fact. Don't spend searches confirming what
a founder already wrote.
For the rest, in order:
Twang — deal_status, then search_threads scoped to the window and the
company/founder name. contact_brief if the thread set is ambiguous.
Superhuman — query_email_and_calendar with the company name and window;
get_thread on anything promising.
CRM — if a roster source is a CRM, check for a recent-activity or notes field.
Search on the company's domain, not just its name. Two unrelated companies sharing a
word is common, and a name-only search will confidently return the wrong firm's threads —
with a real citation, so the invariant won't catch it.
Extract only facts an LP would care about, each with a source and its trust tier:
Do not resolve UNSOURCED items yourself. They go to Stage 5.
Stage 4 — Continuity
Read ledger.jsonl and the two most recent files in updates/.
For each enriched fact, check whether the same milestone was already reported:
Already reported, no change → drop it. Say so in your Stage 6 summary line.
Already reported, materially progressed → keep it, framed as a delta
("Acme's Series A, mentioned in July, closed at $14M with X leading").
New → keep it.
At a monthly cadence this is the feature. LPs read last month's. Repeating yourself is
worse than omitting.
Stage 5 — Ask (max 6 questions)
One round. Use AskUserQuestion. Priority order, cut from the bottom if over six:
Fund-level, always ask — deployed this month; new investments; any exit, markup or
writedown; the ask to LPs this month.
Ask each of these once, covering both funds in the same question ("Deployed this
month — Fund I and Fund II?"). Asking them per fund would be eight questions and blow
the cap.
UNSOURCED items, highest confidence first — "The chat says Acme closed. I found no
email confirming terms. Report it without numbers, with numbers you give me, or hold it?"
Unattributed signals — "Bolt Logistics came up twice and isn't on the roster. New
investment, or skip?"
Batch related fund-level items into one question. Never ask about something you already
have a sourced answer for.
If you had to cut questions, note it in Stage 6 output.
Stage 6 — Draft
Read the last 2–3 files in updates/ and copy their shape, not their content:
section order, section headings, typical length, how companies are named, whether metrics
appear inline or in a list, sign-off, tone.
Write updates/YYYY-MM.md — one combined document covering both funds, with the
portfolio news split into a Fund I section and a Fund II section. Each company goes under
the fund its source group indicates.
A company that appeared in both groups is a follow-on: one entry, placed under the fund
that made the new investment, noting the prior position.
Pick the subject pattern from what the month actually contains (see config.md):
Fund I news present → Fund I & II: {Month} Update. Fund II only → Fund II: {Month} Update. Quarter close for Fund I (January covers Q4, April covers Q1, and so on) → the
Fund I section becomes a quarterly roundup and the subject is Fund I Q{n} & Fund II {Month} Updates. Fund I reports quarterly; Fund II reports monthly. Do not force a Fund I
section into a month that has no Fund I news.
Every portfolio fact traces to an email source or a Stage 5 answer. Nothing else.
Then append each newly reported milestone to ledger.jsonl:
{"company":"Acme","fund":"II","milestone":"Series A closed, $14M, led by X","reported_in":"2026-08","date":"2026-07-28"}
Update state.json: {"last_run":"<today>"}.
Print a short summary: how many companies covered, how many facts sourced from email, how
many from the user, what was dropped as already-reported, and any questions you had to cut.
Stage 7 — Deliver
Most funds send the real LP update from a mailing platform (Mailchimp, Customer.io) run
by one person. This skill never touches that. What you produce is a draft for whoever
runs the send, per deliver_to in config.
Before calling the compose tool, confirm with the user. It has been observed delivering
mail that was never explicitly sent. Show them the recipient and subject and get a yes.
create_or_update_draft with:
to — deliver_to from config. Never an LP address. If you find yourself
assembling a list of LPs, stop — that list lives in the mailing platform, not here.
acting_email AND from — both set to from_account. Setting only from is not
enough; the tool falls back to the primary linked account.
subject — draft_subject from config
body — the Stage 6 markdown, plus a short lead-in noting which facts came from email
sources and which came from the user's answers
Report:
Draft created for <deliver_to>: "<subject>"
Archive: updates/YYYY-MM.md
Verify in your mail client whether this is a draft or was delivered.
If no email MCP is reachable, skip this stage, say so, and hand back the markdown path.
Markdown-only is a perfectly good outcome.
Failure handling
Situation
What you do
WhatsApp bridge not running
Stop, print the start command
Group / channel unresolved
List candidates, ask
One signal source unreachable
Name it, ask whether to proceed without it. Never skip silently
All signal sources unreachable
Stop
A roster source unreachable
Fall back to the remaining sources, report the smaller roster
Roster is empty
Stop. Nothing downstream works without it
Window is empty
Say so. Ask whether to widen it or skip the period
Markdown only, more Stage 5 questions, say what degraded
What this skill is bad at
Metrics tables. The sources are narrative, not structured — there is no clean ARR series
hiding in a WhatsApp group. Write prose. If the user wants a metrics table, that data
comes from somewhere else.