Claude Platform Docs
管理推論フック

Inference hooks インテグレーションを開発する

署名付きのInference hooksリクエストを受信して検証し、許可または拒否の判定を返すAIセキュリティサーバーを構築します。

Inference hooks統合とは「AI security server」(AIセキュリティサーバー)のことで、Anthropicが呼び出すHTTPSサービスです。管理対象のリクエストごとに、サーバーは会話のトランスクリプトを含む署名付きのPOSTを受信し、許可または拒否の「verdict」(判定)を返します。このページでは、そのサーバーを構築するためのプロトコルとして、リクエストと判定のスキーマ、署名検証、運用上の取り決めを説明します。

Inference hooksを有効にしてエンドポイントを指定する方法については、Inference hooksを設定するを参照してください。Inference hooksの概要と使用すべき場面については、Inference hooksの概要を参照してください。

最初の判定のやり取りを確認する

最小限の動作する統合は、各リクエストを読み取って許可するだけのサーバーです。以下のいずれかのサーバーを実行し、公開されたhttps:// URLで公開します。たとえば、自分で管理するホスト上のTLS終端リバースプロキシの背後に配置します。リバーストンネルサービスは使用しないでください(リクエストを受信するを参照)。次に、管理者にエンドポイントとして設定して接続をテストしてもらいます。Test connectionの結果に、サーバーが返した許可の判定が表示されます。

# 実行方法: python server.py
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer


class VerdictHandler(BaseHTTPRequestHandler):
    protocol_version = "HTTP/1.1"  # keep the connection open between verdicts

    def do_POST(self):
        # ボディを読み切ります。トランスクリプトは数メガバイトになることがあります。
        self.rfile.read(int(self.headers.get("Content-Length", 0)))
        verdict = b'{"action": "allow"}'
        self.send_response(200)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(verdict)))
        self.end_headers()
        self.wfile.write(verdict)


ThreadingHTTPServer(("", 8000), VerdictHandler).serve_forever()

リクエストを受信する

Anthropicは、管理者が設定したURLにHTTPS POSTを送信します。設定されたURL全体がエンドポイントです。固定のパスサフィックスはないため、サーバーに適した任意のパスを選択してください。

AIセキュリティサーバーは、Anthropicから到達できる場所でホストしてください。つまり、ポート443のhttps:// URLで、パブリックにルーティング可能なホスト上にあり(プライベート、ループバック、キャリアグレードNATの範囲は接続時に拒否されます)、パブリックCAトラストストアに対して検証可能な証明書を持ち、リダイレクトなしで応答する必要があります。ホストにはIPv4アドレスが必要で、ホストがIPv6アドレスも持っている場合でもAnthropicはIPv4アドレスを使用します。ホストがlocalhostまたはIPv6アドレスであるURLは拒否されます。設定されたURLは最終的な宛先である必要があります。リバーストンネルのホスト(ngrokや同様のトンネルサービス)はサポートされていません。Anthropicのネットワークポリシーによってブロックされます。サーバーは自分で管理するドメインでホストしてください。管理者がURLを設定してテストする方法については、Inference hooksを設定するで説明しています。

すべてのリクエストには、以下の固定ヘッダーに加えて、管理者が設定したカスタムリクエストヘッダーと、組織に署名シークレットがある場合は署名を検証するで説明するwebhook-*署名ヘッダーが含まれます。

ヘッダー値
Content-Typeapplication/json
User-Agentanthropic-dlp/1
Accept-Encodingidentity

フックイベントは2種類あり、トップレベルのtypeフィールドで区別されます。プロンプトフレームは、管理対象の推論リクエストごとに1回、推論が始まる前に送信されます。ツール呼び出しフレームは、Validate tool callsが有効になっている組織で、モデルの応答にツール呼び出しが含まれる場合に、そのいずれかが実行される前に送信されます。いずれの場合も、AnthropicはAIセキュリティサーバーが応答するか、判定のタイムアウトが経過するまで待機します。

プロンプトフレーム

リクエストボディは、以下のフィールドを持つJSONオブジェクトです。

