コンテンツにスキップ

9.3.3 ツールの説明と発見

  • ツールの metadata が呼び出し品質に直接影響する理由を理解する
  • より分かりやすいツール説明の構造を設計できるようにする
  • ツール発見が「ユーザーの要求」を「候補ツール」にどう対応づけるかを理解する
  • 実行できるサンプルを通して、最小限のツール登録・発見システムを理解する

なぜツールは関数名だけでは足りないのか?

Section titled “なぜツールは関数名だけでは足りないのか?”

プログラマーには十分でも、モデルには十分とは限らない

Section titled “プログラマーには十分でも、モデルには十分とは限らない”

たとえば、次の2つの関数名を見てください。

  • search_docs
  • search_policy

人間のエンジニアなら、すぐに違いが分かるかもしれません。
でもモデルは次のことを知りません。

  • どちらが返金ルールの確認に向いているのか
  • どちらがナレッジベース記事の確認に向いているのか
  • 両方の引数が同じなのか

説明がなければ、モデルに見えるのは「似た名前の2つの関数」だけです。

ツール説明の本質は、あいまいさを減らすこと

Section titled “ツール説明の本質は、あいまいさを減らすこと”

よいツール説明は、少なくとも次の5つに答える必要があります。

  1. このツールは何をするのか
  2. どんな場面で使うのか
  3. どのパラメータが必要か
  4. 何を返すのか
  5. 権限やリスクはどの程度か

これらが明確であるほど、
モデルは安定して選びやすくなります。

たとえ話:エンドポイント名より API カタログが大事

Section titled “たとえ話:エンドポイント名より API カタログが大事”

ツール登録表は、API カタログのようなものです。

  • 関数名はエンドポイント名のようなもの
  • 説明は契約メモのようなもの

名前だけあって説明がなければ、 ユーザーもモデルも簡単に間違えてしまいます。


ツールの説明には少なくとも何が必要か?

Section titled “ツールの説明には少なくとも何が必要か?”

名前は「実装」ではなく「用途」が伝わるようにする

Section titled “名前は「実装」ではなく「用途」が伝わるようにする”

たとえば:

  • query_42 はよくない
  • search_refund_policy のほうがよい

なぜなら、モデルがツールを選ぶときは、実装の細かさよりも意味を重視するからです。

説明には「いつ使うか」を書く

Section titled “説明には「いつ使うか」を書く”

単に次のように書くだけでは不十分です。

  • 政策を検索する

よりよい書き方は次のようになります。

  • 返金、請求書、住所変更などのアフターサービス規則を検索する。注文のリアルタイム状態の確認には使わない。

これだけで、誤った呼び出しをかなり減らせます。

パラメータ説明は「どう入れるか」に答える

Section titled “パラメータ説明は「どう入れるか」に答える”

たとえば、次の情報が必要です。

  • パラメータ名
  • 例の値
  • 必須かどうか

返却構造にもルールがあるとよい

Section titled “返却構造にもルールがあるとよい”

ツールの返却構造が毎回バラバラだと、
モデルもスケジューラも後で安定して扱いにくくなります。

そのため、次を明確にしておくとよいです。

  • 成功時のフィールド
  • 失敗時のフィールド
  • エラーコードやエラー種別

初学者がまず覚えるとよいツール説明カード

Section titled “初学者がまず覚えるとよいツール説明カード”
フィールド最低限、何に答えるべきか
nameツール名。できれば意味が分かりやすいこと
descriptionいつ使うべきか、いつ使うべきでないか
required_argsパラメータをどう入れるか
returns成功したときに何が得られるか
risk_levelリスクが高いか、より厳しく制御すべきか

この表は初心者にとても向いています。
「ツール説明」という抽象的な概念を、確認できるチェックリストに変えられるからです。

ツール説明の品質と発見フロー図


まずは、ちゃんとしたツール登録表の例を見てみよう

Section titled “まずは、ちゃんとしたツール登録表の例を見てみよう”

以下のコードは3つのことを行います。

  1. ツールの metadata を登録する
  2. クエリ と tags に基づいて最小限の発見を行う
  3. 候補ツール一覧を返す

単にツール配列を表示するだけより、学習効果があります。
なぜなら、ここではすでに次の点が見えるからです。

  • 「ツール説明」がどのように意思決定に関わるか
