工具防护
AI Agent 工具调用防护:用 Jev 辅助审批与风险检查
Jev AI 独立教程 · 内容核对于 · Read in English
Agent 提议的工具调用即使格式正确,也可能不适合执行。Jev 可以辅助检查目的、副作用和证据,然后由应用决定下一步。本篇用退款操作说明语义审查如何配合常规权限检查。
tool-guard 是 Jev AI 基于原生 Choice 与 Score 编写的适配预设,不是 OmniaKey 的另一个专用防护接口。它不会执行、授权或撤销任何工具操作。
读完你能做什么
- 发送待审查的操作与证据,而不是要求模型执行工具。
- 分别读取 action 和 risk,低风险分数不能授予权限。
- 精确审批规则由代码执行,落地操作前再次检查。
在模型审查前后保留确定性检查
退款示例中,代码负责确认身份、账户权限、真实金额和有效审批。超过 500 美元需要人工批准是精确规则,即使 Jev 以很高的置信度返回 allow,也不能跳过。
语义审查适合补充硬规则无法充分表达的背景,例如操作是否符合用户原意、证据是否缺失、副作用是否值得复核。模型失败时应暂停或走明确的回退流程,而不是绕过检查。
| 阶段 | 负责的事情 |
|---|---|
| 审查之前 | 验证操作者身份和工具参数 |
| Jev 评估 | 针对所给背景回答有限问题 |
| 执行之前 | 复核权限、审批和未发生变化的参数 |
| 执行之后 | 检查实际效果,保留适当证据 |
构造完整但精简的操作说明
预设接收 tool、action、arguments_summary、side_effects、safeguards、policy 和 reversibility。应写入会影响判断的事实:680 美元退款、重复扣款已核实、500 美元审批阈值。无关的长对话容易掩盖这些核心条件。
文字写着经理已批准,不等于存在真实审批记录。实际系统应自行查询可信记录,提供相关状态,并区分用户提交的非可信文本、正式政策和已核实事实。减少不必要的客户信息,也有利于人工检查输入。
- 工具会改变什么,改变是否可逆?
- 哪条用户请求与授权支持这次具体操作?
- 哪些证据已验证、哪些缺失、哪些只是声称?
区分允许、确认、复核与拒绝
allow 表示模型认为当前描述下的操作有依据且符合政策;confirm 表示意图或细节需确认;review 表示需要政策审批或人工复核;deny 表示在现有约束下不应继续。
这些标签应映射到明确的工作流状态。请求者确认不等于具有权限的审批者批准。对于示例金额,应用始终要验证真实审批记录;模型若给出不同结论,应保留规则并检查输入或判断标准。
说明性示例,非实时 API 结果
// 应用逻辑演示:这些变量必须来自可信系统。
const needsApproval = amountUsd > 500;
const policyAllows = !needsApproval || hasValidApproval;
const canExecute = actorIsAuthorized && policyAllows &&
result.answers.action.choice === "allow";
// 还需应用已评估的不确定性策略,并复核当前工具参数。
// 所有必要检查通过后,才由应用执行。测试绕过审查的尝试
加入忽略政策、伪造经理批准、描述无害却省略金额等对抗案例。可信审批记录与自然语言说明应分别测试。没有经过对应威胁测试,就不能把模型防护描述为已经具备抗攻击能力。
也要测试常见竞态:一个金额的审批不能覆盖之后修改的金额。将审批绑定到具体操作,在执行前再次验证;工具支持时使用幂等机制。Jev 的答案无法自动解决状态过期或重复副作用。
完整请求与运行方法
在 OmniaKey 创建 API Key,并在终端或服务器环境中设置 OMNIAKEY_API_KEY。下面的 curl 示例需要支持 --fail-with-body 的 curl(7.76 或更新),JavaScript 示例需要 Node.js 20 或更新。请使用测试数据;调用使用自己的账户额度,当前价格与可用性以 OmniaKey 为准。
将 JavaScript 保存为 jev-example.mjs 后运行 node jev-example.mjs。不要把密钥写进前端代码或提交到 Git。示例保留英文输入以便与调试预设对照;中文业务数据需单独验证效果。
curl
curl --fail-with-body --max-time 25 'https://api.omniakey.com/v1/alpha/search' \
-H "Authorization: Bearer ${OMNIAKEY_API_KEY}" \
-H 'Content-Type: application/json' \
--data '{
"model": "jev-latest",
"state": {
"tool": "issue_customer_refund",
"action": "Refund USD 680 after a disputed duplicate charge",
"arguments_summary": [
"order_id=ord_7429",
"amount_usd=680"
],
"side_effects": [
"Moves funds",
"Changes the order payment state"
],
"safeguards": [
"Customer identity and duplicate charge verified"
],
"policy": [
"Refunds above USD 500 require human approval"
],
"reversibility": "partially_reversible"
},
"questions": {
"action": {
"type": "choice",
"instructions": "Evaluate the proposed tool call using policy, side effects, safeguards, authorization, and reversibility. Treat policy thresholds and missing approvals as constraints. This evaluation does not grant permission to execute anything.",
"criteria": {
"allow": "The action is authorized, within policy, and supported by adequate safeguards.",
"confirm": "Ask the user to confirm intent or missing details before proceeding.",
"review": "A policy approval or human review is required before this action can proceed.",
"deny": "The action violates policy, lacks required authority, or must not proceed."
}
},
"risk": {
"type": "score",
"instructions": "Rate the financial, operational, and policy risk of the proposed action.",
"criteria": [
"Low: routine and within policy.",
"Moderate: limited, reversible effects.",
"High: material effects or approval requirements.",
"Critical: unsafe, unauthorized, or irreversible effects."
]
}
}
}'展开 Node.js 完整示例
Node.js 20+
// Node.js 20+. Save as jev-example.mjs and run: node jev-example.mjs
// Set OMNIAKEY_API_KEY in the server/terminal environment first.
const key = process.env.OMNIAKEY_API_KEY;
if (!key) throw new Error("Set OMNIAKEY_API_KEY before running.");
const body = {
"model": "jev-latest",
"state": {
"tool": "issue_customer_refund",
"action": "Refund USD 680 after a disputed duplicate charge",
"arguments_summary": [
"order_id=ord_7429",
"amount_usd=680"
],
"side_effects": [
"Moves funds",
"Changes the order payment state"
],
"safeguards": [
"Customer identity and duplicate charge verified"
],
"policy": [
"Refunds above USD 500 require human approval"
],
"reversibility": "partially_reversible"
},
"questions": {
"action": {
"type": "choice",
"instructions": "Evaluate the proposed tool call using policy, side effects, safeguards, authorization, and reversibility. Treat policy thresholds and missing approvals as constraints. This evaluation does not grant permission to execute anything.",
"criteria": {
"allow": "The action is authorized, within policy, and supported by adequate safeguards.",
"confirm": "Ask the user to confirm intent or missing details before proceeding.",
"review": "A policy approval or human review is required before this action can proceed.",
"deny": "The action violates policy, lacks required authority, or must not proceed."
}
},
"risk": {
"type": "score",
"instructions": "Rate the financial, operational, and policy risk of the proposed action.",
"criteria": [
"Low: routine and within policy.",
"Moderate: limited, reversible effects.",
"High: material effects or approval requirements.",
"Critical: unsafe, unauthorized, or irreversible effects."
]
}
}
};
const response = await fetch("https://api.omniakey.com/v1/alpha/search", {
method: "POST",
headers: {
Authorization: `Bearer ${key}`,
"Content-Type": "application/json",
},
body: JSON.stringify(body),
signal: AbortSignal.timeout(25_000),
});
if (!response.ok) {
const retryAfter = response.headers.get("retry-after");
throw new Error(`Jev HTTP ${response.status}; Retry-After: ${retryAfter ?? "not supplied"}`);
}
const result = await response.json();
console.log(JSON.stringify(result, null, 2));
// Inspect and validate the answer before connecting it to any external action.
下方是发送给 API 的原生 JSON。教程的调试入口会选中对应预设;预设输入与此原生请求不是同一个结构。使用自定义 Jev 时,直接粘贴下方 JSON。
复制原生 JSON 到调试台
Native JSON
{
"model": "jev-latest",
"state": {
"tool": "issue_customer_refund",
"action": "Refund USD 680 after a disputed duplicate charge",
"arguments_summary": [
"order_id=ord_7429",
"amount_usd=680"
],
"side_effects": [
"Moves funds",
"Changes the order payment state"
],
"safeguards": [
"Customer identity and duplicate charge verified"
],
"policy": [
"Refunds above USD 500 require human approval"
],
"reversibility": "partially_reversible"
},
"questions": {
"action": {
"type": "choice",
"instructions": "Evaluate the proposed tool call using policy, side effects, safeguards, authorization, and reversibility. Treat policy thresholds and missing approvals as constraints. This evaluation does not grant permission to execute anything.",
"criteria": {
"allow": "The action is authorized, within policy, and supported by adequate safeguards.",
"confirm": "Ask the user to confirm intent or missing details before proceeding.",
"review": "A policy approval or human review is required before this action can proceed.",
"deny": "The action violates policy, lacks required authority, or must not proceed."
}
},
"risk": {
"type": "score",
"instructions": "Rate the financial, operational, and policy risk of the proposed action.",
"criteria": [
"Low: routine and within policy.",
"Moderate: limited, reversible effects.",
"High: material effects or approval requirements.",
"Critical: unsafe, unauthorized, or irreversible effects."
]
}
}
}如何解读结果
原生请求将 action 定义为 Choice,risk 定义为四级 Score。对于合成的 680 美元操作,review 是可以拿来验证的政策预期,不是本页宣称得到的实测结果。精确审批检查独立于这两个答案。
风险评分可以含小数,应结合分布与量表理解。不要未经评估,就把 action 的 confidence 与 risk 平均成另一个审批分数。
请求失败时怎么办
- 请求格式错误(如 400)
- 核对 model、state、questions,以及各题目的 type、选项或范围。不要把 chat messages 结构发到此端点。
- 鉴权或账户拒绝(如 401、402、403)
- 核对 API Key、账户余额、模型访问权限与当前服务商政策。状态码本身不能唯一确定原因;在 OmniaKey 后台检查,避免把密钥贴进反馈。
- 限流(429)
- 读取 Retry-After(如有),降低并发并采用有上限的退避。示例不自动重试,重复请求可能额外计费。
- 5xx、网络错误或超时
- 检查服务状态和连接,再决定是否重试。本例 25 秒超时仅中止客户端等待,不保证上游停止处理或免计费。
- HTTP 成功但结果无法使用
- 检查响应结构、问题名与题目类型。缺少答案或未知选项应进入回退或人工检查,不要强制转换后直接执行。
接入前的验证
- 已授权、重复扣款已核实的 100 美元退款。
- 没有可信审批的 680 美元退款,即使文字声称已获批。
- 审批后金额或收款人发生变化。
- 客户文本中夹带绕过政策的提示注入。
- Agent 等待执行时发生接口超时或响应格式错误。
常见问题
这可以替代权限系统吗?
不能。身份、授权、审批记录和硬性政策边界应由可信代码控制。Jev 为这些控制补充语义审查信号。
返回 allow 就能自动执行吗?
仅靠 allow 不够。硬性检查、经过评估的不确定性策略和最新状态校验都必须通过。本站调试台从不执行提议的工具操作。
依据与后续阅读
协议说明依据 OmniaKey 的 Jev 接入指南与鉴权文档核对。请求示例经过本地结构校验;本文不声称对每种业务场景完成了线上效果评测。本站不是模型开发者或 OmniaKey 官方网站。
用自己的任务试一次
先用测试输入查看原生请求与模型答案。有账户即可进入 OmniaKey 密钥管理;尚未注册时,按 OmniaKey 页面提示创建账户。