AI & Data5 November 20269 min read

From Conversation to Cart — Part 4 of 15

Personalisation is a constraint system

Allergies, dietary rules, budget, household size, brand preferences and the pantry are not flavour text for a prompt. They are constraints of different strengths, and the strongest must be enforced in code at every step that can change a basket. Part 4 of From Conversation to Cart shows how.

#Agentic Retail#AI Architecture#POPIA#Privacy Engineering#Data Governance#AI Agents
A shopper holding a phone in a grocery store at dusk, as a thread of light links highlighted produce on the shelves to a glowing basket on the counter.

At ten past four on a Sunday afternoon, a mother in Pietermaritzburg types into the meal assistant: "supper for four tonight, my son is allergic to peanuts, we eat halaal, keep it under R400, we already have rice". The assistant proposes a chicken curry with cucumber raita and a fruit salad. The plan is sensible. Then the curry paste turns out to be out of stock at her store, and the substitution step picks the nearest match by name and price: a satay-style paste. Nothing in the substitution step had been told about the allergy. The meal-planning prompt knew. The code that changed the basket did not.

That is the outcome at risk. A slightly wrong basket costs a sale. One that is wrong about an allergy can harm a child and end a family's trust in the retailer.

Ubuntu Grocer, the retailer in this series, is a composite: a fictional South African grocery chain whose scenario draws on lessons from real retail-agent delivery, with people, systems and figures that are illustrative and describe no single organisation. Part 3 showed how an ingredient line becomes a chosen product and quantity. This part is about the rules every one of those choices must obey.

A request is a bundle of constraints with different strengths

The message carries several instructions: an allergy, a dietary rule, a budget, a household size, a time and something already in the cupboard. Treating them as one block of "preferences" in a prompt is the root of the failure above. Pieter van Wyk, Ubuntu Grocer's principal architect, sorts them into four classes, because each class is enforced differently.

  • Hard constraints must never be violated: a declared allergen, a dietary rule such as halaal or vegetarian, a product the shopper never wants. They are filters. A product passes or it is not a candidate.
  • Bounded constraints are numeric targets with a tolerance: a budget of R400, a household of four. They are checked against the whole basket, and the shopper may trade them off, but only knowingly. "This plan comes to R432. Remove the fruit salad to get under R400?" is legitimate. Silently going over is not.
  • Soft preferences rank without excluding: a favourite brand, less spice, the house brand when money is tight. Violating one makes a basket less pleasing, not unsafe.
  • Facts about the world belong to the retailer: stock at this store or fulfilment node, pack sizes, delivery slots. They are looked up, never inferred.

The pantry answer ("we already have rice") is a soft constraint: it removes a line, but it is a claim about a cupboard, so the review screen asks the shopper to confirm it, as part 3 describes.

The constraint engine: filter in code, then rank

The design response is to turn the bundle into a typed object at the start of the journey and pass that object, not a sentence, to every step. Ruan Botha's AI engineering team calls it the constraint set. The intent agent proposes it. Deterministic code validates it against a closed list of allergens and dietary rules, and the shopper sees it confirmed before planning starts: "No peanuts. Halaal only. Up to R400. Rice left out."

The constraint engine: filter in code, then rankConstraints: no peanuts, halaal (hard) · R400 (bounded) · favourite brand (soft)About 40 candidate products from the matcher1. Hard filter in code: 7 removedallergens, halaal, unknown means excluded2. Bounded check on the whole basketabout R370 against R4003. Soft ranking with the LLMbrand, taste, price4. Basket proposal with reasonsExcluded: 4 peanut,2 no halaal, 1 blankOver budget: back toshopper as a choiceModel sees onlyeligible productsShown: what was leftout, check the pack
Ubuntu Grocer turns the shopper's message into a typed constraint set and applies it in a fixed order. Hard constraints are database predicates over catalogue attributes, so the model never sees an excluded product, and blank allergen data counts as excluded. The budget is checked on the whole basket and traded off with the shopper, and only then do soft preferences rank what is left. Counts are illustrative.

