Файловая система — это не язык политик
Полный доступ к диску — это бинарное разрешение над деревом файлов. Он отвечает на один вопрос: может ли этот процесс открыть этот путь? Он не может ответить на вопрос, который важен для автономного агента: почему этот процесс читает этот файл и оправдывает ли эту цель чтение?
Рассмотрим два чтения одного и того же пути. Агент, разрешающий зависимость, читает файл конфигурации, чтобы узнать расположение реестра пакетов. Агент, готовящий сводку для поддержки, читает хранилище учётных данных, чтобы извлечь API-токен. На уровне файловой системы это идентичные операции. У модели прав нет словаря для намерения, поэтому она не может их разделить. Разрешение либо есть, либо нет, и, будучи выданным, оно применяется к каждому чтению, которое агент выполняет за всё время жизни процесса.
Решение Apple ужесточить полный доступ к диску в macOS для ИИ-агентов — разумный ответ на реальное изменение профиля риска. Агент — не человек-оператор. Он работает на машинной скорости, он может выстраивать цепочки вызовов инструментов, не останавливаясь для суждения, и он может действовать по инструкциям, которые приходят по тому же каналу, что и данные, которые он читает. Однако средство защиты остаётся более грубой версией того же примитива: запрос, диалог согласия, более узкое разрешение. Оно сужает кто может читать, но по-прежнему не может выразить, для чего это чтение. Настоящая единица доверия — это тройка из агента, класса данных и цели. Ни одна модель прав файловой системы не может выразить эту тройку, потому что файловая система не знает задачи агента.
Классы данных как единица разграничения
Рабочая альтернатива — перестать рассматривать файловую систему как границу политики и начать рассматривать класс данных как единицу разграничения. Классифицируйте читаемые данные по уровням до запуска любого агента:
- Публичные: документация, опубликованные справочные материалы, открытые наборы данных.
- Операционные: конфигурация сервисов, манифесты развёртывания, неконфиденциальные логи.
- Персональные: записи пользователей, стенограммы обращений в поддержку, всё, что идентифицирует человека.
- Секретные: учётные данные, токены, закрытые ключи, материал для подписи.
Агент объявляет нужные ему уровни как часть своего манифеста запуска. Агент извлечения, который суммирует публичную документацию, объявляет public. Агент триажа, который читает стенограммы обращений в поддержку, объявляет public и personal. Агент, который ротирует учётные данные, объявляет secret, и это объявление должно быть достаточно необычным, чтобы вызвать проверку.

