Tool Gateway

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

Чем отличается от реестра инструментов Tool Calling описывает реестр: разрешение имени в функцию плюс список разрешённого. Шлюз добавляет к этому три вещи, которых у реестра нет: субъекта, класс риска и состояние подтверждения. Реестр отвечает «такой инструмент существует и включён», шлюз — «этому субъекту в этом контексте это действие сейчас разрешено».

Минимальные требования

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

Последний пункт часто урезают до второй половины. Это ошибка: отказ политики — такое же событие расследования, как выполнение, и без него непонятно, почему агент чего-то не сделал (Agent Audit Log).

Шлюз знает субъекта, а не только инструмент

Валидации имени и аргументов мало. Минимально полезная модель запроса к шлюзу: actor_id, actor_type, tenant_id, requested_capability, risk_class, approval_state.

С этим составом решение принимается не по правилу «инструмент разрешён», а по правилу «инструмент разрешён именно этому субъекту в этом контексте» — момент, в который идентичность перестаёт быть строкой в таблице доступа и становится исполняемой границей (Agent Identity).

Политика как обозримые данные

Правила исполнения удобно держать конфигурацией, а не кодом:

tools:
  read_kb:
    risk: low
    approval: none
    allowed_roles: ["agent_runtime"]
  create_ticket:
    risk: high
    approval: manager
    allowed_roles: ["agent_runtime"]
  prod_db_write:
    risk: critical
    approval: security_and_owner
    allowed_roles: []
    environments: ["staging"]

В таком описании нет ничего умного, и это его достоинство. Последняя запись показывает приём, который стоит держать в голове: инструмент может быть объявлен, но не разрешён никому и доступен только в непромышленной среде — то есть существовать, не будучи достижимым.

Аргумент от модели — недоверенный ввод

Модель не является границей безопасности. Каждый аргумент, полученный от модели, остаётся вводом под контролем возможного атакующего, пока шлюз его не проверил. Инъекция в подсказке становится опасной именно тогда, когда превращается в цепочку подсказка → инструмент → исполнение (Prompt Injection, Tool Hijacking).

Для инструментов, близких к исполнению кода, базовый минимум: запрет по умолчанию, строгая проверка типов и путей, запрет подстановки в командную оболочку и шаблоны, отдельный профиль песочницы на инструмент (Agent Sandboxing) и событие аудита с отредактированными параметрами, результатом проверки, решением политики и идентификатором профиля песочницы.

Шлюз — граница не только для инструментов

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

Смысл объединения в том, что рост стоимости, перегрузка провайдера или переход на более слабую модель — тот же сигнал деградации, что и отказ политики. Если они живут в разных контурах, картина отказа собирается вручную (Agent CostControl, Cost Anomaly Alerting).

Чего у нас не было: манифест инструмента и изоляция обработчика недоверенных данных

Сверка с OWASP AISVS C9.3 подтвердила основное — шлюз знает субъекта, аргумент от модели считается недоверенным вводом, права режутся до минимума, — и добавила три вещи.

Манифест как объявляемый контракт, а не как описание. Инструмент объявляет требуемые привилегии, лимиты ресурсов и требования к проверке вывода, а рантайм их применяет. Разница с нашей формулировкой практическая: у нас политика живёт на стороне шлюза, здесь она приходит вместе с инструментом и потому едет с ним при подключении из чужого реестра (Supply Chain AI).

Вывод инструмента проверяется схемой. У нас проверялся аргумент на входе в инструмент; стандарт требует и обратного — результат тоже валидируется, потому что дальше он попадает в контекст модели как факт (Overreliance).

Компонент, обрабатывающий недоверенные данные, изолируется от способности вызывать инструменты. Это архитектурное разделение, а не проверка: скомпрометированная обработка данных не должна иметь возможности инициировать вызов вообще. Рядом стоит требование архитектурного разделения обработки недоверенного вывода инструмента и работы самого агента — то же разделение с другой стороны (Dual LLM CaMeL).

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

Связано с

  • Tool Calling — реестр инструментов и разрешение имени в функцию
  • Agent Control Plane — где принимается решение, которое исполняет шлюз
  • Approval Path — что происходит, когда политика требует человека
  • Agent Identity — субъект, по которому шлюз принимает решение
  • Tool Hijacking — угроза, против которой стоит проверка аргументов
  • Agent Sandboxing — профиль изоляции на инструмент
  • Agent Audit Log — что шлюз обязан записать
  • Deterministic Veto — детерминированная перепроверка аргументов