把智能体送上生产前,权限这一关总要选一次,而且过去只有两个坏选项:每次都问,流水线被几百次确认弹窗磨到没脾气;全都放行,等于让一个刚读完 README 的模型直接对着生产跑命令。Anthropic 在 9 月 10 日给托管智能体加了第三档 auto——每一次工具调用先交给服务端评估器,由它决定执行、拒绝,还是停下来等人确认。
ant 命令行。托管智能体仍处测试阶段,字段与控制台入口以官方最新文档为准。三档权限,各自的代价在哪
先把三档摆在一起看,才明白为什么需要中间那一档:
| 档位 | 行为 | 代价 |
|---|---|---|
| always_allow | 直接执行,不留确认 | 开发期舒服,生产期危险 |
| always_ask | 每次调用都等人批准 | 摩擦极高,批准逐渐变成走过场 |
| auto | 服务端逐次评估,三选一:执行 / 拒绝 / 暂停等确认 | 决策理由在测试阶段不暴露 |
官方给出的一个数字解释了 always_ask 为什么不可持续:在被统计的手工确认里,约 93% 最终都被批准了。当绝大多数确认都会被点「同意」,这套机制就不再是安全防线,只是摩擦。反过来,always_allow 又完全不设防。auto 的位置就在这两个极端之间。
Step 1:先搞懂评估器看什么、给什么
评估发生在服务端,输入有三样:被调用的工具、这次调用的参数、以及到此刻为止的会话历史。输出是三种决定之一:
| 决定 | 结果 |
|---|---|
| allow | 调用正常执行 |
| ask | 暂停,等人工批准后继续 |
| deny | 直接拦下,模型必须换另一条路 |
Step 2:在工具集级别打开 auto
auto 必须显式开启,不会自己生效。开在工具集的默认配置上,整个工具集就走评估流程:
name: Coding Assistant
model: claude-opus-5
tools:
- type: agent_toolset_20260401
default_config:
permission_policy:
type: auto
先看默认值,再看你要改什么。内置的 agent 工具集默认是 always_allow,而 MCP 工具集默认是 always_ask,两者的出发点完全不同。直接给一个默认全放行的工具集打开 auto 是收紧;给默认就要问的 MCP 工具集打开 auto,反而是把「逐次明确批准」换成了「服务端代判」。
Step 3:逐工具覆盖,把风险挑出来单管
更实用的做法是分层:读操作保持在宽松档,只把高风险动作送进评估器。单工具的策略会覆盖工具集默认值:
name: Coding Assistant
model: claude-opus-5
tools:
- type: agent_toolset_20260401
default_config:
permission_policy:
type: always_allow # 默认:读写文件等常规操作直接跑
configs:
- name: bash
permission_policy:
type: auto # 只有 bash 走服务端评估
Step 4:MCP 工具集要单独设
name: Research Assistant
model: claude-opus-5
tools:
- type: mcp_toolset
server: docs-server
default_config:
permission_policy:
type: auto
configs:
- name: search_docs # 用 MCP 服务器实际上报的工具名
permission_policy:
type: always_allow
如果你同时在运营 MCP 服务器本身,请注意这个组合:管理端开了 auto 的智能体去调你的服务器,调用可能在服务端被静默拒绝,而客户端只看到一个失败结果。MCP 侧的日志要留好,否则两边都以为不是自己的问题。
Step 5:ask 落到谁头上——把终端接进会话
决定为 ask 时,得有人来处理。命令行的做法是把自己挂到正在跑的会话上,待批准的调用会以行内提示的形式出现:
# 连接到托管智能体会话,实时跟进对话记录
ant beta:sessions connect
# 等待批准的调用会以行内提示出现,直接选允许或拒绝
# 想在浏览器里看,加 --web
ant beta:sessions connect --web
# 它会在本机起控制台的会话视图并打开
# 你不需要反复轮询看板:保持连接,直到会话结束或你主动断开
--web 作为默认。终端提示适合一条人盯一个会话,网页视图更适合多人一起看同一条会话并进行审批交接。Step 6:把审计字段接进你自己的日志
开启 auto 之后,工具调用事件会多出两个字段,用来记录这次评估的结论:
| 字段 | 取值 | 用途 |
|---|---|---|
| evaluated_permission | allow / ask / deny | 判断本次调用是被放行、挂了人工还是被拦 |
| reason_code | high_risk(明确高危)或 indeterminate(无明确结论、升级给人) | 区分「确认有风险」和「评估器也拿不准」 |
# 采集思路(伪代码)
on tool_use_event(e):
if e.evaluated_permission == "deny":
alert("agent call denied", tool=e.name, reason=e.reason_code)
elif e.evaluated_permission == "ask":
queue_for_human(e)
# 特别关注 reason_code == "indeterminate" 的那批
# 它们代表评估器也没把握,是人工复核的重点
Step 7:上线前必须知道的四条硬约束
| 约束 | 实际影响 |
|---|---|
| 运行中的会话沿用创建时的配置 | 改策略只对新建会话生效,老会话跑完为止 |
| 被拒的调用客户端不能覆盖 | deny 就是 deny,模型只能换路 |
| 测试阶段不暴露判断理由 | 只拿到事件类型与 reason_code,拿不到解释 |
| 自定义工具不在策略范围内 | 由应用自己执行的工具,自动策略管不到 |
改策略只对新会话生效这条,最容易白忙一场。想给一批已经跑了很久的长任务智能体换策略,只改配置是不够的——需要新建智能体并迁移会话。变更计划里要把这一步算进去。
官方给的三组数字,先弄清是谁测的
介绍这项功能时经常被引用的三组数字是:人工复核在智能体运行中拦下约 13.6% 的危险命令,评估器拦下同一批命令约 89%;另有评估称在 auto 模式下 720 次提示词注入尝试无一成功;以及前面提到的约 93% 手工批准率。这些数字来自 Anthropic 自己在撰写功能文档时公布的评测,属于厂商自测口径,不是独立的第三方复现结果。
这意味着两件事。一是它们的方向可信:纯人工审批在疲劳之后拦不住东西,这是工程常识。二是不要把 89% 当成你的系统会拿到的成绩——不同工具集、不同动作空间下,评估器的表现会不一样。真正该做的是自己搭一批危险调用做对照,跑出你这一套配置下的数字,再决定自动档覆盖哪些工具。
常见问题速查
| 现象 | 常见原因 | 处理 |
|---|---|---|
| 改了策略但行为没变 | 会话沿用了创建时的配置 | 新建智能体并迁移会话 |
| 不弹出审批提示 | 没有客户端连接这条会话 | 用 sessions connect 保持连接 |
| 调用失败但看不到原因 | 被评估器拒绝,理由在测试阶段不暴露 | 看 reason_code,并回看会话前序上下文 |
| 拒绝率高得离谱 | 动作空间太大,评估器难以判断 | 先收敛工具集,再开 auto |
| MCP 调用被静默拒绝 | MCP 侧默认策略与调用方不一致 | 在 MCP 服务器侧留日志并核对工具名 |
| 自定义工具完全不受管 | 应用自行执行的工具在策略范围外 | 在应用层补自己的校验与审批 |
结语
这一档权限真正的意义,是把「谁来判断这次调用安不安全」这个问题从调用方挪到了平台侧。过去这个判断要么靠人(会被疲劳打败),要么靠一堆静态规则(会被上下文骗过)。让评估器看着工具、参数和会话历史做决定,至少在信息量上更接近真实判断所需的条件。
但它不是一劳永逸的答案。它有自己的盲区:判断理由不透明、运行中的会话改不动、自定义工具管不到、数字来自厂商自测。稳妥的用法是把它当作第二道闸而不是整套防线的全部:先把工具集收窄到真正需要的范围,在应用层保留自己的校验,再让 auto 在这套收敛过的动作空间里兜底。三道一起用,你既有自动化的吞吐,也不至于在出事时说不清发生了什么。