エージェントにはupdateUserとdeactivateUserという2つのツールを与えました。サポートチケットには「このアカウントを閉鎖してください」と書かれていました。エージェントはdeactivateUserを呼び出しました。先週、ほぼ同じチケットが届いた際には、updateUserをstatus: "closed"で呼び出し、それはAPIで受け入れられ、下流で若干異なる意味を持っていました。
何も壊れていませんでした。モデルは、どちらが適用されるかを説明が示していない、もっともらしい2つの選択肢の間で選択を誤ったのです。ツール選択は、人々がモデルのせいにし、スキーマで修正する失敗モードです。なぜなら、モデルが頼れるのはスキーマだけだからです。
このガイドでは、モデルがツールを選択する際に実際に何を読んでいるのか、識別しやすい名前と説明の書き方、パラメータ設計がエラー率をどのように変えるのか、そして言葉の変更によって黙って壊れないように選択をテストする方法について解説します。例えば、OpenAPI仕様をエージェントツールに変換するという私たちのガイドのように、ツールが仕様から生成される場合、これはその仕様に何を含めるべきかという問題になります。
ツールがAPI定義から来ている場合、説明はApidogに存在します。そのため、説明を改善することは、ドキュメントとツールの両方を同時に改善することになります。
モデルが見るもの
選択の瞬間、モデルは会話、システムプロンプト、そしてツール定義のリストを持っています。各定義は名前、説明、そしてパラメータスキーマです。モデルはあなたのAPIドキュメント、コードコメント、あるいはupdateUserがレガシーであるという部族知識を持っていません。
これは、すべての曖昧さの解消は定義そのものに書かれなければならないことを意味します。OpenAIの関数呼び出しガイドとAnthropicのツール利用ドキュメントは、同じ点を指摘しています。それは、説明が定義全体の中で最も重要なテキストであり、簡潔であるよりも冗長であるべきだということです。
選択エラーには4つのパターンがあり、それぞれ異なる修正方法があります。
2つの定義が重複している場合、モデルは類似のツールを選択します。これを修正するには、それぞれの説明を、いつそのツールを使わないべきかを明確に記述するようにします。タスク言語と一致する説明がない場合、モデルは何も選択せず、記憶から回答します。これを修正するには、ユーザーが使う言葉を使用します。パラメータが曖昧な場合、モデルは正しいツールを選択するものの、間違った引数を使用します。これを修正するには、型、enum、および単位を使用します。順序が重要で、それが何も示されていない場合、モデルはツールをうまく連鎖できません。これを修正するには、前提条件を説明に明記します。
ツール名をその機能に合わせて命名する
モデルは名前を最初に読むため、名前はその長さが示唆する以上の情報量を持っています。
verbNoun形式をツールセット全体で一貫して使用してください。例:createOrder、refundOrder、getOrderStatus。個々の選択と同様に一貫性が重要です。なぜなら、order_create、getOrder、refundが混在するセットは、それぞれの名前をわずかに読みづらくするからです。
オブジェクトについて具体的に記述してください。searchは悪いツール名です。searchCustomersByEmailは良いツール名であり、何が検索され、どのように検索されるかをモデルに伝えます。
内部的な専門用語は避けてください。APIが顧客を「entity」、サブスクリプションを「instrument」と呼んでいても、モデルはそれらを「customer」や「plan」と書かれたチケットに結びつけません。ツール名は、スキーマの言語ではなく、タスクの言語で命名してください。
コンテキストをまたいで名前を再利用しないでください。異なる名前空間にある2つのlistというツールは、1つのリストに現れるとすぐに曖昧になります。
識別できる説明を書く
有用な説明は4つの質問に答えます。何をするか、何を変えるか、いつ使うか、そしていつ使わないかです。
これは弱いペアの例です。
{ "name": "updateUser", "description": "ユーザーを更新します。" }
{ "name": "deactivateUser", "description": "ユーザーを無効化します。" }
そして、実際に区別できるペアの例です。
{
"name": "updateUser",
"description": "名前、メールアドレス、タイムゾーンなど、アクティブなユーザーのプロフィールフィールドを更新します。ユーザーからの修正やプロフィール編集の要求に使用してください。アカウントの状態を変更するものではありません。アカウントを無効にするには、代わりにdeactivateUserを使用してください。アカウントを閉鎖またはキャンセルするために使用しないでください。"
}
{
"name": "deactivateUser",
"description": "ユーザーアカウントを無効にし、すべてのセッションを取り消し、サインインをブロックします。reactivateUserで元に戻すことができます。顧客がアカウントの閉鎖、キャンセル、一時停止、または停止を要求した場合に使用してください。データを削除するものではありません。永続的な削除には、元に戻せないdeleteUserを使用してください。"
}
ここでは4つのテクニックが機能しています。
関連するツール名を挙げる。「代わりにdeactivateUserを使用してください」は、モデルがそれらを比較しているまさにその瞬間に、曖昧さを直接解消します。
ユーザーの語彙を含める。「close(閉鎖)」「cancel(キャンセル)」「pause(一時停止)」「suspend(停止)」といった単語が登場するのは、それらがチケットに現れる単語だからです。これは、あなたが加えられる変更の中で最も高いリターンをもたらし、ほとんどコストがかかりません。
しないことを述べる。否定的な記述は肯定的な記述よりも識別力があります。なぜなら、隣接する2つのツールの肯定的な主張は似てしまいがちだからです。
可逆性を明示する。リスクがあることを伝えると、モデルはそのリスクについて推論します。これは、AIエージェントのガードレールに関する私たちの投稿にある施行パターンと対になり、そこで真の保護が発揮されます。
長さは問題ありません。破壊的なエンドポイントへの誤った呼び出しを1回防ぐ100語の説明は、安価なものです。
間違った引数を渡しにくくするパラメータ設計
正しいツールが選択された後、次に問題が発生するのは引数です。
JSON Schemaは、ここで必要な制約のほとんどを提供しており、JSON Schemaの検証語彙は、ツール呼び出しAPIがサポートするキーワードをざっと見る価値があります。
セットが閉じている場合は常にenumを使用する。文字列として型付けされたstatusパラメータは、モデルが値を勝手に作り出す可能性があります。enumとして型付けすることで、モデルはAPIが受け入れる値に制約されます。
"status": {
"type": "string",
"enum": ["pending", "paid", "refunded", "cancelled"],
"description": "注文ステータス。「cancelled」は未履行を意味し、「refunded」は履行後に取り消しされたことを意味します。"
}
単位を名前に含める。amountは曖昧であり、モデルはドルまたはセントを不一貫に推測するでしょう。amount_centsは決して曖昧ではありません。同様に、timeout_seconds、distance_meters、duration_msも同様です。
日付形式には例を示す。"description": "ISO 8601形式の開始日、例: 2026-08-26"は、「開始日」とだけ書くよりもはるかに高い頻度で正しくフォーマットされた日付を生成します。
必須リストは正直に設定する。すべてをオプションとマークすると、失敗は実行時に発生します。APIが賢明にデフォルト値を設定するものを必須とマークすると、モデルは値を生成します。どちらも一般的であり、どちらもAIエージェント向けAPIエラー設計に関する私たちの投稿でカバーされている検証エラーとして現れます。
ネストされたものよりもフラットな構造を好む。{"customer": {"address": {"postal_code": "..."}}}を埋めるモデルは、customer_postal_codeの場合には発生しない構造的な間違いを犯します。ツール境界でフラット化し、エグゼキュータで再構成してください。
オーバーロードされたツールを分割する。modeパラメータによって他のすべてのフィールドの意味が変わるツールは、実質的に2つのツールです。これを分割することで、選択が改善され、両方のスキーマが簡素化されます。
前提条件と順序を明記する
複数ステップの作業は、モデルが順序を知らない場合に失敗します。依存するツールの説明でそれを明記してください。
{
"name": "captureCharge",
"description": "以前承認されたチャージをキャプチャします。authorizeChargeからのauthorization_idが必要です。authorization_idをまだ持っていない場合は、最初にauthorizeChargeを呼び出してください。承認された金額を超えるキャプチャはできません。"
}
たった2行で、モデルがすでに読んでいる場所で順序の問題が処理されます。この原則は、すべてのクラスに当てはまります。更新の前に作成、処理の前にアップロード、キャプチャの前に承認。依存するステップの説明で前のステップの名前が示されていない場合、モデルはそれをスキップすると予想されます。順序が複数の呼び出しではなく複数のエージェントにまたがる場合、サブエージェント間のコンテキスト受け渡しに関する私たちの投稿にある引き渡しルールが適用されます。
他の振る舞いと同様に選択をテストする
説明はコードであり、退行します。誰かがスタイルガイドに合わせるために説明を短くし、エージェントが来週には間違ったエンドポイントを選択し始めるかもしれません。
小規模な選択スイートを構築してください。それぞれに期待するツールを指定した20〜50個のプロンプトを用意します。それらを実行し、モデルが選択したツールを記録し、名前のみをアサートします。引数は実行ごとに異なる可能性がありますが、選択は変わるべきではありません。これは、非決定性AIエージェントのテストに関する私たちのガイドで述べられているアプローチの実践的な形です。
次のような、失敗する可能性が最も高いケースでスイートを初期化します。
- セット内で最も類似する2つのツールについて、それぞれにルーティングされるべきプロンプト。
- API語彙ではなく顧客語彙を使用したプロンプト。
- 何も一致しないはずのプロンプト。正しい動作は、強制的に呼び出すのではなく、質問することです。
- 破壊的なツール。間違った選択は実際のコストを伴います。
各プロンプトを複数回実行してください。5回中4回成功するツールは、本番環境ではコイン投げのようなものであり、説明の改善が必要です。
選択テストがライブデータに触れないように、実行をモックに向けます。本番環境の代わりにモックに対してエージェントを実行するに関する私たちの投稿では、セットアップについて解説しています。そして、Apidogは、ツールの生成元と同じ定義からこれらのモックを提供できるため、スキーマと振る舞いが一致した状態を保てます。

