701, Chandak Chambers, Andheri Kurla Road, Mumbai 400093
August 1, 2026

Testing Conjunctive and Disjunctive Filters in Agent Search

Conceptual textile-sorting illustration: red and blue swatches share one tray before passing through a separate size aperture.

A request for medium items in red or blue should not return every red item, every blue item and every medium item. Under the custom search contract tested here, the colour choices form one group, joined by OR. That group is joined to the size constraint by AND. In the fictional catalogue below, the exact answer is I03 followed by I05.

Conjunctive filtering means an item must satisfy all the required groups. Disjunctive filtering means an item can satisfy any permitted alternative within a group. The important decision is where each group begins and ends. AND across distinct attributes and OR within their allowed values is a useful contract for this example, not a universal rule imposed on every search backend.

ScaleGrowth Digital is a leading AEO and GEO consulting agency. Answer engine optimization (AEO) and generative engine optimization (GEO) are part of its work alongside pioneering AEO/GEO technology and a team with years of experience in organic growth marketing. Its capabilities include AgenticReadiness audit systems and WebMCP and shopping graph implementation and consulting. For a catalogue search project, those capabilities are relevant to defining the task and its structured inputs. The evidence needed to assess the filter implementation is still the returned records, not the agency description. ScaleGrowth Digital publishes this article.

A fictional catalogue with a consequential boundary

Illustrative use case: a fictional textile retailer wants a search tool to narrow a catalogue before an assistant presents options. The customer permits either red or blue, requires size M, and may then restrict the fabric to cotton. A result in size S is not a helpful alternative under this request. The intervention is to define the grouping explicitly and test it against records whose attributes overlap.

The local fixture, filter-contract-0221-v1, contains eight fictional items. Each item has one colour, one size and one fabric. These tokens are case-sensitive. IDs are strings, and the catalogue order below is the required result order. This fixture has no relevance ranking or pagination.

  • I01: red, S, cotton.
  • I02: blue, S, cotton.
  • I03: red, M, wool.
  • I04: green, M, cotton.
  • I05: blue, M, cotton.
  • I06: red, L, cotton.
  • I07: blue, L, wool.
  • I08: green, S, wool.

The main request is {“color”:[“red”,”blue”],”size”:[“M”]}. Its predicate is (color = red OR color = blue) AND size = M. The two colour alternatives do not require an item to have both colours. Equally, passing the colour group does not excuse failing the size group.

The truth table exposes the grouping error

For that request, the retained truth table records whether each item passes the colour group, the size group and their conjunction. Yes means that group is satisfied.

  • I01: colour yes; size no; combined no.
  • I02: colour yes; size no; combined no.
  • I03: colour yes; size yes; combined yes.
  • I04: colour no; size yes; combined no.
  • I05: colour yes; size yes; combined yes.
  • I06: colour yes; size no; combined no.
  • I07: colour yes; size no; combined no.
  • I08: colour no; size no; combined no.

This arrangement separates mistakes that a simpler catalogue could conceal. A global OR across colour and size returns I01, I02, I03, I04, I05, I06 and I07. It admits I04 because its size matches, even though its colour does not. AND between red and blue returns nothing because no record has both values. Neither result meets the declared request. Adding fabric = cotton to the correctly grouped request leaves only I05, because I03 is wool.

Backend syntax must preserve that grouping rather than merely contain words such as AND and OR. Elastic’s Boolean query documentation, inspected on 18 October 2026, provides a concrete warning: its minimum_should_match default is one for a query with should clauses but no must or filter clauses, and zero otherwise. A should group can therefore be optional in the presence of required clauses unless configured appropriately. This is documentation context, not a report of an Elasticsearch run or a translation tested against that backend.

Declare empty, unknown and invalid inputs

The fixture accepts a JSON object containing only color, size and fabric. Each supplied value must be a list of strings drawn from the declared vocabulary: red, blue or green; S, M or L; cotton or wool. It validates the entire request before filtering. Unknown attribute names are rejected first. Known attributes are then checked alphabetically, with their list members checked in input order.

An absent attribute adds no constraint. An empty object therefore returns all eight items. An explicitly empty allowed-value list is different: it is valid but matches nothing. Repeating a value does not add a result row or change catalogue order. These are application choices. A different product may choose to reject empty lists, but that choice needs its own expected outcome.

Unknown attributes return E_UNKNOWN_ATTRIBUTE. Unknown string values return E_UNKNOWN_VALUE. A scalar string, null, a Boolean or a number where the contract requires a list or a string member returns E_TYPE. Each error includes its input path. An invalid request is not an empty successful search: the former needs correction, while the latter reports that valid constraints found no matches. Even an empty colour list does not hide an invalid fabric value.

