Compliance APIのuser_preferencesでメンバーの個人設定を取得する
Compliance APIのuser_preferencesは、メンバーが個人設定に書いた「Instructions for Claude」とCoworkのグローバル指示を一覧します。スコープ、絞り込み、ページ送りの落とし穴まで示します。
user_preferencesが返すのは、メンバーが書いた指示文そのもの
Compliance APIのuser_preferencesは、組織の現メンバーが個人設定に書いた指示文を一覧するエンドポイントです。パスはGET /v1/compliance/organizations/{org_uuid}/user_preferencesで、返るのは2種類のテキストだけです。
conversation_preferences: 個人設定の「Instructions for Claude」に書かれた文章cowork_global_instructions: Claudeのデスクトップエージェント、Coworkの「Global instructions」に書かれた文章
どちらも前後の空白を除いた文字列で返り、未設定か、設定後に消された場合はnullになります。チャットの中身やセッションのトランスクリプトとは別物で、メンバーが「Claudeにこう振る舞ってほしい」と恒常的に書いた設定側を見るためのものです。
セッションの文字起こし、チャット・ファイル、Activity Feedをいくら取得しても、個人設定は出てきません。会話の挙動を左右する指示文が、会話ログとは別の場所に置かれているためです。
ここで押さえておく性質が1つあります。この2つの設定はアカウント単位の設定で、同じ文章がメンバーの所属するどの組織でも返ります。複数の連結組織に所属するメンバーは、組織ごとに別の指示を持てるわけではありません。組織Aで取っても組織Bで取っても同じ文字列が出るので、集計するときはuser.idで重複を除くのが前提になります。
呼び出しに必要なキーとスコープ
個人設定を読むスコープはread:compliance_user_dataです。このスコープは、チャット・メッセージ・ファイル・プロジェクト、セッションのメタデータとトランスクリプト、組織のユーザー、ユーザーの個人設定、グループメンバーを読める、広い読み取りスコープとして定義されています。
つまり個人設定のためだけに絞ったスコープはありません。キーを作るときは、既にチャットやセッションの取得に使っているキーと同じ権限になります。個人設定だけを回す専用キーを作っても、そのキーはチャット本文も読めます。シークレットマネージャーに置き、取得系と削除系でキーを分ける運用は変わりません。キー作成の手順はCompliance APIのセットアップとアクセスキー作成にあります。
Admin APIキー(sk-ant-admin01-...)は、Compliance APIではread:compliance_activities、つまりActivity Feedしか持てません。ユーザー系のエンドポイントに使うと、次の形の403が返ります。
Missing required scopes. Got: ['read:compliance_activities'] Needed one of: ['read:compliance_user_data', 'read:org_audit']このメッセージは、チャットやユーザー一覧のエンドポイントで出る形です。個人設定のエンドポイントのエラー文は、APIリファレンスにも個別の記載がありません。同じスコープ判定が走ると考えられますが、実際の文面は自分の環境の応答で確かめてください。
認証ヘッダーの書き方が2か所で違う
注意したいのが認証ヘッダーです。APIリファレンスのuser_preferencesページでは、ExampleのcurlだけがAuthorization: Bearer $ANTHROPIC_COMPLIANCE_API_KEYで書かれています。同じページのHeaders節にはx-api-keyも載っています。Compliance APIの解説ページも「すべてのエンドポイントがx-api-keyヘッダーで認証する」としており、他のエンドポイントの例もx-api-keyです。
この記事のコード例は、解説ページとHeaders節に合わせてx-api-keyで送ります。401が返るときは、キーの値とスコープを確かめたうえで、ヘッダーの形式を入れ替えて試すのが最短の切り分けです。
最初の1回を呼ぶ
必要なのは組織のUUIDだけです。UUIDは組織一覧(GET /v1/compliance/organizations)が返すuuidで、取り方はClaude Enterpriseの組織UUIDを取得する手順に書いています。
org_uuid="91012d09-e48b-438e-a489-1bebfd8fa6f9"
curl --fail-with-body -sS \
"https://api.anthropic.com/v1/compliance/organizations/$org_uuid/user_preferences" \
-H "x-api-key: $ANTHROPIC_COMPLIANCE_ACCESS_KEY" \
-H "anthropic-version: 2023-06-01"応答はdataの配列と、has_more、next_pageです。1件分は次のような形になります(リファレンスの例に沿った形です)。
{
"data": [
{
"conversation_preferences": "Always answer in British English.",
"cowork_global_instructions": "Prefer short status updates.",
"user": {
"id": "user_01WCz1FkmYMm4gnmykNKUu3Q",
"email_address": "jane.doe@example.com"
}
}
],
"has_more": true,
"next_page": "cGFnZV90b2tlbl9leGFtcGxlXzE3MzQ1Njc4OTA="
}userにはidとemail_addressが付きます。email_addressは現在のメールアドレスです。並び順は組織への参加日の昇順で、古いメンバーが先に来ます。
クエリパラメーターは4つだけ
指定できるクエリパラメーターは次の4つです。
| パラメーター | 型 | 既定 | 役割 |
|---|---|---|---|
include_unset | 型真偽値 | 既定false | 役割trueで、未設定のメンバーもnull付きで含める |
limit | 型数値 | 既定20 | 役割1〜100。1ページの最大件数 |
page | 型文字列 | 既定なし | 役割前の応答のnext_pageをそのまま渡す |
user_ids | 型文字列の配列 | 既定なし | 役割対象を絞る。1回に10件まで |
Compliance APIは、定義にないクエリパラメーターを無視せず400で弾きます。user_idsは配列なので、他のエンドポイントと同じくuser_ids[]=...の形で送る書き方が基本です。大括弧を使うときは、curlの-Gと--data-urlencodeの組み合わせで書くと、エンコードで悩まずに済みます。
curl --fail-with-body -sS -G \
"https://api.anthropic.com/v1/compliance/organizations/$org_uuid/user_preferences" \
-H "x-api-key: $ANTHROPIC_COMPLIANCE_ACCESS_KEY" \
-H "anthropic-version: 2023-06-01" \
--data-urlencode "user_ids[]=user_01WCz1FkmYMm4gnmykNKUu3Q" \
--data-urlencode "include_unset=true"user_idsに現メンバーでないIDを入れても、エラーにはなりません。一致するものが無いだけで、結果から消えます。退職したメンバーを指定すると空で返るので、「設定が空」と「そもそもメンバーでない」が見分けられない点に注意が必要です。見分けるにはユーザー一覧(/users)でIDが在籍中かを先に確かめます。
include_unsetで何が変わるか
既定では、2つの値のうち少なくとも1つが設定されているメンバーだけが載ります。include_unset=trueを付けると、現メンバー全員が載り、未設定の値はnullになります。
使い分けは目的で決まります。
何を知りたいかで既定を変える
設定内容を点検したい
書かれた文章だけを見たいなら、未設定の人は結果に不要です。ページ数も減ります。
設定率や漏れを数えたい
メンバー総数のうち何人が指示文を持つかを出すには、分母が必要です。全員を載せてnullを数えます。
ページ送りは「空のページ」でも終わりではない
ここが一番の落とし穴です。1ページにlimitより少ない件数しか入らないことがあり、0件のページが返ることもあります。サーバーが1リクエストで行う作業量に上限を設けているためで、少ない・空という事実だけでは最後のページとは言えません。
終わりの判定は、next_pageがnullになったことだけで行います。has_moreがtrueの間は続きがあります。件数で止める実装は、取りこぼしの原因になります。
またpageトークンは不透明な文字列です。中身を解釈せず、前の応答のnext_pageを一字も変えずに次の呼び出しへ渡します。形式は予告なく変わる可能性があると明記されています。トークンを切り詰めたり書き換えたりすると、Compliance APIの一覧系エンドポイントではカーソルエラーの400が返ります。
全件を取るスクリプトは、次のように書けます。
org_uuid="91012d09-e48b-438e-a489-1bebfd8fa6f9"
base="https://api.anthropic.com/v1/compliance/organizations/$org_uuid/user_preferences"
page=""
while : ; do
args=(-G "$base" -H "x-api-key: $ANTHROPIC_COMPLIANCE_ACCESS_KEY"
-H "anthropic-version: 2023-06-01" --data-urlencode "limit=100")
[ -n "$page" ] && args+=(--data-urlencode "page=$page")
res=$(curl --fail-with-body -sS "${args[@]}") || exit 1
echo "$res" | jq -c '.data[]' >> preferences.jsonl
page=$(echo "$res" | jq -r '.next_page // empty')
[ -z "$page" ] && break
done.next_page // emptyが空文字になった時点でループを抜けます。件数が0でも、next_pageが入っていれば次を取りに行きます。出力はJSON Lines形式に追記するので、途中で落ちても、取れた分は残ります。
取れた指示文をどう使うか
指示文はユーザーが自由に書いた文章です。ここには、その人の仕事の文脈や、社内の運用ルールが含まれることがあります。取得した時点で、チャット本文と同じ種類の機微データとして扱う前提で設計します。
用途は3つ考えられます。
- 組織のポリシーとの突き合わせ: 禁止している振る舞い(「社外秘は無視して回答する」など)を指示していないか、文字列で検査する
- 利用の実態把握:
include_unset=trueで設定済みと未設定を数え、指示を整備しているメンバーの割合を出す - インシデント調査: 想定外の挙動を訴えたメンバーの個人設定と、Coworkのグローバル指示を確認し、原因が指示文にあるかを切り分ける
3つ目は、挙動の優先順位の理解も要ります。Coworkの指示は、グローバル指示を含む複数の層で重なって効きます。層の関係はCoworkの指示と優先順位にまとめてあります。個人設定の側で読めるのはグローバル指示の層までなので、他の層はその記事の整理と合わせて読む形になります。
調査時は、設定を読む前に会話ログも併せて見るのが自然です。セッション側の取得はCompliance APIでセッションの文字起こしを取得する手順が受け持ちます。このエンドポイントからは個人設定の変更履歴は追えません。変更に関わるイベントがあるかは、Activity Feedのイベント一覧で確かめられます。使い方はCompliance APIのActivity Feedの使い方にあります。
差分を追うときの考え方
user_preferencesには、更新日時のフィールドも、時刻での絞り込みも用意されていません。応答のフィールドは、2つの文字列とuserだけです。
そのため、変化を検知する方法は、定期的に全件を取って前回の結果と比較することになります。比較のキーはuser.idです。メールアドレスは変わりうる値なので、キーにしません。
暗号化の扱いと、取得前に確かめること
個人設定とCoworkのグローバル指示は、顧客管理の暗号鍵(CMEK)を使う組織でも、Anthropic側の鍵で暗号化されるデータとして分類されています。アカウント単位で全組織に共有されるデータであるためです。CMEKを導入している組織で「個人設定も自社の鍵の管理下にある」と前提を置くと、監査説明がずれます。
取得を始める前に、次を確認しておくと手戻りが減ります。
- Compliance APIが組織で有効になっているか。無効だと400になる
- キーが
read:compliance_user_dataを持つか。スコープは作成後に変更できない - 取得したデータの保管先と保持期間が、社内の規程で決まっているか
よくある質問
個人設定の書き換えや削除もAPIでできますか
リファレンスに載っているのは一覧(GET)だけです。個人設定を書き換えたり消したりするエンドポイントは、このページにはありません。Compliance APIで削除できるのは、チャット・ファイル・プロジェクトです。
組織を超えたメンバー全員の設定を、1回の呼び出しで取れますか
取れません。パスに組織のUUIDを含むため、呼び出しは組織ごとです。親組織のキーなら配下の連結組織のUUIDを一覧できるので、組織ごとにループを回し、user.idで重複を除きます。同じアカウントの設定は、どの組織でも同じ文字列で返ります。