Carta CRM(顧客管理システム)に保存されている最近の取引情報を集計し、取引関係者向けのレポートに自動変換するスキルです。テナント(利用組織)のデータスキーマ(情報構造)から重要なフィールド(項目)を自動判別します。 **次のような場合に使用:** 「取引流動性の分析」「取引流動を分析してほしい」「過去12カ月間に追加された取引を確認したい」「どの人物が最も多くの取引を紹介しているか」「セクター別の取引内訳」「取引がどこから来ているのか」「/deal-flow-analytics」といった依頼があったとき **機能:** - デフォルトでは過去12カ月間を対象としますが、ユーザーが指定した期間や分析軸に対応します - 個別の取引リストではなく、各軸ごとの件数と集中度(特定分野への偏り)を結果として返します - 個別の取引情報が必要な場合は、search-deals(取引検索スキル)を使用してください
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:instrumentation-fallback --> <重要>
_instrumentation_v2 は、Carta スキルの使用状況を集計する匿名のテレメトリ(利用データ)です。Carta MCP ツール呼び出しの引数に必ず含めてください。プラグインのフックが実行時に上書きするため、常に送信しても安全です。形式は以下の通り:
_instrumentation_v2: {"skills": ["<plugin>:<skill>", ...], "model": "<model-id>", "surface": "<value>"}
skills はセッション全体で累積されます。この呼び出しを駆動しているスキルだけでなく、これまでに読み込まれたすべての Carta スキルをリストアップしてください。各エントリを "plugin:skill" の形式で名前空間を付け、古い順に並べ、最後に最近使用したスキルが来るようにします。Carta スキル(carta-cap-table:*、carta-crm:*、carta-investors:*)のみをリストアップ。Carta 以外のプラグインのスキルは含めないでください。surface は実行している Claude の環境を指します。"chat"(claude.ai または Claude アプリの通常のチャット、Cowork ではない)、"cowork"(Cowork モード)、"code-terminal"、"code-desktop"、"excel" のいずれかです。これらに当てはまらない場合や判定できない場合は、この項目全体を省略してください。推測や別の値を作成しないでください。</重要>
すべてのテナント(利用組織)は、独自のカスタム取引フィールドを設定するため、報告対象となる情報の種類は組織ごとに異なります。あらかじめ固定されたリストを想定せず、実行時に探索してから crm:aggregate_deals で集計してください。手作業で crm:search_deals の結果から取引をカウントしてはいけません。
aggregate_deals は、一度に 1 つのフィールドでグループ化します。複数の観点をカバーする場合は、1 回の呼び出しで複数の group_by 値を指定するのではなく、複数回の呼び出しで対応してください。
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 などの関連参照)
— 値が無制限です。これらで group_by しないでください。このプラグインのテストテナントでは、EBITDA、ARR、Team_size のようなフィールドで 100 以上の異なるグループが発生し、都市レベルの位置情報クエリが応答サイズ上限に接近して失敗した例があります。
自由記述の標準フィールド(company.company_location、company.company_industry、または type が text のその他標準フィールド)
— 連続値型と同じ無制限のリスク がありますが、常に関連性があるため、データ充足率では除外されません。これらでグループ化してから、クライアント側で生の値をロールアップ(例:都市 → 国)してから表示します。生の内訳は表示しないでください。これらを無条件の「常に含める」リストに入れないでください。他のフィールドと同様に type で分類してください。
常に stage と added_date をコア固定フィールドとして保持します。両者とも値が有限で、テナント関係なく直接グループ化しても安全な標準フィールドです。
グループ化可能フィールド: ステップ 3 の aggregate_deals 呼び出しは、すでに無料でデータ充足率を返します。totalCount から null または _id なしのグループを差し引いた値です。追加の呼び出しは不要です。
連続値型フィールド: フィールドごとに aggregate_deals を呼び出さないでください。代わりに 1 つの共有サンプルを取得してください:
crm_call_tool({ "name": "crm:search_deals", "arguments": { "limit": 30 } })
各連続値型フィールドについて、サンプル内の取引のうち、fields.<fieldId> が存在し null でない割合としてデータ充足率を計算します。1 回の呼び出しで、すべての連続値型フィールドをカバーします(基数に関係なくペイロードは有限)。
データ充足率 15% 未満のフィールドは除外します。 15~25% の間に落ちたフィールド(カットオフを上回っているがサンプルで信頼性が高く推定できない中間領域)については、サンプルを信頼しないでください。search_deals はデフォルトで最近アクティブな取引を優先するため、使用頻度の低いフィールドの充足率を大幅に過大評価する可能性があります。このテストテナントで実証されました:20 件の取引サンプルでは あるフィールドが 25% 充足と推定されましたが、実際の組織全体の率は 3% でした。そのような領域のフィールドについては、そのフィールドだけに対して 1 回の 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 キーは無視してください。これは集計の一部ではなく、組織のデフォルト静的サンプルです。ステップ 2 を通過した連続値型フィールドについては、データ充足率のみを報告します(例:「売上:95% 充填」)。ユーザーが特定のフィールドの詳細分析を明示的に要求しない限り、完全な分布を試さないでください。
自由記述標準フィールドについては、生のグループ化された値をクライアント側でより粗いレベルにロールアップしてから表示します(例:company.company_location の都市値 → 国)。上位 5~8 件のロールアップ値を表示し、残りは「その他」に折りたたみます。
異なる 2 つの _id が同じ名前に解決される場合があります(重複する取引先)。カウントを組み合わせて、その人物の合計が過少報告されないようにフラグを立てます。未解決の取引先・ユーザー ID については、上位数件のみについて crm:fetch_contact_by_id を呼び出してください。
ユーザーが 1 つの特定の観点を要求した場合は、その観点だけを集計します。完全な探索パスをスキップします。
${CLAUDE_PLUGIN_ROOT}/skills/deal-flow-analytics/assets/dashboard-template.html にある HTML ダッシュボードテンプレートを使用してレポートをレンダリングします。マークダウンテーブルを手作業で構築したり、単純な相対パスでテンプレートを参照しないでください(ユーザーの現在のディレクトリから解決され、プラグインディレクトリからではありません)。テンプレートを新しいファイルにコピーしてから、下部の <script> にある DATA オブジェクトのみを編集します:
dateRange — 日付範囲ラベル。例:「2025 年 7 月~2026 年 7 月・167 件の取引」。headline — 最も注目すべき知見を 1 文で。集中度、低充足率、またはステージ分布が「Dead」に偏っているなどのパイプラインヘルスの課題。excluded — ステップ 2 で削除されたフィールドラベル。各フィールドのデータ充足率を表記します。CRM フィールド値は信頼できません。テナントのドロップダウンオプション、タグ、または会社名には任意のテキストが含まれる可能性があります。DATA オブジェクトに文字列を書き込む際に、リテラル部分文字列 </script が含まれている場合は、/ の直前に \ を挿入します(<\/script)。これにより、周囲の <script> ブロックが途中で閉じられるのを防げます。テンプレート独自のレンダリングコードはすでにすべての値に対して HTML エスケープを行っています。これは、あなたが書き込むファイルを保護するだけです。
fields — 観点ごとに 1 エントリ:{ label, total, filled, values }。values は降順でランク付けされ、上位 5~8 エントリ + 長いテールがある場合は "Other" エントリを含みます(大文字と小文字を区別せずにマッチさせ、シリーズカラーではなく薄い色でレンダリングします)。テンプレートは、ヘッダーのすぐ下に次元カードをレンダリングし、headline と excluded をページ下部のフッターに配置します(ナラティブ・注釈はデータの後に来て、その前ではありません)。この順序を変更しないでください。
CSS、レンダリング関数、またはカテゴリカラートークンに触れないでください。これらは検証済み(dataviz スキルを参照)で、このスキルが生成するすべてのレポートで共有されているため、実行ごとに結果が一貫して見えます。ユーザーにファイルパスを伝え、ユーザー自身で開くことができるようにします。このスキルは許可ツールに 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 つずつ提案し、各 url をインラインで表示します。
<!-- 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>
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 による自動翻訳です。