- A supplier imports a product called “heavy-duty wall-mounted utility sink”.
- The category sounds perfect. It also does not exist in the marketplace.
- That is the dangerous part of unconstrained catalogue AI: a plausible answer can still corrupt navigation.
- For a procurement marketplace with a large supplier catalogue, we built the flow in the opposite order.
The client problem
A supplier imports a product called “heavy-duty wall-mounted utility sink”. The AI confidently assigns it to “Commercial Washroom Equipment”.
The category sounds perfect. It also does not exist in the marketplace.
That is the dangerous part of unconstrained catalogue AI: a plausible answer can still corrupt navigation. The model may invent a category, choose an obsolete branch, misunderstand a technical specification or return a label that cannot be linked to a real Medusa record.
For a procurement marketplace with a large supplier catalogue, we built the flow in the opposite order. Elasticsearch first retrieves a bounded set of relevant categories from the live marketplace taxonomy. Those categories are mapped back to Medusa IDs and stored with the product. Only then does the model choose among them. The ingestion path checks that the returned ID belongs to the exact stored set before creating any category link.
AI interprets the product. Medusa defines what categories are allowed to exist.
The client problem: manual classification does not scale, open classification does not govern
An imported supplier catalogue can contain thousands of products with inconsistent titles, sparse descriptions and specifications written in different formats.
Manual classification gives people full control but creates a queue that grows faster than catalogue operations can clear it. Asking a language model to produce a category name removes the repetitive work but creates a new problem: the answer is not anchored to the marketplace's taxonomy.
Even when the invented label is sensible, it can split reporting and navigation. “Safety Gloves”, “Protective Gloves” and “Hand Protection” may all describe the same family while only one is canonical. A model may also select a parent category when buyers need a leaf, or use a category removed since the prompt was designed.
The solution is not to choose between people and AI. It is to divide authority: retrieval proposes real possibilities, the model reasons within them, deterministic code validates the decision, and operators handle the exceptions.
Start from the product evidence the catalogue already owns
Candidate quality depends on the product description supplied to search.
The workflow reads uncategorised products in stable ID order. It uses title and description, then gathers specifications from canonical product-attribute relationships. Legacy metadata remains a fallback when structured attributes are unavailable, but it does not outrank the governed product model.
This matters because procurement products are often distinguished by dimensions, materials, standards, compatible equipment or intended environment rather than marketing copy. “Anchor” means little on its own; diameter, substrate and load context may separate several branches.
By building the retrieval query from the current product and canonical specifications, the system gives Elasticsearch the best available evidence before involving a model.
The same evidence later appears in the model prompt, so retrieval and classification reason about one product rather than two different representations.
Let Elasticsearch narrow the taxonomy first
Elasticsearch is used here as a candidate generator, not the final classifier.
Its category index can match product language and specifications against real category documents. The workflow retrieves a bounded list of the strongest candidates for each product rather than passing the entire taxonomy to the model.
This has three benefits. Relevance improves because the model compares nearby choices instead of scanning an enormous hierarchy. Prompt size stays bounded. Most importantly, every proposed option came from the marketplace's indexed taxonomy.
Candidate lookups run with bounded concurrency so a catalogue page does not launch an uncontrolled number of search requests. Search failures are kept separate from a legitimate “no candidates” outcome; an outage should be retried, not misread as proof that the taxonomy has no match.
Retrieval reduces the problem from “name any category” to “choose the best of these real possibilities”.
Map search handles back to live Medusa IDs
A search result is not yet authority.
Elasticsearch may carry a category handle or document identity, but the catalogue change must target a current Medusa product-category record. Before storing candidates, the workflow builds a mapping from live category handles to their Medusa IDs.
Candidates without a valid live mapping are dropped. The retained candidates carry a Medusa category ID, name, description and retrieval confidence. Only identifiers in the expected product-category shape move forward.
This catches drift between the search projection and the commerce source. If Elasticsearch still knows an old category that Medusa no longer exposes, that result cannot quietly become a link.
The distinction reflects the architecture of the platform: Elasticsearch helps discover relevant choices, while Medusa owns the category entities that organise products and buyer navigation.
Store the candidate set with the product
Candidate retrieval and model completion do not necessarily happen in the same process or at the same time.
The workflow therefore stores the bounded candidate set in the product's import metadata and marks the product as having candidates. The later batch-construction phase reads that exact set when building the model request.
This creates a small but important audit boundary. The system knows which choices were offered for that product. Ingestion can compare the answer with the same set rather than rerunning a search after the taxonomy or index changed.
It also separates operational failures cleanly. A product with no usable stored candidates is sent to review rather than producing an open-ended model request. A product whose Elasticsearch lookup failed has a retryable search-error reason.
The candidate set becomes the contract between retrieval, inference and validation.
Constrain both the prompt and the response format
The model receives product name, description and specifications alongside the retrieved candidates. It is asked to select a candidate ID or return an explicit uncategorised decision.
The structured response format enumerates the allowed category IDs. This makes the expected output unambiguous and lets the provider enforce a tighter shape than free text.
However, prompt and schema constraints are not treated as the final security boundary. Models and external APIs can still return malformed, stale or unexpected data. The backend validates again during ingestion.
This defence-in-depth is inexpensive because the allowed set is already stored. The model does not receive permission to create a category, rename taxonomy or choose a sibling outside the retrieved candidates.
It performs the part it is good at: comparing product meaning with a short list of plausible options.
Reject a confident answer when it is outside the set
When model results return, the ingestion workflow loads each product and reconstructs the valid candidate-ID set from its stored metadata.
If the recommended category is inside that set, the result can move toward assignment. If it is missing, malformed or outside the set, the product is marked with an invalid-ID review reason and no category link is created.
This check prevents a fabricated pcat_... value from being accepted merely because it looks like a Medusa identifier. It also protects against mismatched batch lines: a real category valid for product A is not automatically valid for product B.
The validation is product-specific. The question is not “does this category exist somewhere?” but “was this category one of the governed candidates recorded for this exact product?”
A confident model answer remains a proposal until deterministic catalogue code accepts it.
Preserve why a product could not be classified
“Failed categorisation” is too broad to operate.
The pipeline distinguishes several outcomes. No Elasticsearch candidates suggests a retrieval or taxonomy gap. A search error suggests infrastructure and remains retryable. A model-declared data conflict means title, description or specifications contradict each other and the product content needs repair. A no-match decision means the evidence is coherent but none of the candidate categories fits. An outside ID means the model response violated the candidate contract.
These states lead to different work. Retrying a data conflict wastes model calls. Editing product data will not repair an Elasticsearch outage. Expanding taxonomy may help no-match products but should not be the automatic response to an invalid model ID.
By preserving the reason, the platform turns exceptions into a review queue rather than a pile of mysterious uncategorised products.
Do not confuse retrieval confidence with catalogue truth
Elasticsearch candidates include a confidence signal from retrieval. The model also returns its own classification confidence.
Neither number changes the authority boundary. A high score can help rank work or explain why an option was chosen, but it does not allow a category outside the recorded set. A low score can help route a product to review without proving the recommendation is wrong.
This is especially important in technical catalogues, where ambiguous language and sparse supplier data are normal. Numeric confidence looks precise but depends on the evidence and candidate space supplied.
The pipeline uses confidence as context. Category IDs, candidate membership and product lifecycle rules determine what the system is allowed to change.
That keeps an uncertain product from becoming a taxonomy mutation just because the model produced a decimal.
Keep publication separate from categorisation
Assigning a valid category does not mean a product is ready for buyers.
The ingestion path applies valid category decisions and records the result, but non-published products move into a proposed state rather than being silently released. Product copy, price, imagery, supplier readiness and other catalogue checks still have their own responsibilities.
This separation makes AI useful without granting it control over the final commercial decision. Categorisation removes repetitive taxonomy work. Publication remains a broader product-governance event.
Operators can inspect failure reasons, reset unresolved items for a targeted later run and preserve successful assignments. The next article in this cluster examines that human publication boundary in detail.
For this workflow, the key point is simple: choosing an allowed category is one decision, not permission to sell.
Why Medusa and Elasticsearch each have a clear job
Medusa owns products, category records, links and lifecycle state. Elasticsearch supplies fast retrieval over a search-optimised projection of the taxonomy. The model compares meaning among a bounded set.
No component is asked to do everything.
If Elasticsearch proposes a stale handle, live Medusa mapping rejects it. If the model invents an ID, candidate validation rejects it. If a valid category is selected, Medusa records the link. If the product is not ready for publication, its lifecycle remains proposed.
This architecture is why an extensible commerce engine matters. We could add an asynchronous intelligence layer around the catalogue without moving taxonomy ownership into an external model or search index.
AI accelerates the client's catalogue operation while the commerce platform stays authoritative.
The grounded-categorisation checklist
Before allowing AI to classify products, ask:
- Which product fields provide reliable classification evidence?
- Do canonical attributes outrank legacy metadata?
- Does retrieval search the live category projection?
- Is candidate count bounded per product?
- Is search concurrency bounded per batch?
- Are search errors different from no candidates?
- Are retrieved handles mapped to current Medusa IDs?
- Are unmapped or malformed candidates removed?
- Is the candidate set stored with the product?
- Does the model receive only that set?
- Does the structured output enumerate allowed IDs?
- Does ingestion validate membership again?
- Are invalid IDs prevented from creating links?
- Can operators distinguish conflict, no match and infrastructure failure?
- Does categorisation remain separate from publication?
These controls let AI reduce work without expanding its authority.
The broader lesson
Do not ask a model to design your catalogue while it classifies your products.
For this marketplace, Elasticsearch first retrieves relevant categories from the real taxonomy. The workflow maps them to live Medusa IDs and stores the bounded set with each product. The model chooses inside that set, and ingestion verifies the exact product-specific membership before writing a link.
Exceptions retain useful reasons and move to operators. Valid classifications improve the catalogue without publishing products automatically.
The pattern applies beyond categories: whenever AI selects a business entity, retrieve the allowed entities first, constrain the choice and validate it again at the write boundary.
