Claude Media
Claude Codeのclassifier_verdict — tool_decisionで分類器判定を見分ける

Claude Codeのclassifier_verdict — tool_decisionで分類器判定を見分ける

tool_decisionに加わったclassifier_verdict・permission_mode・classifier_categoryで、auto modeの分類器の判定と権限ルールの判定を分けて集計する方法です。

tool_decision イベントの classifier_verdict と permission_mode を見れば、auto modeの分類器が下した判定を、権限ルールによる判定から分けて数えられます。どちらもv2.1.301で加わった属性です。OTEL_LOG_TOOL_DETAILS=1 のときは classifier_category も付き、分類器のブロックが当たった組み込みルールの名前が分かります。

以前は何が区別できなかったのか

tool_decision は、ツールの権限判定が出るたびに記録されるイベントです。decision は accept か reject、source は判定の出どころを表します。

問題は source の config でした。監視ドキュメントでは、config を次のような判定の総称として説明しています。

  • プロジェクト設定、個人設定、管理ポリシーのallow・denyルール
  • --allowedTools と --disallowedTools
  • 有効な権限モード
  • 同じセッションで以前に出した許可
  • 本質的に安全なツール

そのうえで「どの出どころが一致したかはイベントからは分からない」と明記されています。

source が取る値は全部で6つあります。分類器の判定と、人やフックの判定を取り違えないための一覧です。

source出るとき扱い
config出るとき設定、ルール、権限モードなどで自動的に決まったとき扱い上記の総称
hook出るときPreToolUse か PermissionRequest のフックが判定を返したとき扱いフックの判定
user_permanent出るときプロンプトで「Yes, and don't ask again」を選んだとき扱いaccept
user_temporary出るときプロンプトで「Yes」を選んだとき。セッション内の許可を選んだときも扱いaccept
user_abort出るとき回答せずにプロンプトを閉じたとき扱いreject
user_reject出るときプロンプトで「No」を選んだとき扱いreject

user_* はどれも、人がプロンプトで答えた結果です。auto modeは通常プロンプトを出さずに分類器が決めるので、user_* が並ぶのは、分類器の一時停止でプロンプトに戻った後(後述)など、人が答えた場面に限られます。hook も分類器ではなくフックの判定です。分類器の判定を数えるときは、この2系統を混ぜないでください。

auto modeでは、ルールに当たらなかった操作を分類器が審査します。それでも分類器の判定は、ルールの判定と同じ config に埋もれて見えませんでした。

v2.1.301の更新履歴には、2行が加わっています。

属性更新履歴での説明付く条件
classifier_verdict更新履歴での説明分類器の判定を表す付く条件更新履歴に条件の記載なし
permission_mode更新履歴での説明判定時の権限モード付く条件更新履歴に条件の記載なし
classifier_category更新履歴での説明分類器のブロックが当たった組み込みルールの名前付く条件OTEL_LOG_TOOL_DETAILS=1

監視ドキュメントの tool_decision の属性一覧には、この3つがまだ載っていません。属性名と条件の根拠は更新履歴です。

集計の軸は何にするか

分類器の判定を数えるとき、軸は3つあります。

  1. permission_mode が auto のイベントに絞る
  2. その中で classifier_verdict が付いているものを、分類器が審査した判定として扱う
  3. decision でacceptとrejectを分ける

2つ目の使い方は、属性が付く条件を前提にしています。更新履歴は「分類器の判定とルールの判定を見分けられる」としか書いていません。ルールで決まったイベントに classifier_verdict が付かないのか、別の値が入るのかは、ドキュメントからは確定できません。

属性のあるなしで切り分ける前に、手元のバックエンドへ実イベントを流して確かめるのが確実です。特に classifier_verdict が取る値は、更新履歴にも監視ドキュメントにも列挙がありません。ダッシュボードの条件に値を書き込む前に、観測した値を控えてください。

手元でイベントを流して確かめる

