Tool Use(関数呼び出し)

LLM に「外部関数」を提供して、自律的に呼ばせる仕組み。 エージェントの中核で、検索・DB アクセス・コード実行などを LLM 任せにできる。

仕組み

  1. API リクエストに tools 定義を渡す
  2. モデルが「ツール呼び出すべき」と判断したら tool_use ブロックを返す
  3. こちら側で関数を実行
  4. 結果を tool_result ブロックとして履歴に追加
  5. 再度モデル呼び出し → 最終応答(または別ツール)
User: "東京の天気は?"
  ↓
LLM: "tool_use: get_weather(city='Tokyo')"
  ↓ (こちらで実行)
Tool: { temp: 18, condition: "晴れ" }
  ↓
LLM: "東京は晴れで気温 18°C です。"
      

ツールの定義

JSON Schema で引数を定義する。name / description / input_schema が必須。

const tools = [
  {
    name: "get_weather",
    description: "指定都市の現在天気を取得します",
    input_schema: {
      type: "object",
      properties: {
        city: { type: "string", description: "都市名(英語)" },
        unit: { type: "string", enum: ["celsius", "fahrenheit"], default: "celsius" }
      },
      required: ["city"]
    }
  }
]
description が最重要

モデルは description を読んで「いつ呼ぶか」を判断する。 関数名だけでは曖昧な場合は具体例や使用条件まで書く。

ツール付きリクエスト

const res = await client.messages.create({
  model: "claude-sonnet-4-6",
  max_tokens: 1024,
  tools,
  messages: [{ role: "user", content: "東京の天気は?" }]
})

console.log(res.stop_reason) // "tool_use"
console.log(res.content)
// [
//   { type: "text", text: "天気を調べます。" },
//   { type: "tool_use", id: "toolu_...", name: "get_weather", input: { city: "Tokyo" } }
// ]

結果を返す

const toolUse = res.content.find(c => c.type === "tool_use")

const toolResult = await getWeather(toolUse.input.city) // 実関数を呼ぶ

const final = await client.messages.create({
  model: "claude-sonnet-4-6",
  max_tokens: 1024,
  tools,
  messages: [
    { role: "user", content: "東京の天気は?" },
    { role: "assistant", content: res.content },
    {
      role: "user",
      content: [
        {
          type: "tool_result",
          tool_use_id: toolUse.id,
          content: JSON.stringify(toolResult)
        }
      ]
    }
  ]
})

エージェントループ

ツールが連鎖するときはwhile で stop_reason を見る

async function runAgent(userInput: string) {
  const messages = [{ role: "user", content: userInput }]

  while (true) {
    const res = await client.messages.create({
      model: "claude-sonnet-4-6",
      max_tokens: 4096,
      tools,
      messages
    })

    messages.push({ role: "assistant", content: res.content })

    if (res.stop_reason !== "tool_use") {
      // ツール呼び出しが終わったので最終応答
      return res.content.find(c => c.type === "text")?.text
    }

    // ツール群を実行(並列可)
    const toolUses = res.content.filter(c => c.type === "tool_use")
    const toolResults = await Promise.all(
      toolUses.map(async (t) => ({
        type: "tool_result",
        tool_use_id: t.id,
        content: JSON.stringify(await dispatch(t.name, t.input))
      }))
    )

    messages.push({ role: "user", content: toolResults })
  }
}

並列ツール呼び出し

Claude は1 ターンで複数 tool_use を返すことができる。 independent ならPromise.all で並列実行すると速い。

tool_choice の制御

tool_choice意味
{ "type": "auto" }モデルが判断(デフォルト)
{ "type": "any" }必ず何かツールを呼ぶ
{ "type": "tool", "name": "x" }必ず x を呼ぶ
{ "type": "none" }ツール禁止

JSON 出力したいときの定石

ダミーの extract ツールを定義し tool_choice: tool で強制呼出 → 構造化出力が確定する。

tool_result でエラーを返す

{
  type: "tool_result",
  tool_use_id: "...",
  content: "DB connection failed",
  is_error: true
}

エラーを返すとモデルがリトライや別ツールへ切替を試みる。

Anthropic 提供の組み込みツール

Computer Use は仮想マシン内で実行する前提。直接ホスト OS を触らせるのは危険。

MCP(Model Context Protocol)

Anthropic が提唱するツール提供の標準。 MCP サーバー(GitHub / DB / Slack...)を立てれば、Claude / 各種クライアントから共通プロトコルで接続できる。

セキュリティと権限

失敗パターン

症状対処
呼ばれるべきツールが呼ばれないdescription を具体化、Few-shot で例示
引数が間違っているrequired / enum / default を明示
無限ループ最大ステップ数を制限、進捗を観測
関係ないツールも呼ぶtools 数を絞る、tool_choice で制限
tool_result の中身を読まない大きすぎる結果を要約、構造化

ツール多すぎ問題

ツールが 30 個を超えると選択精度が落ちる

具体例: 簡易リサーチエージェント

const tools = [
  {
    name: "search",
    description: "Web を検索してタイトルと URL を返す",
    input_schema: {
      type: "object",
      properties: { query: { type: "string" } },
      required: ["query"]
    }
  },
  {
    name: "fetch_url",
    description: "URL を取得して本文を返す",
    input_schema: {
      type: "object",
      properties: { url: { type: "string" } },
      required: ["url"]
    }
  }
]

// このループで Claude は
// search → fetch_url を複数回 → まとめ
// と自律的に動く

テストとデバッグ

原則

ツールは細かく作りすぎず、汎用的に。Unix のコマンドと同じで、組み合わせで力を発揮する。 1 ツール 1 責務、副作用は明示、引数はシンプル。