Перейти к содержимому

Модуль XVI — голосовые агенты и агенты реального времени

Модуль XVI управляет разговорными агентами и агентами реального времени. Это плоскость наблюдения и управления: она не переизобретает голосовой SDK (Realtime API, WebRTC, ASR или TTS) и сама никогда не открывает медиапоток. Она решает, кто может открыть голосовую сессию, с какой моделью и провайдером, под какой политикой, и отслеживает метаданные этой сессии — но никогда её содержимое.

Открытие голосового интерфейса трактуется как привилегированное действие, а не свободная операция. Политика — default-DENY: сессия без разрешающей политики отклоняется. Открытие двухфазное и проходит через гейт human-in-the-loop (approval gate); оно привязано к plan_hash, так что одобрение нельзя молча повысить до более сильной модели (anti-TOCTOU), аудируется на реального принципала (никогда system) и фиксируется в режиме только добавление. Сам модуль никогда не вызывает провайдера — актуация уходит через отдельный seam отправки.

Вторая половина — наблюдение: модуль отслеживает только метаданные сессии — вычисляемое состояние (live/idle/ended, вычисляемое во время чтения по свежести активности, без хранимой колонки жизненного цикла), число ходов, длительность, задержку (честные среднее и максимум по реальным сэмплам) и язык BCP-47. Из этого он поднимает управленческие findings: нарушение политики, когда телеметрия называет агента/модель/провайдера, не разрешённого ни одной политикой; finding деградации задержки, когда задержка пересекает SLA политики; и finding неуправляемого открытия, когда открытие пытаются выполнить без подключённого гейта — пробел поверхностируется, а открытие всё равно отклоняется.

Модуль объявляет три сущности в общей модели данных:

Сущность Изменяемость Назначение
session изменяемая (upsert) метаданные сессии; ноль содержимого
policy изменяемая управленческое объявление — кто может открыть, с какой моделью/провайдером (default-DENY)
decision только добавление неизменяемый журнал решений об открытии/закрытии

Политика сопоставляется по агенту, разрешённой модели и разрешённому провайдеру (каждый конкретный или wildcard), с опциональными границами по минутам сессии и SLA задержки. Отсутствие сопоставленной политики означает DENY. Журнал решений записывает каждый open_request, open и close с вердиктом политики, статусом гейта и статусом исхода. Доступ на чтение — роль viewer и выше; объявление политики и открытие сессии — это административные, тенантно-ограниченные и аудируемые действия. Эти маршруты модуля публикуются в отдельном beta-справочнике маршрутов модулей, а не в стабильном основном контракте — их форма на уровне полей живёт в типизированных интерфейсах продукта. Денежных сумм здесь нет; FinOps (модуль XI) владеет стоимостью.

Модуль владеет deny-closed seam-ом приёма — собственным событием voice.telemetry.observed — через который внутрипроцессный зонд подавал бы метаданные сессии. Протокол по построению содержит минимум данных: парсер телеметрии несёт allow-list и отклоняет всё событие, если видит запрещённый ключ, поэтому никакое аудио, текст транскрипта, текст ASR/TTS, содержимое prompt/response или PII говорящего никогда не могут быть сохранены. Единственный сохраняемый сигнал транскрипта — односторонний хеш внешнего локатора транскрипта — доказательство того, что транскрипт существует, но никогда сам транскрипт. Управленческие findings излучаются как finding.reported с хешированными деталями, после коммита.

Управляемое открытие отправляет команду вживую: когда оператор настроит голосовой диспетчер, одобренное открытие создаёт серверные эфемерные учётные данные и возвращает их вместе с координатами подключения. Конфигурация сессии оператора задаёт голос и определение ходов; настроенная модель переопределяет запрошенную. Без настроенной модели диспетчер использует запрошенную модель, разрешённую политикой тенанта. Мастер-ключ провайдера никогда не покидает сервер. Без такой настройки точка отправки работает по принципу deny-closed: одобренное открытие честно записывается как «declared, not opened», а не подделывается.

