Tastes, allergies, budget, household size
People rebuy what they already have
3 sites, different packs, different delivery
| Nomin | Emart | ||
|---|---|---|---|
| Eggs, 10 pcs | ₮6,998 | ₮6,300 | −10% |
| Sugar, 1 kg | ₮7,868 | ₮6,680 | −15% |
| Milk, 1 l | ₮5,398 | ₮5,330 | −1% |
| Grand salami | ₮12,980 | ₮14,300 | −9% |
| Cucumber, 100 g | ₮799 | ₮748 | −6% |
OyuLLM classifies the message and extracts days, dish and headcount. Asks if something is missing
The planner searches recipes over MCP. No carrots in the profile means tsuivan without carrots
Removes what is at home. Asks 3 stores for quotes over A2A and splits for the lowest total with delivery
“Approve” → “Pay”. Confirmed twice
A sandbox order per store, one MongoDB transaction
Order numbers and the wallet transaction show in the live trace
Nomin: 3 catalog categories
Emart: one search per item
The stores’ public catalogs
“Milk 3.2%, 1000ml” → milk, 1 l. Every decision is stored with its reason
Is the price and pack size plausible?
52 accepted · 3 to human review · 25 no match
Current price + time-series history
No. One snapshot a week. Households plan weekly, so this is enough, and it puts no load on store servers.
Nomin 19, Emart 33 catalog items have real prices. Good Price is simulated for now and labelled so on screen.
Official store APIs or feeds. Store agents serve quotes over A2A, so swapping the source leaves procurement unchanged.
| robots.txt | What we take | Decision | |
|---|---|---|---|
| Nominnomin.mn | Catalog open. Only /checkout /account /cart /sign-in disallowed | The public product list its category pages load | crawl |
| Emartemartmall.mn | No file (the site returns HTML, API host 404) | The site’s own search, one request per catalog item | crawl |
| Good Pricegoodprice.mn | Catalog open, /api/ /search/ disallowed. AI training crawlers blocked by name | Nothing. We found a public product feed updated hourly | simulated |
Checked: 2026-10-05
Writes or speaks Mongolian (Anir STT)
Chat, live agent trace, basket, profile
Classifies the message and routes it to the right agent. Does the math and checks itself
Message type and slots (days, people, budget, dish). Code decides what to ask when something is missing
Finds recipes and fits the budget
Quotes 3 stores at once and finds the cheapest split with delivery
Checks, then one MongoDB transaction
Nomin · Emart · Good Price. Agent card, skill quote, JSON-RPC message/send
2 agents match Nomin and Emart real prices. Good Price simulated
Memory → embed_cache (30-day TTL) → oyu API
Vector + Atlas Search · time-series prices · transactions · TTL · change stream → live trace
bge-m3 · 1024 dims · cosine
filter: store · key · category
name_mn · name_en
fuzzy maxEdits 2: “ондог” → өндөг (eggs)
search_recipes · ingesting tastes from the profile
| users | phone | unique · partial |
| pantry | user_id, key | unique |
| products | store, key | unique |
| conversations | user_id, updated_at ↓ | |
| run_events | run_id, seq | live trace |
| orders · wallet_tx | user_id, at ↓ | |
| prices | meta.store, meta.key, ts | time-series |
| crawl_matches | run_id, key |
ensure() runs at backend startup and before a crawl writes
2048 vectors · repeats within a plan
sha1(model + text) key
TTL index: 30 days
new vectors are written to the cache
The weekly crawl reuses a vector 4 times. sessions also have a 30-day TTL
Open MCP server: search_recipes, search_products, build_list, get_pantry. Any MCP client can connect.
Every store has an agent card. Procurement asks all three for quotes at once over JSON-RPC.
Vector + Atlas Search: a typo like “ондог” still finds eggs
Time-series: prices from every crawl
Change stream: live trace
Transactions: all or nothing
TTL: embedding cache, sessions
| OyuLLM | 4o-mini | gpt-4o | We use | |
|---|---|---|---|---|
| Understand | 9/10 | 9/10 | 10/10 | OyuLLM |
| Questions | 4/4 | 4/4 | 4/4 | OyuLLM |
| Crawler | 3/3 | 1/3 | 3/3 | OyuLLM |
| Recipe | 5/6 | 6/6 | 6/6 | OyuLLM |
| Planner | timeout | ✗ | ✓ | gpt-4o |
Strong: Mongolian messages, writing questions, matching Mongolian store listings, where 4o-mini got 1/3
Gap: long multi-step tool use. The planner timed out, so it runs on gpt-4o with OyuLLM as fallback
Few cases, one run per model: a trend, not a verdict · + bge-m3, Anir STT, tsuurAI TTS
Money moves only after two steps: “Approve” → “Pay”
Wallet, budget, allergies, diet, stock, quantities
If one store fails, everything rolls back. A repeat tap pays once
Nothing is sent to real sites, no store passwords are stored
A human reviews doubtful matches. robots.txt is respected
Every agent’s thought, tool, result and model is recorded
Stores pay a commission on every order placed through Sagslay. They gain new online customers who buy a full weekly basket.
Automatic weekly plans, pantry reminders, price-drop alerts, multiple family profiles.
Aggregated, no personal data: what people searched for and didn’t find, at what price households switch stores.
The optimizer recommends the cheapest split regardless of commission. Trust is the product.
A pilot with one store: official API, real orders, agreeing the commission rate.