企业级智能体的权限到底怎么落地?以 BizBuddy 为例

给大模型一根「写库的手」之前,先把权限这条命门讲清楚。本文拆解一个纯 Java AI 平台的三层权限模型:工具可见面 → 三档授权 → 业务复核,外加 HITL 人工确认。

一、问题:给 AI 一根「写库的手」,你敢吗?

大多数 Agent Demo 的权限模型是「全有或全无」:要么模型能看到并调用所有工具,要么什么都调不了。放到企业里立刻出问题:

  • 普通员工让「小Z」查一下别的部门的用户信息,能查吗?
  • 模型自己决定发布一条全公司公告,发不发?
  • 一个只读的检索工具,会不会被诱导去调用删除接口?

BizBuddy 的做法是把「谁可见、能不能调、要不要人确认、执行时再校验」拆成三层,并且全程复用底座已有的组织机构与 RBAC,而不是给 AI 单独造一套权限。

二、底座:RuoYi-Vue-Plus 的组织机构与 RBAC

AI 能力要落地企业权限,前提是底座本身有一套完整的权限模型。RuoYi-Vue-Plus 提供的是国内中后台里最成熟的那一套:

概念 表 作用
用户 sys_user 账号主体
角色 sys_role 权限集合
菜单 / 按钮 sys_menu 权限标识(如 system:user:query)
部门 sys_dept 组织树,数据权限的边界
岗位 sys_post 组织内的职务
数据权限 sys_role_dept 角色 → 可访问部门
字典 sys_dict_* 枚举与配置

鉴权用 Sa-Token ,接口上用 @SaCheckPermission("system:user:query") 这类注解;数据权限用 @DataPermission 按部门/角色自动拼 SQL 条件。超级管理员有通配权限 *:*:*。

关键点:这套模型对 AI 不是「另起一套」,而是「同一套」。 AI 工具在代码侧声明它需要的权限标识,运行时用同一套 PermissionService 校验。

三、三层权限模型

