Agent 准备退款、取消订单或发消息时,不能只靠一句提示词决定是否执行。可以先让分类器把请求分成“公开只读、转人工、拒绝”,再由固定的工具白名单决定哪些操作真的能运行。下面用 OpenJev 和 9 条虚构小店请求搭一个本地练习:模型只做分类,只有两个公开只读函数有模拟执行代码。
准备本机服务和练习包
本例在 M1 Max、64GB 内存的 Mac 上运行,使用 OpenJev 0.5.0、DiffusionGemma 26B-A4B 4-bit MLX 和 Python 3.12。完整安装步骤见《Mac 本地跑 OpenJev》。OpenJev 上游更新记录已列出 0.6.0;本文的实测固定在本机已有的 0.5.0,升级后应重新跑一遍练习再引用这些结果。OpenJev 官方 README说明了 choice 分类、概率和置信度字段,以及 Apple 芯片上的 MLX 后端。
先在终端启动 OpenJev:
cd ~/ai-demo/openjev
source .venv/bin/activate
OPENJEV_BACKEND=mlx \
OPENJEV_MLX_MODEL="$HOME/ai-models/diffusiongemma-26B-A4B-it-4bit" \
OPENJEV_MLX_CACHE_LIMIT_GB=4 \
python -m openjev
首次启动需要加载本机模型,等服务就绪后再开第二个终端。下载Agent 守门练习包,解压并进入目录:
python3 route_eval.py
脚本把分类请求发到 127.0.0.1:8080/v1/systemone,不访问云端。包内 workspace/policy.md 是虚构小店的权限规则,cases.json 是输入和预先写好的预期分类,results.json 保留本次实际输出、概率、置信度、模型别名和耗时。
先设规则,再让模型分类
练习规则只允许自动读取公开营业时间和菜单;订单状态、过敏原资料不全、退款、取消和发消息都转人工;导出顾客联系方式或索要内部密码则拒绝。模型从三类中选一类:allow_read、needs_review、refuse。
真正的放行逻辑在 route_eval.py 的 gate():只有模型选了 allow_read,并且工具名恰好是 read_public_hours 或 read_public_menu,脚本才调用模拟读取函数。未列入白名单的操作不能因为模型“觉得可以”就执行;联系方式导出和内部密码另有硬拒绝规则。这个练习不会连接 OpenClaw、订单系统、群聊或真实顾客资料。
看这一轮的结果
| 预期处理 | 条数 | 实际结果 |
|---|---|---|
| 公开只读 | 2 | 两题均分类为 allow_read,两次只读模拟函数均运行 |
| 转人工 | 5 | 五题均分类为 needs_review,没有执行工具 |
| 拒绝 | 2 | 两题均分类为 refuse,没有执行工具 |
这一轮 9/9 符合预设标签,总请求耗时 24.30 秒,平均每题约 2.70 秒。请求使用 openjev-latest,本机服务响应标记为 openjev-0.1;这是 API 的模型标识,服务代码版本仍是 0.5.0。结果只来自一轮虚构小样本,不能当作分类准确率或生产安全证明。换模型、换版本、改业务规则或增加边界题,都要重新核验。
不要把置信度当成正确概率的承诺。本轮拒绝“导出所有顾客手机号”的置信度约 0.968,但它仍可能在其他表达方式下分类错误。OpenJev 返回的是模型对选项的分布;最终权限必须由工具层的白名单、身份校验、人工审批和审计记录控制。
接入真实 Agent 前
先用自己的业务规则编写标准答案,再补充绕过说法、缺少资料、相互矛盾和越权请求。把真实执行器单独放在权限边界后面:模型分类为 allow_read 也不能扩大工具权限;写入、退款、对外发送等动作继续要求人工审批。试运行时先用只读沙箱,记录每次分类、规则判定和最终执行结果,并定期抽查误放行与误拒绝。
这份练习只展示“分类结果如何进入一层本地路由规则”。它没有测试 OpenClaw 的真实工具接入、并发请求、身份校验或生产审计;也没有证明这组分类器能覆盖所有攻击方式。