Настроить и проверить управляемое открытие

Заголовок раздела «Настроить и проверить управляемое открытие»

Включите существующий модуль командой olivares modules on voice. Движок сохраняет выбор и один раз перезапускается, если набор работающих модулей меняется; olivares modules ls показывает, работает ли модуль. Согласно спецификации модулей voice требует FinOps и governance. Выключение voice сохраняет его политики, метаданные сессий и журнал решений.

Диспетчер настраивается на хосте движка через OLIVARES_VOICE_DISPATCH_CONFIG — абсолютный путь к JSON-файлу оператора. Разрешите чтение файла только учётной записи движка; мастер-ключи провайдеров хранятся в этом файле, никогда в аргументах CLI, записях политик или клиентском пакете подключения. Для адаптера OpenAI форма следующая:

{
"providers": [
{"ref": "openai", "kind": "openai", "api_key": "<server-held provider key>"}
],
"policies": [
{
"agent_ref": "contact-agent",
"provider_ref": "openai",
"model": "<your permitted realtime model>",
"voice": "marin",
"max_duration_seconds": 60
}
]
}

Задайте переменную окружения для сервиса движка и перезапустите его. Переданный нечитаемый файл или неверный JSON не позволит запуститься. Отсутствие конфигурации диспетчера сохраняет поведение declared-not-opened. Файл оператора выбирает адаптеры провайдеров и настройки сессии; голосовая политика тенанта отдельно авторизует запрошенных агента, модель и провайдера. Используйте одинаковые ссылки на модель и провайдера в обоих местах.

После входа через olivares login объявите эту политику и запросите одобрение:

Окно терминала
olivares voice policies set --agent-ref contact-agent \
--allowed-model-ref '<your permitted realtime model>' --allowed-provider-ref openai \
--max-session-minutes 1 --max-latency-ms 300
olivares voice sessions open --session-ref contact-1 --agent-ref contact-agent \
--model-ref '<your permitted realtime model>' --provider-ref openai -o json

Первый запрос возвращает op_status: requested, approval_ref и код выхода CLI 7. Он не открывает медиасоединение и не создаёт учётные данные провайдера. Необходимые независимые согласующие должны одобрить эту ссылку на странице одобрений governance или командой olivares governance approvals approve <approval-ref>. Для новых запросов через локальный мост согласований по умолчанию инициатор не может одобрить свой запрос, в том числе через другие учётные данные той же учётной записи. Повторите то же открытие с --approval-ref <approval-ref>. Отказ политики или ещё ожидающее одобрение возвращает 403 и код выхода CLI 3; ошибка адаптера возвращает 502. Проверки бюджета и остановки всего парка продолжают действовать.

Успешный настроенный запрос возвращает op_status: dispatched. Его dispatch_ref — строка JSON, содержащая краткоживущие credential, координаты connect, transport, модель и срок действия. Обращайтесь с ответом как с учётными данными: не вставляйте его в отчёты или логи. Для OpenAI клиент обменивает предложение SDP по возвращённому URL connect с краткоживущими учётными данными, затем владеет медиасоединением WebRTC. Одно создание учётных данных не доказывает подключения медиа. Журнал решений хранит отпечаток SHA-256 пакета с учётными данными, а не учётные данные подключения. Старые сохранённые пакеты тоже преобразуются в отпечатки при чтении; существующие записи только для добавления не переписываются. Обычные идентификаторы провайдера сохраняют своё значение.

Просмотрите сохранённые метаданные и решения:

Окно терминала
olivares voice sessions get contact-1 -o json
olivares voice sessions decisions contact-1 -o json
olivares voice policies ls -o json

Используйте один и тот же каталог данных между перезапусками движка. Политика и решения в режиме только добавления остаются доступными после перезапуска, а также выключения и повторного включения voice; учётные данные провайдера всё равно нужно настроить отдельно. Команды JSON выше используют те же маршруты /v1/m/voice, ограниченные тенантом, что и API.