2026 年,智能体将在企业级应用中取得哪些实质性突破?点击下载《2026 年 AI 与数据发展预测》白皮书,获悉专家一手前瞻,抢先拥抱新的工作方式!
Snowflake Cortex Agents 让业务用户可以用普通英语向数据提问,并获得洞察、结果和可视化内容——不需要了解 SQL 或 schema。它让更多人也能参与到数据与分析这场派对中来。
但许多 Snowflake 客户会构建面向自身客户的应用,而其中一个硬性要求是:每个客户只能看到自己的数据。我们不能只是相信 LLM 会在每一次查询中都加上正确的 WHERE 子句——安全不应该依赖 prompt engineering。
好消息是:这些应用本来就运行在 Snowflake 上,而 Snowflake 现有的治理原语——RBAC、row access policies(RAPs)和 session attributes——可以把 agent 限制在边界之内,让它在物理上无法看到访问者权限范围之外的数据。本文将介绍具体做法。
摘要
Snowflake Cortex Agents 会在一个 Snowflake session 中执行其生成的 SQL,因此,任何应用到该 session 的治理措施(user、role、RAPs、session attributes)都会自动应用到 agent 上;
对于共享访问,使用 service user;
对于按用户访问,通过 External OAuth 进行身份验证,让 agent 以访问用户的身份运行;
对于按租户访问,可以选择三种模式之一——user-per-tenant、role-per-tenant,或 tenant session attribute——每种模式都能清晰映射到 Cortex Agent run API 的调用方式;
关于表、RAPs 和 cURL 命令的完整示例设置,可以在这里找到。

三种访问场景
大多数多租户应用都可以归入以下三类之一:
Shared——每个访问者看到相同的数据;
Per-user——每个访问者都有自己的 Snowflake 身份和自己的数据范围;
Per-tenant——访问者没有 Snowflake 身份,但每个人都属于某个租户(组织 / 团队 / 客户),并且访问权限必须限制在该租户的数据范围内。
传统应用会生成自己的 SQL,并可以在中间层强制执行作用域限制。一旦我们把 SQL 生成委托给 agent,这条退路就不存在了——治理必须在 Snowflake 内部 强制执行。下面我们逐一介绍每种场景,包括当 Cortex Agents 进入这个流程后,具体会发生哪些变化。
场景一:共享访问(Service User)
这是最简单的情况。应用可以用自己喜欢的方式对访问者进行身份验证(例如使用自己的 IdP),只是为了确认他们被允许进入应用,然后以单一 service user 的身份连接到 Snowflake。标准 RBAC 和任何 RAPs 都会应用到该用户。
Cortex Agent:使用 service user 的凭据调用 run API。agent 会继承与 service user 完全相同的权限。不需要任何特殊处理。
场景二:Snowflake 中的按用户身份访问
每个访问者都有一个 Snowflake user,因此我们通过 IdP 对访问者进行身份验证,并使用一个 Snowflake 也接受的 token。Snowflake 支持多种 IdP 集成模式——SCIM(用于用户预配)、SAML(用于登录页面 SSO)和 External OAuth(用于基于 API token 的访问)。对于代表用户调用 Snowflake API 的应用来说,External OAuth 是合适的工具。
访问者完成身份验证后,应用会收到一个 OAuth token,其中的 claims 会映射到某个 Snowflake user。应用会把自己的 session ID 与这个 token 一起存储,并在每一次 Snowflake API 调用时——包括 Cortex Agent run——转发该 token。Snowflake 会验证 token,并以访问者用户的身份执行调用,同时受到该用户所适用的所有 RBAC 和 RAPs 约束。
Cortex Agent:使用访问者的 OAuth token 调用 run API。无需其他操作。
场景三:按租户访问(访问者没有 Snowflake 身份)
这是更有意思的情况。IdP 登录会给我们一个租户标识符——可能是一个 custom claim,也可能是根据约定推导出来的(例如 sub claim 中的邮箱域名)。应用会将每个访问者的 session 映射到该租户。现在的问题是:我们如何让 Snowflake——以及 Cortex Agent——按照该租户的范围来运行?
有三种模式。下面是一个快速对比:

