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

Агенты должны запрашивать действия, а не получать средства для выдачи себя за человека или сервисную учётную запись. Это кажется очевидным, пока не изучишь типичный инструмент агента: функция http_request принимает URL, заголовки, метод и тело, а агент получает bearer-токен из переменной окружения. Вызов инструмента выглядит аккуратно. Полномочия же оказываются разбросаны по тексту промпта, памяти процесса, журналам, истории оболочки и любому следующему подпроцессу, который запустит агент.
Архитектура без секретов проводит чёткую границу между намерением и выполнением. Агент говорит: «создать развёртывание этого сервиса в этом окружении». Слой, владеющий учётными данными, решает, можно ли выполнить действие, выбирает нужное удостоверение, выполняет аутентифицированный вызов и возвращает результат. Это меняет возможности аудита, подтверждения и отзыва доступа. Кроме того, такая схема заставляет создавать интерфейсы, которым действительно можно доверить автономность.
Контракт должен описывать намерение, а не транспорт
Контракт действия называет операцию, которую узнаёт пользователь, и ограничивает входные данные фактами, необходимыми для этой операции. Детали транспорта должны оставаться за границей. Разницу легко не заметить, потому что HTTP превращает любое действие в метод, URL, заголовки и JSON-тело.
Рассмотрим два интерфейса инструмента для открытия запроса на изменение. Первый часто встречается, но небезопасен для автономного процесса:
{
"name": "http_request",
"input": {
"method": "POST",
"url": "https://code.example/api/projects/alpha/changes",
"headers": {
"Authorization": "Bearer ${TOKEN}",
"Content-Type": "application/json"
},
"body": {
"title": "Fix timeout",
"branch": "agent/fix-timeout"
}
}
}
Этот интерфейс даёт агенту контроль над назначением, способом аутентификации и формой запроса. Удаление самого токена ничего не исправит, если агент может выбрать псевдоним заголовка, идентификатор учётных данных, URL прокси или команду оболочки, которая прочитает токен в другом месте. Секрет переместился, но полномочия не уменьшились.
Интерфейс, построенный вокруг контракта, выглядит так:
{
"name": "create_change_request",
"input": {
"project": "alpha",
"source_branch": "agent/fix-timeout",
"title": "Fix timeout in retry path",
"description": "Adds a bounded retry and a regression test."
}
}
Слой выполнения сопоставляет project с известной конечной точкой и одобренной учётной записью. Он сам добавляет заголовок аутентификации. Он может отклонить имя ветки, проверить целевой репозиторий, запросить подтверждение или вернуть ошибку удалённого сервиса. У агента нет параметра со смыслом «использовать любые учётные данные, которые дадут максимум доступа».
Это различие часто размывают: архитектура без секретов не равна простому сокрытию токенов. Сокрытие пытается контролировать то, что агент видит после получения полномочий. Контракт действия не даёт агенту завладеть этими полномочиями. Если промпт модели утечёт, журнал инструментов скопируют или подпроцесс прочитает окружение, первая схема уже потеряла учётные данные. Вторая может раскрыть рабочие данные, которым нужны собственные меры защиты, но не передаёт материал для подписи запросов.
Контракт также не должен делать вид, будто каждой конечной точке нужен отдельный инструмент. Специальные действия оправданы там, где человек может описать желаемый результат одним предложением. «Перезапустить это тестовое окружение» описывает результат. «Отправить PATCH на любой URL» является примитивом транспорта. Если этот примитив нужен заданию по обслуживанию, отдайте его отдельной интеграции с жёсткими ограничениями, а не универсальному агенту для работы с кодом.
Запрос должен выполнять владелец учётных данных
Контракт ничего не защищает, если агент по-прежнему выполняет финальный сетевой вызов с секретом, подключённым к его процессу. Компонент, который хранит учётные данные, должен сам выполнять HTTP-запрос или SSH-подключение.
Граница выполнения отвечает за пять задач:
- сопоставляет имя действия с фиксированным назначением и правилами протокола;
- выбирает сохранённое удостоверение из небольшого одобренного набора;
- добавляет учётные данные только в исходящий запрос или обмен данными для SSH-аутентификации;
- записывает запрос, решение и результат, не помещая секреты в журнал;
- возвращает ответ в форме, предназначенной для действия, а не дамп своего внутреннего состояния.
Процесс модели не должен получать ни токен, ни закрытый ключ, даже временный. Избегайте конструкций вроде TOKEN=$(vault read ...), файлов с учётными данными в рабочем каталоге, значений Authorization в сгенерированных командах curl и SSH-агентов, общих с оболочкой, запущенной агентом. Каждая такая схема удобна, потому что сохраняет существующие скрипты. Но каждая превращает процесс агента во владельца учётных данных.
Документ IETF OAuth 2.0 Security Best Current Practice делает в другом контексте тот же практический вывод: bearer-токены нужно защищать при хранении и передаче, потому что любой, кто ими владеет, может их использовать. Bearer-токен не становится безопасным от просьбы к модели не выводить его. Проверкой авторизации становится сам факт владения. Для инструмента агента лучше вообще не давать процессу владеть токеном.
Для SSH граница должна владеть не только закрытым ключом. Интерфейс ssh host command даёт агенту широкие возможности даже тогда, когда ключ не покидает вспомогательный процесс. Помощник должен выбрать сохранённое описание хоста и удостоверение, а затем разрешить форму команды, подходящую для этого хоста. Например, сервер развёртывания может разрешать status, restart-service и tail-release-log с именем сервиса. Он не должен молча принимать bash -c только потому, что кому-то понадобилось быстрое решение.
Не путайте это с прокси-посредником. Прокси пересылает произвольный трафик клиента и обычно видит учётные данные во время передачи. Слой действий, владеющий учётными данными, получает запрос на именованную операцию, сам формирует исходящий вызов и хранит секрет в собственном хранилище. От этого различия зависит, может ли агент превратить одобренное действие в другое.
Дизайн параметров определяет, сколько полномочий просочится
Каждое поле контракта создаёт степень свободы. Хорошие поля указывают объект работы или передают содержимое, действительно необходимое действию. Плохие поля меняют направление полномочий, используемое удостоверение или выполняемую низкоуровневую операцию.
Проверьте каждый предлагаемый входной параметр: если агент изменит это значение, сможет ли он перенаправить привилегированный запрос в другую систему, расширить набор затрагиваемых ресурсов или изменить аутентификацию? Если да, удалите поле, превратите его в перечисление, сопоставляемое исполнителем, или разделите операцию на отдельные контракты.
Интерфейс развёртывания хорошо показывает разницу:
{
"name": "deploy_release",
"input_schema": {
"type": "object",
"additionalProperties": false,
"required": ["service", "environment", "version", "reason"],
"properties": {
"service": {"type": "string", "enum": ["api", "worker"]},
"environment": {"type": "string", "enum": ["test", "production"]},
"version": {"type": "string", "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$"},
"reason": {"type": "string", "maxLength": 500}
}
}
}
Схема не допускает неожиданные поля вроде url, headers, credential_name или command. Исполнитель может сопоставить service и environment с известной целью развёртывания. Важность additionalProperties: false легко недооценить. Без этого разрешающий валидатор может сохранить неизвестное поле, а позже кто-то подключит его к HTTP-клиенту «для гибкости». Так безобидная точка расширения превращается в лазейку для учётных данных.
Перечисления подходят не всегда. Название репозитория, ветка, номер задачи или путь к файлу могут меняться. Проверяйте такие значения с учётом их предметной области и после разрешения дополнительно выполняйте проверку границы. Например, сопоставьте идентификатор репозитория с локальным списком разрешённых значений, а затем используйте связанное с ним удалённое расположение. Не принимайте URL репозитория и не пытайтесь решить, выглядит ли он безопасным.
К свободному тексту нужен отдельный подход. Агенту может понадобиться написать описание задачи, сводку запроса на слияние или ответ службы поддержки. Этот текст является содержимым, а не полномочием, но он всё равно может причинить вред через упоминания, разметку, шаблоны или встроенные команды, которые обработает удалённый сервис. Ограничьте его длину, явно определите правила отображения и не вставляйте его в команду оболочки. Если действие должно выполнить команду, создавайте массив аргументов напрямую и передавайте непроверенный текст как аргумент-данные, а не как часть строки команды.
Универсальные инструменты запросов создают скрытые движки политик
Универсальный HTTP-инструмент популярен, потому что с его помощью можно за день подключить агента к любому сервису. Для большинства привилегированных задач агентов он не подходит: каждый промпт, описание инструмента и участок кода превращается в неофициальную политику авторизации.
Команды часто начинают с оболочки вроде:
request(method, url, headers, body)
Затем добавляют защитные меры. Блокируют несколько доменов. Удаляют Authorization. Разрешают определённые методы. Проверяют префикс URL. Отклоняют localhost. Требуют подтверждение для рискованных вызовов. Через несколько месяцев кому-то нужен новый адрес с особым заголовком, он добавляет исключение, и в оболочке появляется язык политик без тестов и понятного владельца.
Проблема не в том, что универсальные инструменты всегда вредны. Они подходят для отладочной консоли, которой управляет человек и где оператор уже обладает полномочиями и может проверить каждый байт. Они также подходят интеграционному сервису, который получает вызовы от контролируемого вами кода и имеет узкое сетевое удостоверение. Автономный агент устроен иначе: он может выполнять много вызовов, находить неожиданные пути и действовать на основе непроверенного текста. Ему нужно меньше степеней свободы.
Создавайте именованные действия вокруг устойчивых рабочих единиц. Для сервиса контроля версий лучше использовать read_merge_request, comment_on_merge_request и create_branch, а не универсальный REST-клиент. Для операций предпочтительнее get_service_status, fetch_release_logs и request_deployment. Контрактов может стать больше, но у каждого будут владелец, набор тестов, понятная отметка о необходимости подтверждения и обозримый радиус воздействия.
Не прячьте универсальный запрос и внутри именованного действия. Инструмент update_ticket, который принимает произвольные path, method и body, изменил только название. Контракт должен связывать эти детали. Он может предоставлять управляемый объект изменений, если удалённому API это необходимо, но исполнитель должен сам выбирать конечную точку, HTTP-метод, тип содержимого и учётную запись.
Спецификация Model Context Protocol помогает обнаруживать инструменты: сервер может публиковать клиенту их имена, описания и JSON-схемы входных данных. Схема полезна, но не делает безопасным слишком широкое действие. JSON Schema может сообщить, что URL является строкой. Она не может определить, что это единственная платёжная конечная точка, к которой разрешено обращаться рабочему удостоверению. Авторизация остаётся обязанностью слоя выполнения.
В запросе на подтверждение должно быть понятное человеку действие
Подтверждение человеком работает, когда человек видит узнаваемый запрос и может быстро его отклонить. Оно перестаёт работать, когда пользователя просят одобрить непрозрачный набор транспортных деталей после того, как агент уже принял важные решения.
Сравните две карточки подтверждения:
Allow POST https://api.example/v1/resources/882?
Headers: Authorization, X-Region, X-Client
Deploy version 2.14.3 of api to production
Reason: Fixes failed payment retries
Requested by: signed agent process build-worker
Вторая карточка позволяет оценить намерение. Она также даёт аудиторской записи полезную фразу. В первой нужно восстановить смысл по URL и списку заголовков, что быстро приводит к усталости от подтверждений. Люди нажимают кнопку, не читая неразборчивые запросы, особенно когда обычный запуск агента создаёт несколько таких окон.
Запрашивайте подтверждение в момент, когда решение меняет уровень полномочий. Слой выполнения может один раз разрешить новый процесс агента на время сеанса, а затем требовать отдельного решения для выбранных чувствительных учётных данных или разрушительных действий. Так повседневная работа остаётся удобной, а все учётные записи не считаются одинаковыми. Токен проекта только для чтения и удостоверение для развёртывания в production не должны подчиняться одному правилу подтверждения лишь потому, что оба передаются в HTTP-заголовках.
В тексте подтверждения нужно указывать, кто запросил операцию. Идентичность процесса важна: терминальный агент, фоновый помощник и неизвестный исполняемый файл не заслуживают одинакового доверия. В macOS полномочия подписи кода помогают человеку, подтверждающему запуск, понять источник запроса. Это не доказывает безопасность каждой инструкции промпта, но отвечает на первый вопрос: какой процесс пытается действовать от имени этой учётной записи?
Никогда не делайте подтверждение единственным средством защиты. Человек может неправильно прочитать запрос, действовать в спешке или оставить сеанс открытым. Контракт всё равно должен ограничивать входные данные и фиксировать маршрут к учётным данным. Но и не создавайте отдельный язык политик, если ясного контракта действия и решения о подтверждении достаточно. Правила с произвольными полями, временными окнами, регулярными выражениями и утверждениями пользователя быстро превращаются в ещё одну программу, которую никто не сможет уверенно проверить во время инцидента.
Неудачное развёртывание показывает, где ломаются свободные контракты
Типичный сбой начинается с агента, которому разрешено выполнять развёртывание в test через инструмент оболочки. Команда хранит облачный токен в окружении агента, потому что этого требует CLI для развёртывания. Схема инструмента принимает environment и extra_args, что казалось безобидным, пока существовал только test.
В задаче агенту говорят: «проверь срочное исправление в test и сообщи результат». Агент выполняет ожидаемую команду. Затем он видит в репозитории устаревшее сообщение о развёртывании и пробует дополнительный аргумент из старого скрипта. Этот аргумент выбирает production, меняет целевую учётную запись или добавляет расширение оболочки. У токена были права для production, потому что разделение учётных данных казалось лишней сложностью. В этот момент формулировка промпта уже не спасёт. Процесс владеет широкими полномочиями, а интерфейс позволяет ему выбирать цель.
Граница контракта меняет последовательность:
- Агент вызывает
deploy_releaseс перечисляемыми сервисом, окружением, версией и причиной. - Исполнитель сопоставляет окружение с фиксированной целью и выбирает удостоверение, назначенное этой цели.
- Исполнитель запрашивает решение, если для этого удостоверения оно требуется, а затем записывает результат для запуска агента, который отправил запрос.
- Исполнитель возвращает идентификатор и статус развёртывания либо структурированный отказ с объяснением, почему продолжить нельзя.
Агент не может добавить --account, указать облачную конечную точку или прочитать токен. Ошибочное значение production всё ещё возможно, потому что и люди, и модели могут попросить выполнить не то действие. Но теперь в тексте подтверждения прямо написано production, выбранное удостоверение может иметь только полномочия, предназначенные для развёртывания в production, а запись действия связывает решение с процессом и запросом.
Это различие важно при расследовании. В свободной схеме специалисты часто находят разрозненные фрагменты: запись оболочки, события облачного аудита, журнал CI и, возможно, значение токена, который теперь нужно отозвать. В схеме с контрактом можно проверить запрошенное действие, разрешённую цель, метку удостоверения, результат подтверждения, статус ответа и сеанс, который всё запустил. Аудиторский журнал не устраняет ошибку, но сокращает время, которое уходит на догадки о выполненном пути.
Ответы об ошибках должны помогать восстановлению и не раскрывать внутренние данные
Защищённый слой действий должен возвращать ошибки, с которыми агент может работать, не получая секрет, данные подписи запроса или структуру внутреннего хранилища. Слишком расплывчатые ошибки подталкивают агента к повторам и обходным решениям. Слишком подробные превращают журналы ошибок в канал утечки информации.
Используйте стабильные коды ошибок и небольшую публичную структуру:
{
"ok": false,
"error": {
"code": "APPROVAL_REQUIRED",
"message": "Deployment to production needs user approval.",
"retryable": true,
"request_id": "act_01H..."
}
}
Заблокированное хранилище должно возвращать VAULT_LOCKED, отказ пользователя, отвечающего за подтверждение, должен быть APPROVAL_DENIED, нарушение контракта, INVALID_ARGUMENT, а ответ 429 от удалённого сервиса может быть REMOTE_RATE_LIMITED. Агент сможет сообщить состояние, подождать, повторить запрос после изменения условия или выбрать безопасную альтернативу. Ему не следует возвращать ошибку с необработанным заголовком авторизации, дампом субъекта токена, закрытой конфигурацией хоста или полностью подписанным запросом.
Разделяйте ошибку авторизации и ошибку удалённого сервиса. «Доступ запрещён» может означать, что локальный исполнитель отклонил действие, выбранной удалённой учётной записи не хватает прав или удалённый сервис отверг некорректную аутентификацию. Для этих случаев нужны разные исправления. Публичное сообщение может оставаться коротким, а защищённая запись аудита исполнителя должна хранить точный код причины и статус удалённого сервиса.
Повторные попытки должны учитывать смысл контракта. Операции чтения обычно можно повторять. Создание задачи, отправка сообщения или запуск развёртывания могут привести к повторной работе. Добавляйте идентификатор идемпотентности, если удалённый API его поддерживает. Его должен сгенерировать исполнитель либо принять как ограниченный идентификатор запроса. Сохраните связь до отправки запроса и используйте её снова при повторе. Не позволяйте агенту создавать новый идентификатор при каждом тайм-ауте: пытаясь помочь, он может создать дубликаты.
Для действий без поддержки идемпотентности на удалённой стороне используйте схему подготовки и подтверждения. Действие подготовки возвращает короткоживущий план с описанием цели и изменений. Действие подтверждения ссылается на этот план и требует актуального решения. Это добавляет один сетевой обмен, но обходится дешевле, чем повторная оплата, удаление или изменение production после неоднозначного сбоя сети.
Для аудита нужны два представления и один источник истины
Полезная система аудита отвечает на два разных вопроса: что пытался выполнить запуск агента и что сделал каждый привилегированный вызов? Если объединить их в один неразличимый поток событий, будет сложно либо восстановить сеанс, либо найти конкретный запрос.
Ведите журнал сеанса для запуска. В нём должны быть идентичность процесса, время начала и окончания, решение об авторизации, состояние отзыва и действия, запрошенные за время запуска. Отдельно ведите журнал активности вызовов. В нём нужны имя действия, нормализованные параметры, метка выбранных учётных данных без секрета, результат подтверждения, время выполнения, класс назначения и итог.
Оба представления должны строиться из одной добавляемой записи, которую нельзя менять. Иначе экран сеанса и журнал вызовов могут расходиться, если один из записывающих компонентов завершится с ошибкой или по-разному отфильтрует события. У зашифрованного журнала без чтения есть и практическое преимущество: компонент, добавляющий событие, не должен расшифровывать старые записи только для того, чтобы записать новую.
Защита от незаметного изменения требует офлайн-проверки. Цепочка хешей позволяет обнаружить удаление, подмену или перестановку записей, если проверяющему доступна последовательность журнала. Проверка должна выполняться над шифротекстом, чтобы аудитор мог подтвердить непрерывность цепочки без ключа хранилища. Это не доказывает, что скомпрометированная машина никогда не пропускала события. Но это подтверждает, что сохранённая цепочка не была незаметно изменена задним числом. Эти утверждения нужно разделять.
Утилита командной строки для проверки должна понятно сообщать об ошибках. Например:
$ sp audit verify audit.log
verified: 184 records
first sequence: 9012
last sequence: 9195
chain: valid
Если запись 9137 изменили, команда должна указать первую нарушенную последовательность и завершиться с ненулевым кодом. Не сообщайте только «проверка не пройдена». Во время инцидента важно знать, с какого места свидетельства перестают быть надёжными.
Sallyport использует такое разделение для сеансов агентов и отдельных действий, строя оба представления из одного зашифрованного журнала аудита с цепочкой хешей. Команда sp audit verify проверяет его без ключа хранилища. Для локального шлюза агента это правильная схема: отзыв работающего сеанса и расследование отдельного вызова являются разными задачами.
Контракты нужно проверять попытками выйти за их границы
Тесты штатного сценария доказывают, что действие работает. Тесты безопасности доказывают, что заявленные входные данные являются единственными средствами управления для вызывающей стороны. Пишите такие тесты до добавления удобного параметра, потому что именно через удобные параметры полномочия обычно возвращаются.
Для каждого действия проверьте как минимум следующее:
- отклоняется неожиданное поле, включая
headers,url,commandи ссылки на учётные данные; - отклоняются значения, которые после разрешения выходят за набор ресурсов, разрешённых действию;
- исходящие HTTP-запросы получают учётные данные только после того, как исполнитель сформировал назначение;
- записи аудита не содержат токены, материал закрытых ключей и подписанные поля авторизации;
- отклонённый или отозванный сеанс не может повторно использовать прежнее подтверждение.
Используйте в тестах поддельный исходящий сервер и проверяйте полученный запрос. Тест должен проверять фактический URL, метод, заголовки, сформированные исполнителем, и отсутствие аутентификации, контролируемой вызывающей стороной. Если замокетировать только внутренний клиент исполнителя, можно не заметить главное: что покинет машину, если агент передаст вредоносные параметры?
Проверяйте также неудобные входные данные, которые агент в конце концов создаст: идентификатор репозитория с префиксом схемы, имя ветки со знаками оболочки, Unicode-символ, похожий на символ в метке окружения, повторяющиеся поля JSON, огромное описание и тайм-аут после того, как удалённый сервис принял действие. Проверка контракта должна завершаться отказом. Если исполнитель не может уверенно разрешить запрошенную цель, он должен отклонить вызов и вернуть понятную ошибку.
Проверяйте контракты как код, обладающий полномочиями. Спросите, даёт ли новое поле вызывающей стороне путь к другому хосту, более широким правам учётной записи, другой команде или другому классу объектов. Если да, сделайте полномочия явными в названии действия и правилах подтверждения. Простое действие delete_file со свободным абсолютным путём гораздо сложнее анализировать, чем remove_preview_asset с идентификатором ресурса, который разрешается внутри известного проекта.
Обычно первым стоит исправить контракт, принимающий произвольный URL или строку оболочки. Замените его самым узким именованным действием, которое покрывает реальную работу пользователей. Интерфейс станет менее «умным», а агент получит меньше полномочий, причины ограничений которых не придётся объяснять задним числом. Это и есть прогресс.
Вопросы и ответы
Может ли AI-агент использовать API, не получая API-ключ?
Да. Отдельный слой выполнения может аутентифицировать запрос, не раскрывая учётные данные, если он сам владеет ими и выполняет запрос. Агент передаёт имя действия и ограниченные параметры, а затем получает ответ или сообщение об ошибке.
Что такое контракт действия для AI-агента?
Контракт действия описывает намерение, допустимые параметры, ожидаемый результат и поведение при ошибке для одной операции. Он уже спецификации API, потому что должен описывать только те действия, которые агент может попросить выполнить у слоя выполнения.
Какие поля нужно убрать из интерфейса инструмента агента?
Инструмент агента может принимать рабочие данные: репозиторий, окружение, текст задачи или идентификатор ресурса. Он не должен принимать заголовки авторизации, строки cookie, пути к закрытым ключам или произвольные объекты запросов, позволяющие косвенно выбирать учётные данные.
Безопасен ли универсальный инструмент HTTP-запросов для автономных агентов?
Только если операция намеренно остаётся примитивом транспортного уровня и вы принимаете связанные с этим полномочия. Для большинства автономных агентов лучше использовать именованные операции, поскольку универсальная пара HTTP-метод и URL часто превращает каждый промпт в часть скрытой политики доступа.
Как агенту обрабатывать отклонённое действие?
Шлюз должен вернуть стабильную машиночитаемую ошибку, сообщающую, что действию нужно подтверждение или хранилище заблокировано, не раскрывая секреты. Агент может сообщить об этом и подождать. Ему нельзя обходить отказ через другой путь к учётным данным.
Как поддержать несколько учётных записей, не передавая учётные данные?
Добавьте выбор учётной записи в контракт, если для одного действия допустимы несколько удостоверений. Сопоставляйте этот выбор с сохранёнными учётными данными внутри слоя выполнения и отклоняйте неизвестные значения вместо того, чтобы принимать от агента произвольную ссылку на учётные данные.
Решает ли редактирование вывода инструмента проблему раскрытия учётных данных?
Нет. Фильтрация вывода уменьшает риск случайного раскрытия, но не отменяет полномочия, которые агент уже получил вместе с токеном или закрытым ключом. Сначала не допускайте учётные данные в процесс, а обработку ответов рассматривайте отдельно.
Могут ли инструменты без секретов работать с SSH-командами?
Для SSH нужны именованный хост, разрешённая форма команды и сохранённое удостоверение, выбранное слоем выполнения. Передача закрытого ключа через переменную окружения, временный файл или параметр агента лишь меняет место возможной утечки.
Как контракты действий предотвращают повторные разрушительные запросы?
Используйте идентификатор, защищённый от повторного выполнения, узкую операцию и идентификатор запроса, который сохраняет слой выполнения. Для неидемпотентных действий требуйте подтверждение человека в момент выполнения или используйте схему подготовки и подтверждения с явным сроком действия.
Предоставляет ли MCP авторизацию для инструментов агентов?
Используйте схему инструментов Model Context Protocol для обнаружения и проверки входных данных, но не путайте проверку схемы с авторизацией. Контракт всё равно должен связывать запрошенное действие с учётными данными, которые хранятся вне процесса агента, и с решением о выполнении под контролем человека.