The engine works in a fixed order, and the order matters.

  1. Hard filter, in code. Each candidate product is tested against catalogue attributes: allergen "contains" and "may contain" fields, and a dietary certification with a named certifier. This is a database predicate, not a model judgement, so the model never sees an excluded product and cannot be talked into choosing one. Unknown means excluded: a product with empty allergen fields is removed for a shopper with that allergy, and the exclusion is counted, which turns a hidden data-quality problem into a measurable one that part 5 takes up.
  2. Bounded check on the whole basket. Code totals the basket against the budget, with live prices, and quantities against household size. A breach goes back to the shopper as a specific trade-off, not to the model for a quiet fix.
  3. Soft ranking. Among the survivors, the matcher and its re-ranking step, which uses a large language model (LLM), order candidates by preference, relevance and price.
  4. Proposal with reasons. The result carries its reasons: what was excluded and why, what was assumed, and what to check on the pack.

In our worked example, for illustration only, the plan starts with about 40 candidate products. The hard filter removes 7: four that contain or may contain peanuts, two without halaal certification and one with blank allergen data. The budget check passes at about R370. The numbers are invented; the shape is not. The hard filter does the safety work before any model chooses.

Constraints must travel with the journey

The opening failure was not a bad model. It was a constraint that existed in one step and not the next. Every step that can introduce a product must re-apply the hard filter itself.

Constraints travel with the journeyEVERY STEP THAT CAN ADD A PRODUCT CHECKS AGAINAGENT STEPPlan the mealConstraint setconfirmedCODE + LLMMatch productsHard filter,unknown outRULES SERVICESubstituteHard filterre-appliedCODESet quantitiesBudget andhousehold sizeAGENT STEPPropose basketRe-validatedby orchestratorJourney state held by the backend: constraint set, shopper edits, journey IDFallback path after a model timeout: same constraint set, same filter
The constraint set lives in journey state held by the backend, not in the model's context window, and every step that can introduce a product checks it again. At Ubuntu Grocer the step that first broke was substitution, an older rules service that had never received the allergy. The fallback path used when a model call fails gets the same set and the same filter.

Four places catch teams out.

  • Substitution. Often an older rules service, it must take the constraint set as input or not be called.
  • Fallback. A degraded path for when a model times out is good practice; one that drops the constraint set is not. No fallback may be less safe than the primary path, as part 10 sets out.
  • Later requests. "Add something for dessert" is checked against the same set, which lives in journey state held by the backend, not in the model's context window, where a long conversation can push it out.
  • The shopper's own edits. If she adds a peanut product by hand, that is her decision. The assistant may point out the conflict once, plainly, but it does not remove the item. Authority over the basket stays with the shopper, as part 6 sets out.

No system can promise more than its data: allergen fields copy supplier declarations, and packs change. So whenever an allergen constraint is active, the assistant says: "We have excluded products listed as containing or possibly containing peanuts. Please check the pack before use." That is where the system's knowledge honestly ends.

Sensitive information: use it for the journey, keep as little as possible

The message contains three kinds of information that South African privacy law treats with particular care. This section is general information, not legal advice.

The Protection of Personal Information Act, 2013 (POPIA), section 26, prohibits processing personal information concerning a person's health or religious or philosophical beliefs, among other categories, unless an authorisation applies. A food allergy is very likely information about health. A halaal requirement can reveal a religious belief, and a vegetarian household may be expressing a philosophical one. Section 27(1)(a) lifts the prohibition where the data subject consents, and section 1 defines consent as "any voluntary, specific and informed expression of will". The health authorisations in section 32 are written for bodies such as medical professionals, insurers and schools, so for a grocery assistant consent is likely to be the practical route, a point each retailer should confirm with its own advisers.

The son adds a third consideration. Information about a child, defined as a person under 18 who is not legally competent to act without the assistance of a competent person, falls under section 34, and section 35 allows processing with the prior consent of a competent person, normally a parent. Section 11(2) puts the burden of proving consent on the responsible party and lets consent be withdrawn at any time. Section 10 requires information to be adequate, relevant and not excessive for its purpose.

