Claude Media
Claude APIの安全対策 — 自社サービスに組み込む前のユーザーID・AI開示・段階的ガード

Claude APIの安全対策 — 自社サービスに組み込む前のユーザーID・AI開示・段階的ガード

自社サービスにClaude APIを組み込む前に決めておく安全策を、ユーザーIDのハッシュ化、AI開示、警告から停止までの段階、入力の事前審査に分けて解説します。

自社サービスにClaude APIを組み込むなら、公開前に決めておきたい安全策は4つあります。APIコールごとのID保存、利用者IDのハッシュ化、AI利用の開示、違反ユーザーへの段階的な対応です。これらは利用規約とUsage Policyを守るための提案として、ヘルプセンターが段階別に示しています。

提案は「入れたほうがよい順」に並んでいます。この記事では、その並びを自社サービスの設計に置き換え、IDの渡し方とハッシュの作り方を具体例で示します。

安全策は「基本・中間・高度・網羅」の4段で考える

ヘルプセンターの「API safeguards tools」は、安全策を4つの段に分けています。守れなかった場合は、アクセスの停止や終了につながりうると冒頭に書かれています。

段階

Anthropicが示す安全策の4段

  • 基本

    APIコールごとのID保存、利用者へのID付与、サインアップ必須化、許可される用途の周知、違反の繰り返しへの警告・スロットル・停止。

  • 中間

    利用者とClaudeのやり取りを、限られたプロンプトや自社の知識コーパスに絞る設計。

  • 高度

    Claudeでコンテンツモデレーションを行う。モデレーションAPIで、Claudeに送る前の入力を審査する。

  • 網羅

    モデレーションで有害と判定されたプロンプトを人が確認する社内の仕組み。違反率の高い利用者を制限または排除する。

全部を初日から入れる必要があるとは書かれていません。基本の段は、公開前にほぼ追加費用なく入れられるものです。ここを飛ばして高度な審査だけを入れると、問題が起きたときに「誰の、どのコールか」を特定できません。

基本の段 — 起きたときに追跡できる状態を作る

コールごとにIDを残す

基本の最初の項目は、APIコールに紐づくIDを自社側に保存することです。違反の疑いが出たとき、該当するやり取りを自社のシステムから探し出せるようにするための項目です。

実装としては、自社で採番するリクエストIDと、返されるレスポンスのIDの両方を、自社のログに並べて持つ形が考えられます。

利用者にIDを振り、ハッシュにして渡す

2つ目は、利用者にIDを割り当てておくことです。誰が規約違反をしているかを追えれば、サービス全体を止めずに、その人だけに対処できます。

Anthropicへ渡すかどうかは事業者の判断に任されています。ただし渡せば、違反箇所をより正確に特定できると書かれています。渡す場合は、利用者のプライバシーを守るため、暗号学的にハッシュ化したIDにします。

渡し先は、Messages APIのリクエストの metadata.user_id です。APIリファレンスでは、この項目の説明は次のとおりです。

  • uuid、ハッシュ値、その他の不透明な識別子にする
  • Anthropicが不正利用の検知に使うことがある
  • 氏名・メールアドレス・電話番号のような、個人を識別できる情報は入れない
  • 最大512文字

ヘルプセンターの「ハッシュ化」とAPIリファレンスの「不透明な識別子」は、同じ方向を向いた要求です。生のメールアドレスをそのまま入れるのは、どちらにも反します。

ハッシュの作り方の例

メールアドレスをSHA-256にかけるだけの方法は、避けたほうが無難です。メールアドレスは推測しやすい文字列なので、候補を総当たりすれば元の値を当てられる場合があります。これは一般的な暗号の性質による注意点です。

次の例は、自社だけが持つ秘密鍵を使うHMACで、利用者の内部IDからハッシュを作る形です。鍵の管理方法とハッシュ関数は自社で決めて固定します。

import hashlib
import hmac
import os
 