組織全体に配るときは、管理者設定の settings.json に同じ変数を env で書きます(キーは監視ドキュメントの設定例にあるものだけです)。

{
  "env": {
    "CLAUDE_CODE_ENABLE_TELEMETRY": "1",
    "OTEL_LOGS_EXPORTER": "otlp",
    "OTEL_LOG_TOOL_DETAILS": "1",
    "OTEL_EXPORTER_OTLP_PROTOCOL": "grpc",
    "OTEL_EXPORTER_OTLP_ENDPOINT": "http://collector.example.com:4317"
  }
}

手元で試すには、コンソール出力が最短です。監視ドキュメントのクイックスタートにある変数のうち、ログ側だけを使います。

export CLAUDE_CODE_ENABLE_TELEMETRY=1
export OTEL_LOGS_EXPORTER=console
export OTEL_LOGS_EXPORT_INTERVAL=1000
export OTEL_LOG_TOOL_DETAILS=1
claude --permission-mode auto

起動後に、ルールで許可した操作(例えば npm test のallowルールに合うコマンド)と、ルールに当たらない操作の両方を実行させます。出力された tool_decision を並べて、classifier_verdict が付くイベントと付かないイベントの差を見ます。

OTEL_LOG_TOOL_DETAILS=1 を付けると tool_parameters にBashのコマンドが載ります。コマンド本文は機微情報になり得るので、本番のバックエンドへ流す前に、属性のマスキングを決めておいてください。この変数で何が見えるかはOTEL_LOG_TOOL_DETAILSとTOOL_CONTENTで見える範囲にまとめています。

分類器に回る操作とは何か

集計結果を読むには、分類器が何を審査するかを知っている必要があります。権限モードのドキュメントによると、auto modeの判定順序は次のとおりで、最初に一致した段階が勝ちます。

手順

auto modeの判定順序

  1. 1

    allow・ask・denyルール

    ルールに一致した操作は、その場で決まります。ただし例外があります(次の小節)。

  2. 2

    読み取り専用と作業ディレクトリ内の編集

    自動承認されます。サーバー側レビューのあるセッションでは、読み取り専用とサンドボックス内のシェルコマンドも、レビューを待ちます。

  3. 3

    それ以外はすべて分類器へ

    分類器が許可か拒否を決めます。

  4. 4

    ブロック時は理由がClaudeに返る

    多くのセッションで、理由は [Data Exfiltration] のようにルール名で示されます。

つまり permission_mode が auto でも、すべてのイベントが分類器の判定とは限りません。1段階目のルールで決まった操作は、auto modeのセッションでもルールの判定です。これが permission_mode だけでは足りず、classifier_verdict と組み合わせる理由になります。

ルールの判定に見えて分類器に回る操作

auto modeに入ると、広いallowルールは外されます。対象は Bash(*) のような全許可、Bash(python*) のようなインタープリターのワイルドカード、パッケージマネージャーの実行コマンド、Agent と Monitor のallowルールが対象です。Bash(npm test) のような狭いルールは残り、auto modeを抜けると外したルールも戻ります。

この仕様は集計の読み方に効きます。defaultモードでは config で通っていた操作が、auto modeでは分類器の審査を通るようになることがあります。モードを切り替えた前後で classifier_verdict が付くイベントが増えても、ツールの使い方が変わったとは限りません。permission_mode を軸に入れるのは、この比較のためです。

もう1つの例外が、保護対象パスへの書き込みです。allowルールが一致していても分類器に回ります。ルールを書いたのに分類器の判定として数えられるイベントがあれば、この2つを疑ってください。

サブエージェントの操作も分類器にかかる

サブエージェントは3か所で審査されます。起動前に委任タスクの説明、実行中に各操作(親セッションと同じ判定順序。frontmatterの permissionMode は無視)、終了時に作業内容と最終報告です。つまり、サブエージェント内の操作も tool_decision の分類器の判定として数えられます。親セッションの操作だけを見ているつもりで件数を読むと、ずれます。

分類器の呼び出しは費用と遅延を足す

