AiHummer
Русский
ВойтиЛичный кабинет
v1.0.x
{ }Swagger

Шлюз и движок обработки запросов

v1.0.x · обновлено 2026-07-21

Сердце AiHummer — это единый сервис-шлюз (gateway). Он одновременно и административный API (настройки, подключение каналов, маркетплейс), и движок обработки запросов (цикл вызова функций, который порождает ответ). Поэтому типовое развёртывание — это всего один сервис плюс PostgreSQL: отдельный слой воркеров запускать не обязательно.

Коротко: шлюз принимает запрос, движок выполняет шаги, а очередь доставки возвращает результат в канал.

Один сервис, две роли

По умолчанию шлюз слушает публичный порт :8780, что задаётся AIHUMMER_GATEWAY_ADDR — этот порт несёт весь внешний трафик (API, привязку устройств, WS/SSE, входящие вебхуки, прокси приложения/pocket и пробы работоспособности). Веб‑интерфейс администратора работает на отдельном приватном слушателе (по умолчанию :8781, AIHUMMER_WEBUI_ADDR), раздаётся по корневому пути / и в идеале привязан к внутреннему интерфейсу. В любом случае процесс всегда один и тот же единый сервис.

# gateway.env — единственная обязательная настройка
AIHUMMER_DATABASE_URL=postgres://user:pass@localhost:5432/aihummer?sslmode=disable
# Веб-интерфейс администратора после старта — на http://localhost:8781/ (приватный слушатель)

Единственная жёсткая зависимость — PostgreSQL. Postgres — единый источник истины для агентов, настроек, диалогов, памяти, состояния доставки и аудита. Всё остальное — дополнительные сервисы, векторное хранилище и провайдеры моделей — опционально и подключается только тогда, когда вы это настроите.

[!NOTE] Без базы данных шлюз стартует в health-only режиме: он отвечает на GET /healthz, чтобы оркестратор или балансировщик видели, что процесс работает, но запросы обслуживать не будет. GET /readyz проверяет PostgreSQL и возвращает 503, пока база недоступна.

Что происходит при старте

При старте шлюз выполняет несколько шагов в строгом порядке:

  1. открывает пул соединений с базой данных,
  2. применяет ожидающие миграции под advisory-локом PostgreSQL,
  3. разрешает конфигурацию (значение из БД → переменная окружения → встроенное значение по умолчанию) и
  4. связывает сервисы — маршрутизатор, оркестратор, каналы, инструменты, память, доставку — в работающий шлюз.

Важное следствие: большинство возможностей подключаются опционально через ключ настройки. Ненастроенная возможность просто не активируется, и поэтому среда выполнения по умолчанию остаётся компактной и предсказуемой. Вы включаете нужное из веб-интерфейса или переменной AIHUMMER_*, и шлюз учитывает это при следующем старте (или на горячую — для тех параметров, которые это поддерживают).

Движок обработки запросов

Когда сообщение доходит до шлюза, за дело берётся движок обработки запросов (turn engine). Он ведёт цикл вызова функций: модели передаются системный промпт и диалог, она может вызывать инструменты (или порождать суб-агентов), результат каждого инструмента возвращается обратно, и цикл продолжается, пока модель не выдаст финальный ответ. Этот ответ затем передаётся слою доставки.

входящее сообщение
   └─▶ движок обработки запросов
         ├─ сборка слоистого системного промпта
         ├─ вызов модели ─▶ вызовы инструментов / суб-агенты ─▶ результаты ─┐
         │       ▲                                                          │
         │       └─────────────────────────────────────────────────────-──┘
         └─ финальный ответ ─▶ надёжная доставка ─▶ канал-источник

Поскольку цикл строго отслеживает, откуда пришёл каждый вход, ответы формируются из истории диалога и результатов инструментов, а не за счёт внедрения недоверенного текста в инструкции. Именно это свойство делает описанную ниже слоистость промпта не только быстрой, но и безопасной.

Слоистый, дружелюбный к кэшу системный промпт

Системный промпт — не единый блок. Он собирается слоями, намеренно упорядоченными так, чтобы стабильные части шли первыми, а изменчивые — последними. Это важно, потому что провайдеры моделей кэшируют промпт по его префиксу: пока начало промпта байт-в-байт идентично, кэшированный префикс переиспользуется и заново обрабатывается только хвост.

Зона Слои (по порядку) Меняется…
Стабильный префикс (кэшируемый) базовая идентичность + гид по инструментам/памяти → арендатор → профиль агента → навыки редко — на агента/арендатора
Изменчивая часть (добавляется последней) состояние настройки → подгрузка памяти → текущая дата каждый запрос

Стабильный префикс несёт всё, что определяет, кто такой агент: встроенную идентичность и гид по тому, как работают инструменты и память, затем слой арендатора, профиль агента и отрендеренный блок навыков. Ничего из этого не меняется между двумя соседними запросами одного агента, поэтому это и образует переиспользуемый кэшируемый префикс.

Изменчивая часть — данные текущего шага, которые могут меняться при повторном запуске, — добавляется после стабильного префикса именно для того, чтобы не делать кэш недействительным: состояние настройки, память, подгруженная под конкретный диалог, и текущая дата меняются от запроса к запросу, но раз они стоят в конце, то стоят ровно столько, сколько добавляют.

[!TIP] Этот порядок — причина того, почему меняющиеся данные вроде сегодняшней даты могут присутствовать в каждом запросе, не оплачивая повторное кодирование всей идентичности каждый раз. Держите свой контент на агента в стабильных слоях (профиль, навыки), а изменчивую часть оставьте движку.

Куда дальше