Appearance
Filters & attributes β
How to narrow product search by attribute β brand, price, sticker, vendor code β when your agent queries your catalog. This applies to the in-product sales agent (which builds filters for you automatically) and to any external agent you wire up over the Product (commerce) MCP. Read this when you need to constrain results by attribute, or when a filter "silently returns nothing."
In the app
You don't hand-write filters for the in-product agent β it applies them for you while it searches. You build filters by hand only when you connect your own agent to the catalog over the Product MCP. Either way, the catalog itself is connected and managed under Knowledge Base β your product integration (https://app.mychatbot.app/knowledge-base).
Cheat sheet β
Which filters each search tool honors β
Every filter-accepting tool enforces all ten operators with the same semantics β including whole-catalog semantic_product_search. A filter is never silently ignored; the remaining skill is matching the operator to the intent and the attribute's shape.
| Search tool | What it does | Filters it honors |
|---|---|---|
semantic_product_search | Free-text semantic search across your whole catalog | all ten operators |
filter_category_products | Lists products in one category, with filters | all ten operators |
get_available_filters | Shows which attributes/values you can filter on within a category | all ten operators |
get_category_attributes, get_category_attribute_values | Discover the exact attribute names and their real values | discovery only β no filters |
get_product_details, get_product_variants, find_similar_products, get_products_by_ids, get_all_categories | Detail / lookup / browse | no filters |
Which operator fits which intent
Exact values and list membership β eq / in. Excluding a value or element β ne. Partial text anywhere in a string, case-insensitive β contains. Numeric ranges (price >= 20) β gt/gte/lt/lte β bounds may be numbers or numeric strings, and the comparison is numeric even on attributes stored as text. Known-case prefixes/suffixes β startswith/endswith (case-sensitive, whole stored string).
One nuance worth knowing. On a whole-catalog search, eq/in/contains also guide which candidate products get retrieved from the compact searchable copy of each product's attributes; the comparison and prefix operators don't steer that retrieval β they are applied as a strict constraint on everything that comes back. Practically: keep the descriptive intent in query, use filters as hard constraints, and make sure a range-filtered attribute holds values that read as plain numbers (get_category_attribute_values shows them). A range means the attribute exists and compares: products that lack the attribute don't match, and neither do values with no numeric reading against a numeric bound (decorated values like "1 200 Π³ΡΠ½" are excluded, not passed through) β so a range on an attribute the catalog doesn't carry returns nothing.
What a filter looks like β
A filter is a small object:
json
{ "attribute": "brand", "operator": "eq", "value": "Numbuzin" }attributeβ the attribute name exactly as it appears in your feed (case- and underscore-sensitive; MyChatBot does no rewriting). The reserved attributenametargets the product's top-level name.operatorβ one ofeq,ne,gt,gte,lt,lte,in,contains,startswith,endswith. All of them are enforced on every filter-accepting tool.valueβ a single value, a list whenoperatorisin, or a nonblank string whenoperatoriscontains. For the range operators a number and a numeric string (50/"50") behave identically β both compare numerically.
Multiple filters are AND-ed together:
json
{
"query": "hydrating serum",
"filters": [
{ "attribute": "brand", "operator": "eq", "value": "Numbuzin" },
{ "attribute": "skin_type", "operator": "in", "value": ["dry", "normal"] }
]
}Range filter β works on semantic_product_search and the category tools alike, as long as the attribute's stored values read as plain numbers (they may be stored as text):
json
{
"query": "hydrating serum",
"filters": [
{ "attribute": "price", "operator": "gte", "value": 20 },
{ "attribute": "price", "operator": "lte", "value": 60 }
]
}Look up the real attribute names first
Because attribute must match your feed exactly, discover the available attributes and their real values with get_category_attributes and get_category_attribute_values before you build a filter. In the app you can see the same attributes on your product integration's page (Knowledge Base β your product integration βhttps://app.mychatbot.app/knowledge-base).
Partial string matching with contains β
Use contains when the shopper knows only part of a product name or another string attribute. It performs a case-insensitive literal substring match: ASHEN matches a name such as The Ashen Evening Dress wherever the fragment appears.
json
{
"query": "evening dress",
"filters": [
{ "attribute": "name", "operator": "contains", "value": "ASHEN" }
]
}attribute: "name" targets the product's top-level name rather than a feed attribute called attr_name. Use it with semantic_product_search for catalog-wide lookup or filter_category_products when the category is known. get_available_filters also accepts it to narrow facet counts, but does not return products; both category tools require a category_id.
contains accepts a nonblank string and applies only to string fields. It is not a numeric or boolean operator. Wildcard characters such as * and ? are treated as ordinary text, not as patterns.
Stickers, coverage lists & other multi-value attributes β
Some attributes hold several values per product β a native list (stickers), or one string that joins values with commas (e.g. a cities within radius coverage list). eq matches these element-wise: it matches the full stored value exactly, or any single element of the list. Full-string equality is exact (case preserved); the element match is case-insensitive and ignores surrounding whitespace. in matches when any element equals any of several accepted values:
json
{
"query": "gift sets",
"filters": [ { "attribute": "stickers", "operator": "eq", "value": "ΠΠΎΠ΄Π°ΡΡΠ½ΠΎΠΊ" } ]
}This returns every product whose stickers include ΠΠΎΠ΄Π°ΡΡΠ½ΠΎΠΊ, regardless of its other tags. Likewise { "attribute": "cities within radius", "operator": "eq", "value": "Rosneath" } matches a record whose comma-separated coverage list contains Rosneath as an element. A filter value that itself contains a comma can only match as the full stored string β it can never be a single list element.
How the other operators treat multi-value attributes:
neis the exact negation ofeq: it matches only when no element equals the filter value (case-insensitive) and the full stored value differs βcities within radius ne "Rosneath"excludes every record covering Rosneath.gt/gte/lt/lteon a native list match when any element satisfies the comparison. A comma-separated string is not split for ranges β it compares as one string, which is rarely what you want; range-filter typed numeric attributes instead.startswith/endswithon a native list match when any element carries the prefix/suffix (case-sensitive). A comma-separated string is tested whole β its elements are not split out; useeq/infor membership orcontainsfor fragments.
Use eq for list membership β never contains
contains is a substring match and matches inside words: on a coverage list containing Rosneath, contains "Neath" wrongly matches, while eq "Neath" correctly does not (Neath is not an element). Filter list membership with eq/in; keep contains for genuine partial-text lookups in one string field.
Filtering by SKU or product code β
Identifier attributes are not filterable on whole-catalog semantic search β they're deliberately kept out of the searchable-attributes copy and handled by exact-match ranking instead. An attribute is treated as an identifier when its name contains any of these as a whole word:
vendorcode, productcode, sku, upc, ean, isbn, mpn, asin, barcode,
model, part, product_id, item_id, catalog, article, Π°ΡΡΠΈΠΊΡΠ»Matching is by whole word, not substring β product_id and item_id count, but ordinary words that merely contain one of these (e.g. departure contains "part", compartment) are not treated as identifiers.
Filtering by SKU on semantic search returns nothing
An eq/in filter on sku, vendorcode, barcode, etc. can't be satisfied by whole-catalog search. To match exact codes:
- Put the code straight in
query. MyChatBot automatically boosts exact code/SKU matches and skips semantic ranking for code-like queries, so the exact item lands on top. - Fetch by id with
get_products_by_idswhen you already know the product id. - To filter on a code column directly, use
filter_category_productsinside that product's category (you may need a reindex first β see below).
The vendor-site URL attribute β
URL-valued attributes (image links, a vendor site link) are excluded from filtering like other links. The Ukrainian vendor-site link attribute ΠΏΠΎΡΠΈΠ»Π°Π½Π½Ρ Π½Π° ΡΠ°ΠΉΡ (romanized posilannya-na-sayt; ΠΠΎΡΠΈΠ»Π°Π½Π½Ρ_Π½Π°_ΡΠ°ΠΉΡ and ΠΏΠΎΡΠΈΠ»Π°Π½Π½Ρ_Π½Π°_ΡΠ°ΠΉΡ are also recognized) gets extra ranking weight so "find the product at this vendor URL" queries land on the exact item. MyChatBot tunes this behind the scenes.
When a filter returns nothing β
An empty result isn't always a real "no results"
A catalog indexed before the current searchable-attributes copy existed can have a missing attribute blob, so exact filters can't match even when the value genuinely exists.
Tell-tale: semantic_product_search with a filter returns [], but get_category_attribute_values (or filter_category_products) shows the value is really there.
Fix β a from-scratch reindex. This isn't a self-serve toggle. Either delete and re-add the integration in Knowledge Base (https://app.mychatbot.app/knowledge-base), or contact MyChatBot support with the integration id and ask them to reindex it.
MyChatBot tunes search relevance for you
Result ordering blends semantic similarity, keyword matching, exact-code boosts, and the special URL weighting above. These weights aren't self-serve β MyChatBot tunes relevance for your catalog. If ranking or filtering doesn't fit your inventory, contact support.
Best practices β
Do
- Use
eq/infilters for categorical facets (brand, sticker, condition) and list membership (native lists and comma-separated attributes),containsfor partial text in string fields such asname,neto exclude a value or element, andgt/gte/lt/ltefor typed numeric ranges β onsemantic_product_searchtoo. - Look up attribute names and values with
get_category_attributesandget_category_attribute_valuesbefore building a filter, soattributematches the feed exactly β and so you know a range-filtered attribute is really numeric. - Put SKUs/barcodes in
query, not in a filter, and let exact-code boosting do the work.
Don't
- Don't range-filter attributes whose values don't read as plain numbers (
"1 200 Π³ΡΠ½") β those pairs cannot be compared numerically. Bounds may be numbers or numeric strings; both behave identically. - Don't use
startswith/endswithwhen case or position is uncertain β they are case-sensitive and test the whole stored string;containsis the forgiving option. - Don't use
containsfor list membership or numeric/boolean fields β it matches inside words (contains "Neath"matchesRosneath); useeq/infor membership and comparison operators for typed numbers. - Don't filter by SKU/
vendorcodeon semantic search β those aren't filterable there. - Don't assume a filter that returns
[]is a real "no results" β on an older catalog it may be a stale index; fix it with a from-scratch reindex (delete & re-add, or ask support).
Test it (over the Product MCP) β
json
// 1. Discover the exact attribute name + type
{ "tool": "get_category_attributes", "category_id": "skincare_serums" }
// 2. See the real values you can filter on
{ "tool": "get_category_attribute_values",
"category_id": "skincare_serums", "attribute_name": "brand" }
// 3. Apply an eq filter on semantic search
{ "tool": "semantic_product_search",
"query": "brightening serum",
"filters": [ { "attribute": "brand", "operator": "eq", "value": "Numbuzin" } ] }
// 4. Verify a partial product-name match (case-insensitive)
{ "tool": "semantic_product_search",
"query": "evening dress",
"filters": [ { "attribute": "name", "operator": "contains", "value": "ASHEN" } ] }
// 5. Confirm range filters via the category tool
{ "tool": "filter_category_products",
"category_id": "skincare_serums",
"filters": [ { "attribute": "price", "operator": "lte", "value": 40 } ] }If step 3 returns [] but step 5 (or get_category_attribute_values) shows the value exists, the catalog's searchable-attributes copy is likely stale β fix it with a from-scratch reindex (delete & re-add the integration, or ask MyChatBot support).
See also β
- Search tools reference β the full tool list, params, and return shapes.
- Getting inventory in β connecting a catalog and how attributes become filterable.
- How search works β the search pipeline these filters run through.
- Image search β image-based product matching.
- Troubleshooting & best practices β stale-index, name-pollution, and SKU-filtering gotchas in depth.
- Product (commerce) MCP β the MCP endpoint that exposes these search tools to your agent.