Блог • AI / Agent

Новые возможности Claude Managed Agents 2026: как AI Agent сам решает, разрешён ли Tool Call? Permission policy JSON и MCP Security

10 сентября 2026 года Anthropic добавил новый тип в permission policy Claude Managed Agents: auto. В тот же день события agent.tool_use и agent.mcp_tool_use начали нести поле evaluation рядом с прежним evaluated_permission.

То, что модель предложила Tool Call, ещё не значит, что вызов исполнят. Решает оценка стратегии на сервере: она читает JSON policy из конфигурации Agent и по имени инструмента, input и содержимому сессии этого вызова ставит allow, deny или ask.

В этой статье:

Запомните это: auto — не «всё открыто» и не ручное одобрение. Если сервер считает вызов безопасным, он уже отработал до того, как вы его увидели; если высоким риском — у клиента даже нет шанса отменить deny. Ниже: три стратегии → оценка по вызову → JSON события → MCP → поток одобрения.

Три стратегии: always_allow, always_ask, auto

permission policy касается только инструментов, которые исполняет сервер: встроенный agent_toolset_20260401 и MCP toolset, которые вы подключаете. Пользовательские инструменты исполняет ваше приложение, эта стратегия их не берёт. В запросе нужен beta-заголовок managed-agents-2026-04-01. Официальное описание:

Claude Managed Agents Permission policies.

Стратегия решает «когда этому вызову бежать», а не «есть ли инструмент в каталоге». Убрать инструмент у Agent — через disable. Не ждите, что стратегия его спрячет.

Стратегия Что делает сервер Что ещё делать клиенту
always_allow Сразу исполняет, никого не ждёт Достаточно читать события, шага подтверждения нет
always_ask Останавливается после события tool_use На каждое заблокированное событие отправить user.tool_confirmation
auto Оценивает этот вызов: бежать, отказать или остановиться и спросить вас Обрабатывать только события со статусом ask; deny не отменить

Значения по умолчанию с двух сторон разные. У Agent toolset по умолчанию always_allow. У MCP toolset по умолчанию always_ask. Ни один toolset сам не включает auto — это нужно записать в JSON.

Уже идущая session продолжает жить с тем toolset, с которым её создали. После правки Agent новую стратегию получат только новые session. Примечания к выпуску:

Claude Platform release notes (2026-09-10).

Что auto смотрит на самом деле

Раньше было только «этот инструмент всегда можно» или «этот инструмент всегда спрашивать». auto переносит решение с уровня инструмента на уровень вызова.

В документации конкретно: оценка смотрит сам инструмент, input этого вызова и содержимое сессии до этого момента. Поэтому один и тот же bash с двумя разными command может дать один allow и один deny.

  1. 1
    Вызов разрешён

    Сервер считает этот вызов безопасным: инструмент исполняется как при always_allow. Паузы нет, человеческого окна нет.

  2. 2
    Вызов отклонён

    Сервер оценил его как высокий риск: инструмент не бежит. Agent получает ошибочный tool result: Permission to use {tool_name} has been denied., и is_error: true. Сессия продолжается. Ваш клиент этот deny не изменит.

  3. 3
    Вызов остановился и ждёт вас

    Сервер не даёт однозначного вывода: сессия встаёт на паузу как при always_ask. Дальше вы разрешаете или отклоняете событием подтверждения.

Намерение читается только из тех user.message, которые отправляете вы. Результаты инструментов, скачанные страницы, ответы MCP Server, сообщения между тредами: сервер оценивает содержимое, но не считает их инструкциями. Некоторые вызовы оцениваются как высокий риск, кто бы ни просил.

Если недоверенный текст конечного пользователя вы кладёте как есть в user.message, сервер примет это за ваше намерение и может разрешить вызов. Таким входным инструментам отдельно ставьте always_ask.

В каком JSON пишется стратегия

Стратегия появляется в двух местах: default_config.permission_policy у toolset и перекрытие одного инструмента в configs. Конфиг ниже ставит Agent toolset и GitHub MCP в auto, а bash отдельно закрепляет как always_ask.

Конфиг tools при создании Agent (фрагмент из официальной документации)
{
  "name": "Ops Agent",
  "model": "claude-opus-5",
  "mcp_servers": [
    {
      "type": "url",
      "name": "github",
      "url": "https://mcp.example.com/github"
    }
  ],
  "tools": [
    {
      "type": "agent_toolset_20260401",
      "default_config": {
        "permission_policy": { "type": "auto" }
      },
      "configs": [
        {
          "name": "bash",
          "permission_policy": { "type": "always_ask" }
        }
      ]
    },
    {
      "type": "mcp_toolset",
      "mcp_server_name": "github",
      "default_config": {
        "permission_policy": { "type": "auto" }
      }
    }
  ]
}

mcp_server_name должен совпасть с записью в mcp_servers, у которой name тот же. Когда на стороне MCP перекрывают по имени инструмента, name — имя, которое сообщил Server, не ваш собственный псевдоним.