フィールド型説明
typestringフックイベント:"prompt"または"tool_call"(ツール呼び出しフレームを参照)。今後、他のイベントタイプが導入される予定のため、認識できない値は適切に処理してください(前方互換性を参照)。
request_idstring相関付けのための、フレームごとの不透明な識別子。webhook-idヘッダーと同じ値です。
tenant_idstring または nullリクエストが属する組織の不透明な識別子。
actorobjectリクエストの帰属先となるプリンシパルで、typeで区別されます(現在送信される値は"user"のみ):id(同じアカウントのリクエスト間で安定したタグ付き識別子)とemail_address(利用可能な場合)。idとemail_addressはどちらもnullになる可能性があります。
sourceobject発信元のアプリケーション:application(ソースの値を参照)。
messagesarray推論時点までの会話のトランスクリプト。コンテンツブロックを参照してください。
session_idstring または null会話の不透明な識別子(存在する場合)。解析しないでください。Claude Codeの場合、これはベストエフォートの、クライアントが主張するセッション識別子です。
modelstring または nullこのリクエストの公開モデル識別子(利用可能な場合)。
metadataobject文字列キーから文字列値への予約済み拡張マップで、現在は空で送信されます。ここから何も必須としないでください。また、存在しない場合、存在する場合、どのようなキーが現れる場合にも対応できるようにしてください。

リクエストボディの例:

{
  "type": "prompt",
  "request_id": "req_abc123",
  "tenant_id": "11111111-1111-1111-1111-111111111111",
  "actor": {
    "type": "user",
    "id": "user_01AbCdEfGhIjKlMnOpQrStUv",
    "email_address": "alice@example.com"
  },
  "source": {
    "application": "claude-ai"
  },
  "session_id": "22222222-2222-2222-2222-222222222222",
  "model": "claude-sonnet-4-5",
  "messages": [
    {
      "role": "user",
      "content": [
        {
          "type": "text",
          "text": "Summarize the attached report."
        },
        {
          "type": "attachment",
          "file_name": "q2-report.pdf",
          "media_type": "application/pdf",
          "size_bytes": 48213,
          "text": "Q2 revenue grew 14% quarter over quarter..."
        }
      ]
    }
  ],
  "metadata": {}
}

コンテンツブロック

messagesの各エントリには、userまたはassistantのrole(ツールの結果は、公開Messages APIのコンテンツモデルに合わせてuserロールの下に表示されます)と、typeで区別されるブロックのcontent配列があります。

ブロックのtypeフィールド
texttext:テキストコンテンツ。
tool_useid:対応するツール結果が参照する識別子。tool_name:ツールの名前。input:モデルがツールに渡した引数。 tool_info:ツール呼び出しフレームにのみ含まれ(それ以外では省略され、nullになることはありません)、ツールを実行または提供する主体を示すオブジェクト。ツール呼び出しフレームを参照してください。
tool_resultcontent:ツールの出力をテキストとしたもので、各部分は改行で結合されます。画像などのバイナリ部分はプレースホルダーマーカーに置き換えられ、生のバイトが送信されることはありません。is_error:ツール呼び出しが失敗したかどうか。tool_name:ツールの名前。これにより、ポリシーは以前のブロックを相互参照することなくツールの識別情報に基づいて条件を設定できます。tool_use_id:対応するtool_useブロックのid。
attachmentfile_name:元のファイル名またはパス。media_type:添付ファイルのメディアタイプ。size_bytes:元のファイルのサイズ。text:利用可能な場合の添付ファイルのテキストコンテンツ(抽出されたドキュメントのテキスト、音声の文字起こし、リンクのメタデータなど)。添付ファイルの生のバイトが送信されることはありません。

type、textブロックのtext、tool_resultブロックのcontentとis_errorを除き、これらのフィールドはいずれも値が不明な場合にnullになる可能性があります。たとえば、画像はfile_nameとtextがnullに設定されたattachmentブロックとして届きます。

認識できないtypeを持つブロックは、前方互換性のための追加です。保証されるフィールドはtypeのみです。ポリシーは存在する他のフィールドを検査してもかまいませんが、認識できないタイプを理由にリクエストを拒否してはなりません。

トランスクリプトの内容

