Agent 的策略即代码 (Policy-as-Code):OPA、Rego 以及你的工具循环中缺少的决策点
当监管机构第一次要求你证明你的支持代理在 3 月 14 日没有访问某位二级客户的账单记录时,你会发现关于你的鉴权架构的一个令人不悦的事实:系统提示词说“不要访问二级客户的账单”,YAML 工具清单说 tools: [search_orders, refund_order, get_billing],而在两者之间,模型做出了决定。由于不存在决策点,因此没有决策记录。代理是否做了正确的事是无法审计的,只能从发生的日志中推断。
这是智能体工程中没人画在架构图上的部分。如今的工具权限仍然存在于由创建智能体的人编辑的 YAML 文件中,通过描述意图的系统提示词呈现给模型,并由包裹每个工具调用的应用代码强制执行(如果真的执行了的话),例如 if user.tier == "premium" 检查。随着工具目录超过 50 个条目,且条件在租户、数据类别和用户角色之间成倍增加,这种手动构建的网格便不再具备扩展性,而系统提示词也不再是一个可靠的执行面。模型不是你的鉴权层,即使它的表现看起来像是一个鉴权层。
取而代之的是策略即代码(policy-as-code):一个专门的策略引擎 —— OPA 配合 Rego、AWS Cedar 或类似的声明式工具 —— 作为策略决策点(Policy Decision Point)位于每个工具调用之前。引擎在每次调用时只回答一个问题:给定这个主体(principal)、这个工具、这些参数和这个上下文,该操作是否被允许?智能体运行时(agent runtime)从未参与投票。这篇文章将探讨这种架构在实践中的样子,以及它所解决的四个即使是提示词工程也无法解决的问题。
提示词从未是鉴权层
将系统提示词视为策略表达极具诱惑力,因为它感觉是声明式的 —— 你写下规则,模型遵循规则,故事结束。失败模式在于提示词是被“解释”的,而不是被“强制执行”的。一个足够棘手的输入、一个微妙地暗示能力的工具描述,或者一个与规则冲突的目标,模型做出的“判断”就会产生策略违规,而这在对话记录中看起来与合法操作完全一样。2026 年的 OWASP 智能体应用前十榜单(OWASP Top 10 for Agentic Applications)将此称为“最小代理权(Least Agency)”失效:问题不再仅仅是智能体可以访问什么,而是它在没有检查点的情况下拥有多少自由度来对该访问权限采取行动。
YAML 清单也好不到哪去。在需要条件判断之前,它们还能扩展。一旦“这个智能体可以调用 refund_order”变成了“如果订单属于该主体的租户、订单时间小于 30 天、金额低于 500 美元且主体拥有 refunds:write 权限,则该智能体可以调用 refund_order”,YAML 的表达能力就不再足够,你开始在工具包装器中散布各种检查。六个月后,一项新的合规要求降临,而你无法找到所有需要更改规则的地方。
策略决策点(PDP)模式在 XACML 和云 IAM 中广为人知,它将这种逻辑外部化。应用代码变成了策略执行点(Policy Enforcement Point,PEP):它获取输入,询问 PDP,并根据答案采取行动。策略本身存储在单独的文件中,受版本控制,由安全团队审查,并可作为单元测试运行。智能体运行时像调用其他任何服务一样调用 PEP。模型在循环中没有发言权,因为根本没有询问模型。
OPA,Rego 以及 Cedar:引擎的选择
三种策略引擎出现在了智能体运行时的讨论中,它们之间的差异正变得越来越重要。
Open Policy Agent (OPA) 是 CNCF 毕业的通用引擎,使用 Rego 作为其策略语言。Rego 是声明式的,支持丰富的数据连接(你可以基于整个请求上下文以及通过 OPAL 加载的外部数据进行推理),并拥有成熟的生态系统 —— Sidecar、Wasm 包、语言 SDK。代价是 Rego 的学习曲线:它更接近 Datalog 而非 YAML,用英文表达起来很简单的策略可能需要一整个 Session 才能表达清楚。对于智能体运行时,前置于工具网关的 OPA-as-sidecar 是最常被提及的模式:网关在调用工具前调用 OPA,而 OPA 在不到一毫秒的时间内给出答复。
AWS Cedar 是较新的参与者,是一种专门为鉴权策略设计的开源语言,具有刻意受限的语法。Cedar 的设计选择 —— 默认拒绝、禁止胜于允许、 与顺序无关的评估、无副作用 —— 使策略在组合时更容易推理。AWS 在 2026 年 3 月将 Cedar 作为 Amazon Bedrock AgentCore Policy 内置的策略引擎发布,它在网关边界拦截每一个智能体工具调用,并针对一组策略集进行授权。这些策略可以直接用 Cedar 编写,也可以从自然语言陈述中生成并形式化为 Cedar。自然语言路径很有趣,因为它承认编写策略才是最难的部分,而不是运行策略。
Cerbos 及类似的 PDP 服务 是为不想学习新语言的团队提供的 YAML 策略替代方案。策略定义在 YAML 中,评估时间在亚毫秒级,集成方式是 HTTP。权衡之处在于表达能力:需要连接外部数据的复杂策略在 Rego 中比在 Cerbos 模型中更容易实现。
对于大多数智能体运行时来说,引擎本身并不如架构上的承诺重要:每一次工具调用在执行前都必须获得 PDP 的决策。像对待数据库一样对待 PDP —— 选择一个,将其作为基础设施运行,赋予其明确的契约,停止在 TypeScript 中手动编写等效代码。
能力令牌取代 YAML 授权
即使部署了 PDP, “该智能体当前拥有什么权限” 这个问题仍需要一种表达方式。目前已趋于稳定的模式——且 IETF 关于智能体交易令牌(Transaction Tokens for Agents)的草案正在将其正式化——是使用短效的能力令牌(capability tokens)。这些令牌是通过 OAuth 2.0 令牌交换 (RFC 8693),从较长效的用户会话中根据具体任务派生出来的。
其结构如下:用户登录并获得一个生存时间(TTL)为数小时的会话令牌。当该用户启动一 个智能体任务时,智能体运行时会将该会话令牌交换为一个能力令牌,其作用域被严格限制在该任务中——特定的工具、特定的资源范围、特定的租户——且 TTL 以分钟计,并明确规定不可刷新。如果智能体在任务中途需要新的能力,它会请求授权服务器,而不是去查 YAML 文件。
两个结构性细节保证了这一机制的运作。
交易令牌(Transaction Token)草案将 “委托人(principal)”(发起任务的人或上游系统)与 “执行者(actor)”(当前执行动作的智能体)区分开来。每一个策略决策都可以针对两者同时做出:“该 智能体 可以调用此工具,但前提是 委托人 拥有对该数据的底层访问权。” 混淆代理(Confused-deputy)攻击——即智能体被提示词注入,从而代表第三方使用其自身权限——变得难以实现,因为策略可以要求委托人与执行者达成一致。
第二个细节是能力令牌的作用域只能缩小,不能扩大。当智能体 A 产生智能体 B 时,A 传递给 B 的令牌是由授权服务器从 A 的令牌中派生出来的,其范围等于或窄于 A。父级智能体不能授予子级智能体它们自己不具备的能力;授权服务器在交换时强制执行这一点,而不是在应用逻辑中执行,这是随着代码库演进仍能保持正确性的唯一方法。
结果是,“这个智能体现在能做什么”不再是一个通过阅读 YAML 文件来回答的问题。它由当前的能力令牌决定,且该令牌的过期速度通常比大多数智能体引发的事故发生的速度还要快。