分類器は既定でSonnet 5で動き、/model の選択には従いません。EnterpriseプランやClaude APIなどでは、分類器の呼び出しがトークン使用量に数えられます。1回の審査はトランスクリプトの一部と保留中の操作を送るので、実行前に往復が1回増えます。読み取りと保護対象外の作業ディレクトリ内の編集は分類器を通らないため、オーバーヘッドの大半はシェルコマンドとネットワーク操作です。classifier_verdict の件数は、この追加コストが発生した回数の目安になります。

classifier_categoryで何が分かるか

classifier_category は、分類器のブロックが当たった組み込みルールの名前です。画面の通知に出る [Data Exfiltration] のような理由と、同じ種類の情報をテレメトリ側で取れるようになったと考えられます。ただし、画面の理由とこの属性の値が完全に一致するかどうかは、ドキュメントに記載がありません。

使い道は、拒否の内訳です。

  • どのカテゴリーのブロックが多いかを数え、environment で信頼済みのインフラを登録するか判断する
  • 特定のカテゴリーが特定のチームに偏っていないかを、OTEL_RESOURCE_ATTRIBUTES のチーム属性と組み合わせて見る

画面でも、/permissions のRecently deniedタブで拒否を見直せます。ただし、セッションごとの手作業です。テレメトリなら、組織全体の拒否をカテゴリー別に横断して見られます。

数字の読み違いを避ける3つの注意

分類器の「判定なし」はrejectとして数えられるか分からない

分類器が応答を返せないなど、判定が出ない場合、Claude Codeは操作を拒否します。この拒否は、画面の通知にもRecently deniedにも載りません。tool_decision にどう記録されるかは、ドキュメントに記載がありません。拒否件数が画面の記録と合わないときは、この経路を疑ってください。原因の切り分けはauto modeの分類器が応答不能になるとBashが止まる原因と回避策が参考になります。

連続ブロックでauto modeが止まる

分類器が3回連続、または累計20回ブロックすると、auto modeは一時停止してプロンプトに戻ります。再開後はClaude Codeが承認を求めるようになり、承認すればauto modeに戻ります。しきい値は設定で変えられません。ブロック件数の推移を見るときは、この上限で分類器の審査が一度止まることを念頭に置いてください。

モードの切り替えは別イベントに出る

権限モードの変更は permission_mode_changed という別のイベントとして記録されます。trigger には shift_tab、exit_plan_mode、auto_gate_denied、auto_opt_in があります。auto modeに入ったセッションがいつ抜けたかは、tool_decision の permission_mode の変化と、このイベントを突き合わせると追えます。

拒否された入力そのものを残したいとき

tool_decision の tool_parameters は OTEL_LOG_TOOL_DETAILS=1 のときだけ付き、拒否されたBashのコマンドを確認する用途にも使えます。一方、画面の通知とRecently deniedタブはコマンドやURLを省略します。auto modeの拒否を入力まで含めて取りたいときは、PermissionDenied フックが使えます。フックには拒否された呼び出しが tool_input として渡ります。

テレメトリは「何がどれだけ拒否されたか」の集計に、フックは「何を拒否されたか」の記録に向きます。分類器の拒否を継続的に見直す体制なら、両方を置く構成になります。

他のイベントと組み合わせる

tool_decision と tool_result は、どちらも tool_use_id を持っています。拒否されたツール呼び出しは tool_decision だけに残り、実行された呼び出しは tool_result に結果が残ります。したがって次のように使い分けられます。

知りたいこと見るイベント
分類器が拒否した操作の内訳見るイベントtool_decision(classifier_verdict・classifier_category)
分類器が許可して実際に走った操作見るイベントtool_decision と tool_result を tool_use_id で結合
モードの出入り見るイベントpermission_mode_changed

セキュリティ監査の全体像はClaude Codeセキュリティ監査とOTELイベントの対応表にあります。v2.1.301の全項目はClaude Code v2.1.301のリリースノートで確認できます。

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