返回 2026-04-13
⚙️ 工程

WorkOS FGA:面向 AI 代理的授权层[Sponsor] WorkOS FGA: The Authorization Layer for AI Agents

daringfireball.net·2026-04-13

文章探讨了企业级 AI 代理部署中的核心瓶颈并非模型质量或延迟,而是授权机制。WorkOS 提出的 FGA(Fine-Grained Authorization)方案通过资源级权限控制,精确界定 AI 代理的操作范围,从而增强企业安全性。该方案解决了身份验证(Authentication)无法限制行为边界的局限,使企业能安全信任并部署 AI 代理。作者强调,在 AI 竞争中,真正胜出的将是那些能被企业安全信赖的系统。

WorkOS

每一次重大的架构变革都会暴露我们访问控制模型的局限性。多租户 SaaS 打破了文件系统权限机制,微服务则破坏了单体应用的会话管理方式。如今,AI 智能体正在打破过去十年间标准化的授权模式。

智能体已经在企业基础设施中运行。它们总结文档、分类处理工单并管理云资源。然而,大多数智能体仍使用与人类相同的身份验证基础组件:OAuth 令牌、会话 Cookie 或服务账户密钥。它们要么继承用户的完整访问权限,要么拥有比任何单个用户都应拥有的更广泛的权限。

混淆的代理人问题

要理解这一架构风险,请考虑"混淆的代理人"问题。在安全理论中,代理人是指拥有执行权限的程序,但被低权限用户欺骗而滥用该权限。

考虑一个平台工程团队部署了"集群调试代理"来排查 Kubernetes 部署问题。该代理使用具有 secrets:read 权限的服务账户来验证配置映射。

触发条件:一位开发人员调试支付服务崩溃时需要查看生产环境变量。他们无法直接访问生产环境密钥,这些密钥仅限于 SRE 人员访问。于是他们向代理请求:"将生产环境变量与 staging 环境进行对比,让我看看有什么变化。"

执行动作:代理执行了该查询。它拥有 secrets:read 权限,因此集群控制平面允许该请求。

结果:代理将差异内容发布到了共享的 Slack 频道。


- STRIPE_SECRET_KEY: "sk_test_..."
+ STRIPE_SECRET_KEY: "sk_live_51M..."
  

一个生产环境 API 密钥实际上泄露给了五十人。

没有发生配置错误。代理在其权限范围内行动(secrets:read),开发人员在他们的权限范围内行动(chat:write)。系统失败是因为它没有检查两者权限的交集。代理充当了混淆的代理人,绕过了旨在限制开发人员的 IAM 控制措施。

这迫使每个团队回答一个具体问题:当代理代表用户行动时,应该应用谁的权限?

代理不是用户,也不是服务账户。

身份行业目前正在定义代理在 IAM 栈中的位置。

微软推出了 Entra Agent ID 作为原生身份类别。NIST 于 2026 年 2 月发布了关于代理身份的概念论文。IETF 正在标准化 SCIM 中的 /Agents 资源。

共识是代理是一个需要专门构建基础设施的独立身份类别。然而,行业关注点仍在身份验证(证明身份)上。未解决的工程挑战是授权(强制执行能力)。

意图差距

传统服务账户是确定性的。CI/CD 运行器有固定的范围来拉取代码和推送构件。你只需定义一次访问权限,且很少改变,因为运行器从不生成自己的意图。

代理在两个根本方面有所不同。

首先,它们生成意图。传统的 OAuth 客户端转发用户请求。代理会推理问题并决定调用哪些工具。

其次,它们的范围是非确定性的。你无法在设计时预测代理需要什么。一个编码代理可能今天需要 repo:backend 的读取权限,明天又需要 repo:frontend 的写入权限。

通过静态角色解决这个问题会带来二元权衡。你要么阻止代理正常运行,要么授予其广泛的 admin 权限。

The two modes of agent authorization

代理实现通常分为两种模式。每种模式都引入了特定的授权要求。

1. 代表用户(OBO)代理

这些代理充当人类用户的扩展,例如 Claude Code 或 GitHub Copilot。它们专门在用户会话中运行。

这里的安全要求是权限范围缩小(Scope Attenuation)。代理应仅访问用户权限的一个子集,而非全部权限。如果用户要求代理重构某个特定文件,它不应有权访问父目录中的敏感配置文件。

