生产级 LLM Agent 的工具调用必须经过服务端网关鉴权,建议用短生命周期 intent 证书和确定性检查而非事后日志。
随着 LLM Agent 从实验走向生产,一个残酷的教训逐渐清晰:模型可以提出行动方案,但必须不允许其在未事先证明已获得授权的情况下执行敏感工具调用。"LLM Agent 工具授权"是一门与 Prompt 对齐完全不同的学科——它将 Agent 访问视为一个授权工程问题,需要确定性检查、短时生效的能力以及可审计的决策。
本文扩展了一个实用的、可投入生产的 5 步检查清单,并展示了可立即应用的具体模式,以在未经授权或被污染的工具调用执行前将其阻断。
事后检测(记录后追责)对高影响操作来说为时已晚:金融转账、密钥访问、对外服务出口或破坏性操作。攻击者(或被 Prompt 污染的链路)可以构造对模型看起来无害、或能绕过防护栏的提案——除非你在每次执行前都要求凭据和意图证明。
将每一次工具调用视为"不可信输入",必须由服务端网关进行完全中介。
颁发描述任务的短时、服务端签名的意图证书,包含结构化声明:允许的工具、资源、参数边界、任务 ID、过期时间和来源。参考 IGAC 风格的意图证书或 IBAC/授权 Agent 模式。
证书必须是窄界的,不能扩展作用域。它作为一份契约:Agent 只能在证书所规定的子集范围内请求工具调用。
使用绑定发送方的证明(DPoP 风格或 mTLS),而非长期有效的持有者 API 密钥。将令牌绑定到:调用方密钥、受众、HTTP 方法/URI、nonce/jti 和短 TTL。
这可以防止跨 Agent 的重放或令牌盗用,并确保是原始主体在发起调用。
对每次调用运行确定性策略决策。将 PDP(Open Policy Agent、OpenFGA 或轻量级进程内求值器)协同部署或嵌入,以保持低延迟。
使用单调约束:收窄权限的策略更新应自动应用;权限扩展必须要求人工审批和显式版本化 rollout。
为每个提案和决策发出只追加、防篡改的事件。包含:意图 ID、令牌密钥 ID、主体、规范化的参数哈希、策略版本、决策,以及适用时的审批 ID。
同时记录被拒绝的提案——它们对调优规则和事件分诊极其有价值。
对于不可逆或敏感的影响(付款、密钥生成、生产变更),需要绑定到精确请求哈希和作用域的显式人工审批。
审批必须是单次使用的,绑定到工具、参数、主体和过期时间。永远不要让人工审批变成一张空白支票。
对于不可逆或敏感的效果(付款、密钥、生产变更),要求与精确请求哈希和作用域绑定的显式人工批准。
批准必须是一次性的,绑定到工具、参数、主体和过期时间。永远不要让人类批准成为一张空白权限。
Agent 提议调用 send_payment_tool 处理发票 1234。强制执行以下流程:
Agent 必须呈现一个作用域为 pay-invoice:1234 的意图证书。
验证令牌证明:绑定发送方、未过期、 audience 正确。
策略引擎评估风险规则:能力与意图和静态允许列表相交,参数边界检查和配额检查。
发出审计事件。如果安全则执行;否则打开人工审批或拒绝。
Mini decision snippet(伪代码):
if intent_cert.valid and token.sender_bound and policy.allows(intent_cert.scope):
allow()
else:
deny_and_audit()
关键实用模式:
完全中介:模型从不直接调用执行端点。所有提案都经过一个网关,该网关验证 schema、令牌证明、意图证书和策略。
单调委托:当 Agent 委托给子 Agent 时,将父级和请求作用域的交集作为子能力派生——绝不扩大权限。
快速拒绝路径:实现一个廉价的 allow/deny 层(对未知或过期能力直接 deny),将复杂分类保留给异步求值。
TypeScript 示例:一个最小化执行包装器:
type Capability = {
taskId: string;
principal: string;
tool: string;
action: string;
resource: string;
argsHash: string;
exp: number;
aud: string;
};
async function callTool(proposal, cap: Capability, ctx) {
// expiry, tool and resource equality checks
if (Date.now() / 1000 >= cap.exp || proposal.tool !== cap.tool || proposal.resource !== cap.resource) {
throw new Error('deny');
}
// args hash and audience binding
if (sha256(canonical(proposal.args)) !== cap.argsHash || cap.aud !== ctx.audience) {
throw new Error('deny');
}
// deterministic policy check
const decision = await policy.check({
principal: ctx.principal,
tool: proposal.tool,
action: proposal.action,
resource: proposal.resource,
task: cap.taskId,
approval: ctx.approval
});
// audit the attempt and policy version
await audit({ proposal, cap, decision, policyVersion: policy.version });
if (!decision.allow) throw new Error('deny');
return execute(proposal);
}
生产环境中还需添加:schema 验证、重放 nonce 检查、DPoP 或 mTLS 证明验证、配额以及出口约束。
对于交互式 Agent,目标是在 p95 时延下单数字或亚 10ms 的策略决策。策略:将最小化的 PDP 与缓存的策略包协同部署。在进程内维护一个小型确定性拒绝列表,用于已知危险工具。使用 OpenFGA 或 Zanzibar 风格的关系检查来处理资源关系,将重量级 join 保留给离线审计。
协同部署一个最小化的 PDP 与缓存的策略包。
在进程内维护一个小型确定性拒绝列表,用于已知危险工具。
使用 OpenFGA 或 Zanzibar 风格的关系检查来处理资源关系,将重量级 join 保留给离线审计。
对策略进行版本化管理,并实现缓存失效机制以支持紧急拒绝。
向审批者展示:精确的工具、规范化的参数值、资源标识符、效果摘要,以及到审计事件的直接(哈希绑定)链接。
使用绑定到请求哈希 + 主体的一次性审批令牌。在执行前重新验证,以防策略或令牌在此期间被撤销。
存储规范化的参数哈希而非原始密钥。保留策略版本、意图证书、令牌密钥 ID 和决策追踪。这允许在不暴露敏感 payload 的情况下进行快速分诊。
实现事件急停开关和紧急策略,可立即拒绝指定主体或工具。
将"LLM Agent 工具授权"视为一门学科:短时意图证书、绑定发送方的令牌、确定性策略检查、可审计的决策,以及人工门槛。这能减少由未授权或被污染工具调用导致的一类高影响事件。
如果你在生产环境部署 Agent,请在执行前设置授权边界——这是防止灾难性错误摩擦最低的方式。你会为你的组织在这份检查清单上增加哪一项检查?分享你的模式或策略。
(文章中附有可实现的参考和示例的链接。)