权限与审批

权限系统回答一个问题:这个工具调用能不能执行、还是要先问人。它由三层组成——模式(用户当前选择)、项目规则(WorkApprovalRules)、工具风险(读 / 写)。规则永远优先于模式。

五档权限模式

模式行为典型场景
plan 计划非只读工具直接拒绝(不是「问了再执行」),返回固定拒绝话术只想让模型出方案,不许动文件
readonly 只读只读工具放行,写工具直接拒绝读代码、查资料、做分析
ask 询问(默认)写操作逐个请求批准第一次在陌生仓库里动手
auto 自动常规写操作直接执行,敏感操作仍会询问信任的重复性任务
bypass 绕过全部放行,包括规则里被 deny 之外的一切一次性、隔离环境

非法值一律回落到 ask(同时兼容历史写法 read-only / read_only)。

判定顺序

  1. 模式硬约束:plan / readonly 先判,命中即结束——这两个模式不受项目规则影响。
  2. 项目规则:按工具名与路径匹配 WorkApprovalRule;deny 覆盖任何模式,allow 也会放行 ask / auto 下的调用。
  3. 模式 + 工具风险:没有命中规则时,只读工具按模式放行,写工具按模式决定「直接执行」还是「请求批准」。

项目规则模型

字段说明
ToolName工具名,支持 * 通配
PathPattern可选路径匹配;只对文件类工具生效(读写/删除/移动/打补丁五种),其他工具不参与路径匹配
Decisionallow 或 deny,其他取值创建失败
IsEnabled规则可临时停用而不删除

匹配评分:精确工具名优先于通配,带路径的规则优先于不带路径;同一工具 + 同一路径模式的重复规则会在创建时合并成一条,避免规则抖动。

运行模式对权限的影响

  • interactive:保持所选模式,逐步确认。
  • autopilot:把 ask 提升为 auto(少打断),但 plan / readonly 不会被提升——强约束不被托管执行绕过。

三条入口的差异

入口权限来源
编码会话完整三层:模式 + 项目规则 + 工具风险;会话上持久化 PermissionMode 与 AgentMode
对话页模式 + 逐工具覆盖(ToolApprovalOverrides);不读取项目规则——对话没有项目上下文
工作流节点节点配置的 toolApprovals 与运行级 toolApprovalMode 叠加,后者只覆盖未显式配置的工具

审批交互链路

  1. 判定器返回「需要批准」后,Agent 循环发出 approval_request 事件(含工具名与参数)。
  2. 前端渲染成审批卡片:批准 / 拒绝,可附带理由。
  3. 批准则执行该次调用并把结果回填;拒绝则把拒绝原因作为工具结果返回给模型,让它换方案。
  4. 与 question 事件的区别:approval_request 是「要不要执行这个工具」,question 是「向用户追问信息」,两者都有自己的 id,不能混用。

安全建议

  • 在陌生仓库先跑 ask,确认工具面符合预期后再切 auto。
  • 把「永不希望自动执行」的工具(例如删除文件、推送代码)写成 deny 规则,这样连 auto / bypass 都不会绕过。
  • 用路径规则限定作用范围:例如允许写 docs/**,其余仍走确认。
  • MCP 工具与内置工具共用这套判定;接新服务器先用 ask 跑一遍,确认它到底会调用什么。

观测与排查

  • 规则接口返回 WorkApprovalRuleDto;非法 decision 报 approvalRule.invalidDecision,规则不存在报 approvalRule.notFound。
  • 被拒绝的工具调用会在消息流里显示为工具结果(含拒绝原因),便于解释「为什么模型没做那件事」。
  • 怀疑权限覆盖顺序时,先确认是否命中项目规则(规则优先于模式),再确认运行模式是否把 ask 提升成了 auto。