JevAutoModeMiddleware 在派发前判断操作是否适合当前任务。语义允许之后仍需通过 PermissionEngine;拒绝时返回与原调用配对的工具结果。
示例场景:先确认订单状态,再退款
假设你在构建一个客服 Agent,它有两个工具:query_order:查询订单和发货状态。refund:向支付系统发起退款。
refund(orderId="A1001"),跳过查询。此时工具名和参数都合法,用户也具备退款权限,但对话中还没有证据表明退款条件成立。
JEV 在这里增加一次结合上下文的判断:根据当前对话和这次工具调用的参数,这个操作是否适合自动执行? 判断未通过时,refund 不会被派发,Agent 会收到拒绝结果,可以据此补充查询或请求复核。
中间件会自动把当前会话消息、受保护工具的名称和参数交给 JEV。你不需要手工拼装判断请求,但必须让前序查询结果进入 Agent 上下文。JEV 不会自行查询订单;退款资格、金额上限和幂等仍由业务代码校验。
1. 为退款工具配置检查
先创建客户端,并把refund 加入受保护工具集合。下面使用 SHADOW 模式观察判断,暂不改变原有执行流程。
如果还要检查对外发送消息,可以改为
.guardedTools(Set.of("refund", "send_message"))。工具进入这个集合后才会接受检查;集合并不授予工具执行权限。
2. 接入你的 Harness
将guard 注册到已有 Agent。model 是生成模型,toolkit 已注册 query_order 和 refund,permissionContext 是应用现有的权限配置。
guard。正常的 Harness 调用链负责提供会话状态。
对于“查订单后退款”的请求,query_order 不在受保护集合中,可以沿原权限链执行;随后提出的 refund 才会接受 JEV 检查。这样,JEV 可以结合查询结果和用户的条件性要求判断退款操作。
3. 从观察切换到实际拦截
SHADOW 用来查看判断是否符合你的业务预期,不会阻止退款。如果希望真正拦截,需要在构造options 时将模式改为 JevExecution.Mode.ENFORCE,并用新的配置重新构建中间件和 Agent。
以阈值 0.8 为例,假设两次判断分别返回以下概率:
这些概率用来说明处理方式,不代表模型一定会给出同样判断。即使 JEV 允许,业务校验仍可能拒绝退款;真正执行成功也必须以退款工具返回的业务结果为准。
如果一次提出多个工具调用,中间件分别判断受保护项。被拒绝的调用会得到与原
toolCallId 对应的工具结果,其余调用保持原顺序进入后续流程;中间件不会自动重试退款工具。
运行离线示例
JevHarnessExample使用合成判断展示 OFF、SHADOW、ENFORCE 下的行为。按案例构建步骤设置JEV_CP 后执行:
异常与人工确认
- 检查失败:ENFORCE 下,缺少会话状态、缺答案、非法概率、超时或后端失败都会拒绝受保护调用;SHADOW 保留原流程,OFF 不发起判断。取消检查后不继续派发。
- 人工已确认:已确认的 ALLOWED 调用沿用原确认链。Service 通过
JevConfirmedCalls绑定工具名和参数指纹;确认后参数变化时,ENFORCE 会以CONFIRMATION_CHANGED拒绝,必须重新确认。 - 中间件顺序:会修改工具参数的中间件应在此检查之前完成修改,避免执行的参数与检查时不同。
agentOverrides.jev.guard 装配同一能力,见Service 配置。
退款场景对比测试
2026-09-26,使用同一组 120 个合成会话快照、128 次受保护调用,对比当前中间件中的 JEV 与 Qwen 判定。保持本页阈值0.8、总预算 2 秒,每个后端运行一轮;实际返回模型为 jev-1.13.0 与 qwen3.8-max。所有退款均为本地模拟。
当前通用安全问题与阈值组合下,JEV 判断较快,但过于保守,全部正常退款也被拦截。Qwen 在有效判断中的准确率为 99.16%,另有 9 次响应未通过格式校验;失败兜底造成了上表中的 6 次正常退款受阻。两者均无超时。检查耗时不代表完整 Agent 任务耗时,这组结果也不代表真实支付成功率;启用接管前仍需按业务场景校准。
完整数据集、标注规则、运行命令、离线行为测试及 60 秒预算对照均放在
agentscope-examples/jev/benchmarks/tool-guard。可查看测试方法或下载完整用例与原始结果。