Tool Use(Function Calling)
Claudeに外部ツール(関数)を使わせる方法を学びます。天気取得、DB検索、API呼び出しなどをClaudeが判断して実行できるようになります。
基本的な流れ
1. ツール定義をAPIに渡す
2. Claudeがツール呼び出しを返す(tool_use)
3. アプリがツールを実行して結果を返す(tool_result)
4. Claudeが結果を元に最終回答を生成
ツール定義
JSONスキーマでツールの名前・説明・パラメータを定義する。
tools = [
{
"name": "get_weather",
"description": "指定された都市の現在の天気を取得する",
"input_schema": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "都市名(例: 東京、大阪)"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "温度の単位"
}
},
"required": ["city"]
}
}
]
良いツール定義のポイント
descriptionを具体的に書く — Claudeはこれを読んで使うかどうか判断するpropertiesの各フィールドにもdescriptionをつけるrequiredを適切に設定して、必須パラメータを明示する
実行フロー(完全な例)
import anthropic
import json
client = anthropic.Anthropic()
# 1. ツール定義
tools = [
{
"name": "get_weather",
"description": "指定された都市の現在の天気を取得する",
"input_schema": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "都市名"}
},
"required": ["city"]
}
}
]
# 2. 最初のリクエスト
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
tools=tools,
messages=[
{"role": "user", "content": "東京の天気を教えて"}
]
)
# 3. Claudeがtool_useを返す
# response.stop_reason == "tool_use"
# response.content == [
# {"type": "text", "text": "東京の天気を確認しますね。"},
# {"type": "tool_use", "id": "toolu_01...", "name": "get_weather", "input": {"city": "東京"}}
# ]
# 4. ツールを実際に実行(ここはアプリ側の実装)
def get_weather(city):
# 実際にはAPIを叩く
return {"temp": 22, "condition": "晴れ", "humidity": 45}
# tool_useブロックを取得
tool_use = next(b for b in response.content if b.type == "tool_use")
result = get_weather(tool_use.input["city"])
# 5. 結果をClaudeに返す
final_response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
tools=tools,
messages=[
{"role": "user", "content": "東京の天気を教えて"},
{"role": "assistant", "content": response.content},
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": tool_use.id,
"content": json.dumps(result, ensure_ascii=False)
}
]
}
]
)
print(final_response.content[0].text)
# => "東京は現在22°Cで晴れています。湿度は45%です。"
複数ツールの利用
複数のツールを定義すると、Claudeが状況に応じて適切なツールを選ぶ。1回のレスポンスで複数ツールを呼ぶこともある。
tools = [
{
"name": "get_weather",
"description": "都市の天気を取得",
"input_schema": {
"type": "object",
"properties": {
"city": {"type": "string"}
},
"required": ["city"]
}
},
{
"name": "get_exchange_rate",
"description": "通貨の為替レートを取得",
"input_schema": {
"type": "object",
"properties": {
"from_currency": {"type": "string"},
"to_currency": {"type": "string"}
},
"required": ["from_currency", "to_currency"]
}
}
]
並列ツール呼び出し
Claudeが1回のレスポンスで複数のtool_useブロックを返すことがある。
# "東京と大阪の天気を比較して" と聞くと:
# response.content == [
# {"type": "tool_use", "name": "get_weather", "input": {"city": "東京"}},
# {"type": "tool_use", "name": "get_weather", "input": {"city": "大阪"}}
# ]
# 全てのtool_resultをまとめて返す
tool_results = []
for block in response.content:
if block.type == "tool_use":
result = execute_tool(block.name, block.input)
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": json.dumps(result, ensure_ascii=False)
})
tool_choice — ツール利用の制御
| 値 | 動作 |
|---|---|
{"type": "auto"} |
Claudeが判断(デフォルト) |
{"type": "any"} |
必ず何かのツールを使う |
{"type": "tool", "name": "get_weather"} |
指定ツールを必ず使う |
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
tools=tools,
tool_choice={"type": "any"}, # 必ずツールを使わせる
messages=[...]
)
エラーハンドリング
ツール実行が失敗した場合、is_errorフラグで伝える。
{
"type": "tool_result",
"tool_use_id": tool_use.id,
"content": "都市名が見つかりませんでした: ホゲ市",
"is_error": True
}
Claudeはエラー内容を理解して、ユーザーに適切に説明したり、別のアプローチを試みる。
実践パターン
パターン1: ループ処理(エージェント的な使い方)
messages = [{"role": "user", "content": user_input}]
while True:
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=4096,
tools=tools,
messages=messages,
)
# ツール呼び出しがなければ終了
if response.stop_reason == "end_turn":
print(response.content[0].text)
break
# ツール実行して結果を追加
messages.append({"role": "assistant", "content": response.content})
tool_results = []
for block in response.content:
if block.type == "tool_use":
result = execute_tool(block.name, block.input)
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": json.dumps(result, ensure_ascii=False)
})
messages.append({"role": "user", "content": tool_results})
パターン2: ツールでの構造化データ抽出
ツールの「実行」をスキップして、Claudeに構造化データを出力させるテクニック。
tools = [
{
"name": "extract_info",
"description": "テキストから構造化情報を抽出する",
"input_schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"email": {"type": "string"},
"company": {"type": "string"}
},
"required": ["name", "email"]
}
}
]
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
tools=tools,
tool_choice={"type": "tool", "name": "extract_info"},
messages=[
{"role": "user", "content": "田中太郎(tanaka@example.com)、株式会社ABC所属"}
]
)
# tool_use.input にJSONスキーマ準拠の構造化データが入る
extracted = response.content[0].input
# => {"name": "田中太郎", "email": "tanaka@example.com", "company": "株式会社ABC"}
参考リンク
- Tool Use Guide — 公式Tool Useガイド
- Anthropic Courses - Tool Use — Tool Useコース(5章)
- Anthropic Cookbook — ツール活用レシピ