トランスクリプトは、推論時点までの会話をエンドユーザーが見ているとおりに表したものです。トランスクリプトのテキスト、ツール呼び出しとその結果、添付ファイルから抽出されたテキスト、以前のターンが含まれます。システムプロンプト、ツール定義、Anthropic内部のコンテキスト、Claudeの非表示の推論、生のファイルバイトは含まれません。

すべてのブロックが除外されたターンは丸ごと省略されます。そのため、userとassistantが厳密に交互に並ぶことを前提にしないでください。

トランスクリプトは切り詰められずに送信されます。そのため、大きな添付ファイルを含む長い会話では、リクエストボディも大きくなります。実際には、モデルのコンテキストウィンドウによってボディは約10 MB未満に収まりますが、プロトコル上は最大64 MiBまで許容されます。一般的なデフォルト値の中には、これよりはるかに小さいものがあります。たとえば、nginxのclient_max_body_sizeは1 MB、Expressのexpress.json()は100 kBです。ボディが拒否されるとWebhook障害として扱われます。そのため、障害時の処理がAllow the requestの場合、サイズの大きすぎるプロンプトは検査されないままモデルに届きます。

ソースの値

source.applicationは閉じた列挙型ではなく、オープンな文字列です。一般的な値はclaude-ai、claude-code、coworkです。接続テストと自動的なサーキットブレーカーの復旧チェックではconfig-testが使用されます。新しい値が現れる可能性があり、サーバーは認識できない値を理由にリクエストを拒否してはなりません。

source.applicationは信頼境界ではなく、参考程度のルーティングメタデータとして扱ってください。セキュリティ上重要なポリシー判断をこれだけに依存させないでください。

ツール呼び出しフレーム

Claudeがツール呼び出しを生成すると、Anthropicはそれらを列挙した1つのツール呼び出しフレームを送信します。claude.ai独自のツールの一部への呼び出しは省略される場合があり、ツール呼び出しがすべて省略されたものだけである応答では、ツール呼び出しフレームは生成されません。利用可能範囲を参照してください。1つの判定がフレーム全体に適用されます。一部のツール呼び出しを許可し、他を拒否することはできません。このフレームは、プロンプトフレームと同じエンドポイントに、同じヘッダー、署名、トップレベルフィールドで送信されます。Claudeがコード実行ツールで実行するコードによって行われるツール呼び出しも、同じ方法で、別のツール呼び出しフレームとして、実行前に送信されます。

プロンプトフレームとは次の3点が異なります。

  • typeは"tool_call"です。
  • messagesには最新のメッセージ、つまりClaudeが生成したばかりのassistantメッセージのみが含まれます。これには任意のtextブロックと、フレームが列挙するツール呼び出しごとに1つのtool_useブロックが、モデルが生成した順序で含まれます。それ以前の会話は、そのモデル呼び出しの前に送信されたプロンプトフレームに含まれていたため省略されます。プロトコルが今後その前に以前のメッセージを追加する可能性があるため、messagesの最後のエントリを読み取ってください。
  • 各tool_useブロックには、ツールを実行または提供する主体を示すtool_infoオブジェクトが含まれます。

session_idが設定されている場合、両方のフレームで同じ値になります。ツール呼び出しフレームには独自のrequest_idがあり、プロンプトフレームのものと同様に不透明です。

tool_infoは、ツールが何にアクセスできるかではなく、ツールを実行または提供する主体を示します。これはtypeフィールドで区別される4種類のいずれかであり、各種類には独自のフィールドがあります。Anthropicは、以下の種類のうちツールに当てはまる最初のものを送信します。新しい種類が現れる可能性があります。認識できないtypeは受け入れ、そのような種類についてはtypeのみに依存してください。

該当しないオプションのフィールドは省略され、nullになることはないため、tool_infoが単に{"type": "client"}である場合もあります。tool_nameはツールを定義した者が選択し、サーバーのtoolset_nameはリクエストを作成した者が選択するため、どちらも信頼境界として扱わないでください。

プラットフォームツール

プラットフォームツールとは、Web検索やコード実行など、Claude API自体がリクエストを処理する際に実行するツールです。

フィールド存在説明
type常に"platform"
tool_type常にweb_search_20250305などの、ツールのバージョン付きタイプ。完全一致で照合し、名前や日付を解析して取り出さないでください。
toolset_nameオプションツールが属するツールのグループ。

