
Snowflake の IS_AGENT_ACTIVATED でSnowflake CoCo利用時だけ PII をマスキングしてみた
かわばたです。
Snowsight 上の Snowflake CoCo や Snowflake CoWork などの AI エージェントが社内データにアクセスする場面が増えてきました。
「分析者が直接 SQL を書くときは生データを見たいが、エージェント経由のアクセスでは PII をマスクしたい」そんなケースに対応できるのが IS_AGENT_ACTIVATED です。
この関数をマスキングポリシーの条件に組み込むと、同一ロールでもエージェント利用時だけマスキングを適用し、通常の SQL 分析ではマスクしないという制御が可能になります。
実際に Snowsight 上の Snowflake CoCo と Snowflake CoWork の両方で動作を確認してみたので、手順と結果をまとめます。
機能概要
IS_AGENT_ACTIVATED とは
IS_AGENT_ACTIVATED は、現在のセッションが AI エージェントによって実行されているかどうかを判定するコンテキスト関数です。SYS_CONTEXT 関数経由で呼び出します。
-- 任意のエージェントが有効かどうかを判定
SYS_CONTEXT('SNOWFLAKE$CURRENT', 'IS_AGENT_ACTIVATED')
-- 特定のエージェントタイプが有効かどうかを判定
SYS_CONTEXT('SNOWFLAKE$CURRENT', 'IS_AGENT_ACTIVATED', 'CORTEX_CODE_SNOWSIGHT')
戻り値は VARCHAR 型('TRUE' または 'FALSE')です。BOOLEAN 値として扱う場合は ::BOOLEAN でキャストします。
対応エージェントタイプ
| エージェントタイプ | 説明 |
|---|---|
SNOWFLAKE_INTELLIGENCE |
Snowflake CoWork エージェント |
CORTEX_CODE_SNOWSIGHT |
Snowsight 上の Snowflake CoCo |
CORTEX_CODE_CLI |
CLI クライアントの Snowflake CoCo |
CORTEX_CODE_DESKTOP |
デスクトップクライアントの Snowflake CoCo |
マスキングポリシーとの組み合わせ
マスキングポリシーの CASE 式で IS_AGENT_ACTIVATED を条件に使うことで、エージェント経由のアクセスだけマスクする制御を実現できます。
-- 全エージェント対象のマスキングポリシー
CREATE OR REPLACE MASKING POLICY mask_pii_for_all_agents AS (val STRING)
RETURNS STRING ->
CASE
WHEN SYS_CONTEXT('SNOWFLAKE$CURRENT', 'IS_AGENT_ACTIVATED')::BOOLEAN = TRUE
THEN '***MASKED***'
ELSE val
END;
POLICY_CONTEXT によるシミュレーション
マスキングポリシーを適用する前に、POLICY_CONTEXT 関数でエージェント実行時の挙動をシミュレーションできます。SNOWFLAKE$CURRENT_ACTIVATED_AGENT_TYPES 引数にエージェントタイプを指定します。
-- Snowsight 上の Snowflake CoCo からのアクセスをシミュレーション
EXECUTE USING POLICY_CONTEXT(
SNOWFLAKE$CURRENT_ACTIVATED_AGENT_TYPES => ('CORTEX_CODE_SNOWSIGHT')
)
AS SELECT * FROM masking_test_db.sch.customers;
制限事項
database、schema、nameパラメータによる個別エージェントの絞り込みは SNOWFLAKE_INTELLIGENCE のみサポート。他のエージェントタイプではフィルタ引数は使用不可- 戻り値は VARCHAR 型のため、BOOLEAN 値として扱う場合は
::BOOLEANキャストが必要 - マスキングポリシー自体の制約(同一カラムに複数ポリシーを設定できない等)はそのまま適用される
前提条件
- Snowflake: AWS 東京リージョン、Enterprise Edition
- 本機能のステータス: 2026年6月30日時点で公式ドキュメント上 Preview 表記なし
- 必要な権限: ACCOUNTADMIN ロール(検証用)
- CoCo: Snowsight 上で利用可能な状態であること
- Snowflake CoWork: 利用可能な状態であること
事前準備
検証用データベース・テーブルの作成
PII を含む検証用テーブルを作成します。
検証用テーブル作成
USE ROLE ACCOUNTADMIN;
-- 検証用データベース
CREATE DATABASE IF NOT EXISTS masking_test_db;
CREATE SCHEMA IF NOT EXISTS masking_test_db.sch;
USE SCHEMA masking_test_db.sch;
CREATE OR REPLACE TABLE customers (
customer_id NUMBER COMMENT '顧客ID',
full_name VARCHAR COMMENT '氏名',
email VARCHAR COMMENT 'メールアドレス',
phone_number VARCHAR COMMENT '電話番号',
date_of_birth DATE COMMENT '生年月日',
annual_salary NUMBER(10, 2) COMMENT '年収',
notes VARCHAR COMMENT '備考(機密情報なし)'
);
-- 検証用ダミーデータの投入(20レコード)
INSERT INTO customers VALUES
(1, 'John Smith', 'john.smith@example.com', '+1-555-0101', '1985-03-15', 85000.00, 'VIP customer'),
(2, 'Jane Doe', 'jane.doe@example.com', '+1-555-0102', '1990-07-22', 72000.00, 'Regular customer'),
(3, 'Michael Johnson', 'michael.j@example.com', '+1-555-0103', '1978-11-03', 95000.00, NULL),
(4, 'Emily Williams', 'emily.w@example.com', '+1-555-0104', '1992-01-30', 68000.00, 'New account'),
(5, 'David Brown', 'david.b@example.com', '+1-555-0105', '1988-05-18', 91000.00, NULL),
(6, 'Sarah Davis', 'sarah.d@example.com', '+1-555-0106', '1995-09-07', 63000.00, 'Preferred customer'),
(7, 'Robert Miller', 'robert.m@example.com', '+1-555-0107', '1982-12-25', 78000.00, NULL),
(8, 'Lisa Wilson', 'lisa.w@example.com', '+1-555-0108', '1993-04-11', 82000.00, 'Corporate account'),
(9, 'James Moore', 'james.m@example.com', '+1-555-0109', '1975-08-19', 105000.00, NULL),
(10, 'Amanda Taylor', 'amanda.t@example.com', '+1-555-0110', '1987-02-14', 74000.00, 'Trial period'),
(11, 'Christopher Anderson', 'chris.a@example.com', '+1-555-0111', '1991-06-28', 88000.00, NULL),
(12, 'Jennifer Thomas', 'jennifer.t@example.com', '+1-555-0112', '1984-10-05', 71000.00, 'Seasonal buyer'),
(13, 'Daniel Jackson', 'daniel.j@example.com', '+1-555-0113', '1996-03-20', 66000.00, NULL),
(14, 'Jessica White', 'jessica.w@example.com', '+1-555-0114', '1989-07-08', 93000.00, 'Loyalty member'),
(15, 'Matthew Harris', 'matthew.h@example.com', '+1-555-0115', '1980-11-15', 99000.00, NULL),
(16, 'Ashley Martin', 'ashley.m@example.com', '+1-555-0116', '1994-01-22', 70000.00, 'Student discount'),
(17, 'Andrew Garcia', 'andrew.g@example.com', '+1-555-0117', '1986-05-30', 110000.00, NULL),
(18, 'Megan Martinez', 'megan.m@example.com', '+1-555-0118', '1997-09-12', 67000.00, 'Referral program'),
(19, 'Joshua Robinson', 'joshua.r@example.com', '+1-555-0119', '1983-12-01', 86000.00, NULL),
(20, 'Lauren Clark', 'lauren.c@example.com', '+1-555-0120', '1990-04-25', 79000.00, 'Premium member');
SELECT * FROM customers ORDER BY customer_id LIMIT 5;

