Query filters
The structured filter shape used by Find Records, related lists, and metrics. One syntax everywhere.
Shape
[
{ "fieldName": "IsClosed", "operator": "=", "values": ["false"] },
{ "fieldName": "CloseDate", "operator": "<=", "values": ["THIS_QUARTER"] }
]
A list of conditions, combined with AND. There is no OR and no nesting — use IN for alternatives on one field.
| Key | Notes |
|---|---|
fieldName | Field API name on the object being filtered |
operator | See below |
values | Always an array, even for a single value |
In the Studio, the filter builder offers the object’s fields and picklist values. You only write the JSON when calling Find Records programmatically or from an agent.
Operators
| Operator | Meaning | Example |
|---|---|---|
= | Equals | {"fieldName":"StageName","operator":"=","values":["Proposal"]} |
!= | Not equal (<> also works) | {"fieldName":"Type","operator":"!=","values":["Partner"]} |
< | Less than | {"fieldName":"Amount","operator":"<","values":["10000"]} |
<= | At most | {"fieldName":"CloseDate","operator":"<=","values":["THIS_QUARTER"]} |
> | Greater than | {"fieldName":"Amount","operator":">","values":["50000"]} |
>= | At least | {"fieldName":"CreatedDate","operator":">=","values":["LAST_N_DAYS:30"]} |
IN | Any of | {"fieldName":"StageName","operator":"IN","values":["Proposal","Negotiation"]} |
NOT IN | None of | {"fieldName":"StageName","operator":"NOT IN","values":["Closed Lost"]} |
LIKE | Pattern match | {"fieldName":"Name","operator":"LIKE","values":["%Acme%"]} |
IN and NOT IN take several values. Every other operator uses the first one and ignores the rest. A LIKE value with no % in it matches anywhere in the field: Acme runs as %Acme%.
The Studio’s filter builder offers all of these except NOT IN. Write the JSON for that one.
Date literals
Date and datetime fields accept Salesforce date literals as values:
| Literal | Meaning |
|---|---|
TODAY · YESTERDAY · TOMORROW | |
THIS_WEEK · LAST_WEEK · NEXT_WEEK | |
THIS_MONTH · LAST_MONTH · NEXT_MONTH | |
THIS_QUARTER · LAST_QUARTER · NEXT_QUARTER | |
THIS_YEAR · LAST_YEAR · NEXT_YEAR | |
THIS_FISCAL_QUARTER · LAST_FISCAL_QUARTER · NEXT_FISCAL_QUARTER | Your org’s fiscal calendar |
THIS_FISCAL_YEAR · LAST_FISCAL_YEAR · NEXT_FISCAL_YEAR | Your org’s fiscal calendar |
LAST_N_DAYS:30 | The last 30 days |
NEXT_N_DAYS:90 | The next 90 days |
LAST_N_WEEKS:6 · LAST_N_MONTHS:6 · LAST_N_QUARTERS:2 · LAST_N_YEARS:3 | NEXT_N_ works the same way |
LAST_N_FISCAL_QUARTERS:2 · LAST_N_FISCAL_YEARS:2 | Fiscal equivalents, NEXT_N_ too |
Write the literal as the value itself, with no quotes inside it: "values": ["THIS_QUARTER"]. Absolute dates work too: "2026-09-30", or an ISO datetime like "2026-09-30T17:00:00Z". Anything else on a date field comes back refused, naming the forms it takes.
Values are strings
Every value is a string in the JSON, whatever the field’s type. The engine converts based on the field:
| Field type | Write |
|---|---|
| Checkbox | "true" / "false" |
| Number, currency | "50000" — no symbols, no separators |
| Percent | "75" for 75% |
| Date | "2026-09-30" or a literal |
| Picklist | The API value, not the label |
WARNING
Filter picklists on the API value stored in the database, which isn’t always what the UI displays.
Common patterns
Open records
[{"fieldName":"IsClosed","operator":"=","values":["false"]}]
Closing this quarter, still open
[{"fieldName":"IsClosed","operator":"=","values":["false"]},
{"fieldName":"CloseDate","operator":"<=","values":["THIS_QUARTER"]}]
Meaningful deals in late stages
[{"fieldName":"StageName","operator":"IN","values":["Proposal","Negotiation"]},
{"fieldName":"Amount","operator":">=","values":["25000"]}]
Stalled: no activity in 30 days
[{"fieldName":"IsClosed","operator":"=","values":["false"]},
{"fieldName":"LastActivityDate","operator":"<","values":["LAST_N_DAYS:30"]}]
Recently created
[{"fieldName":"CreatedDate","operator":">=","values":["LAST_N_DAYS:7"]}]
The filterable surface
Find Records accepts filters and sortBy only on the entity’s filterable fields. ContextWorks refuses anything else and names the valid set, so an agent can re-plan instead of querying a field the entity never offered. Id is always accepted.
By default a field is filterable when it’s in the curated detailed set. The field picker’s Filter column overrides that per field, in both directions:
- Filter-only — declare a field filterable without returning it anywhere.
IsClosedis the shipped example: agents screen on it, it never spends payload tokens. - Return-but-don’t-filter — keep a field in payloads but stop agents filtering on it: unindexed fields on large objects, or fields where filtering gives a wrong answer.
Get Catalog with an entity’s name lists its filterable fields with their valid picklist values and sampled example values — the agent-facing half of this declaration.
Named filters
A named filter is a named condition on the entity — open, committed — passed by name in Find Records’ filterNames instead of constructed as JSON. It means whatever the admin wrote down: whether “open deals” excludes renewals is the org’s call.
Named filters resolve by name from the element library, after the filterable check and never from caller input. That is why a named filter may use fields that are not individually filterable.
They combine by AND, with each other and with filters. The catalog lists each entity’s named filters with the meaning attached to each one; an unknown name comes back refused, with the valid set.
Where filters appear
| Where | How |
|---|---|
| Find Records | The filters input, as JSON — and filterNames, named filters by name |
| Related lists | The filter builder, per list |
| Metrics | The filter builder, on the child records |
| Named filters | The filter builder, on the Filters library page |
Entity.find | req.filtersJson · req.filterNames |
Agents learn filterable field names from Get Catalog — see Invocable actions.
Limitations
- No OR across fields. Conditions AND together. Use
INfor alternatives on one field; make two calls or define two related lists for genuinely different conditions. - No nested grouping. No parentheses.
- No conditions on child records. “Accounts with more than five open cases” is a report. Parent fields do work:
Account.Industryon an Opportunity entity filters like any other curated field. - No aggregate conditions. Filters select records; they don’t test a total.
Filters narrow within what the caller can already see — they never widen access. See Security.