Pattern A: User-per-Tenant
为每个租户创建一个 Snowflake user,并为每张多租户表应用一个以 CURRENT_USER() 为 key 的 RAP:
CREATE ROW ACCESS POLICY IF NOT EXISTS per_user_rap AS (key_column VARCHAR) RETURNS BOOLEAN -> key_column = CURRENT_USER();你需要为每个租户管理凭据(轮换、secret-manager 存储、入驻 / 离开时创建和删除),应用也需要一种方式将租户映射到 Snowflake user——可以是映射表,也可以是类似 USER_
Cortex Agent:使用该租户 user 的凭据调用 run API。无需其他操作。
Pattern B: Role-per-Tenant
单个 service user 持有每个租户 role 的授权;你按请求切换 role。RAP 以 CURRENT_ROLE() 为 key:
CREATE ROW ACCESS POLICY IF NOT EXISTS per_user_rap AS (key_column VARCHAR) RETURNS BOOLEAN -> key_column = CURRENT_ROLE();租户入驻时创建的是 role(不是 user),将该租户的数据访问权限授予它,并将该 role 授予 service user。你仍然需要一个租户到 Snowflake role 的映射。应用自己发出的 SQL 可以使用连接池——只需要在每次查询之前执行 USE ROLE。
Cortex Agent:在 run API 调用中,将 X-Snowflake-Role header 设置为租户 role。为了防止任何 fallback,需要将 service user 配置为没有默认 secondary roles,这样 agent 就没有其他可 fallback 的 role。
Pattern C: Tenant Session Attribute
完全不需要按租户创建 Snowflake 对象。单个 service user 可以访问所有租户的数据,我们通过设置 session attribute 来限定每个 session 的范围——这是一种新的 session variable,一旦在某个 session 中设置,就不能再更改。
使用 SET_SYS_CONTEXT() 并指定保留 namespace SNOWFLAKE$SESSION_ATTRIBUTES 来设置 session attribute,使其不可变。(任何其他 namespace——或 NULL——设置的都是普通的可变 session variable)。
SELECT SET_SYS_CONTEXT('SNOWFLAKE$SESSION_ATTRIBUTES', 'TENANT', 'ALICE');RAP 通过 SYS_CONTEXT() 读取它:
CREATE ROW ACCESS POLICY IF NOT EXISTS sess_attr_rap AS (key_column VARCHAR) RETURNS BOOLEAN -> key_column = SYS_CONTEXT('SNOWFLAKE$SESSION_ATTRIBUTES', 'TENANT');Cortex Agent:run API 的 payload 中接受一个 variables block,Snowflake 保证这些变量会在任何 agent 生成的 SQL 运行之前被设置到 session 上:
{ "variables": { "TENANT": { "value": "ALICE", "type": "string", "is_immutable_session_attribute": true } }}is_immutable_session_attribute: true 这个 flag 至关重要。如果 agent 生成的 SQL 试图更改 TENANT——无论是意外、幻觉,还是 adversarial prompt 导致的——Snowflake 都会拒绝这次更改并抛出错误。RAP,以及你的租户边界,会在整个运行过程中保持完整。
将租户映射到数据值:Entitlement Tables
很多时候,租户标识符(user / role / attribute)与数据中存储的值并不匹配。例如,Hessco 这个租户可能拥有被标记为 hessco.com、hessco.co.uk 和 hessco.co.jp 的多行数据。entitlement table 可以弥合这个差距:
CREATE TABLE IF NOT EXISTS entitlement (tenant_id STRING, value STRING);-- e.g., ('Hessco', 'hessco.com'), ('Hessco', 'hessco.co.uk'), ('Hessco', 'hessco.co.jp')一个 memoizable UDF 会在每个 session 中收集一次允许访问的值,这样我们就不需要为每一行都重新查询该表:
CREATE FUNCTION IF NOT EXISTS allowed_values() RETURNS ARRAY MEMOIZABLE AS 'SELECT ARRAY_AGG(value) FROM entitlement';数据表上的 RAP 会测试 array membership,而不是做相等判断:
CREATE ROW ACCESS POLICY IF NOT EXISTS entitlement_rap AS (key_column VARCHAR) RETURNS BOOLEAN -> ARRAY_CONTAINS(key_column::VARIANT, allowed_values());最后,在 entitlement table 本身也加上一个 RAP,确保每个 session 只能看到自己的映射关系。predicate 会匹配你选择的租户模式——以下是 role-per-tenant 的例子:
CREATE ROW ACCESS POLICY IF NOT EXISTS entitlement_by_role_rap AS (tenant_id VARCHAR) RETURNS BOOLEAN -> tenant_id = CURRENT_ROLE();ALTER TABLE entitlement ADD ROW ACCESS POLICY entitlement_by_role_rap ON (tenant_id);对于 user-per-tenant,将 predicate 替换为 tenant_id = CURRENT_USER();对于 session-attribute 模式,则使用 tenant_id = SYS_CONTEXT('SNOWFLAKE$SESSION_ATTRIBUTES', 'TENANT')。
连接池 + Session Attributes:一种混合模式
Pattern C(session attributes)有一个小问题。那些也会发出自己 SQL 的应用——比如内置 dashboard——通常会使用连接池:一个长期存在的 service-user session 会被多个访问者复用。但 session attributes 是不可变的,因此一个被固定到租户 ALICE 的 session 永远不能再被租户 BOB 复用。这会破坏连接池机制。
对于应用自己发出的 SQL,理想情况下你会使用一个可变的 session variable。对于 Cortex Agent 调用,你需要一个不可变的 session attribute,因为 agent 可能会尝试更改任何可变内容。
解决方法是编写一个 RAP,让它同时接受两种形式,并在不可变 attribute 存在时优先使用它:
CREATE ROW ACCESS POLICY IF NOT EXISTS sess_attr_or_var_rap AS (key_column VARCHAR) RETURNS BOOLEAN -> key_column = COALESCE( SYS_CONTEXT('SNOWFLAKE$SESSION_ATTRIBUTES', 'TENANT'), SYS_CONTEXT(NULL, 'TENANT') );应用自己发出的 SQL(使用连接池):在每次查询开始时,设置可变 session variable:SELECT SET_SYS_CONTEXT(NULL, 'TENANT', '
Cortex Agent 调用:通过在 variables block 中包含 is_immutable_session_attribute: true 来设置 session attribute。
无论哪种方式,RAP 都会获取到正确的值——而 agent 的查询会受到不可变形式的保护。
总结
为 AI 驱动的应用定制数据访问,是“与数据对话”从 demo 走向产品的关键差异。Snowflake 现有的治理原语——RBAC、row access policies 和 immutable session attributes——提供了你所需的一切能力,让你可以放心地让 Cortex Agents 处理多租户数据,而不会破坏租户边界。选择适合你隔离模型的模式,将其接入 Cortex Agent run API,然后让 agent 负责写 SQL,由 Snowflake 负责执行规则。
如果你想查看一个设置 data、agents、roles 等内容并提供示例 cURL 命令的示例,可以查看这个 Snowflake Notebook。

点击链接立即报名注册:Ascent - Snowflake Platform Training - China,更多 Snowflake 精彩活动请关注专区。