マスキングポリシーの作成
2つのパターンのマスキングポリシーを作成します。
マスキングポリシー作成
パターン1: 全エージェント対象
エージェントの種類を問わず、エージェント経由のアクセスであればマスクするポリシーです。
CREATE OR REPLACE MASKING POLICY masking_test_db.sch.mask_pii_for_all_agents AS (val STRING)
RETURNS STRING ->
CASE
WHEN SYS_CONTEXT('SNOWFLAKE$CURRENT', 'IS_AGENT_ACTIVATED')::BOOLEAN = TRUE
THEN '***MASKED***'
ELSE val
END;
パターン2: Snowsight 上の Snowflake CoCo のみ対象
Snowsight 上の Snowflake CoCo 経由のアクセスだけマスクし、他のエージェント(Snowflake CoWork 等)ではマスクしないポリシーです。後の検証で切り替えて使います。
CREATE OR REPLACE MASKING POLICY masking_test_db.sch.mask_pii_for_cortex_code_snowsight AS (val STRING)
RETURNS STRING ->
CASE
WHEN SYS_CONTEXT('SNOWFLAKE$CURRENT', 'IS_AGENT_ACTIVATED', 'CORTEX_CODE_SNOWSIGHT')::BOOLEAN = TRUE
THEN '***MASKED***'
ELSE val
END;
マスキングポリシーの適用
本記事では検証をシンプルにするため、PII のうち email と phone_number の 2 カラムにのみマスキングポリシーを適用します。まずはパターン1(全エージェント対象)を適用します。
ALTER TABLE masking_test_db.sch.customers
ALTER COLUMN email SET MASKING POLICY masking_test_db.sch.mask_pii_for_all_agents;
ALTER TABLE masking_test_db.sch.customers
ALTER COLUMN phone_number SET MASKING POLICY masking_test_db.sch.mask_pii_for_all_agents;
検証用ロールの作成
検証用ロール MASKING_TEST_ROLE を作成し、必要な権限を付与します。このロールで直接 SQL とエージェント経由の両方を試すことで、同一ロールでもアクセス経路によってマスキング結果が変わることを確認します。
検証用ロール作成
USE ROLE ACCOUNTADMIN;
-- 検証用ロールの作成
CREATE ROLE IF NOT EXISTS MASKING_TEST_ROLE;
-- 必要な権限を付与
GRANT USAGE ON DATABASE masking_test_db TO ROLE MASKING_TEST_ROLE;
GRANT USAGE ON SCHEMA masking_test_db.sch TO ROLE MASKING_TEST_ROLE;
GRANT SELECT ON ALL TABLES IN SCHEMA masking_test_db.sch TO ROLE MASKING_TEST_ROLE;
GRANT USAGE ON WAREHOUSE <your_warehouse_name> TO ROLE MASKING_TEST_ROLE;
-- 検証用ロールを自分に付与
GRANT ROLE MASKING_TEST_ROLE TO USER <your_username>;
試してみた
検証用ロールで通常の SQL クエリを実行する(マスクされない)
MASKING_TEST_ROLE に切り替えて、Snowsight のワークシートから直接 SQL を実行します。
USE ROLE MASKING_TEST_ROLE;
SELECT customer_id, full_name, email, phone_number
FROM masking_test_db.sch.customers
ORDER BY customer_id
LIMIT 5;

