Fetch-entities
Find companies and/or prospects using any combination of filters (returns ~10 sample rows)
- Whenever the user is asking to find companies who need or are showing intent/interest/relevancy for a certain product or service, use the business_intent_topics filter.
- ALWAYS use autocomplete for the following filters: linkedin_category, naics_category, job_title, interests, skills, business_intent_topics, company_tech_stack_tech.
- **CRITICAL:** Standardized values from autocomplete MUST be used in the subsequent fetch call. DO NOT use raw user input for these filters under any circumstances.
- **PERSISTENCE:** Ensure standardized values are preserved and used even if other tools (like match) are called between autocomplete and fetch.
**ENTITY_TYPE SELECTION (REQUIRED):**
- **Use "prospects"** - When request involves people/individuals in ANY way
- **Use "businesses"** - When request is ONLY about companies with NO people
**KEY: Any people-related request = use "prospects" directly**
**LOCATION FILTERS:**
- `company_country_code` / `company_region_country_code` filter the company's HQ location.
- `prospect_country_code` / `prospect_region_country_code` filter where the person is based.
- If `entity_type` is `prospects` and the user mentions a location without making clear whether it applies to the person or the company, ask before fetching:
"Before I search, when you say "in <location>", do you mean:
- Prospects who are physically based there
- Prospects working at companies headquartered there
- Both: prospects who are physically based there and work at companies headquartered there"
- Do not ask when the wording is clear, such as "companies in Germany" (company HQ) or "prospects based in New York" (prospect location).
- Only call this tool after the user confirms which location filter to use.
**PROSPECT CONTACT INFO (EMAIL / PHONE):**
- Prospect fetch returns discovery fields only (name, title, company, etc.)—**not** email or phone **values**. `has_contact_details` only **filters** who qualifies (`email` | `phone` | `email_or_phone` | `email_and_phone`); it does not add contact columns.
- Map user intent to `has_contact_details.value`: emails only → `email`; phones only → `phone`; at least one → `email_or_phone`; both → `email_and_phone`.
- If `entity_type` is `prospects` and the user did not explicitly ask for contact details (email, phone, mobile, contact info, or similar), ask before fetching:
"Before I search, would you like to include contact details in your results?
- Emails only
- Both emails and phone numbers
- No thanks, prospects only"
- Store the user's answer as session intent for this prospects dataset. Do not ask this pre-fetch contact question again for the same session/dataset unless the user changes the dataset or changes their preference.
- Do not ask this for business-only searches.
- For emails, phones, or exports that include them, run `enrich-prospects` on the fetch `table_name` (same `session_id`) with `enrich-prospects-contacts`, then use the enriched `table_name` downstream.
**EVENT DETAILS:**
- `filters.events` only selects businesses with that signal—it does not add event detail fields to fetch results.
- If the fetch used `filters.events` and the user did not already ask for event details in the same message, you MUST ask after presenting results and before `fetch-*-events` or export:
"Would you like me to retrieve event details for these results?
- Yes, get event details
- No thanks, keep results as-is"
- Wrong: call `fetch-*-events` immediately after `fetch-entities` returns results with matching event signals.
- Right: present the matching results, ask the event-details question, and call `fetch-*-events` only after the user confirms.
- If yes: run `fetch-*-events` with matching `event_types`.
**WORKFLOW**
1) `fetch-entities` → explore (returns masked preview + `table_name`, no charge)
2) (Optional) `enrich-business` / `enrich-prospects` → add details (name, domain, revenue, size, tech stack, emails, phones) **only if user asks or answers the contact-details prompt with emails/phones/both**
3) If `filters.events` was used: use the event-details prompt before `fetch-*-events`
4) After this user turn's requested fetch/enrich/events work is done, make a separate `show-sample` call for each final relevant `table_name` (for split/parallel results, sample every final dataset; call it again after later turns that add more data; charges once per table)
5) After user approves cost: `export-to-csv` on the **latest** `table_name` (post-events or post-enrich when applicable)
- Only ask about export when the workflow is finished **and** there is more data than shown in chat (preview subset, bulk fields, or user asked for a file)—not when the answer is already complete in the message.
- Never auto-export; export only after explicit user confirmation **regardless of credit balance**.
**Cost Estimation:**
- **CRITICAL: NEVER auto-export. Always wait for explicit user confirmation after showing the cost estimate, regardless of credit balance.**
- **Never substitute export (or any credit-consuming action) when the user's actual request cannot be fulfilled.** Explain the limitation and ask how to proceed — do not spend credits on something the user did not ask for.
- Once cost is displayed in the table, the user can then decide whether to proceed with export or refine their search
**REQUEST PLANNING (MANDATORY)**
- Determine all filters in advance; make **ONE** comprehensive fetch call.
- Multiple fetch calls when filters can be combined are **FORBIDDEN**.
- Exception — category fallback: if a fetch using linkedin_category returns too few results (< 20) or the preview rows are clearly a different business type than requested, make ONE retry replacing linkedin_category with an autocompleted naics_category (never send both).
Once this turn's exploration work is finished, call `show-sample` with the final `table_name` — it is the last step before replying to the user and will display results according to the user's request.
**READING `counts` (never guess which number to quote)**
- `records_matching_filters` — how many exist upstream. **Headroom, not delivered data.** Never say these were fetched, saved, or exported.
- `records_available` — rows this step delivered. On `show-sample`/`export-to-csv` it is the exportable/exported row count; on `enrich`/`events` it equals `records_received` (all input rows were kept). **This is the number to tell the user.**
- `records_requested` — the cap that was applied. Defaults to 30 when the user named no number.
- `records_shown_in_preview` — preview rows only. Never a dataset size.
- `records_received` / `records_with_errors` — inputs into this step / inputs that failed.
- When `records_matching_filters` > `records_available`, you have a **subset**. Say so: "N of M matching — want more?" Never "all M".
- **Never do arithmetic on `records_matching_filters`** — no scaling costs, credits, or totals to it. Quote `cost_in_credits` as returned; it already covers exactly `records_available` rows.
**RESULT LIMITS**
- Max 1000 results per request; do not imply exhaustion.
- If more needed: suggest refining filters or running another targeted search (positive framing).
**MAX_PER_COMPANY**
- **CRITICAL: USE ONLY IF USER SPECIFIES A NUMBER.**
**BUYING INTENT (CRITICAL FOR SALES PROSPECTING)**
- When user wants to find potential customers/prospects for what they're selling
- Use business_intent_topics filter (requires autocomplete)
- Example Keywords: "selling to", "need", "looking for", "interested in buying", "prospects for"
**JOB FILTER RULES**
- Broad role categories: use `job_level` + `job_department` ONLY (never `job_title`).
- Example: job_level ["c-suite", "director", "vice president"] + job_department ["engineering"]
- Specific titles: use `job_title` ONLY.
- `job_level`/`job_department` are more precise; if seniority/department is requested, ALWAYS use them.
- Use autocomplete to get standardized job titles.
- If too broad, narrow with `website_keywords`.
**AMBIGUOUS TERMS**
- For broad/ambiguous terms toggle options (e.g., "designers", "engineers", "security", "mining", "consulting"):
- Present specific subcategory options AND an option to search **ALL relevant categories (including the general term)**.
- **Do not auto-select** the general term without user choice.
**SESSION / REFERENCES**
- If `session_id` provided: store filters/results; otherwise return a new one.
- Use the `session_id` to retrieve stored data later.
- Pass previous result table names into reference-table fields:
- `businesses_reference_table` refines prospects from prior fetch-businesses results; requires `session_id`. For company details from prospect data, use enrich-business instead.
- **IMPORTANT: When chaining enrichment → fetch, always use the enriched table name (from enrich response) not the original fetch table name as reference**
- Enriched result tables from enrich tools can also be used as reference tables; when used, enriched fields may be available in results.
**EXCLUDE**
- Optional `exclude_key`:
- `"prospects"` or `"business"`: tenant-global exclude list (server maps this for you).
- **Specific list:** pass the `dataset_id` from `get-dataset`, `export-to-csv`, or dataset listing —not the display name.
- Omit: no exclusion.
**AUTOCOMPLETE REQUIREMENTS:**
These filters REQUIRE autocomplete before fetch-entities:
- linkedin_category
- naics_category
- job_title
- interests
- skills
- business_intent_topics
- company_tech_stack_tech
- city_region (only for USA cities)
**MANDATORY RULE:** If you use ANY of these filters, you MUST call autocomplete FIRST.
NO EXCEPTIONS. NO SHORTCUTS.
Once you have the autocomplete results, you MUST use them in the fetch-entities call. DO NOT revert to the user's original raw input. Standardized values MUST persist even if multiple tools are used in sequence.
**Exception:** If linkedin_category autocomplete returns empty or no suitable match after broadening your query once, run autocomplete with field=naics_category and use naics_category instead. For other filters, skip the filter entirely.
**EVENT-BASED FILTERS (use enum values directly, no autocomplete needed):**
- `events`: Object with "values" (array of event types from fixed enum) and "last_occurrence" (days: 30-90)
**Do NOT autocomplete these filters (use directly):**
- country_code, company_country_code → use ISO Alpha-2 codes (e.g., "US", "IL")
- region_country_code, company_region_country_code → use ISO 3166-2 codes (e.g., "US-CA", "IL-TA")
- businesses_reference_table → extract from previous fetch-businesses results
- business_id, prospect_id → extract from previous results
**CONSTRAINTS**
- For enum-backed filters, use schema enum values directly.
- Never set more than one of: `linkedin_category`, `naics_category`.
- Never set both `region_country_code` and `country_code`; same for company.
- Only run enrich tools when explicitly requested or when the user answers the contact-details prompt with emails/phones/both.
- To filter by a specific company, first call match-business to get its ID, then pass it here.
- Returns Business/Prospect IDs; do NOT chain with `match-business` / `match-businesses` / `match-prospects`.
- `businesses_reference_table` requires `session_id`.
- If a filter is unsupported/invalid, stop and alert the user.