TOOL_REGISTRY = [
{
"name": "search_refund_policy",
"description": "返金、請求書、住所変更などのアフターサービス規則を検索する",
"tags": ["policy", "refund", "invoice", "after_sales", "返金", "請求書", "サポート"],
"required_args": ["keyword"],
"returns": ["policy_text"],
"risk_level": "low",
},
{
"name": "get_order_status",
"description": "注文の現在状態を確認する。たとえば、未発送、発送済み、配達済みなど",
"tags": ["order", "status", "shipping", "after_sales", "注文", "発送", "状態"],
"required_args": ["order_id"],
"returns": ["order_status"],
"risk_level": "medium",
},
{
"name": "calculator",
"description": "加減乗除、手数料の合計、差額計算など、決定的な数値計算を行う",
"tags": ["math", "fee", "total", "calculation", "計算", "手数料", "合計", "差額"],
"required_args": ["expression"],
"returns": ["result"],
"risk_level": "low",
},
]
def discover_tools(query, registry, top_k=2):
cleaned = query.lower().replace("", "").replace("?", "")
compacted = cleaned.replace(" ", "")
words = set(cleaned.split())
words.update(compacted[i : i + 2] for i in range(max(len(compacted) - 1, 0)))
scored = []
for tool in registry:
text = " ".join([tool["name"], tool["description"], " ".join(tool["tags"])]).lower()
score = sum(word in text for word in words)
scored.append((tool["name"], score))
scored.sort(key=lambda item: item[1], reverse=True)
return scored[:top_k]
queries = [
"返金ポリシーは何ですか",
"注文はもう発送されましたか",
"手数料の合計として 299 に 80 を足して 5 を引く",
]
for query in queries:
print(query, "->", discover_tools(query, TOOL_REGISTRY))

期待される出力:

Terminal window
返金ポリシーは何ですか -> [('search_refund_policy', 1), ('get_order_status', 0)]
注文はもう発送されましたか -> [('get_order_status', 2), ('search_refund_policy', 0)]
手数料の合計として 299 に 80 を足して 5 を引く -> [('calculator', 3), ('search_refund_policy', 0)]

このコードは何を教えているのか?

Section titled “このコードは何を教えているのか?”

このコードは、特に重要な2つのことを教えています。

  1. ツールは「むき出しの関数」ではなく、metadata を持つオブジェクトである
  2. ツール発見は本質的に、「要求」と「ツール説明」の対応づけである

ユーザーは、ツール名とまったく同じ言葉を使うとは限らないからです。
たとえば:

  • ユーザーは「発送された?」と言う
  • ツール名は get_order_status かもしれない

tags がなければ、発見の段階で候補ツールを見落としやすくなります。

なぜここでは直接実行せず、候補だけ返すのか?

Section titled “なぜここでは直接実行せず、候補だけ返すのか?”

「発見」は最初の一歩だからです。
ここで解決したいのは次のことです。

  • どのツールが候補集に入る価値があるか

その後には、普通はさらに次の処理があります。

  • パラメータ補完
  • ツール選択
  • 実行と検証

さらに小さな「候補ツールの絞り込み表」の例

Section titled “さらに小さな「候補ツールの絞り込み表」の例”
query = "返金ポリシーは何ですか"
candidates = discover_tools(query, TOOL_REGISTRY)
for item in candidates:
print({"query": query, "candidate_tool": item[0], "score": item[1]})

期待される出力:

Terminal window
{'query': '返金ポリシーは何ですか', 'candidate_tool': 'search_refund_policy', 'score': 1}
{'query': '返金ポリシーは何ですか', 'candidate_tool': 'get_order_status', 'score': 0}

この例は初心者にとても向いています。
なぜなら、まず次のことが見えるからです。

  • ツール発見の段階で本当に出力されるのは答えではない
  • 候補となるアクションの集合である

実際のシステムでは「発見」は1種類ではない

Section titled “実際のシステムでは「発見」は1種類ではない”

これは最も直感的な層です。利点は次のとおりです。

  • シンプル
  • 説明しやすい

欠点は次のとおりです。

  • 意味の一般化が弱い

ツールが多くなると、よくある方法は次のようになります。

  • ツール説明を embedding にする
  • ユーザー意図とベクトルで照合する

これは次のような場合に向いています。

  • ツール数が多い
  • ツール説明が長い

高リスクなシステムでは、
ツール発見を完全にモデルに任せないこともあります。
その代わりに、先にルールを追加します。

  • 注文関連のリクエストは先に注文ツールを見る
  • 削除系の操作は必ず人間の確認を入れる

これは、ツール発見が単なる recall の問題ではなく、
方針の問題でもあることを示しています。

初めてツールシステムを作るときの、最も安定した順番

Section titled “初めてツールシステムを作るときの、最も安定した順番”

より安定した順番は、たいてい次のとおりです。

  1. まずツール説明を分かりやすく書く
  2. 次に、いちばん簡単な候補 recall を作る
  3. 候補集が妥当か確認する
  4. その後でパラメータ補完と実行を追加する

最初から「モデルが自動で正しく選べるか」に集中するより、ずっと安定します。


