AgentFlow is the platform. This document describes the company whose data flows through it in every seed, demo, metric, and warehouse table — the single source of truth for the business legend. Docs, demo values, the data generator, and the operational layer are aligned to this document, not the other way around.
Downstream consumers:
- Generator spec / unit economics — order volumes, channel mix, and
seasonality below are the fixed frame; exact distributions are pinned in
generator-spec.md. - Docs sweep — README,
docs/architecture.md, and the DV2 docs inherit the storyline and the vocabulary from §5. - Operational layer design — the three ops surfaces (order timeline,
stuck-orders worklist, exception inbox) serve the workflows in §4; the
serving split is decided in
ADR 0011 and the surface contracts
are pinned in
ops-surfaces-spec.md.
A mid-size Russian own-brand (private-label) importer of small kitchen appliances. Product design, QC, and the brand live in Russia; manufacturing is contracted to audited factories in China. The archetype is well established on the Russian market — own-brand appliance importers of this shape have grown from ~4.7 to ~13–14 B ₽ of annual revenue over the last five years (Forbes on the Kitfort founders). The demo company sits earlier on that curve: ~2,000 orders/day, ~3–5 B ₽/year — large enough for real multi-channel pain, small enough that a single data platform team is plausible.
Positioning. Mid price segment with a deliberate value twist: the product looks premium but sells at an accessible price (marketplace bestsellers at 1,500–3,000 ₽, top lines at 5,000–8,000 ₽). The catalog is small kitchen appliances: kettles, grills and air fryers, blenders and planetary mixers, coffee makers, multibakers, kitchen scales, vacuum sealers. A large share of purchases are gifts — which drives both the seasonality (§3) and the CRM practice of tracking contact birthdays for gift campaigns.
Brand narrative vs. data. The marketing story is "smart kitchen" — app-connected appliances are part of the brand's roadmap and demo narrative, but no IoT/device telemetry exists in the v1 data model. Do not add device events, firmware versions, or app sessions to seeds or contracts; the data story is orders, stock, and fulfilment.
Brand name. Deliberately unnamed in v1 ("the importer"). Product names in
seeds use neutral category-based names without a brand string — settled as a
hard decision in generator-spec.md §3: no brand token
anywhere in the data.
| Branch | Region | Jurisdiction | Role in the legend |
|---|---|---|---|
msk |
RU | RU | HQ, central warehouse (fulfils all three RU channels), main WMS |
spb |
RU | RU | Regional warehouse + B2B showroom |
ekb |
RU | RU | Regional warehouse (Urals/Siberia dealer logistics) |
dxb |
UAE | UAE | Re-export trading hub, registered as a free-zone entity in JAFZA (Jebel Ali Free Zone): China → Jebel Ali → Gulf market + re-export. Re-export is ~40% of UAE foreign trade; Chinese electronics reach the Middle East through exactly this route |
ala |
KZ | KZ | EAEU hub: Kazakhstan local market + EAEU customs contour |
Each branch is a separate legal entity in its jurisdiction, which is why per-jurisdiction PII satellites and per-branch row policies in the DV2 vault are a business requirement, not an architectural flourish: RU customer data stays in RU, UAE data in UAE, KZ data in KZ.
The dxb entity's free-zone registration is load-bearing for the economics:
goods held in JAFZA sit outside UAE customs territory (no import duty
until they enter the mainland, none at all on re-export), and qualifying
free-zone trading income is taxed at 0% under the UAE corporate tax regime.
That is what makes a China → Jebel Ali → Gulf/Africa consolidation-and-re-export
leg cheaper than routing the same containers through the mainland — and why
the branch exists as a trading hub rather than a sales office.
Three sales channels with deliberately asymmetric economics — most of the money is wholesale, most of the order count is marketplaces:
| Channel | Who buys | Order shape | Typical check | Volume |
|---|---|---|---|---|
| B2B wholesale | Several hundred active dealer accounts: regional appliance chains, gift/corporate buyers, independent e-com sellers | Multi-line orders (boxes of units), negotiated prices, deferred payment, retro-bonus program | 30,000–80,000 ₽ | ~150–200 orders/day |
| Marketplaces (FBS) | Retail buyers on Wildberries / Ozon | Single-item orders fulfilled from the importer's own warehouse (FBS) | 1,500–3,000 ₽ | ~1,800 orders/day |
| Own D2C site | Retail buyers, brand loyalists, gift shoppers | Small orders; the only channel with session/funnel telemetry | 2,000–5,000 ₽ | small share of orders |
Market grounding: in the small-appliance category ~76% of purchases happen online and ~92% of online purchases go through marketplaces; category sales grew ~50% on Wildberries and ~65% on Ozon in 2025 (Oborot.ru, AdIndex). An importer with a 90/10 marketplace/D2C split in retail order count is the norm, not an outlier.
Channel-specific mechanics that show up in the data:
- Retro-bonuses (B2B). Dealers earn quarterly rebates for hitting volume thresholds. This is what "loyalty" means in this business — dealer bonus accrual, not retail points.
- CRM-driven B2B sales. Wholesale runs on Bitrix24: deals, dealer organizations, and decision-maker contacts, including birthdays — the gift assortment makes personal dates a real sales trigger.
- Marketplace mechanics (FBS). Commission, returns with a return window, price promos dictated by platform sales events. Stock is shared with the other channels — see the oversell case in §4.
- Demand peaks are gift-driven: New Year (Nov–Dec, the dominant peak), March 8, a secondary February 23 bump, plus marketplace-dictated sale events (11.11, platform birthdays).
- Supply is containers from China: 40–60 day lead time (factory → sea → customs → central warehouse). Procurement for the New Year peak is committed in early autumn; a late or customs-stuck container is a top-3 business risk and a core operational storyline (§4).
- Regulatory frame — mandatory marking. Russia's Chestny ZNAK (Честный
знак) marking became mandatory for importers of electronics on
2026-05-01, with the remaining household-appliance categories (multicookers,
microwaves, vacuum cleaners, etc.) joining on 2026-09-01
(kontur.ru,
1C).
For a kitchen-appliance importer in mid-2026 this is a live compliance
program: every imported unit carries a GS1 DataMatrix code. This is why the
warehouse has a first-class marking-code hub (
hub_marking_code) and why customs classification (ТНВЭД) lives in the product catalog satellite.
The operations team currently juggles five tools to answer one question about one order: 1С, Bitrix24, the WMS screen, marketplace seller cabinets, and logistics Excel sheets. AgentFlow's serving layer exists to replace that tab-switching with one API surface. Three recurring situations define the requirements:
- Cross-channel stock sync (the freshness case). One central warehouse serves all three channels. A wholesale order for 200 units of a bestseller must be reflected in available-to-promise before the marketplaces keep selling those units — otherwise the importer ships apologies instead of goods and collects marketplace penalties for cancellations. This is the business reading of AgentFlow's headline event → live metric axis: second-level freshness is not a vanity benchmark, it is oversell prevention.
- The inbound container. ETA / customs / receiving status for goods on
the water. Everyone from procurement to B2B sales plans against it
("promise the dealer the grills from the March container?"). Today it lives
in Excel manifests (
excel__*sources); surfacing it is a roadmap item for the ops layer. - Kill-the-five-programs triage. Where is order X? Which orders are stuck
between confirmation and shipment longer than the stage SLA? Which failed
events need a manual decision? These map to the three ops surfaces —
Order 360 timeline, stuck-orders worklist, and exception inbox —
now live (
GET /v1/entity/order/{id}/timeline,/v1/ops/stuck-orders,/v1/ops/exceptions).
Ground rule: entity and table names in code do not change. The legend is applied by reading existing structures in domain terms (and by docs), not by renames. The two exceptions are listed in §5.4.
| Code artifact | Reading in the legend |
|---|---|
order / orders_v2 (ORD-YYYYMMDD-NNNN) |
An order from any of the three channels. Status flow pending → confirmed → shipped → delivered / cancelled is the central-warehouse fulfilment path |
user / users_enriched |
A customer: either a dealer-account contact (B2B) or a retail buyer (D2C/marketplace). total_spent = lifetime value; preferred_category = appliance category |
session / sessions_aggregated |
D2C site sessions only — marketplaces do not expose session telemetry. Funnel stages (add_to_cart, checkout) are meaningful for the D2C slice |
product / products_current |
An own-brand SKU (kettle, air fryer, blender, …); category = small-appliance category; stock_quantity = units at the central warehouse — the shared pool behind the oversell case |
metric revenue |
Confirmed order value across all channels |
metrics order_count, avg_order_value |
All channels; AOV is bimodal by design (30–80k ₽ wholesale vs 1.5–3k ₽ retail) — segment before averaging |
metrics conversion_rate, active_sessions |
D2C site funnel only |
metric error_rate |
Pipeline/data health (an ops signal, not a commerce number) |
| Code artifact | Reading in the legend |
|---|---|
hub_store / store_code (msk-01, spb-shr-02, …) |
A branch facility: central warehouse, regional warehouse, showroom, hub office. Not a retail chain store |
hub_customer |
Dealer organizations and retail buyers, deduplicated to one golden record; representations live in per-source satellites |
hub_supplier (supplier_inn / foreign tax-id) |
Chinese contract factories (plus a few RU packaging/component suppliers — hence INN support) |
hub_employee |
Sales / account managers — B2B attribution |
hub_marking_code (gs1_gtin) |
Chestny ZNAK GS1 DataMatrix codes — a live importer obligation since 2026-05-01 (§3) |
hub_shipment, lnk_order_shipment |
Outbound warehouse shipments (split-shipment capable). Inbound container receipts are the planned second leg of this hub |
sat_customer_loyalty__bitrix__* |
Dealer retro-bonus program: segment, accrued bonus (né "points"), last activity |
sat_customer_personal__1c__* |
Contact PII per jurisdiction; birth_date is load-bearing — gift campaigns run on contact birthdays |
sat_order_marketplace__wb__* |
FBS order facets: platform status, commission, return window |
sat_product_catalog__1c__* (ТНВЭД) |
Customs classification — first-class data for an importer, not decoration |
sat_product_stock__wms__* |
The shared stock pool (qty_on_hand / qty_reserved / qty_available) that all three channels draw down |
bv_customer_mdm |
Golden customer record: 1С is master for identity/PII, Bitrix24 for the commercial relationship |
bv_order_canonical |
One status vocabulary across channels — the substrate for Order 360 and stuck-orders |
| Prefix | System | Feeds |
|---|---|---|
1c__ |
1С:УТ + 1С:ЗУП (ERP) | Orders, pricing, catalog, suppliers, employees, customer identity |
bitrix__ |
Bitrix24 CRM | B2B deals, dealer orgs, decision-maker contacts, retro-bonus state |
wms__ |
Warehouse management | Stock, shipments, marking codes at receiving |
site__ |
Own D2C site | Sessions, behavior events, site orders |
wb__ |
Wildberries seller API | FBS orders, commissions, returns |
excel__ |
Logistics spreadsheets | Container manifests, cross-dock — the inbound-container storyline |
pg_ops__ |
Postgres OLTP (hot tier) via CDC | Operational order/customer rows promoted into the vault |
mp__ |
Consolidated marketplace order feed | High-volume retail order history |
| Change | Scope | Status |
|---|---|---|
Former external-dataset record_source prefix → mp__* (+ governance SQL, officer probes, admission tests) |
The prefix carried the name of a retired public benchmark dataset that the demo loader once replayed as transaction history. Under the legend it is the consolidated marketplace feed, and the prefix says so. The dataset and its loader have since been removed from the codebase entirely (see CHANGELOG.md) | Done (B2) |
Demo value repin: currencies to RUB (primary), AED/KZT in branch stories; demo revenue/counts consistent with §1–2 |
contracts/entities/order.yaml currency examples, NL demo answers, seeded ORD-* rows |
Done (S0/S1 — RUB is the house currency across contracts, demo answers, and seeds) |
Vocabulary guardrails for all public docs: the company is an own-brand /
private-label importer — always that framing; "store" (in hub_store) is
rendered as branch/warehouse, never as a retail shop; "loyalty" is rendered
as dealer retro-bonuses; IoT stays in the brand narrative and out of the
data model.
Six humans, one machine, one compliance role. Endpoints marked planned are the operational-layer roadmap; everything else is live API surface.
| Persona | Questions they ask | Surface |
|---|---|---|
| Owner / CEO | "Revenue today vs yesterday? Orders during the НГ peak? Is AOV holding after the price move?" | GET /v1/metrics/revenue · order_count · avg_order_value; POST /v1/query (NL: "top products this week") |
| B2B account manager | "What has dealer X ordered this quarter? Are they on track for the retro-bonus threshold? Which of my contacts has a birthday before March 8?" | GET /v1/entity/user/{id}; POST /v1/query; vault: bv_customer_mdm, sat_customer_loyalty__bitrix__* |
| E-com / marketplace manager | "Site conversion this week? Are WB orders flowing or did the feed break? Top SKUs by orders during the sale event?" | GET /v1/metrics/conversion_rate · active_sessions · error_rate; GET /v1/admin/analytics/top-entities (admin-key); POST /v1/query |
| Operations manager | "Everything about ORD-20260404-1001 — now, in one place. Which orders are stuck pre-shipment past SLA? What failed overnight and needs a human?" | GET /v1/entity/order/{id}; /v1/alerts (+history/test); /v1/deadletter (+replay/dismiss); GET /v1/entity/order/{id}/timeline; GET /v1/ops/stuck-orders; GET /v1/ops/exceptions (+stats/acknowledge/resolve) |
| Category / procurement manager | "Which SKUs sell fastest per branch? What is on hand vs reserved? When does the next container land?" | GET /v1/search; GET /v1/entity/product/{id}; POST /v1/query; vault: sat_product_stock__wms__*; container ETA — planned (today: excel__* manifests) |
| Data engineer / analyst | "Which events move this metric? What is the contract and its staleness budget? What changed between contract v3 and v4? Are we inside SLO?" | GET /v1/catalog; /v1/contracts/* (+versions/diff/validate); /v1/lineage/*; /v1/slo; /v1/admin/analytics/* (admin-key) |
| AI agent / integration | Any of the above, programmatically — the agent is one consumer, not the product | Python/TS SDKs, MCP/LangChain/LlamaIndex integrations over the same API: POST /v1/query + /v1/query/explain, /v1/entity/*, POST /v1/batch, /v1/webhooks, /v1/stream |
| PII officer (per jurisdiction) | "Who can read dealer-contact PII in dxb? Prove RU data never crosses the border" |
Not REST: DV2 governance — jurisdiction-scoped officer roles, column-limited analyst grants, per-branch row policies (warehouse/agentflow/dv2/governance/, ClickHouse and Postgres variants) |
The bimodal channel mix is what makes several of these questions interesting: revenue questions need channel segmentation (§5.1), stock questions are cross-channel by nature, and the operational questions exist precisely because three channels share one warehouse.
Market research grounding the legend (retrieved 2026-07-03):
- Forbes — история основателей Kitfort — own-brand importer archetype and revenue trajectory
- Oborot.ru — рынок бытовой техники — online/marketplace share in the small-appliance category
- AdIndex — прогноз продаж бытовой техники — category growth on WB/Ozon
- Контур — маркировка радиоэлектроники and 1С — сроки маркировки электроники — Chestny ZNAK timeline for importers
- Кристалл Форвардинг — импорт через Jebel Ali and DDA — торговые партнёры ОАЭ — UAE re-export share and the China → Gulf electronics route