import anthropic
 
client = anthropic.Anthropic()
 
# 自社だけが持つ鍵。環境変数や秘密情報の管理サービスから読む
SECRET = os.environ["USER_ID_HASH_KEY"].encode()
 
 
def anonymous_user_id(internal_user_id: str) -> str:
    """内部の利用者IDから、Anthropicに渡す不透明なIDを作る"""
    return hmac.new(SECRET, internal_user_id.encode(), hashlib.sha256).hexdigest()
 
 
message = client.messages.create(
    model="claude-sonnet-5-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "こんにちは"}],
    metadata={"user_id": anonymous_user_id("member-10293")},
)

渡すのは内部の会員番号のような、氏名やメールアドレスと一対一では結び付かない値からにします。鍵を変えると同じ利用者でもIDが変わるので、一度決めたら固定し、鍵のローテーションが必要になるときは、変更前後のIDの対応表を自社側に残します。

利用者の識別を、IDを自前で持つのでなくAnthropic側のプロファイルに任せる方法もあります。ヘッダーでリクエストを紐づける仕組みはUser Profilesの手順にまとめています。

個人情報保護の観点でIDを見る

日本の個人情報保護法で、個人情報は「特定の個人を識別できるもの」と定義され、他の情報と容易に照合でき、それによって特定の個人を識別できるようになるものも含まれます。

自社の中では、利用者IDは会員データベースと容易に照合できます。つまり自社にとってのIDは、個人情報として扱う前提で管理するのが安全です。Anthropicに渡すのは、その照合ができない形、つまり自社の鍵がなければ元に戻せない値にする、というのが「ハッシュ化して渡す」の実務上の意味になります。

渡してよい値と避ける値を並べると次のとおりです。

IDの候補Anthropicへ渡す形として
メールアドレス・電話番号・氏名Anthropicへ渡す形として渡さない(APIリファレンスが明示)
会員番号をそのままAnthropicへ渡す形として避けたほうが無難(自社外から他の情報と結び付く恐れ)
会員番号を鍵付きハッシュにした値Anthropicへ渡す形として設計例として妥当
ランダムに採番したUUID(対応表は自社保管)Anthropicへ渡す形として設計例として妥当

利用者がClaudeへの入力に個人情報を書いてしまう側の話は別の論点です。要配慮個人情報の扱いは要配慮個人情報をClaudeに入力してよいかで扱っています。

サインアップ・用途の周知・段階的な対応

残りの3項目は、サービス側の仕組みです。

  • Claudeを使う前に、自社のプラットフォームでアカウント登録を求めることを検討する
  • 許可される用途を、利用者に理解してもらう
  • 利用規約とUsage Policyに繰り返し違反する利用者を、警告・スロットル・停止する

「警告・スロットル・停止」は、重い順に並べる使い方ができます。一度の違反でいきなり停止せず、繰り返した人だけを段階的に制限するという読み方です。ここでスロットルとは、利用できる量や頻度の制限を指します。段階を何回の違反で上げるかは、自社の用途に合わせて決める設計項目です。

段階を決めるときの組み立て方の一例は次のとおりです。

手順

違反への対応を段階にする

  1. 1

    検知した事実を記録する

    どの利用者の、どのコールが問題になったかを、保存したIDから引けるようにします。

  2. 2

    初回は警告する

    許可されない用途であることを、画面とメールで伝えます。

  3. 3

    繰り返したらスロットルする

    利用できる量や頻度を絞ります。

  4. 4

    なお続くなら停止する

    アカウントの利用を止め、再開の条件を決めておきます。

この4段は設計例で、ヘルプセンターの手順ではありません。記載は「繰り返し違反する利用者を警告・スロットル・停止する」までです。

外向けのサービスでは、AI利用を開示する

