AIエージェントのツール選択を改善する設計ガイド
エージェントにはupdateUserとdeactivateUserという2つのツールを与えました。サポートチケットには「このアカウントを閉鎖してください」と書かれていました。エージェントはdeactivateUserを呼び出しました。ところが先週、ほぼ同じチケットに対しては、updateUserをstatus: "closed"で呼び出していました。APIには受け入れられましたが、下流では少し異なる意味を持つ処理です。
何も壊れていません。モデルが、説明だけでは区別できないもっともらしい2つの選択肢から、誤ったツールを選んだのです。
ツール選択の失敗はモデルのせいにされがちですが、モデルが判断材料として使えるのは、会話、システムプロンプト、ツール定義だけです。本記事では、モデルがツール選択時に読む情報、識別しやすい名前と説明、エラーを減らすパラメータ設計、そして説明変更による退行を検出するテスト方法を解説します。
OpenAPI仕様をエージェントツールに変換する場合は、仕様に何を含めるかがそのままツール設計になります。API定義がApidogにあるなら、説明を改善することでドキュメントとツールを同時に改善できます。
モデルが実際に読むもの
ツール選択の瞬間、モデルが持っているのは次の情報です。
- 会話
- システムプロンプト
- ツール定義の一覧
- 各ツールの名前、説明、パラメータスキーマ
モデルは、あなたのAPIドキュメント、コードコメント、updateUserがレガシーであるというチーム内の知識を持っていません。
つまり、曖昧さの解消に必要な情報はツール定義そのものに書く必要があります。OpenAIの関数呼び出しガイドとAnthropicのツール利用ドキュメントも、説明が重要であり、簡潔さより十分な具体性を優先すべきだと示しています。
代表的な選択エラーは4種類です。
- 定義が重複している 類似ツールの説明に「いつ使わないか」まで書く。
- ユーザーの言葉と説明が一致しない チケットや会話で使われる語彙を説明に入れる。
-
パラメータが曖昧である
型、
enum、単位、形式を明記する。 - 実行順序が不明である 前提条件と、先に呼ぶべきツールを説明する。
ツール名は機能に合わせて命名する
モデルは名前を最初に読むため、名前には大きな識別力があります。
verbNoun形式を統一する
ツールセット全体で次のような規則を使います。
createOrderrefundOrdergetOrderStatus
order_create、getOrder、refundのように形式が混在すると、各ツールの比較が難しくなります。
オブジェクトと操作を具体化する
searchは何をどのように検索するのか不明です。一方、searchCustomersByEmailなら対象と検索方法が分かります。
内部用語も避けてください。APIが顧客をentity、サブスクリプションをinstrumentと呼んでいても、ユーザーの「customer」や「plan」という表現には結び付きません。ツール名はスキーマの言語ではなく、タスクの言語で命名します。
また、異なる名前空間でlistのような名前を使い回さないでください。1つのツール一覧に並ぶと、すぐに曖昧になります。
識別できる説明を書く
説明は最低限、次の4点に答えるべきです。
- 何をするか
- 何を変更するか
- いつ使うか
- いつ使わないか
これは弱い例です。
{ "name": "updateUser", "description": "ユーザーを更新します。" }
{ "name": "deactivateUser", "description": "ユーザーを無効化します。" }
次のように、境界を明示してください。
{
"name": "updateUser",
"description": "名前、メールアドレス、タイムゾーンなど、アクティブなユーザーのプロフィールフィールドを更新します。ユーザーからの修正やプロフィール編集の要求に使用してください。アカウントの状態を変更するものではありません。アカウントを無効にするには、代わりにdeactivateUserを使用してください。アカウントを閉鎖またはキャンセルするために使用しないでください。"
}
{
"name": "deactivateUser",
"description": "ユーザーアカウントを無効にし、すべてのセッションを取り消し、サインインをブロックします。reactivateUserで元に戻すことができます。顧客がアカウントの閉鎖、キャンセル、一時停止、または停止を要求した場合に使用してください。データを削除するものではありません。永続的な削除には、元に戻せないdeleteUserを使用してください。"
}
この例では、次の4つが機能しています。
-
関連ツールを参照する
「代わりに
deactivateUserを使用してください」と書くと、モデルが比較している時点で判断できます。 - ユーザーの語彙を含める 「close」「cancel」「pause」「suspend」のように、実際のチケットに現れる言葉を入れます。
- 使わない場面を書く 隣接するツールは肯定的な説明が似るため、否定的な説明の方が識別力を持ちます。
- 可逆性と危険性を示す 取り消し可能か、データを削除するかを明記します。AIエージェントのガードレールと組み合わせ、実行側でも制御してください。
説明が100語程度になっても問題ありません。破壊的なエンドポイントの誤呼び出しを1回防げるなら、十分に安いコストです。
間違った引数を渡しにくくする
正しいツールを選んだ後は、引数が次の失敗点になります。
JSON Schemaには、多くの必要な制約が用意されています。JSON Schemaの検証語彙で利用できるキーワードを確認しましょう。
閉じた集合にはenumを使う
文字列だけのstatusでは、モデルが存在しない値を生成できます。
"status": {
"type": "string",
"enum": ["pending", "paid", "refunded", "cancelled"],
"description": "注文ステータス。「cancelled」は未履行を意味し、「refunded」は履行後に取り消しされたことを意味します。"
}
単位をパラメータ名に含める
amountはドルかセントか分かりません。amount_centsなら曖昧さがありません。
同様に、次のような名前を使います。
timeout_secondsdistance_metersduration_ms
日付形式には例を示す
"description": "ISO 8601形式の開始日、例: 2026-08-26"
「開始日」とだけ書くより、正しい形式を生成しやすくなります。
requiredはAPIの実際の制約に合わせる
すべてをオプションにすると、エラーが実行時に発生します。逆に、APIがデフォルト値を設定する項目を必須にすると、モデルが不要な値を生成します。どちらもAIエージェント向けAPIエラー設計で扱うべき検証エラーにつながります。
ネストを減らす
次のような構造は、構造的な間違いを誘発します。
{"customer": {"address": {"postal_code": "..."}}}
ツール境界では、次のようにフラット化し、エグゼキュータ側で再構成する方法を検討してください。
{"customer_postal_code": "..."}
オーバーロードされたツールを分割する
modeによって他のフィールドの意味が変わるツールは、実質的に複数のツールです。分割すれば、選択もスキーマも簡単になります。
前提条件と順序を明記する
複数ステップの処理は、依存関係を説明に書かないと失敗します。
{
"name": "captureCharge",
"description": "以前承認されたチャージをキャプチャします。authorizeChargeからのauthorization_idが必要です。authorization_idをまだ持っていない場合は、最初にauthorizeChargeを呼び出してください。承認された金額を超えるキャプチャはできません。"
}
「更新の前に作成」「処理の前にアップロード」「キャプチャの前に承認」のような依存関係も同じです。依存するツールの名前が説明にない場合、モデルは前のステップをスキップする可能性があります。
複数の呼び出しではなく、複数のエージェント間で順序を引き継ぐ場合は、サブエージェント間のコンテキスト受け渡しのルールも適用してください。
ツール選択をテストする
説明はコードと同じく退行します。誰かがスタイルガイドに合わせて説明を短くしただけで、次の週から別のエンドポイントが選ばれることもあります。
小規模な選択テストスイートを作りましょう。
- 期待するツールを指定したプロンプトを20〜50個用意する。
- モデルが選択したツール名を記録する。
- 引数ではなく、ツール名をアサートする。
- 各プロンプトを複数回実行する。
これは、非決定性AIエージェントのテストを実装する実践的な方法です。
最初は、次のケースを含めてください。
- 最も似ている2つのツールに振り分けるプロンプト
- API用語ではなく顧客用語を使うプロンプト
- どのツールにも一致しないプロンプト
- 間違えるとコストが発生する破壊的ツール
一致しない場合の正しい動作は、無理に呼び出すことではなく、追加で質問することです。
各プロンプトを5回実行し、4回しか成功しないツールは本番ではコイン投げと同じです。説明を改善してください。
テストはライブデータに接続せず、モックへ向けます。本番環境の代わりにモックに対してエージェントを実行する方法については、こちらのガイドも参照してください。Apidogなら、ツールの生成元と同じ定義からモックを提供できるため、スキーマと振る舞いを一致させられます。
典型的に失敗する3つのツールセット
CRUDセット
getUser、listUsers、searchUsers、queryUsersのように、長年のAPI拡張で似たエンドポイントが増えたセットです。モデルにとっては、1つの概念に対する4つの名前に見えます。
すべてに説明を追加するより、エージェントには必要な1つだけを公開し、残りをツールリストから外してください。厳選したセットは、完全なセットより優れています。
Adminセット
getInvoice、voidInvoice、deleteInvoiceのように、読み取り操作と破壊的操作が同じトーンで並んでいるセットです。
説明に結果と危険性を追加し、承認が必要な操作としてマークしてください。ただし、説明だけを信頼せず、実行者側でも強制します。この多層防御については、AIエージェントがAPIを破壊するのを防ぐで詳しく解説しています。
Legacyセット
同じ機能を持つエンドポイントが2つあり、一方が非推奨になっているセットです。仕様に両方が残っていると、ジェネレータは両方を出力し、エージェントは古い方を選ぶことがあります。
非推奨の操作を生成ツールから削除するのが最善です。残す場合は、説明の冒頭に次のように書きます。
非推奨。代わりに
createOrderV2を使用してください。
この行が先頭にある場合、モデルは比較的よく尊重します。説明の末尾に埋め込むだけでは無視されやすくなります。
説明を共有アーティファクトとして管理する
ツール説明が振る舞いを左右するなら、誰が所有するかを決める必要があります。個人のマシンに保存された設定に依存すると、開発者ごとに異なる挙動が生まれます。
ツールセットを、他のインターフェースと同じようにレビューする共有アーティファクトとして扱いましょう。
エージェント中心のプラットフォームでは、この仕組みを直接モデル化できます。Sharklyエージェントは、指示、ランタイム、スキル、リポジトリを含む保存済み設定です。スペースで共有すれば、1人の作業設定をチーム全体で再利用できます。
価値は単なるストレージではありません。説明の変更が、個人のローカル調整ではなく、チーム全体に影響するレビュー可能な変更になります。
ユーザーの言葉を説明に入れる
最も大きなギャップは語彙です。
APIでは「subscription」と呼んでいても、顧客は「plan」「membership」「billing」と言うかもしれません。「deactivate」も、顧客からは「cancel」「close」「turn off」と表現されます。
サポートチケット、検索ログ、失敗したエージェント実行のトランスクリプトから、実際に使われるフレーズを集めましょう。そして、それらを対応するツールの説明に入れます。
この作業は1時間程度でも、スキーマを細かく調整するより選択精度を改善できることがあります。
エージェントがツールを選ばず、知識だけで回答する場合も注意してください。推論の失敗ではなく、ユーザーの語彙とツールの説明が一致していないために、ツールが見えていない可能性があります。
ツールセットのチェックリスト
- 名前が一貫した
verbNoun規則に従い、対象オブジェクトを特定している - 説明に、変更内容、使用条件、非使用条件が含まれている
- 重複するツールが互いを明示的に参照している
- ユーザーが実際に使う語彙が説明に含まれている
- 破壊的・不可逆な操作であることが明記されている
- 閉じた集合に
enumが設定されている - 単位と形式がパラメータ名または説明に含まれている
- 形式には具体例がある
-
requiredがAPIの実際の制約と一致している - 依存するツールと前提条件が名前付きで示されている
- モックを使った選択テストがCIで実行されている
モデルは、あなたが書いたテキストのパターンを使って選択しています。間違った選択が起きたら、まず説明を確認してください。多くの場合、修正すべき場所はそこです。
Apidogをダウンロードすれば、説明、モック、テストを1つのプロジェクトで管理できます。
よくある質問
ツール説明の長さはどれくらいが適切ですか?
曖昧さを解消できる長さにします。通常は2〜5文が目安です。曖昧でないツールは短くし、隣接するツールの区別にコンテキストを使ってください。
説明に例を入れるべきですか?
形式や単位には例を入れることを推奨します。長い使用例はコンテキストを消費する一方で、選択精度をあまり改善しないため、通常は不要です。
狭いツールを多数持つべきですか?
ある程度までは、1つのことだけを行う狭いツールの方が選択しやすくなります。ただし、数十を超えるとツール一覧自体が問題になります。OpenAPIからエージェントツールを生成する場合は、フィルタリングや検索も検討してください。
システムプロンプトで選択を修正できますか?
既知の混乱が1〜2個だけなら、一時的な対策として使えます。しかし、スケーラブルではありません。システムプロンプトは全ツールで共有されますが、説明は必要なツールと一緒に移動できるからです。
モデルがパラメータ値を生成し続ける場合は?
型を制約し、enumを追加し、値は以前の呼び出しから取得するものであって生成するものではないと説明します。それでも発生する場合は、ラッパーで検証し、許可された値を含むエラーを返してください。
これらのルールはMCPサーバーにも適用されますか?
はい。MCPサーバーも名前、説明、スキーマを同じように公開するため、同じ設計ルールが適用されます。MCPとは何かについては、こちらの解説を参照してください。


Top comments (0)