同じように失敗する3つのセット
CRUDセット。APIがgetUser、listUsers、searchUsers、queryUsersを公開しているが、これらは長年にわたって成長したエンドポイントから生成されたものです。モデルにとってこれらは1つのアイデアに対する4つの名前です。修正策は、これら4つすべてに良い説明を付けることではありません。エージェントにはそのうちの1つだけを公開し、残りをツールリストから外すことです。厳選されたセットは、完全なセットよりも常に優れています。
Adminセット。読み取りツールと破壊的ツールが、getInvoice、voidInvoice、deleteInvoiceのように同じトーンで並んでいます。テキストには、これら2つがキャリアを終わらせる可能性があることを示すものが何もありません。説明に結果を追加し、承認が必要なものとしてマークし、言葉を信頼するのではなく、実行者側で強制します。この多層的なアプローチについては、AIエージェントがAPIを破壊するのを防ぐという私たちの投稿で解説しています。
Legacyセット。同じ機能を果たす2つのエンドポイントがあり、1つは非推奨です。仕様には両方がリストされているため、ジェネレータは両方を出力し、エージェントはほぼ半分の確率で古い方を選択します。この場合、生成されたツールから非推奨の操作を削除するか、説明の先頭に「非推奨。代わりにcreateOrderV2を使用してください。」と記載します。モデルは、この行が最初にある場合はそれを尊重しますが、最後に埋もれている場合は無視します。
説明は共有設定である
ツール説明が振る舞いを駆動するということを受け入れると、次に問題となるのは、誰がそれらを所有するのかということです。ほとんどのチームでは、その答えは偶発的です。最初にエージェントを設定した人が、自分のマシンのファイルに保存している、といった具合です。
ツールセットを、他のインターフェースと同様にレビューされる共有アーティファクトとして扱ってください。エージェント作業を中心に構築されたプラットフォームは、これを直接モデル化することがよくあります。Sharklyエージェントは、指示、ランタイム、スキル、およびリポジトリをカバーする保存された設定であり、それをスペースで共有することで、ある人の作業設定がチームによって再利用可能になります。その価値はストレージにあるのではありません。説明の変更が、開発者の一人のエージェントの振る舞いを他と異なるものにするサイレントなローカル調整ではなく、誰もが影響を受けるレビュー可能な編集になるという点にあります。

