Когда агент просит больше, чем вы: разбор OverAct
Вы просите ассистента найти свободное время в четверг.

Вы просите ассистента найти свободное время в четверг. Он заодно ищет в вашей почте и перечисляет контакты - на всякий случай. Каждый вызов по отдельности выглядит разумно. Вместе это доступ, о котором никто не просил. Этот разрыв и пытается измерить препринт OverAct, опубликованный на arXiv 1 октября.
Коротко
Факты исследования: OverAct - детерминированный бенчмарк без судьи для проактивного превышения полномочий, то есть вызовов инструментов сверх нужного запросу. Он охватывает восемь чувствительных к приватности областей по шесть инструментов. Все семь проверенных моделей вышли за минимальный набор, базовое раздутие охвата - от 1,18 до 2,39 раза. Шаг-фильтр SelfAudit снизил показатель избыточного доступа к личным данным на 43% на умеренных и расплывчатых запросах ценой части покрытия задач. ↗

Что считает OverAct
Бенчмарк использует 720 эпизодов в банках, здравоохранении, электронной торговле, почте и календаре, кадрах, умном доме, путешествиях и соцсетях, всего 48 инструментов. Семь моделей из четырёх семейств запускали по три раза на условие, около 90 720 основных запусков. Главная метрика, коэффициент раздутия охвата, делит число вызванных инструментов на размер размеченного минимального набора. Базовые значения - от 1,18 (DeepSeek-v3, у которой и самое низкое выполнение задач) до 2,39 (DeepSeek-v4-Pro); GLM-5.2 - 1,96. В среднем это около 0,7 лишнего вызова на эпизод. ↗
Расплывчатые запросы обходятся дороже всего
Сильнее всего влияла формулировка запроса. Точные запросы давали почти идеальное соблюдение, а расплывчатые - в 2,7 раза больший избыток. Среди исправлений на уровне подсказки точный список разрешений дал коэффициент 0,96 при покрытии задач 0,95, но требует знания минимального набора. Явный охват (1,42), минимизация (1,18) и уточнение (1,09, покрытие 0,74) меняют покрытие на охват по-разному. Список с лишними инструментами помогал слабо: модели использовали запас примерно пропорционально его размеру. Мой анализ: широкий список разрешений - более слабая защита, чем кажется. ↗
Исправление, работающее как фильтр
SelfAudit просит агента обосновать каждый запланированный вызов словами пользователя и убирает необоснованные вызовы до выполнения. В абляции на умеренных и расплывчатых эпизодах одно обоснование ухудшило результат (показатель приватности +9%), одна фильтрация снизила его на 36%, а полный конвейер - на 43% (с 2,26 до 1,29), при снижении покрытия задач с 0,94 до 0,89. Авторы называют это доказательством концепции. Моё прочтение: названная причина модель не ограничивает, а отдельный шаг, который может отказать, ограничивает.
Игрушечный счётчик, который я написал
Я написал выдуманный пример с придуманными названиями инструментов и выполнил его локально: запросу нужен один календарный инструмент, агент вызывает три. Код считает коэффициент охвата 3,0 и полное покрытие, а затем показывает, что один неверный инструмент тоже даёт коэффициент 1,0 при покрытии 0. Поэтому статья читает оба числа вместе. Входные данные выдуманы, код не является счётчиком статьи.
Чего это не показывает
Авторы отмечают, что схемы контролируемые, по шесть инструментов на область, так что абсолютные уровни в реальных системах могут отличаться. Теоретическая модель подстроена постфактум, показатель приватности считает все категории личных данных равными, а строгий критерий приватности может назвать избыточными и полезные вызовы. Покрытие задач здесь - полнота минимального набора, а не доказательство выполнения задачи. Я прочитал только препринт: бенчмарк и смягчение не запускал и публичный выпуск кода не проверял.
Оригинальная синтетическая проверка
# Invented tool names. Compare an agent's calls with the minimal set.
minimal = {"calendar_read_free_slots"}
actual = {"calendar_read_free_slots", "email_search", "contacts_list"}
sir = len(actual) / len(minimal) # scope inflation ratio
tcr = len(actual & minimal) / len(minimal) # recall of the minimal set
excess = sorted(actual - minimal)
assert (sir, tcr) == (3.0, 1.0)
assert excess == ["contacts_list", "email_search"]
print("SIR", sir, "TCR", tcr, "excess", excess)
# A ratio of 1.0 is not proof of compliance: the right count can hide the wrong tool.
wrong = {"email_search"}
assert len(wrong) / len(minimal) == 1.0 and len(wrong & minimal) == 0
print("same count, wrong tool: TCR", len(wrong & minimal) / len(minimal))