pre-meeting
$
npx mdskill add anthropics/claude-for-financial-advisors/pre-meetingBuild a financial review prep document an advisor can read in 10 minutes and walk into the meeting confident.
SKILL.md
.github/skills/pre-meetingView on GitHub ↗
---
name: pre-meeting
description: Prepare a complete client review meeting prep document for a financial advisor, for whatever timeframe the review covers (quarterly, annual, ad hoc). Given a household name or email and a timeframe, pulls CRM context (Salesforce, Redtail or Wealthbox), portfolio data (Orion Connect, Addepar or Envestnet/Tamarac), estate & tax status from the estate platform (Wealth.com), meeting notes from the meeting-intelligence tool (Zocks) or the CRM, recent correspondence (Gmail or Outlook), and the household's plan snapshot from the planning platform (MoneyGuide), then assembles a meeting-ready prep doc with agenda, talking points, and action items. Triggers on "pre meeting", "/pre-meeting", "prep for [client]", "quarterly review prep", "get me ready for my meeting with [client]", or "client meeting tomorrow".
---
# Pre Meeting
Build a financial review prep document an advisor can read in 10 minutes and walk into the meeting confident.
## Inputs
Required: **household name and/or email address**, and the **timeframe** the review covers (quarterly, annual, or ad hoc). If either is missing, ask for both before doing anything else — default the timeframe to quarterly if the advisor doesn't care which.
Optional (ask only if ambiguous): meeting date/time, anything specific the advisor wants to cover.
**Take the advisor's grain literally.** A household and a single account are both valid subjects. "The Harrington IRA" means that account; "the Harringtons" means the household. Don't silently widen a named account to its household, or narrow a household to one account.
## Data Gathering
Follow the **Connector Placeholder Convention** (the plugin's conventions are defined in the onboarding skill): before assuming a system below isn't connected, look for its tools the way the next paragraph says — don't guess at a tool-name prefix like `mcp__orion__*`, since real connector tool names use opaque prefixes. If they're there, use them. If they aren't, say "This is where I'd pull [data] from [system], but it isn't connected in this session. You can connect it from your connector settings," then offer the manual fallback (paste, upload an export, or skip) and keep going. Apply this to every source below, not just the first one that's missing. **If more than one connected tool could answer the same source below for this household** — two CRMs, two portfolio platforms, or any pairing that holds the same fact — follow the Ask-Once, Then Route Convention in its fixed order: **identify the household in one system** (source 1's disambiguation rule — in the CRM, or in one of the overlapping systems if no CRM is connected), **then ask the advisor once which is the book of record** — one question naming the systems for every source that overlaps — **before an overlapping source's read goes out, then dispatch that source's read to the system they named, and only that one.** Reads for sources that don't overlap go out as usual. Never read the second system before they answer, and never guess. A name that doesn't resolve in the first system is not a reason to search the second: ask then, and put the name in the same question ("I couldn't find the Hendersons in Wealthbox — is Redtail their book of record, or do they go by another name?"). The question comes when that first search returns, whatever it returned — a match, several candidates (they go in that same question), nothing at all, or an error you can't read — before any other call to either overlapping system. "It isn't in this one, so let me check the other" is exactly the search this rule forbids: which system holds the household is the advisor's to tell you, not yours to find out by searching. When they answer, offer to save the choice so they aren't asked again next session — the offer opens the reply that takes their answer, before your first read to the system they named, even when their answer also hands you a different name to search: they paste *"For the [household] household, treat [system] as the book of record for [data type]. Don't ask me to choose again for this household."* into **Settings → General → Instructions for Claude** — Claude can't write those settings, so never offer to save it yourself or say you have. Two routes below are defined, not asked about: the CRM's household record is the book of record and the meeting-intelligence tool only colors it (source 4), and the held-away alts check reads an alts platform only when it isn't already this doc's portfolio source (source 2). This gathering pass touches several systems in sequence, so the check isn't a one-time thing at the top: re-run it whenever a later source could answer something an earlier one already did, and if two sources you did pull disagree on a material fact, stop and surface it to the advisor as a blocking question before the brief is finalized rather than presenting both. If the disagreement is by orders of magnitude for the same household, follow the Magnitude-Conflict Convention: name the conflict, and exclude the outlier's figures from every table and total rather than quoting them as evidence.
**Look for the tools before you trust the registry, or the advisor.** Your own tools are the check that decides: a system whose tools are in your tool list, or come back from a `ToolSearch` by the system's own name, is connected and callable — use them. Where the session offers `ToolSearch`, a system's tools can be held back until it loads them, so search by name for every source below whose tools aren't already in your list; where it offers none, nothing is held back, and your tool list is every tool you have. An advisor saying a system isn't connected, or that none is, doesn't decide it either, since advisors have usually forgotten what they connected during onboarding: look for every source below this way before you name any of them as not connected, and when you do, say it as what you found, not as what they told you. `ListConnectors` can answer "No installed connectors found" even in a session with several live, working connectors, and in some clients it renders a user-facing card rather than returning data at all. So it explains a gap, it never establishes one, and an empty result means **unknown**, never "nothing is connected". When it does return entries, read `enabledInChat`, not `connected`: `connected: true` with `enabledInChat: false` is authenticated but switched off for this chat, so tell the advisor they can enable it here rather than reporting it as unconnected; a missing or `null` `connected` is unknown, not disconnected.
Once identity is confirmed, **pull from all connected sources in parallel** — one slow or missing source degrades only its own section of the doc, not the rest. Before starting this multi-source pull, tell the advisor what you're about to gather and why, so it doesn't look like a silent hang — and in the same breath **name the sources you won't be pulling because you looked for their tools and found none** (above), each in the line above, which offers to connect it. Advisors don't notice a gap on their own. The offer costs nothing if they say no, and it never blocks: make it, then carry on with the best pass the connected systems allow. If the advisor has already said they don't have a given provider, don't raise it again, in that line or anywhere else, and don't leave "connect this" language anywhere in the document. And once the household and timeframe are known, don't ask "should I start?" — narrate what you're doing and go. Questions can still come before the document is written — a missing household or timeframe (Inputs), which household is theirs (source 1), which system is the book of record, a conflict between two sources, and source 7's data questions — but each asks for a fact only the advisor holds, never for permission to run the pull you've just described. It asks the advisor to agree to two things only: source 7's save in the analytics platform, once per conversation, in one line, and a report run on a portfolio system that only runs reports (source 2), as that system's rules say.
**Dispatch the parallel pull as one `claude-for-financial-advisors:source-extract` subagent per source, all in a single message** — the Agent tool, `Agent(claude-for-financial-advisors:source-extract)`, one call per source in the same response so they run concurrently rather than one after another — except a source whose systems overlap, whose read waits on the book-of-record answer above and goes out once the advisor has named the system — each in the foreground (`run_in_background: false`) so every block comes back as its call's result inside this turn. **Hand each read its system's tools by name.** The check above is yours, never the read's: take each system's tool names from your own tool list, or from the `ToolSearch` by its name when they aren't there, and hand the read every name that came back for its system exactly as written — the full name, never a prefix you guessed and never the system's name in a tool's place — because, of its system's tools, a read calls only those you name, by exactly the names you give; tool search, which it may use to load them, is not one of them. **Asking a system's assistant is a read.** A question put to a system's own assistant reads that system, even where the system keeps the question in the advisor's own history, so it is never a reason to leave the system unread. A dispatch hands its read every tool you found for its system, never a shorter list and never a note to avoid one, and a read you do inline works from the same list: which of them a read calls is for the read's own instructions and the system's provider file to decide. Each dispatch hands over the household identity as you have it, the one system that subagent is to query, the tool names you found for it, the field schema for that source (what its heading below says to pull), and the window the timeframe implies — or, where a source reads current state and has no meaningful review window, a plain statement of that instead of a window. Each returns a filled schema block. Two reasons this is a subagent rather than a tool call you make yourself: the raw payloads — email threads, full holdings tables, an estate look-back — stay out of your context so you assemble the doc from six compact blocks instead of six raw dumps, and the extraction work for all six happens at once rather than sequentially in your own reasoning.
**You still own identity.** The subagents are instructed never to resolve it: a `claude-for-financial-advisors:source-extract` that finds several candidates or a mismatch returns `IDENTITY MISMATCH` with what it saw and stops. Handle that the way the disambiguation rule below says — show the advisor the candidates, confirm, re-dispatch. Verify the returned blocks agree on the household before assembling anything from them. Fanning the reads out does not move that responsibility; it stays with you.
A subagent that returns `NOT CONNECTED` is the Connector Placeholder Convention case. It won't offer the manual fallback itself — it isn't in the conversation with the advisor. You make that offer. A `NOTHING FOUND` return is an answer, not a gap: the system was reached, searched, and holds nothing for this household, so its section says *"Nothing found in [system] for [household] — searched [what the read reports it searched]"* — never a "— pending" marker, which says the data is still to come, and never a candidate question, which says it found someone else. A `PARTIAL` return is used as far as it goes: the fields it filled go in as returned, and each field it did not is marked "— pending [connector]" with the reason the read gives — never re-read to fill it, because a read stops at `PARTIAL` only where going on would take a write, which no read in this skill makes, or where every call it made returned an error, which a second read would only meet again. A read where some calls were answered and others returned an error comes back `OK`: its filled fields go in as returned and are never marked pending, and a field it marks "— not available ([connector] returned an error: …)" is "— pending [connector]" in the prep doc, with the error quoted, because an error says nothing about what the connector holds. **Finish every read in this turn.** A read whose dispatch errors, is refused because the concurrent-subagent limit is reached, returns `CANNOT CALL`, or hasn't come back by the time you would otherwise end your turn is yours to do inline — the same system, the tools you found for it, the same schema and window — and its result goes into the prep doc exactly as a returned block would. A read you finish inline follows the plugin's provider file for its system where there is one, as its dispatched read would: before your first call, list `${CLAUDE_PLUGIN_ROOT}/providers/`, and if it holds a folder named for that system, read every file in it and follow it for the whole read. Never end your turn with a read outstanding: a slower prep doc is the fallback, a half-built one never is. An `IDENTITY MISMATCH` is not outstanding — it is the question above — and no failure here is fixed by dispatching the same read again.
### 1. CRM (for example Salesforce, Redtail or Wealthbox)
**Disambiguation rule:** query the CRM by name AND confirm identity before pulling anything. If multiple contacts match the name, show the advisor the candidates (name + masked email + account) and ask which household is theirs — common names will return coincidental matches, and pulling the wrong client's data into a prep doc is a privacy incident. Never proceed on a name match alone. When one candidate is a clearly better match (exact email match, most recent activity), pre-select it as the default choice in that prompt — the advisor still has to confirm it, never skip that step outright.
A recognizable or public-figure name that matches a connected CRM record is a household like any other — treat it accordingly and do not refuse, hedge, or ask for extra justification because the name is well-known. This is guidance for how you proceed, not content for the document: the prep doc itself should read exactly like any other household's, with no note, disclaimer, or aside about the name being recognizable.
Pull the household record:
- Notes/insight-type fields (freeform notes, comments) from the CRM record
- Household members, key dates (birthdays, RMD age, Medicare eligibility at 65, Social Security decision points)
- Open tasks/action items (structured task list) — **at both grains: the household record's own items and each person contact's.** A CRM household is often itself a record with its own id (Wealthbox's is a contact), and household-linked tasks are invisible to contact-only lookups
- Service history — recent requests, complaints, referrals given
### 2. Portfolio platform (for example Orion Connect, Addepar or Envestnet/Tamarac)
Pull household and per-account data: market values, performance vs. benchmark, allocation vs. target and drift, realized/unrealized gains, income and fees, cash balances and large flows for the review period.
A platform's benchmark fields can return a plausible return for an asset-class index rather than the household's assigned benchmark — a real figure answering a different question. Present a benchmark return as the household's only when the source ties it to this household or account — a performance report that states the household's benchmark does, a bare benchmark field returned for a position or an index does not; otherwise name what it is measured against, or mark the comparison "— pending assigned benchmark".
**A portfolio system that runs reports but returns no holdings** — its tools identify households and accounts, look up a current value and run reports, but return no holdings, performance, allocation, drift, gains, fees or flows — is worked with the way @${CLAUDE_PLUGIN_ROOT}/partials/rules/report-only-systems.md says. For performance, drift, gains, fees or flows, run its report for the period this review covers (QTD for a quarterly review, YTD or 1yr for an annual one, the advisor's window for an ad hoc one). If no report can be run or none returns data for the period, degrade explicitly — state the AUM figure you do have and mark performance/drift/fees/flows "— pending [system] report," rather than presenting AUM as if it were the full portfolio picture.
Where the connector exposes reconciliation status (e.g. Envestnet/Tamarac returning `reconciliationStatus` / `lastReconciliationDate`), pull and surface it — flag stale or unreconciled data before quoting balances built on it.
**Held-away alts check (lightweight):** every connected alts platform (for example CAIS, iCapital or Addepar) that isn't this doc's portfolio source is read like every other source: one more `source-extract` read in the parallel pull, to that platform, one read for each. The platform that is the portfolio source is not read again here, since its own holdings already report its alts through lookthrough. The read has no review window, since it reads holdings as they stand, and its schema is three fields: how many alternative investment positions are held for the household; the platform's own total value for them, with the as-of date of each figure; and upcoming capital calls, each with its amount and due date.
Positions found → one line in the template, cited to the platform, pointing to `/alts-brief` for detail (no lockups or performance here): the count, the platform's own total with its as-of dates where it gave one — never a total you summed from its rows — and upcoming capital calls as the read returned them. Where the read marks capital calls not available, the line says the platform doesn't give them, in its own words where the read quoted any: never a schedule worked out from an unfunded commitment, and never "none" the platform didn't say. No positions — the read returns `NOTHING FOUND`, or a count of none → the line says nothing was found in the platform for the household, with what the read searched, or for a count of none what you asked it for, as any source that held nothing does (above), so the advisor knows the platform was checked and nothing was guessed. No alts platform connected → **omit the line entirely, no "pending"**: this check is optional, and its absence isn't a gap. Platform connected but the read came back `PARTIAL` → "— alts coverage not checked; run /alts-brief if this household holds alternative investments".
### 3. Estate & tax — the estate platform (for example Wealth.com)
Pull, as the estate platform reports them:
- The look-back report for the most recent filed tax year, whatever the review's timeframe: the tax year, filing status, AGI, taxable income, federal and state tax, capital gains, dividends and deductions, and the federal and state bracket tables
- From the document inventory, the documents uploaded within the review window, each with its type and dates
Cite each figure to the estate platform and its tax year — never recompute or estimate a figure Claude wasn't given. The look-back exists for filed tax returns only, never for a trust, will or other estate document.
### 4. Meeting notes — the meeting-intelligence tool (for example Zocks), or CRM notes as fallback
There is no Zocks "prep" endpoint — Zocks' MCP only exposes atomized reads (contacts, meetings, per-meeting AI results, insights), not the finished brief its own product UI generates. Build the picture yourself:
- **Fan out, then dedupe.** Resolve the household's contacts, list their past meetings, then pull AI results/summaries per meeting. Per-meeting extractions repeat near-duplicate household/financial detail across meetings, and a long-standing household can return dozens of results and summaries — collapse those into one current picture instead of listing each copy.
- **Precedence, in order:** prefer the meeting-intelligence tool's AI results/summaries over the raw transcript; use the transcript only when you need the client's own words verbatim (e.g., a direct quote), not as the default source; if it isn't connected, or is connected but returns no contact/meetings for this household, fall back to whatever the CRM has logged from prior meetings — the common case is the latter, not a missing connector; only fall back further to a manual paste/upload if neither is available.
- **Default to summary-first.** Don't dump every AI result for every meeting — pull summaries for the last 1-2 meetings by default. Treat a full extraction fan-out across more meetings as a deeper, slower pass and ask the advisor before spending that extra latency.
- **Household is a relationship, not a record.** Zocks has no household object — it's "the people who usually meet together." Treat the CRM's household record as the book of record and use the meeting-intelligence tool only to color it; reconcile what a meeting extraction says against the CRM rather than treating any single meeting's extraction as authoritative.
- **One item, one row.** When an action item from the meeting-intelligence tool and a CRM task describe the same underlying thing (e.g. a Roth conversion analysis mentioned in a meeting and tracked as a CRM task), merge them into a single line using the CRM's status — never list it twice just because it showed up unresolved in the meeting-intelligence tool and resolved in the CRM.
- **Cite the meeting**, by date (and meeting ID if the tool returns one), for anything sourced from the meeting-intelligence tool — and never attribute a fact to a CRM or planning source that the Zocks MCP itself didn't return — its tools expose Zocks's own meeting data only, not the systems Zocks integrates with.
- **Layer firm-level Insights separately**, when the connector has an insights tool — firm-wide trending topics, sentiment, referral opportunities. That's distinct from "what changed for this household" and belongs in Talking Points (see below), not folded into Since We Last Met. A household-scoped insight or sentiment result from the same tool, tied to this client specifically, is a Relationship Signal, not a firm trend — route it there instead.
- **Relationship signals — source from insights and notes, not task fields.** Populate the Relationship Signals section from the meeting-intelligence tool's AI results/summaries and insights (when the connector exposes them) first, then CRM freeform notes fields (meeting notes, "notes"/"comments" on the contact or household record) — never from CRM structured task/action-item fields. Task fields track what's due, not what's true about the relationship, and are used inconsistently across RIAs; a CRM with an empty task list can still have a rich notes field. This section should still populate from whichever of the meeting-intelligence tool or CRM notes is available — it does not wait on both, and it never blocks on the task list being empty or unmaintained. If both the meeting-intelligence tool and CRM notes are unavailable, mark the section "— pending [meeting-intelligence tool / CRM notes]" per the Connector Placeholder Convention rather than omitting it. Cite every signal the same way as above: date (and meeting ID if returned) for anything sourced from the meeting-intelligence tool, the field name (e.g. "per CRM notes field") for anything CRM-sourced. A signal with no source behind it doesn't go in the doc.
- **This skill still writes the Proposed Agenda itself** from the gathered data — never call a Zocks-generated agenda/prep or its Default Prompts a substitute for that section.
### 5. Email (for example Gmail or Outlook) — available today for most users
Search correspondence with the household's email address over a window that follows the chosen timeframe — roughly the last 3-4 months for a quarterly review, ~12 months for an annual review, or whatever's appropriate for an ad hoc one. Extract:
- Open requests or questions the client is waiting on
- Commitments the advisor made ("I'll get you that Roth analysis")
- Life events mentioned (job change, new grandchild, home purchase, health, inheritance)
- Tone/sentiment — anything suggesting concern or dissatisfaction
### 6. Plan snapshot — the planning platform (for example MoneyGuide)
**This source has no review window.** It reads the household's plan as it stands right now, so the dispatch hands that fact over in the window's place — never a blank, and never the review timeframe, which would imply a lookback this source doesn't have.
**Identity stays inside this pull**, the same way every other source resolves its own system: the subagent searches MoneyGuide by surname — households are stored surname first and the search matches the start of the name — and returns `IDENTITY MISMATCH` with what it saw if several match or the only match is a different household, or `NOTHING FOUND`, naming the surname it searched, if nothing matches at all.
Pull:
- Net worth — total, assets, liabilities
- Probability of success — only when the household has a plan
- Each goal — name, initial expense, start year — only when the household has a plan
- The plan's last-updated date, which dates the plan without saying what changed in it
Quote every figure exactly as MoneyGuide returns it: the output is prose and already rounded, so never recompute, re-derive or re-round it, and never fill a gap with a figure of your own.
**No plan on file** is a normal, informative answer from a working connector, not a degraded read: net worth still comes back and still goes in the doc, while probability of success and goals are marked not applicable for this household rather than left blank. An absent probability of success is never rendered as zero and never dropped silently — and never marked pending either, which would send the advisor chasing a connector problem instead of reading the connector's honest answer.
### 7. Portfolio analytics and risk — the portfolio analytics platform (for example BlackRock Advisor Center)
**This source runs on its own, after the parallel pull.** Every source above is dispatched as a read-only `source-extract` subagent, all in one message. This one can't be: it needs the holdings source 2 returned, it can ask the advisor questions, and it can save a portfolio. A read-only subagent does none of those, and handing it this work returns `PARTIAL` with the analytics silently missing. So run it yourself, in this turn, once the pull is back; the only thing that ends your turn before it finishes is a question to the advisor: one of its own below, or the blocking question a conflict between sources raises (above) — the section already carries one source that waits, the overlapping-systems read that holds for the book-of-record answer, and this is the second.
**When it's there, it runs.** An advisor saying nothing is connected is not the check: look for the platform's tools anyway, as above, before asking about a save or saying none was made. If they're there, the analytics are part of this pass — not an offer. When they need a new saved portfolio, the one thing they wait on is the advisor's agreement to that save (below). If it isn't connected, omit this source and everything below it entirely: no "pending", no gap line, and the rest of the doc is unaffected. And never compute its figures in their place: without it, no volatility, stress, scenario or risk-driver figure appears that you worked out yourself — not from assumed sensitivities, asset-class rules of thumb or the holdings themselves, and not as a substitute table. A figure another connected system returns itself can be quoted, attributed to that system and paired with its reference. This is additive colour on top of source 2's own performance and drift figures, never a replacement for them.
**Look for a saved portfolio before building one.** The analytics read a *saved* portfolio, and the advisor may already have one — their own, or an earlier prep's. List the advisor's saved portfolios and saved households before creating anything, and keep the two straight when reporting them: they return different kinds of subject, and a portfolio whose *name* contains "Household" is still a portfolio. Both list saved objects only — accounts synced from the custodian never appear — so an empty result means nothing has been saved for this household, not that the household is unknown. Advisors name these themselves, so match the way an advisor would rather than by exact string: "Henderson Family", "Hendersons Q2 60/40" and "Henderson Family — Pre-Meeting 2026-06-24" are all candidates for the Hendersons. A saved one whose name isn't this household's is never used without asking, whatever it holds, since another client on the same model can hold the same funds: at most it is a candidate in the question below.
**Ask which to use only when there is a real choice.** Several plausible candidates, or one that predates the review period → show each by **name and the date it carries**, since that pairing is what lets an advisor recognise their own work, and ask whether to analyze one of them, save a new one from today's holdings, or leave the analytics out. Give them the trade-off in a line, before the options: a saved portfolio is a point-in-time artifact answering *how this looked then*, today's holdings answer *how it looks now*. Word the new option as the save it is, and end on the no: *"…, save today's holdings to your [platform] library as "[name]" (I can't delete it afterwards, and picking this is your OK to save it), or leave the analytics out of this prep?"*, so an advisor who picks the save has agreed to it, knows it, and isn't asked again. That option is then the save request (below), and the question names every answer, the no included, so nothing follows it, and no second request for the same save goes beside the question. **This is a data question** — a fact only the advisor holds, asked once. Exactly one current match → say which one you're using and carry on: nothing is saved, so nothing is asked. Nothing saved → build one, once the advisor agrees to the save (below).
**They pick a saved one → read it before analyzing it.** Read the chosen portfolio by its id, so the doc can say what it holds and as of when; never analyze a portfolio you haven't read back. Analyze its holdings exactly as they stand — don't re-key today's positions into it, which would overwrite the artifact. Cite the analytics to that portfolio and its date rather than to source 2's current holdings, and name it in Portfolio Review so the advisor knows which one the figures came from. Then reconcile: "figures computed on" names every account and position the saved portfolio leaves out, including positions excluded when it was built, so it adds up to the household total, and the stress test carries the same caveat.
**Building a new one → save it dated, and never write over an earlier one.** The saved portfolio is the ground truth this prep's figures were computed against. This platform is not a system of record and its portfolios are point-in-time artifacts by design, so one accumulating per prep is intended behaviour, not mess to clean up. Build it as a saved household under `"{Household Name} — Pre-Meeting {YYYY-MM-DD}"`: the household so the advisor can find it, the skill so they know what produced it, the date so it stays the record of this prep. Names must be unique among the advisor's saved portfolios and households, compared trimmed and case-sensitively, so a second run the same day takes a short distinguishing suffix rather than overwriting.
**Never save a portfolio built on positions the advisor didn't supply.** Source 2's holdings, or an upload or paste the advisor gave, are the only book this write may carry — with a proxy or exclusion the advisor named for a position that wouldn't resolve. No stand-in, sample or illustrative positions, under this household's name or any other, however clearly they are labelled. With no holdings of the household's own in hand there is nothing to build from: omit this source the way an unconnected platform is omitted, and say so.
Build fresh rather than cloning a previous prep. A clone carries account structure forward, but the next step re-keys today's holdings and re-resolves every position anyway — so cloning costs a clone, a rename and an update where a create costs one call, and the clone tools generate their own names, making the dated name a second write regardless.
**Ask before the first save, once per conversation, in one line, and save only with the advisor's agreement.** A saved portfolio stays in the advisor's library, because this plugin has no tool that deletes one, so like every other write in this plugin it waits for their agreement. Ask it in this one sentence, with the household, the platform and the name filled in, since it already says that nothing saved fits, what you would save, where, under what name, why, and that it stays, and ends in a question that names both answers: *"Nothing is saved for [household] in your [platform] library, so to run its risk and stress-test analytics I need to save these holdings there as "[name]", and I can't delete it afterwards — OK to save it, or should I leave the analytics out?"* That sentence is the whole request, and nothing else in the message is about the save: not what the saved-portfolio listing found, or what a no means, which the sentence says; not what happens once they answer, which the work that follows shows; and not how to answer it. Saying you are about to save is not asking. Ask as late as you can while still before the save: once the saved-portfolio listing and the security search below are back, in the same message as any question still open then, such as a proxy or exclusion for a position that wouldn't resolve, with this line last so that a bare "yes" plainly answers it. Where the which-to-use question above is open, its new-save option is this request in the sentence's place, and that question goes last instead. Then end your turn; the save, the analytics and the document follow their answer. Ask once per conversation, not once per save: once the advisor has agreed in this conversation, every later save in it goes ahead without asking, and the close still names each one.
**What counts as agreement** is the advisor's own words, in this conversation, agreeing to a save in the platform: a yes to this line, picking the new-save option above, agreement given the same way in /portfolio-rebalance-review earlier in this conversation (accepting its current-against-proposed comparison included), or saying it unprompted ("save whatever Advisor Center needs"). A yes with a condition you can meet, such as a proxy or an exclusion, is agreement to the save with that condition. A yes on a condition you can't meet, such as deleting it afterwards, is not agreement: say in a line that you can't, and go on as below. Asking for the prep, a "go ahead" before you asked that doesn't mention saving, asking for risk or stress figures before being told they need a save, and a standing instruction in their settings are not agreement, so ask. A run that saves nothing asks nothing: one that analyses a portfolio already saved, one where the platform isn't connected, one with no holdings to build from, or one whose security search failed (below).
**Without agreement, nothing is saved and the analytics don't run.** That covers a no, and a reply that answers the other questions in the message and passes over the save: asking again would be a second request, so go on exactly as for a no. Write the document without the analytics, left out exactly as when the platform isn't connected: no "pending", no gap line, no figure computed in their place, and no further reads on the menu. Nothing in the document says they were left out or why — not the Data Note, not the Executive Summary, not Portfolio Review — because a line about them tells whoever reads the doc that something is still owed when nothing is. The one place that says why the analytics are missing is the close, in one line, in chat. Don't ask again in this conversation, here or in the other skill. If the advisor then asks for them, or says yes after all, that is their agreement, because the close has told them what the analytics need: save, run them, and fold them into the file already written, the way an accepted further read is.
**Re-key today's holdings into the portfolio you are building** — the new-portfolio branch only. Resolve every position through the platform's security search first, passing the whole set in **one batched call** rather than one call per ticker. **If the search itself fails** — the platform refuses it, or answers with an error in place of the resolutions — no position can be keyed, so there is nothing to build and no save to ask for: don't ask it, and go on as for a write that fails (below). A `unique` resolution proceeds by its CUSIP. An `ambiguous` or `none` resolution is never guessed and never silently dropped: offer the advisor a proxy security they name or explicit exclusion, with the portfolio total visibly adjusted down by that position's value, and say which you're proceeding with. That's the second data question here; when the save still waits on the advisor's agreement, ask both in one message, the save line last (above). **However many positions come back `ambiguous` or `none`, that is one question, not one per position, and never a reason to skip the analytics.** List them together, each with its value, say what they total, and let the advisor answer for all of them at once — "leave them all out" is a complete answer — or name a proxy for any of them. Then run the analytics on the rest. Leaving positions out, with the total visibly adjusted and each one named in the Data Note, is how this pass handles them, not a partial or made-up book. **Being asked to pick the proxy is not the advisor naming one.** "You choose" authorizes a substitution without making it, and which security stands in for another is a selection judgment this skill doesn't make — the proxy sets the base every risk, scenario and concentration figure in Portfolio Review is read against. Put the choice back: what the security search returned, what each candidate is, and that excluding the position is an answer needing no pick. Pressed again, say that plainly and ask again. Until the advisor names a security or excludes it the position stays unresolved — a proxy you picked is not one they named, however the invitation was worded. Build the payload as the platform's own tool documents it — positions identified by 9-character CUSIP, weights as fractions summing to 1.0 against a per-account value, and weights or market values within an account but never both.
**If the write fails, say so — never reshape the holdings to make it succeed.** Analytics platforms constrain what they'll accept — concentration limits, minimum holdings, identifier formats — and a household's real positions may simply not fit. Never drop a position, merge holdings, substitute a proxy the advisor didn't name, or adjust a weight to get past a rejection. Report it in Portfolio Review with whatever the platform said about why, skip the analytics for this prep, and keep source 2's own performance and drift data, which never had these constraints. Don't restate the platform's limits here: it enforces them, it changes them, and a copy can only drift toward being wrong. If the platform rejects one account rather than the whole household, offer to leave that account out — with the total visibly adjusted, the same choice as an unresolved position — and analyze the rest. The advisor's call; never reshape the account itself.
**Run the analytics** once the saved portfolio exists: the platform's allocation, risk and scenario reads and its fund-health read. Read every result the way @${CLAUDE_PLUGIN_ROOT}/partials/rules/platform-analytics.md says, and fund health the way @${CLAUDE_PLUGIN_ROOT}/partials/rules/fund-health.md says. **Then benchmark the risk read to the closest model the allocation read returns**, which is what turns an allocation difference into its impact: the benchmarked call returns tracking error and the active contribution behind it.
**Fold, don't append.** These results become content *inside* Portfolio Review as three separately labelled, independently omittable pieces — **Volatility & Risk Drivers**, **Stress Test Impact** and **Allocation vs. Closest Model** — never a trailing section of their own. A read that didn't come back is omitted on its own without dragging the other two out. Fund-health ideas and risk flags fold into Talking Points as plain-English points.
## Assemble the Prep Doc
Use `templates/pre-meeting-template.md` in this skill's folder as the document skeleton. Fill every section; where data was unavailable, mark it "— pending [connector]" rather than leaving blanks silently — except a source that was searched and held nothing, which says so instead (Data Gathering above).
**Where a source said where its answer came from, the doc keeps it**, so the advisor, or anyone reviewing the doc, can check a figure against the system that gave it. A citation a read returned after a value stays beside that figure, or in a numbered note under the table that the figure points to, and is never moved to another figure or dropped. It always names the system it came from and keeps its citation id and page, so a reader can tell which system to check the figure against, and where: carry it in the form the read gave it, add the system's name where that form lacks it, and shorten nothing in it but the document's name. Each link a read returned under `sources:` goes whole beside that system's name in the Data Note's **Sources and as-of** line, whatever the read's status. That line is the doc's one place for the link: never repeated on a line that cites the system, the held-away alts line included, and never a list of links of its own. When the advisor asks to see the source behind a citation a read returned, list `${CLAUDE_PLUGIN_ROOT}/providers/`, and if it holds a folder named for that system, read every file in it and follow what it says about showing a cited source. That is the advisor's request, not a read, and adds nothing to the doc. With no such folder, or nothing in it about showing a source, say you can't open the source from here, and give the citation and the link as the doc carries them.
**No figure goes in bare, anywhere in the doc.** Pair each risk, scenario, drift, allocation or concentration figure with the household's own reference — its IPS band, its assigned model's risk profile, or a stated tolerance this run already pulled from meeting notes — and frame it strictly as within or outside that reference, never as good or bad. With none of the three on file, say "no stated reference on file" rather than inventing one or dropping the figure.
The doc opens with two unnumbered sections, the same pair /portfolio-rebalance-review's drift analysis opens with:
- **Executive Summary** — two or three sentences for the advisor to read before walking in: where the household stands and what the meeting is likely to turn on, each risk, drift, allocation or concentration figure framed within or outside the reference the Data Note names and never as good or bad, or "no stated reference on file" where there is none. No call on whether the portfolio suits the household. This is the same summary the chat reply opens with, not a second one written for chat.
- **Data Note** — provenance for everything below: the sources and their as-of dates, which saved portfolio the analytics ran on when they ran (and nothing about them when they didn't), the total the figures are computed on and the positions it excludes, and the reference named once in the form every figure that carries one reuses, the Executive Summary included. A fee-basis line only when a read carrying the analytics platform's own advisory-fee assumption is included.
Then the numbered sections, in order:
1. **Client Snapshot** — household, AUM, tenure, risk profile. A row whose value no source returned — tenure, last review date, risk profile — reads "— pending [connector]", never a figure or profile inferred from the holdings.
2. **Relationship Signals** — client concerns/sentiment, life events, upcoming personal dates (birthdays, anniversaries, milestones), proactive talking points — each signal cited to its source
3. **Since We Last Met** — open action items from last meeting with assignee and status (mark "unknown — pending CRM" unless the CRM's own task list confirms done; never infer "done" from a meeting-notes source that doesn't report completion), notable correspondence
4. **Portfolio Review** — performance vs. benchmark table, top contributors/detractors, allocation drift table, cash position. Returns, benchmark returns, targets and current weights are quoted as the source returned them, and the +/- and Drift cells are the difference of the two quoted figures beside them — nothing else in these tables is derived. The performance table's fee basis, net or gross, is the one the source stated, or reads "— basis not stated by [connector]". A figure the source didn't return reads "— pending [connector]", and so does any +/- or Drift cell that needs it: never a return you estimated, and never a blank that reads as zero. When source 7 ran, its output lands here too: a short **Current positioning** summary — geography within the sleeves, sector or sub-asset class within each — as the bridge from the allocation data to the analytics, then the three analytics reads folded in as separately labelled, independently omittable lines, each paired with the reference the Data Note names. A further read the advisor accepts afterwards is folded in here later by revising this file, and its absence is never a gap. This section stays a meeting summary: close it with one line offering to run /portfolio-rebalance-review for the full picture — a full drift analysis, rebalancing options, tax-aware trades, a rationale memo — rather than deepening this section inline. **If the portfolio trailed its benchmark, that goes first** — in these tables and at the top of Talking Points, with an honest explanation, not buried; advisors lose trust by dodging it.
5. **Planning Opportunities** — proactive items: rebalancing, tax-loss harvesting, Roth conversion, RMD/QCD planning, 529 funding, beneficiary review, insurance gaps. Check the household's key dates (Data Gathering, source 1) against the milestone triggers: turning 50 (catch-up contributions), 59½ (penalty-free withdrawals), 62-70 (Social Security), 65 (Medicare), the RMD age (the CRM's where it gives one, otherwise by birth year: 73 for 1951-1959, 75 for 1960 or later, and a member born before 1951 has already reached it) — a household member at or approaching one is an opportunity to list here. The look-back's figures (source 3) go here too, under their tax year, as the estate platform reported them.
6. **Proposed Agenda** — a 30-45 minute agenda with time boxes. A platform's flag (fund health, a risk flag) can be an agenda item, worded as something to discuss — never as a move on the holding (review, swap, trim, sell) — and marked †, with one line under the agenda: *† flagged by [platform] for discussion; not a recommendation*.
7. **Talking Points & Anticipated Questions** — 3-5 talking points in plain English (portfolio/market-facing — personal talking points live in Relationship Signals); firm-level Insights/trends when available; likely client questions (especially about underperformance or markets) with suggested framing. Underperformance leads this section when there is any (item 4). A platform's flag or fund idea goes in the same way as on the agenda — worded as something to discuss, never as a move on the holding (review, swap, trim, sell), marked †, with the same one line under the section.
8. **Action Items Draft** — pre-drafted next steps to confirm in the meeting. An owner or due date nobody has set reads "— confirm in meeting", never a name or date you assigned. A platform's flag goes in the same way as on the agenda — worded as a discussion, marked †, with the same one line under the table.
This skill never computes or invents a plan probability, funded status, or Monte Carlo result — MoneyGuide's own net worth, probability of success and goals go under Planning Opportunities as color, quoted exactly as they came back, never as a plan section of their own.
## Output
- **Write the doc in the advisor's voice, or in none.** Other people may read it without this conversation around it, and the advisor may screen-share parts — so Claude never appears in it as "I", "me" or "my". That holds for the whole file, talking points included, and for a doc that never reaches the client. The close below is a chat message rather than part of the document, so it isn't covered. Keep the language client-friendly throughout, for the same reason. If the doc or any excerpt will be shared with the client, recommend running those excerpts through **/compliance** first. The file carries client data, so it holds what this meeting needs and nothing more.
- **Summary-First Convention: open the reply with the file's Executive Summary** — the same one, not a second written for chat. Then stop. The tables stay in the file; don't walk the advisor through what they can read.
- **Then the directions and the export question, as one closing pair with nothing between them.** The directions are source 7's four further reads — thematic and factor exposure, concentration and flagged issues, a peer or model comparison, a wealth projection — named plainly so the advisor can take none, one or several; alongside them, the option to convert to .docx or .pdf (via the docx skill) or to make the doc longer or shorter. **Each further read is the platform's own read that returns it:** a peer or model comparison is against the closest-model match the allocation read returns, or a model the advisor names; a wealth projection is reported as percentile bands simulated from forward assumptions, labeled as a hypothetical range and never as a forecast or a plan result — the planning platform's probability of success, where there is one, stays its own figure. If the platform has no read that returns it, say so and leave it out. Never replace it with a read of your own. **Only offer what this run can actually deliver:** no analytics platform, or no saved portfolio, and the further reads aren't on the menu at all rather than offered and then withdrawn. Don't create .docx or .pdf unless asked — markdown is the first-pass deliverable and the heavy formats are materially slower.
- **Run only what they accept**, folding each result into the file already written — Portfolio Review's Further reads block, or Talking Points where it belongs there — never a second document and never a trailing section. They decline or don't answer → the doc stands as written, and nothing is marked pending.
- **Confirm what a converted document should cover** before generating it — the latest analysis only, or everything in this session. Ask once, and only where there's real ambiguity.
- **Say what you wrote, after the pair.** If this run created or renamed anything in a connected system — the saved portfolio in the analytics platform is the usual one, and often the only one — list it plainly, one short line per write, in the advisor's language rather than the tool's: *"Along the way, in order to generate these materials, I created the Henderson Family — Pre-Meeting 2026-09-25 portfolio for you in [system]."* Name what it's called and where it lives so the advisor can find it later; this plugin has no tool that deletes it. Say it unprompted, only for writes that actually happened, and never soften it into asking whether that was alright. It is a report, not a request. Where the analytics waited on the advisor's agreement to a save and it didn't come, nothing was saved, so say instead, in one line: *"[platform]'s risk and stress-test analytics aren't in this prep: they run only on a saved portfolio, and nothing was saved there without your OK."* That line is the whole of it: no invitation to reconsider, and no offer of anything that reads a saved portfolio.
## Out of Scope
- **No trade execution.** This skill never places, stages, or confirms a trade.
- **No sending to the client.** The prep doc is for the advisor; sharing it is the advisor's call, through their normal workflow.
- **No inventing plan probabilities or performance.** See "Assemble the Prep Doc" above.
- **No stand-in holdings.** No portfolio is saved to the analytics platform on positions the advisor didn't supply, and a proxy for a position that wouldn't resolve is never Claude's own pick — being asked to choose one is not the advisor naming it (Data Gathering, source 7).
- **No legal advice.** Estate/tax findings are flagged for the advisor (and the household's attorney/CPA where relevant) to evaluate, not acted on here.
## Important Notes
A summary; each rule is stated in the step it governs.
- **No question asks permission to gather, and nothing is saved without the advisor's agreement** — the questions before the document is written ask for facts only the advisor holds, and the advisor is asked to agree to two things only, source 7's save, asked once per conversation, in one line, before the first save and in the same message as any data question still open, and a report run on a report-only portfolio system (source 2); without agreement the document is written without the analytics (Data Gathering, source 7).
- **Report the writes in the close** — anything created or renamed in a connected system is named in plain English at the end, a report, not a second request (Output).
- **Claude never appears in the document in the first person** (Output).
- **Underperformance goes first, not buried** (Assemble, items 4 and 7).
- **Never a saved portfolio built on positions the advisor didn't supply** (Data Gathering, source 7).
- Never fabricate performance numbers, plan probabilities, or client details. If a source is unavailable and the advisor can't provide data, show the section as pending (Assemble the Prep Doc).
- Flag compliance-sensitive content: if the prep doc will be shared with the client, recommend running client-facing excerpts through **/compliance** (Output).
- Watch for milestone triggers in the data (Assemble, item 5).
- Treat all client data as confidential; only include what's needed for this meeting (Output).