Claude Media
Compliance APIのuser_preferencesでメンバーの個人設定を取得する

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になります。

使い分けは目的で決まります。

くらべる

何を知りたいかで既定を変える

既定のまま

設定内容を点検したい

書かれた文章だけを見たいなら、未設定の人は結果に不要です。ページ数も減ります。

include_unset=true

設定率や漏れを数えたい

メンバー総数のうち何人が指示文を持つかを出すには、分母が必要です。全員を載せて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つ考えられます。

  1. 組織のポリシーとの突き合わせ: 禁止している振る舞い(「社外秘は無視して回答する」など)を指示していないか、文字列で検査する
  2. 利用の実態把握: include_unset=trueで設定済みと未設定を数え、指示を整備しているメンバーの割合を出す
  3. インシデント調査: 想定外の挙動を訴えたメンバーの個人設定と、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で重複を除きます。同じアカウントの設定は、どの組織でも同じ文字列で返ります。

この記事を共有:XはてブLinkedIn