flowchart TD A[&#34;智能体定义绑定工具<br/>ai_agent_tool.decision&#34;] --> M[&#34;合并决策&#34;] B[&#34;场景包内工具决策<br/>ai_scenario_pack_tool.decision&#34;] --> M C[&#34;会话资源集直接选中的工具<br/>默认:只读→允许 / 写入→需确认&#34;] --> M M -->|&#34;decision = 2 禁止&#34;| D[&#34;不注册:模型不可见&#34;] M -->|&#34;decision = 0 允许&#34;| E[&#34;注册进 Toolkit&#34;] M -->|&#34;decision = 1 需确认&#34;| E E --> F{&#34;运行期权限规则&#34;} F -->|&#34;ALLOW&#34;| G[&#34;直接执行&#34;] F -->|&#34;ASK&#34;| H[&#34;暂停 → 人工确认 → 恢复 / 拒绝&#34;] F -->|&#34;DENY&#34;| I[&#34;拒绝&#34;] G --> J[&#34;工具内部业务权限复核<br/>PermissionService&#34;] H --> J

第 1 层:工具可见面(装配期决定)

一个工具能不能被模型看见,由装配期决定,运行期无法绕过(工具的 JSON Schema 在装配时就固定了)。可见面来自三处叠加:

  1. 智能体绑定 :ai_agent_tool 里「智能体 × 工具」的绑定与决策;
  2. 会话资源集 :对话底栏 + 里选的工具 / 技能 / MCP 工具(下一轮生效);
  3. 平台内置只读工具 :get_current_time / get_current_user / get_current_dept / get_current_permissions 四个「无害只读」工具,无需绑定即可用,默认放行。

decision = 禁止 的工具根本不注册进 Toolkit------模型看不到,谈不上被诱导调用。这比「注册后运行时拒绝」安全得多。

第 2 层:三档授权(运行期规则)

对进入可见面的工具,按「智能体 × 工具」的三档决策生成权限规则(ai_agent_tool.decision):

决策 值 行为
允许 0 直接执行
需确认 1 命中即暂停,等人工确认(HITL)
禁止 2 不注册(模型不可见)

决策有多个来源,且「越显式越优先」:

复制代码
会话资源集直接选中  >  场景包内决策  >  智能体绑定决策
  • 请问------同一工具被「直接选中」时,档位取选中时的默认:只读 → 允许,写入 → 需确认;
  • 用户个人的「记住该工具」信任,按 (userId, sessionId) 槽位在每轮对话时并入,不写进共享的装配实例------避免某个用户点的「允许」让所有人都免确认。

第 3 层:业务权限复核(执行期)

即使前两层都放行,工具在执行时仍会再校验一次业务权限。以「发布系统公告」工具为例:

java 复制代码
@Override
public Mono<ToolResultBlock> callAsync(ToolCallParam param) {
    Long operatorId = resolveOperatorId(param);           // 从 RuntimeContext 取操作人
    if (operatorId == null) {
        return Mono.just(ToolResultBlock.error("无法识别当前操作人,已拒绝发布公告"));
    }
    if (!hasNoticePermission(operatorId)) {               // 复核菜单权限
        return Mono.just(ToolResultBlock.error("当前用户无「通知公告新增」权限,已拒绝发布公告"));
    }
    // ... 参数校验、落库
}

private boolean hasNoticePermission(Long operatorId) {
    Set<String> perms = permissionService.getMenuPermission(operatorId);
    return perms.contains("*:*:*") || perms.contains("system:notice:add");
}

这道复核的意义是纵深防御 :万一工具可见面或档位配置出错,工具自己也会用提问用户的实际权限兜底。写操作三档与业务权限同时满足才能落地。

四、HITL:写操作的「暂停---确认---恢复」

企业里最敏感的从来不是「读」,而是「写」。BizBuddy 的 HITL 走的是 AgentScope 框架原生机制,而不是自己发明的提示词约定:

  1. 装配期为写工具写入 ASK 规则;
  2. 模型调用该工具时,框架暂停 整个 Agent,并发出 RequireUserConfirmEvent;
  3. 前端弹出确认卡片,用户点「允许 / 拒绝」;
  4. 允许则以 ConfirmResult 恢复执行;拒绝则不执行。
java 复制代码
// 工具侧无需手写确认逻辑------权限判定沿用 ToolBase 的默认实现,
// 由框架按装配期写入的 PermissionContextState 规则判定。
public class CreateNoticeTool extends ToolBase { /* ... */ }

这套机制带来两个工程好处:

  • 确认是「链路的暂停点」而不是「工具内的 if」:会话状态被完整保存,恢复后上下文不丢;
  • 专家链路内置写工具短期去重 :一次编排里(含 HITL 等待与重试),「同工具 + 同入参」的写调用在 TTL 内只真正执行一次,避免重复发布公告这类重复副作用。

五、组织机构是怎么参与 AI 的

RBAC 不只是「有没有权限」,还包括「能看到谁的数据」。AI 侧主要在三个地方用到组织机构:

5.1 专家可见范围

ai_expert_agent.visible_scope 决定专家对谁可见:

取值 含义
0 全部用户可见
1 仅本部门(owner_dept_id)可见
2 仅创建者本人(create_by)可见

候选专家清单每轮现算 :启用 ∩ 提问用户可见 ∩ 专家角色。

5.2 配额(按提问用户)

专家可配置日 / 月 Token 配额 与请求次数配额 (daily_token_quota / daily_request_quota / monthly_token_quota)。配额按提问用户计,防止「一个账号把预算跑光」。

5.3 数据权限的「异步线程坑」

RuoYi 的 @DataPermission 依赖 Sa-Token 的线程上下文 拿当前用户。但 AgentScope 的工具运行在 Reactor 线程上,线程上下文不可用,直接调用会踩到空指针。

因此 BizBuddy 的 AI 工具遵循两条纪律:

  1. 操作人从 RuntimeContext 取 ,而不是 LoginHelper;
  2. 权限校验用不依赖线程上下文的 PermissionService ;对涉及数据权限的写操作,额外提供不挂 @DataPermission 的服务方法,并显式做归属校验。

六、审计:每次决策都可追溯

权限不是「配完就完了」,还要能复盘。平台把以下五类记录全部落库:

  • 会话与消息(ai_message);
  • 工具调用(ai_tool_call_log:工具名、入参、出参、状态、耗时);
  • 权限决策与确认;
  • 链路追踪(ai_trace:装配快照含工具清单、模型、策略);
  • 编排运行(ai_route_run:小Z 的路由决策与专家调用)。

出问题时可以精确回答:这一轮模型看到了哪些工具?调用了什么?用户确认了吗?用的是哪个模型?

七、落地清单

把上面这套压缩成一张清单,方便你对照自己的项目:

  1. 可见面用装配期裁剪,禁止的工具根本不注册,而不是运行时拦截;
  2. 三档授权(允许 / 需确认 / 禁止)比布尔开关更贴近企业语义;
  3. 决策来源要有优先级,越显式越优先,且用户级信任不能污染共享实例;
  4. 写操作默认「需确认」,并让确认成为链路的暂停-恢复点;
  5. 执行期再复核一次业务权限,纵深防御;
  6. 组织机构参与可见范围与配额,让「部门」成为真实边界;
  7. 异步线程里不要依赖线程上下文,显式传递操作人;
  8. 全链路留痕,否则排障时无从下手。

相关仓库

作者:AI架构师张磊

相关推荐
慢云智慧空间1 小时前
从智能终端到空间AI,慢云科技如何重新定义智慧建筑的核心能力?
人工智能·python·科技
栈知见1 小时前
04-让 Agent 会"用工具": Tool Calling 实战
agent
合调于形1 小时前
Jusshen zhzzneng《具身智能》词条汉语拼音字母标调拼写实测案例
人工智能·自然语言处理·人机交互·语音识别·学习方法
DP DPharness1 小时前
cc-safety-net 上手指南:从 npx install 到 doctor 自检
人工智能·dpharness
用户4270276726811 小时前
一次缓存优化:SQL 从 502 降到 5
java
youdexiang1 小时前
会议记录工具哪个好?搜索能力横评
人工智能
小师兄吃牛肉1 小时前
C语言指针进阶全解析
java·c语言·算法
倔强的石头1061 小时前
【Linux指南】动静态库系列(十一):PLT 与延迟绑定:第一次调用动态库函数时发生了什么
linux·人工智能·python
梦帮科技1 小时前
vLLM / TensorRT-LLM 极限推理:PagedAttention 细粒度物理页表管理与连续批处理(Continuous Batching)实战
数据结构·人工智能·分布式·python·深度学习·算法·vllm