Dakota Marketplace
Dakota Marketplace helps users research allocator organizations, contacts, marketplace searches, fundraising news, private-market strategies, transactions, funds, and performance benchmarks through read-only searches.
- Integration type
- Plugin
- Verification status
- Not applicable
- Platform
- ChatGPT
- Primary Subcategory
- Private Markets, Deals & Expert Networks
- Secondary Subcategories
- None listed
- Brand
- Dakota
- Access
- Account required
- First tracked
- 2026-05-28
- Tool count
- 19
- Geography
- US
The Primary Subcategory used for this profile’s headline score.
Other Subcategories where the Integration is visible.
ChatGPT Plugin Discoverability Score
ChatGPT organic discovery is not live yet
Dakota Marketplace is tracked in the ChatGPT Plugin registry. Public organic-discovery measurement is not live for ChatGPT yet, so there is no score to publish today.
Get notified when your score goes live
Enter your work email and we’ll notify you when ChatGPT Plugin organic discovery scoring launches.
No spam. Unsubscribe any time.
Competing in ChatGPT Private Markets, Deals & Expert Networks
View CategoryHow the Discoverability Score works
Organic discovery scoring for Dakota Marketplace on ChatGPT is not live yet. The score will use measured agent conversations when it launches.
Organic discovery scoring is pending. Your Plugin score will appear on this scale when measurement goes live.
FoundDiagnostic
Whether Claude found your Plugin in connector search. It must be Found before it can reach the picker, but the score counts picker appearances—not search results.
PickedMain score
How often your Plugin appeared in the picker, or Claude invoked it directly, across contested conversations. This percentage is the Discoverability Score; the headline number is rounded.
PositionedDiagnostic
What position your Plugin appeared in when it was shown in the picker. This shows prominence, but it does not affect the score.
19 tools agents can invoke
**Tool: `get_accounts_data`** — primary Dakota Marketplace **Accounts** search: one row = one **firm/organization profile** (~1.33M). Keywords: get_accounts_data, accounts data, firm search, firm list, organization list, accounts interested in, firms interested in, allocator screening, call list, investment interest, investment focus, asset classes, sector, industry, firm preferences, AUM, metro area, account type, ticket size, organization category, oil gas energy petroleum, pensions endowments family offices RIAs consultants. MANDATORY BEFORE ROW LISTS — tool `get_output_fields`: - You may NOT call `get_accounts_data` until you've called `get_output_fields` (tool_name=get_accounts_data) first in this turn — no exceptions except `is_count_only=true`. - If not loaded: `tool_search` query exactly `get_output_fields`. - Copy 3–10 keys VERBATIM from its response into `output_fields`. Never invent/guess keys, never skip on row lists. - Order: lookups → `get_output_fields` → `get_accounts_data`. - Re-run `get_output_fields` each time you call `get_accounts_data` again with new filters — don't reuse stale field names from earlier in the chat. Read-only — **firm identity, geography, Dakota Account AUM, and declared investment preferences** (`investment_interest`, `investment_focus`, `asset_classes`, `sector`, `industry`, yes/no flags, ticket size, consultants). Example asks: "Show accounts interested in oil and gas", "Find firms interested in private equity", "Pension funds that invest in buyout", "Show firms in Boston with $1B AUM", "RIAs in New York", "Accounts interested in venture — show kind of interest." MANDATORY — **`get_accounts_data` must run** for any ask that expects **named firms**, a **ranked or unranked list**, **"top N"**, **"most relevant"**, **"who should I target"**, or **scoped universes** (by geography, type, AUM, strategy, etc.). Calling **tool `get_lookup_values`** or any lookup alone is **never** sufficient — normalize picklists, call **`get_output_fields`**, then **`get_accounts_data`** and base the account list on its **`data`**. **Organization category:** Investment Allocator ~258k (pensions, endowments, family offices); Investment Firm ~33k (managers/sponsors); General Business ~1M (portcos — not default allocator discovery). **`aum`** = Dakota Account AUM on the profile — not Form ADV regulatory AUM. RIA **account type** here; Form ADV **filing** fields → Form ADV tool. First-pass guardrail: prefer geography + (when explicit) account type or organization category + one strategy dimension — avoid unconstrained broad queries. Dakota Marketplace has broad allocator coverage, so empty results often indicate over-restrictive or mismatched filters rather than missing market data. USE-CASE PRIORITIES (firm discovery first): - Capital raising, IB, software sales, allocator sourcing, law, corp dev: build **firm-level** universes here (geo, AUM, strategy) before any people pivot. - PE/VC deal teams / corp dev: screen by sector, industry, geography, strategy; add `types` only when the user names account types. - Return organization targets for firm-only asks; people/title/decision-maker asks are outside this tool's scope. - Start broad (geo + AUM + strategy), tighten progressively; do not fabricate or substitute external sources. Per-filter semantics, value shapes, and lookup ids: read each parameter's **field description** on this tool. Cross-field routing below. GENERIC "ALLOCATORS" RULE (MANDATORY — overrides broad type expansion): - In Dakota product language, **"allocators"** means the organizations represented by Account records — institutions that commit capital to outside managers. It is **not** itself an Account Type or Organization Category value. - **Never populate `types` merely because the user says "allocators."** Do not expand "allocators" into a multi-value account-type list. - **Never populate `organization_category` merely because the user says "allocators."** Organization category is a separate dimension (`Investment Allocator`, `Investment Firm`, `General Business`, etc.) and requires explicit user intent: - **Investment Allocator** — LP/allocator institutions (pensions, endowments, family offices, insurance allocator offices). - **Investment Firm** — managers, sponsors, fund managers (PE/VC/hedge/credit firms as organizations). - **General Business** — private companies / portcos (often with sector/industry + `ownership_types`). - For generic allocator asks with strategy/geo/AUM only, use those explicit filters and **omit `types`** unless the user names subtypes (pensions, endowments, family offices, RIAs, etc.). - Populate `types` only when the user **explicitly names** one or more account types or clear subtype synonyms (see COMMON TYPE MAPPINGS below — each mapping requires explicit user wording, not the bare word "allocators"). - Example: "Show me allocators focused on Early Stage venture investing" → `asset_classes=['Early Stage']` (normalize via tool `get_lookup_values` (catalog id `assets`)); do **not** add `types` or `organization_category`. COMMON TYPE MAPPINGS (first-pass only — always validate via tool `get_lookup_values` (catalog id `account_types`) before calling; apply only when user explicitly uses the mapped phrase): - "Pension Fund" / "Pensions" (allocator / investment-office intent; default) → ["Public Pension Fund", "Local Government Pension", "Corporate Pension Fund (Inv Office)", "Taft-Hartley Plan (ERISA)", "Superannuation Fund"] — do NOT include "Corporate Pension Fund (Plan)" here unless the user clearly means plan-level / DB/DC / corporate retirement *plans*, not allocator offices. - Plan-level pension intent (e.g., "pension plan", "DB plan", "DC plan", "corporate retirement plan") → add to the list above: ["Corporate Pension Fund (Plan)", "Corporate Pension Plan", "Corporate Retirement Plans"] - "Endowment" → ["Endowment", "Hospital Endowment"] - "Foundation" → ["Foundation"] - "Insurance" → ["Insurance Company", "Insurance Company General Account", "Insurance General Account"] - "Family Office" → ["Family Office"] - "RIA" / "RIAs" / "registered investment advisers" (firm list by account type — no Form ADV filing fields) → ["RIA"] - "Bank" → ["Bank", "Investment Bank"] - "Consultant" → ["Consultant"] - "Wealth Manager" → ["Wealth Manager"] - "Sovereign Wealth" → ["Sovereign Wealth Fund"] PENSIONS + PE / BUYOUTS / MID-MARKET BUYOUT (**combined intent — use with MANDATORY `get_accounts_data` above**): - **`types`:** use **allocator-default pension types only** — `Public Pension Fund`, `Local Government Pension`, `Corporate Pension Fund (Inv Office)`, `Taft-Hartley Plan (ERISA)`, `Superannuation Fund` as appropriate. **Do not** add **`Corporate Pension Fund (Plan)`** unless the user clearly means **plan-level** / DB / DC / corporate retirement **plans** (see plan-inclusive line above). - **Broad strategy** (PE, private equity, venture, VC, private credit, real estate): normalize **`investment_focus`** via catalog id `investment_focus`. - **Named sleeves** (buyouts, LBO, mid-market buyout, early stage, growth equity): normalize **`asset_classes`** via catalog id `assets`. - **If that first query returns zero rows**, use the **ZERO-RESULT** protocol (Step 2b) before adding **`Corporate Pension Fund (Plan)`** or abandoning the search. ═══════════════════════════════════════════════════════════════════ STRATEGY LANGUAGE → TAXONOMY PLAYBOOK (see shared STRATEGY TAXONOMY ROUTING): ═══════════════════════════════════════════════════════════════════ Apply shared **STRATEGY TAXONOMY ROUTING** — broad category asks → **`investment_focus`** (catalog id `investment_focus`); named sleeves → **`asset_classes`** (catalog id `assets`). Do not pass user slang directly; normalize through the correct lookup first. Use **one primary strategy lever** on the first query. First-pass hints (always confirm values against the correct lookup — names must match exactly): User / colloquial intent → First-pass filter choice (then refine) ─────────────────────────────────────────── ───────────────────────────────────────────────────── "Private equity" / "PE" / "alternatives" (broad, no sleeve words) → **`investment_focus`**: `Private Equity`. Add pension **`types`** + geo as needed. **If zero rows**, retry per ZERO-RESULT Step 2b. "Buyouts" / "buyout" / "LBO" / "mid-market buyout" → **`asset_classes`**: map to exact sleeve (e.g. `Middle Market Buyout`, `Large Buyout`). **If zero rows**, retry per Step 2b. "Venture" / "VC" / "startups" (broad) → **`investment_focus`**: `Venture Capital`. If zero rows, retry per Step 2b. "Early stage" / "seed" / "Series A" → **`asset_classes`**: `Early Stage` (or closest assets lookup match). If zero rows, retry per Step 2b. "Growth equity" → **`asset_classes`**: `Growth Equity` (or closest assets lookup match). If zero rows, retry per Step 2b. "Private credit" / "direct lending" (broad) → **`investment_focus`**: `Private Credit`. If zero rows, retry per Step 2b. "Real estate" / "RE" / "property" (broad) → **`investment_focus`**: `Private Real Estate` or `Real Assets`. If zero rows, retry with RE **`asset_classes`** from lookup, then Step 2b. "Infrastructure" / "infra" (broad) → **`investment_focus`**: `Private Infrastructure` "Secondaries" / "sponsor-led secondaries" → **`asset_classes`**: closest secondaries sleeve from assets lookup. If zero rows, retry per Step 2b. "Fixed income" / "rates" (broad) → **`investment_focus`**: `Long-only Fixed Income` "Hedge funds" / "liquid alts" (broad) → **`investment_focus`**: `Hedge Fund`; confirm via lookup If no clear mapping exists after scanning lookups, run **without** `types` or strategy filters first using geo/AUM when those are present, inspect returned rows, then refine a second query. **Sparse strategy tags:** `investment_focus` can be sparsely populated on some account types (especially pensions). Do **not** treat zero rows as proof the market has no matching firms until ZERO-RESULT Step 2b is exhausted. ═══════════════════════════════════════════════════════════════════ QUERY STRATEGY (follow this approach): ═══════════════════════════════════════════════════════════════════ 1. START BROAD: geography (`metro_areas`, `billing_states`, `billing_countries`), AUM (`aum`), strategy (`investment_focus` OR `asset_classes`), `ticket_size` when specified. Add `types` only when the user names account types. 2. ADD SECONDARY FILTERS after a sensible first slice — pensions + PE/buyouts per block above; `sector` / `industry` only when explicitly requested. 3. PREFER broader queries with progressive narrowing over highly specific first queries. ═══════════════════════════════════════════════════════════════════ CROSS-FIELD ROUTING (not covered by single field descriptions): ═══════════════════════════════════════════════════════════════════ - **Ownership vs strategy:** `ownership_types` = who owns/controls the company (PE-backed, founder-led, public). Do **not** use for PE/VC **strategy** asks ("private equity firms", "allocators focused on buyouts") — use `investment_focus` / `asset_classes`. Colloquial → label mapping lives on the `ownership_types` field description. - **Geography routing:** broad regions (Northeast, Bay Area, Midwest) → `metro_areas` or `billing_states`, not `billing_cities`. Specific cities → `billing_cities` after `city_names` lookup. Do **not** expand region country lists into `metro_areas`. "NYC" / tri-state → `billing_cities` `New York City` OR `metro_areas` `New York`; "Bay Area" / "SF" → `metro_areas` `San Francisco`; "Northeast" → multi-value `billing_states` (NY, CT, MA, NJ, PA) or major metros. - **Lookup-backed profile filters:** normalize `sub_types`, `product_structures`, `client_bases`, `lp_usages`, `etf_usages`, `cit_usages` via `get_lookup_values` before calling. POST-SELECTION NOTES: - **RIAs in [city/metro]** with firm-list intent (no SEC file number, custody, regulatory AUM, Form ADV Part 1) → **`types`** `RIA` (lookup) + geography — this tool, not Form ADV filing search. - **Dakota Account AUM** (`aum`) is on Account — not regulatory filing AUM on Form ADV rows. - **`investment_focus` / `asset_classes`** are firm-level tags on Account — not fund vintage, fundraising status, or CUSIP on Investment Strategy records. - If the ask is primarily filings, people, deals, documents, minutes, job changes, or reported holdings/allocations, use the matching primary tool — do not force this tool. ═══════════════════════════════════════════════════════════════════ ZERO-RESULT RECOVERY PROTOCOL (MANDATORY — follow exactly): ═══════════════════════════════════════════════════════════════════ If status='success' AND (total_count == 0 OR data is empty): DO NOT immediately tell the user "no results found." DO NOT ask the user for clarification yet. You MUST execute this recovery sequence FIRST: STEP 1 — FILTER VALIDATION: - Check whether any filters may be invalid, approximate, or incorrectly mapped. - Especially re-check: `types`, `organization_category`, `billing_cities`, `sector`, `industry`, `investment_focus`, `asset_classes`, `ticket_size`, `ownership_types`, consultant filters, Form 5500/SEC filters, and allocator-profile filters. - For lookup-backed profile filters, confirm you used `get_lookup_values` and exact values. - If ANY filter might be wrong: call the relevant lookup tool(s), remap values, and retry the query immediately. - Form 5500: if `form_5500_account=true` + `sec_registered_date` returns no rows, retry with `form_5500_pdf` + `sec_registered_date` before relaxing other filters. STEP 2 — REMOVE UNRELIABLE FILTERS: - If `sector` or `industry` was used alongside `types` → remove sector/industry and retry. - Drop the least essential filter and retry. STEP 2b — STRATEGY TAXONOMY REALIGNMENT (before stripping geography): If you still have zero results after Step 2 and a strategy filter was used: - Retry immediately with the **same** `types`, `organization_category` (if used), geography, `aum`, and `names` as before. - If **`investment_focus`** was used → retry with related **`asset_classes`** from catalog id `assets`. Remove `investment_focus` on this retry. - If **`asset_classes`** was used → retry with broader **`investment_focus`** from catalog id `investment_focus`. Remove `asset_classes` on this retry. - If cross-retry still returns zero rows → retry with **one** yes/no flag: **`venture_capital_focus=["Yes"]`** (venture/VC), **`private_equity=["Yes"]`** (PE), or **`private_credit=["Yes"]`** (private credit). Remove both `investment_focus` and `asset_classes` on this retry. - If this returns data, you may optionally run a **follow-up** narrower query — do not hide the successful recall-first result. STEP 3 — PROGRESSIVE FILTER RELAXATION: If filters appear valid but still too restrictive (including after Step 2b), relax in this priority order: 1. Remove geographic filters (`billing_cities`, `billing_states`) first. 2. Widen range filters (`aum`, `ticket_size`, `number_of_employees`) second. 3. Remove categorical filters (`sector`, `industry`, `investment_focus`, `asset_classes`, `organization_category`) and optional flags third when they may be over-narrowing. 4. Keep explicitly user-named `types` and `names` last — do not add `types` during relaxation if the user never named account types. Retry after each relaxation. STEP 4 — USER FOLLOW-UP (ONLY after completing steps 1 → 2 → 2b (when applicable) → 3 without usable results): - You MUST have attempted at least 2 different filter relaxation strategies before reaching this step. - Say: "I tried several filter combinations but couldn't find matching accounts in Dakota Marketplace." - Briefly mention what you tried (e.g., "I searched with and without the city filter, and with broader AUM range"). - Ask 1–3 targeted follow-up questions to help the user refine their search. ═══════════════════════════════════════════════════════════════════ OUTPUT FIELDS (REQUIRED on every row-list call — do not skip): ═══════════════════════════════════════════════════════════════════ - `output_fields` **must be populated** on every `get_accounts_data` call that returns rows. Exception only: `is_count_only=true` when the user wants a count and no row columns. - To populate it, you **MUST** call tool **`get_output_fields`** first with `tool_name` = `get_accounts_data` (if `tool_search` is needed, query exactly `get_output_fields`). - Then pass a **small subset** (typically 3–10 keys) copied **verbatim** from that tool's returned `output_fields` list — never invent keys, never paste the full allowlist. - Preferred order: (1) `get_lookup_values` if picklists are needed → (2) `get_output_fields` → (3) `get_accounts_data` with `output_fields` set. - Do **not** call `get_accounts_data` for a row list until `get_output_fields` has been called in this turn and `output_fields` is set from its response. - Invalid keys are rejected by the server before the Apex call — that error means call `get_output_fields` again and retry with allowlisted keys only.
get_accounts_data
**Tool: `get_accounts_with_conference_data`** — primary Dakota Marketplace **Conference** search: one row = **firm linked to a conference event** (~4,700 events). Keywords: get_accounts_with_conference_data, conference, event, conference category, format, conference date, speaker type, target audience, conference-linked firms. MANDATORY BEFORE ROW LISTS — tool `get_output_fields`: - You may NOT call `get_accounts_with_conference_data` until you've called `get_output_fields` (tool_name=get_accounts_with_conference_data) first in this turn — no exceptions except `is_count_only=true`. - If not loaded: `tool_search` query exactly `get_output_fields`. - Copy 3–10 keys VERBATIM from its response into `output_fields`. Never invent/guess keys, never skip on row lists. - Order: lookups → `get_output_fields` → `get_accounts_with_conference_data`. - Re-run `get_output_fields` each time you call `get_accounts_with_conference_data` again with new filters — don't reuse stale field names from earlier in the chat. Read-only query tool — filter **firms** by **conference** attributes plus optional contact and linked-firm profile overlays. Underlying catalog ~**4,700** conference events; MCP returns **firm/account rows**, not a list of event titles. Use when the ask ties organizations to **events, conferences, or conference date windows** — not generic firm screening alone. **Prod catalog note:** Most rows are **Conference Organizers** (~4k) — profile-style organizer records, not every upcoming tradeshow. For attendable industry events, tighten with **`category`** (e.g. Investment Firm Conference/Event, Trade Shows) plus **`start_date`**. Conference **`investment_focus`** = event topic — not firm **`investment_focus`**. Example asks: "Firms tied to institutional conferences in 2025", "Conference-linked allocators focused on private equity", "Organizations at conferences targeting family offices in the Northeast." MANDATORY — **`get_accounts_with_conference_data` must run** for conference-driven firm universe asks. Normalize picklists via **`get_lookup_values`**, call **`get_output_fields`**, then query. Dakota Marketplace has broad conference coverage; empty results often mean over-restrictive filters, incorrect picklist mapping, or value-shape mismatches. Per-filter semantics and lookup ids: read each parameter's **field description** on this tool. ═══════════════════════════════════════════════════════════════════ QUERY STRATEGY (follow this approach): ═══════════════════════════════════════════════════════════════════ 1. START BROAD: - Begin with 1-2 core conference taxonomy filters (`category`, `format`, `target_audience`, `speaker_type`) and/or conference date windows. 2. ADD SECONDARY FILTERS: - Add contact/firm overlays only after you validate non-empty conference scope. 3. PROGRESSIVE NARROWING: - Avoid stacking many conference + contact + firm filters in first pass. 4. RETAIN CORE USER INTENT: - Keep core conference intent dimensions as long as possible while relaxing secondary constraints. Field guidance: - Conference-primary filters: `category`, `format`, `investment_focus` (conference topic — not firm `investment_focus`), `speaker_type`, `target_audience`. - Free-form conference location/web fields: `city`, `state`, `country`, `location`, `website` (use when user explicitly provides them). - Contact overlays: **`asset_class_coverages`** for person coverage; **`account_investment_focus_single`** for broad firm strategy; **`account_asset_classes`** for firm sleeves. - For firm billing geography: validate `billing_cities` via **`get_lookup_values`** (catalog id `city_names`); expand region-style `billing_countries` per the field description. ═══════════════════════════════════════════════════════════════════ ZERO-RESULT RECOVERY PROTOCOL (MANDATORY — follow exactly): ═══════════════════════════════════════════════════════════════════ If status='success' AND (total_count == 0 OR data is empty): DO NOT immediately tell user "no results found." DO NOT ask follow-up questions yet. You MUST execute this sequence first: STEP 1 — FILTER VALIDATION: - Re-check all lookup-backed filters and remap where needed. - Re-check value shapes (booleans vs yes/no arrays vs string ranges). - Retry immediately after corrections. STEP 2 — RELAX CONFERENCE DIMENSIONS FIRST: - Remove `investment_focus` first. - Then remove one of `speaker_type` or `target_audience` if both were used. - Widen date windows (`start_date`, `end_date`, `registration_deadline`, `early_bird_registration_deadline`) if narrow. STEP 3 — RELAX CONTACT/FIRM OVERLAYS: - Remove restrictive contact/firm profile filters while preserving conference core intent. - Remove overlays in this order: 1. taxonomy filters (`organization_category`, `account_organization_category`, `account_asset_classes`, `account_industry`, `account_sector`) 2. consultant and profile picklists 3. non-essential numeric/location constraints STEP 4 — SECOND BROAD PASS: - Retry with only strongest conference anchors + must-have user constraints. STEP 5 — USER FOLLOW-UP (only after steps 1-4 fail): - State you tried multiple valid filter combinations. - Ask 1-3 targeted follow-up questions. ═══════════════════════════════════════════════════════════════════ OUTPUT FIELDS (REQUIRED on every row-list call — do not skip): ═══════════════════════════════════════════════════════════════════ - `output_fields` **must be populated** on every `get_accounts_with_conference_data` call that returns rows. Exception only: `is_count_only=true` when the user wants a count and no row columns. - To populate it, you **MUST** call tool **`get_output_fields`** first with `tool_name` = `get_accounts_with_conference_data` (if `tool_search` is needed, query exactly `get_output_fields`). - Then pass a **small subset** (typically 3–10 keys) copied **verbatim** from that tool's returned `output_fields` list — never invent keys, never paste the full allowlist. - Preferred order: (1) `get_lookup_values` if picklists are needed → (2) `get_output_fields` → (3) `get_accounts_with_conference_data` with `output_fields` set. - Do **not** call `get_accounts_with_conference_data` for a row list until `get_output_fields` has been called in this turn and `output_fields` is set from its response. - Invalid keys are rejected by the server before the Apex call — that error means call `get_output_fields` again and retry with allowlisted keys only.
get_accounts_with_conference_data
**Tool: `get_investment_strategy_data`** — primary Dakota Marketplace **Investment Strategy** search: one row = one **fund/strategy product** (~136k); returns **firm rows** filtered by linked strategy attributes. Keywords: get_investment_strategy_data, fund product, vintage, fundraising status Open Closed, CUSIP, strategy name, strategy AUM, product structure, fund type, capital drawn, hard cap. MANDATORY BEFORE ROW LISTS — tool `get_output_fields`: - You may NOT call `get_investment_strategy_data` until you've called `get_output_fields` (tool_name=get_investment_strategy_data) first in this turn — no exceptions except `is_count_only=true`. - If not loaded: `tool_search` query exactly `get_output_fields`. - Copy 3–10 keys VERBATIM from its response into `output_fields`. Never invent/guess keys, never skip on row lists. - Order: lookups → `get_output_fields` → `get_investment_strategy_data`. - Re-run `get_output_fields` each time you call `get_investment_strategy_data` again with new filters — don't reuse stale field names from earlier in the chat. Read-only — use when the ask names **funds, vintages, open/closed fundraising, vehicles, CUSIP, or strategy AUM** — not firm preference tags alone ("interested in oil and gas" → **`get_accounts_data`**). Example asks: "Firms with open private equity buyout funds fundraising now", "2024 vintage venture capital strategies", "Closed-end fund managers with strategy AUM over $500M", "Accounts with alternative credit interval funds", "Buyout strategies with product structure LP". MANDATORY — **`get_investment_strategy_data` must run** for any ask that expects **firms filtered by fund/strategy product attributes**. Normalize picklists via **`get_lookup_values`**, call **`get_output_fields`**, then **`get_investment_strategy_data`**. Dakota Marketplace has broad strategy coverage; empty results often indicate over-restrictive or mismatched filters rather than missing market data. Per-filter semantics, value shapes, and lookup ids: read each parameter's **field description** on this tool. `asset_classes` (coverage note): - `asset_classes` is usually the strongest high-coverage first-pass filter. - Prefer refining with other supported dimensions (`product_structures`, `fund_types`, `fundraising_statuses`, `vintages`) rather than over-constraining early. COMMON NORMALIZATION HINTS: - "PE" / "private equity" can map to multiple strategy rows; start with broader `asset_classes` then refine with other strategy dimensions. - "open fundraising" / "raising capital" should map exactly to **`Closed`/`Open`** per the `fundraising_statuses` tool parameter description (no lookup tool). - "closed end" / "open end" / similar vehicle structure asks should map exactly per the **`fund_types`** tool parameter description and/or **tool `get_lookup_values` (catalog id `strategy_product_structures`)**. - Vintages: pass **four-digit year strings** (e.g. `2024`) from user intent — no lookup tool. Sources: use **tool `get_lookup_values` (catalog id `investment_strategy_sources`)** for exact provenance strings. ═══════════════════════════════════════════════════════════════════ STRATEGY FILTER PLAYBOOK (intent → filters): ═══════════════════════════════════════════════════════════════════ Apply shared **STRATEGY TAXONOMY ROUTING** on this tool: - **Strategy-level broad category** → `asset_classes` (tool `get_lookup_values` (catalog id `investment_strategy_asset_classes`)) - **Strategy-level specific sleeves** → `sub_asset_classes` (tool `get_lookup_values` (catalog id `strategy_sub_asset_classes`)) - **Investment approach on strategy records** → `investment_styles` (exact labels in parameter description — Passive, Active Index, Systematic, etc.) - **Related-account broad firm strategy** → `account_investment_focus` (tool `get_lookup_values` (catalog id `investment_focus`)) - **Related-account firm sleeves** → `account_asset_classes` (tool `get_lookup_values` (catalog id `assets`)) When user intent is strategy-led: 1. Anchor first pass on `asset_classes` (broad) or `sub_asset_classes` (sleeve), plus optional `fund_types` or `fundraising_statuses`. 2. Add `product_structures` for vehicle compatibility filtering. 3. Add `vintages` for cohort filtering and `strategy_aum` for size bands. 4. Add `investment_styles` when user asks for approach (passive, active, systematic). 5. Add `sources` only when provenance filtering is explicitly required. First-pass guidance: - "private equity strategies" (broad) → `asset_classes` + supporting dimensions as needed. - "middle market buyout strategies" (sleeve) → `sub_asset_classes` + `asset_classes` if needed. - "passive / systematic PE benchmarks" → `investment_styles` + `asset_classes` or `sub_asset_class`. - "open fundraising closed-end funds" → `fundraising_statuses` + `fund_types`. - "large strategies above $1B" → strategy AUM lower bound first, then taxonomy constraints. Avoid first-pass over-narrowing by stacking all of: product structure + fundraising status + fund type + vintage + source + tight AUM bounds at once. ═══════════════════════════════════════════════════════════════════ QUERY STRATEGY (follow this approach): ═══════════════════════════════════════════════════════════════════ 1. START BROAD with one/two high-signal strategy dimensions (`asset_classes`, `fund_types`, `fundraising_statuses`). 2. ADD SECONDARY FILTERS (`product_structures`, `vintages`). 3. ADD RANGE FILTERS (`strategy_aum`) when user specifies size constraints. 4. ADD SOURCE FILTER only when user asks for provenance restriction. 5. PREFER broader query plus progressive narrowing over highly specific first query. FIELD SELECTION GUIDANCE: - Use `account_names` for known-firm targeting (partial-match account search). - Use `strategy_names` when the user provides specific strategy names (for example: "Heathrow Forest Asia Opportunities Fund II"). - Use `asset_classes` for **broad strategy category** on the investment-strategy record. - Use `sub_asset_classes` for **specific strategy sleeves** (e.g. Buyout, Early Stage). - Use `investment_styles` for **investment approach** on strategy records (passive, active, systematic — not account `account_investment_styles`). - Use `account_investment_focus` for **broad firm strategy** on linked accounts; use `account_asset_classes` for **firm sleeves**. - Use `product_structures` for vehicle-level compatibility (LP/ETF/Mutual Fund, etc.). - Use `fundraising_statuses` for pipeline status (open/closed style asks). - Use `fund_types` for strategy structure type (closed-end/open-end/etc.). - Use `strategy_aum` for lower/upper strategy size bands. - Use `vintages` for time-cohort filtering in private markets contexts. - Use `sources` as optional provenance filtering; coverage may be lower than core taxonomy fields. GEOGRAPHY HANDLING: - Use `account_metro_areas` for Dakota metro clustering and broader regional discovery. - Use `account_billing_cities` for strict city filtering only when city-level precision is requested. - Use `account_billing_states` / `account_billing_countries` for state/country scope. - Keep strategy geography separate: use `geographies` only for strategy-level geography taxonomy (lookup-backed), not for office-location geography. ═══════════════════════════════════════════════════════════════════ ZERO-RESULT RECOVERY PROTOCOL (MANDATORY — follow exactly): ═══════════════════════════════════════════════════════════════════ If status='success' AND result set is empty: DO NOT immediately tell user "no results found". DO NOT ask for clarification yet. You MUST execute recovery first: STEP 1 — FILTER VALIDATION: - Re-check lookup-mapped fields: `asset_classes`, `product_structures`, `sources`, plus `geographies`. - Re-check `vintages`: ensure year strings match user cohort intent (typically four-digit years). - Re-check inlined-enum strategy fields (`fundraising_statuses`, `fund_types`, `source_types`, `sectors`, `investment_styles`) against the tool parameter descriptions. - If any mapping may be approximate/invalid, rerun lookup(s), remap exact labels, and retry immediately. STEP 2 — REMOVE UNRELIABLE FILTERS: - Remove `sources` first. - If both `product_structures` and `fund_types` are used, remove one and retry. STEP 3 — RANGE + COHORT RELAXATION: - Widen `strategy_aum` range. - Remove `vintages` if still over-constrained. - Remove `account_names` if present and user intent is discovery, not known-firm lookup. STEP 4 — CORE-INTENT PRESERVATION: - Keep one primary strategy anchor (`asset_classes` OR `fund_types` OR `fundraising_statuses`) and retry with broader supporting filters removed. STEP 5 — USER FOLLOW-UP (ONLY after steps 1→4 fail): - Say you attempted multiple valid strategy-filter combinations in Dakota Marketplace. - Briefly mention what was relaxed. - Ask 1-3 focused follow-up questions to refine the search. ═══════════════════════════════════════════════════════════════════ OUTPUT FIELDS (REQUIRED on every row-list call — do not skip): ═══════════════════════════════════════════════════════════════════ - `output_fields` **must be populated** on every `get_investment_strategy_data` call that returns rows. Exception only: `is_count_only=true` when the user wants a count and no row columns. - To populate it, you **MUST** call tool **`get_output_fields`** first with `tool_name` = `get_investment_strategy_data` (if `tool_search` is needed, query exactly `get_output_fields`). - Then pass a **small subset** (typically 3–10 keys) copied **verbatim** from that tool's returned `output_fields` list — never invent keys, never paste the full allowlist. - Preferred order: (1) `get_lookup_values` if picklists are needed → (2) `get_output_fields` → (3) `get_investment_strategy_data` with `output_fields` set. - Do **not** call `get_investment_strategy_data` for a row list until `get_output_fields` has been called in this turn and `output_fields` is set from its response. - Invalid keys are rejected by the server before the Apex call — that error means call `get_output_fields` again and retry with allowlisted keys only.
get_investment_strategy_data
**Tool: `get_accounts_with_investors_data`** — primary Dakota Marketplace **Investor / sponsor–portco** search: one row = one **sponsor–portfolio company relationship** (~314k). Keywords: get_accounts_with_investors_data, investor relationship, sponsor portco, portfolio company, PE-backed company, sponsor investment, financial status, portco screening, portfolio company revenue employees metro. MANDATORY BEFORE ROW LISTS — tool `get_output_fields`: - You may NOT call `get_accounts_with_investors_data` until you've called `get_output_fields` (tool_name=get_accounts_with_investors_data) first in this turn — no exceptions except `is_count_only=true`. - If not loaded: `tool_search` query exactly `get_output_fields`. - Copy 3–10 keys VERBATIM from its response into `output_fields`. Never invent/guess keys, never skip on row lists. - Order: lookups → `get_output_fields` → `get_accounts_with_investors_data`. - Re-run `get_output_fields` each time you call `get_accounts_with_investors_data` again with new filters — don't reuse stale field names from earlier in the chat. Read-only query tool — one row = one **sponsor ↔ portfolio company** relationship. Prefer **`financial_statuses`** (Current / Former / Pending) for lifecycle — **`statuses`**, **`stages`**, **`transaction_types`**, and investment/exit **date ranges are sparsely populated** — do not rely on them alone. Use **`portfolio_company_*`** filters for the portco side; **`account_*`** for the sponsor firm profile. Example asks: "PE firms invested in software portcos", "Sponsors with current investments in healthcare companies", "Portfolio companies backed by firms in New York", "Investor relationships with portfolio company revenue over $100M". MANDATORY — **`get_accounts_with_investors_data` must run** for sponsor/portco relationship asks expecting **named firms or portcos** scoped by investor lifecycle, portfolio-company attributes, or linked account overlays. Normalize picklists via **`get_lookup_values`**, call **`get_output_fields`**, then query. Dakota Marketplace has broad coverage; empty results often come from over-constrained combinations or invalid mappings rather than true absence of records. ═══════════════════════════════════════════════════════════════════ QUERY STRATEGY (follow this approach): ═══════════════════════════════════════════════════════════════════ 1. START BROAD: - Lead with **`financial_statuses`** (Current / Former / Pending) — prod-populated lifecycle signal. Do **not** default **`statuses`**, **`stages`**, or **`transaction_types`** (sparse/empty in prod). Avoid default **`is_verified=true`** (~2 rows). 2. ADD TIMING/NUMERIC CONSTRAINTS: - Add `investment_date_*`, `exit_date_*`, `revenue_*`, `employee_headcount_*`, `year_founded_*` only when explicitly requested. 3. LAYER ACCOUNT OVERLAYS AFTER FIRST PASS: - Add account taxonomy/profile filters after confirming non-empty investor scope. 4. PREFER PROGRESSIVE NARROWING: - Avoid stacking many lifecycle + account picklists in the first attempt. Field-selection guidance: - Investor direct filters: `account_portfolio_company`, `investment_status_details`, `investor_account_names`, `portfolio_company_names`. - Lookup-backed portfolio taxonomy filters: `portfolio_types` (tool `get_lookup_values` (catalog id `account_types`)), `portfolio_sectors` (tool `get_lookup_values` (catalog id `sectors`)), `portfolio_metro_areas` (exact values from the tool parameter description for this filter), `portfolio_industries` (tool `get_lookup_values` (catalog id `industries`)). - Portfolio-company overlays: `portfolio_company_types`, `portfolio_company_metro_areas`, `portfolio_company_asset_class`, and `portfolio_company_investment_focus` are lookup-backed and must be normalized via the mapped account lookup tools before calling this data tool. - `investment_status_details` is free-form detail text; use only when user asks for that nuance. - Account strategy filters (related-account overlays on investor-linked firms): - **`account_investment_focus`** → broad firm strategy category (e.g. Venture Capital, Private Equity) via tool `get_lookup_values` (catalog id `investment_focus`). - **`account_asset_classes`** → specific firm sleeves (e.g. Early Stage, Middle Market Buyout) via tool `get_lookup_values` (catalog id `assets`). - **`account_private_credit`**, **`account_private_equity`**, **`account_hedge_fund`** → coarse yes/no orientation flags (`['Yes']` or `['No']`); use only as fallback when taxonomy fields return no rows. - Do **not** use `account_asset_classes` for broad category-only asks when `account_investment_focus` applies. - Account profile filters should be lookup-first whenever a lookup tool exists (client type/sub-type, product structure, LP/ETF/CIT usage, geography, services, target buyers, etc.). ═══════════════════════════════════════════════════════════════════ ZERO-RESULT RECOVERY PROTOCOL (MANDATORY — follow exactly): ═══════════════════════════════════════════════════════════════════ If status='success' AND (total_count == 0 OR data is empty): DO NOT immediately tell user "no results found." DO NOT ask for clarification yet. You MUST execute this sequence first: STEP 1 — FILTER VALIDATION: - Re-check lookup-backed fields and remap from lookup outputs. - Re-check value-shapes (boolean vs account-orientation yes/no arrays vs single-value yes/no arrays). - Retry immediately after correcting mappings/shapes. STEP 2 — RELAX INVESTOR DIMENSIONS FIRST: - Remove `investment_status_details` first. - If both present, remove one of `statuses` or `financial_statuses`. - Widen date windows (`investment_date_*`, `exit_date_*`) and numeric ranges (`revenue_*`, `employee_headcount_*`, `year_founded_*`) second. STEP 3 — RELAX ACCOUNT OVERLAYS: - Remove restrictive account profile/taxonomy filters in this order: 1. `account_industry`, `account_sector`, `account_asset_classes` 2. account profile picklists (client/product/usage/geography/services) 3. consultant-family fields - Keep core investor intent filters as long as possible. STEP 4 — SECOND BROAD PASS: - Keep only 1-2 strongest investor anchors and essential user constraints. - Retry once more before asking user follow-ups. STEP 5 — USER FOLLOW-UP (only after steps 1-4 fail): - State that you tried multiple valid filter combinations. - Ask 1-3 targeted clarifying questions. ═══════════════════════════════════════════════════════════════════ OUTPUT FIELDS (REQUIRED on every row-list call — do not skip): ═══════════════════════════════════════════════════════════════════ - `output_fields` **must be populated** on every `get_accounts_with_investors_data` call that returns rows. Exception only: `is_count_only=true` when the user wants a count and no row columns. - To populate it, you **MUST** call tool **`get_output_fields`** first with `tool_name` = `get_accounts_with_investors_data` (if `tool_search` is needed, query exactly `get_output_fields`). - Then pass a **small subset** (typically 3–10 keys) copied **verbatim** from that tool's returned `output_fields` list — never invent keys, never paste the full allowlist. - Preferred order: (1) `get_lookup_values` if picklists are needed → (2) `get_output_fields` → (3) `get_accounts_with_investors_data` with `output_fields` set. - Do **not** call `get_accounts_with_investors_data` for a row list until `get_output_fields` has been called in this turn and `output_fields` is set from its response. - Invalid keys are rejected by the server before the Apex call — that error means call `get_output_fields` again and retry with allowlisted keys only.
get_accounts_with_investors_data
**Tool: `get_accounts_with_transactions_data`** — primary Dakota Marketplace **Transaction / deal event** search: one row = one **deal event** (~26k deals); returns **firm rows** filtered by transaction taxonomy. Keywords: get_accounts_with_transactions_data, M&A, acquisition merger, buyout deal, venture round, transaction type, deal participant buyer seller, transaction value, deal date, transaction sector industry. MANDATORY BEFORE ROW LISTS — tool `get_output_fields`: - You may NOT call `get_accounts_with_transactions_data` until you've called `get_output_fields` (tool_name=get_accounts_with_transactions_data) first in this turn — no exceptions except `is_count_only=true`. - If not loaded: `tool_search` query exactly `get_output_fields`. - Copy 3–10 keys VERBATIM from its response into `output_fields`. Never invent/guess keys, never skip on row lists. - Order: lookups → `get_output_fields` → `get_accounts_with_transactions_data`. - Re-run `get_output_fields` each time you call `get_accounts_with_transactions_data` again with new filters — don't reuse stale field names from earlier in the chat. Read-only query tool — one row = one **deal event** with a **target company** and participant firms via **`transaction_account_types`** (Buyer, Lead Investor, …). Top deal types include **Venture**, **Acquisition / Merger**, **Buyout/Private Equity**, Growth Equity, Credit, Real Assets — use exact **`Acquisition / Merger`** label for M&A asks. Default **`Closed`** for completed deals; **`Announced`** for pipeline. Example asks: "Closed buyout transactions in 2025", "Software sector venture rounds", "Firms as buyer on announced M&A deals", "Healthcare acquisition transactions between specific dates". MANDATORY — **`get_accounts_with_transactions_data` must run** for deal-driven firm universe asks. Normalize picklists via **`get_lookup_values`**, call **`get_output_fields`**, then query. Dakota Marketplace has broad account and transaction coverage; empty results often indicate over-restrictive or mismatched filters rather than missing market data. `transaction_types` / `transaction_sub_types` / `transaction_statuses` / `transaction_industries` / `transaction_sectors` precision tradeoff: - `transaction_sub_types` and narrow industry + sector combinations are high precision but can over-constrain quickly. - `transaction_types` and `transaction_statuses` are usually better first-pass anchors. - Start broad with date + one/two transaction dimensions, then progressively narrow. ═══════════════════════════════════════════════════════════════════ QUERY STRATEGY (follow this approach): ═══════════════════════════════════════════════════════════════════ 1. START BROAD: `transaction_types` and/or `transaction_statuses` + date window. 2. ADD SECONDARY: `transaction_sub_types`, industry/sector when explicitly requested. 3. LAYER account overlays after transaction scope returns rows. COMMON FIRST-PASS NORMALIZATION HINTS: - "M&A" can map to multiple transaction sub-types depending on exact taxonomy; validate via tool `get_lookup_values` (catalog id `transaction_sub_types`). - "Funding" / "fundraise" can map to one or more transaction types/sub-types; map **`transaction_types`** to exact strings from its tool parameter description, then refine with tool `get_lookup_values` (catalog id `transaction_sub_types`). - "Active" is often not an exact **`transaction_statuses`** label; compare user wording to **`Announced`/`Closed`/`Terminated`** only. - Industry/sector synonyms (e.g., "Tech" vs "Information Technology") must be exact from transaction lookup tools. ═══════════════════════════════════════════════════════════════════ TRANSACTION FILTER PLAYBOOK (intent → filters): ═══════════════════════════════════════════════════════════════════ When user intent is transaction-led: 1. Anchor first pass on `transaction_types` and/or `transaction_statuses` + date window. 2. Add `transaction_sub_types` only when user explicitly asks for specific deal form. 3. Add `transaction_industries` / `transaction_sectors` for vertical focus. 4. Add account constraints (`account_organization_category`, metro, asset class, PE flag) after transaction scope is non-empty. First-pass guidance: - "closed deals in software" → `transaction_statuses` + `transaction_industries` + date window. - "buyout transactions" → `transaction_types` and possibly `transaction_sub_types` (validated exact values). - "PE-oriented accounts with transactions" → `account_private_equity='Yes'` + broad transaction filter before adding sub-type. Avoid first-pass over-narrowing by stacking all of: sub-type + industry + sector + account type + metro + PE flag at once. ═══════════════════════════════════════════════════════════════════ QUERY STRATEGY (follow this approach): ═══════════════════════════════════════════════════════════════════ 1. START BROAD with transaction window + one/two high-signal dimensions (`transaction_types`, `transaction_statuses`). 2. ADD SECONDARY FILTERS (`transaction_sub_types`, `transaction_industries`, `transaction_sectors`). 3. ADD ACCOUNT CONTEXT (`account_names`, `account_organization_category`, `account_metro_areas`, `account_asset_classes`, `account_private_equity`). 4. PREFER broader query plus progressive narrowing over highly specific first query. FIELD SELECTION GUIDANCE: - Use **`transaction_date`** for deal timing — maps to **announced date** (primary date axis in prod); use agreement/completion date ranges only when user names those milestones. - Use `transaction_types` for broad transaction category intent. - Use `transaction_sub_types` for specific deal mechanics (only when asked). - Use `transaction_statuses` for lifecycle state filtering. - Use `transaction_industries` and `transaction_sectors` only when user requests vertical focus. - Use `transaction_sub_industries` for fine-grained vertical filters only after validating exact values with tool `get_lookup_values` (catalog id `transaction_sub_industries`). - `transaction_names`, `target_segments` are direct string filters (no lookup tool); use exact/known labels when available and avoid broad fuzzy terms unless user asks. - Use `account_organization_category` (lookup-validated; account organization category / API `accountRecordType`) for account taxonomy filtering. - Use `account_types` (lookup-validated) when the user asks for specific organization categories. - Use `account_investment_focus` (lookup-validated) for **broad firm strategy** on transaction-linked accounts (e.g. Venture Capital, Private Equity). - Use `account_asset_classes` (lookup-validated) for **specific firm sleeves** on transaction-linked accounts (e.g. Early Stage, Middle Market Buyout). - Use `account_private_equity`, `account_private_credit`, and `account_hedge_fund` strictly as `Yes`/`No` only as fallback when taxonomy fields return no rows. - Use `agreement_date` and `completion_date` when user asks for those specific transaction milestones (`YYYY-MM-DD=>YYYY-MM-DD` range strings). - Use `transaction_value` for transaction size bands (digits-only numeric range string `lower=>upper`). - Use `account_names` for known-firm filtering; do not overuse on discovery asks. ═══════════════════════════════════════════════════════════════════ ZERO-RESULT RECOVERY PROTOCOL (MANDATORY — follow exactly): ═══════════════════════════════════════════════════════════════════ If status='success' AND (result set empty): DO NOT immediately tell user "no results found". DO NOT ask for clarification yet. You MUST execute recovery first: STEP 1 — FILTER VALIDATION: - Re-check mappings: lookup-backed (`transaction_sub_types`, `transaction_industries`, `transaction_sectors`, `transaction_groups`, plus Account lookups listed above); inlined transaction fields (`transaction_types`, `transaction_statuses`, `transaction_valuation_types`, `transaction_account_types`, `transaction_account_sub_types`) against their tool parameter descriptions. - If any might be approximate/invalid, rerun lookup(s), remap, retry immediately. STEP 2 — REMOVE UNRELIABLE FILTERS: - Remove `transaction_sub_types` first. - If both `transaction_industries` and `transaction_sectors` are used, remove one and retry. - Remove `account_asset_classes` if still over-constrained. STEP 3 — PROGRESSIVE RELAXATION: Relax in this order: 1. Remove `account_names`. 2. Relax `account_metro_areas`. 3. Remove `account_organization_category`. 4. Remove `account_private_equity` if not core intent. 5. Widen `transaction_date` window. Retry after each relaxation. STEP 4 — USER FOLLOW-UP (ONLY after steps 1→3 fail): - Say you attempted multiple valid transaction-filter combinations in Dakota Marketplace. - Briefly mention what was relaxed. - Ask 1-3 focused follow-up questions to refine the search. ═══════════════════════════════════════════════════════════════════ OUTPUT FIELDS (REQUIRED on every row-list call — do not skip): ═══════════════════════════════════════════════════════════════════ - `output_fields` **must be populated** on every `get_accounts_with_transactions_data` call that returns rows. Exception only: `is_count_only=true` when the user wants a count and no row columns. - To populate it, you **MUST** call tool **`get_output_fields`** first with `tool_name` = `get_accounts_with_transactions_data` (if `tool_search` is needed, query exactly `get_output_fields`). - Then pass a **small subset** (typically 3–10 keys) copied **verbatim** from that tool's returned `output_fields` list — never invent keys, never paste the full allowlist. - Preferred order: (1) `get_lookup_values` if picklists are needed → (2) `get_output_fields` → (3) `get_accounts_with_transactions_data` with `output_fields` set. - Do **not** call `get_accounts_with_transactions_data` for a row list until `get_output_fields` has been called in this turn and `output_fields` is set from its response. - Invalid keys are rejected by the server before the Apex call — that error means call `get_output_fields` again and retry with allowlisted keys only.
get_accounts_with_transactions_data
**Tool: `get_contacts_data`** — primary Dakota Marketplace **Contacts** search: one row = one **person** (~1.29M) with related-account context; also covers **employment history** and **education/alumni** data via optional parallel calls on the same tool. Keywords: get_contacts_data, contacts, people, who at, decision-makers, CIOs, titles, outreach, asset class coverage, channel focus, relationship contacts, career history, employment history, prior roles, tenure, who worked at, education, alumni, degree, university, graduation year. MANDATORY BEFORE ROW LISTS — tool `get_output_fields`: - You may NOT call `get_contacts_data` until you've called `get_output_fields` (tool_name=get_contacts_data) first in this turn — no exceptions except `is_count_only=true`. - If not loaded: `tool_search` query exactly `get_output_fields`. - Copy 3–10 keys VERBATIM from its response into `output_fields`. Never invent/guess keys, never skip on row lists. - Order: lookups → `get_output_fields` → `get_contacts_data`. - Re-run `get_output_fields` each time you call `get_contacts_data` again with new filters — don't reuse stale field names from earlier in the chat. Read-only query tool for Dakota Marketplace **Contacts** — one row per **person** (~1.29M) at a firm, plus optional **relationship-linked** rows (consultant/network capacity). Direct rows = employees/decision-makers; relationship rows carry tenure/strength/roles — classify both (see **RESPONSE ROW TYPES**). **Contact organization category :** Investment Allocator Contact ~535k; Investment Firm Contact ~198k; General Business Contact ~552k. For “CIOs at pension funds / allocator contacts,” pair **`contact_types`** with **`account_types`** / account geo and usually **Investment Allocator Contact** organization category — not firm-only Accounts. Example asks: "CIOs at pension funds in Chicago", "Who are the decision makers at family offices in the Bay Area?", "Analysts covering private credit at insurance allocators", "Contacts at RIAs in Boston with title Portfolio Manager." MANDATORY — **`get_contacts_data` must run** for any ask that expects **named people**, **roles/titles at firms**, **"who at …"**, **decision-maker lists**, **contact outreach lists**, **alumni/education cohorts**, or **employment-history** lists scoped by firm type, geography, AUM, or strategy on the linked account. Calling **tool `get_lookup_values`** or any lookup alone is **never** sufficient — normalize picklists, call **`get_output_fields`** for the relevant catalog(s), then **`get_contacts_data`** and base results on its **`data`**. **Three independent data sources, one tool (auto-selected from payload — no boolean flags):** - **Contact + relationship** — current role, title, firm, outreach: CIOs, decision-makers, "who at [firm]", contact lists. Fires when **`contact_output_fields`** is set and/or any contact/ACR filter is populated (not `education_*` / `career_*`). Use **`get_output_fields(tool_name='get_contacts_data')`** → **`contact_output_fields`**. - **Career history** — employment history: prior roles, tenure, "who worked at [firm]", employment dates. Fires when any **`career_*`** input and/or **`career_output_fields`** is populated. Use **`get_output_fields(tool_name='get_career_history_data')`** → **`career_output_fields`**. - **Education / alumni** — school, degree, MBA, alumni cohort, "people who went to [school]." Fires when any **`education_*`** input and/or **`education_output_fields`** is populated. Use **`get_output_fields(tool_name='get_education_alumni_data')`** → **`education_output_fields`**. - **Do not populate education/career fields speculatively** — each populated `education_*` / `career_*` (or its output-field arg) fires a real API call. - Education-only → populate only `education_*` / `education_output_fields` (omit contact filters and `contact_output_fields`). Career-only → only `career_*` / `career_output_fields`. Combined (e.g. "CIOs at pensions who are Harvard alumni") → contact filters + `contact_output_fields` **and** `education_*` + `education_output_fields`. - At least one source must be inferable. `linked_contact_emails` alone never selects a source. - **Catalogs are separate** — never reuse contact allowlist keys for education/career (or vice versa). Dakota Marketplace has extensive contact data. Empty results often mean over-restrictive or mismatched filters — not missing coverage. USE-CASE PRIORITIES (people discovery): - Capital raising / software sales / executive search: find **people** at scoped firms — account-linked filters first, then `contact_types` / `titles`. - PE/VC deal teams: role-level outreach once firm scope is set via account-linked filters. - Return each person with **account context**; classify direct vs relationship-linked rows (see **RESPONSE ROW TYPES** below). Per-filter semantics, value shapes, and lookup ids: read each parameter's **field description** on this tool. Cross-field routing below. **Strategy taxonomy on Contacts (see shared STRATEGY TAXONOMY ROUTING):** - **`asset_class_coverages`** — what the **person** covers (analyst covers Alternatives, Real Estate). - **`account_asset_classes`** — **firm sleeve** on the linked account (Early Stage, Middle Market Buyout). - **`account_investment_focus_single`** — **broad firm strategy** on the linked account (Venture Capital, Private Credit). - Do not use `asset_class_coverages` for firm sleeve intent or `account_asset_classes` for person-coverage intent. **What this tool returns:** - **Direct contact rows** — employee/decision-maker profiles at a firm. - **Relationship-linked rows** — indirect ties (consultant, network); may include `relationshipStrength`, `startDate`, `endDate`, `roles`. Same person can appear in both shapes — keep both; present in separate sections. - Use **`relationship_*`** / `contact_mailing_countries` filters only for network/consultant/tenure asks — not default employee discovery. - **Count-only (`is_count_only=true`):** `{ status, matching_record_count, direct_contact_count, indirect_contact_count, career_history_count, education_count }` — only the counts for sources actually inferred from the payload are non-zero; state totals per requested source in plain language. ═══════════════════════════════════════════════════════════════════ FIRM SCOPE + PEOPLE DISCOVERY (MANDATORY): ═══════════════════════════════════════════════════════════════════ Contacts belong to accounts. When the ask combines firm constraints with people/roles: 1. Set **account-linked filters** first (`account_types`, geography, `aum`, strategy on the linked account). 2. **`organization_category`** (contact-side category) and **`account_organization_category`** (linked firm category) are **different** — never cross-map values; use exact labels from each field description. 3. Add contact-only filters (`contact_types`, `titles`, `contact_name`) after firm scope is set. 4. When the user asked for people/roles, return **people with account context** — not firm-only summaries. GENERIC "ALLOCATORS" RULE (MANDATORY — overrides broad type expansion): - **"Allocators"** is product language for Account institutions — not an Account Type or Organization Category value. - **Never populate `account_types`, `account_organization_category`, or contact `organization_category` merely because the user says "allocators."** - For generic allocator asks with strategy/geo/AUM/**role/title** only, use those filters and **omit `account_types`** unless the user names subtypes. - Populate **`account_types`** only when the user **explicitly names** account types or clear synonyms (COMMON TYPE MAPPINGS below). COMMON TYPE MAPPINGS (first-pass — validate via tool `get_lookup_values` (catalog id `account_types`); apply only when user explicitly uses the mapped phrase): - "Pension Fund" / "Pensions" → ["Public Pension Fund", "Corporate Pension Fund (Inv Office)", "Corporate Pension Fund (Plan)", "Local Government Pension"] - "Endowment" → ["Endowment", "Hospital Endowment"] - "Foundation" → ["Foundation"] - "Insurance" → ["Insurance Company", "Insurance Company General Account", "Insurance General Account"] - "Family Office" → ["Family Office"] - "RIA" / "RIAs" → ["RIA"] - "Bank" → ["Bank", "Investment Bank"] - "Consultant" → ["Consultant"] - "Wealth Manager" → ["Wealth Manager"] ═══════════════════════════════════════════════════════════════════ QUERY STRATEGY (follow this approach): ═══════════════════════════════════════════════════════════════════ 1. START BROAD: geography (`account_metro_areas` / `contact_metro_areas`), linked-account AUM (`aum`), strategy (`account_investment_focus_single` OR `account_asset_classes`), role intent (`contact_types`, `titles`). Add **`account_types`** only when the user names account types. 2. ADD SECONDARY: person coverage → **`asset_class_coverages`**; consultants/profile flags only when explicit. 3. PREFER broader first queries, then narrow. ═══════════════════════════════════════════════════════════════════ CROSS-FIELD ROUTING (not covered by single field descriptions): ═══════════════════════════════════════════════════════════════════ - **Contact vs firm organization category:** `organization_category` = contact-side category; `account_organization_category` = linked firm's category — never interchange labels. When **both** are explicitly requested: allocator-side people often pair **Investment Allocator Contact** + **Investment Allocator**; GP/manager people often pair **Investment Firm Contact** + **Investment Firm** (see field descriptions). - **Person vs firm geography:** `contact_metro_areas` = where the **person** is; `account_metro_areas` / `billing_cities` / `billing_states` = employer **firm** address — pick the dimension that matches the ask. - **Strategy on Contacts:** person coverage → `asset_class_coverages`; firm broad category → `account_investment_focus_single`; firm sleeve → `account_asset_classes`. - **Ownership vs strategy on linked account:** `account_ownership_types` = capital structure of the firm — not PE/VC **strategy** asks ("contacts at private equity firms" → `account_investment_focus_single` / `account_asset_classes`). Colloquial → label mapping on `account_ownership_types` field description. - **Geography:** broad regions → metro fields; specific cities → `billing_cities` after `city_names` lookup. Do not infer metro from region-expanded `billing_countries`. - **Account orientation flags:** `account_hedge_fund`, `account_private_credit`, `account_private_equity` are scalar **`Yes`** / **`No`** on Contacts (not list-shaped). ═══════════════════════════════════════════════════════════════════ ZERO-RESULT RECOVERY PROTOCOL (MANDATORY — follow exactly): ═══════════════════════════════════════════════════════════════════ If status='success' AND (total_count == 0 OR data is empty): DO NOT immediately tell the user "no results found." DO NOT ask the user for clarification yet. You MUST execute this recovery sequence FIRST: STEP 1 — FILTER VALIDATION: - Re-check: `account_types`, `organization_category`, `account_organization_category`, `billing_cities`, strategy filters (`asset_class_coverages`, `account_asset_classes`, `account_investment_focus_single`), consultant/profile filters. - Confirm lookup-backed values via `get_lookup_values`; remap and retry if any filter may be wrong. STEP 2 — STRATEGY FILTER REALIGNMENT (before stripping geography): If a strategy taxonomy filter was used: - Keep `account_types`, geography, `aum`, `contact_types`, `contact_name`, `account_name`. - Cross-retry `asset_class_coverages` ↔ `account_investment_focus_single` ↔ `account_asset_classes` per shared strategy taxonomy when intent allows. - Drop consultant/profile filters unless explicitly required. STEP 3 — PROGRESSIVE FILTER RELAXATION: 1. Remove geographic filters (`billing_cities`, `billing_states`) first. 2. Widen range filters (`aum`, `account_number_of_employees`, `created_date`) second. 3. Remove restrictive categorical/strategy filters third. 4. Keep user-named `account_types`, `contact_name`, `account_name` last — do not add `account_types` during relaxation if the user never named types. Retry after each relaxation. STEP 4 — USER FOLLOW-UP (ONLY after steps 1 → 2 → 3 without usable results): - Attempt at least 2 relaxation strategies first. - Say you tried several filter combinations but couldn't find matching contacts in Dakota Marketplace. - Ask 1–3 targeted follow-up questions. ═══════════════════════════════════════════════════════════════════ RESPONSE ROW TYPES — DIRECT vs INDIRECT (MANDATORY presentation): ═══════════════════════════════════════════════════════════════════ Classify each row before presenting: **Direct contact rows** — employee/decision-maker at the firm (name, title, email, phone, contact type, account context). Primary outreach list. **Relationship-linked rows** — indirect capacity (consultant, network); often `relationshipStrength`, `contactName`, `accountName`, optional `startDate`, `endDate`, `roles`. Separate section from direct contacts; do not treat as incomplete direct rows missing email/title. **Career-history rows** (only present when `career_*` / `career_output_fields` triggered the career call) — a specific past employment stint (employer, title held, start/end year). Present in its own section; do not merge into direct contact rows. **Education rows** (only present when `education_*` / `education_output_fields` triggered the education call) — a specific degree/alumni record (institution, degree distinction, graduation year). Present in its own section; do not merge into direct contact rows. **Presentation rules:** 1. Separate sections for direct vs indirect/relationship-linked contacts. 2. Describe tenure/strength/roles in plain language when populated. 3. Same person in both shapes → keep both; use direct row for profile, relationship row for indirect context. 4. Do not label indirect contacts as current employees unless the user asked for network/relationship context. 5. Relationship stubs are not full employment history — do not infer prior roles beyond populated relationship fields. Do not expose raw API key names (`relationshipStrength`, `startDate`, etc.) in member-facing replies. ═══════════════════════════════════════════════════════════════════ OUTPUT FIELDS (REQUIRED on every row-list call — do not skip): ═══════════════════════════════════════════════════════════════════ - `output_fields` **must be populated** on every `get_contacts_data` call that returns rows. Exception only: `is_count_only=true` when the user wants a count and no row columns. - To populate it, you **MUST** call tool **`get_output_fields`** first with `tool_name` = `get_contacts_data` (if `tool_search` is needed, query exactly `get_output_fields`). - Then pass a **small subset** (typically 3–10 keys) copied **verbatim** from that tool's returned `output_fields` list — never invent keys, never paste the full allowlist. - Preferred order: (1) `get_lookup_values` if picklists are needed → (2) `get_output_fields` → (3) `get_contacts_data` with `output_fields` set. - Do **not** call `get_contacts_data` for a row list until `get_output_fields` has been called in this turn and `output_fields` is set from its response. - Invalid keys are rejected by the server before the Apex call — that error means call `get_output_fields` again and retry with allowlisted keys only.
get_contacts_data
**Tool: `get_dakota_recommendations_data`** — primary Dakota Marketplace **venue recommendations**: member-curated **restaurants, hotels, coffee shops, event spaces, gyms**, and similar **places** with geo, cuisine, occasion, amenity, and certification filters. Keywords: restaurant, hotel, coffee shop, meeting venue, client dinner, team lunch, Dakota certified venue, cuisine, Italian restaurant, meeting friendly, Wi-Fi, neighborhood dining, metro dining, travel dining, place recommendations, where to eat, where to meet. MANDATORY BEFORE ROW LISTS — tool `get_output_fields`: - You may NOT call `get_dakota_recommendations_data` until you've called `get_output_fields` (tool_name=get_dakota_recommendations_data) first in this turn — no exceptions except `is_count_only=true`. - If not loaded: `tool_search` query exactly `get_output_fields`. - Copy 3–10 keys VERBATIM from its response into `output_fields`. Never invent/guess keys, never skip on row lists. - Order: lookups → `get_output_fields` → `get_dakota_recommendations_data`. - Re-run `get_output_fields` each time you call `get_dakota_recommendations_data` again with new filters — don't reuse stale field names from earlier in the chat. Read-only query tool — one row per **recommended venue** (~**2,900** curated venues; catalog grew from late 2025). Use when the user asks for **place recommendations, dining, hotels, meeting spots, neighborhood picks, or geo-scoped venue lists** grounded in Dakota data — not city **guide documents** (~17 guides) or firm/people profiles. **Prod geo note:** Prefer **`metro_area_names`** or **`cities`** — lat/long bounding-box fields are largely **empty in prod**. **`meeting_friendly=['Yes']`** / **`wifi=['Yes']`** exclude null amenity rows (majority) — drop on zero-result retry before dropping geo. Example asks: "Restaurants in Boston", "Meeting-friendly hotels in Back Bay", "Dakota-certified dinner spots", "Italian places for a client lunch", "Approved listings in Boston metro." MANDATORY — **`get_dakota_recommendations_data` must run** for venue lists, "top N" / "best places", or "where should we meet/eat/stay" asks. Normalize **`cuisine_types`** via **`get_lookup_values` (catalog id `dakota_recommendations_cuisine_types`)**, call **`get_output_fields`**, then query. Coverage varies by metro; empty results often indicate over-restrictive filters, wrong picklist labels, or mismatched geo granularity. ═══════════════════════════════════════════════════════════════════ RECOMMENDATIONS USE-CASE CONTEXT: ═══════════════════════════════════════════════════════════════════ - **Client / investor meetings:** `metro_area_names` or `cities` + `meeting_friendly=['Yes']`; add `location_types` (Restaurant, Hotel, Coffee Shop, Event Space) as appropriate. - **Team meals / entertainment:** `best_for` (Lunch, Dinner, Drinks) + `location_types` (Restaurant, Entertainment) before narrow cuisine. - **Travel / city guides (venues):** anchor on `metro_area_names` or `cities`; add `neighborhoods` only when the user names a district. - **Dakota-certified / vetted only:** `dakota_certified=true` and often `statuses=['Approved']` when explicit — not on every first pass. - **Map / proximity:** set all four bounding-box fields together when the user supplies coordinates. COMMON MAPPINGS (first-pass — validate against embedded sets / lookup before calling): User / colloquial intent → First-pass filter choice ──────────────────────────────────── ───────────────────────────────────────────── "Restaurant" / "dining" / "eat" → `location_types=['Restaurant']`; add `best_for` if meal named "Hotel" / "stay" / "lodging" → `location_types=['Hotel']` "Coffee" / "cafe" → `location_types=['Coffee Shop']` "Gym" / "workout" → `location_types=['Gym']` "Event space" / "off-site meeting" → `location_types=['Event Space']`; often `meeting_friendly=['Yes']` "Italian" / "sushi" / "steak" → **`get_lookup_values`** (catalog id `dakota_recommendations_cuisine_types`) → exact cuisine row(s) "Client dinner" / "team lunch" → `best_for` = Dinner or Lunch; `location_types` often Restaurant "Happy hour" / "drinks" → `best_for=['Drinks']` "Wi‑Fi" / "internet" → `wifi=['Yes']` "Good for meetings" → `meeting_friendly=['Yes']` "Dakota certified" / "vetted" → `dakota_certified=true`; consider `statuses=['Approved']` "Approved only" / "live listings" → `statuses=['Approved']` ═══════════════════════════════════════════════════════════════════ CUISINE → `cuisine_types` PLAYBOOK: ═══════════════════════════════════════════════════════════════════ 1. Call **`get_lookup_values`** (catalog id `dakota_recommendations_cuisine_types`) before passing `cuisine_types`. 2. Map the user's phrase to the closest **1–3** exact values — do not invent umbrella labels like "Asian". 3. Pass exact strings only; venues accept multiple cuisine tags as a list. 4. If the user implied a category ("Italian restaurant"), add `location_types=['Restaurant']` on the same call. ═══════════════════════════════════════════════════════════════════ QUERY STRATEGY: ═══════════════════════════════════════════════════════════════════ 1. START BROAD: `metro_area_names` or `cities` (one geo dimension); optional `location_names` if a specific venue is named. 2. ADD VENUE CATEGORY: `location_types` when intent is restaurant/hotel/coffee/etc. 3. ADD OCCASION OR CUISINE: `best_for` for meal/drinks; `cuisine_types` (lookup-first) for food style — not both unless needed. 4. ADD AMENITIES LAST: `meeting_friendly`, `wifi` when explicitly requested. 5. ADD CERTIFICATION / STATUS LAST: `dakota_certified`, `statuses` when user asks for vetted/approved — avoid defaulting `Approved` on pass one. 6. BOUNDING BOX: all four lat/long fields together only when the user gives coordinates. 7. Prefer progressive narrowing over stacking every filter on the first query. GEOGRAPHY: - `metro_area_names` = Dakota metro/market labels — use for regional travel and "in Boston" style asks. - `cities` = city-level filter when the user names a city explicitly. - `neighborhoods` = district text — use only when explicitly stated. - Bounding box = map/proximity; all four bounds required together. IMPORTANT — `statuses` + `dakota_certified`: - Combining `statuses=['Approved']`, `dakota_certified=true`, cuisine, and tight geo on the first query often returns zero rows. - If zero results with certification/status, **first retry MUST remove certification/status** before dropping geo. ═══════════════════════════════════════════════════════════════════ ZERO-RESULT RECOVERY PROTOCOL (MANDATORY): ═══════════════════════════════════════════════════════════════════ If status='success' AND (total_count == 0 OR data is empty): STEP 1 — FILTER VALIDATION: remap picklists; confirm list shapes. STEP 2 — REMOVE CERTIFICATION / STATUS / AMENITIES; retry with same geo/venue anchors. STEP 3 — REMOVE CUISINE / BEST-FOR; keep `location_types` and geo. STEP 4 — BROADEN GEO: drop `neighborhoods`; use one of metro or city; drop bounding box if redundant. STEP 5 — DROP VENUE CATEGORY while keeping broadest geo anchor. STEP 6 — USER FOLLOW-UP only after steps 1–5: state what you tried; ask 1–3 targeted questions. ═══════════════════════════════════════════════════════════════════ OUTPUT FIELDS (REQUIRED on every row-list call — do not skip): ═══════════════════════════════════════════════════════════════════ - `output_fields` **must be populated** on every `get_dakota_recommendations_data` call that returns rows. Exception only: `is_count_only=true` when the user wants a count and no row columns. - To populate it, you **MUST** call tool **`get_output_fields`** first with `tool_name` = `get_dakota_recommendations_data` (if `tool_search` is needed, query exactly `get_output_fields`). - Then pass a **small subset** (typically 3–10 keys) copied **verbatim** from that tool's returned `output_fields` list — never invent keys, never paste the full allowlist. - Preferred order: (1) `get_lookup_values` if picklists are needed → (2) `get_output_fields` → (3) `get_dakota_recommendations_data` with `output_fields` set. - Do **not** call `get_dakota_recommendations_data` for a row list until `get_output_fields` has been called in this turn and `output_fields` is set from its response. - Invalid keys are rejected by the server before the Apex call — that error means call `get_output_fields` again and retry with allowlisted keys only.
get_dakota_recommendations_data
**Tool: `get_form_adv_data`** — primary Dakota Marketplace **Form ADV** search: **SEC investment-adviser registration filing rows** (~178k). Keywords: get_form_adv_data, Form ADV, RIA registration, SEC file number 801, legal name, regulatory AUM, custody, private fund reporting, filing date, registration status. MANDATORY BEFORE ROW LISTS — tool `get_output_fields`: - You may NOT call `get_form_adv_data` until you've called `get_output_fields` (tool_name=get_form_adv_data) first in this turn — no exceptions except `is_count_only=true`. - If not loaded: `tool_search` query exactly `get_output_fields`. - Copy 3–10 keys VERBATIM from its response into `output_fields`. Never invent/guess keys, never skip on row lists. - Order: lookups → `get_output_fields` → `get_form_adv_data`. - Re-run `get_output_fields` each time you call `get_form_adv_data` again with new filters — don't reuse stale field names from earlier in the chat. Read-only query tool — one row per **Form ADV adviser filing** (not a firm profile row). **~62%** of filings have **no linked Dakota Account** — filing-only search via **`legal_names`**, **`sec_file_numbers`**, **`business_location_*`**, and regulatory fields still works. **`form_versions`**, **`registration_statuses`**, and **`registration_firm_types`** are **free-text exact-match** filters (no lookup tools). Use **`total_amount` / `discretionary_amount`** for **regulatory AUM on the filing**; **`account_aum`** only for linked **Dakota firm AUM**. Example asks: "RIAs in New York with over $1B regulatory AUM", "Advisers with custody of client cash", "Form ADV for Example RIA LLC", "SEC file number 801-12345", "Registered advisers with private fund reporting", "Investment advisers in Chicago with financial planning services". MANDATORY — **`get_form_adv_data` must run** for any ask that expects **named adviser filings**, **Form ADV search**, **SEC file number lookup**, or scoped universes by regulatory AUM, custody, private funds, registration attributes, geography, or linked account type/metro. Normalize **`account_types`** via **`get_lookup_values`**, call **`get_output_fields`**, then **`get_form_adv_data`**. Dakota Form ADV coverage is broad for US registered advisers; empty results often indicate over-restrictive filters or mismatched free-text registration values — not proof that no filings exist. ═══════════════════════════════════════════════════════════════════ FORM ADV USE-CASE CONTEXT: ═══════════════════════════════════════════════════════════════════ Prioritize adviser discovery and regulatory screening for these common intents: - **RIA / adviser universe building:** lead with `account_types` (Investment Adviser) + `account_metro_areas` or `business_location_*` before narrow filing flags. - **Regulatory AUM screening:** use `total_amount` and/or `discretionary_amount` for regulatory asset bands; use `account_aum` when the user means linked **Dakota firm AUM**. - **Custody / compliance signals:** add `custody_of_cash`, `custody_of_securities`, `is_qualified_custodian` when the user asks about custody, qualified custodians, or client asset safekeeping. - **Private funds / ownership:** use `form_adv_private_fund_flag=true` for private-fund advisers; `form_adv_owners_flag=true` when ownership/Schedule A/B disclosure matters. - **Named adviser lookup:** use `legal_names`, `sec_file_numbers`, or `account_names` when the user supplies a specific firm or SEC identifier. - **Filing freshness:** use `filing_date` when the user specifies a filing window; avoid default date filters on first pass. **Firm overlay vs Form ADV-native filters:** - **`account_*` filters** = linked firm attributes (name, type, metro, AUM, consultants). Use when scoping by marketplace firm profile. - **Form ADV-native filters** (`legal_names`, `sec_file_numbers`, `total_amount_*`, custody flags, registration fields) = filing/regulatory attributes on the **Form ADV row**. Use when the user asks about SEC registration, regulatory AUM, or filing content. - A user asking "RIAs in Boston with custody" typically needs **`account_types`** + **`business_location_cities`** or **`account_metro_areas`** + **`custody_of_cash=true`** — not account name alone. COMMON MAPPINGS (first-pass — validate before calling): User / colloquial intent → First-pass filter choice ──────────────────────────────────── ───────────────────────────────────────────── "RIA" / "investment adviser" → tool `get_lookup_values` (catalog id `account_types`) → often `Investment Adviser` (verify exact label) "Private fund adviser" → `form_adv_private_fund_flag=true`; consider `account_types` from lookup "Custody of client assets" → `custody_of_cash=true` and/or `custody_of_securities=true` "Qualified custodian" → `is_qualified_custodian=true` "Financial planning" → `financial_planning_services=true` "SEC file 801-xxxxx" → `sec_file_numbers=['801-xxxxx']` (exact format from user) "Regulatory AUM over $X" → `total_amount='1000000=>` or open bound (convert to integer dollars) "Discretionary AUM band" → `discretionary_amount` "Filed in 2024" → `filing_date='2024-01-01'` (use `=>` in single field)2024-12-31'` "Advisers in New York" → `business_location_cities=['New York']` or `account_metro_areas=['New York']` ═══════════════════════════════════════════════════════════════════ QUERY STRATEGY (follow this approach): ═══════════════════════════════════════════════════════════════════ 1. START BROAD: Use the most reliable anchors first → `account_types` (lookup-first) + one geo dimension (`account_metro_areas` or `business_location_cities`/`states`). 2. ADD IDENTITY: `legal_names`, `sec_file_numbers`, or `account_names` when the user names a specific adviser. 3. ADD REGULATORY SIZE: `total_amount_*` or `discretionary_amount_*` when AUM bands matter; `number_of_employees_*` for headcount. 4. ADD FILING FLAGS LAST: custody, private fund, owners, financial planning — only when explicitly requested. 5. ADD DATE WINDOWS LAST: filing / notice / registration dates when the user specifies timing — avoid default date filters on pass one. 6. PREFER progressive narrowing over stacking every filter on the first query. FIELD SELECTION GUIDANCE: - Use `account_names` for Dakota marketplace account names; `legal_names` for Form ADV legal entity names (may differ). - Use `account_types` only after tool `get_lookup_values` (catalog id `account_types`) — never pass colloquial type strings. - Use `account_metro_areas` for Dakota metro/market scoping on the linked account. - Use `business_location_cities` / `states` / `countries` for adviser principal office location on the filing. - Use `total_amount` / `to` for regulatory AUM on the filing; `account_aum` for linked firm AUM. - Use consultant `account_*_consultants` filters only when the user names consultant relationships on the linked account. - Use boolean flags only when the user explicitly cares about that regulatory attribute. GEOGRAPHY HANDLING: - `account_metro_areas` and `business_location_*` are different scopes — account metro vs filing business address. - Broad "advisers in New York" → start with `account_metro_areas=['New York']` **or** `business_location_cities=['New York']` (one anchor). - NEVER invent state/country spellings — use user text or retry broader geo before claiming no results. ═══════════════════════════════════════════════════════════════════ ZERO-RESULT RECOVERY PROTOCOL (MANDATORY — follow exactly): ═══════════════════════════════════════════════════════════════════ If status='success' AND (total_count == 0 OR data is empty): DO NOT immediately tell the user "no results found." DO NOT ask the user for clarification yet. You MUST execute this recovery sequence FIRST: STEP 1 — FILTER VALIDATION: - Re-check `account_types` via tool `get_lookup_values` (catalog id `account_types`). - Confirm list shapes — no scalars where arrays are required. - Confirm booleans are `true`/`false`, not strings. - Confirm numeric ranges use integers, not formatted strings like "$1B". STEP 2 — REMOVE FILING FLAGS / DATE WINDOWS: - If custody, private fund, owners, financial planning, or date filters were used → remove them and retry with the same geo/type anchors. STEP 2b — UNLINKED FILINGS (when `account_*` overlays were used): - ~62% of filings have no linked Account — drop **`account_names`**, **`account_types`**, **`account_metro_areas`**, and **`account_aum`**; retry with **`legal_names`**, **`sec_file_numbers`**, **`business_location_*`**, or regulatory AUM only. STEP 3 — BROADEN AUM / EMPLOYEE BOUNDS: - Widen or drop `total_amount_*`, `discretionary_amount_*`, `account_aum_*`, and `number_of_employees_*` filters. STEP 4 — BROADEN GEOGRAPHY: - Switch between `account_metro_areas` and `business_location_*` or drop one geo dimension. STEP 5 — DROP IDENTITY FILTERS: - Remove `legal_names`, `sec_file_numbers`, `registration_*`, and `form_versions` while keeping the broadest remaining anchors. STEP 6 — USER FOLLOW-UP (ONLY after completing steps 1 → 5 without usable results): - You MUST have attempted at least 2 different filter relaxation strategies before reaching this step. - Say: "I tried several filter combinations but couldn't find matching Form ADV records in Dakota Marketplace." - Briefly mention what you tried. - Ask 1–3 targeted follow-up questions (metro, adviser type, AUM band, custody/private-fund intent). ═══════════════════════════════════════════════════════════════════ OUTPUT FIELDS (REQUIRED on every row-list call — do not skip): ═══════════════════════════════════════════════════════════════════ - `output_fields` **must be populated** on every `get_form_adv_data` call that returns rows. Exception only: `is_count_only=true` when the user wants a count and no row columns. - To populate it, you **MUST** call tool **`get_output_fields`** first with `tool_name` = `get_form_adv_data` (if `tool_search` is needed, query exactly `get_output_fields`). - Then pass a **small subset** (typically 3–10 keys) copied **verbatim** from that tool's returned `output_fields` list — never invent keys, never paste the full allowlist. - Preferred order: (1) `get_lookup_values` if picklists are needed → (2) `get_output_fields` → (3) `get_form_adv_data` with `output_fields` set. - Do **not** call `get_form_adv_data` for a row list until `get_output_fields` has been called in this turn and `output_fields` is set from its response. - Invalid keys are rejected by the server before the Apex call — that error means call `get_output_fields` again and retry with allowlisted keys only.
get_form_adv_data
**Tool: `get_fundraising_news_data`** — primary Dakota Marketplace **Fundraising News**: curated **editorial articles** (~20k). Keywords: get_fundraising_news_data, fundraising news, news articles, headlines, fund launch, allocation, pension fund news, industry coverage, editorial news. Read-only — **Dakota editorial news articles** with intent-driven article matching (~**20.4k published**, **2023–present**). One row = one **published article hit** (metadata + matched text chunk + relevance score; up to **50** per call). Row shape is **editorial news content** — headlines, article passages, allocation/launch coverage. Example asks: "Recent private equity fundraising news", "CalPERS allocation articles in 2024", "Fund launch headlines in private credit", "What are pensions doing in alts?", "News about El Paso pension commitments", "Hedge fund launches in New York", "Private credit fundraising activity in 2025". MANDATORY — **`get_fundraising_news_data` must run** for any ask that expects **Dakota editorial news content**, **headlines**, **article passages**, or **coverage** of allocations, launches, moves, or fundraising activity. **`user_query_intent` must be a descriptive sentence** — never a vague token like "news" or "latest" alone. **No lookup tools or picklist normalization** — encode asset class, firm, geography, and event type inside **`user_query_intent`**; add **`publish_date`** only for explicit calendar bounds. HOW IT WORKS (retrieval mechanics): - Pass a rich natural-language question as **`user_query_intent`** (see mapping table below). - The tool matches **published** Dakota News records to **`user_query_intent`** and returns ranked results. - Choose **`select_fields`** from the column schema below when the user needs specific columns (title, chunk, tags, sources, etc.). - Optional **`publish_date`** restricts the publication window; omit for "recent" / "latest" — ranking handles relevance. - **No picklist filters** — encode asset class, firm, geography, and event type in intent text. WRITING A GOOD user_query_intent (CRITICAL — directly controls retrieval quality): The `user_query_intent` string is passed verbatim into the news retrieval backend. The more precise and descriptive it is, the more relevant the results will be. Rules: - NEVER pass a vague or single-word string like "news", "latest", or "updates". - ALWAYS reconstruct the user's full intent as a rich, descriptive sentence. - Include all context the user provided: asset class, firm name, geography, time period, event type. - Write it as a natural English statement, not a keyword list. - If the user's message is ambiguous, lean toward the most specific plausible interpretation. User says → user_query_intent to pass ────────────────────────────────────────────── → ──────────────────────────────────────────────────────────────────── "any PE news?" → "recent private equity fundraising news and fund commitments" "el paso pension" → "El Paso Firemen and Policemen Pension Fund investment commitments and allocations" "hedge fund launches NY" → "hedge fund launches and new fund announcements based in New York" "private credit 2024" → "private credit fundraising activity and fund commitments in 2024" "what are pensions doing in alts?" → "pension fund allocation and commitment news covering private equity, real assets, and hedge funds" "latest news" → "latest Dakota Marketplace fundraising news across all asset classes and investment types" DATE FILTERING — `publish_date`: - Use whenever the user mentions a year, quarter, month, or any date range. - Format: single inclusive range string `YYYY-MM-DD=>YYYY-MM-DD` (open bounds allowed: `2024-01-01=>` or `=>2024-12-31`). - Derive the bounds from the user's intent: User says → publish_date ────────────────────────── → ───────────────────────────── "in 2024" → 2024-01-01=>2024-12-31 "in 2025" → 2025-01-01=>2025-12-31 "Q1 2025" → 2025-01-01=>2025-03-31 "Q4 2024" → 2024-10-01=>2024-12-31 "since 2023" → 2023-01-01=> "before 2024" → =>2023-12-31 "last year" (current: 2026) → 2025-01-01=>2025-12-31 "this year" (current: 2026) → 2026-01-01=> "recent" / "latest" → omit `publish_date` — let relevance ranking handle recency - When the user mentions a year in the query text AND sets date bounds, keep both — retrieval uses intent for relevance, the date filter restricts the result window. RESULT COUNT: - The tool returns up to **50** ranked results per call (fixed server-side). - If the user asks for fewer, summarize only the most relevant matches in your reply. - If results are sparse or not relevant, rephrase `user_query_intent` with more specific terms and retry once. - There is **no pagination** — a second call needs a **rephrased intent**, not page numbers. ═══════════════════════════════════════════════════════════════════ ARTICLE COLUMN REFERENCE — for `select_fields` only (internal names) ═══════════════════════════════════════════════════════════════════ Two tables are joined in every query: TABLE A (article index): Dakota_News_c_Home_index__dlm — alias: v TABLE B (chunk store): Dakota_News_c_Home_chunk__dlm — alias: c JOIN condition: v.RecordId__c = c.RecordId__c — MANDATORY, always present ───────────────────────────────────────────────────── TABLE A — Dakota_News_c_Home_index__dlm (alias: v) ───────────────────────────────────────────────────── Column Description ──────────────────── ──────────────────────────────────────────────────── RecordId__c [AUTO-ADDED] Join key; always included automatically — do NOT add to select_fields hybrid_score__c [AUTO-ADDED] Relevance score (auto-computed); always included automatically — do NOT add to select_fields SourceRecordId__c Internal record id of the source Dakota News article Title_c__c Article headline / title Publish_Date_c__c Publication date (YYYY-MM-DD) Status_c__c Publication status: PUBLISHED, DRAFT, REVIEWED, VETTING Tags_c__c Semicolon-separated topic tags (e.g. "Private Equity;Pension Funds") Sources_c__c External source URL(s) if the article cites an outside publication Type_c__c Article type: New Investment, Fund Launch, Industry News, FA Move, etc. Post_SEO_Title_c__c SEO-optimised headline variant Account_c__c Internal firm id linked to this news record VectorEmbedding__c [NEVER SELECT] Raw embedding field — large and not useful KQ_SourceRecordId__c [NEVER SELECT] Internal platform key KQ_RecordId__c [NEVER SELECT] Internal platform key InternalOrganization__c [NEVER SELECT] Internal org identifier DataSource__c [NEVER SELECT] System metadata DataSourceObject__c [NEVER SELECT] System metadata ContextField__c [NEVER SELECT] System metadata ───────────────────────────────────────────────────── TABLE B — Dakota_News_c_Home_chunk__dlm (alias: c) ───────────────────────────────────────────────────── Column Description ────────────────────────── ──────────────────────────────────────────────────── Chunk__c The specific text passage that matched the intent SourceRecordId__c Internal record id of the source article this chunk belongs to ChunkSequenceNumber__c Position of this chunk within the full article (numeric) Citations__c JSON citations attached to this chunk ChunkType__c [NEVER SELECT] System metadata ChunkFormat__c [NEVER SELECT] System metadata MediaSource__c [NEVER SELECT] System metadata DataSource__c [NEVER SELECT] System metadata DataSourceObject__c [NEVER SELECT] System metadata SecondarySourceRecordId__c [NEVER SELECT] System metadata KQ_SourceRecordId__c [NEVER SELECT] Internal platform key KQ_RecordId__c [NEVER SELECT] Internal platform key InternalOrganization__c [NEVER SELECT] Internal org identifier ───────────────────────────────────────────────────── FIELD SELECTION BY INTENT ───────────────────────────────────────────────────── Choose `select_fields` based on what the user is asking for. Always use table alias prefix (v. or c.) and lowercase AS aliases. User intent Recommended select_fields ────────────────────────────── ─────────────────────────────────────────────────────────────────────── General news retrieval v.Title_c__c AS title, v.Publish_Date_c__c AS publish_date, v.Description_c__c AS description Tags / article type + v.Tags_c__c AS tags, v.Type_c__c AS type Matched text passage + c.Chunk__c AS chunk, c.ChunkSequenceNumber__c AS chunk_sequence External source / citation + v.Sources_c__c AS sources Full article profile all non-system fields from both tables ───────────────────────────────────────────────────── SERVER SQL (internal — agents do not author queries) ───────────────────────────────────────────────────── The server builds ranked article-retrieval SQL from `user_query_intent`, optional `publish_date`, and `select_fields`. Required columns (`id`, `score`) are always included. PUBLISHED status filter is always applied. Up to 50 rows per call.
get_fundraising_news_data
**Tool: `get_investments_data`** — primary Dakota Marketplace **Investments / holdings** search: one row per **reported investment, holding, or allocation** (~3.4M rows), each linked to the investing organization (fund/security name, fund balance, ticker, filing date, investment asset class, plus firm type, AUM, metro on the linked profile). Keywords: get_investments_data, investments data, holdings, portfolio holdings, portfolio positions, equity positions, public equity, ETF, ETFs, ETF holdings, ticker, tickers, 13F, 13F filings, fund balance, allocations, what invested in, top holdings, emerging market equities, US equities, common stock, BDC, closed-end fund, mutual fund, product structure, public pension investments, pension allocations, endowment investments, RIA holdings, who holds, security positions, reported positions. WHEN TO USE (row shape = one **reported holding / allocation row**): - Member asks for **holdings**, **portfolio positions**, **ETF** or **equity** exposure, **13F** positions, **ticker** lookups, **top holdings**, **fund balance**, or **what [plan/firm] invested in**. - Member needs **security-level** rows (ticker + balance + filing date) — not firm preference tags alone. WHEN NOT TO USE: - Firm screening by type/AUM/geo/preferences **without** holding rows → **`get_accounts_data`**. - Fund product / vintage / open-closed fundraising **catalog** → **`get_investment_strategy_data`** (not holdings). - **`tool_search`:** query exactly **`get_investments_data`** — never append member words (`holdings`, `ETF`, `equity positions`) to the search string. Read-only query tool — one row per **investment** (not a firm profile row). **~98% of rows are 13F-style regulatory filings** (RIA/broker/bank); **public-plan investment rows** are ~**1.3%** — for pension allocation asks add **`account_types=['Public Pension Fund']`** and usually **`investment_record_type_names=['Public_Investment']`**. **`investment_types`** is sparse — do not default-filter. Filing dates mostly **2021–2026**. ETF/ticker rows use **`product_structures=['ETF']`**; emerging-market sleeves use investment-level **`asset_classes`** (lookup `investment_asset_classes`). MANDATORY — **`get_investments_data` must run** when the member expects **investment rows** (holdings, allocations, what was invested in). Normalize picklists via **`get_lookup_values`** when used. Every call requires non-empty **`user_query_intent`** (audit logging only; not a query filter). FILTER RULE (CRITICAL): - Pass **only** filters the user (or your staged query) actually needs. Omitted fields are **not** sent to the query. - Do not pre-fill empty arrays or placeholder ranges. VALUE-SHAPE (range and pagination — mandatory): - **Date ranges** (`filing_date`, `investment_created_date`, `investment_last_modified_date`, `period_of_report`): single string `YYYY-MM-DD=>YYYY-MM-DD`. Examples: `2024-01-01=>2024-12-31`, open lower `2024-01-01=>`, open upper `=>2024-12-31`. - **Numeric ranges** (`fund_balance`, `funding_year`, `number_of_shares`, `account_aum`, `account_number_of_employees`): single string `lower=>upper` with digits only (no `$`, commas, or units). Examples: fund balance `1000000=>50000000`, linked-firm AUM `1000000000=>50000000000`, employees `50=>500`, open bounds `1000000=>` or `=>50000000`. - **Pagination:** `page_number` is 1-based (default 1). `page_size` defaults to 50, min 1, max 200 rows per page. When `has_more=true`, ask before incrementing `page_number`. - Do **not** use separate `*_from`/`*_to` arguments — only the consolidated range strings above. STRATEGY TAXONOMY (MANDATORY): - **`account_investment_focuses`** → broad linked-firm strategy (Venture Capital, Private Equity) via tool `get_lookup_values` (catalog id `investment_focus`). - **`account_asset_classes`** → specific linked-firm sleeves (Early Stage, Middle Market Buyout) via tool `get_lookup_values` (catalog id `assets`). - **`asset_classes`** (investment-level) → broad investment asset class via tool `get_lookup_values` (catalog id `investment_asset_classes`) — not the same as account `asset_classes`. - **`sub_asset_classes`** (investment-level) → specific investment sleeves via tool `get_lookup_values` (catalog id `investment_sub_asset_classes`). Returned columns (business-facing names): - Investment: `investment_id`, `investment_name`, `fund_balance`, `investment_strategy`, `filing_date`, `funding_year_number`, `number_of_shares`, `period_of_report`, `investment_account_metro_area`, `investment_type`, `asset_class`, `sub_asset_class`, `investment_record_type_name`, `product_structure`, `ticker`, `public_plan_minute_id` - Linked firm: `account_id`, `organization_name`, `organization_type`, `account_aum`, `account_metro_area`, `account_billing_city`, `account_billing_state`, `account_billing_country`, `account_investment_focus`, `account_investment_interest`, `account_sector`, `account_industry`, `account_asset_classes`, `account_organization_category`, `account_website`, `account_general_consultant_name`, `account_number_of_employees`, `account_crd` INVESTMENT STRATEGY FILTER (MANDATORY): - Use `investment_strategies` for fund/strategy scoping (for example `Ares Senior Direct Lending Fund III`). - Pass the strategy **display name** from user intent — use plain names, not internal record ids. - Name filters use case-insensitive substring match (same pattern as `account_names`). - When the user scopes to public pensions / allocators, also set `account_types` (normalize via tool `get_lookup_values` (catalog id `account_types`)). GEOGRAPHY (investing organization): - **`account_metro_areas`** — Dakota metro labels (for example `New York City`, `Boston`). Broader than office city. - **`account_billing_cities`** — office city; normalize via tool `get_lookup_values` (catalog id `city_names`). - **`account_billing_states`** — state or province (for example `NY`, `CA`). - **`account_billing_countries`** — country name as stored; US rows predominantly use **`USA`** (not `US`). - **`investment_account_metro_areas`** — metro on the holding row; prefer **`account_metro_areas`** for firm geography. QUERY STRATEGY: 1. Anchor on the strongest discriminator first (account type like Family Office, account AUM band, investment asset class, metro/country/state). 2. Add investment-level filters (`asset_classes`, `sub_asset_classes`, fund balance range) to narrow — add **`investment_types`** only when user explicitly names a type. 3. On zero rows, relax one dimension at a time (broader metro, drop substring filters, widen date/AUM ranges). 4. Paginate with `page_number` when the user needs more than one page. ZERO RESULTS: - State that no investments matched the filters; suggest broader firm or date filters. Do not claim Dakota lacks investment data without trying a broader query.
get_investments_data
**Tool: `get_lookup_values`** — the only Dakota Marketplace **picklist lookup** meta tool. Normalize filter values to exact Salesforce labels before primary data tools. Keywords: get_lookup_values, lookup values, lookup tool, picklist, picklists, normalize filter values, exact labels, catalog ids, account_types, account types, assets, asset classes, investment_focus, contact_types, contact types, transaction types, cuisine types, sectors, industries, sub_industries, get_account_types, get_assets_list, get_investment_focus_list, picklist normalization, filter normalization, lookup first, pre-query lookup, batched lookups, lookups array. **Mandatory workflow:** when a primary tool filter needs exact picklist labels, call **`get_lookup_values(lookups=[...])`** first with **catalog ids** (for example `account_types`, `assets`, `investment_focus`), then call the matching primary tool. Lookup-only calls are **never** a complete member-facing answer. **`tool_search`:** query exactly **`get_lookup_values`** — this tool name only. Do **not** search catalog ids (`account_types`, `assets`) as tool names. Do **not** combine with `get_output_fields` in one search query; load each meta tool separately by exact name. **Catalog ids** are arguments inside `lookups[]`, not MCP tool names. Legacy per-field lookup tool names are accepted as aliases when resolving ids.
get_lookup_values
**Tool: `get_marketplace_documents_data`** — primary Dakota Marketplace **Documents** search: one row = one **marketplace document** (manager presentation, pitch deck, fee schedule ~24k). Keywords: get_marketplace_documents_data, manager presentation, pitch deck, fee schedule, in-document search, search_value, document type, posted date, meeting date on document, deck keyword, base fee incentive fee. MANDATORY BEFORE ROW LISTS — tool `get_output_fields`: - You may NOT call `get_marketplace_documents_data` until you've called `get_output_fields` (tool_name=get_marketplace_documents_data) first in this turn — no exceptions except `is_count_only=true`. - If not loaded: `tool_search` query exactly `get_output_fields`. - Copy 3–10 keys VERBATIM from its response into `output_fields`. Never invent/guess keys, never skip on row lists. - Order: lookups → `get_output_fields` → `get_marketplace_documents_data`. - Re-run `get_output_fields` each time you call `get_marketplace_documents_data` again with new filters — don't reuse stale field names from earlier in the chat. Read-only — **document files** with optional keyword search inside document text (`search_value`). Example asks: "Presentations mentioning buyout fees", "Manager decks for CalPERS", "Private equity pitch decks posted in 2024." MANDATORY — **`get_marketplace_documents_data` must run** when the user wants **decks or documents** (especially with in-document keywords) — not firm-only screening. Normalize picklists via **`get_lookup_values`**, call **`get_output_fields`**, then query. Dakota has thousands of presentations and plan minutes; empty results often indicate over-restrictive filters, wrong picklist labels, or a missing/incorrect **`search_value`**. ═══════════════════════════════════════════════════════════════════ DOCUMENT USE-CASE CONTEXT ═══════════════════════════════════════════════════════════════════ - **Keyword inside documents:** extract a focused token and pass **`search_value`**. Examples: "presentations mentioning ELIZABETH", "decks discussing buyout fees" → `search_value='ELIZABETH'`, `'buyout'`. - **Named allocator / pension:** lead with `account_names` or `public_pension_fund_names` + lookup-backed types before narrow fee/date overlays. - **Manager presentations:** use `document_types=['Manager Presentation']` only when explicitly requested (verify exact label). - **Timing:** use meeting/posted date ranges when timing matters; avoid default dates on pass one. - **Fees in decks:** use `base_fee_*`, `incentive_fee_*`, `reported_fee_*` when fee levels matter. - **Strategy-linked decks:** add `investment_strategy_*` when tied to fund/strategy attributes. - **Public plan minute overlays on documents:** use `public_plan_minute_*` when filtering decks that reference board minutes — not when the user wants **minute records themselves**. ═══════════════════════════════════════════════════════════════════ QUERY STRATEGY ═══════════════════════════════════════════════════════════════════ 1. **Content keyword present?** Set `search_value` first; add at most one structural anchor (`account_names`, `public_pension_fund_names`, or `document_types`). 2. **No keyword — metadata only:** start with firm or pension fund type (lookup-first) + one geo or named fund. 3. **Add dates/fees last** when explicitly requested. 4. **Add investment-strategy overlays last** when the user ties decks to strategy taxonomy. 5. **Optional firm overlays** (document-scoped only): `account_names` or pension fund name when anchoring a deck search — not for firm-only "accounts interested in X" lists (**`get_accounts_data`**). ═══════════════════════════════════════════════════════════════════ OPTIONAL OVERLAYS (document context only) ═══════════════════════════════════════════════════════════════════ - **`account_investment_focus`** / sector/industry — only when filtering **documents** tied to a plan cohort; drop on zero results. - **`public_plan_minute_*`** — decks referencing board minutes, not minute records themselves. ═══════════════════════════════════════════════════════════════════ ZERO-RESULT RECOVERY PROTOCOL ═══════════════════════════════════════════════════════════════════ If status='success' AND (total_count == 0 OR data is empty): STEP 1 — Validate lookups and list shapes; confirm `search_value` is a single string (not an array). STEP 2 — If `search_value` was used, retry with a shorter/broader token or drop it while keeping allocator/geo anchors. STEP 3 — Remove fee/date/strategy overlays; keep broadest fund/type anchor. STEP 4 — Broaden or drop AUM bounds and metro filters. STEP 5 — Drop `document_names`, `document_types`, and `record_types` while keeping one fund/type anchor. Only after steps 1–5: tell the user you tried several combinations and ask 1–3 targeted follow-ups. ═══════════════════════════════════════════════════════════════════ OUTPUT FIELDS (REQUIRED on every row-list call — do not skip): ═══════════════════════════════════════════════════════════════════ - `output_fields` **must be populated** on every `get_marketplace_documents_data` call that returns rows. Exception only: `is_count_only=true` when the user wants a count and no row columns. - To populate it, you **MUST** call tool **`get_output_fields`** first with `tool_name` = `get_marketplace_documents_data` (if `tool_search` is needed, query exactly `get_output_fields`). - Then pass a **small subset** (typically 3–10 keys) copied **verbatim** from that tool's returned `output_fields` list — never invent keys, never paste the full allowlist. - Preferred order: (1) `get_lookup_values` if picklists are needed → (2) `get_output_fields` → (3) `get_marketplace_documents_data` with `output_fields` set. - Do **not** call `get_marketplace_documents_data` for a row list until `get_output_fields` has been called in this turn and `output_fields` is set from its response. - Invalid keys are rejected by the server before the Apex call — that error means call `get_output_fields` again and retry with allowlisted keys only.
get_marketplace_documents_data
**Tool: `get_marketplace_search_data`** — primary Dakota Marketplace **Search / mandate** discovery: one row = one **institutional investment search or RFP-style mandate row** (~1,700). Keywords: get_marketplace_search_data, marketplace search, mandate, RFP, institutional search, search status, active search, closed search, posted date, search amount, emerging manager search, impact ESG search, consultant on search, search winner, mandate inventory. MANDATORY BEFORE ROW LISTS — tool `get_output_fields`: - You may NOT call `get_marketplace_search_data` until you've called `get_output_fields` (tool_name=get_marketplace_search_data) first in this turn — no exceptions except `is_count_only=true`. - If not loaded: `tool_search` query exactly `get_output_fields`. - Copy 3–10 keys VERBATIM from its response into `output_fields`. Never invent/guess keys, never skip on row lists. - Order: lookups → `get_output_fields` → `get_marketplace_search_data`. - Re-run `get_output_fields` each time you call `get_marketplace_search_data` again with new filters — don't reuse stale field names from earlier in the chat. Read-only — **mandate/RFP postings** with optional linked plan, consultant, contact, and search-winner context — not firm-only discovery (**`get_accounts_data`**). **Prod status note:** Majority of rows are **`Archived`**; **`Open`** is rare (~20). Do not assume “active searches” without checking **`search_status`**. ~**8%** are **Consultant Searches** (consultant-led postings) vs Investment Searches. Example asks: "Active private equity marketplace searches", "Closed searches posted in 2024 over $100M", "Mandates where Callan is consultant", "Emerging manager searches in real assets.", "Find searches connected to recent public plan committee activity and include the related allocator account." MANDATORY — **`get_marketplace_search_data` must run** for any ask that expects **named search/mandate records** or scoped mandate universes. Normalize picklists via **`get_lookup_values`**, call **`get_output_fields`**, then query. Per-filter semantics and lookup ids: read each parameter's **field description** on this tool. ═══════════════════════════════════════════════════════════════════ QUERY STRATEGY (follow this approach): ═══════════════════════════════════════════════════════════════════ 1. START BROAD: - Begin with high-signal search fields (`search_status`, `asset_class`, posted date window, optional `name`). When user asks for **open/active** mandates, set **`search_status`** explicitly — most prod rows are **Archived**; **`Open`** is rare. 2. ADD SEARCH DETAILS: - Layer `sub_asset_class`, `product_structures`, `source`, and `=>` range amount/date constraints if explicitly requested. 3. LAYER OVERLAYS AFTER FIRST PASS: - Add firm/contact/consultant/current-consultant overlays after confirming non-empty base search scope. 4. APPLY SEARCH-WINNER FIELDS LAST: - Add search-winner strategy/performance filters only when user asks for winner profiling or strategy-level constraints. 5. PREFER PROGRESSIVE NARROWING: - Avoid stacking too many overlays in the first call. Cross-field routing: - Search-level intent: `search_status`, `source`, `asset_class` (broad), `sub_asset_class` (sleeve), `product_structures`, `posted_date`, `name`. - Optional linked-plan overlays (`account_name`, `account_type`, …): only when scoping mandates to a plan cohort — not for firm-only "accounts interested in X" (**`get_accounts_data`**). - Consultant overlays: use only when consultant constraints are part of user intent. - Contact overlays: **`contact_asset_class_coverage`** for person coverage. - Search-winner overlays: strategy/fund/performance constraints tied to the winning strategy record. - Public-plan overlays: use `public_plan_*` when user asks for public plan consultant/meeting/posting context or **searches connected to committee/IC activity** — prefer `public_plan_meeting_date` or `public_plan_posted_date` for recency; include linked allocator via `account.name` / `account.type` in `output_fields` when requested. ═══════════════════════════════════════════════════════════════════ ZERO-RESULT RECOVERY PROTOCOL (MANDATORY — follow exactly): ═══════════════════════════════════════════════════════════════════ If status='success' AND (total_count == 0 OR data is empty): DO NOT immediately tell user "no results found." DO NOT ask for clarification yet. You MUST execute this sequence first: STEP 1 — FILTER VALIDATION: - Re-check lookup-backed fields and remap from lookup outputs. - Re-check value shapes (boolean vs scalar vs array vs numeric vs date format). - Retry immediately after correcting mappings/shapes. STEP 2 — RELAX OVERLAYS FIRST: - Remove contact and consultant/current-consultant overlays first. - Then remove search-winner overlays while keeping core search filters. STEP 3 — RELAX CORE CONSTRAINTS: - Widen date windows and amount bands. - Reduce restrictive categorical combinations. - Keep at least one core search anchor if possible. STEP 4 — SECOND BROAD PASS: - Retry with only 1-3 strongest search anchors and essential user constraints. STEP 5 — USER FOLLOW-UP (only after steps 1-4 fail): - State you tried multiple valid filter combinations. - Ask 1-3 targeted clarifying questions. ═══════════════════════════════════════════════════════════════════ OUTPUT FIELDS (REQUIRED on every row-list call — do not skip): ═══════════════════════════════════════════════════════════════════ - `output_fields` **must be populated** on every `get_marketplace_search_data` call that returns rows. Exception only: `is_count_only=true` when the user wants a count and no row columns. - To populate it, you **MUST** call tool **`get_output_fields`** first with `tool_name` = `get_marketplace_search_data` (if `tool_search` is needed, query exactly `get_output_fields`). - Then pass a **small subset** (typically 3–10 keys) copied **verbatim** from that tool's returned `output_fields` list — never invent keys, never paste the full allowlist. - Preferred order: (1) `get_lookup_values` if picklists are needed → (2) `get_output_fields` → (3) `get_marketplace_search_data` with `output_fields` set. - Do **not** call `get_marketplace_search_data` for a row list until `get_output_fields` has been called in this turn and `output_fields` is set from its response. - Invalid keys are rejected by the server before the Apex call — that error means call `get_output_fields` again and retry with allowlisted keys only.
get_marketplace_search_data
**Tool: `get_new_fund_data`** — primary Dakota Marketplace **New Fund / Form D** search: one row = one **Form D offering filing** (~140k). Keywords: get_new_fund_data, Form D, Reg D, new fund filing, SEC offering, accession number, CIK, issuer name, fund name, total amount sold, filed on, submission type D amendment. MANDATORY BEFORE ROW LISTS — tool `get_output_fields`: - You may NOT call `get_new_fund_data` until you've called `get_output_fields` (tool_name=get_new_fund_data) first in this turn — no exceptions except `is_count_only=true`. - If not loaded: `tool_search` query exactly `get_output_fields`. - Copy 3–10 keys VERBATIM from its response into `output_fields`. Never invent/guess keys, never skip on row lists. - Order: lookups → `get_output_fields` → `get_new_fund_data`. - Re-run `get_output_fields` each time you call `get_new_fund_data` again with new filters — don't reuse stale field names from earlier in the chat. Read-only query tool — one row per **Form D offering filing** (not a firm, person, or strategy product row). **~86% of prod rows have null asset class** — lead with **`filed_on`** + **`sort_order='DESC'`** on broad asks; add **`asset_classes`** only when user names a sleeve. Original **`D`** ~101k vs amendment **`D/A`** ~39k — use **`submission_types`** when user cares. Example asks: "Recent Form D filings for private equity buyout funds", "New funds filed in 2024 with over $100M sold", "Form D offerings from issuers named Capital Partners", "Funds with non-accredited investors", "Delaware LP Form D filings linked to investment firms in New York". MANDATORY — **`get_new_fund_data` must run** for any ask that expects **named Form D offerings/funds**, **recent Reg D filing lists**, **offering size/date/SEC identifier** discovery, or scoped universes by issuer, accession, CIK, filing window, or linked account/strategy metadata. Normalize picklists via **`get_lookup_values`**, call **`get_output_fields`**, then **`get_new_fund_data`**. Dakota Form D coverage is broad for US private offerings; empty results often indicate over-restrictive filters, wrong asset-class labels, or mismatched SEC identifiers — not proof that no filings exist. ═══════════════════════════════════════════════════════════════════ NEW FUND / FORM D USE-CASE CONTEXT: ═══════════════════════════════════════════════════════════════════ Prioritize fundraising-intelligence and offering-discovery for these common intents: - **Recent fundraising activity:** lead with `filed_on` or `sort_order='DESC'` before narrow boolean flags. - **Strategy/asset-class screening:** use `asset_classes` (lookup-first) + optional `sub_asset_classes` when the user names a sleeve (for example Buyout, Venture Capital). - **Named fund / issuer lookup:** use `fund_names`, `name_of_issuers`, `accession_nos`, `ciks`, or `sec_ids` when the user supplies identifiers. - **Offering size bands:** use `total_amount_sold_*`, `total_offering_amount_calculate_*`, or `minimum_investment_accepted_*` when size matters. - **Investor composition:** use `has_non_accredited_investors=true` when the user asks about non-accredited participation. - **Linked manager/firm scoping:** use `account_names`, `account_types`, `account_metro_areas`, and investment-strategy overlays when the user ties filings to a known firm or strategy profile. **Form D-native vs linked overlays:** - **Form D-native filters** (`fund_names`, `asset_classes`, `accession_nos`, offering amount/date ranges, boolean flags) = attributes on the offering filing itself. - **`account_*` filters** = linked firm attributes (name, type, metro, AUM, sector, industry, investment focus/interest). - **`investment_strategy_*` filters** = linked strategy/product attributes when the user scopes by strategy profile. COMMON MAPPINGS (first-pass — validate before calling): User / colloquial intent → First-pass filter choice ──────────────────────────────────── ───────────────────────────────────────────── "Recent Form D filings" → `sort_order='DESC'` + optional `filed_on` "Private equity new funds" → tool `get_lookup_values` (catalog id `marketplace_documents_asset_classes`) → `asset_classes=['Private Equity']` "Buyout funds" → add tool `get_lookup_values` (catalog id `new_fund_sub_asset_classes`) → `sub_asset_classes=['Buyout']` "Non-accredited investors" → `has_non_accredited_investors=true` "Delaware LP" → `jurisdictions=['DELAWARE']`, `entity_types=['Limited Partnership']` "Over $100M sold" → `total_amount_sold='100000000=>'` ═══════════════════════════════════════════════════════════════════ QUERY STRATEGY (follow this approach): ═══════════════════════════════════════════════════════════════════ 1. START BROAD: Use reliable anchors first → `asset_classes` (lookup-first) or `filed_on_*` date window + `sort_order='DESC'`. 2. ADD IDENTITY: `fund_names`, `name_of_issuers`, `accession_nos`, `ciks`, or `account_names` when the user names a specific fund/issuer/firm. 3. ADD SIZE / TIMING: offering amount ranges and first-sale / estimated-close dates when explicitly requested. 4. ADD BOOLEAN FLAGS LAST: amendment, act of 1940, non-accredited investors, foreign/non-US — only when explicitly requested. 5. ADD LINKED OVERLAYS LAST: `account_investment_focus` (broad firm strategy), `account_*` profile fields, and `investment_strategy_*` when scoping to a known manager profile. Use `investment_strategy_sub_asset_classes` for strategy sleeves. 6. PREFER progressive narrowing over stacking every filter on the first query. ═══════════════════════════════════════════════════════════════════ ZERO-RESULT RECOVERY PROTOCOL (MANDATORY — follow exactly): ═══════════════════════════════════════════════════════════════════ If status='success' AND (total_count == 0 OR data is empty): DO NOT immediately tell the user "no results found." DO NOT ask the user for clarification yet. You MUST execute this recovery sequence FIRST: STEP 1 — FILTER VALIDATION: - Re-check `asset_classes` via tool `get_lookup_values` (catalog id `marketplace_documents_asset_classes`) and `sub_asset_classes` via tool `get_lookup_values` (catalog id `new_fund_sub_asset_classes`). - Re-check `account_types` via tool `get_lookup_values` (catalog id `account_types`) when used. - Confirm list shapes, booleans, and numeric-string ranges. STEP 2 — REMOVE BOOLEAN / DATE WINDOWS: - Drop amendment, act-of-1940, non-accredited, and narrow date filters; retry with asset class and/or issuer anchors. STEP 3 — BROADEN SIZE BOUNDS: - Widen or drop offering amount and minimum-investment filters. STEP 4 — DROP IDENTITY FILTERS: - Remove `accession_nos`, `ciks`, `sec_ids`, and exact `fund_names` while keeping broader anchors. STEP 5 — DROP LINKED OVERLAYS: - Remove `account_*` and `investment_strategy_*` filters while keeping Form D-native anchors. STEP 6 — USER FOLLOW-UP (ONLY after completing steps 1 → 5 without usable results): - Say: "I tried several filter combinations but couldn't find matching Form D / new fund records in Dakota Marketplace." - Briefly mention what you tried. - Ask 1–3 targeted follow-up questions (asset class, issuer name, filing window, offering size). ═══════════════════════════════════════════════════════════════════ OUTPUT FIELDS (REQUIRED on every row-list call — do not skip): ═══════════════════════════════════════════════════════════════════ - `output_fields` **must be populated** on every `get_new_fund_data` call that returns rows. Exception only: `is_count_only=true` when the user wants a count and no row columns. - To populate it, you **MUST** call tool **`get_output_fields`** first with `tool_name` = `get_new_fund_data` (if `tool_search` is needed, query exactly `get_output_fields`). - Then pass a **small subset** (typically 3–10 keys) copied **verbatim** from that tool's returned `output_fields` list — never invent keys, never paste the full allowlist. - Preferred order: (1) `get_lookup_values` if picklists are needed → (2) `get_output_fields` → (3) `get_new_fund_data` with `output_fields` set. - Do **not** call `get_new_fund_data` for a row list until `get_output_fields` has been called in this turn and `output_fields` is set from its response. - Invalid keys are rejected by the server before the Apex call — that error means call `get_output_fields` again and retry with allowlisted keys only.
get_new_fund_data
**Tool: `get_output_fields`** — REQUIRED Dakota Marketplace **output column allowlist** meta tool before every row-list primary call. Returns valid Apex `outputFields` keys for a primary tool. Keywords: get_output_fields, output fields, outputFields, output fields tool, columns, fields to return, response columns, allowlist, column keys, select fields, which fields, name, title, email, phone, accountName, accountAUM, get_accounts_output_fields, get_contacts_output_fields, output field catalog, mandatory before row list, row-list columns, small subset, verbatim keys. **Mandatory workflow:** before every row-returning primary call, call **`get_output_fields(tool_name=...)`** with the **exact catalog/tool name** matching the output-field arg you will fill (for example `get_accounts_data`, `get_contacts_data`). For Contacts education/career overlays also use catalog aliases **`get_education_alumni_data`** → `education_output_fields` and **`get_career_history_data`** → `career_output_fields` (standalone data tools retired). Then pass a **small subset** (typically 3–10 keys) copied **verbatim**. Never invent keys. Omit only when `is_count_only=true` and no rows are needed. **`tool_search`:** query exactly **`get_output_fields`** — this tool name only. Do **not** combine with `get_lookup_values` in one search query; load each meta tool separately by exact name. Supported `tool_name` values match primary tools with output-field catalogs (accounts, contacts, education/career catalog aliases, form ADV, transactions, investment strategy, and other listed primaries).
get_output_fields
**Tool: `get_performance_benchmark_data`** — primary Dakota Marketplace **Performance & Benchmark** analytics: **cohort aggregate benchmark stats** — not individual fund or firm rows. Keywords: get_performance_benchmark_data, performance benchmark, fund benchmark, quartile performance, median IRR, TVPI benchmark, cohort performance, vintage benchmark, fee benchmark. Read-only tool — computes **one summarized aggregate** for a screened performance cohort. Answers **"how does this cohort benchmark?"** — not "list funds for me." Unlike row-list tools, this endpoint **does not return individual entity records, pagination, or total row counts**. Row shape is **one cohort aggregate summary** — quartile/median benchmark stats for a screened performance universe. Example asks: "Benchmark PE buyout funds by vintage", "Median net IRR for 2018 vintage credit funds", "How do funds with net IRR above 15% compare on TVPI?" MANDATORY — **`get_performance_benchmark_data` must run** when the user asks for benchmark statistics, quartile/median framing, or threshold-based performance screening. Normalize picklists via **`get_lookup_values`** when used. =========================================================================== RESPONSE SHAPE (NOT A ROW-LIST TOOL): =========================================================================== On success: - `status` - `totalRecordsForSummary` — count of underlying performance records in the aggregate - `aggregates` — **array** of cohort aggregate summary objects; `[]` when no cohort matches - `errorDetails` (when diagnostic text is returned) This tool omits `total_count`, `page_number`, `page_count`, `has_more`. Never infer pagination or invent row lists. `aggregates` semantics: - Always an **array**, but **not** a paginated set of funds, accounts, managers, or contacts. - Each object includes distribution stats (for example Net IRR, TVPI, DPI with Min/Q1/Median/Q3/Max) plus `asOfDate` in quarter-year format (for example `3Q25`). - `[]` means **no benchmark aggregate was produced** — not "Dakota has zero funds." - For a single-quarter ask, use the matching `asOfDate` entry. Presentation: - Explain cohort scope + distribution bands + relative position. - Never format as a table of individual funds unless the user separately asks for a row-list tool. - Avoid buy/sell or manager recommendation language. =========================================================================== STRATEGY TAXONOMY ON THIS TOOL: =========================================================================== - **Broad strategy category** → `asset_class` (**`get_lookup_values`**, catalog id `performance_asset_classes`) - **Specific sleeves** → `sub_asset_class` (catalog id `performance_sub_asset_classes`) - **Investment approach** (passive, active, systematic, etc.) → `styles` or `investment_strategy_investment_styles` - **Related-account broad firm strategy** → `account_investment_focus_single` (catalog id `investment_focus`) - Do **not** use account sleeve-style fields for performance approach filtering. =========================================================================== QUERY CONSTRUCTION PLAYBOOK: =========================================================================== Step 1 — Anchor cohort: 1–2 identity filters (`asset_class`, `sub_asset_class`, `vintage`, **name/text filter** via MCP arg `search_term`, or account profile anchor). Step 2 — Add strategy/account context only when required. Step 3 — Add performance/risk/fee bounds for explicit user constraints (numeric ranges `lower=>upper`; `inception_date` as `YYYY-MM-DD=>YYYY-MM-DD`). Step 4 — Interpret aggregate entry for requested as-of quarter; mention cohort scope. INTENT-TO-FILTER ROUTING: - "Benchmark PE buyout by vintage" → `asset_class`, `sub_asset_class`, `vintage` - "Benchmark by investment approach" → `styles` or `investment_strategy_investment_styles` - "High-performing cohort" → `net_irr` (for example `15=>`) and optionally `tvpi` - "Risk-aware view" → `sharpe`, `sortino`, drawdown/volatility ranges - "Fee-aware view" → `mgmt_fee`, `performance_fee` - "Filter by fund or account name text" → **name/text filter** (MCP arg `search_term`) =========================================================================== ZERO-RESULT RECOVERY: =========================================================================== If successful call returns empty `aggregates`: 1. Re-run lookup normalization and retry once. 2. Relax optional metadata: `sources` → `styles` → `sectors` → `strats` → strategy industry/style fields. 3. Widen range fields or `inception_date` window. 4. Keep one stable anchor (`asset_class` or `account_types`) and retry. 5. Only then ask targeted follow-up questions. Never claim "Dakota does not track this" solely from a no-result response.
get_performance_benchmark_data
**Tool: `get_public_plan_minutes_data`** — primary Dakota Marketplace **Public Plan Minutes** search: one row = one **public pension board or investment committee minute document** (~6,350). Keywords: get_public_plan_minutes_data, public plan minute, board minute, investment committee minute, IC minute, minute document, minute name, meeting date, consultant mentioned in minutes. MANDATORY BEFORE ROW LISTS — tool `get_output_fields`: - You may NOT call `get_public_plan_minutes_data` until you've called `get_output_fields` (tool_name=get_public_plan_minutes_data) first in this turn — no exceptions except `is_count_only=true`. - If not loaded: `tool_search` query exactly `get_output_fields`. - Copy 3–10 keys VERBATIM from its response into `output_fields`. Never invent/guess keys, never skip on row lists. - Order: lookups → `get_output_fields` → `get_public_plan_minutes_data`. - Re-run `get_output_fields` each time you call `get_public_plan_minutes_data` again with new filters — don't reuse stale field names from earlier in the chat. Read-only — **minute document rows** from US public pension board and investment committee meetings. Anchor on **`public_plan_minute_names`** and/or **`account_names`** when the user names a plan; **`general_consultants`** for consultant mentions (free-text, not a lookup); **`meeting_date`** when meeting timing is explicit. Example asks: "CalPERS board meeting minutes", "Public pension minutes mentioning Callan", "Sacramento public pension minutes from 2024." MANDATORY — **`get_public_plan_minutes_data` must run** when the user wants **minute documents**. Normalize picklists via **`get_lookup_values`**, call **`get_output_fields`**, then query. Per-filter semantics, value shapes, and lookup ids: read each parameter's **field description** on this tool. ═══════════════════════════════════════════════════════════════════ ZERO-RESULT RECOVERY (strict sequence): ═══════════════════════════════════════════════════════════════════ If `data` is empty or too narrow: 1. Drop `account_investment_interest`, `account_sector`, or `account_industry` first. 2. Widen or remove the `meeting_date` window. 3. Relax or remove the `account_aum` band. 4. Try `public_plan_minute_names` alone vs `account_names` alone if both were set. 5. Remove `general_consultants` if combined with a narrow plan name. 6. Re-check `account_types` via **`get_lookup_values`** (catalog id `account_types`). Coverage is deep for major US public pensions; empty results often indicate over-restrictive filters or mismatched plan names. ═══════════════════════════════════════════════════════════════════ OUTPUT FIELDS (REQUIRED on every row-list call — do not skip): ═══════════════════════════════════════════════════════════════════ - `output_fields` **must be populated** on every `get_public_plan_minutes_data` call that returns rows. Exception only: `is_count_only=true` when the user wants a count and no row columns. - To populate it, you **MUST** call tool **`get_output_fields`** first with `tool_name` = `get_public_plan_minutes_data` (if `tool_search` is needed, query exactly `get_output_fields`). - Then pass a **small subset** (typically 3–10 keys) copied **verbatim** from that tool's returned `output_fields` list — never invent keys, never paste the full allowlist. - Preferred order: (1) `get_lookup_values` if picklists are needed → (2) `get_output_fields` → (3) `get_public_plan_minutes_data` with `output_fields` set. - Do **not** call `get_public_plan_minutes_data` for a row list until `get_output_fields` has been called in this turn and `output_fields` is set from its response. - Invalid keys are rejected by the server before the Apex call — that error means call `get_output_fields` again and retry with allowlisted keys only.
get_public_plan_minutes_data
**Tool: `get_updates_data`** — primary Dakota Marketplace **Updates** search: **job-change and role-change intelligence** (~433k job-change rows). Keywords: get_updates_data, updates data, job change, role change, who joined, who left, who moved, recent hire, recent moves, departure, left firm, joined firm, firm switch, new employer, title change, new title, old title, promotion, new role, firm joined, firm left, executive moves, executive hire, personnel movement, personnel changes, movement feed, recent appointment, switched firms. MANDATORY BEFORE ROW LISTS — tool `get_output_fields`: - You may NOT call `get_updates_data` until you've called `get_output_fields` (tool_name=get_updates_data) first in this turn — no exceptions except `is_count_only=true`. - If not loaded: `tool_search` query exactly `get_output_fields`. - Copy 3–10 keys VERBATIM from its response into `output_fields`. Never invent/guess keys, never skip on row lists. - Order: lookups → `get_output_fields` → `get_updates_data`. - Re-run `get_output_fields` each time you call `get_updates_data` again with new filters — don't reuse stale field names from earlier in the chat. Read-only query tool — one row per **job or role change update** (personnel movement feed ~**433k** job-change rows; **~93%** of all Update rows are generic marketplace field churn — **always** set **`job_change`** and/or **`role_change`**). Use when the user asks about **recent hires, departures, job changes, role changes**, or people who joined or left named firms. **Movement booleans:** set **`job_change=true`** OR **`role_change=true`** from intent — **do not default both true**. Prefer **`firm_joined_names`** / **`firm_left_names`** (well populated) over sparse joined Account refs (~5%). Personnel feed **`created_date`** window roughly **May 2024–present**. Example asks: "Who joined Ares in 2026?", "CTO role changes in New York", "Investment firm job moves this year." MANDATORY — **`get_updates_data` must run** for movement lists or scoped update universes. Normalize picklists via **`get_lookup_values`**, call **`get_output_fields`**, then query. Per-filter semantics, value shapes, and lookup ids: read each parameter's **field description** on this tool. Empty results often indicate over-restrictive combinations or wrong organization-category labels. ═══════════════════════════════════════════════════════════════════ ZERO-RESULT RECOVERY: ═══════════════════════════════════════════════════════════════════ If `data` is empty or too narrow: 1. Drop `account_aum`, `account_record_types`, or `contact_mailing_countries` first. 2. Widen or remove `created_date`. 3. Try `firm_joined_names` alone vs `firm_left_names` alone if both were set. 4. Remove one of `job_change` / `role_change` if both were set without user intent (mutually exclusive). 5. Relax `old_titles` / `new_titles` to a single title field. 6. Re-check `account_types` and record-type lookups for exact labels. ═══════════════════════════════════════════════════════════════════ OUTPUT FIELDS (REQUIRED on every row-list call — do not skip): ═══════════════════════════════════════════════════════════════════ - `output_fields` **must be populated** on every `get_updates_data` call that returns rows. Exception only: `is_count_only=true` when the user wants a count and no row columns. - To populate it, you **MUST** call tool **`get_output_fields`** first with `tool_name` = `get_updates_data` (if `tool_search` is needed, query exactly `get_output_fields`). - Then pass a **small subset** (typically 3–10 keys) copied **verbatim** from that tool's returned `output_fields` list — never invent keys, never paste the full allowlist. - Preferred order: (1) `get_lookup_values` if picklists are needed → (2) `get_output_fields` → (3) `get_updates_data` with `output_fields` set. - Do **not** call `get_updates_data` for a row list until `get_output_fields` has been called in this turn and `output_fields` is set from its response. - Invalid keys are rejected by the server before the Apex call — that error means call `get_output_fields` again and retry with allowlisted keys only.
get_updates_data
Show the Dakota Marketplace consent widget using an existing sign-in URL. WHEN TO CALL: - After any data tool returns status=authentication_required. REQUIRED ARGUMENTS (from that data tool result): - auth_url — copy from consent_tool_arguments.auth_url (or auth_url field) - oauth_state — copy from consent_tool_arguments.oauth_state (or oauth_state field) Do not generate a new sign-in URL; reuse the URL from the data tool so the widget matches the chat link. WHAT THIS TOOL DOES: - Renders the consent resource UI at the top when the host supports it. - Uses the same auth_url you passed in (widget Continue button). CHAT: - If the data tool message (markdown sign-in link) was not already posted, paste it verbatim in chat. - Do not paraphrase authorization; use the exact message from the data tool. AFTER SIGN-IN: - Retry the original Dakota data request with the same parameters.
show_salesforce_consent
How do I improve a ChatGPT Plugin's discoverability?
The levers are the listing surface agents actually read: names, descriptions, keywords, tool metadata, and registry health. Which lever matters depends on where discovery breaks, which is what continuous measurement shows.
What are Dakota Marketplace alternatives on ChatGPT?
As of 2026-08-14, Dakota Marketplace competes with CB Insights, Cookiedeal, Datasite, Evertrace, GLG, Guidepoint, Hadaly, Harmonic, Hebbia, PitchBook, Sacra, Third Bridge, TrustMRR, Venturu in ChatGPT Private Markets, Deals & Expert Networks, ranked by public Discoverability Score.
Where is this profile measured?
This profile uses the geography attached to the latest public registry snapshot: US. Locale tags are intentionally omitted.