アプリケーションツール

アプリケーションツールとは、claude.ai独自のツールなど、リクエストを行うAnthropicアプリケーション自体が提供するツールです。

フィールド存在説明
type常に"application"
toolset_nameオプションツールが属するツールのグループ。

claude.ai自体が提供するWeb検索ツールに対するtool_useブロック:

{
  "type": "tool_use",
  "id": "toolu_01LmNoPqRsTuVwXyZaBcDeFg",
  "tool_name": "web_search",
  "input": {
    "query": "comparable deals for unannounced 4.2B USD Acme Corp acquisition"
  },
  "tool_info": {
    "type": "application"
  }
}

claude.aiはこのツールを常にweb_searchと名付けるわけではないため、名前だけで照合しないでください。inputには常に検索クエリが含まれ、他のフィールドが含まれる場合もあります。

サードパーティツール

サードパーティツールとは、claude.aiのコネクタや、リクエストがmcp_serversで指定するMCPサーバーなど、Anthropicが把握しているサーバー上のツールです。これはAnthropicがそのサーバーを審査したことを意味するものではありません。

フィールド存在説明
type常に"third_party"
toolset_nameオプションリクエストがサーバーに付けた名前。
originオプションサーバーのURLのスキーム、ホスト、およびデフォルト以外のポート。localhostを含む、プライベートまたはローカルのアドレスである場合があります。originがない場合は、安全であることではなく、不明であることを意味します。
verified_originoriginがある場合は常にAnthropicのサーバー自体がそのサーバーに接続する場合にのみtrueになります。falseは、Anthropicが確認していないオリジンとして扱ってください。

リクエストがmcp_serversでcrmと名付けたMCPサーバー上のツールに対するtool_useブロック:

{
  "type": "tool_use",
  "id": "toolu_01GhIjKlMnOpQrStUvWxYzAb",
  "tool_name": "crm_search",
  "input": {
    "query": "accounts renewing in Q4"
  },
  "tool_info": {
    "type": "third_party",
    "toolset_name": "crm",
    "origin": "https://mcp.crm.example.com",
    "verified_origin": true
  }
}

クライアントツール

クライアントツールとは、それ以外のすべてのツールで、通常はClaudeを呼び出すアプリケーションが実行するツールです。bashやコンピューター使用など、Anthropicが定義し、呼び出し元のアプリケーションが実行するツールもクライアントツールであり、tool_typeにバージョン付きタイプが含まれます。リクエストで宣言されていないツールへの呼び出しも"client"になります。

ローカルMCPサーバーなど、Claude Codeがユーザーのコンピューターから直接接続するMCPサーバー上のツールは、クライアントツールです。そのtool_infoは{"type": "client"}であり、tool_nameはClaude Codeが付けた名前で、mcp__<server>__<tool>の形式になります。

拒否すると、Claude Codeが実行する前に呼び出しが停止されます。Claude Codeとローカルサーバー間のやり取りはAnthropicを経由しないため、AIセキュリティサーバーがツールの結果を確認できるのは、Claude Codeがそれを送り返した場合のみです。その場合、そのテキストは次のプロンプトフレームのtool_resultブロックに含まれます。

フィールド存在説明
type常に"client"
tool_typeオプションAnthropicがツールを定義している場合の、bash_20250124などのツールのバージョン付きタイプ。完全一致で照合し、名前や日付を解析して取り出さないでください。
toolset_nameオプションbrowserなど、ツールが属するツールのグループ。

呼び出し元のアプリケーションが宣言するツールに対するtool_useブロック:

{
  "type": "tool_use",
  "id": "toolu_01AbCdEfGhIjKlMnOpQrStUv",
  "tool_name": "read_file",
  "input": {
    "path": "reports/q3.txt"
  },
  "tool_info": {
    "type": "client"
  }
}

Anthropicが定義し、呼び出し元のアプリケーションが実行するbashに対するtool_useブロック:

{
  "type": "tool_use",
  "id": "toolu_01HiJkLmNoPqRsTuVwXyZaBc",
  "tool_name": "bash",
  "input": {
    "command": "ls -la reports/"
  },
  "tool_info": {
    "type": "client",
    "tool_type": "bash_20250124"
  }
}

