博客 • 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。
本文將介紹:
- 三種 permission policy 各自攔在哪一層
auto按次評估時看什麼、三種結果分別留下什麼 JSON- MCP toolset 爲什麼默認
always_ask,和 auto 怎麼疊 - 會話停在
requires_action之後,user.tool_confirmation怎麼寫 - 怎麼用 JSONNote 把策略、事件和審批請求拆開覈對
先記住這一點: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
調用被放行
服務器認爲這次安全,工具按
always_allow那樣執行。沒有暫停,也沒有人工窗口。 -
2
調用被拒絕
服務器把它評成高風險,工具不跑。Agent 收到一條錯誤 tool result:
Permission to use {tool_name} has been denied.,並且is_error: true。會話繼續。你的客戶端不能改這個 deny。 -
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。
{
"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,一次高風險調用被拒。
{
"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 必須先被校驗;這邊講的是平臺自己會再寫一份評估結果,而且這份結果你推不翻。前一篇見
MCP Tool Call 和默認 always_ask
MCP 把工具目錄從你的倉庫挪到了外面的 Server。Server 用 JSON-RPC 暴露 tool,每個 tool 帶inputSchema。Host 把目錄餵給模型,再把模型的調用轉成tools/call。規範見
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
先出 tool_use 事件
會話發出
agent.tool_use或agent.mcp_tool_use,裏面已經有evaluated_permission: "ask"。 -
2
再出 idle
會話暫停,
session.status_idle的stop_reason.type是requires_action。被堵住的事件 id 在stop_reason.event_ids。它會一直等。 -
3
你回確認事件
對每個阻塞 id 發
user.tool_confirmation,tool_use_id填那個事件 id,result填allow或deny。拒絕時可用deny_message解釋。一次請求可以帶多條確認。 -
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
先格式化策略
把 Agent 的
tools配置丟進JSON 格式化,確認default_config和configs裏的permission_policy.type沒有寫錯、沒有被覆蓋喫掉。 -
2
再校驗事件形狀
用JSON Schema給
evaluation寫一份最小 schema:type枚舉always_allow/always_ask/auto,auto 時要求嵌套evaluated_permission。未知的reason_code用additionalProperties兼容,不要直接拒掉。 -
3
對比兩次調用
同一工具一允一拒時,用JSON Diff對齊兩次
input和兩次evaluation。差別幾乎總在 command、path 或會話裏剛剛發生的那一步,不在工具名。 -
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。
把策略和 tool_use 事件拆開看