In design terms:

  • Confirm the use, even for one journey. Processing within a single journey still relies on an authorisation, so the confirmation step ("No peanuts. Halaal only.") says what the information will be used for and asks the shopper to confirm. By default the set is discarded when the journey ends.
  • Separate consent to remember. "Remember 'no peanuts' for future meal plans?" is a second, separate question, asked when it is useful, recorded with a timestamp and wording version, and reversible from the profile screen. It is not buried in the app's terms.
  • Keep the instruction, not the reason. The profile stores exclude: peanut, strength: hard, not "my son, age seven, carries an adrenaline auto-injector". The stored code is still health information and needs the same consent, access control and withdrawal path: minimising it reduces the harm, not the obligations. Our article on agent memory and POPIA applies the same pattern.
  • Do not infer. The assistant does not conclude that a household is halaal from its purchase history, or that someone is diabetic from what they stopped buying. An inference about health or religion can itself be sensitive information that was never volunteered.
  • Keep it out of telemetry. Free text is redacted before it reaches long-lived logs and traces; the constraint set is recorded as codes.

Our guides on which data AI can touch and lawful basis as a design input cover the wider method. The constraint set is both a safety mechanism and a sensitive record, and must be designed as both.

The trade-offs

A strict engine produces smaller baskets: a small convenience store may have no eligible curry paste at all. Lindiwe Dube, who owns the commercial outcome, accepted that cost, and the assistant offers a different recipe rather than a risky product.

Some shoppers accept "may contain" products and know their own risk, so a shopper may relax that one rule explicitly, per allergen. The default stays strict.

Strength classes need a policy owner. Whether a R400 budget tolerates R410 is a business decision, written down, versioned and tested like any other rule.

Questions to take into your architecture review

  1. Is the request turned into a typed constraint set before planning, and does the shopper see it confirmed?
  2. Which constraints are hard, bounded and soft, who decided, and where is that written down?
  3. Is the hard filter a code or database predicate over catalogue attributes, applied before any model chooses?
  4. What happens to a product with blank allergen or certification data? Show the test.
  5. List every step that can introduce a product, including substitution and fallback. Which re-apply the hard filter?
  6. What is saved to a profile, with what consent wording, and how is consent withdrawn?
  7. Do prompts, traces or logs hold allergy, religious or child-related free text, and for how long?

Key points

  • A personalised request is a bundle of constraints of different strengths: hard, bounded, soft and facts about the world.
  • Enforce hard constraints as code-level filters over catalogue attributes before any model chooses, and treat unknown data as excluded.
  • Every step that can add a product, especially substitution and fallback, must re-apply the hard filter.
  • Trade bounded constraints such as budget with the shopper, never silently.
  • Allergy, religious and child-related information is sensitive under POPIA. Confirm its use, save it only with separate consent, minimise it and never infer it.

CloudNala's point of view

Most personalisation failures we see in reviews of retail-agent programmes are constraints written into a prompt that never reached the code that changed the basket. Our test is blunt: delete the prompt, and ask whether the system would still refuse to put a peanut product in that boy's basket. If not, the safety lives in the wrong place.

Next: Part 5, The catalogue is the real retail knowledge base. All parts are on the series page.

Background reading: Protection of Personal Information Act, 2013 (gov.za), sections 1, 10, 11, 26, 27, 32, 34 and 35, checked on 5 November 2026.

How CloudNala can help

CloudNala reviews personalisation designs for retail assistants. We classify every constraint a shopper can express, trace each through every step that can change a basket, test the hard filters adversarially and review consent and telemetry against POPIA with your information officer.


Work with CloudNala

CloudNala helps organisations move from technology ambition to practical execution across cloud, AI, data, platform engineering and digital services.

Whether you are exploring AI, modernising your cloud environment, building a public-sector digital service, or turning an idea into a working MVP, we can help you shape the roadmap and deliver the next step.

Book an Agentic Retail Review or write to us at consult@cloudnala.co.za