判定を返す

どちらの結果の場合も、HTTP 200とJSONの判定ボディで応答してください。actionフィールドで区別されます。リクエストを許可するには:

{
  "action": "allow"
}

拒否するには:

{
  "action": "deny",
  "deny_reason": "This prompt appears to contain customer payment card data, which your organization's policy does not allow.",
  "reference_id": "scan_01HXPT4R9V"
}
フィールド制約セマンティクス
action"allow"または"deny"。必須allowは推論の続行を許可し、denyは推論を拒否します。
deny_reasonstring または null。最大500文字で、それより長い値は切り詰められますactionがdenyの場合にエンドユーザーに表示されます。allowの場合は無視されます。
reference_idstring または null。[A-Za-z0-9._:/-]の文字で最大50文字この評価に対する独自の識別子。拒否のinference_hooks_request_denied コンプライアンスアクティビティに記録され、エンドユーザーに表示されることはありません。不透明な値にしてください。リクエストの内容や個人データを含めないでください。

書式の問題によって拒否が破棄されることはありません。サイズ超過のdeny_reasonは切り詰められ、不正な形式のreference_idは通知なしに破棄され、actionは引き続き尊重されます。

逆は成り立ちません。解析可能な判定を伴うHTTP 200以外のものはすべてWebhook障害であり、判定の代わりに組織の障害時の処理が適用されます。特に次の点に注意してください。

  • エラーステータスで拒否を示さないでください。200以外の応答は拒否ではなく失敗です。
  • allowまたはdeny以外のaction値は、Webhook障害として扱われます。

Anthropicは応答ボディを最大64 KiBまで読み取り、ボディは非圧縮である必要があります。リダイレクトは追跡されず、Cookieは無視されます。判定ボディ内の不明なフィールドは無視されるため、ここで説明するフィールドに加えて、より豊富なオブジェクトを返すことができます。

ツール呼び出しフレームも同じ判定ボディを受け取り、このセクションのすべてのルールがそのまま適用されます。allowはツール呼び出しの実行を許可して応答を続行させ、denyはそれらすべてを停止し、deny_reasonを含め、拒否されたプロンプトと同じエラーで応答を終了します。最初のツール呼び出しの前に配信されたテキストは取り消されません。

署名を検証する

リクエストは、Standard Webhooks仕様に従い、3つのヘッダーを使って署名されます。Anthropicはヘッダー名を小文字で送信しますが、プロキシによって大文字・小文字が変更される場合があります。そのため、ヘッダーは大文字と小文字を区別せずに参照してください。

ヘッダー内容
webhook-idこの配信の一意の識別子。ボディのrequest_idと同じ値です。冪等性キーとして、また署名対象ペイロードの最初の要素として使用します。
webhook-timestampリクエストが署名された時刻。10進数文字列で表したUnix時間(秒)です。サーバーの時計と前後どちらかに5分以上ずれているタイムスタンプは拒否してください。
webhook-signatureスペース区切りの1つ以上のv1,<base64>値。各値は{webhook-id}.{webhook-timestamp}.{raw body bytes}に対するHMAC-SHA256です。定数時間比較を使い、いずれかの値が自分で計算した値と一致すればリクエストを受け入れます。

検証のバグの大半は、次の2つの点が原因です。

  • 生のバイトを検証する。 JSONの解析や再エンコードを行う前に、受信したとおりのボディに対してHMACを計算してください。
  • シークレットは標準のbase64デコーダーでデコードする。 署名シークレットはwhsec_プレフィックスの後ろの値で、ヘッダー内の署名と同じく標準のbase64アルファベット(+と/)でエンコードされています。URLセーフなデコーダーを使うと、シークレットに+や/が含まれる場合に誤ったキーバイトが導出されます。そして、ほとんどのシークレットにはこれらの文字が含まれます。

組織に署名シークレットがある場合、Anthropicが送信するリクエストはすべて署名されます。接続テストも例外ではありません。セットアップフローでは、最初のテストの前にシークレットが生成されるためです。Inference hooksを有効にするにはシークレットが必要なので、署名のないリクエストはすべて拒否してください。