Принудительное применение должно находиться на уровне инструментов, а не на уровне ОС. Агент не получает смонтированный том и путь. Он получает функции: read_public_doc(id), read_support_ticket(id), read_credential_ref(name). Каждая функция сверяет объявленный набор уровней агента с уровнем данных, которые она собирается вернуть. Если агент не объявил secret, функция доступа к учётным данным возвращает отказ, а не дескриптор файла. Поскольку собственный код агента никогда не видит путь в файловой системе, он не может повысить привилегии, открыв файл напрямую. Граница — это свойство интерфейса, а не уровня привилегий процесса.
Это также создаёт журнал аудита, который журнал файловой системы не может восстановить. Журнал файловой системы фиксирует, что процесс 4821 открыл /etc/credentials/store. Журнал уровня инструментов фиксирует, что агент triage-v3 с объявленной целью summarise open support tickets запросил read_support_ticket(88213) и получил запись уровня personal. Когда происходит чтение между уровнями, журнал несёт рядом с ним объявленную цель. В этом разница между знанием о том, что файл был открыт, и знанием о том, чего агент пытался достичь.
Конкретный механизм
Этот паттерн — обёртка возможностей с проверкой уровня и отметкой цели. В общих чертах:
TIERS = {"public": 0, "operational": 1, "personal": 2, "secret": 3}
def guarded_read(agent, resource, tier):
if TIERS[tier] > TIERS[agent.declared_max_tier]:
audit.deny(agent.id, resource, tier, agent.purpose)
raise ScopeError(f"{agent.id} is not scoped for {tier}")
audit.allow(agent.id, resource, tier, agent.purpose)
return resource.fetch()
Объявленный максимальный уровень агента фиксируется при запуске. Его расширение в середине запуска — это не изменение конфигурации; это новый запуск с новым манифестом и новым одобрением. Поток аудита доступен только для добавления и ключуется по идентичности агента и объявленной цели, поэтому проверяющий может восстановить не только то, что было прочитано, но и какая задача мотивировала каждое чтение.
Это не песочница в смысле операционной системы. Это слой политики, который предполагает, что агент взаимодействует с миром исключительно через обёрнутые инстр
Чего это стоит
Классификация по уровням выполняется вручную и со временем дрейфует. Появляется новый источник данных; кто-то назначает ему уровень; шесть месяцев спустя источник содержит поле, которого раньше не содержал, и уровень теперь неверен. Классификации нужен владелец и периодичность проверок, и этот владелец — реальная постоянная затрата. Нет автоматического способа вывести правильный уровень поля из его содержимого, а попытки сделать это, как правило, либо слишком разрешительны, либо слишком шумны, чтобы им доверять.
Принудительное применение на уровне инструментов предполагает, что агент не может обойти уровень инструментов. Это верно внутри песочницы без прямого доступа к системным вызовам и без сетевого выхода за пределы обёрнутых интерфейсов. Это неверно в тот момент, когда агент выполняется в процессе, который может открывать файлы, порождать подпроцессы или напрямую обращаться к сети. Слой политики настолько силён, насколько сильна изоляция под ним, а значит, дизайн требует и того, и другого: уровневых интерфейсов инструментов и среды выполнения, которая действительно не может из них вырваться.
Компромисс сознательный. Больше работы по классификации на старте, владелец для дрейфа уровней и среда выполнения, обеспечивающая изоляцию, — в обмен на поверхность раскрытия, которая читаема, принудительно исполнима и поддаётся аудиту. Разрешение файловой системы дёшево выдать и невозможно осмыслить постфактум. Объявление уровня дорого поддерживать и легко читать во время проверки.
Правило проектирования
Никогда не выдавайте агенту тот же примитив доступа, который вы выдали бы человеку-оператору. У человека есть суждение, которого нет у агента; у агента есть пропускная способность, которой нет у человека. Человек с полным доступом к диску читает то, что требует задача, и останавливается. Агент с полным доступом к диску читает то, к чему его ведут его политика или его промпт, со скоростью, которую не может обеспечить никакая проверка человеком. Примитив должен отражать эту асимметрию, а не игнорировать её.
Ограничивайте чтение самым узким классом данных, который удовлетворяет задачу. Рассматривайте любое расширение как изменение, требующее повторного одобрения, а не как переключатель конфигурации. Если агенту нужны personal данные для одного шага конвейера, этот шаг должен быть отдельным запуском с собственным манифестом, а не более широким разрешением для всего конвейера.
Предпочитайте интерфейсы в форме запроса, а не в форме данных. Функция, которая возвращает текущий обменный курс для валютной пары, имеет форму запроса: агент заявляет, что ему нужно, и получает именно это. Смонтированный том с CSV-файлами имеет форму данных: агент получает всё и должен решить, что читать. Интерфейсы в форме запроса делают цель явной в месте вызова, а именно там и должна жить политика. Интерфейсы в форме данных перекладывают решение на агента, где оно невидимо для модели прав и, часто, для журнала аудита.
Ужесточение Apple полного доступа к диску — сигнал, что индустрия заметила: агенты — это другой вид принципала. Следующий шаг — перестать расширять примитив файловой системы и начать выражать тройку, которая действительно управляет раскрытием: какой агент, читая какой класс данных, с какой целью. Эта тройка и есть политика. Файловая система — всего лишь место, где случайно лежат байты.
