博客 • AI / Agent

Claude Managed Agents 2026 新功能解析:AI Agent 如何自动判断 Tool Call 是否允许?JSON 权限策略与 MCP Security 完整教程

2026 年 9 月 10 日,Anthropic 给 Claude Managed Agents 的权限策略加了一种新类型:auto。同一天,agent.tool_use和agent.mcp_tool_use事件开始带evaluation字段,和原来的evaluated_permission并排。

模型提出 Tool Call,并不等于这次调用会被执行。真正拍板的是服务器上的策略评估:它读你写进 Agent 配置的 JSON policy,再对这一次调用的工具名、输入和会话内容给出 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

策略出现在两个位置:toolset 的default_config.permission_policy,以及configs里某一条工具的覆盖。下面这份配置把 Agent toolset 和 GitHub MCP 都设成auto,再把bash单独钉成always_ask。

创建 Agent 时的 tools 配置(节选自官方文档)
{
  "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,一次高风险调用被拒。

被 auto 拒绝的 agent.tool_use 事件
{
  "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 用 JSON-RPC 暴露 tool,每个 tool 带inputSchema。Host 把目录喂给模型,再把模型的调用转成tools/call。规范见

MCP Tools。

Managed Agents 对这件事的默认态度很保守:MCP toolset 默认always_ask。新工具被加进某个你已经连上的 Server 时,不会在你的应用里悄悄执行。这是 MCP Security 在平台侧能落地的第一道闸,比「相信 Server 自己的 description」可靠。

你仍然可以改。信任某个 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 和权限不能互相替代。

ask 之后的 JSON 审批流

一次调用评成 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 会收到带你deny_message的 tool result。

允许或拒绝一次等待中的调用
{
  "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,你再发确认,API 会回 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
    先格式化策略

    把 Agent 的tools配置丢进JSON 格式化,确认default_config和configs里的permission_policy.type没有写错、没有被覆盖吃掉。

  2. 2
    再校验事件形状

    用JSON Schema给evaluation写一份最小 schema:type枚举always_allow / always_ask / auto,auto 时要求嵌套evaluated_permission。未知的reason_code用additionalProperties兼容,不要直接拒掉。

  3. 3
    对比两次调用

    同一工具一允一拒时,用JSON Diff对齐两次input和两次evaluation。差别几乎总在 command、path 或会话里刚刚发生的那一步,不在工具名。

  4. 4
    留一份可分享的复盘

    策略和打码后的事件可以用Hash 分享递给同事,数据不过服务器。密钥和生产 token 不要放进去。

常见问题

auto 会不会把所有 Tool Call 都放行?

不会。auto 是按次评估:同一工具的两次调用,输入和会话不同,结果可以不同。判定为 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。

小结

9 月 10 日加上的auto,把「这个工具能不能用」改成了「这一次调用能不能跑」。判断依据是你写进 Agent 的 JSON policy,加上这一次的工具、输入和会话;判断结果写回事件里的evaluated_permission和evaluation。

模型负责提出调用。策略引擎负责允许、拒绝或停下来问人。MCP 默认先问人。自定义工具你自己管。客户端推翻不了 deny。

把策略 JSON 和事件 JSON 当成两份契约来读,不要把 Schema 合法误认成已经授权。需要人盯的工具继续 always_ask;需要少打断、又能留下审计字段的工具,再打开 auto。

返回博客