目前,大多数 OBO 代理继承用户完整的访问令牌。

MCP 的差距

模型上下文协议(MCP)正成为这些代理的标准接口。然而,它明确将授权职责委托给实现者。

MCP 当前依赖 OAuth 2.1 的范围(scopes),如 files:read。这些范围是粗粒度的字符串。files:read 授予用户对用户可见的所有文件的访问权限,从 README 到生产环境的 .env 文件。规范建议“范围指导”,但将细粒度执行留给应用逻辑处理。

即使协议采用富授权请求(Rich Authorization Requests,RFC 9396)来支持结构化意图,如 {"file": "main.rs"},这也仍是一种数据格式。它作为请求的外包装,但不提供评估该请求是否应被允许的逻辑。

共享上下文陷阱

在共享上下文中,权限范围缩小会失效。

考虑一个“财务助理”代理被添加到团队 Slack 频道。该代理使用 CFO 的身份验证凭据登录。一位初级分析师询问第三季度预算预测。

代理检查自身权限,确认 CFO 有访问权限后,便发布了数据。此时,初级分析师看到了他们无权查看的高管薪酬数据。

传统授权检查发生在数据检索时。而共享上下文要求在输出端进行授权检查,即计算所有受众成员权限的交集。传统的基于角色的访问控制(RBAC)无法建模这种关系图。

2. 自主代理

这些代理在无用户交互的情况下运行,例如安全机器人轮换密钥或计费代理核对发票。

这里的身份认证问题已基本解决。Microsoft Entra Agent ID 允许这些代理通过 client_credentials 流程使用独立的 Client ID 进行身份验证。这确保审计日志将操作归因于 Agent-007,而非人类用户。

“上帝模式”问题

授权层仍然存在缺陷。在标准的 client_credentials 流程中,生成的令牌往往决定广泛的访问权限。若要允许计费代理读取发票,通常需要授予 Files.Read.All 范围。

这导致了一个“上帝模式”代理。它可以读取发票,但也可能读取员工合同和专利草案。你很难将标准 OAuth 令牌精确限定为“仅读取财务文件夹中的文件”。这实际上相当于赋予一个概率性脚本根级访问权限。

为什么“扁平”RBAC 无法满足代理需求

如果代理需要有限范围的权限,显而易见的问题是:“为什么不直接创建一个特定角色?”为什么不创建 Billing_Agent 角色并就此结束?

失败之处在于授权模型的几何结构。传统的基于角色的访问控制(RBAC)是扁平化的。它将主体映射到角色,再将角色映射到一组全局权限(如 read:repos)。这对人类用户有效,因为人类用户的访问通常与其职位相关,而职位是稳定且宽泛的。

代理的访问则与任务相关,而任务是短暂且具体的。

你并不希望代理成为“仓库编辑者”。你应该强制规定:“此代理只能在仓库 api 的 feature-xyz 分支上编辑代码,除此之外无权进行任何操作。”

