Long-read · AI · Архитектура

Как Operations Agent BULLS пересобирает маршрут за 11 секунд

TL;DR

Operations Agent — один из 10 агентов BULLS AI Operating System. Отвечает за диспетчеризацию, ETA, перепланирование маршрутов и эскалации. Когда на маршруте случается инцидент (ремонт пути, простой парка, погода), Operations Agent за 11 секунд пересобирает план: проверяет альтернативные станции, парк, окна для перегрузки, согласует с RZD Agent и Pricing Agent, формирует action card и кладёт оператору на подтверждение. Всё это — через MCP-протокол и графовую память над цепью поставок.

Сценарий: задержка на ст. Челябинск-Гл.

Реальный кейс из апреля 2026. Перевозка SHP-2026-04-1240, BULLS BOX уменьшенной высоты с мраморным мелом, маршрут Тёплая Гора → Кудьма. На станции Челябинск-Гл. — внеплановый ремонт пути, ожидаемый простой 4–6 часов.

В 9:14 МСК ГЛОНАСС-датчик показывает остановку контейнера. Через 8 секунд Operations Agent получает event. Через 11 секунд оператор Сергей Моисеев в Control Tower ГК «Старатели» видит action card: «Простой 2ч на Челябинск-Гл. Operations Agent предлагает переключить отгрузку на ст. Кунгур — это уберёт 4ч из ETA и снимет риск штрафа. Подтвердить?»

Операция, на которую раньше уходил день переговоров с диспетчерами, занимает один клик.

Лог решения · 11 секунд

Полный audit-log этого инцидента доступен в Control Tower клиента. Сокращённая версия:

09:14:02.184 [event-bus] shipment.SHP-2026-04-1240 → stationary at lat 55.16, lon 61.40 (Челябинск-Гл.) 09:14:02.391 [Operations Agent] received event, classifying... 09:14:03.023 [Operations Agent] classified as incident (severity: medium) 09:14:03.117 [Operations Agent] calling graph.query via MCP 09:14:03.524 [graph] alternative routes from current location: ├─ via Кунгур → ETA 02 May 14:30 (−4h vs current) ├─ via Уфа → ETA 02 May 18:45 (−1h vs current) └─ wait at Челябинск-Гл. → ETA 02 May 22:30 (current) 09:14:04.812 [Operations Agent] calling rzd.check_capacity via MCP 09:14:06.120 [RZD Agent] Кунгур: capacity available, no penalty risk 09:14:06.245 [Operations Agent] calling pricing.check_delta via MCP 09:14:07.014 [Pricing Agent] via Кунгур: +2400 ₽ (within Premium Flow SLA) 09:14:07.512 [Operations Agent] calling risk.score_alternative via MCP 09:14:09.318 [Risk Agent] via Кунгур: risk score 0.18 (low) — acceptable 09:14:09.542 [Operations Agent] generating action card for user... 09:14:11.020 [Control Tower] action card delivered to user moiseev@stratel.ru 09:14:11.020 [audit-log] incident_id: I-2026-04-9214 recorded

На всё ушло 11 секунд от detection до делика action card в ЛК клиента. Без AI-агента такая операция занимала бы 2–6 часов: диспетчер увидел статус, позвонил в РЖД, потом перевозчику, потом клиенту, согласовал, отправил подтверждение по email.

Bounded autonomy: что Operations Agent делает сам, а что — нет

Это критически важный архитектурный принцип. AI-агент не действует «вместо человека» — он усиливает оператора. Граница автономии чётко прописана и одинакова для всех клиентов BULLS:

  • Сам. Получение event, классификация инцидента, запрос графовой БД, запросы к другим агентам, формирование action card, audit-log.
  • С подтверждением оператора. Переключение маршрута, бронирование альтернативного парка, отправка эскалации в РЖД, корректировка ETA для клиента.
  • Только оператор. Изменение договора, любые финансовые транзакции, отмена перевозки, удаление данных, изменение тарифов.

«AI не должен принимать решения, которые потом нельзя откатить. Граница автономии — это не ограничение, а гарантия».

MCP-вызовы между агентами

Operations Agent не «всезнайка». Он специалист по диспетчеризации. Когда нужно проверить ёмкость станции — вызывает RZD Agent через MCP. Когда нужно посчитать дельту по тарифу — Pricing Agent. Когда оценить риск — Risk Agent. Это позволяет каждому агенту иметь узкий, проверяемый, тестируемый контракт.

Пример MCP-вызова Operations → Risk:

{ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "risk.score_alternative", "arguments": { "shipment_id": "SHP-2026-04-1240", "alt_route": "via_kungur", "factors": ["weather","capacity","history"] } } }

Графовая память: почему это важнее vector-DB

Многие AI-проекты работают на vector DB (Pinecone, Qdrant, Weaviate) — это поиск по семантическому сходству. Хорошо для документов и FAQ. Плохо для логистики.

В логистике важны отношения: какая станция связана с какой, какой парк подходит под какой груз, какие коридоры конкурируют за ёмкость. Это естественно ложится на граф.

BULLS использует Neo4j для основного графа цепи поставок и Qdrant для semantic search по документам и истории диалогов. Operations Agent делает graph traversal за 200 мс по графу с миллионами рёбер.

Audit-log — это не «лог» в обычном смысле

Каждое решение Operations Agent — записано. Не как «строка в логе», а как событие с полным контекстом: какие данные были на входе, какие MCP-вызовы агент сделал, какие альтернативы рассмотрел, какое решение предложил, какое подтверждение получил.

Это критично для:

  • Compliance (152-ФЗ, 187-ФЗ). При проверке оператор может показать каждое автоматическое решение с обоснованием.
  • Тонкая настройка моделей. Все случаи, когда оператор отклонил предложение агента, становятся обучающим сигналом.
  • Доверие клиента. Логист может посмотреть, почему агент предложил именно этот маршрут — и понять логику.
  • Дебаггинг. Когда что-то идёт не так, у нас есть полный trace до причины.

Главное за 30 секунд

  1. Operations Agent — специалист, не «всезнайка». Делает одну вещь хорошо: диспетчеризация и пересборка маршрутов.
  2. Bounded autonomy — твёрдое правило. Агент рекомендует, оператор подтверждает критичные действия.
  3. MCP-протокол — Operations Agent не интегрирован монолитом, а вызывает других агентов как инструменты. Это позволяет тестировать и эволюционировать каждого отдельно.
  4. Графовая память (Neo4j) для цепи поставок + vector DB (Qdrant) для semantic search.
  5. Audit-log — не лог, а контекст каждого решения. Для compliance, обучения и доверия.