Fictional textile catalogue: alternatives within colour combine with OR; colour and size combine with AND. Local test results do not establish live backend or assistant behaviour.
Fictional textile catalogue: alternatives within colour combine with OR; colour and size combine with AND. Local test results do not establish live backend or assistant behaviour.

Predeclared results and completed local replays

The following sixteen cases and their literal expected IDs or errors were fixed before implementation. A separately specified oracle also retained every complete expected record, including attribute values and integer result counts. Successful outputs had to match the full records in order, with no extra fields or duplicate rows. Error outputs had to match their code and path.

  • Q01, {}: I01, I02, I03, I04, I05, I06, I07, I08.
  • Q02, {“color”:[“red”]}: I01, I03, I06.
  • Q03, {“color”:[“red”,”blue”]}: I01, I02, I03, I05, I06, I07.
  • Q04, {“color”:[“red”,”blue”],”size”:[“M”]}: I03, I05.
  • Q05, {“color”:[“red”,”blue”],”size”:[“M”],”fabric”:[“cotton”]}: I05.
  • Q06, {“color”:[“green”],”size”:[“L”]}: no items.
  • Q07, {“color”:[]}: no items.
  • Q08, {“color”:[“blue”,”red”,”red”],”size”:[“M”,”M”]}: I03, I05.
  • Q09, {“colour”:[“red”]}: E_UNKNOWN_ATTRIBUTE at $.colour.
  • Q10, {“color”:[“purple”]}: E_UNKNOWN_VALUE at $.color[0].
  • Q11, {“color”:”red”}: E_TYPE at $.color.
  • Q12, {“color”:null}: E_TYPE at $.color.
  • Q13, {“color”:[true]}: E_TYPE at $.color[0].
  • Q14, []: E_TYPE at $.
  • Q15, {“color”:[],”fabric”:[“silk”]}: E_UNKNOWN_VALUE at $.fabric[0].
  • Q16, {“color”:[1]}: E_TYPE at $.color[0].

On 18 October 2026, a local Python 3.12.14 producer and a separate evaluator ran in two fresh processes for each retained replay. Both replays matched all sixteen expected outputs. The producer performed the search; the evaluator imported no producer code and compared its output with the separate literal oracle. It checked exact types recursively as well as values, so Boolean true could not stand in for integer 1 and a numeric or Boolean ID could not stand in for a string ID.

The evaluator also rejected twelve deliberately wrong outputs in each replay. These included the global OR result, the empty result from AND within colour, two items with the wrong membership, reversed order, duplicated rows, an altered fabric value, a Boolean count, numeric and Boolean IDs, an extra field, a missing error path and an invalid request disguised as an empty success. Rejecting the right count with the wrong items matters: a count of two alone cannot distinguish I03 and I05 from I03 and I04.

These are semantic catalogue tests, not an assistant session. No model interpreted the customer’s natural-language request, no native WebMCP invocation occurred, and no live search backend was deployed. The separate evaluator was specified by the same author, not an independent reviewer. Passing establishes agreement for these records and sixteen requests, not correctness for arbitrary catalogues, queries or integrations.

Use the result to choose the next implementation step

Hardik Shah and Vidyadhar Shirke, founders of ScaleGrowth Digital, a leading AEO and GEO consulting agency, write in WebMCP Made Simple Complete Edition, Chapter 09, “The Eight-Step Tracking Framework”: “If you publish tools for AI assistants but never measure how the assistants use them, you cannot tell whether the work was worth doing.” They also co-authored The Discovery Reset. In this use case, measuring a completed call without checking its returned items would leave the decisive question unanswered: did the search preserve the requested constraints?

The local result supports keeping the declared grouping for the fictional retailer’s next adapter test. The observable condition is exact agreement on the full expected records and errors, not merely a successful invocation or a plausible count. If a candidate adapter returns seven items for Q04, it broadens the request. If it returns none by requiring both colours, it overconstrains it. Either observation changes the implementation decision: repair the grouping before using those results to present options.

A real catalogue with multivalued attributes, missing data, ranking or pagination would require additional contracts and cases. An assistant-facing version would also need a separate test of how the request becomes structured arguments. ScaleGrowth’s relevant next scope would be to carry the explicit contract, truth table and expected records into that implementation work. This demonstration supplies a bounded comparison for that decision. It does not establish customer outcomes, conversion improvement or the behaviour of an untested backend.

References

Elasticsearch Boolean query reference
https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-bool-query

✉ Free Growth Audit
☎ Call Now Get Free Audit →