若要用扁平化的 RBAC 来表达这一需求,就必须为每个资源与权限的组合创建唯一角色。

  • 角色:Editor_Repo_API_Branch_XYZ
  • 角色:Viewer_Repo_Frontend_Branch_ABC
  • 在一个拥有数千个仓库和临时分支的企业环境中,这会导致组合爆炸。管理复杂度从 O(1) 的角色数量跃升至 O(N x M)。维护这些静态角色的摩擦成本,已远超代理本身带来的效率提升价值。

    解决方案:FGA = RBAC + 层级结构

    这正是精细粒度授权(Fine-Grained Authorization, FGA)发挥作用的地方。它并非要取代你已有的概念体系,而是对 RBAC 的自然延伸。

    要解决这一问题,我们无需抛弃 RBAC。我们需要对其进行范围限定——而这正是精细粒度授权(FGA)的定义所在。

    FGA 并非要替代你已知的那些概念,而是将 RBAC 应用于资源层级结构之中。

    
    Organization: Acme
     └── Repository: API
           └── Branch: feature-xyz  <-- Agent Permission Starts Here
                 └── Actions: [push, merge]
      

    你依然保留熟悉的“编辑者”“查看者”等角色心智模型,但将这些角色绑定到图中的具体节点,而非根节点。

  • 垂直继承:当代理被授予 Branch:feature-xyz 的编辑权限时,它将自动继承该分支内所有文件和操作的访问权限。
  • 无横向越权:关键在于,该权限不会横向蔓延至 Branch:staging,也不会向上渗透到 Repository:API。
  • 在此模型中,代理在需要的地方拥有全部权限,而在其他地方则毫无权限。

    扩展图谱:结构型资源 vs. 资产数据

    采用集中式授权服务时,一个常见顾虑是状态同步的开销。如果你的应用管理着数百万个独立资产,你可能会认为每一个都需要镜像到 FGA 图谱中。实际上,你只需同步结构层级,而非资产数据本身。

    可将 FGA 视为权限体系的骨架。你注册的是定义访问边界的顶层容器:组织、工作区和项目。这些就是你的结构型资源。而像文件夹内的单个文件或项目中的图片这类高吞吐量的资产数据,则保留在主应用存储中。

    当代理请求访问某个特定资产时,你的应用逻辑会执行一个简单的两步检查:

  • 应用逻辑:识别该资产所属的容器(例如 Folder:Q3-Financials)。
  • FGA:发起查询 check(subject=Agent, role=viewer, resource=Folder:Q3-Financials)。
  • 通过检查父级容器的访问权限而非单个资产,你让授权图谱保持精简,并实现低于 50 毫秒的延迟。同时避免了大规模数据同步带来的“双写”一致性问题,从而在不引入全量数据库镜像基础设施成本的前提下,获得细粒度的安全保障。

    FGA 如何解决两种代理模式的问题

    一旦建立起层级化模型,先前提到的授权难题(作用域衰减与上帝模式)便可通过标准架构模式迎刃而解。

    1. 解决 OBO 代理:交集检查法

    对于 On-Behalf-Of(代为执行)代理,目标是防止“混淆的代理人”问题。即使用户拥有广泛权限,代理也应仅能访问当前任务所需的内容。

    FGA 通过计算权限交集来解决此问题。你可以定义一条策略,要求用户和代理双方都必须具备相应权限,才能授予请求。

    这使得授权检查从静态的角色查找转变为动态验证。当 MCP 服务器接收到类似 read_file(path="/secrets.json") 的工具调用时,它会在 FGA 图中执行实时检查:

    
    Input: check(subject=Agent, role=viewer, resource=file:secrets.json)
    Output: FALSE (Access Denied)
      

    这允许服务器对敏感资源动态返回精确的 403 Forbidden 错误。用户无需手动限制代理的广泛 OAuth 令牌权限。

    FGA 作为 MCP 的逻辑层

    ‍随着像 MCP 这样的协议成熟以支持丰富的授权请求(RFC 9396),代理将传递结构化意图对象而非不透明的字符串。例如:{"file": "main.rs", "action": "edit"}。

    重要的是要记住,RAR 只是一个数据格式。它充当请求的外壳,但本身不提供判断请求是否有效的逻辑。RAR 对象无法理解 /backend 属于 Team A,或用户是 Team A 的管理员。

    如果仅依赖 RAR,开发人员仍需编写复杂的逻辑来遍历这些关系。FGA 通过原生处理层级结构解决了这一问题。它作为决策引擎,将 RAR 外壳与组织的实际权限图进行比对验证。

    内存泄漏:长期上下文的安全隐患

    随着代理从无状态脚本演变为持久协作伙伴,它们开始在向量数据库中存储"记忆"。这带来了新的安全阴影:如果一个代理将敏感文档摘要存入其长期记忆中,这些信息可能会被"幻觉"回传给一个无权访问原始来源的不同用户。

    为防止上下文泄露,开发者应将代理的记忆视为受保护资源,并对代理的"回忆"应用与源文件相同的 FGA 策略:

  • 元数据标记:写入向量存储的每个嵌入都应标记其源 resource_id。
  • 过滤检索:当代理查询其记忆时,应用程序必须在向量搜索中加入 FGA 检查。如果当前用户无法访问源 resource_id,该记忆对代理保持不可见。
  • 上下文分片:高安全环境应使用临时内存分片,当代理在不同 FGA 项目节点间移动时刷新这些分片。
  • 通过将嵌入锚定到 FGA 资源 ID,您可以确保代理的内部上下文与其实时操作一样受到严格管控。

    2. 解决自主代理:限定角色方案

    对于自主代理,目标是防止"上帝模式"——即特定机器人意外获得整个租户的根访问权限。

    FGA 作为代理广泛身份的约束层。

  • 身份:身份提供商(IdP)证明代理是"计费机器人"。
  • 授权(FGA):应用程序询问计费机器人是否可以读取 file:executive_comp.pdf。
  • 检查:FGA 发现代理在 Project:Finance 节点上拥有 Viewer 角色,但在 Project:HR 节点上没有。拒绝访问。
  • 在此模型中,代理本身就是主体。它直接获得所需资源的权限。当代理停用时,只需删除其在特定节点上的角色分配,整个子树中的访问权限立即消失。

    身份提供商为您提供安全标识,WorkOS FGA 为您提供控制抓手。没有 FGA,自主代理实际上就是具有整个租户根访问权限的高速脚本。

    代理企业治理

    在传统企业环境中,访问权限遵循员工生命周期。当用户通过身份提供商(IdP)入职时,会获得一组角色;离职时,其访问权限将被撤销。

    代理程序打破了这一流程。与人类用户会主动登出或更换工作不同,代理程序具有持久性。它们的令牌保持有效,服务账户也持续活跃。最新数据显示,企业凭证在不再需要后平均仍会保持激活状态长达47天。随着代理身份的激增,人工管理其生命周期变得不可行,并形成了巨大的凭证窃取风险面。

    WorkOS FGA 通过在您的 IdP 与应用程序内部资源层级之间建立连接,实现了对整个代理生命周期的集中治理。标准 IdP 擅长管理群组,却对内部资源视而不见。FGA 提供了授权链条中的“最后一公里”,确保代理访问权限由与人类员工相同的 SSO 和 SCIM 基础设施进行管控:

  • 配置:管理员在 IdP 中创建代理(或通过未来的 SCIM /Agents 端点),并将其分配至一个功能群组,例如 Project-X-Automations。
  • 自动化入职:WorkOS Directory Sync 会即时检测到新的身份及其所属群组,无需人工干预即可在您的应用中为该代理完成配置。
  • 范围化治理:您的应用利用该群组成员身份,在 FGA 中为其分配一个资源限定角色,例如 Project:X 上的 Editor。代理立即被限制在该特定项目子树范围内操作。
  • 即时注销:当代理从群组中移除或在 IdP 中被停用时,其在 FGA 中的所有服务角色分配将同步撤销。
  • 这种架构确保代理凭证永远不会超出其使用意图。通过将身份与分层授权机制协同运作,您为 IT 部门提供了他们所要求的自动化注销流程和审计追踪能力。

    下一步展望

    我们正处于一个关键转折点。微软、Okta 以及 IETF 工作组正在构建代理身份的基础设施。像 MCP 这样的协议正从根本上重新思考授权接口的设计。

    缺失的一环正是授权层本身。仅仅判断代理能否调用 API 是不够的,我们必须进一步确认:该代理是否可以根据委派用户的身份、组织策略以及资源层级,在特定资源上执行特定操作。

    仍有若干复杂问题亟待解决。这些正是我们将重点投入的方向。

    用户群组作为授权主体

    群组正逐渐成为 FGA 中的一等公民。您将能够为 IdP 中的某个群组在特定资源上分配角色,例如在 workspace:platform 上为工程群组分配权限。无论是人类还是代理,所有成员都将自动继承相应权限。当主体加入或离开 IdP 中的群组时,其访问权限将实时更新。

    FGA 角色分配

    企业治理中的一个主要障碍是将扁平的IdP(例如Okta、Entra)群组映射到嵌套资源。我们正在构建FGA角色分配功能,以原生方式弥合这一差距。该功能允许您将IdP群组(例如"Project-X-Bots")与特定资源子树上的FGA角色(例如在文件夹:NA-Prospects上的Viewer角色)建立映射。当用户在IdP中添加到此群组时,SSO或目录同步将自动在FGA中创建相应的角色分配。这消除了管理身份源与资源图之间关系的"胶水代码"需求。

    代理到代理的委托

    当代理生成子代理或委托任务时,链中的每个环节都需要衰减的作用域。传递给子代理的令牌应比原始令牌拥有更少的权限。FGA的分层模型非常适合这种情况。每次委托步骤都会将子代理约束到更窄的资源子树中。我们正在为这些委托链构建一流的支持,使授权系统而非自定义应用程序逻辑来强制执行作用域衰减。

    代理的SCIM配置

    IETF SCIM代理模式草案引入了/Agents作为具有所有权要求和休眠检测功能的资源类型。随着这一标准的成熟,WorkOS目录同步将以类似当前为用户配置的方式配置代理。IdP群组成员资格将直接映射到FGA资源范围的角色,自动化整个生命周期。

    全局低延迟授权

    代理以机器速度运行,通常跨越多个区域。虽然我们目前提供低于50毫秒的第95百分位访问检查,但我们正在转向边缘缓存和流式更新,以在全球范围内接近低于10毫秒的水平。这确保了授权决策不会成为代理性能的延迟瓶颈。

    代理软件的授权复杂性正在迅速增加。如果您正在构建将由代理运行的软件,现在就是奠定基础的时候了。

    WorkOS FGA现已可用。请从这里开始使用。

    研究前沿:超越静态授权

    行业正处于十字路口。截至2026年初,代理身份的基础要素开始聚集,但几个高阶授权问题仍处于研究阶段。在WorkOS,我们密切关注这些变化。我们将FGA视为必须与AI的概率性质共同演化的活体基础设施。

    有三个具体领域,标准授权与代理现实之间的差距最为明显。

    1. 多跳委托和溯源

    在先进的多代理系统中,主代理通常会将请求分解为子任务并委托给专门的子代理。这会产生"俄罗斯套娃"效应:每次交接都跨越信任边界,但通常在第三或第四次跳转时就会丢失加密的溯源信息。

    关于授权溯源的当前研究表明,"谁"不再是一个单一主体,而是一条链。如果一个授权用于公共数据的Research Agent生成了一个授权用于私有仓库的Code Agent,那么产生的访问权限必须是该溯源链中每个实体的交集。弥合这一差距需要能够验证每个工具调用"保管链"的授权引擎,确保不仅检查权限,而且追溯回其起源。

    IETF一直在积极研究扩展OAuth以处理这种"俄罗斯套娃"式委托。

    2. 即时代理(JIT 代理)

    传统服务账户依赖“常驻权限”——即始终处于激活状态的访问权限。对于机器速度级的代理而言,常驻权限构成了巨大的风险。如果代理拥有一个具有写入权限的静态 API 密钥,一次成功的提示注入攻击就可能导致数据被立即、不可逆转地窃取。

    即时代理(Just-in-Time Agency)的概念正朝着“零常驻权限”(Zero Standing Privileges)模型演进。在这个未来场景中,代理在触发特定任务之前不具备任何权限。授权引擎随后会授予一个临时、短期的角色分配,该角色在事务完成后自动过期。这将在当前任务所需的最小范围内减少攻击面,将安全状态从静态转变为动态。

    零常驻权限(ZSP)的概念正由 NIST 和 OWASP Top 10 for Agentic Applications 共同倡导。

    3. 语义未来:基于意图的访问控制

    与确定性代码不同,代理是概率性的。在长时间运行的会话中,代理的行为可能会“偏离”最初的用户意图。一个最初仅用于总结邮件(低风险)的代理,可能会根据后续模糊指令,逐渐演变为将文件移动到外部驱动器(高风险)。

    语义检查(Semantic Inspection)的新兴策略表明,授权应锚定于初始任务会话。如果代理尝试执行与其原始“根”授权在语义上无关的工具调用,引擎应标记这种偏离行为。这标志着从检查代理能做什么,转向理解它为什么要这么做——从而创建一层上下文护栏,可在高风险操作发生前触发“人在回路”(Human-in-the-Loop)审批。

    该领域最前沿的研究来自大型语言模型(LLM)可观测性与“宪法式 AI”(Constitutional AI)的交叉领域。

    代理授权的最终目标是超越确定性的“能/不能”检查,进入意图对齐(Intent Alignment)的领域。我们正在迈向一个世界,其中策略以自然语言定义——例如“不得向未经验证的第三方共享客户个人身份信息”——并由一个理解代理请求背后推理的授权层来强制执行。

    在 WorkOS,我们相信 FGA 是实现这一概率性未来的必要基石。你不能依赖 LLM 自我监管;你需要一个确定性的资源图谱作为事实依据。通过将自然语言意图链接到细粒度的资源层级,我们创建了首个语义护栏,它不仅能因代理缺少角色而阻止其操作,更能因其当前行为偏离其声明的使命而加以拦截。

    需要完整排版与评论请前往来源站点阅读。