ただし、例外が1つあります。シークレットが必須になる前にInference hooksを有効にした組織では、管理者がシークレットを生成するまで署名のないリクエストが送信され続けます。署名のないリクエストは、シークレットが存在することを管理者が確認するまでの間だけ受け入れ、その後は拒否してください。

シークレットのローテーションは即座に切り替わります。ただし、以前のシークレットで署名されたリクエストが、その後約1分間届く可能性があります。すでに送信中のリクエストも同様です。これらの遅れて届くリクエストが拒否されないように、切り替え期間中はAIセキュリティサーバーで両方のシークレットによる署名を受け入れてください。

以下のサンプルはサーバー実装です。AIセキュリティサーバーは単発のリクエストではなく長時間稼働するHTTPSサービスであるため、shellタブはありません。各サンプルは、その言語の標準ライブラリのみを使用しています。Standard Webhooksプロジェクトでは、ほとんどの言語向けに検証ライブラリも公開されています。

import base64
import hashlib
import hmac
import time

TOLERANCE_SECONDS = 300


def verify(secret: str, headers: dict[str, str], body: bytes) -> bool:
    """Return True if the body was signed by Anthropic for this organization.

    Anthropic sends header names in lowercase, but proxies are free to
    re-case them, so normalize the lookup to lowercase.
    """
    lowercased = {name.lower(): value for name, value in headers.items()}
    try:
        message_id = lowercased["webhook-id"]
        timestamp = lowercased["webhook-timestamp"]
        signatures = lowercased["webhook-signature"]
    except KeyError:
        return False  # unsigned request: not from Anthropic

    try:
        signed_at = int(timestamp)
    except ValueError:
        return False
    if abs(time.time() - signed_at) > TOLERANCE_SECONDS:
        return False  # replayed, or the clocks disagree

    try:
        key = base64.b64decode(secret.removeprefix("whsec_"), validate=True)
    except ValueError:
        return False  # misconfigured secret: reject rather than crash

    payload = f"{message_id}.{timestamp}.".encode() + body
    expected = b"v1," + base64.b64encode(
        hmac.new(key, payload, hashlib.sha256).digest()
    )

    # バイト列で比較します。str に対する compare_digest は非 ASCII 入力で例外を送出します。
    return any(
        hmac.compare_digest(expected, candidate.encode())
        for candidate in signatures.split()
    )

運用上の動作

タイムアウトとリトライ

管理者は、判定のタイムアウトを1~10,000msの範囲で設定します(デフォルトは5,000ms)。この時間枠は、接続、TLSハンドシェイク、リクエスト、応答を含むやり取り全体に適用されます。同じタイムアウトがツール呼び出しフレームにも適用されます。

Anthropicは、接続の試行が失敗した場合にのみ、100msの遅延の後に1回だけリトライします。リトライは同じタイムアウトの時間枠を共有し、同じwebhook-idと同じ署名を持ちます。AIセキュリティサーバーが応答した後は、やり取りがリトライされることはありません。

Webhook障害

次のものはすべてWebhook障害として扱われます。

  • タイムアウト
  • 200以外のステータス(リダイレクトを含む)
  • 解析できない、またはサイズが大きすぎるレスポンスボディ
  • 到達できないエンドポイント

Webhook障害が拒否として扱われることはありません。代わりに、組織の障害時の処理の設定によって、影響を受けたリクエストをブロックするか、検査なしで続行するかが決まります。

サーキットブレーカー

AIセキュリティサーバーに起因するWebhook障害が継続すると、「circuit breaker」(サーキットブレーカー)が作動して適用が停止されます。Anthropicはサーバーへの接続を停止し、すべてのリクエストに障害時の処理が適用されます。

作動から10分後以降、Anthropicはサーバーが復旧したかどうかを確認します。最大で約1分に1回、Test connectionが送信するものと同じ合成テストリクエスト(source.applicationはconfig-test)をサーバーに送信します。このリクエストは他のリクエストと同様に署名され、ユーザーのコンテンツは含まれません。通常どおり応答してください。有効な判定(許可または拒否)が返されるとブレーカーがリセットされて適用が再開されます。Webhook障害の場合はブレーカーが作動したままとなり、チェックが継続されます。管理者はいつでもブレーカーをリセットでき、管理者による設定変更によって自動チェックは停止されます。サーキットブレーカーを参照してください。