もう1つのヘルプセンター記事「Usage Policyを破らないために、Claude APIで製品を出す前に何をすべきか」は、安全は共有責任だとしたうえで、追加の推奨を3つ挙げています。

  1. Claudeをコンテンツモデレーションのフィルタとして使い、違反を見つけて防ぐ
  2. 外向けの製品では、利用者にAIシステムと対話していることを開示する
  3. 機微な情報や意思決定が絡む場合は、利用者に届く前に有資格者が内容を確認する

その前提として、Anthropic側の安全機能は完全ではなく、事業者は「第二の防衛線」だと書かれています。

開示は「チャット画面の初期表示」に置ける

外向けのチャットでは、各セッションの冒頭かプロダクトのUI上で、AIと対話していることを示すのが最低要件です。チャットの冒頭表示や回答の下の注記が、その置き場所になります。未成年が相手の製品には追加の要件があり、未成年向けサービスの安全対策に書いています。

有資格者の確認が要る線を決める

3つ目の「有資格者による確認」は、どこからが機微なのかを自社で線引きする項目です。Usage Policyで高リスク用途に挙がっている領域は、その線引きの手がかりになります。改定の内容はUsage Policy 2026年改定に整理しています。

中間から網羅 — Claudeの外側に足す層

Anthropic側の安全機能と、自社で足す層

Anthropicは、APIの入力と出力に対してリアルタイムの安全機能をデフォルトで動かしています。追加で有効化する設定のフィルタはありません。自社でモデレーション層を足したい場合は、開発者ドキュメントのモデレーションのガイダンスを参照するよう書かれています。

入力を事前審査する

高度の段にある「Claudeに送る前に入力を審査する」について、APIドキュメントのjailbreak対策のページに具体策があります。軽量なモデルで入力を事前に分類する「無害性スクリーン」です。構造化出力で結果を単純な判定に絞ります。

分類のリクエスト自体を、モデルの安全分類器が拒否することがあります。ドキュメントは、stop_reason が refusal の応答を、有害という判定として扱うよう書いています。

import anthropic
 
client = anthropic.Anthropic()
 
 
def is_blocked(user_text: str) -> bool:
    """事前審査の呼び出し例。判定の詳細は自社のポリシーに合わせて書く"""
    resp = client.messages.create(
        model="<軽量モデルのID>",
        max_tokens=16,
        system="入力が自社サービスの利用規約に反するなら BLOCK、そうでなければ OK とだけ答える",
        messages=[{"role": "user", "content": user_text}],
    )
    if resp.stop_reason == "refusal":
        return True  # 拒否は有害判定として扱う
    return resp.content[0].text.strip().upper().startswith("BLOCK")

上の断片は、ドキュメントの考え方を最小限に縮めた例示です。ドキュメントの例は構造化出力を使っています。<軽量モデルのID> は、自社で使う軽量モデルのIDに置き換えてください。

人が見る層を最後に置く

網羅の段は、機械の判定を人が見る社内の仕組みです。判定を受けた利用者を、人が確認してから制限や排除に進みます。判定の誤りで利用者を止める事故を避ける役割もあります。人の確認は、モデレーションの判定が積み上がる、利用者数の多いサービスで効いてきます。

Bedrock経由で使う事業者には、非公開のS3バケットを有効にして、プロンプトと応答を自社の評価のために保存する提案があります。Bedrock以外の経路には、この項目はありません。

自社サービスの規模別に、どこまで入れるか

次の表は、公開前にどの段まで入れるかを決めるための目安です。

サービスの形公開前に入れる段理由
社内ツール(従業員のみ)公開前に入れる段基本のうちID保存と周知理由利用者が限られ、アカウントが既にある
会員向けの外部サービス公開前に入れる段基本すべて+AI開示理由外向けで、利用者の特定が必要
不特定多数が使うチャット公開前に入れる段基本から高度まで+人の確認の入口理由悪用の試みが増える
医療・法律・金融の判断に近い公開前に入れる段上記+有資格者の確認理由意思決定への影響が大きい
この記事を共有:XはてブLinkedIn