Что получится в результате
Соберем ИИ-агента для склада, который каждый день читает товары, ячейки, остатки, резервы, движения, заказы, закупки и результаты пересчета, затем находит stockout, overstock, пересорт, расхождения между системами, товары для cycle count и задачи для склада.
Первая рабочая версия будет делать так:
- настройки хранятся в `settings`;
- товары и SKU хранятся в `sku_master`;
- склады и ячейки хранятся в `warehouse_locations`;
- снимок остатков хранится в `inventory_snapshot`;
- резервы под заказы хранятся в `reservation_snapshot`;
- движения товара хранятся в `stock_movements`;
- закупки и ожидаемые поставки хранятся в `incoming_stock`;
- правила пополнения хранятся в `reorder_rules`;
- расчет доступного остатка пишется в `available_stock`;
- риски stockout пишутся в `stockout_alerts`;
- излишки пишутся в `overstock_alerts`;
- расхождения между системами пишутся в `discrepancy_log`;
- задания на пересчет пишутся в `cycle_count_tasks`;
- результаты пересчета пишутся в `cycle_count_results`;
- черновики корректировок пишутся в `adjustment_drafts`;
- рискованные действия уходят в `approval_queue`;
- одобренные действия попадают в `execution_queue`;
- задачи складу, закупкам и продажам пишутся в `task_queue`;
- ежедневная сводка пишется в `daily_warehouse_report`;
- все действия пишутся в `audit_log`;
- ошибки интеграции пишутся в `error_log`.
В первой версии агент не меняет остатки, не списывает товар, не переносит между ячейками, не создает реальные корректировки и не закрывает инвентаризацию. Он читает данные, считает риски, готовит задачи и отправляет спорные действия на approval.
Что понадобится
- n8n Cloud или self-hosted n8n.
- Google Sheets для MVP-таблиц.
- ERP, WMS, CMS магазина или выгрузка CSV: Odoo, Zoho Inventory, Shopify, 1С, МойСклад, Битрикс24, RetailCRM.
- Read-only API-ключ к системе остатков.
- Список складов, зон и ячеек.
- Справочник SKU.
- История движений минимум за 30 дней.
- Список открытых заказов и резервов.
- Список ожидаемых поставок.
- Канал approval: Telegram, Slack, email или задача.
- API-ключ LLM-провайдера.
- Ответственный сотрудник склада, который подтверждает пересчет и корректировки.
Шаг 1. Выберите первый складской сценарий
Не запускайте агента сразу на весь склад.
Для MVP выберите один сценарий:
- найти SKU ниже reorder point;
- найти товары с риском stockout;
- найти товары с излишками;
- найти расхождения между магазином и складом;
- подготовить задания на cycle count;
- найти заказы без резерва;
- подготовить ежедневный складской отчет.
Самый безопасный старт: `каждое утро проверить остатки, резервы и incoming stock, затем создать задачи по рисковым SKU`.
Проверка: сценарий можно вручную проверить на 10 SKU.
Шаг 2. Запретите опасные действия
В первой версии запретите агенту:
- менять физический остаток;
- создавать stock adjustment в ERP;
- списывать товар;
- перемещать товар между ячейками;
- менять серию или партию;
- менять срок годности;
- закрывать инвентаризацию;
- менять резерв под заказ;
- отменять заказ;
- менять reorder point без согласования;
- массово обновлять SKU;
- удалять товарную карточку.
Разрешите агенту:
- читать данные;
- считать доступный остаток;
- искать риски;
- создавать задания на пересчет;
- готовить черновик корректировки;
- отправлять approval;
- вести лог.
Проверка: API-токен первого запуска имеет только чтение.
Шаг 3. Создайте Google Sheet проекта
Создайте таблицу:
Warehouse inventory agent
Добавьте листы:
settings
sku_master
warehouse_locations
inventory_snapshot
reservation_snapshot
stock_movements
incoming_stock
reorder_rules
available_stock
stockout_alerts
overstock_alerts
discrepancy_log
cycle_count_tasks
cycle_count_results
adjustment_drafts
approval_queue
execution_queue
task_queue
daily_warehouse_report
audit_log
error_log
Проверка: n8n может читать и писать во все листы.
Шаг 4. Заполните settings
В `settings` добавьте колонки:
key
value
description
updated_at
Заполните минимум:
planning_horizon_days | 14 | горизонт прогноза stockout
stockout_days_threshold | 7 | критический запас в днях
overstock_days_threshold | 90 | излишек в днях
inventory_accuracy_target | 98 | целевая точность учета
cycle_count_daily_limit | 30 | максимум пересчетов в день
approval_required | true | корректировки только через approval
auto_execute | false | автоматическое применение выключено
max_adjustment_qty | 5 | лимит черновика корректировки
Проверка: `approval_required = true`, `auto_execute = false`.
Шаг 5. Заполните sku_master
В `sku_master` добавьте колонки:
sku
product_id
barcode
name
category
unit
abc_class
is_serialized
is_batch_tracked
has_expiry_date
default_supplier
status
updated_at
Пример:
TSHIRT-BLACK-M | P-1001 | 4600000000012 | Футболка черная M | apparel | pcs | A | false | false | false | textile_supplier | active | 2026-05-23
Проверка: у каждого активного товара есть `sku`, `barcode`, `unit` и `status`.
Шаг 6. Заполните warehouse_locations
В `warehouse_locations` добавьте колонки:
location_id
warehouse_id
zone
aisle
rack
shelf
bin
location_type
capacity_units
status
updated_at
`location_type`:
storage
pick
receiving
packing
quarantine
damaged
return
Пример:
LOC-A-01-02-03 | WH-MAIN | A | 01 | 02 | 03 | BIN-03 | pick | 120 | active | 2026-05-23
Проверка: у каждого складского остатка есть `location_id`.
Шаг 7. Заполните inventory_snapshot
В `inventory_snapshot` добавьте колонки:
snapshot_at
source_system
warehouse_id
location_id
sku
barcode
batch_no
serial_no
expiry_date
on_hand_qty
damaged_qty
quarantine_qty
unit
updated_at
Пример:
2026-05-23 08:00 | odoo | WH-MAIN | LOC-A-01-02-03 | TSHIRT-BLACK-M | 4600000000012 | - | - | - | 120 | 0 | 0 | pcs | 2026-05-23
Проверка: `on_hand_qty` не пустой, а отрицательные остатки попадают в `error_log`.
Шаг 8. Заполните reservation_snapshot
В `reservation_snapshot` добавьте колонки:
snapshot_at
order_id
source_system
warehouse_id
sku
reserved_qty
reservation_status
promised_ship_date
updated_at
Статусы:
reserved
partially_reserved
not_reserved
released
cancelled
Пример:
2026-05-23 08:00 | SO-2281 | shopify | WH-MAIN | TSHIRT-BLACK-M | 8 | reserved | 2026-05-24 | 2026-05-23
Проверка: агент видит заказы, которые забирают товар из доступного остатка.
Шаг 9. Заполните stock_movements
В `stock_movements` добавьте колонки:
movement_id
movement_at
source_system
warehouse_id
from_location_id
to_location_id
sku
qty
movement_type
document_id
operator
created_at
`movement_type`:
receipt
shipment
transfer
adjustment
return
write_off
cycle_count
reservation
release
Проверка: за последние 30 дней есть движения по товарам класса A и B.
Шаг 10. Заполните incoming_stock
В `incoming_stock` добавьте колонки:
incoming_id
source_system
purchase_order_id
supplier
warehouse_id
sku
ordered_qty
received_qty
expected_qty
expected_date
status
updated_at
Статусы:
ordered
confirmed
in_transit
partially_received
received
delayed
cancelled
Пример:
IN-775 | odoo | PO-775 | textile_supplier | WH-MAIN | TSHIRT-BLACK-M | 300 | 0 | 300 | 2026-05-30 | confirmed | 2026-05-23
Проверка: будущие поставки видны агенту при расчете stockout.
Шаг 11. Заполните reorder_rules
В `reorder_rules` добавьте колонки:
sku
warehouse_id
min_qty
max_qty
safety_stock_qty
average_daily_demand
lead_time_days
reorder_point
reorder_qty
owner
updated_at
Формула:
reorder_point = average_daily_demand * lead_time_days + safety_stock_qty
Пример:
TSHIRT-BLACK-M | WH-MAIN | 40 | 300 | 20 | 12 | 7 | 104 | 250 | procurement | 2026-05-23
Проверка: у SKU с регулярными продажами есть `reorder_point`.
Шаг 12. Подключите источник данных в n8n
Создайте workflow:
Warehouse Inventory Agent - daily check
Добавьте узлы:
- `Schedule Trigger`;
- `Read sku_master`;
- `Read warehouse_locations`;
- `Read inventory_snapshot`;
- `Read reservation_snapshot`;
- `Read stock_movements`;
- `Read incoming_stock`;
- `Read reorder_rules`;
- `Calculate available_stock`;
- `Detect stockout`;
- `Detect overstock`;
- `Detect discrepancies`;
- `LLM warehouse analysis`;
- `Create cycle count tasks`;
- `Send approval`;
- `Write audit_log`;
- `Write error_log`.
Проверка: workflow вручную запускается и читает все листы без ошибки доступа.
Шаг 13. Если есть ERP или WMS, подключите read-only API
Для Odoo через External API читайте модели:
product.product
stock.quant
stock.move
stock.location
purchase.order
sale.order
Для Shopify Admin API:
GET /admin/api/2025-01/inventory_levels.json
GET /admin/api/2025-01/locations.json
GET /admin/api/2025-01/products.json
Для Zoho Inventory API:
GET /inventory/v1/items
GET /inventory/v1/warehouses
GET /inventory/v1/purchaseorders
GET /inventory/v1/salesorders
Проверка: API возвращает товары и остатки, но write-запросы не используются.
Шаг 14. Рассчитайте available_stock
Для каждого SKU и склада возьмите:
on_hand_qty из inventory_snapshot
reserved_qty из reservation_snapshot
damaged_qty из inventory_snapshot
quarantine_qty из inventory_snapshot
incoming_qty из incoming_stock
Формула:
available_qty = on_hand_qty - reserved_qty - damaged_qty - quarantine_qty
В `available_stock` добавьте колонки:
run_id
snapshot_at
warehouse_id
sku
on_hand_qty
reserved_qty
damaged_qty
quarantine_qty
available_qty
incoming_qty_14d
unit
status
calculated_at
Статусы:
ok
negative_available
missing_inventory
missing_reservation
unknown_sku
Проверка: SKU `TSHIRT-BLACK-M` получил рассчитанный `available_qty`.
Шаг 15. Найдите stockout в stockout_alerts
Условия:
available_qty <= reorder_point
или:
days_until_stockout <= stockout_days_threshold
В `stockout_alerts` добавьте колонки:
alert_id
run_id
warehouse_id
sku
available_qty
average_daily_demand
days_until_stockout
incoming_qty_14d
reorder_point
risk_level
recommended_action
owner
status
created_at
`risk_level`:
low
medium
high
critical
Пример:
SA-1001 | RUN-20260523 | WH-MAIN | TSHIRT-BLACK-M | 28 | 12 | 2.3 | 300 | 104 | high | ускорить PO-775 или ограничить продажи | procurement | open | 2026-05-23
Проверка: товар ниже `reorder_point` появляется в `stockout_alerts`.
Шаг 16. Найдите излишки в overstock_alerts
Условия:
days_of_inventory >= overstock_days_threshold
или:
available_qty > max_qty
В `overstock_alerts` добавьте колонки:
alert_id
run_id
warehouse_id
sku
available_qty
average_daily_demand
days_of_inventory
max_qty
risk_level
recommended_action
owner
status
created_at
Проверка: медленный товар с большим остатком попадает в список задач продажам или закупкам.
Шаг 17. Найдите расхождения в discrepancy_log
Сравните остатки из разных систем:
ERP on_hand
WMS on_hand
shop available
marketplace available
Google Sheet manual count
В `discrepancy_log` добавьте колонки:
discrepancy_id
run_id
sku
warehouse_id
source_a
qty_a
source_b
qty_b
difference_qty
difference_pct
reason_guess
risk_level
status
created_at
Статусы:
open
needs_count
explained
approved_adjustment
closed
Проверка: если в магазине 10, а в WMS 7, агент пишет расхождение и не исправляет его сам.
Шаг 18. Настройте prompt для LLM warehouse analysis
В n8n добавьте узел `LLM warehouse analysis`.
System prompt:
Ты складской аналитик. Работай только с переданными данными.
Не меняй остатки, не списывай товар, не создавай перемещения и не закрывай инвентаризацию.
Если данных не хватает, верни status = needs_data.
Любое действие с физическим остатком отправляй в approval.
Ответ возвращай только JSON.
User prompt:
Проанализируй SKU и складской риск.
sku:
{{$json.sku_master}}
available_stock:
{{$json.available_stock}}
stockout_alerts:
{{$json.stockout_alerts}}
overstock_alerts:
{{$json.overstock_alerts}}
discrepancies:
{{$json.discrepancy_log}}
movements:
{{$json.stock_movements}}
Верни JSON:
{
"sku": "...",
"warehouse_id": "...",
"status": "ok | stockout_risk | overstock | discrepancy | needs_count | needs_data",
"risk_level": "low | medium | high | critical",
"summary": "...",
"evidence": ["..."],
"recommended_actions": [
{
"action_type": "create_cycle_count | create_procurement_task | create_sales_task | draft_adjustment | ask_warehouse",
"owner": "warehouse | procurement | sales | operations",
"text": "...",
"requires_approval": true
}
]
}
Проверка: LLM возвращает валидный JSON и не предлагает списание без approval.
Шаг 19. Создайте cycle_count_tasks
В `cycle_count_tasks` добавьте колонки:
task_id
run_id
warehouse_id
location_id
sku
barcode
expected_qty
reason
priority
assigned_to
status
created_at
due_at
Причины:
stockout_risk
discrepancy
negative_available
high_value_sku
fast_moving_sku
recent_adjustment
no_recent_count
Статусы:
open
in_progress
counted
needs_review
closed
cancelled
Проверка: агент создает не больше `cycle_count_daily_limit` задач в день.
Шаг 20. Запишите cycle_count_results
После пересчета сотрудник склада заполняет `cycle_count_results`.
Колонки:
result_id
task_id
warehouse_id
location_id
sku
expected_qty
counted_qty
difference_qty
counted_by
counted_at
comment
status
Статусы:
matched
mismatch
needs_recount
approved
rejected
Проверка: если `difference_qty != 0`, агент создает черновик корректировки, а не меняет остаток.
Шаг 21. Создайте adjustment_drafts
В `adjustment_drafts` добавьте колонки:
draft_id
source_task_id
warehouse_id
location_id
sku
expected_qty
counted_qty
adjustment_qty
reason
evidence_json
risk_level
approval_required
status
created_at
Статусы:
draft
sent_to_approval
approved
rejected
manual_only
Проверка: черновик корректировки содержит evidence: задача пересчета, ожидаемое количество, фактическое количество и комментарий сотрудника.
Шаг 22. Настройте approval_queue
В `approval_queue` добавьте колонки:
approval_id
source
source_id
warehouse_id
sku
action_type
action_text
payload_json
risk_level
requested_by
approver
status
requested_at
approved_at
decision_comment
Статусы:
pending
approved
rejected
needs_recount
expired
В approval отправляйте:
- корректировку остатка;
- списание;
- перемещение между ячейками;
- изменение reorder point;
- снятие резерва;
- закрытие результата инвентаризации;
- массовые изменения SKU.
Проверка: без статуса `approved` действие не попадает в `execution_queue`.
Шаг 23. Сделайте Telegram approval
В n8n добавьте узел `Telegram`.
Сообщение:
SKU: TSHIRT-BLACK-M
Склад: WH-MAIN / LOC-A-01-02-03
Ожидалось: 120 pcs
Посчитали: 116 pcs
Разница: -4 pcs
Действие: создать черновик корректировки -4 pcs.
Approve: /approve ADJ-9001
Recount: /recount ADJ-9001
Reject: /reject ADJ-9001
После `/approve ADJ-9001` workflow должен:
- найти строку в `approval_queue`;
- проверить статус `pending`;
- записать `approved`;
- заполнить `approved_at`;
- передать действие в `execution_queue`;
- записать событие в `audit_log`.
Проверка: `/recount` создает новую задачу пересчета, а не корректировку.
Шаг 24. Настройте execution_queue
В `execution_queue` добавьте колонки:
execution_id
approval_id
target_system
warehouse_id
sku
action_type
payload_json
status
executed_at
result_json
error_message
Статусы:
queued
manual_only
executed
failed
skipped
Для MVP используйте `manual_only`: агент готовит действие, а сотрудник склада выполняет его в ERP или WMS.
Проверка: пока write-доступ не включен, все корректировки остаются `manual_only`.
Шаг 25. Создайте task_queue
В `task_queue` добавьте колонки:
task_id
source
source_id
warehouse_id
location_id
sku
task_type
title
description
owner_team
assignee
priority
status
created_at
due_at
closed_at
`task_type`:
cycle_count
procurement_follow_up
warehouse_check
sales_warning
data_fix
reorder_rule_review
Пример:
TASK-552 | stockout_alerts | SA-1001 | WH-MAIN | LOC-A-01-02-03 | TSHIRT-BLACK-M | procurement_follow_up | Проверить поставку PO-775 | SKU уйдет в stockout через 2.3 дня | procurement | buyer_1 | high | open | 2026-05-23 | 2026-05-24 | -
Проверка: каждое предупреждение превращается в задачу с владельцем.
Шаг 26. Настройте daily_warehouse_report
В `daily_warehouse_report` добавьте колонки:
report_date
total_sku
stockout_risk_count
critical_stockout_count
overstock_count
discrepancy_count
cycle_count_open
cycle_count_done
adjustments_pending
tasks_created
summary
created_at
Пример summary:
Сегодня 12 SKU ниже reorder point, 3 критических stockout, 5 расхождений между WMS и магазином, 18 задач cycle count, 4 черновика корректировки ждут approval.
Проверка: отчет отправляется складу, закупкам и операционному менеджеру.
Шаг 27. Настройте audit_log
В `audit_log` добавьте колонки:
event_id
run_id
event_type
sku
warehouse_id
actor
input_hash
output_hash
summary
created_at
Пишите события:
run_started
data_loaded
available_stock_calculated
stockout_found
overstock_found
discrepancy_found
cycle_count_created
adjustment_drafted
approval_requested
approval_approved
task_created
run_finished
Проверка: по `run_id` можно объяснить, почему агент создал задачу или черновик.
Шаг 28. Настройте error_log
В `error_log` добавьте колонки:
error_id
run_id
step
source_system
warehouse_id
sku
error_type
error_message
payload_sample
status
created_at
resolved_at
`error_type`:
api_error
unknown_sku
unknown_location
negative_stock
missing_reservation
invalid_json
approval_error
write_error
Проверка: при неизвестной ячейке агент пишет `unknown_location`, а не подставляет склад по умолчанию.
Шаг 29. Протестируйте на одном SKU
Создайте тестовые данные:
sku_master:
TSHIRT-BLACK-M | P-1001 | 4600000000012 | Футболка черная M | apparel | pcs | A | false | false | false | textile_supplier | active | 2026-05-23
inventory_snapshot:
2026-05-23 08:00 | odoo | WH-MAIN | LOC-A-01-02-03 | TSHIRT-BLACK-M | 4600000000012 | - | - | - | 40 | 0 | 0 | pcs | 2026-05-23
reservation_snapshot:
2026-05-23 08:00 | SO-2281 | shopify | WH-MAIN | TSHIRT-BLACK-M | 12 | reserved | 2026-05-24 | 2026-05-23
reorder_rules:
TSHIRT-BLACK-M | WH-MAIN | 40 | 300 | 20 | 12 | 7 | 104 | 250 | procurement | 2026-05-23
Ожидаемый расчет:
available_qty = 40 - 12 = 28
days_until_stockout = 28 / 12 = 2.3
Ожидаемый результат:
- в `available_stock` появилась строка `available_qty = 28`;
- в `stockout_alerts` появился риск;
- в `task_queue` появилась задача закупкам;
- в `daily_warehouse_report` обновился счетчик stockout;
- в `audit_log` появился запуск;
- в `error_log` нет ошибки.
Проверка: агент не создал stock adjustment и не изменил остаток.
Шаг 30. Проверьте негативные сценарии
Сделайте 5 тестов:
- удалите SKU из `sku_master`;
- удалите ячейку из `warehouse_locations`;
- поставьте `on_hand_qty = -5`;
- сделайте расхождение между WMS и магазином;
- верните от LLM невалидный JSON.
Ожидаемый результат:
- неизвестный SKU попадает в `error_log` как `unknown_sku`;
- неизвестная ячейка попадает как `unknown_location`;
- отрицательный остаток попадает как `negative_stock`;
- расхождение попадает в `discrepancy_log`;
- невалидный JSON попадает как `invalid_json`;
- без approval ничего не попадает в `execution_queue`.
Проверка: агент не исправляет плохие данные догадками.
Минимальная проверка результата
Прототип работает, если выполняются условия:
- `sku_master` содержит минимум 10 SKU;
- `warehouse_locations` содержит реальные ячейки;
- `inventory_snapshot` содержит физический остаток;
- `reservation_snapshot` содержит резервы;
- `available_stock` показывает доступный остаток;
- `stockout_alerts` ловит SKU ниже reorder point;
- `overstock_alerts` ловит излишки;
- `discrepancy_log` ловит расхождения систем;
- `cycle_count_tasks` создает задания на пересчет;
- `adjustment_drafts` создает только черновики;
- `approval_queue` блокирует рискованные действия;
- без `approved` нет реального исполнения;
- `task_queue` показывает владельца задачи;
- `daily_warehouse_report` отправляет сводку;
- `audit_log` объясняет действия;
- `error_log` показывает плохие данные.
Что нельзя автоматизировать в первой версии
- списание товара;
- изменение физического остатка;
- перемещение между ячейками;
- закрытие инвентаризации;
- изменение партии или серийного номера;
- изменение срока годности;
- снятие резерва с заказа;
- отмену заказа;
- изменение reorder point;
- массовое обновление SKU;
- удаление товара;
- любые действия без approval, если они меняют складской учет.
Частые вопросы
Можно ли начать без WMS?
Да. Для MVP хватит Google Sheets, выгрузки из магазина или ERP и ручного листа ячеек. Но если есть партии, серийные номера, адресное хранение и много движений, лучше подключать WMS или ERP как основной источник.
Может ли агент сам корректировать остатки?
В первой версии нет. Он может создать `adjustment_drafts` и отправить approval, но корректировку должен подтвердить ответственный сотрудник склада.
Что важнее контролировать первым?
Начните с stockout, товаров ниже reorder point, расхождений между системами и SKU класса A. Эти ошибки быстрее всего влияют на продажи и операционные проблемы.
Как проверить, что агент не путает доступный и физический остаток?
Разделите `on_hand_qty`, `reserved_qty`, `damaged_qty`, `quarantine_qty` и `available_qty`. В каждом alert агент должен показывать, какую цифру использовал.
Чем складской агент отличается от агента для логистики?
Складской агент работает с остатками, ячейками, резервами, пересчетом и корректировками внутри склада. Логистический агент работает с отправлениями после отгрузки: перевозчики, трекинг, задержки и доставка клиенту.