ユーザーが使う言葉に注目する
最も一般的なギャップは語彙です。あなたのAPIでは「subscription(サブスクリプション)」と言いますが、顧客は「plan(プラン)」「membership(メンバーシップ)」「billing(請求)」と言うかもしれません。あなたのAPIでは「deactivate(無効化)」と言いますが、彼らは「cancel(キャンセル)」「close(閉鎖)」「turn off(停止)」と言うでしょう。
実際の言語を収集してください。サポートチケット、検索ログ、または失敗したエージェント実行のトランスクリプトから上位のフレーズを抽出し、それらが一致するはずのツールの説明に組み込みます。これには1時間かかりますが、通常、スキーマをどれだけ調整するよりも選択の精度が向上します。
失敗にも目を光らせてください。エージェントが何も選択せず、自身の知識から回答する場合、それは推論の失敗ではなく、語彙のミスマッチです。タスク言語とツールテキストが重ならなかったため、ツールが見えなかったのです。
ツールセットのチェックリスト
- 名前は一貫した
verbNoun規則に従い、特定のオブジェクトを指していること。 - すべての説明は、何が変更され、いつ使用すべきか、いつ使用すべきでないかを述べていること。
- 重複するツールは互いを明示的に指していること。
- 説明には、内部的な用語だけでなく、ユーザーが実際に使用する言葉が含まれていること。
- 破壊的で不可逆なアクションは、説明でその旨が述べられていること。
- すべての閉じたセットに対してenumが宣言されていること。
- 単位と形式は、パラメータ名または説明に例とともに記載されていること。
- 必須リストは、APIが実際に強制するものと一致していること。
- 依存するツールはその前提条件を名前で示していること。
- CIでモックに対して選択スイートが実行されていること。
モデルは、あなたが書いたテキストに対してパターンマッチングを行っています。モデルが間違った選択をした場合、最初に確認すべき場所はテキストであり、通常、変更が必要な唯一の場所もそこです。Apidogをダウンロードすれば、説明、モック、テストを1つのプロジェクトで管理できます。
よくある質問
ツール説明の長さはどれくらいが良いですか? 曖昧さを解消できる程度で、通常は2〜5文です。説明はコンテキストを占有するので、曖昧さのないツールは短くし、隣接するツールにスペースを割いてください。
説明に例を入れるべきですか? フォーマットや単位については、例を入れることで多くの間違いを防げるため、推奨します。長い使用例は、コンテキストコストがかかり、選択をほとんど変えないため、スキップしてください。
狭いツールを多数持つか、柔軟なツールを少数持つか、どちらが良いですか? ある程度の点までは、狭いツールの方が良いです。それぞれのツールが1つのことを行うため、選択の信頼性が高まります。数十を超えると、リスト自体が問題となり、OpenAPIからエージェントツールを生成するという私たちの投稿で述べられているように、フィルタリングや検索が必要になります。
システムプロンプトで選択を修正できますか? 部分的には可能で、1つか2つの既知の混乱に対する合理的な一時しのぎにはなります。しかし、スケーラブルではありません。プロンプトはすべてのツールで共有されるのに対し、説明はそれが必要なツールとともに移動するからです。
モデルがパラメータ値を勝手に生成し続ける場合はどうすればよいですか? 型を制約し、enumを追加し、その値が以前の呼び出しから得られるべきであり、生成されるべきではないことを説明に明記してください。それでも発生する場合は、ラッパーで検証し、許可された値を示すエラーを返してください。
これらのルールはMCPサーバーにも適用されますか? はい。MCPサーバーは同じ形式で名前、説明、スキーマを公開するため、同じ文言のルールが適用されます。MCPとは何かについての私たちの解説では、プロトコル自体についてカバーしています。
