Skip to main content
This guide builds, with synthetic examples, what a fashion store turns on in Niadra for a shopping assistant that works on WhatsApp and in the app: the state of the items, what the customer wants and refuses, what the agent may claim about price and stock, coordination with the after-sales agent and the measurement of what the assistant sold. Each part is a feature of the space, turned on by itself; nothing here depends on everything being on.

What the sector asks for

  • An item has a price and a stock that change by the minute, and an agent that states “we have it in your size” needs a value from seconds ago.
  • The customer says what she does not want (“nothing in black”), and a search that ignores that wastes the conversation.
  • The same cart passes through two agents and the store’s checkout, and the order arrives hours later: the sale must be tied to the exact card the assistant showed.
  • An after-sales agent and a campaign agent contact the same person; one of them must wait.

1. The types: item, order and the assistant’s state

The store item is a shared type: it exists in Niadra while someone sees it, engages with it or watches it. Price and availability come live from the e-commerce platform; a search snapshot may be shown, never claimed. Derive the type from the variants table with niadra types derive and complete what only the store knows:
The order is a customer type (ownership: subject), with its lines, the success states (delivered, kept) and the exposure token stamp on each line, which outcome measurement reads. The assistant’s working state is a type with ownership: agent: the step of the service, the offer shown and a cart note marked pii, with a 16 KB cap and 30 days of retention (Working memory). With the types in the object-types document and the state feature on, the platform pushes state through POST /v1/objects/push and a resolver worker re-reads what Niadra asks for.

2. The assistant’s turn

Each answer of the assistant is a recorded turn: the context read with the constraints block and the state, the item search, what the list showed, the answer.
“Nothing in black” and “size 40” become, through the signals, a stated hard constraint and a stated attribute; on the next turn the constraints block already carries them, rendered for search_products through the binding (exclude_colors: ["black"], size: "40"), and Niadra measures, call by call, whether the search honored what it was sent. In TypeScript, the exposure interactions travel as batch items (the cURL tab of the signals page).

3. The claim contract

The assistant states prices, promotions and availability. The retail contract checks each number against what the search returned, in the agent’s process, without a model:
“Was R299.90,nowR 299.90, now R 199.90”: both numbers have a role (price_list and price_sale, by the terms “was” and “now”), and each is checked against the value of the same role the search showed, within the 15 seconds of claim_max_age. A price that went stale in the chat is rewritten only when unequivocal (a literal copy of the field, with the fresh value in the turn); “sold out” with no search in the turn is no_evidence, marked. “I reserved the 40 for you” without a reserve_item call is a promise without an action. “Want me to sort by color?” never triggers: it is in the negative corpus, which the CI’s niadra contract test maintains. See Claims.

4. Coordination: one farewell, one budget

Two agents talk to the same customer: the assistant, in the conversation, and the campaign one, which sends an offer days later. The store’s coordination document declares the marketing purpose with a budget of 2 contacts per 7 days and a required token, the whatsapp channel with a 24-hour window and a paid template outside it, and the store’s WhatsApp gateway. The conversation’s farewell is an effect with a key, so it goes out once, whichever agent tries it:
The store’s WhatsApp gateway checks the token without talking to Niadra and lets the offer out once (Gateways). The third offer in the week gets deny with budget_exhausted and the time the next one frees; a customer who asked not to receive offers is on the suppression list, which the campaign agent honors even with Niadra out of reach.

5. The sale, order by order

The order arrives from the platform as a system event, with the exposure token the app copied into each cart line. The measurement document declares the outcome:
A line with a valid token is attributed to the exact card, deterministically (line); one without a token, to the same item the customer engaged with in the 7-day window (identity, probable, with the method’s confidence next to the value). A line returned for size becomes an inferred attribute, which applies only when the customer asks for “my size”. GET /v1/measure/attribution adds up by day, agent and method, and POST /v1/measure/reconcile checks the total against the store’s BI CSV. Before running an experiment on the constraints block, niadra counterfactual --tool search_products --element hard says, from the recorded turns, whether the search really changes what it returns when the block comes in. See Outcomes and attribution.

What stays off

Everything above starts off. A store that only wants the context and the memory of each customer turns nothing on; one that wants to see why the assistant said what it said turns on turns; state, signals, claims, coordination and measurement each come in when the team has the type, the contract, the gateway or the revenue definition ready.

Next steps

Object types and state

the shared item, the working set and the re-reads.

Signals and constraints

“nothing in black” in the agent’s tools.

WhatsApp agents

the conversation itself: turns, verification and handoff.

Outcomes and attribution

from the card to the order, and the counterfactual.