How it works
From a kitchen's rules to one Valio Aimo order
Mandate is a purchasing agent for a kitchen. It orders from Valio Aimo on its own only what the kitchen's mandate allows, and a person decides the rest.
Every line it prepares either goes through is held for a personor is refused
Architecture
The path every request takes
Architecture diagram. Four ways in: the Kitchen screen and the Request page, used by the chef; the chat, used by the in-app agent; and your own agent over MCP or REST. All four pass one gate. First it works out who is asking from the caller's key or signed cookie, never from the request body. Then it reads the request and looks up the products: Gemini reads requests and menus and scores how well a substitute fits; Valio Aimo gives the catalogue and live price and stock; Exa gives product facts and public listings. Then the mandate's checks: limits and caps, approvals bound to the exact terms, and one receipt per key. Then one state change, written to the op log with who asked. Each line ends one of three ways: ordered within the mandate, waits for the chef, or refused with the reason. The op log is in Aiven Postgres and streams live to every open screen, including Operations, which also shows recall cases from the recall list that Context.dev checks every 5 minutes.
Every request, from any of the four ways in, passes the same checks before anything is ordered, and every change is written to one log in Postgres.
The kitchen's rules
Each kitchen's own rules decide what the agent may buy
Each kitchen sets three kinds of rule, one per card below; only the mandate decides what the agent may buy without asking.
Preferences
They only change the order of the list. Weights over price, reliability, Finnish origin, carbon and organic.
Requirements
A product that breaks one is out, with the reason shown.
- Origin per category: prefer or require
- Allergens the kitchen must be free from
- Tender list only; labels such as vegetarian
The mandate
The chef's words and the numbers that enforce them.
- Caps per line, per order and per week
- A hard limit above the caps
- Never delegated: an allergen change, a new product, and three more
Seven kitchens, each with its own rules
All seven are fictional seed kitchens, each with its own city, size, receiving days, menu cycle and mandate.
- Hotel
- Lunch restaurant
- Public central kitchen
- À la carte
- Care home
- Café
- Ski resort
Presets preview how one shortage ranks under price first, Finnish required, lowest carbon or most reliable; they change nothing.
Goes through alone
Only when every check passes:
- Within the mandate's per-line, per-order and weekly caps
- A product this kitchen already buys
- No allergen change
- Valio Aimo states enough stock
- A day the kitchen receives goods
- The exact terms (price, quantity, date) unchanged since the quote
- Before the ordering cut-off
- Whole packs of Valio Aimo's lot step
and nothing in the next column applies.
Held for a person
The line waits, with its reason on screen, when it has:
- A cost over a cap, even when the order is split
- A product the kitchen hasn't bought before
- An allergen change, decided apart from routine lines
- No stock figure from Valio Aimo: held for one tap, not counted as cover until the supplier confirms
- A delivery on a day the kitchen doesn't receive goods
- A substitute that breaks the kitchen's origin preference
- A product under a recall notice
- An outside agent's order
- A model's caution. A model can add a caution that holds a line, and no caution can allow one.
Refused
No approval passes it:
- Over the hard limit, even split across lines
- After the ordering cut-off
- A part pack, off Valio Aimo's lot step
- On a request, a product that breaks a stated requirement, such as lactose-free, even as a substitute
Only a person in the kitchen approves, and only the exact terms; any later edit voids it.
Each rule with its test: Proof.
The agent
The agent prepares the order and leaves the approval to the chef
It works in at most 8 steps and stops at any decision the chef must make.
- Six kinds of ask, sorted by rules before any modelA routine order, the seeded event, a shortage repair, a change to a need, a question about a plan, or something it doesn't do.
- At most 8 stepsEach run has a step limit, a deadline and a cancel button.
- A scripted planner on the live appThe steps follow a fixed script. A Gemini Flash-Lite planner exists as an opt-in and is off on the live app.
- Typed facts about each productThe planner reads short, typed fields. A supplier's product text is data and can't give it instructions.
- One clarifying questionWhen something it needs is missing, such as the day, it asks once and goes on. Its reply uses only numbers from the task's ledger.
- It never approves“Approve it” in chat is refused, with a pointer to the decision for the chef.
Limits today: in chat the agent plans only the seeded buffet, so a new event goes through the Request page; and a second item in the same message is dropped.
Five flows
Five ways an order moves through Mandate
Each flow in four stages, with one case recorded from the live app.
One item
A request in plain words, such as “10 l lactose-free milk for Friday”, becomes one checked line, ordered alone or held for the chef.
- ReadRules read the words first, then Gemini Flash-Lite, and a check compares the reading with the words: every amount, unit and stated requirement must survive, or it asks. A date past the cut-off is named, with the next delivery day.
- FindA catalogue search shortlists up to 5 products with reasons, drops any that contradict the request, and asks Valio live for their prices and stock.
- SizeThe amount becomes packs by printed content and is checked against the kitchen's own numbers. Conflicting content holds the line.
- DecideThe mandate decides: ordered alone, or held for the chef's approval.
Event to menu
An event brief becomes a menu the chef accepts, then needs, then whole packs. Each line is shown to the chef for review: we don't yet claim the right product for every menu dish.
- BriefMissing guests, date, diet or budget are asked one at a time. Rules read the brief's guests, date and requirements, with no model call; Gemini Flash-Lite reads product requests.
- MenuGemini 3.8 Flash proposes dishes with every amount labelled an estimate; without it, the team's dish templates stand in. Nothing is planned until the chef edits and accepts the menu.
- NeedsEach ingredient becomes a need, guests × amount per guest ÷ yield, with no model. Changing the grams per guest recomputes the line and voids any approval.
- OrderEach need is quoted and checked against the mandate, and a product that's out goes to the out-of-stock flow. The chef decides once per reason group, then the order and its receipt.
Out of stock
When Valio is out, the agent finds and sizes substitutes, ranks them by the kitchen's rules, and holds anything new for the chef.
- SpotA line quoted out of stock, undeliverable or unknown is named in its own words.
- FindCandidates come from Valio Aimo's substitution rules, then hand-checked rescues, then same-category products, each sized to the same need. Making it in house is an option when every ingredient can be ordered.
- RankRequirements rule candidates out with a reason; known stock ranks first, then the kitchen's preferences. Gemini Decisions scores how well each substitute fits the dish, one input to the code's ranking, and can flag a constraint risk that holds the line. It never approves or allows anything.
- HoldA new product, an allergen change or a broken preference waits for the chef. If another kitchen takes the stock, the rest moves to the next candidate and the approval is voided (tested, simulated). With no candidate left, options outside the catalogue are shown for information and never ordered.
Outside agent
Your own agent connects over MCP or REST, uses the same tools through the same checks, and every line it orders waits for the chef.
- ConnectEach visitor gets their own key and MCP address on the Agents page, working only in their own sandbox and metered at 120 calls, 30 writes and 20 quotes a minute.
- ReadThe agent reads its context first: who it is, what it may do, the kitchens, mandates and open plans.
- OrderIt searches, quotes, then orders or plans an event. An unknown product is refused before any call to Valio Aimo, and every line it orders is held.
- WaitTrying to approve or change the mandate gets 403, and Ops logs it. The chef approves in the Kitchen, and the agent reads the receipt.
Approval
The chef approves exact terms. Any edit voids the approval, and the order is checked again before it's placed.
- GroupHeld lines are grouped by reason and decided one group at a time, so an allergen change never rides with routine lines.
- ApproveThe chef presses and holds on the exact terms, in the Kitchen or on the chat's decision card. The approval is bound to the plan version, the terms, the mandate version and an expiry.
- EditAny edit or substitute sends the plan back to draft, voids the approval and shows what changed. Tested in the app's screens, not yet checked on the live app.
- OrderUnder a lock the order re-checks version, terms, mandate, expiry, cut-off and caps, and refuses any mismatch. However many times it's sent, there is one receipt.
State machines
Three state machines hold the rules
A plan, each line and each approval move through fixed states. The checks on this page decide which way they go.
Each diagram scrolls sideways.
Plan
Green is the usual path. Any edit sends the plan back to draft and clears its terms, so an earlier approval no longer applies.
Line
A line inside the mandate is ordered without asking. Any other line waits for the chef with its reasons. A line below Valio Aimo's lot step can't be ordered at all.
Approval
An approval is tied to the plan version, the exact terms, the mandate version and an expiry. If any of them changes, the order is refused.
Each rule with its test: Proof.
What Valio Aimo sees
Valio Aimo's control room shows every held line, by cause, across kitchens
Ops reads the same records the kitchens write, so Valio Aimo sees why a line is waiting and can open the exact kitchen plan.
Each Ops tab, and the forecast, is shown on real data on the Story page. This section keeps the record underneath them.
The op log: 9 kinds of change
Every entry has a sequence number, who acted and the door it came through. Open screens update from it after each commit.
- Plan created
- Line edited
- Offer recorded
- Substitute proposed
- Approval recorded
- Order placed
- Incident recorded
- Web finding recorded
- Refusal recorded
Partners and fallbacks
What each partner service does, and its fallback
Every outside service sits behind a port, so a dead API or Wi-Fi drops to a fallback that the screen labels. The Partners zone of the system map shows the same five; this table adds each one's status.
| Partner | Job | Fallback | Status |
|---|---|---|---|
| Valio Aimo | The catalogue of 17,546 products; live price and availability for shortlisted products only, at most 200 per call, availability fetched again after 15 minutes. | The cached offer, labelled with its age; the file catalogue; scenario stock. | Seen live |
| Gemini 3.5 Flash-Lite | Reads product requests and chat messages, and writes the chat's reply from the ledger. The agent planner job is opt-in and off on the live app. | The rules parser, the rules classifier, the ledger's own text. | Seen live |
| Gemini 3.8 Flash | Proposes a menu from a brief; every amount is an estimate. | The team's dish templates. | Seen live |
| Gemini Decisions | Scores how well each substitute fits the dish, one input to the code's ranking, and can flag a constraint risk that holds the line. It never approves or allows anything. | A recorded replay, then rules. | Every shortage; falls back, labelled |
| Aiven | Runs the app as one container; Postgres holds every table and pushes live updates to Ops. | PGlite with the same migrations, for tests and offline. | Seen live |
| Exa | Cited product facts in the Why drawer: net content, origin, ingredients. Options outside the catalogue. | Recorded responses, under daily caps. | Seen live, Why drawer |
| Context.dev | Checks the recall list every 5 minutes and matches each notice against the catalogue. A matching product's line is held. | Recorded notices; a drill, labelled as one. | Seen live, no real recall matched |
| Featherless (Gemma) | An optional open-model provider in the router. No job uses it. | Not needed. | Optional, unused |
| NVIDIA Nemotron VL on Verda | Reading a photo of a prep list or delivery note. | The tool stays hidden until it is switched on. | Wired, not live |
Every web call goes through a response cache, daily caps per key and per instance, and a breaker. LLM calls log their model, tokens and latency; only some sponsor calls reach the Ops trace drawer so far.
Built, simulated, planned
Which parts are built, simulated or planned
Everything on this page falls in one of three columns, and the app labels the simulated parts on screen.
Built
In the code, with how far we've checked it.
- Approve, order and one receipt in the Kitchen
- The same order sent 4 times with one key: one receipt
- An outside agent's approve refused with 403
- A menu from a brief, then a plan, on Request
- Chat: a held line and a decision card; “approve it” refused
- The Why drawer with cited web facts
- Recall cases in Ops; no real recall has matched an order
- A late date caught on Request, the next day offered
Tested, not yet seen live
- Approval bound to terms, hard limit, caps when split, lot step, unknown supply never cover, per-line authority, reason groups, cut-off at commit, rescue resize, vegetarian kept
- An outside agent's stale order refused over MCP
- Gemini Decisions in the ranking
- Re-rescue when another kitchen takes the stock
Wired, to rehearse before we claim it
- Void-on-edit in the app's screens, rank presets and the ranked rescue on the live app
- Usual orders, from a simulated history, with no week view yet
- Every sponsor call in the trace drawer: some are there
- A review step, switched off
- Reading a photo (Nemotron); Featherless as a provider
Simulated
Stand-ins, each labelled in the app.
- Every order is a local simulated commitment
- The seven kitchens are fictional
- The scenario: the booking, stock on hand, recipes and the December clock
- Team estimates: the normal week and the mandate amounts
- Simulated events: the salmon contention, shifted cut-offs and the Ops simulated run
- Usual orders come from a simulated history
Planned
Decided or written down, and not built yet.
- New events planned from chat
- A place picker, a chat-first home and one request page (D15)
- One evaluator for every hard requirement (D16)
- Lines bound to their need, with one command key in the core (D18, partly landed)
- Hybrid retrieval (D19, held): search today matches names
- Ops numbers per cause
- The right product for every menu dish
- Streaming the op log out, margin-aware suggestions, Exa monitors