Skip to main content

概述

Permission system(io.agentscope.core.permission)拦截 agent 的每一次工具调用,给出三种决策之一:允许(ALLOW) 执行、拒绝(DENY) 执行,或者询问用户(ASK) 确认。 它把静态配置与动态运行时分析组合起来。三个组件共同决定结果:
  • Rules —— 针对每个 tool 与命令的显式 allow / deny / ask 模式,最高优先级。规则有两种来源:在 PermissionContextState 中静态预配置,或在 ASK 提示中由用户接受建议规则而动态加入。建议规则由本次工具调用自动生成 —— 一旦接受,将来相同的调用便会被自动处理,不再询问。
  • Mode —— 配置阶段设定的全局静态策略;决定所有不命中任何规则的调用的默认行为(例如 EXPLORE 让 agent 进入只读;DONT_ASK 静默拒绝未命中的调用)。
  • Built-in Checks —— 由 tool 自身在运行时基于真实输入做的动态分析(在 ToolBase#checkPermissions 中实现)。这些是运行时检查而非预配置模式,因此不可绕过,不受 mode 或 rules 覆盖。
Deny 规则与危险路径检查是不可绕过的 —— 即使在 BYPASS 模式下也照常生效。

Permission Mode

PermissionMode 枚举(io.agentscope.core.permission.PermissionMode)支持以下模式,分别适配不同的部署场景: 可以在创建 agent 时通过 permissionContext(...) 设置 mode:

Permission Rule

PermissionRule(record)把某个 tool 与具体的调用模式映射到三种行为之一:ALLOWDENYASK 每条规则由下述字段组成。当权限引擎评估一条规则时,它会用 ruleContent 与实际调用入参调用该 tool 的 matchRule() 方法,判断规则是否命中。
  • toolName · String · required — 规则适用的 tool 名:内置 todo_write,或任意自定义 tool 名。
  • ruleContent · String | null · optional — 匹配模式 —— 语义随 toolName 变化,由该 tool 的 matchRule() 方法解释。null 表示对该 tool 的所有调用均匹配。
  • behavior · PermissionBehavior · requiredALLOWDENYASKPASSTHROUGH
  • source · String · required — 规则来源:"userSettings""projectSettings""session""suggested" 等。

配置规则

初始化时 —— 通过 PermissionContextState.builder() 把规则传入:
运行时通过建议规则 —— 当权限系统返回 ASK 时,会基于本次调用自动生成建议规则。把已接受的规则附在 ConfirmResult.acceptedRules 中回传,agent 会自动写入引擎:
完整可运行示例:agentscope-examples/documentation/.../tool/PermissionContextExample.javahitl/PermissionHITLExample.java

Built-in Checks

每个 tool 都实现了一个 checkPermissions(toolInput, context) 方法(位于 ToolBase),在运行时基于真实调用入参执行检查,返回 Mono<PermissionDecision>。这些检查不可绕过 —— 无论 mode 或 rules 是什么,它们都生效。 PermissionDecision 提供四个静态构造方法:allow(message) / deny(message) / ask(message) / passthrough(message)。返回 PASSTHROUGH 表示「我不强加判断,交给引擎按 rules / mode 评估」。 自定义 tool 可以重写 checkPermissions() 实现自己的检查逻辑:

危险路径保护

ToolBase 内置的危险路径列表通过 ToolDangerousPathConstants 维护,自定义 tool 可以在 @Tool 注解上追加 dangerousFiles / dangerousDirectories 把额外路径并入受保护集合。命中后即使在 BYPASS 模式下也会强制 ASK。

结合 HITL

当权限引擎对某个工具调用返回 ASK 决策时,agent 不会直接执行,而是暂停并返回一个 GenerateReason.PERMISSION_ASKING 的响应。返回的 Msg 中包含处于 ASKING 状态的 ToolUseBlock,调用方据此向用户展示待确认的操作,收集决策后通过 ConfirmResult 恢复 agent。

交互流程

  1. 配置 ASK 规则,标记需要人工确认的工具
  2. Agent 遇到 ASK 工具时暂停,返回 PERMISSION_ASKING
  3. 从返回的 Msg 中提取 ToolUseBlock(状态为 ASKING),向用户展示
  4. 构建 ConfirmResult,附在新消息的 metadata 中恢复 agent

全部工具被拒绝

当用户在确认界面拒绝了本轮推理产出的全部工具调用时,agent 默认会继续下一轮推理 —— 此时模型只能看到 “Permission denied by user” 的工具结果,容易产生无效推理。 如果需要在这种场景下停止 agent,可以装备一个 onActing middleware 观察 AllToolsDeniedEvent 并发出 RequestStopEvent。停止后 Msg.getGenerateReason() 返回 ALL_TOOLS_DENIED 具体实现参见 Middleware — 全部工具被拒绝时停止 agent

Streaming 模式

使用 streamEvents() 时,不需要从返回的 Msg 提取 ToolUseBlock —— 通过事件流直接获得 RequireUserConfirmEvent,它携带了待确认的工具调用列表:
如果使用 streamEvents(List.of(resumeMsg)) 发起恢复,事件流会在恢复执行工具之前包含 UserConfirmResultEvent。使用它的 replyId 将本次接受的确认结果关联到之前的 RequireUserConfirmEvent;该事件只包含本次恢复消息携带的确认结果。 两种模式的区别:

无人值守模式

在 CI 或定时任务等无人值守场景下,把 mode 设为 DONT_ASK,所有 ASK 决策会自动降级为 DENY:
完整可运行示例:agentscope-examples/documentation/.../hitl/PermissionHITLExample.java

常见配方

下面的示例展示了如何为常见部署场景配置 permissionContext。每个配方把一种 mode 与一组规则结合,匹配特定的使用场景。