Count CRM Records
count_crm_recordsCount the CRM records matching a filter, and return a small sample. For a population question a PERSON asked -- 'how many contacts have no mobile phone'. Reads a local mirror, calls no CRM API, spends nothing, changes nothing. matched is the whole count; the sample is capped and says so.
NOT how you write a scope: a run's filter is resolved when the run is dispatched, so composing needs no counts and no record ids. If you are composing a plan, you do not need this.
A FILTER WIDENS AS WELL AS NARROWS, and the widening case is the one that gets asked one term at a time. 'Our procurement contacts' is not several questions -- it is ONE group with combinator OR over the words that name the concept: title contains_word Procurement, OR Purchasing, OR Sourcing, OR Buyer, OR department is Purchasing. Ask it as one call. Asking each term separately costs a call per guess, answers each in isolation so nothing tells you the union, and double-counts anyone whose title carries two of the words. Groups nest, so an OR over synonyms sits inside an AND with the rest of the question -- those people, and no activity since a date.
Tool call template
Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.
{
"id": 1,
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"arguments": {
"connection_id": "<connection_id>",
"object_type": "<object_type>"
},
"name": "count_crm_records"
}
}Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| root | No | The root of the filter tree. A group combines nodes with AND or OR; a node is either another group or a condition naming a field, an operator, and a value, and groups NEST -- an OR over the several words that name one concept, inside an AND with the rest of the question, is one filter and one call. EVERY NODE CARRIES ITS OWN `kind`: "group" on a group, "condition" on a condition. It is what selects the node type, so a nested group that omits it is refused before anything else is read. Call list_filterable_fields first: the fields and the operators each accepts are specific to this connection's CRM. OMIT IT ENTIRELY to count every record of the object on this connection -- that is the same scope a run with no filter operates on, and it needs no conditions to express. | |
| limit | No | How many matching records to return, up to 200. Omit for 10, or for none when there is no root. 0 returns the count alone. | |
| fields | No | The fields to return on each sample record, by the names list_filterable_fields gives. Omit for every field, which is fifty or more on most objects: name the few the question needs. | |
| offset | No | How many matching records to skip, to page through more than one limit holds. Records come in a stable order, so offset 0, 200, 400 reads them all. | |
| aggregate | No | One number over EVERY matching record, not the sample: sum, avg, min or max of a number field. What won deals are worth is the sum of amount over opportunities where is_won is true. | |
| object_type | Yes | Which CRM object to count. One of: account, contact, lead, opportunity, case. | |
| connection_id | Yes | The CRM connection to read. Required. Call list_crm_connections to get one. |