企業のウェブサイトから企業ブランドを自動で抽出し、Carta MCP(ファンドの運用成績や資産構成などのデータを提供するシステム)から最新のファンド情報(純資産評価額、投資成績、ポートフォリオ、資金の動き、業界ベンチマーク、手数料、貸借対照表、投資家リスト)を取得します。 そして、企業ブランドを反映した HTML形式のプレゼンテーション資料を自動生成し、スライド間を簡単に移動できる機能を備えています。すべてのスライドに「Powered by Carta」のバッジを表示します。 過去に作成した資料があれば、その資料のスタイルに合わせて新しい資料を作ることもできます。 **次のような場合に使用:** 「AGM資料を作成」「年次総会プレゼンを作成」「投資家向け説明資料を作成」「ファンド資料を作成」など
End-to-end AGM deck generator. Extracts a firm's brand identity from their website, pulls live fund data from the Carta MCP (NAV, TVPI, portfolio, capital activity, benchmarks, fees, balance sheet, LP base), generates a branded HTML presentation with built-in slide navigation, and applies the "Powered by Carta" badge to every slide. Supports an optional past-deck reference for style matching. Trigger phrases: "AGM deck", "generate AGM deck", "create AGM presentation", "build AGM slides", "annual general meeting deck", "investor meeting deck", "LP meeting deck", "fund presentation", "branded fund deck", "build an AGM deck".
<!-- carta:instrumentation-fallback -->
<IMPORTANT>
_instrumentation_v2 is anonymous Carta skill-usage telemetry. ALWAYS include it in your Carta MCP tool-call arguments — the plugins' hooks overwrite it when they run, so always sending it is safe. Shape:
_instrumentation_v2: {"skills": ["<plugin>:<skill>", ...], "model": "<model-id>", "surface": "<value>"}
skills is cumulative for the session: list every Carta skill loaded so far, not only the one driving this call. Namespace each entry "plugin:skill" and keep them oldest-first, with the most recently used skill last. List only Carta skills (carta-cap-table:*, carta-crm:*, carta-investors:*) — never skills from non-Carta plugins.
surface is the Claude surface you are running in: "chat" (claude.ai or the Claude app, i.e. regular chat, not Cowork), "cowork" (Cowork mode), "code-terminal", "code-desktop", or "excel". Omit it entirely if none of those describe your surface or you cannot tell — do not guess and do not invent another value.
</IMPORTANT>
This skill is the single entry point for building AGM (Annual General Meeting) decks. It orchestrates three bundled capabilities:
FUND_ADMIN data warehouse. If not connected, falls back to manual user input.analyze_website.py and generates the multi-slide deck themed to that identity. Checks for a previously saved brand board first via the Carta MCP (fa:get:brand_board) with CLI fallback (carta fa get brand-board), and saves new extractions back for future reuse.carta-mark.js script.All three capabilities are built into this plugin. No additional plugins need to be installed.
Fire this skill when the user asks to:
carta-brand-extraction skill directlycarta-presentationpowered-by skill directlyClaude writes no slide HTML. All slide HTML is produced by compile_deck.py — a deterministic compiler that reads template.html and substitutes token values. Claude's only outputs are:
brands/<slug>.css — brand colors and fonts (written once via the Write tool)creative-values.json — 28 short text strings for headlines and narrative copyEverything else — every <section>, every chart config, every data table — is generated by the compiler from the canonical template. Editing slide HTML directly is always wrong.
| File | When to read | Why |
|---|---|---|
references/slide-spec.md |
Before Pass 1 | Understand which query feeds which slide and what each token expects |
references/template.html |
Only if debugging a specific slide | See the exact token positions — do not copy/edit HTML from it |
references/slide-templates/README.md |
Only if building brand CSS | Design system primitives and CSS variable reference |
| File | Role |
|---|---|
deck-stage.js |
Custom element sizing each <section> to 1920×1080 |
deck-nav.js |
Presentation navigation: ← → arrows, fullscreen, slide counter |
design-system/system.css |
Typography, chrome, layout, accent utilities |
design-system/tokens.css |
Brand → intent token mapping |
design-system/charts.js |
Declarative line / donut / hbar chart renderer |
design-system/carta-mark.js |
Auto-injects "Powered by Carta" on every slide |
Before doing any work, ensure you have these inputs. If any are missing, ask the user:
Reporting period (required)
AskUserQuestion with the question "What period should the AGM deck cover?" and these three computed options (derive quarter boundaries from today's date):
as_of_date passed to Agent A (last day of the chosen period, ISO format: YYYY-MM-DD). For full year, use December 31 of that year.as_of_date from their answer.Website URL (required)
https:// automatically.Fund selection (required)
Logo (optional input — mandatory handling rule below)
🚨 MANDATORY LOGO RULE — NO EXCEPTIONS:
firm_logo_url from Agent A if present (Priority 2), otherwise extract from website via Agent B (Priority 3).Past AGM deck (optional)
${CLAUDE_PLUGIN_ROOT}/skills/carta-agm-deck-builder/references/ as the style guideline. Read the design toolkit README (references/slide-templates/README.md) to understand all available primitives before composing slides.Do not proceed past Gate 0 until you have at least the reporting period and website URL.
Checkpoint: Call
mcp__<SERVER>__skill_checkpoint(skill_name="carta-investors:carta-agm-deck-builder", checkpoint_label="skill_started")before proceeding.
These two steps are independent and MUST run in parallel. Both run as sub-agents (they require MCP tool access and multi-step reasoning).
Tell the user: "Fetching fund data and extracting brand identity in parallel — this saves significant time."
Fire both in a single message (two Agent tool calls in the same response):
Dispatch a sub-agent with the firm UUID, fund selection, and Carta MCP tool access. The agent should return the assembled fund_data JSON.
🚨 CRITICAL — use the playbook. Before dispatching Agent A, read the compact playbook file with the Read tool:
${CLAUDE_PLUGIN_ROOT}/skills/carta-agm-deck-builder/references/agent-a-playbook.md
Pass the entire content of that file as Agent A's prompt (prepend the firm UUID, fund selection, and any user context). The playbook contains the exact MCP call sequence, saved-query gate, batch structure, default SQL, and efficiency rules — all in ~80 lines.
The playbook is the single source of truth for the data-fetch logic. Do NOT duplicate it in the agent prompt.
Dispatch a sub-agent with the website URL, firm UUID (if already known), and past deck path (if provided). The agent should return the brand_data JSON plus logo assets.
🚨 CRITICAL — use the playbook. Before dispatching Agent B, read the compact playbook file with the Read tool:
${CLAUDE_PLUGIN_ROOT}/skills/carta-agm-deck-builder/references/agent-b-playbook.md
Pass the entire content of that file as Agent B's prompt (prepend the website URL, firm UUID if known, and past deck path if provided). The playbook contains the exact MCP gate sequence, brand board check, website extraction fallback, save logic, and custom font handling.
The playbook is the single source of truth for the brand-extraction logic. Do NOT duplicate it in the agent prompt.
While Agents A and B run, also read the design toolkit README (${CLAUDE_PLUGIN_ROOT}/skills/carta-agm-deck-builder/references/slide-templates/README.md) and the example deck (references/template.html) so you have all design primitives and layout patterns loaded for Step 3 as soon as the agents return.
After both agents complete, merge their results and proceed to Step 3. If either agent fails, handle the failure independently (e.g., MCP fallback for fund data, manual theme for brand) — a failure in one does not block the other.
Checkpoint: Call
mcp__<SERVER>__skill_checkpoint(skill_name="carta-investors:carta-agm-deck-builder", checkpoint_label="deck_generation_started")before proceeding.
(Runs as Agent A in parallel with Step 2)
The full data-fetch logic — MCP connection, saved-query gate, 3-batch query execution, default SQL, and fallback — lives in the playbook at references/agent-a-playbook.md. That file is the single source of truth; do not duplicate its content here.
What Agent A returns: a fund_data JSON object with results from up to 13 query slots (fund metrics, NAV time series, benchmarks, portfolio investments, company info, etc.). Every field is optional — slides with missing data are automatically skipped in Step 3.
(Runs as Agent B in parallel with Step 1)
The full brand-extraction logic — saved brand board check (MCP gate), website extraction fallback, brand summary, save-after-extraction, and custom font handling — lives in the playbook at references/agent-b-playbook.md. That file is the single source of truth; do not duplicate its content here.
What Agent B returns: a brand_data JSON object with brand_palette (colors with hex/role/count), typography (fonts, optional font_faces for custom @font-face blocks), logos (candidates with URLs), and source ("saved" or "extracted").
After Agent B returns, map the brand palette into the generated brand CSS. All three roles must be present — never drop secondary or accent colors.
| Extraction role | CSS variable | Used for |
|---|---|---|
primary (highest-count) |
--brand-accent-1 |
.ds-dark slide backgrounds, primary emphasis, chart series 1 |
secondary (highest-count) |
--brand-accent-2 |
Secondary emphasis (.ds-on-accent-2), chart series 2 |
accent (highest-count) |
--brand-accent-3 |
Tertiary accent, chart series 3 |
Also map surface and ink colors from the extraction:
background / light-background → --brand-paper, --brand-paper-alttext / dark-text → --brand-ink, --brand-ink-2, --brand-ink-muteborder → --brand-ruleQuick self-check: if --brand-accent-1, --brand-accent-2, and --brand-accent-3 are all the same value, or any one is missing — stop and fix the brand CSS before proceeding. See references/brands/example.css for the complete variable list.
If brand_data.typography.font_faces is non-empty, generate @font-face blocks and inject them in a <style> tag in the deck's <head>, after the Google Fonts <link> and before the brand CSS <link>. Prefer woff2 sources. If font_faces is empty, skip this entirely.
Confirm all before running the compiler:
references/slide-spec.md — understand which query feeds each slide and what each token expects--brand-accent-1, --brand-accent-2, --brand-accent-3; --brand-on-accent is a light color (white or cream) when --brand-accent-1 is darkcp block in step 3b ran — design-system/, deck-stage.js, deck-nav.js exist without having been passed through the Write toolIf any box is unchecked, complete that step now before proceeding.
Walk the Slide Roster in order. For each slide apply exactly ONE of these two outcomes — no other outcomes exist:
🚨 CRITICAL — DON'T MIX COLUMNS ACROSS QUERIES. The Slide Roster designates a query per slide to prevent subtle data errors caused by column reuse:
🚨 CRITICAL — NO DATA FABRICATION. This is a hard stop, not a guideline:
🚨 ABSOLUTE RULE — EVERY ROSTER SLIDE IS A SEPARATE <section>. NO EXCEPTIONS.
Every slide listed in the Slide Roster MUST be rendered as its own independent <section> block. This is not a style guideline — it is a hard structural requirement:
<section>.The goal is a complete deck. A 28-slide deck with real data is always better than a 15-slide deck where half the slides were silently merged away.
Every slide that presents quantitative data MUST include at least one chart visualization. Text-only tables and bullet-point lists of numbers are never acceptable when a chart would work.
When composing chart markup:
"area": true, "dots": true, "highlightLast": true, "endLabel": "<current value>" in the first series. Benchmark series use "dashed": true."centerLabel" and "centerNumber"."valueLabel" on each row and "series" for color coding.Tables are acceptable ONLY alongside a chart or KPI strip for detail-heavy data — never as the sole visualization.
The output is an HTML file with sibling asset directories that the user opens in any browser. No Playwright, Chromium, or npm dependencies are needed. The HTML includes built-in slide navigation (deck-nav.js) with prev/next buttons, keyboard arrows, fullscreen mode, and viewport scaling.
(a) Write the brand CSS file. Create a <firm-slug>.css file following the structure in references/brands/example.css. Map all extracted brand colors to --brand-* variables as described in the "Brand color mapping" section above.
(b) Set up the working directory — MANDATORY: use bash cp, never the Write tool.
The design-system files (tokens.css, system.css, charts.js, carta-mark.js, deck-stage.js, deck-nav.js) are static. They must be copied with a single bash command. Do NOT read them into context and re-write them — that wastes ~3 minutes and ~10k output tokens for zero benefit.
Run this bash block exactly as written:
OUTPUT_DIR="/tmp/agm-deck"
REFERENCES_DIR="${CLAUDE_PLUGIN_ROOT}/skills/carta-agm-deck-builder/references"
mkdir -p "$OUTPUT_DIR/design-system" "$OUTPUT_DIR/brands" "$OUTPUT_DIR/assets"
cp -r "$REFERENCES_DIR/design-system/." "$OUTPUT_DIR/design-system/"
cp "$REFERENCES_DIR/slide-templates/deck-stage.js" "$OUTPUT_DIR/"
cp "$REFERENCES_DIR/slide-templates/deck-nav.js" "$OUTPUT_DIR/"
cp "$REFERENCES_DIR/slide-templates/deck-shell.html" "$OUTPUT_DIR/"
Logo — priority chain (resolve before writing brand CSS):
cp it verbatim, use it. Stop here.firm_logo_url from Agent A → run process-logo. Stop here.Priority 1 — user-provided file:
PROVIDED_LOGO_PATH="<absolute path the user gave>"
LOGO_FILENAME=$(basename "$PROVIDED_LOGO_PATH")
cp "$PROVIDED_LOGO_PATH" "$OUTPUT_DIR/assets/$LOGO_FILENAME"
echo "Logo: $OUTPUT_DIR/assets/$LOGO_FILENAME"
Priority 2 — firm_logo_url from Agent A (downloads + removes background):
uv run "${CLAUDE_PLUGIN_ROOT}/skills/carta-agm-deck-builder/scripts/compile_deck.py" process-logo \
--url "<firm_logo_url from Agent A result>" \
--output "$OUTPUT_DIR/assets/firm-logo.png"
LOGO_FILENAME="firm-logo.png"
First run downloads the rembg model (~170MB, cached after that). SVGs skip background removal automatically.
Set both --brand-logo-light and --brand-logo-dark in the brand CSS to url("../assets/$LOGO_FILENAME").
After the cp commands succeed, the only files you write from scratch are:
$OUTPUT_DIR/brands/<firm-slug>.css — generated from Agent B's brand extraction$OUTPUT_DIR/<firm-slug>-agm-<year>.html — the composed deckDo NOT write generated deck files into the plugin's references/ directory.
(c) Compose the HTML deck — deterministic compiler + 28 creative tokens.
This is a two-pass process. The compile_deck.py script handles 190 tokens mechanically; you only need to supply 28 short creative text strings.
Pass 1 — Run the compiler (deterministic substitution):
uv run "${CLAUDE_PLUGIN_ROOT}/skills/carta-agm-deck-builder/scripts/compile_deck.py" compile \
--queries-dir /tmp/agm-queries \
--template "${CLAUDE_PLUGIN_ROOT}/skills/carta-agm-deck-builder/references/template.html" \
--brand-slug "<firm-slug>" \
--firm-name "<Firm Name>" \
--period-label "<Full Year 2025>" \
--as-of-date <YYYY-MM-DD> \
--output "$OUTPUT_DIR/<firm-slug>-agm-<year>.html" \
--creative-prompt "$OUTPUT_DIR/creative-tokens.md"
Pass 2 — Fill the creative tokens:
Read creative-tokens.md (it is very short — one line per field with data context). Write creative-values.json:
{
"COVER_HERO_LINE1": "Investing in the future of",
"COVER_HERO_EMPHASIS": "financial services.",
"COVER_STANDFIRST": "A full-year review of ...",
...all creative fields...
}
Then apply:
uv run "${CLAUDE_PLUGIN_ROOT}/skills/carta-agm-deck-builder/scripts/compile_deck.py" apply \
--partial "$OUTPUT_DIR/<firm-slug>-agm-<year>.html" \
--creative-values "$OUTPUT_DIR/creative-values.json" \
--output "$OUTPUT_DIR/<firm-slug>-agm-<year>.html"
Verify:
grep -c 'data-screen-label' "$OUTPUT_DIR/<firm-slug>-agm-<year>.html"
# Should equal the number of active slides
Checkpoint: Call
mcp__<SERVER>__skill_checkpoint(skill_name="carta-investors:carta-agm-deck-builder", checkpoint_label="deck_generation_finished")before proceeding.
The compiler's apply command overwrites the partial file in place with the final HTML. If the script reports remaining {{ tokens, use the Edit tool to patch them before opening.
Navigation is automatic. The deck-nav.js script (loaded via deck-shell.html) provides:
No additional rendering step is needed. The .html file is the final deliverable.
Carta badge: carta-mark.js (loaded via deck-shell.html) auto-injects a "Powered by Carta" footer on every <section>. The SVG uses fill="currentColor", so it inherits correct contrast automatically — no manual placement needed.
decl-shell replacement: deck-shell.html' **Overflow guard**: slides use overflow: hidden(set bydeck-stage.js), so content that doesn't fit is clipped silently. Design each slide to fit: use .ds-body--smfor dense tables, paginate long tables across slides, keep chartheight` within the available vertical space, and use compact legend layouts for donuts with many items.
Open the HTML file for the user:
open <output-file>
Clean up temporary files — run immediately after opening:
rm -rf /tmp/agm-queries/
rm -f "$BLOB_PATH"
rm -f "$OUTPUT_DIR/creative-tokens.md" "$OUTPUT_DIR/creative-values.json"
echo "Done."
Checkpoint: Call
mcp__<SERVER>__skill_checkpoint(skill_name="carta-investors:carta-agm-deck-builder", checkpoint_label="skill_finished")before proceeding.
Confirm delivery:
design-system/, brands/, and assets/ directories — it references them for styling and charts."🚨 CRITICAL — Post-generation audit. After every deck build, output the following three sections verbatim. This is non-negotiable and must appear even if all slides were included:
Before rendering these tables, call call_tool({"name": "fa__list__saved_queries", "arguments": {}}) and build a lookup map: for each entry whose collection or subcollection_name matches "AGM Deck", record name → _links.web_url. Skip this prefetch silently if the Carta MCP was not connected. Do NOT construct, guess, or fabricate URLs.
Slides included (list each slide by number and title):
| # | Slide | Data source |
|---|---|---|
(one row per rendered slide; if a saved query was found for this slide's data source, hyperlink the data source name to its _links.web_url; otherwise render it as plain text) |
Slides skipped (list each skipped slide and the exact reason):
| # | Slide | Reason skipped |
|---|---|---|
| (one row per skipped slide, or "None — all slides included"; hyperlink the data source name the same way when a match exists) |
Data provenance confirmation:
All figures in this deck come directly from Carta MCP query results or your explicit input. No data was invented, estimated, extrapolated, or inferred. If a slide required data that was not returned by Carta, it was skipped (see table above).
MANDATORY: If you cannot honestly make that statement — if any number was estimated or extrapolated — replace it with an explicit disclosure of exactly which values were fabricated and why, and offer to regenerate those slides once the user provides real data.
Slides are produced in this order. All slides with available data are included.
| # | Slide | Data Source(s) | Required Visualization |
|---|---|---|---|
| 1 | Cover — fund name, firm name, as-of date, confidential | Fund Performance Summary |
— (hero layout, .ds-dark, .ds-display headline) |
| 2 | Agenda — auto-generated from active slide titles | Auto | — (2-column list with .ds-rule dividers) |
| 3 | Fund Performance Summary — hero KPIs + fund metrics | Fund Performance Summary |
KPI strip (4-col .ds-num with .ds-kpi-highlight) + line chart (TVPI trajectory, area: true, highlightLast: true) |
| 4 | Fund IRR vs. Benchmarks — fund IRR vs. vintage/size cohort percentiles | Fund IRR vs. Benchmarks |
line chart — fund solid (area: true), cohort p25/p50/p75 dashed: true |
| 5 | NAV Trend — monthly NAV over time | NAV Trend |
line chart with area: true, dots: true, highlightLast: true, endLabel |
| 6 | Multi-Fund Performance — all firm funds side-by-side | Fund Performance Summary |
hbar chart (TVPI or NAV by fund) + table with KPI strip header |
| 7 | Capital Deployment / Dry Powder — % deployed, pace vs. cohort | Capital Deployment / Dry Powder |
line chart (deployment pace vs. cohort, solid + dashed) + KPI strip |
| 10 | LP Geography — LP locations by state/country | LP Geography |
donut chart (top regions by commitment) + legend block |
| 11 | Portfolio Overview — NAV % by company + investments by vintage | Portfolio Overview |
donut chart (NAV composition by sector/thesis) + .ds-card legend |
| 11b | Investment Detail & Performance — SOI-style table | Investment Detail & Performance |
hbar chart (top 5–8 investments by MOIC or FMV) + table with KPI strip |
| 12 | Portfolio Company Logo Grid — active investments as cards | Portfolio Company Logo Grid |
Logo grid using .ds-card--flat cards |
| 12b | Logo Leaderboard — top N companies ranked visually | Logo Leaderboard |
hbar chart with company names, value as MOIC or total value |
| 13 | Asset Type Breakdown — Preferred Equity / SAFE / Note composition | Asset Type Breakdown |
donut chart with centerLabel + centerNumber + legend |
| 14 | Investment Performance Buckets — capital bucketed 0x / 1x / 1–3x / 3–10x / 10x+ | Investment Performance Buckets |
hbar chart — one row per bucket, valueLabel showing count and $amount |
| 15 | Top Performing Investments — ranked by MOIC | Top Performing Investments |
hbar chart (MOIC ranking) + supporting list with .ds-accent-border |
| 16 | Annual Markups / Markdowns — unrealized gain/loss YoY | Annual Markups / Markdowns |
hbar chart (gain/loss per company, multi-series for markup vs markdown) + KPI strip |
| 17 | Deal-Level IRR — cost vs FMV + IRR | Deal-Level IRR |
hbar chart (invested vs. FMV per deal, multi-series) + table |
| 18 | Geographic Portfolio Mix — US vs. international | Geographic Portfolio Mix |
donut chart (US vs. international) + legend |
| 19 | SPV Performance — per-SPV invested, contributions, MOIC | SPV Performance Table |
hbar chart (MOIC by SPV) + KPI strip header |
| 20 | Portfolio KPI Highlights — ARR, MRR, headcount, retention | Portfolio KPI Highlights |
line chart (trend for top metric) + KPI strip + table |
| 21 | Profitability Milestone Tracker — profitability by quarter | Profitability Milestone Tracker |
hbar chart (companies by profitability status) + KPI strip |
| 22 | Financing Round History — raises, pre/post-money valuations | Financing Round History |
line chart (cumulative capital raised over time) + KPI strip (total raised, avg pre-money) + table |
| 25 | Portfolio Company Deep Dives — per-company cards | Portfolio Company Deep Dives |
2×2 .ds-card grid with rotating accent borders |
| 27 | Fund Expenses Breakdown — fees, legal, audit, admin | Fund Expenses Breakdown |
donut chart (expense composition) or hbar chart + KPI strip |
| 28 | Market Outlook & Themes — 3 thematic focus areas | User input | 3-col .ds-card grid on .ds-alt surface with accent borders |
| 29 | Closing / Contact — firm contact info, IR email | User input | — (hero layout, .ds-dark, .ds-display headline) |
Every slide in this roster must appear in the deck unless its data is completely absent. The only valid skip reason is zero usable data — not layout preference, not data overlap with another slide, not perceived redundancy. Skip = no data. Present = render it.
Note on slide numbering: The roster follows the numbering above (gaps like 8–9, 24 are intentional — reserved for future slides). Slides 11b and 12b are sub-slides that appear after their parent — they are always separate <section> blocks, never merged into 11 or 12.
Run these checks before delivering. Every item is a command or a visual confirm — not a memory check.
<div class="ds-chrome-logo"> is present in every <section>.ds-dark slides use data-variant="dark" — verify at least one dark slide shows the light/cream logo, not the dark markcp'd verbatim to $OUTPUT_DIR/assets/; no regeneration, no website download{{ tokens remain: grep -c '{{' "$OUTPUT_FILE" → must be 0grep -c 'data-screen-label' "$OUTPUT_FILE" matches expected active slides.ds-dark slide (accent-1 bg), one .ds-kpi-highlight--2 (accent-2), one chart series 3 or .ds-pill--3 (accent-3)--brand-on-accent is a light color — text on .ds-dark slides must be readable; check brands/<slug>.css<section> slides are wrapped inside <deck-stage>…</deck-stage> — grep -c '<deck-stage>' "$OUTPUT_FILE" must be 1deck-stage.js and deck-nav.js are loaded in <head> — without them slides render as a vertical stack with no navigationcarta-mark.js)design-system/, brands/, assets/, deck-stage.js, deck-nav.js alongside the HTML file❌ Writing slide HTML directly — Claude never writes <section> blocks. The compiler generates all slide HTML from template.html. Using Write or Edit to produce slide HTML bypasses the template entirely and is the primary cause of structural variation between decks. If the compiler fails, fix the compiler — do not hand-write slides.
❌ Writing agent prompts inline instead of using the playbooks — do not write data-fetch or brand-extraction instructions from memory or paraphrase the logic. Always Read the playbook files (references/agent-a-playbook.md, references/agent-b-playbook.md) and pass their content as the agent prompts. The playbooks are the single source of truth for each agent's logic.
❌ Using the old multi-call data-fetch pattern — do not fall back to fa:list:saved_queries → fa:get:saved_query → dwh:execute:queries unless fa:get:agm_deck_data explicitly fails. The new command fetches, executes, and returns all ~21 AGM queries in a single call with server-side parallelism. The old pattern is retained only as a documented fallback in the playbook.
❌ Silently substituting a different query's columns — when the designated query is available and non-empty, always use its columns as the primary data source. Do not quietly swap in a similarly-named column from another query. A deal_irr decimal from Top Performing Investments is not the same value as deal_irr_pct from Deal-Level IRR — they differ in scale and context. Complementary data from other queries is welcome on any slide, but it should enrich, not replace, the designated query's output.
❌ Using cat >> bash appends to write slide batches — appended content lands outside </deck-stage> because the Write call in Step 1 already closed the file with </deck-stage></body></html>. The result: slides 01–03 display correctly, every slide after that is invisible (outside the custom element). Always write the complete deck in one Write call. If the output is truncated, use the Edit tool to insert missing slides before </deck-stage> — never append with bash.
❌ Ignoring a provided logo — if the user gave you a logo file, copy it with cp and use it. Do NOT fetch, download, redraw, or generate an SVG version. Do NOT use any other image.
❌ Generating slides without reading the canonical template first — read references/template.html before writing any HTML. The template defines the exact <section> structure, grid layout, class names, and {{TOKEN}} positions for every slide in the Roster. Skipping it means inventing layouts that will differ deck to deck — the root cause of the variation problem this template solves.
❌ Deviating from the template structure — the template's grid configs, element order, and class names are not suggestions. Do not move elements, change column counts, swap chart types, or add extra wrappers. Replace {{TOKEN}} values only. If a token has no data, skip the entire slide — do not fill it with placeholder text or restructure the layout.
❌ Monochrome slides — if only one brand color is visible, you're not using the accent utilities. Every deck must feature all three --brand-accent-* values through .ds-dark slides, .ds-card borders, .ds-kpi-highlight, .ds-accent-bar, .ds-pill, chart series, and <em> text. A monochrome deck is a failed deck.
❌ Tables without charts — a slide full of numbers but no chart is a failed slide. If a slide has quantitative data, it gets a line/donut/hbar chart. Tables are only acceptable alongside a chart or KPI strip.
❌ Inventing or extrapolating data — if a query returned no results, the slide is skipped. Do NOT fill it with estimated values, trend lines constructed from partial data, plausible sector splits, representative company names, or any other fabricated content. This is the most critical failure mode: invented numbers in an LP presentation can cause legal and reputational harm. When in doubt, skip the slide.
❌ Merging two roster slides into one — if the roster lists Slide 13 and Slide 11 as separate slides, they must be rendered as two separate <section> blocks even if their data source overlaps. Never collapse one slide's content into another slide's layout. A merged slide is a skipped slide for both entries in the post-generation audit.
❌ Dropping slides with empty data silently — always record every skipped slide (name + reason) so you can report them to the user in the Step 4 post-generation audit. Silent omissions undermine trust.
❌ Using the Write tool for design-system files — tokens.css, system.css, charts.js, carta-mark.js, deck-stage.js, deck-nav.js, and deck-shell.html are static files. Reading them into context and re-writing them costs ~3 minutes and ~10k output tokens for zero benefit (the model strips comments and truncates sections, producing a degraded copy). The only correct path is the bash cp block in step 3b. The Write tool is only valid for <firm-slug>.css and <firm-slug>-agm-<year>.html — the two files that are genuinely generated.
❌ Inlining all CSS in <style> without the design-system folder — inline styles break the token inheritance chain and make brand theming impossible. Always set up the working directory with design-system/, brands/, and assets/ as relative paths.
❌ Forgetting deck-nav.js — without the navigation script, the HTML file renders all slides stacked vertically with no way to navigate. Always copy deck-nav.js into the working directory alongside deck-stage.js.
carta-mark.js is loaded in deck-shell.html. It auto-injects the footer on every <section>.deck-nav.js is copied to the working directory root (same level as the HTML file).design-system/, brands/, assets/) via relative paths. The entire output folder must be moved together.原文・著作権は Anthropic および各プラグイン作者に帰属します。日本語訳は Claude API による自動翻訳です。