Если опустить default_config, Agent toolset включится как always_allow. Это удобное значение по умолчанию, не безопасное.

evaluation, которую оставляет каждый вызов

Какая бы ни была стратегия, agent.tool_use и agent.mcp_tool_use несут поле верхнего уровня evaluated_permission со значением allow, ask или deny. У большинства событий есть ещё объект evaluation, в котором type показывает, какая стратегия вынесла решение.

При auto в объекте ещё пишется решение сервера; если исход ask или deny, добавляется reason_code. Официальный пример: bash идёт через auto, высокорисковый вызов отклонён.

Событие agent.tool_use, которое auto отклонил
{
  "type": "agent.tool_use",
  "id": "sevt_01pqr...",
  "name": "bash",
  "input": {
    "command": "rm -rf /workspace/reports"
  },
  "evaluated_permission": "deny",
  "evaluation": {
    "type": "auto",
    "evaluated_permission": {
      "type": "deny",
      "reason_code": "high_risk"
    }
  },
  "processed_at": "2026-03-25T14:05:12Z"
}
evaluation Результат верхнего уровня Смысл
{"type":"always_allow"} allow Разрешённая стратегия — always_allow, вызов уже исполнен
{"type":"always_ask"} ask Разрешённая стратегия — always_ask, сессия вас ждёт
{"type":"auto","evaluated_permission":{"type":"allow"}} allow auto счёл этот вызов безопасным, уже отработал
{"type":"auto","evaluated_permission":{"type":"ask","reason_code":"indeterminate"}} ask auto не дал вывода, остановился спросить вас
{"type":"auto","evaluated_permission":{"type":"deny","reason_code":"high_risk"}} deny auto оценил как высокий риск, уже отказал

reason_code нужен клиенту для ветвления и журнала аудита, это не текст для человека. Сейчас в документации названы indeterminate и high_risk. Клиент должен пережить будущие новые type или reason_code.

В двух случаях нет evaluation. Agent вызвал инструмент, который в сессии не включён: в событии только evaluated_permission: "deny". Старых событий, записанных до появления поля, тоже нет: тогда allow читали как always_allow, ask — как always_ask.

Это тот же слой, что «JSON — граница безопасности», но разрез другой. Там arguments модели сначала надо проверить; здесь платформа сама пишет результат оценки, и его не перевернуть. Предыдущая статья:

AI Agent и граница безопасности JSON.

MCP Tool Call и always_ask по умолчанию

MCP уносит каталог инструментов из вашего репозитория на внешний Server. Server отдаёт tool по JSON-RPC, у каждого tool есть inputSchema. Host кормит каталог модели и превращает её вызов в tools/call. Спецификация:

MCP Tools.

У Managed Agents к этому отношение по умолчанию осторожное: MCP toolset стоит always_ask. Новый инструмент, добавленный на уже подключённый Server, тихо в вашем приложении не исполнится. Это первая дверь MCP Security на стороне платформы — надёжнее, чем «верить description самого Server».

Менять всё равно можно. Доверяете GitHub MCP и хотите меньше прерываний — смените у этого toolset default_config.permission_policy на always_allow или auto. Меняется «когда исполнять», не «нужно ли ещё проверять Schema».

Слой На что отвечает На что не отвечает
JSON Schema Верны ли поля, типы, обязательные ключи и перечисления параметров Должен ли этот вызов случиться
Tool Calling Какой инструмент выбрала модель и какие arguments заполнила Исполнит ли Host
permission policy allow / ask / deny для этого вызова Совпадает ли payload со schema, увела ли description модель

Три слоя вместе похожи на дверь. Включить только auto, а Schema оставить {"sql":{"type":"string"}} — вход для оценщика слишком широк, чтобы судить, больше вызовов падают в indeterminate, то есть ask. Сжать schema — помочь auto вынести вывод, который можно записать в лог. Кто за какой слой отвечает:

Безопасность MCP: почему Schema, Tool Calling и права не заменяют друг друга.

JSON-поток одобрения после ask

Вызов со статусом ask может прийти только из always_ask или из auto со статусом indeterminate. Дальше порядок событий фиксирован.

  1. 1
    Сначала событие tool_use

    Сессия отдаёт agent.tool_use или agent.mcp_tool_use, внутри уже есть evaluated_permission: "ask".

  2. 2
    Затем idle

    Сессия на паузе: у session.status_idle поле stop_reason.type равно requires_action. id заблокированных событий — в stop_reason.event_ids. Она будет ждать.

  3. 3
    Вы отвечаете событием подтверждения

    На каждый заблокированный id отправьте user.tool_confirmation: в tool_use_id — id того события, в result — allow или deny. При отказе deny_message может объяснить. В одном запросе может быть несколько подтверждений.

  4. 4
    Сессия снова running

    Когда все блокировки сняты, разрешённые инструменты исполняются; отклонённые не бегут, Agent получает tool result с вашим deny_message.

