Cartaの顧客管理システムに蓄積された最近の案件情報を、機関ごとに重要なデータ項目を自動判別しながら、投資家向けのレポートに集計するスキルです。 次のような場合に使用: ユーザーが「案件フロー分析」「案件フローの分析」「過去12ヶ月間に追加された案件のレビュー」「誰が最も多くの案件を紹介したか」「セクター別の案件内訳」「案件はどこから来ているのか」といった発言をしたり、「/deal-flow-analytics」と入力したりした場合。 デフォルトでは過去12ヶ月のデータを対象としますが、ユーザーが指定した任意の期間や分析軸にも対応します。個別の案件リストではなく、各分析軸ごとの件数と集中度に関する重要なポイントを返します。個別案件の検索については、deal-searchスキルをご利用ください。
Aggregates recent deal flow in the Carta CRM into a dealmaker-facing report, auto-discovering which fields matter for this tenant's schema. Use this skill when the user says things like "deal flow analytics", "analyze our deal flow", "review deals added in the last 12 months", "who introduced most of our deals", "breakdown of deals by sector", "where is our deal flow coming from", or "/deal-flow-analytics". Defaults to a trailing-12-month window but accepts any date range or dimension the user specifies. Returns counts and concentration callouts per dimension, not a list of individual deals — use search-deals for that.
<!-- carta:plugin-version --> <carta-plugin>carta-crm:1.14.2</carta-plugin>
すべてのテナント(利用者単位の独立した環境)がカスタムディール項目を設定するため、レポート対象として有用な軸は組織ごとに異なります。固定リストを前提とせず、実行時に軸を検出したうえで crm:aggregate_deals で集計してください。crm:search_deals でディールを手作業で集計してはいけません。
aggregate_deals は一度に1つの項目でのグループ化に対応しています。複数の軸をカバーするには、複数の group_by 値を1回の呼び出しに入れるのではなく、複数回の呼び出しを行ってください。
crm_call_tool({ "name": "crm:get_deal_fields", "arguments": {} })
すべての項目をその type だけで分類します。プローブ処理は不要です。
グループ化可能 (dropdown、multiselect、boolean、または stage、tags、people.*、dealLead のような標準 set 項目)
— 値の範囲は項目の options リストで制限されているため、直接 aggregate_deals で集計しても常に安全です。
連続値 (number、input、textarea、datepicker、または company や contacts-list のような関連参照)
— 値が無制限です。これらでグループ化してはいけません。このプラグインのテストテナントでは、EBITDA、ARR、Team_size などの項目から 100 以上の異なるグループが返され、都市レベルの位置情報クエリを破損させるレスポンスサイズ制限に近づきました。
自由形式の標準項目 (company.company_location、company.company_industry、またはその他のタイプが text の標準項目)
— 連続値と同じく無制限のリスクがありますが、常に関連性があるため、入力率(記入率)で除外されません。これでグループ化してから、クライアント側で生の値をロールアップ(例:都市 → 国)してから表示してください。生の内訳を表示してはいけません。これらを無条件の「常に含める」リストに入れないでください。他のすべてと同じ方法でタイプによって分類してください。
stage(段階)と added_date(追加日)は常に固定コアとして保持してください。どちらも制限された標準項目で、テナントに関係なく直接グループ化しても安全です。
グループ化可能項目: ステップ3の aggregate_deals 呼び出しはすでに入力率を返します。totalCount からnull/no-_id グループを差し引いた値です。追加の呼び出しは不要です。
連続値項目: 項目ごとに aggregate_deals を呼び出さないでください。代わりに1つの共有サンプルを取得します。
crm_call_tool({ "name": "crm:search_deals", "arguments": { "limit": 30 } })
連続値項目ごとに、入力率をサンプルされたディール全体に対して fields.<fieldId> が存在し null でない割合として計算します。1回の呼び出しですべての連続値項目をカバーします。基数(値の種類の数)に関わらずペイロードは有界です。
入力率が15%未満の項目は除外してください。 15~25%の間に該当する項目(基準値を超えているが、サンプルで確実に推定できない曖昧な範囲)については、サンプルを信頼しないでください。search_deals はデフォルトで最近アクティブなディールを優先するため、めったに使われない項目の真の入力率を大幅に過大評価する可能性があります。このテストテナントで確認されました:20件のサンプルが、実際の組織全体の入力率が3%だったのに、ある項目を25%で埋まっていると推定しました。該当する項目については、その項目だけに対する単一の aggregate_deals 呼び出しで再確認し、サンプル推定ではなく正確な totalCount を使用してください。
除外された項目を「除外 — カバレッジ不足」という短い行に記載してください。黙って削除してはいけません。
stage、ステップ2を通過したすべてのカスタムグループ化可能項目、および全自由形式標準項目(ロールアップ付き)について、日付ウィンドウでフィルタリングして集計します。
crm_call_tool({
"name": "crm:aggregate_deals",
"arguments": {
group_by: ["<field_id>"],
filters: [
{ field_id: "added_date", operator: "between", value: ["<start> 00:00:00", "<end> 23:59:59"] }
]
}
})
各グループ内の dealInfo キーは無視してください。これは静的な組織デフォルトサンプルで、集計の一部ではありません。入力率チェックに通った連続値項目については、入力率のみを報告してください(例:「売上:95%入力済み」)。ユーザーが明示的に掘り下げるよう要求しない限り、完全な分布を試みないでください。
自由形式の標準項目については、グループ化された生の値をクライアント側でより粗いレベルにロールアップしてから表示してください(例:company.company_location の都市値 → 国)。上位5~8個のロールアップされた値を表示し、残りを「その他」に集約してください。
異なる2つの _id が同じ名前に解決されることがあります(連絡先の重複)。それらのカウントを合算し、人物の総数の過小報告ではなく重複にフラグを付けてください。未解決の連絡先/ユーザーIDについては、上位数個に対してのみ crm:fetch_contact_by_id を呼び出してください。
ユーザーが特定の軸を要求した場合、その軸だけを集計してください。完全な検出パスをスキップしてください。
${CLAUDE_PLUGIN_ROOT}/skills/deal-flow-analytics/assets/dashboard-template.html のHTMLダッシュボードテンプレートを使用してレポートをレンダリングしてください。手作業でマークダウンテーブルを構築したり、相対パスでテンプレートを参照したりしないでください(ユーザーの現在のディレクトリから解決され、プラグインディレクトリからではありません)。テンプレートを新しいファイルにコピーし、その <script> の下部にある DATA オブジェクトのみを編集してください。
dateRange — 日付範囲ラベル。例:「2025年7月 – 2026年7月 · 167件のディール」
headline — 最も注目すべき単一の知見を1文で(集中度、低い入力率、または死亡段階に向かって歪んだパイプラインヘルスなど)
excluded — ステップ2で削除された項目ラベル。各入力率付き
CRMフィールド値は信頼できません。テナントのドロップダウンオプション、タグ、または会社名には任意のテキストが含まれる可能性があります。DATA オブジェクトに文字列を書き込む場合、リテラル部分文字列 </script が含まれていれば、/ の前に \ を挿入してください(<\/script)。周囲の <script> ブロックを早期に閉じることができなくなります。テンプレート自身のレンダリングコードはすでにすべての値をHTMLエスケープしています。これは、あなたが書き込むファイルを保護するだけです。
fields — 次元ごとに1つのエントリ:{ label, total, filled, values }。値は降順でランク付けされ、上位5~8エントリ + ロングテール がある場合は "Other" エントリ(大文字小文字を区別しないでマッチし、シリーズカラーではなく薄いカラーでレンダリング)テンプレートはヘッダーのすぐ下にある次元カードをレンダリングし、headline と excluded をページ下部のフッターに表示します。叙述的な情報と注意点はデータの前ではなく、後に来ます。この順序を変更しないでください。
CSSやレンダリング関数、またはカテゴリ色トークンに手を加えないでください。これらは検証済み(dataviz スキルを参照)で、このスキルが作成するすべてのレポート全体で共有されているため、実行から実行へと結果が一貫して見えます。ユーザーにファイルパスを伝えて、自分で開けるようにしてください。このスキルの allowed-tools に Bash がないため、ブラウザを直接起動することができません。
任意の次元をCRMレポートとして保存することを提案してください。
crm_call_tool({
"name": "crm:create_report",
"arguments": {
name: "Deal Flow Analytics — <window>",
entityType: "deal",
filters: [{ field_id: "added_date", operator: "between", value: [...] }],
groupBy: ["<dimension field_id>"]
}
})
保存されたレポートごとに1つの groupBy (aggregate_deals と同じ1項目制約)。ユーザーが保持したい次元ごとに1つを提案し、各 url をインラインで表示してください。
<!-- carta:plugin-version --> <carta-plugin>carta-crm:1.14.5</carta-plugin>
Every tenant configures its own custom deal fields, so the dimensions worth
reporting on differ per org. Discover them at runtime instead of assuming a
fixed list, then aggregate with crm:aggregate_deals — never tally deals by
hand from crm:search_deals.
aggregate_deals groups by one field at a time. Cover multiple
dimensions with multiple calls, not one call with multiple group_by values.
crm_call_tool({ "name": "crm:get_deal_fields", "arguments": {} })
Classify every field using its type alone — no probing needed:
dropdown, multiselect, boolean, or a standard set
field like stage, tags, people.*, dealLead) — the value space is
bounded by the field's options list, so it's always safe to
aggregate_deals on directly.number, input, textarea, datepicker, or a
relational reference like company/contacts-list) — unbounded values.
Never group_by these — on this plugin's test tenant, fields like
EBITDA, ARR, and Team_size returned 100+ distinct groups each and
nearly hit the response size limit that broke a city-level location query.company.company_location,
company.company_industry, or any other standard field of type text) —
same unbounded risk as Continuous, but always relevant, so they don't get
excluded by fill rate. Group by them, then roll the raw values up
client-side (e.g. city → country) before presenting — never show the raw
breakdown. Do not put these in an unconditional "always include" list;
classify them by type like everything else.Always keep stage and added_date as the fixed core — both are bounded,
standard fields safe to group on directly regardless of tenant.
Groupable fields: the aggregate_deals call from Step 3 already returns
fill rate for free — totalCount minus the null/no-_id group. No extra
call needed.
Continuous fields: don't call aggregate_deals per field. Pull one
shared sample instead:
crm_call_tool({ "name": "crm:search_deals", "arguments": { "limit": 30 } })
For each continuous field, compute fill rate as the share of sampled deals
whose fields.<fieldId> is present and non-null. One call covers every
continuous field — bounded payload regardless of cardinality.
Exclude any field below 15% fill rate. For fields landing between 15–25%
(the ambiguous band — above the cutoff but not reliably estimated by sample),
don't trust the sample — search_deals defaults to
recently-active deals first, which can massively overstate a rarely-used
field's true fill rate. Confirmed on this test tenant: a 20-deal sample
estimated one field at 25% filled when the true org-wide rate was 3%. For any
field in that band, re-check with a single aggregate_deals call on just
that field and use its exact totalCount instead of the sample estimate.
List excluded fields in a short "excluded — low coverage" line rather than dropping them silently.
For stage, every groupable custom field that passed Step 2, and every
free-text standard field (with rollup), filtered to the date window:
crm_call_tool({
"name": "crm:aggregate_deals",
"arguments": {
group_by: ["<field_id>"],
filters: [
{ field_id: "added_date", operator: "between", value: ["<start> 00:00:00", "<end> 23:59:59"] }
]
}
})
Ignore the dealInfo key in each group — it's a static org-default sample,
not part of the aggregation. For continuous fields that passed the fill-rate
check, report fill rate only (e.g. "Revenue: 95% filled") — don't attempt a
full distribution unless the user explicitly asks to drill into one.
For free-text standard fields, roll the raw grouped values up to a coarser
level client-side before presenting (e.g. company.company_location city
values → country) — show the top 5–8 rolled-up values and collapse the rest
into "Other".
Two different _ids can resolve to the same name (duplicate contacts) — combine
their counts and flag the duplicate rather than under-reporting the person's total.
For unresolved contact/user IDs, call crm:fetch_contact_by_id on the top few only.
If the user asks for one specific dimension, only aggregate that one — skip the full discovery pass.
Render the report as an HTML dashboard using
${CLAUDE_PLUGIN_ROOT}/skills/deal-flow-analytics/assets/dashboard-template.html
— don't hand-build markdown tables, and don't reference the template by a bare
relative path (it resolves from the user's cwd, not the plugin directory).
Copy the template to a new file, then edit only the DATA object at the
bottom of its <script>:
dateRange — the date range label, e.g. "Jul 2025 – Jul 2026 · 167 deals".headline — the single most notable finding, one sentence (a
concentration, a low fill rate, or a pipeline health issue like a stage
distribution skewed toward Dead).excluded — field labels dropped in Step 2, each with its fill rate.CRM field values are untrusted — a tenant's dropdown option, tag, or company
name could contain arbitrary text. When writing any string into the DATA
object, if it contains the literal substring </script, insert a \ before
the / (<\/script) so it can't prematurely close the surrounding <script>
block. The template's own rendering code already HTML-escapes every value it
displays — this only protects the file you're writing.
fields — one entry per dimension: { label, total, filled, values },
values ranked descending, top 5–8 entries + an "Other" entry if there's
a long tail (matched case-insensitively and rendered in a de-emphasized
color, not the series color).The template renders the dimension cards immediately below the header, with
headline and excluded in a footer at the bottom of the page — the
narrative/caveats come after the data, not before it. Don't reorder this.
Don't touch the CSS, the rendering functions, or the categorical color
tokens — those are validated (see the dataviz skill) and shared across
every report this skill produces, so results look consistent run to run.
Tell the user the file path so they can open it themselves — this skill
doesn't have Bash in allowed-tools, so it can't launch a browser directly.
Offer to save any dimension as a CRM report:
crm_call_tool({
"name": "crm:create_report",
"arguments": {
name: "Deal Flow Analytics — <window>",
entityType: "deal",
filters: [{ field_id: "added_date", operator: "between", value: [...] }],
groupBy: ["<dimension field_id>"]
}
})
One groupBy per saved report (same one-field constraint as aggregate_deals)
— offer one per dimension the user wants to keep, and surface each url inline.
原文・著作権は Anthropic および各プラグイン作者に帰属します。日本語訳は Claude API による自動翻訳です。