CCA-F(Claude Certified Architect — Foundations)試験のタスクステートメント2.3は「エージェント間でツールを適切に配布し、tool choiceを設定する」と読める。Domain 2(Tool Design & MCP Integration、採点対象の18%)に位置し、ドメインウェイトは控えめであるにもかかわらず、コミュニティ合格レポートの中でもトラップ問題の収率が特に高い領域である。理由は明快だ。tool distributionとtool_choiceは、エージェントアーキテクチャ(Domain 1)・プロンプトエンジニアリング(Domain 4)・信頼性(Domain 5)の交差点に位置する。この1か所での設計ミスがツール選択エラー・幻覚的な関数呼び出し・構造化出力のドリフト・暴走するagentic loopへと連鎖し、それらはすべて試験の他の箇所で採点される。タスク2.3を正しく理解することは高いレバレッジをもたらす。
この学習ノートでは、CCA-F候補者がアーキテクチャレベルで設計を求められる全体像を説明する。各エージェントが保有すべきツールを決定する原則・coordinator対subagentの分割・tool_choiceパラメーターの4つの値(auto・any・forced tool object・none)とそれぞれを選ぶ状況・スキーマ強制のためのforced tool callパターン・ワークフロー状態に応じた動的ツール可用性・エージェントをその役割に閉じ込めるアクセス制御メカニズム・過大なツールカタログが引き起こす実測可能なパフォーマンス劣化。最後にCommon Exam Trapsセクション・名前付き試験シナリオに紐付けた実践アンカー・5つの候補者質問によるFAQで締め括る。
Tool Distributionの原則 — 各エージェントに関連するツールのみを割り当てる
Tool distributionは、システム内の各エージェントが参照できるツールを決定するアーキテクチャ的な決定である。ランタイムの懸念ではなく、Messages APIのすべての呼び出しで渡すtools配列と各subagent定義で設定するallowed_toolsリストのスキーマである。原則は言葉では信じられないほど単純で、実際には驚くほど難しい。各エージェントにはそのタスクを完了するために必要なツールのみを与え、それ以上は与えない。
「関連するツールのみ」が本番要件である理由
エージェントが参照できるツールはどれも3つの希少なリソースを消費する。
- コンテキストトークン — 各ツール定義(名前・説明・
input_schema)はすべてのリクエストのシステムコンテキストに挿入される。40ツールのカタログは各ループイテレーションの各ターンに数千トークンを追加する。 - 選択の認知負荷 — Claudeはカタログ全体を読み込み、ユーザーのゴールと比較して選択しなければならない。カタログが大きいほど、ニアミス選択の確率が高くなる(正しい呼び出しが
search_accountsのときにsearch_customersを選ぶなど)。 - 爆発半径 — エージェントが呼び出せるすべてのツールは、エージェントが誤用できるツールでもある。本番データベースへの書き込みアクセスも持つリサーチsubagentは、本番データベースを破壊できるリサーチsubagentである。
ツールセットを絞り込むことで3つの負荷が同時に減少する。これがAnthropicの公式ツール作成ガイダンスが積極的なスコーピングをパフォーマンスのマイクロ最適化ではなく、第一級の設計原則として扱う理由だ。
Tool distributionは、マルチエージェントシステムにおけるエージェントへのツールの割り当てである。各エージェントは、そのタスクに必要なツールのみを含む意図的にスコープ設定されたtools配列(またはsubagent定義内のallowed_toolsリスト)を受け取る。配布の決定はランタイムではなく設計時に行われ、コンテキストコスト・ツール選択精度・爆発半径の安全性を直接制御する。CCA-Fタスク2.3は候補者が配布の決定をシナリオ形式で正当化できるかどうかを問い、単に原則を暗唱できるかどうかを問わない。
出典: https://www.anthropic.com/engineering/writing-tools-for-agents
ロールファーストの配布ヒューリスティック
ツールを列挙する前に、エージェントの役割を1文で記述する。「請求返金エージェントは顧客の返金リクエストを解決する。」その文から到達可能でなければならない名詞と動詞(refund・charge・customer・account・policy_document)をリストアップし、各概念に正確に1つのツールをマッピングする。役割説明で呼び出されないものは省略する。「ツールライブラリがあり、どのエージェントがどれを使えるか」から始める候補者は過大なカタログを持ち、役割説明から始める候補者は引き締まったカタログを持つ。
エージェントごとのツール数を減らす理由 — 曖昧さを減らし、選択精度を向上させる
「エージェントごとのツールを減らす」の背景にある実証的な観察は、Claudeのツール選択精度がカタログの成長とともに低下し、その低下は線形ではなくカタログがモデルの有効な選択スパンを超えると加速するということだ。これは直感的(40のほぼ同一なボタンを前にした人間も間違いが増える)であり、本番トレースで直接観察できる。
精度低下をもたらす3つのメカニズム
- ニアデュプリケートの混乱 — 名前や説明が重なるツール(
search_users・lookup_accounts・find_customers)は、ユーザーの言い方が曖昧な場合に間違いを引き起こす。 - 説明の希薄化 — 長いカタログは各ツールの説明をシステムコンテキストのさらに下に押しやる。「中間で失われる」効果がツール境界の想起を低下させる。
- 過剰なツール呼び出し — 多くのツールが見えると、コンテキストから直接答えられる場合でも何らかのツールを呼び出しやすくなる。これはツールの「大きな工具箱を持つ大工はハンマーを使う場面をより多く見つける」効果だ。
ツール削減ルールは良い説明と合成される
Tool distributionは必要条件だが十分条件ではない。引き締まったカタログでも説明が曖昧であれば失敗する。これがDomain 2.1の懸念事項だ。正しいメンタルモデルは:タスク2.1が各ツールの境界を明確にし、タスク2.3が最初から正しいツールだけが各エージェントに見えるようにする。両方のレバーを引かなければならない。
コミュニティの合格レポートは「エージェントのツール数を過大にする」をCCA-Fにおけるトップレベルの失敗として一貫して挙げている。シナリオの答えに「エッジケースに対応できるように全50のプラットフォームツールへのアクセスを与える」という選択肢が含まれている場合、その選択肢はほぼ常に間違いである。正しい答えはカタログを役割をカバーできる最小限まで縮小する。 出典: https://www.anthropic.com/engineering/writing-tools-for-agents
CoordinatorのツールセットとSubagentのツールセット — 関心の分離
Coordinator-subagentアーキテクチャでは、coordinatorと各subagentはそれぞれのISOLATEDツールカタログで実行される。配布の決定は2レベルある:coordinatorのカタログ1つと各subagentロールごとのカタログ1つ。これらを単一の共有カタログとして扱うことは一般的な設計上の失敗だ。
Coordinatorが保有すべきツール
coordinatorの仕事はタスクを分解し、subagentを派遣し、最終的な答えを組み立てることだ。そのツールセットはこれを反映すべきである。
- Subagent派遣ツール(coordinatorの主要なインターフェース:リサーチsubagentをスポーン、extractionsubagentをスポーン)。
- 全体的なプランを追跡するための状態管理ツール(タスクリストの読み書き・セッションのチェックポイント)。
- 集約されたsubagentの出力に対して動作する最終回答組み立てツール。
coordinatorはsubagentが使用する低レベルのツール(ファイル読み取り・データベース書き込み・外部API呼び出し)への直接アクセスをほぼ持つべきではない。coordinatorがsubagentの仕事を直接できる場合、subagentは冗長であり、アーキテクチャは崩壊している。
各Subagentが保有すべきツール
各subagentのカタログはその単一の責務にスコープされる。リサーチsubagentはウェブ検索と要約ツールを持つ。Extractionsubagentはドキュメント読み取りと構造化出力ツールを持つ。検証subagentはルックアップと比較ツールを持つ。Subagentは、アーキテクチャが2レベルを超える明示的な階層でない限り、他のsubagentをスポーンする権限を持つべきではない。
CCA-Fにおける分割の重要性
試験のシナリオはマルチエージェントリサーチシステムを提示し、どのエージェントがどのツールを保有すべきかを問う。そうでなければツールを綺麗に分割するシナリオでcoordinatorが直接ファイル読み取りアクセスを持つのはトラップの答えだ。正しい設計はファイル読み取りをリサーチsubagentにプッシュする。同様に、3レベル階層をシナリオが明示的に説明していない限り、subagentが他のsubagentをスポーンするアクセス権を持つのもトラップの答えだ。
試験でcoordinator-subagentシナリオを図式化するとき、答えの選択肢を読む前に各ツールに正当な所有者をラベル付けする。原則ではなく選択肢に基づいて配布を選ぶ候補者はニアコレクトなdistractor でだまされやすい。 出典: https://docs.anthropic.com/en/docs/claude-code/sub-agents
tool_choiceの設定 — auto・any・forced(特定ツール名)のモード
tool_choiceはMessages APIパラメーターであり、次のターンでClaudeが呼び出せるツールを制御する。パラメーターはauto・any・明示的なtoolオブジェクト(forced)・noneの4つの有効な形式を持つ。これらのうちいずれか2つの意味の違いを誤解することがDomain 2における最も繰り返し起こるトラップの1つだ。
4つの形式
{ "type": "auto" }— Claudeが会話に基づいてツールを使用するかどうか、およびどのツールを使用するかを決定する。デフォルト。{ "type": "any" }— Claudeはカタログから何らかのツールを使用しなければならない。このターンではプレーンテキストで応答できない。{ "type": "tool", "name": "<tool_name>" }— Claudeはこのターンで指定された特定のツールを呼び出さなければならない。{ "type": "none" }— Claudeはいかなるツールも呼び出してはならず、プレーンテキストで応答しなければならない。
tool_choiceは次のレスポンスでClaudeのツール呼び出し動作を制約するMessages APIパラメーターである。4つの値(auto・any・forced tool object { type: "tool", name: "..." }・none)はそれぞれ異なるアーキテクチャ上の意図を表す。autoはデフォルトでClaudeに決定を委ねる。anyはどのツールかを指定せずにツール呼び出しを強制する。forced objectはツールに名前を付けることでClaudeの選択を完全に取り除く。noneはこのターンのツール使用を無効にする。パラメーターはAPI呼び出しごとに設定されるため、同一のagentic loop内の各ターンで変更できる。
出典: https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/implement-tool-use
tool_choiceはエージェントごとではなく呼び出しごとに設定される
試験でよくある誤解はtool_choiceが一度設定するエージェント設定であるということだ。そうではない。tool_choiceはすべてのMessages API呼び出しで独立して設定されるため、単一のagentic loopが最初のターンにtool_choice: anyを設定して初期ツール呼び出しを強制し、続くターンにautoに切り替えてClaudeに決定させ、最終ターンにforcedオブジェクトに切り替えてスキーマ準拠の答えを出力することができる。ループ全体にわたる動的なtool_choiceは、タスク2.3とタスク4.3の複数のシナリオの背後にある設計レバーだ。
tool_choice: auto — モデルがツールを使うかどうかとどのツールを使うかを決定する
tool_choice: autoはデフォルトであり、ほとんどのオープンエンドなagentic シナリオの正解である。autoの下で、Claudeはユーザーのゴールを読み込み、ツールカタログと比較して自律的に決定する。
- ツール呼び出しが必要かどうか、または直接テキスト回答で十分かどうか。
- どの特定のツールを呼び出すか。
- 同じメッセージ内で複数の並列ツール呼び出しを出力するかどうか。
autoが正しい場合
autoはワークフローが探索的またはマルチブランチの場合に正しい。予測不可能なチケットを処理するカスタマーサポート解決エージェント・未知のファイルにわたってバグを調査するcode-generation-with-claude-codeエージェント・どのsubagentを派遣するかを決定するmulti-agent-research-system coordinatorなど。これらの各ケースで、ツールを呼び出すかどうかとどのツールを呼び出すかについてのClaudeの判断は機能であり、バグではない。
autoが間違いの場合
autoはアーキテクチャがツール呼び出しを必要とする場合、例えば唯一許容される出力形状が特定ツールのスキーマである構造化extractionワークフローの最終ターンでは間違いである。autoの下で、Claudeが回答は完全であると判断してどのツールスキーマにも準拠しないプレーンテキストのレスポンスを出力するかもしれない。extractionパイプラインが最終ターンにforced tool_choiceに切り替える理由がこれだ。
autoと並列ツール呼び出し
autoの下で、現代のClaudeモデルは独立したツール呼び出しを積極的に並列化する。4つの無関係な事実を調べるリサーチエージェントは通常1つのメッセージで4つのtool_useブロックを出力する。これはデフォルトの動作であり、tool_choiceが切り替えるものではない。
tool_choice: any — モデルが何らかのツールを使わなければならない(純粋なテキスト応答を防ぐ)
tool_choice: anyは「Claudeは何らかのツールを呼び出さなければならないが、どれかは指定しない」という意味だ。forced tool objectより弱く、autoより強い。狭い範囲のシナリオで正しい選択であり、より広いシナリオではトラップの答えだ。
anyの正当なユースケース
anyが適切な場合:
- ワークフローがこのターンでツールを介した行動をとる必要があるが(例:「何らかのログツールでこのイベントを必ずログする」)、コンテキストによって特定の行動が異なる。
- 「調査ツールが呼び出されるまでユーザーへの直接応答なし」というビジネスルールがあるため、エージェントはまだプレーンテキストで応答すべきでない。
- Claudeがもっともらしく聞こえるが調査不十分なテキスト回答でリサーチフェーズを省略することを防ぎたい。
anyが保証しないこと
anyはClaudeがどのツールを選ぶかを保証しない。カタログにsearch_knowledge_baseとescalate_to_humanの両方が含まれている場合、Claudeはいずれかを選択する可能性があり、アプリケーションは両方の結果を処理しなければならない。「anyはClaudeに正しいツールを使わせる」または「anyはClaudeをタスクに集中させる」と説明する答えは保証を誇張している。anyはテキスト応答のオプションを取り除くだけであり、ツールの選択はClaudeの判断の中に残る。
anyが間違いの場合
試験でanyが間違いの答えとなる場合:
- シナリオが特定のツールを必要とする(代わりにforced tool objectを使用)。
- シナリオが単に良い動作を望む(より良いツール説明で
autoを使用。anyは選択品質を向上させず、テキストオプションを取り除くだけ)。 - シナリオがテキスト応答を拒否することが妥当な出力をブロックするオープンエンドな調査である(
autoを使用)。
CCA-Fのコミュニティプールで最も頻度の高いtool_choiceのトラップはanyを特定ツールを強制する方法として扱うことだ。anyは何らかのツールを強制するだけで、どのツールかを指定しない。シナリオが正確なツール強制を必要とする場合、正しい値はforced tool object { type: "tool", name: "<specific>" }でありanyではない。anyを「正しいツール呼び出しを強制する」と同一視する答えは常に間違いである。
出典: https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/implement-tool-use
tool_choice: forced — モデルが特定の名前のツールを呼び出さなければならない
forced tool_choiceの値は{ "type": "tool", "name": "<tool_name>" }の形状のオブジェクトである。現在のターンのClaudeの選択判断を完全に取り除く:次のレスポンスは名前付きツールの正確に1つのtool_useブロックを含まなければならない。交渉の余地はなく、テキストへのフォールバックも、代替ツールもない。
Forced tool_choiceの目的
Forced tool_choiceの正規メカニズムの用途は:
- 最終ステップのスキーマ強制 — extractionワークフローの終わりに
emit_structured_recordツールをforceして出力がツールのinput_schemaに準拠することを保証する。 - 確定的なパイプラインステージ — ステップNが常に
classify_intentを呼び出さなければならない固定マルチステップパイプラインで、そのツールをステップNにforceする。 - 振動ループの解消 — Claudeが2つのツールの間で交互に選択する場合、一方をforceすると振動が終了する。
Forced tool_choiceでないもの
Forced tool_choiceはClaudeにツールについてより深く考えさせる方法ではない。明示的にClaudeの選択判断をバイパスする。forcedツールが現在の状態に対して間違っている場合でも、Claudeは構築できるinputを使ってそのツールを呼び出し、それらのinputはナンセンスになる可能性がある。Forced tool_choiceは形状への制約であり、正確さへの制約ではない。
並列ツール呼び出しとの相互作用
tool_choiceがforced tool objectの場合、Claudeは名前付きツールの正確に1つのtool_useブロックを出力する。並列マルチツール出力は抑制される。これはforcedツールパイプラインとautoパイプラインのレイテンシを比較するシナリオ問題にとって重要で、forcedモードでは並列化が失われる。
Strict modeとの相互作用
Forced tool_choiceはツール定義のstrict: trueと自然にペアリングされる。strict: trueはツールのinput_schemaが正確に強制されることを保証し、forced tool_choiceはこの特定のツールが呼び出されることを保証する。この2つのペアがスキーマ保証された構造化出力を生成する(タスク4.3シナリオの正規パターン)。
Forced tool_choiceはパラメーターの{ type: "tool", name: "..." }形式である。次のレスポンスが名前付きツールを正確に呼び出すことを義務付けることで、1ターンのClaudeのツール選択判断を完全に取り除く。スキーマ準拠の最終出力を強制し、確定的なパイプラインステージを固定し、agentic loopの振動を解消するために使用される。テキスト応答のみを禁止して選択はClaudeに委ねるanyとは異なる。Claudeの選択ロジックを強化するのではなく、バイパスする。
出典: https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/implement-tool-use
Forced Tool Choiceのユースケース — スキーマ強制・ツールを通じた構造化出力
Forced tool_choiceの主要なCCA-Fユースケースはツール使用を通じた構造化出力の強制である。これはDomain 2.3が設定を担当する正規タスク4.3パターンだ。
パターン:input_schemaが出力スキーマであるツールを定義する
「このスキーマに合うJSONを返して」とプロンプトで求める代わりに、input_schemaが望む出力スキーマそのものであるツールを定義する。そのツールに表す行動の名前を付ける(emit_customer_record・submit_bug_report・record_extracted_entities)。このツールに名前を付けたforced tool objectにtool_choiceを設定し、理想的にはツール定義にstrict: trueを設定する。
Forced tool_choiceによりClaudeはそのツールを正確に呼び出し、strict: trueによりそのツールのinputがスキーマに正確に準拠することが保証されるため、結果のtool-useブロックのinputフィールドはスキーマ検証済みのJSONオブジェクトであり、そのまま消費できる。パースの曖昧さも散文に包まれたJSONも欠けているフィールドもない。
プロンプトベースのJSON指示よりも優れている理由
プロンプトベースの「このようなJSONを返して」という指示には3つの繰り返す失敗モードがある:欠損または余分なフィールド・JSONの周りに包まれた散文・エッジケースでのソフトなスキーマドリフト。Forced tool_choiceとstrict: trueはプロンプト指示への準拠(ソフト)からAPIレベルのスキーマ検証(ハード)に強制を移すことで3つすべてを排除する。コミュニティ合格レポートはこれをCCA-Fで「最も重要な5つのメンタルモデル」の1つとして一貫して挙げている。
このパターンを適用するタイミング
以下の場合に構造化出力のためにforced tool_choiceを適用する。
- ダウンストリームのコンシューマーが厳格なスキーマ準拠を必要とする(パイプラインパーシング・データウェアハウスのロード・コントラクトAPI)。
- 大量実行しており、レコードごとの検証と再試行コストを負担できない。
- 出力形状が安定していて事前にわかっている。
リクエストごとに出力形状が変わる場合(autoを使用して小さなセットからClaudeに適切なツールを選ばせる)または出力に構造化データと並んでフリーフォームの説明が含まれる場合(2ターンパターンを検討:レコードにはforced tool、説明にはauto)はこのパターンを適用しない。
Forced tool_choiceとnamed toolのstrict: trueの組み合わせはCCA-Fの「構造化出力準拠を保証する」問いの正規回答である。「より厳格な指示をシステムプロンプトに追加する」または「後からJSONを検証して再試行する」を提案する答えは、プロンプト準拠ではなくAPIレベルの強制に依存するforced toolパターンよりほぼ常に劣る。プログラム的な強制はプロンプトベースのガイダンスを上回る。
出典: https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/strict-tool-use
動的ツール可用性 — ワークフロー状態に基づいてツールの有効化・無効化する
ツールの可用性はagentic loopの寿命を通じて静的である必要はない。適切に設計されたループはターンごとに表示されるツールセットを頻繁に変更し、現在のワークフロー状態に適したツールのみが公開されるようにする。
動的可用性が存在する理由
単一エージェントが計画・実行・検証・レポートなど複数の異なるフェーズを経過する場合がある。各フェーズには異なるツールが適切である。計画フェーズで実行ツールを公開すると時期尚早な行動を招く。実行フェーズでレポートツールを公開するとClaudeが省略して部分的なサマリーを出力しやすくなる。表示されるツールをフェーズの意図にスコープすることでClaudeを適切な概念的レーン内に保つ。
ツール可用性を変化させる2つのメカニズム
- 呼び出しごとの
tools配列 — 最もシンプルなメカニズム。アプリケーションが現在のワークフロー状態に基づいて各Messages API呼び出しで異なるtools配列を渡す。状態機械が小さいほど、これは単純になる。 - 呼び出しごとの
tool_choice— より柔らかいメカニズム。tools配列を定数に保ちながらtool_choiceを変化させる。計画フェーズでauto、実行フェーズの名前付き「execute」呼び出しにforced tool object、最終サマリーフェーズにnone。両方のメカニズムを組み合わせて使用できる。
具体的な例 — 3フェーズのExtractionパイプライン
ターン1(計画):tools = [list_documents, read_document]、tool_choice = auto。Claudeが関連ドキュメントをリストして読み込む。ターン2(抽出):tools = [read_document, emit_record]、tool_choice = { type: "tool", name: "emit_record" }。Claudeがスキーマ準拠のレコード出力にforceされる。ターン3(終了):tools = []、tool_choice = none。Claudeがそれ以上のツール呼び出しなしに人間が読めるサマリーを書く。
この例は、動的ツール可用性がマイクロ最適化ではなく、Claudeの動作をワークフローの現在の意図と整合させるための構造的な技法であることを示している。
CCA-Fシナリオで「エージェントは調査フェーズが完了するまで行動してはならない」というフレーズは、動的ツール可用性の答えを示唆している。調査中はカタログから実行ツールを除去(またはtool_choice: noneを設定)し、その後に復元する。同じ効果をより強制力の強いシステムプロンプトで達成しようとする答えは、プロンプト準拠ではなくAPIレベルの保証に依存するため劣る。
出典: https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/implement-tool-use
ツールアクセス制御 — エージェントがスコープ外のツールにアクセスするのを防ぐ
Tool distributionの決定はアクセス制御の決定でもある。エージェントがツールを見られなければ、どれほど巧みなプロンプトが説得しようともそのツールを呼び出すことはできない。これがエージェントシステムにおけるアクセス制御がプロンプト層ではなくツール定義層で実装される理由だ。
ツールアクセス制御の3つの層
- 配布時のスコーピング — 各Messages API呼び出しの
tools配列、または各subagent定義のallowed_toolsリストが、エージェントが見られるツールを正確に列挙する。配列にないツールはClaudeから見えない。 - サーバーサイドの認可 — ツールの実装は引き続きすべての呼び出しを認可する。「エージェントはスコープ外に設定されているから」と信頼する
delete_userツールは負債だ。多層防御。 - フックベースのインターセプト — Agent SDKの
PreToolUseフックは実行時に特定のツール呼び出しを拒否できる(例:rm -rfを参照するBash呼び出しを拒否)。フックはタスク1.5の概念だが、アクセス制御のループを閉じる。
プロンプトベースのアクセス制御が失敗する理由
「ユーザーが管理者でない限りdelete_userツールを呼び出さないで」はプロンプトベースの制約だ。Claudeは通常はそれに従うが、「通常は」はアクセス制御の保証ではない。同じ制約を配布として表現する(管理者でないエージェントは単純にtools配列にdelete_userを持たない)とハードな境界になる。CCA-Fは一貫してハードな境界の答えを好む。
アクセス制御サーフェスとしてのSubagentのallowed_tools
Claude Codeのカスタムsubagent定義はallowed_toolsリストを公開する。これがsubagentのケーパビリティをスコープするための構造的な方法だ。allowed_tools: [Read, Grep, Glob]で定義された「リサーチ」subagentは、その動作プロンプトが誤ってそれらを招待した場合でも、Write・Edit・Bashを物理的に呼び出せない。これはタスク1.3(subagent呼び出し)をフィードするタスク2.3のレバーだ。
3つのツールアクセス制御メカニズム、それぞれ1文:
tools配列 /allowed_tools— 配布時のスコーピング;見えないツールは呼び出せない。- ツール実装内のサーバーサイドの認可 — ランタイム強制;多層防御。
PreToolUseフック — 実行前の特定呼び出しのプログラム的な拒否権。
経験則:構造的な制約(エージェントの役割・マルチテナント分離)には配布時スコーピングを、データレベルの制約にはサーバーサイド認可を、動的ポリシーチェックにはフックを好む。 出典: https://docs.anthropic.com/en/docs/claude-code/sub-agents
ツールセットサイズがパフォーマンスに与える影響 — 大きなツールカタログの認知負荷
公式に発表されたツール選択精度が崩壊する閾値はなく、試験は正確な数値を問わない。試験が問うのは効果の方向性と軽減パターンだ。
効果の方向性
カタログ内のツール数が増えるにつれて、3つの測定可能なことが同時に悪化する:
- 選択精度 — 与えられたユーザーゴールに対してClaudeが正しいツールを選択する確率が下がる。
- Input schema準拠 — コンテキスト内のツールが多いほど、類似するツール間でツールの入力フィールド名と型がより頻繁に混在する。
- 過剰なツール呼び出し頻度 — 直接回答で十分な場合でもツールを呼び出しやすくなる。
これらの効果は相互作用する。いくつかのニアデュプリケートと曖昧な説明を持つ40ツールのカタログは、明確な説明を持つ10ツールのカタログより質的に悪いエージェント動作を生成する。40ツールのカタログのツール説明を修正すると一部は回復するが、すべては回復しない。根本的な制約はカタログサイズ自体だ。
優先順位順の3つの軽減策
- 重複するツールを統合する — カタログに
search_usersとlookup_accountsの両方がある場合、より明確な境界を持つ1つのsearch_accountsツールに統合する。 - エージェントを分割する — 単一エージェントが複数の役割を担っているために多くのツールを必要とする場合、coordinatorと役割ごとのsubagentに分割してツールを配布する。
- 動的ツール可用性を使用する — 同じエージェントが同じ役割を担いながらフェーズを通過する場合、フェーズごとに表示されるツールを変化させる。
カタログを縮小できない場合
一部の正当なユースケースは大きなカタログを必要とする(IDEスタイルのコードアシスタントは例えば多くの組み込みツールを公開する)。これらのケースでは、軽減策がツール検索パターンにシフトする:MCPコネクターはClaudeがクエリするまでツール定義の読み込みを遅延するツール検索をサポートする。これによりインコンテキストのカタログを小さく保ちながら大きな物理ライブラリへのアクセスを維持する。ツール検索はタスク2.4のトピックだが、その動機はここにある。
CCA-Fでは「エージェントが間違ったツールを選び続ける」を「より多くのケースをカバーするためにより多くのツールを追加する」で解決する答えは間違いだ。修正の正しい方向はより少なく、より適切にスコープされたツール — 統合によるか、subagentへの分割によるか、動的可用性によるか — だ。ツールを増やすことは選択精度を決して向上させない。 出典: https://www.anthropic.com/engineering/writing-tools-for-agents
Strict Modeとの相互作用 — Forced-Plus-Strictパターン
Strict mode(ツール定義のstrict: true)はツールのinput_schemaがAPIレイヤーで正確に強制されることを保証する直交するメカニズムだ。最も重要なCCA-F構造化出力パターンでtool_choiceと合成される。
Strict Modeが行うこと
strict: trueの場合:
- ツールの
input_schemaはクローズされていなければならない(宣言されたもの以外の追加プロパティはない)。 - 型とenum制約はAPIによって強制され、Claudeは無効なツールinputを出力できない。
- requiredとマークされたフィールドは必ず存在しなければならない。
Forced-Plus-Strictパターン
tool_choice: { type: "tool", name: "emit_record" }とemit_recordのstrict: trueの組み合わせは3つの保証を生む:
- Claudeは他のツールではなく
emit_recordを呼び出す。 - その呼び出しのClaudeの
inputはスキーマに正確に準拠する。 - アプリケーションは検証オーバーヘッドなしに
inputを直接消費できる。
これはタスク4.3(「ツール使用とJSONスキーマを使って構造化出力を強制する」)のアーキテクチャ的な答えであり、forced tool_choiceが選択レベルの半分のパターンであるためタスク2.3の中に存在する。
Strict ModeだけでISUFFICIENTな場合
Strict modeは形状を強制し、意味論は強制しない。discount_percent: numberフィールドを持つstrict: trueツールは文字列入力を拒否するが、-500を数値として喜んで受け入れる。意味論的な検証(割引は0から100の間でなければならない)は依然としてツールのサーバーサイド実装に属する。
tool_choiceとNone — ツール呼び出しを完全に抑制する
tool_choice: noneはClaudeが次のターンにいかなるツールも呼び出すことを禁じる。レスポンスはプレーンテキストでなければならない。この値はtools配列を変更せずにツール使用をクリーンに無効化するために存在する。
noneを使用するタイミング
- 最終回答サマリーフェーズ — 調査と構造化出力の後、最終的な人間が読めるサマリーがそれ以上のツール呼び出しを発火すべきではない。
- 安全性に敏感なターン — エージェントが人間が読んで行動しようとしているレスポンスを生成する場合、ツールを無効にすることで最後の瞬間の行動を防ぐ。
- 説明ターン — 「あなたが行ったことを説明して」というレスポンスはそれ以上の行動を取るべきではない。
noneを使用すべきでないタイミング
- 「計画」フェーズでのツール使用を防ぐため — 代わりに動的ツール可用性(
tools配列を縮小)を使用する。noneは呼び出しごとに上書きできるが、配布は構造的な境界だ。 - いかなるツール呼び出しも不適切な場合にプレーンテキストレスポンスを強制するため — これはまさに
noneの目的だが、autoがより少ない手間で同じ仕事をしないか確認する(ツールが有用でない場合Claudeはすでにテキストを出力する)。
やさしい解説: Tool DistributionとTool Choice
Tool distributionとtool_choiceは設計コインの両面だ。一方は各エージェントが見られるツールを決定し、もう一方は与えられたターンにエージェントがどのツールを呼び出すことが許可されるかを決定する。異なるドメインからの3つの比喩が全体像をカバーする。
Analogy 1: 病院の診療科 — 役割スコーピングとしての配布
病院の救急科を想像してほしい。トリアージ看護師はバイタルモニター・患者記録システム・「専門医に回す」内部フォームへのアクセスを持つ。看護師が信頼できないからではなく、それらのツールが他の役割に属しており、それらをトリアージワークステーションに含めることで混乱を招き、看護師が仕事をするのに必要としないサーフェスを公開するからだ。心臓専門医・放射線科医・薬剤師はそれぞれ自分の役割にスコープされた独自のツールセットを持つ。これがcoordinator-subagentアーキテクチャにおけるtool distributionそのものだ。各エージェント(役割)はその責務に関連するツールのみを参照する。ED医師(coordinator)は専門医(subagent)に派遣するが、専門医のツールを直接操作しない。すべての医師がすべてのツールを持つ病院は悲惨なことになる。すべてのエージェントがすべてのツールを持つエージェントシステムは単に非効率でエラーが起きやすくなるが、同じ原則が当てはまる。
Analogy 2: 自動販売機のセレクター — tool_choiceのモード
自動販売機にはtool_choiceにきれいにマッピングされる3種類の「購入強制」構成がある。autoモードでは、自由に歩み寄り、カタログを見て、何かを買うかどうかを決める。何も買わないかもしれない。anyモードでは、誰かが前払いカードを渡してきて去る前に使わなければならない。何かを買わなければならないが、どのお菓子を選ぶかはまだ自分で決める。forcedモードでは、誰かが手を伸ばして自分でボタンコードを入力して「ピーナッツM&Mを買うんだ。交渉の余地はない」と言う。noneは4番目の構成:機械が使用中止で、いかなる選択も許可されない。各モードには理由がある。autoは購入がオプションの場合に正しい。anyは何かを買わなければならないが選択は自分の場合に正しい。forcedは特定のアイテムが交渉不可の場合に正しい。noneは機械を完全に通り過ぎるべき場合に正しい。「any」と「forced」を混同することは、プリペイドカードが特定のお菓子に固定すると思うようなものだ。固定しない。ただ購入を強制するだけだ。
Analogy 3: 建設現場の許可証 — 許可デスクでのアクセス制御
規制された建設現場では、各作業員は操作が認定された機器を正確に列挙した許可証バッジを持つ。大工チームはのこぎりと釘打ち機の許可証を持つ。電気チームは配管とブレーカーの許可証を持つ。クレーンオペレーターはクレーンのみの許可証を持つ。作業員が機器をスキャンすると、リーダーが許可証を機械と照合する。許可証が一致しない作業員は機器を物理的に起動できない。インターロックが拒否する。これはtool access controlを許可デスクとして表現したものだ。バッジ(allowed_toolsリスト)が作業員(エージェント)が触れられるものを決定する。クレーンに「認定を受けていない限りクレーンを操作しないで」と書くことはプロンプトベースの制約だ。点火時の許可証強制は配布ベースの制約だ。試験は一貫して後者を好む。最初のものは準拠に依存し、2番目のものは構造的に違反が不可能だからだ。エージェントは許可証を持っていないツールを誤用できない。
どの比喩がどの試験問題に合うか
- 各エージェントが保有すべきツールについての質問 → 病院の診療科の比喩。
auto・any・forced・noneの選択についての質問 → 自動販売機の比喩。- スコープ外のツール使用を防ぐについての質問 → 建設現場の許可証の比喩。
よくある試験のトラップ
CCA-Fタスク2.3は、アウトラインに名前が挙げられている2つのトラップと、コミュニティの合格レポートで記録されているいくつかの高頻度の暗黙のトラップを示す。
トラップ1:anyを「特定のツールを強制する」として扱う
アウトラインはこれを明示的に挙げている。tool_choice: anyは特定のツールを保証しない。テキスト応答を禁じるだけだ。2つ以上のツールが見えてビジネスロジックがそのうちの1つを正確に必要とする場合、anyは不十分だ。正しい値はforced tool object { type: "tool", name: "<specific>" }だ。distractor の答えは定期的にanyを「エージェントをタスクに集中させる」や「正しいツール呼び出しを強制する」と表現する。どちらのフレーミングも間違いだ。anyはforcedより弱く、代替として使うべきでない。
トラップ2:Forced tool_choiceを「Claudeがこのツールをより深く考える」として扱う
再びアウトラインから:forced tool_choiceはClaudeの選択判断を完全にバイパスする。ツールが現在の状態に対して正しいかどうかについてClaudeの推論を向上させない。単に呼び出しを義務付け、アーキテクチャが状態を正しく設定していることを信頼する。forcedツールがターンに対して間違っている場合でも、Claudeは構築できるinputを使ってベストエフォートの呼び出しを出力する。forcedモードを「Claudeが正しいツールを選ぶのを助ける」と説明する答えはメカニズムを誤って述べている。
トラップ3:過大なツールカタログを「安全な」選択として扱う
繰り返す distractor は「エッジケースに対応できるようにすべてのプラットフォームツールへのアクセスを与える」と言う。コミュニティの合格レポートはこれを一貫して間違いと識別する。過大なカタログは選択精度を低下させ、コンテキストコストを膨張させ、爆発半径を広げる。修正の正しい方向は常により厳格なスコーピングだ。
トラップ4:プロンプトベースのアクセス制御を配布の代替として提案する
繰り返す distractor は「delete_userを呼び出さないようにシステムプロンプトに指示を追加する」と提案する。これは準拠に依存するプロンプトベースの制約だ。正しい答えはエージェントのtools配列からdelete_userを完全に削除する。配布はハードな境界であり、プロンプトはソフトな境界だ。試験はハードな境界を好む。
トラップ5:autoが十分な場合にanyを使用する
候補者は「エージェントがツールを確実に使うように」という防御的なデフォルトとしてanyに頼ることがある。オープンエンドなワークフローでは、autoがほぼ常に正しい答えだ。Claudeはツールが有用な場合にツールを使用し、テキストが適切な場合にテキストで応答する。ツールが必要ない場合にanyでツール呼び出しを強制すると、inputが貧弱なツール呼び出しの品質が低くなる。
実践アンカー
Tool distributionとtool_choiceの概念はすべてのCCA-Fシナリオクラスターに現れるが、2つのシナリオで最も高いウェイトを持つ。
Developer-Productivity-With-Claudeシナリオ
開発者がSDK駆動のエージェントを使用して大きなコードベース全体で自律的なタスクを実行する。異なる役割は異なるツールセットを必要とする:調査エージェントはRead・Grep・Globが必要、リファクタリングエージェントはEdit・Writeが必要、テスト作成エージェントはWrite・Read・Bashが必要。coordinator-subagent分割でどのエージェントがBashを保有すべきか、どれがEditを保有すべきか、どれがReadのみを保有すべきかを問うシナリオ問題を予期する。パイプラインステージでのtool_choice問題も予期する:調査ステージはauto、最終サマリーステージはnone、特定の構造化成果物(リファクタリングプランレコードなど)を出力しなければならないステージはforced tool choice plus strict: true。
Multi-Agent-Research-Systemシナリオ
このシナリオでは、coordinatorがリサーチsubagentを派遣し、その発見を収集し、最終レポートを組み立てる。ツール配布の決定がアーキテクチャの骨格だ。coordinatorはsubagent派遣ツールと状態管理を保有し、各リサーチsubagentはウェブ検索と要約ツールを保有し、どちらも相互汚染すべきでない。coordinator対subagentのツールセット分割・最終レポート出力ステップにスキーマを強制するためのforced tool_choiceの決定・subagentがさらなるsubagentをスポーンするのを防ぐための動的ツール可用性の決定を問う質問を予期する。
FAQ — Tool DistributionとTool Choice上位5問
tool_choice: anyとforced tool objectの違いは何か?
tool_choice: anyは「Claudeはカタログから何らかのツールを呼び出さなければならないが、どれかは指定しない」という意味だ。Claudeは引き続きすべての見えるツールにわたって選択判断を行使する。Forced tool object { type: "tool", name: "<specific>" }は「Claudeはこの特定のツールを正確に呼び出さなければならない」という意味だ。forcedの形式では選択判断はない。ツール呼び出しが必要だがいくつかのうちのどれでも受け入れられる場合にanyが適切であり、スキーマ強制または確定的なパイプラインステージが正確に1つのツールを必要とする場合にforcedが適切である。それらを交換可能として扱うことはCCA-Fタスク2.3で最も高い頻度のトラップの1つであり、anyは特定のツールを保証しない。
ClaudeからスキーマのあるJSONを強制するにはどうすればよいか?
CCA-F標準のパターンは3つのメカニズムを組み合わせる:(1) input_schemaが望む出力スキーマに一致するツールを定義する、(2) そのツール定義にstrict: trueを設定する、(3) パイプラインの最終ターンに、そのツールに名前を付けたforced tool objectにtool_choiceを設定する。一緒にして3つの保証を生む:Claudeが正しいツールを呼び出す・ツールのinputがスキーマに正確に準拠する・アプリケーションがパーシングや検証オーバーヘッドなしに出力を直接消費できる。「このスキーマに合うJSONを返して」のようなプロンプトベースの指示はAPIレベルの強制ではなくプロンプト準拠に依存するため劣る。
単一エージェントにどのくらいのツールを与えるべきか?
試験は数値の閾値を指定しないが、方向は明確だ:役割をカバーする程度まで少ないほど良い。エージェントの1文の役割説明から始め、到達可能でなければならない名詞と動詞を列挙し、到達可能な概念ごとに正確に1つのツールを割り当てる。役割のニーズを超えるカタログは選択精度を低下させ、コンテキストコストを膨張させ、爆発半径を広げる。エージェントが大きなツールセットを必要とする場合、coordinatorとsubagentへの分割・重複するツールの統合・動的ツール可用性でワークフローフェーズに見えるツールをスコープすることを検討する。
同一のagentic loop内のターンをまたいでtool_choiceを変化させることはできるか?
はい、これは第一級の設計パターンだ。tool_choiceはMessages API呼び出しごとに設定されるため、単一のループが合法的に探索的な調査ターンではautoを使用し、スキーマ準拠の出力ターンを強制するためにforced tool objectに切り替え、最終的な自然言語サマリーターンにはnoneに切り替えることができる。このパターンは構造化extractionパイプライン・マルチフェーズリサーチエージェント・異なるターンが異なる動作制約を持つあらゆるワークフローで使用される。
エージェントがアクセスすべきでないツールを呼び出すのを防ぐにはどうすればよいか?
エージェントのtools配列(またはsubagentのallowed_toolsリスト)からツールを削除する。配布層での不可視性はハードな構造的境界だ。Claudeがそれを見られないためツールを呼び出すことができない。「管理者でない限りdelete_userツールを呼び出さないで」のようなプロンプトベースの指示はソフトな境界であり、準拠に依存し、設計によって時々失敗する。多層防御のために、配布時スコーピングをツール実装内のサーバーサイド認可および特定の呼び出しを実行時に拒否できる(任意で)PreToolUseフックと組み合わせる。CCA-Fはプロンプトベースのアクセス制御よりハードな境界の答えを一貫して好む。
参考資料
- Define tools — best practices for tool descriptions and tool_choice: https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/implement-tool-use
- Tool use with Claude — overview and agentic loop: https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/overview
- Handle tool calls — tool_result format and error responses: https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/handle-tool-calls
- Create custom subagents — Claude Code Docs: https://docs.anthropic.com/en/docs/claude-code/sub-agents
- Strict tool use — schema-guaranteed output: https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/strict-tool-use
- Writing tools for agents — Anthropic Engineering Blog: https://www.anthropic.com/engineering/writing-tools-for-agents
関連するExamLabのトピック:Tool Interface Design — Descriptions and Boundaries、Multi-Agent Orchestration with Coordinator-Subagent Patterns、Subagent Invocation, Context Passing, and Spawning、MCP Server Integration into Claude Code。