プロンプトフレームとツール呼び出しフレームは1つのサーキットブレーカーを共有し、どちらの失敗もカウントされます。

各作動は、Activity Feedにinference_hooks_circuit_breaker_trippedアクティビティとして、作動ごとに1件記録されます。ブレーカーが作動している間は、リクエストごとのInference hooksアクティビティは記録されないため、作動アクティビティがフィード上で作動期間を示す唯一の記録となります。

レイテンシ

適用を行うと、組織内のすべての管理対象リクエストの「latency」(レイテンシ)に、AIセキュリティサーバーのラウンドトリップが加わります。Validate tool callsが有効な場合、ツール呼び出しフレームを生成する応答もその判定を待機します。これはシャドウモードでも同様です。判定は高速に保ち、大規模な組織に展開する前にサーバーの負荷テストを行ってください。

送信元IPアドレス

AIセキュリティサーバーへのリクエストは160.79.106.0/24から送信されます。これは、Anthropicが公開している送信IP範囲の一部です。許可リストにはこのブロックを追加してください。同じページに記載されている受信IP範囲にはこのブロックが含まれないため、そちらは使用しないでください。許可リストを使うとサーバーの露出を減らせますが、署名検証の代わりにはなりません。このブロックには、Inference hooks以外のAnthropicの送信トラフィックも含まれるためです。

前方互換性

プロトコルは、正しく記述されたサーバーを壊すことなく拡張されます。サーバーは次のものを無視する必要があります。

  • いずれかのフレームの不明なトップレベルフィールド。
  • metadata内の不明なキー。
  • 新しいsource.application値。
  • 新しいactor.type値。actorはtypeで区別される共用体であり、現在送信される種類は"user"のみです。将来の種類ではtypeが存在することのみが保証されます。
  • 認識できないtypeを持つコンテンツブロック。
  • userまたはassistant以外のroleを持つメッセージ(今後の改訂で追加される可能性があります)。

認識できないブロックタイプやフィールドを理由にリクエストを拒否しないでください。既知のフィールドを読み取り、残りはスキップしてください。

今後、他のフックイベントタイプが導入される予定です。新しいイベントタイプは、フィールドをスキップするだけでは処理できない追加です。リクエストには引き続き判定が必要です。トップレベルのtypeが認識できない値である場合は、エラーステータスではなく許可の判定を返してください。エラー応答はWebhook障害であり、失敗が継続するとサーキットブレーカーが作動します。

統合を設計する

本番環境のAIセキュリティサーバーでは、通信プロトコル以外にもいくつかの設計上の判断が必要です。

webhook-idで重複を排除する。 webhook-idヘッダーは配信ごとに一意で、ボディのrequest_idと同じ値です。接続失敗時のリトライでも同じ値が使われるため、冪等性キーとして使用できます。判定を記録する場合は、この値をレコードのキーにしてください。

判定を記録し、拒否と突き合わせる。 返した各判定を、そのreference_idとともに保存してください。すべての拒否は、サーバーが返したreference_idを含むinference_hooks_request_deniedコンプライアンスアクティビティとして記録されます。これにより、Activity Feedの拒否を、自社システム内の対応するレコードと突き合わせることができます。

常に許可するサーバーでアーカイブする。 トランスクリプトを制限せずにリアルタイムで取得するには、無条件に{"action": "allow"}を返し、応答した後にフレームを保存します。これは、Compliance APIをポーリングする方法に代わるプッシュ型の手段です。保存する前に応答することで、サーバーとのやり取りがユーザーのクリティカルパスに影響しなくなります。

deny_reasonはエンドユーザー向けに書く。 返したテキストは、リクエストがブロックされたときにユーザーに表示されます(500文字で切り詰められます)。自社チームにしか理解できないスキャナーのコードを出力するのではなく、どの種類のコンテンツを削除すべきかなど、ユーザーが何を変更すればよいかを伝えてください。

次のステップ

Inference hooksを有効にし、エンドポイントを接続してテストし、適用、障害時の処理、展開を制御します。

Inference hooksとは何か、判定のやり取りの仕組み、使用すべき場面について説明します。

Was this page helpful?