email と phone_number が生データのまま表示されれば問題ありません。エージェント経由ではないため、IS_AGENT_ACTIVATED は FALSE を返し、CASE 式の ELSE 節で元の値がそのまま返ります。
同じロールで Snowsight 上の Snowflake CoCo 経由で確認する(マスクされる)
同じ MASKING_TEST_ROLE のまま、Snowsight 上の Snowflake CoCo から同じテーブルを問い合わせます。
CoCo のロール設定が MASKING_TEST_ROLE になっていることを確認してください。

CoCo に「masking_test_db.sch.customers テーブルから顧客ID、氏名、メールアドレス、電話番号を5件取得してください」のように依頼します。

email と phone_number が ***MASKED*** と表示されれば問題ありません。同じ MASKING_TEST_ROLE を使っていても、CoCo 経由のアクセスでは IS_AGENT_ACTIVATED が TRUE を返し、マスキングが適用されます。
同じロールで Snowflake CoWork 経由で確認する(マスクされる)
同じ MASKING_TEST_ROLE のまま、Snowflake CoWork から同じテーブルを問い合わせます。

こちらも email と phone_number が ***MASKED*** と表示されればOKです。Snowflake CoWork は SNOWFLAKE_INTELLIGENCE エージェントタイプとして判定されるため、パターン1(全エージェント対象)のマスキングポリシーが適用されます。
同一ロール(MASKING_TEST_ROLE)でも、直接 SQL では生データが見え、エージェント経由ではマスクされることが確認できました。
特定エージェントのみマスキングする
次に、パターン1(全エージェント対象)を解除し、パターン2(Snowsight 上の Snowflake CoCo のみ対象)に切り替えます。マスキングポリシーの変更は ACCOUNTADMIN で行います。
USE ROLE ACCOUNTADMIN;
-- パターン1を解除
ALTER TABLE masking_test_db.sch.customers
ALTER COLUMN email UNSET MASKING POLICY;
ALTER TABLE masking_test_db.sch.customers
ALTER COLUMN phone_number UNSET MASKING POLICY;
-- パターン2を適用
ALTER TABLE masking_test_db.sch.customers
ALTER COLUMN email SET MASKING POLICY masking_test_db.sch.mask_pii_for_cortex_code_snowsight;
ALTER TABLE masking_test_db.sch.customers
ALTER COLUMN phone_number SET MASKING POLICY masking_test_db.sch.mask_pii_for_cortex_code_snowsight;
Snowsight 上の Snowflake CoCo → マスクされる
MASKING_TEST_ROLE で Snowsight 上の Snowflake CoCo から問い合わせます。

