← Все статьи

Знакомьтесь, Jev: второе мнение, которое отвечает типами, а не прозой

Теперь Agent! спрашивает Jev (TypeSafe System One), насколько разрушительна команда шелла, прежде чем её выполнить. Рассказываем, почему Jev — советник, а не ещё один LLM-провайдер.

Сегодня в Agent! появляется новый уровень защиты: Jev, сокращение от TypeSafe System One. Перед запуском команды шелла Agent! теперь может задать Jev один вопрос: насколько вероятно, что эта команда безвозвратно уничтожит данные? Если оценка выше вашего порога, команда отклоняется.

Функция появилась в коммите 337c94a2, «Add Jev (TypeSafe System One) decision layer». В этой статье речь пойдёт о самом важном проектном решении: Jev — не ещё один LLM-провайдер.

Почему бы просто не спросить другую модель?

Agent! уже работает с 23 LLM-провайдерами. Самым простым путём было бы добавить «модель безопасности» как ещё одного провайдера и спрашивать её обычным языком, выглядит ли команда опасной. Проблема в том, что возвращается в ответ: проза. «Эта команда может быть рискованной в зависимости от…» — это не вердикт. В итоге вы разбираете предложения, чтобы решить, запускать ли rm.

Jev устроен иначе. Он отвечает на типизированные вопросы о состоянии, возвращая Choice, Score или Noul — типизированный ответ «ничего». Он не генерирует текст и не генерирует аргументы для инструментов. Сообщение коммита формулирует вывод так: Jev «консультирует существующий цикл инструментов, а не выступает в роли APIProvider».

В этом разделении и заключается вся архитектура:

  • Выбранная вами модель действует. Она планирует, вызывает инструменты и пишет код.
  • Jev оценивает. Он возвращает число, которое код может сравнить с порогом.

Где он находится

Jev ничего не заменяет. Порядок проверок для каждой команды шелла такой:

  1. ShellSafetyService.check: жёстко заданные правила, отклоняющие катастрофические команды. Никаких моделей.
  2. Jev: только для команд, уже прошедших шаг 1, как второе мнение о том, чего не видят шаблоны.
  3. Выполнение команды.

С первого дня проверка охватывает оба пути выполнения шелла в ShellTools (executeTCC и executeTCCStreaming).

Создан так, чтобы никогда не тормозить вашу задачу

Советник, способный заблокировать агента, по-своему опасен. Если сервис недоступен, зависнет ли ваша ночная задача? Здесь ответ — нет. JevAdvisor работает по принципу fail-open. Нет ключа, выключен переключатель или сервис лежит — это означает «нет мнения», и команда выполняется.

Однако fail-open безопасен, только если он заметен. В течение первого же дня два последующих коммита это обеспечили:

  • «Make the advisor observable» (e25384f3) добавил колбэк использования и отчёты об ошибках, так что неудачная проверка записывается в лог, а не выглядит молча как «безопасно».
  • «Log the verdict, not just that Jev answered» (d3c47e67) заставил каждую проверку выводить фактический результат: процент риска разрушения и то, была ли команда разрешена или отклонена.

Клиент — полноценный пакет

Первая версия использовала самописный HTTP-клиент: POST /v1/systemone для вопросов, GET /v1/models для списка моделей, Bearer-аутентификацию и повторные попытки с задержкой при ответах 429 и 529. Уже через несколько часов 9e330357 заменил его пакетом TypeSafeKit, а f3a817b8 вендорил этот пакет прямо в репозиторий Agent, чтобы сборка никогда не зависела от его загрузки.

Настройка

Jev находится в настройках и имеет собственный API-ключ, который хранится в Keychain в отдельном слоте, не связанном с провайдерами. Там же есть выбор модели, загружаемый из /v1/models, и переключатель консультаций. Выключите переключатель — и Agent! будет вести себя в точности как раньше.

Почему это важно

Агенты повсюду получают доступ к шеллу, а стандартный ответ на вопрос о безопасности — «модель будет осторожна». Правила на основе шаблонов лучше, потому что их можно проверить. Но они знают только те шаблоны, которые кто-то записал. Типизированное второе мнение добавляет суждение, не добавляя неоднозначности: оно возвращает число, а решение принимает код.

Мы будем настраивать порог по умолчанию и следить за логами. Если Jev отклонит то, что не следовало, или пропустит то, что должен был поймать, откройте issue на GitHub и приложите строку из лога.