返却構造も、なぜツール説明の一部なのか?

Section titled “返却構造も、なぜツール説明の一部なのか?”

発見は「ツールを見つける」だけでなく、後続フローにつながるかも重要だから

Section titled “発見は「ツールを見つける」だけでなく、後続フローにつながるかも重要だから”

たとえば:

  • search_refund_policypolicy_text を返す
  • get_order_statusorder_status を返す

後続システムがこれらを1つの回答にまとめる必要があるなら、
返却フィールドが明確であるほど、後の処理は安定します。

シンプルな統一返却ルールの例

Section titled “シンプルな統一返却ルールの例”
def normalize_tool_result(ok, data=None, error=None):
return {
"ok": ok,
"data": data or {},
"error": error,
}
print(normalize_tool_result(True, data={"policy_text": "7日以内は返金可能です"}))
print(normalize_tool_result(False, error="missing_order_id"))

期待される出力:

Terminal window
{'ok': True, 'data': {'policy_text': '7日以内は返金可能です'}, 'error': None}
{'ok': False, 'data': {}, 'error': 'missing_order_id'}

統一された返却構造には、次のような利点があります。

  • スケジューラが処理しやすい
  • ログを分析しやすい
  • Agent が observation を読みやすい

ツール説明でよくある落とし穴

Section titled “ツール説明でよくある落とし穴”

誤解1: 関数シグネチャが分かれば十分

Section titled “誤解1: 関数シグネチャが分かれば十分”

プログラマーにとっては十分でも、
モデルにとってはたいてい不十分です。

誤解2: ツール説明は短いほどよい

Section titled “誤解2: ツール説明は短いほどよい”

短すぎると、あいまいになります。
本当に大事なのは次の2つです。

  • 正確であること
  • 区別できること

単に短ければよいわけではありません。

誤解3: 発見は1つでもツールを返せればよい

Section titled “誤解3: 発見は1つでもツールを返せればよい”

候補集の質が悪ければ、
その後の選択も実行も悪くなります。

そのため、ツール発見はシステム品質にとって重要な前段階です。

これをノートやプロジェクトにするなら、何を見せるとよいか

Section titled “これをノートやプロジェクトにするなら、何を見せるとよいか”

見せる価値が高いのは、次のようなものです。

  • たくさんのツール関数定義
  • ではなく、
  1. ツール説明カード
  2. ユーザー質問 -> 候補ツール一覧
  3. なぜそのツールが上位に来たのか
  4. ツール返却構造をどう統一したか

こうすると、見る人には次のことが伝わりやすくなります。

  • あなたはツールシステムの「発見層」を理解している
  • 単に関数をモデルに接続しただけではない

このページを終えたら、この証拠カードを残します。

ツール契約
名前、説明、入力スキーマ、出力スキーマ
権限
ツールが読み取りまたは変更を許可されている範囲
呼び出しトレース
引数、結果、エラー、再試行、またはフォールバック
失敗確認
間違ったツール、不適切な引数、危険な操作、または観測不足
安全対策
検証、確認、サンドボックス化、レート制限、またはロールバック

この節で最も大事なのは、たくさんの項目名を覚えることではありません。
次の1つの判断軸を持つことです。

Agent が安定してツールを選べるのは、モデルが「すごく賢くて全関数を理解している」からではなく、ツールが発見可能で、区別可能で、検証可能な対象として説明されているから。

この主線が分かれば、
次に学ぶ次の内容も理解しやすくなります。

  • ツールルーティング
  • ツールの安全性
  • 複数ツールの協調

そして、「まずツール説明を分かりやすくすること」が第一歩だと分かるはずです。


  1. サンプルの登録表に search_faq ツールを追加して、search_refund_policy と混同されるか見てみましょう。
  2. なぜ tags は、ツール名よりも第一段階の recall に向いていることが多いのでしょうか?
  3. 考えてみましょう:高リスクなツールの説明には、用途とパラメータのほかに、何を書き足しますか?
  4. ツールがどんどん増えるとき、まず強化したいのは「ツール説明」と「ツール実行器」のどちらですか? なぜですか?
参考実装と解説
  1. search_faq には、一般的なヘルプ質問と返金ポリシー検索を分ける tags と例を入れます。そうしないと search_refund_policy と競合します。
  2. 最初の検索層では tool name より tags が有効です。意図、領域、リスク、データソースをより柔軟に表せるからです。
  3. 高リスクツールには、目的と parameters だけでなく、権限、副作用、確認ルール、rollback の限界、監査ログ、呼び出してはいけない例も書きます。
  4. ツールが増えたら、まず description と retrieval を強化して正しいツールを選ばせます。executor の安全チェックも必要ですが、悪い routing を毎回救うことはできません。