Разрешить или отклонить ожидающий вызов
{
  "events": [
    {
      "type": "user.tool_confirmation",
      "tool_use_id": "sevt_01ask...",
      "result": "allow"
    },
    {
      "type": "user.tool_confirmation",
      "tool_use_id": "sevt_01mcp...",
      "result": "deny",
      "deny_message": "Do not push to main from this session."
    }
  ]
}

Если evaluated_permission события не ask, повторное подтверждение даст 400. Сюда входят вызовы, которые auto уже пометил deny: у клиента нет канала на пересмотр. Интерактивно можно через ant beta:sessions connect: в терминале видны ожидающие вызовы, их можно разрешить или отклонить.

Свою очередь одобрения, запись deny обратно в Agent и воспроизводимую стратегию в Host оставим статье про реализацию. Здесь только тот JSON, который платформа уже оценила за вас.

auto — не контрольная точка

В документации есть фраза, которую нельзя пропускать: auto — не человеческая контрольная точка. Если сервер считает вызов безопасным, он исполнится до того, как кто-то его увидит; эффект может быть необратим. Инструменту, который должен видеть человек, ставьте always_ask.

Пользовательские инструменты тоже не в этих воротах. У agent.custom_tool_use нет ни evaluated_permission, ни evaluation. Ваше приложение получает событие, само решает исполнить или отказать и отвечает user.custom_tool_result. Платформа этот прыжок за вас не оценит.

Поэтому фраза «как AI Agent сам решает, разрешён ли Tool Call» узкая: только инструменты Agent и MCP, которые исполняет сервер, и только после того, как вы явно записали policy как auto. Остальное либо всегда можно, либо всегда спрашивать, либо платформе вообще не принадлежит.

Сверить стратегию и события в JSONNote

JSON стратегии, событие tool_use и запрос подтверждения внешне похожи, поля — с разных слоёв. При отладке не сканируйте глазами.

  1. 1
    Сначала отформатировать стратегию

    Конфиг tools у Agent бросьте в форматтер JSON и убедитесь, что default_config и configs несут permission_policy.type без опечатки и не съеденный перекрытием.

  2. 2
    Затем проверить форму события

    Через JSON Schema напишите минимальную schema для evaluation: type перечисляет always_allow / always_ask / auto; при auto требуйте вложенный evaluated_permission. Неизвестный reason_code совместите через additionalProperties, не отсекайте сразу.

  3. 3
    Сравнить два вызова

    Когда один инструмент один раз разрешили, другой раз отказали, через JSON Diff выровняйте два input и два evaluation. Разница почти всегда в command, path или только что случившемся шаге сессии, не в имени инструмента.

  4. 4
    Оставить разбор, которым можно поделиться

    Стратегию и замаскированные события коллеге можно передать через Hash-шаринг: данные не идут на сервер. Ключи и промышленные token туда не кладите.

FAQ

Пропустит ли auto все Tool Call?

Нет. auto оценивает каждый вызов: два вызова одного инструмента с разным input и сессией могут разойтись. high_risk даёт прямой deny; клиент не отменит его через user.tool_confirmation.

Законный JSON Schema уже значит «можно исполнять»?

Нет. Schema отвечает только, верна ли форма параметров. permission policy отвечает, можно ли этому вызову бежать. Законная по форме команда bash под auto всё равно может выйти deny.

Какая стратегия у MCP Tool Call по умолчанию?

У MCP toolset по умолчанию always_ask. Новый инструмент, добавленный на Server, сам в вашем приложении не исполнится. Когда Server уже доверен, смените default_config.permission_policy на always_allow или auto.

Попадают ли пользовательские инструменты под permission policy?

Нет. Custom tools исполняет ваше приложение. Событие — agent.custom_tool_use, без evaluated_permission и evaluation. Вы сами решаете, бежать или нет, затем отвечаете user.custom_tool_result.

Может ли auto заменить ручное одобрение?

Нет. В документации прямо: auto — не человеческая контрольная точка. Если сервер считает вызов безопасным, он исполнится до того, как кто-то его увидит; побочные эффекты могут быть необратимы. Инструмент, который должен видеть человек, отдельно ставьте в always_ask.

Итог

Добавленный 10 сентября auto сменил «можно ли пользоваться этим инструментом» на «можно ли бежать этому вызову». Опора — JSON policy, которую вы записали в Agent, плюс инструмент, input и сессия этого вызова; результат возвращается в evaluated_permission и evaluation события.

Модель предлагает вызов. Движок стратегии разрешает, отказывает или останавливается спросить человека. MCP по умолчанию сначала спрашивает. Пользовательские инструменты — ваши. Клиент не отменяет deny.

Читайте JSON стратегии и JSON события как два договора. Законный Schema — ещё не разрешение. Инструменты, которые должен смотреть человек, оставляйте в always_ask; тем, кому нужно меньше прерываний и при этом поля аудита, открывайте auto.

← Назад к блогу