Snowsight 上の Snowflake CoCo(CORTEX_CODE_SNOWSIGHT)経由ではマスクされます。
Snowflake CoWork → マスクされない
同じ MASKING_TEST_ROLE で Snowflake CoWork から問い合わせます。

Snowflake CoWork(SNOWFLAKE_INTELLIGENCE)経由ではマスクされず、生データが表示されます。IS_AGENT_ACTIVATED の第3引数に 'CORTEX_CODE_SNOWSIGHT' を指定しているため、それ以外のエージェントでは FALSE が返ります。
(補足)POLICY_CONTEXT でマスキング挙動を事前シミュレーションする
実際にエージェントを動かす前に、POLICY_CONTEXT 関数でマスキングの挙動を事前にシミュレーションすることもできます。
USE ROLE ACCOUNTADMIN;
-- Snowsight 上の Snowflake CoCo からのアクセスをシミュレーション
EXECUTE USING POLICY_CONTEXT(
SNOWFLAKE$CURRENT_ACTIVATED_AGENT_TYPES => ('CORTEX_CODE_SNOWSIGHT')
)
AS
SELECT customer_id, full_name, email, phone_number
FROM masking_test_db.sch.customers
ORDER BY customer_id
LIMIT 5;
最後に
Snowflake の IS_AGENT_ACTIVATED 関数を使い、エージェント利用時だけ PII をマスキングする設定を検証しました。
ポイントは、ロールベースのアクセス制御を変えずに、エージェント実行コンテキストかどうかでマスキング結果を出し分けられる点です。今回の検証では、同一の MASKING_TEST_ROLE で直接 SQL を実行すると生データが見え、エージェント経由で問い合わせるとクエリ結果上の PII がマスクされることを確認できました。エージェントや LLM にセンシティブな値が渡るリスクを低減できます。
さらに、IS_AGENT_ACTIVATED の第3引数でエージェントタイプを指定すれば、Snowsight 上の Snowflake CoCo だけマスクして Snowflake CoWork 経由のアクセスではマスクしない、といった細かい制御も可能です。用途やリスクレベルに応じてエージェントごとにポリシーを使い分けられます。
この記事が何かの参考になれば幸いです!








