AiHummer доки
v1.0.x
RU EN

Gateway и turn-движок

v1.0.x · обновлено 2026-06-26

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

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

По умолчанию gateway слушает :8765, что задаётся AIHUMMER_GATEWAY_ADDR. Инсталлятор может выбрать другой свободный порт, но процесс всегда один и тот же.

# gateway.env — единственная обязательная настройка
AIHUMMER_DATABASE_URL=postgres://user:pass@localhost:5432/aihummer?sslmode=disable
# Админка после старта — на http://localhost:8765/admin/

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

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

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

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

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

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

Turn-движок

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

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

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

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

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

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

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

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

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

Куда дальше