jpskill.com
🛠️ 開発・MCP コミュニティ

function-calling

LLM(大規模言語モデル)がAPIやデータベースと連携し、ツールを使いながらタスクを達成するAIエージェントを構築する際に、ツールの定義、呼び出し、結果の処理を繰り返すことで、現実世界でアクションを実行できるようにするSkill。

📜 元の英語説明(参考)

Implement function/tool calling with LLMs — define tools, handle calls, and return results in a loop. Use when building AI agents with tools, letting LLMs interact with APIs or databases, creating agentic workflows, or enabling models to take real-world actions.

🇯🇵 日本人クリエイター向け解説

一言でいうと

LLM(大規模言語モデル)がAPIやデータベースと連携し、ツールを使いながらタスクを達成するAIエージェントを構築する際に、ツールの定義、呼び出し、結果の処理を繰り返すことで、現実世界でアクションを実行できるようにするSkill。

※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o function-calling.zip https://jpskill.com/download/14920.zip && unzip -o function-calling.zip && rm function-calling.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/14920.zip -OutFile "$d\function-calling.zip"; Expand-Archive "$d\function-calling.zip" -DestinationPath $d -Force; ri "$d\function-calling.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して function-calling.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → function-calling フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-18
取得日時
2026-05-18
同梱ファイル
1

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

Function Calling

概要

Function calling (ツール利用とも呼ばれます) を使用すると、LLM は外部関数を呼び出してアクションを実行したり、情報を取得したりできます。モデルは、いつ、どのツールを呼び出すかを決定します。あなたのコードはそれらを実行し、結果を返します。これにより、モデルがデータベースをクエリしたり、API を呼び出したり、計算を実行したりできる、真のエージェントワークフローが可能になります。

コアコンセプト

フローは常に次のとおりです。

  1. スキーマを使用してツールを定義します
  2. メッセージとツールの定義をモデルに送信します
  3. モデルはツール呼び出し (名前 + 引数) を返します
  4. あなたのコードが関数を実行します
  5. 結果をモデルに返します
  6. モデルは結果を使用して推論を続けます
  7. モデルが最終的なテキスト応答を返すまで繰り返します

OpenAI Function Calling

ツールの定義と登録

from openai import OpenAI
import json

client = OpenAI()

# ツールのスキーマを定義します
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "都市の現在の天気を取得します。気温、状況、湿度を返します。",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "都市名 (例: 'San Francisco, CA')"
                    },
                    "unit": {
                        "type": "string",
                        "enum": ["celsius", "fahrenheit"],
                        "description": "温度単位。デフォルト: celsius"
                    }
                },
                "required": ["city"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "send_email",
            "description": "受信者にメールを送信します。",
            "parameters": {
                "type": "object",
                "properties": {
                    "to": {"type": "string", "description": "受信者のメールアドレス"},
                    "subject": {"type": "string"},
                    "body": {"type": "string"}
                },
                "required": ["to", "subject", "body"]
            }
        }
    }
]

ツール関数の実装

def get_weather(city: str, unit: str = "celsius") -> dict:
    # 本番環境では、実際の天気 API を呼び出します
    return {
        "city": city,
        "temperature": 22 if unit == "celsius" else 72,
        "unit": unit,
        "conditions": "Partly cloudy",
        "humidity": "65%"
    }

def send_email(to: str, subject: str, body: str) -> dict:
    # 本番環境では、sendgrid/resend/smtp を使用します
    print(f"Sending email to {to}: {subject}")
    return {"success": True, "message_id": "msg_123"}

# ツールディスパッチャ
TOOL_MAP = {
    "get_weather": get_weather,
    "send_email": send_email,
}

def execute_tool(name: str, arguments: dict) -> str:
    if name not in TOOL_MAP:
        return json.dumps({"error": f"Unknown tool: {name}"})
    try:
        result = TOOL_MAP[name](**arguments)
        return json.dumps(result)
    except Exception as e:
        return json.dumps({"error": str(e)})

エージェントループ

def run_agent(user_message: str, max_iterations: int = 10) -> str:
    messages = [{"role": "user", "content": user_message}]

    for iteration in range(max_iterations):
        response = client.chat.completions.create(
            model="gpt-4o",
            messages=messages,
            tools=tools,
            tool_choice="auto"  # ツール使用を強制する場合は "required"
        )

        message = response.choices[0].message
        messages.append(message)  # アシスタントのメッセージを履歴に追加します

        # 完了したかどうかを確認します (ツール呼び出しがもうない場合)
        if message.tool_calls is None:
            return message.content

        # すべてのツール呼び出しを実行します (並列実行される場合があります)
        for tool_call in message.tool_calls:
            name = tool_call.function.name
            args = json.loads(tool_call.function.arguments)

            print(f"  → Calling {name}({args})")
            result = execute_tool(name, args)
            print(f"  ← Result: {result}")

            messages.append({
                "role": "tool",
                "tool_call_id": tool_call.id,
                "content": result
            })

    return "Max iterations reached"

# エージェントを実行します
result = run_agent("What's the weather in Tokyo? If it's over 20°C, email weather@team.com with a trip recommendation.")
print(result)

Anthropic Tool Use

import anthropic
import json

client = anthropic.Anthropic()

# Anthropic ツールのスキーマ形式
tools = [
    {
        "name": "search_database",
        "description": "キーワードで製品データベースを検索します。一致する製品と価格を返します。",
        "input_schema": {
            "type": "object",
            "properties": {
                "query": {
                    "type": "string",
                    "description": "検索クエリ"
                },
                "limit": {
                    "type": "integer",
                    "description": "返す最大結果数 (1-20)",
                    "default": 5
                }
            },
            "required": ["query"]
        }
    }
]

def run_claude_agent(user_message: str) -> str:
    messages = [{"role": "user", "content": user_message}]

    while True:
        response = client.messages.create(
            model="claude-3-5-sonnet-20241022",
            max_tokens=4096,
            tools=tools,
            messages=messages
        )

        # アシスタントの応答を履歴に追加します
        messages.append({"role": "assistant", "content": response.content})

        # 停止理由を確認します
        if response.stop_reason == "end_turn":
            # 最終的なテキスト応答を抽出します
            for block in response.content:
                if hasattr(block, "text"):
                    return block.text
            return ""

        if response.stop_reason == "tool_use":
            # すべてのツール使用ブロックを処理します
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

Function Calling

Overview

Function calling (also called tool use) lets LLMs invoke external functions to take actions or retrieve information. The model decides when and which tools to call; your code executes them and returns results. This enables true agentic workflows where the model can query databases, call APIs, perform calculations, and more.

Core Concept

The flow is always:

  1. Define tools with schemas
  2. Send messages + tool definitions to the model
  3. Model returns a tool call (name + arguments)
  4. Your code executes the function
  5. Return the result to the model
  6. Model uses the result to continue reasoning
  7. Repeat until the model returns a final text response

OpenAI Function Calling

Define and Register Tools

from openai import OpenAI
import json

client = OpenAI()

# Define tool schemas
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Get current weather for a city. Returns temperature, conditions, and humidity.",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "City name, e.g. 'San Francisco, CA'"
                    },
                    "unit": {
                        "type": "string",
                        "enum": ["celsius", "fahrenheit"],
                        "description": "Temperature unit. Default: celsius"
                    }
                },
                "required": ["city"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "send_email",
            "description": "Send an email to a recipient.",
            "parameters": {
                "type": "object",
                "properties": {
                    "to": {"type": "string", "description": "Recipient email address"},
                    "subject": {"type": "string"},
                    "body": {"type": "string"}
                },
                "required": ["to", "subject", "body"]
            }
        }
    }
]

Implement Tool Functions

def get_weather(city: str, unit: str = "celsius") -> dict:
    # In production, call a real weather API
    return {
        "city": city,
        "temperature": 22 if unit == "celsius" else 72,
        "unit": unit,
        "conditions": "Partly cloudy",
        "humidity": "65%"
    }

def send_email(to: str, subject: str, body: str) -> dict:
    # In production, use sendgrid/resend/smtp
    print(f"Sending email to {to}: {subject}")
    return {"success": True, "message_id": "msg_123"}

# Tool dispatcher
TOOL_MAP = {
    "get_weather": get_weather,
    "send_email": send_email,
}

def execute_tool(name: str, arguments: dict) -> str:
    if name not in TOOL_MAP:
        return json.dumps({"error": f"Unknown tool: {name}"})
    try:
        result = TOOL_MAP[name](**arguments)
        return json.dumps(result)
    except Exception as e:
        return json.dumps({"error": str(e)})

Agent Loop

def run_agent(user_message: str, max_iterations: int = 10) -> str:
    messages = [{"role": "user", "content": user_message}]

    for iteration in range(max_iterations):
        response = client.chat.completions.create(
            model="gpt-4o",
            messages=messages,
            tools=tools,
            tool_choice="auto"  # or "required" to force tool use
        )

        message = response.choices[0].message
        messages.append(message)  # Add assistant message to history

        # Check if we're done (no more tool calls)
        if message.tool_calls is None:
            return message.content

        # Execute all tool calls (may be parallel)
        for tool_call in message.tool_calls:
            name = tool_call.function.name
            args = json.loads(tool_call.function.arguments)

            print(f"  → Calling {name}({args})")
            result = execute_tool(name, args)
            print(f"  ← Result: {result}")

            messages.append({
                "role": "tool",
                "tool_call_id": tool_call.id,
                "content": result
            })

    return "Max iterations reached"

# Run the agent
result = run_agent("What's the weather in Tokyo? If it's over 20°C, email weather@team.com with a trip recommendation.")
print(result)

Anthropic Tool Use

import anthropic
import json

client = anthropic.Anthropic()

# Anthropic tool schema format
tools = [
    {
        "name": "search_database",
        "description": "Search the product database by keyword. Returns matching products with prices.",
        "input_schema": {
            "type": "object",
            "properties": {
                "query": {
                    "type": "string",
                    "description": "Search query"
                },
                "limit": {
                    "type": "integer",
                    "description": "Max results to return (1-20)",
                    "default": 5
                }
            },
            "required": ["query"]
        }
    }
]

def run_claude_agent(user_message: str) -> str:
    messages = [{"role": "user", "content": user_message}]

    while True:
        response = client.messages.create(
            model="claude-3-5-sonnet-20241022",
            max_tokens=4096,
            tools=tools,
            messages=messages
        )

        # Add assistant response to history
        messages.append({"role": "assistant", "content": response.content})

        # Check stop reason
        if response.stop_reason == "end_turn":
            # Extract final text response
            for block in response.content:
                if hasattr(block, "text"):
                    return block.text
            return ""

        if response.stop_reason == "tool_use":
            # Process all tool use blocks
            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": result
                    })

            messages.append({"role": "user", "content": tool_results})

Parallel Tool Calls

OpenAI may call multiple tools simultaneously. Always handle them as a batch:

# OpenAI returns multiple tool_calls in one response
# Execute them all, then return all results at once
if message.tool_calls:
    tool_results = []
    for tool_call in message.tool_calls:  # May have 2+ calls
        result = execute_tool(
            tool_call.function.name,
            json.loads(tool_call.function.arguments)
        )
        tool_results.append({
            "role": "tool",
            "tool_call_id": tool_call.id,
            "content": result
        })
    messages.extend(tool_results)  # Add ALL results before next API call

Streaming with Tool Calls

from openai import OpenAI

client = OpenAI()

def stream_with_tools(user_message: str):
    messages = [{"role": "user", "content": user_message}]

    with client.chat.completions.stream(
        model="gpt-4o",
        messages=messages,
        tools=tools,
    ) as stream:
        for event in stream:
            chunk = event.choices[0].delta if event.choices else None
            if not chunk:
                continue

            # Stream text tokens
            if chunk.content:
                print(chunk.content, end="", flush=True)

            # Accumulate tool calls (streamed in pieces)
            if chunk.tool_calls:
                for tc in chunk.tool_calls:
                    # tc.function.arguments is a partial JSON string
                    pass  # Accumulate until stream ends

        # After stream completes, get the final message
        final = stream.get_final_message()
        if final.choices[0].message.tool_calls:
            # Process tool calls as usual
            pass

TypeScript Example

import OpenAI from "openai";

const client = new OpenAI();

const tools: OpenAI.Chat.Completions.ChatCompletionTool[] = [
  {
    type: "function",
    function: {
      name: "get_stock_price",
      description: "Get the current stock price for a ticker symbol",
      parameters: {
        type: "object",
        properties: {
          ticker: { type: "string", description: "Stock ticker e.g. AAPL" },
        },
        required: ["ticker"],
      },
    },
  },
];

function getStockPrice(ticker: string): string {
  // Mock implementation
  const prices: Record<string, number> = { AAPL: 185.5, GOOGL: 141.2, MSFT: 378.9 };
  const price = prices[ticker.toUpperCase()];
  return JSON.stringify(price ? { ticker, price, currency: "USD" } : { error: "Not found" });
}

async function runAgent(query: string): Promise<string> {
  const messages: OpenAI.Chat.Completions.ChatCompletionMessageParam[] = [
    { role: "user", content: query },
  ];

  while (true) {
    const response = await client.chat.completions.create({
      model: "gpt-4o",
      messages,
      tools,
    });

    const msg = response.choices[0].message;
    messages.push(msg);

    if (!msg.tool_calls?.length) return msg.content ?? "";

    for (const tc of msg.tool_calls) {
      const args = JSON.parse(tc.function.arguments);
      const result = tc.function.name === "get_stock_price"
        ? getStockPrice(args.ticker)
        : JSON.stringify({ error: "Unknown tool" });

      messages.push({ role: "tool", tool_call_id: tc.id, content: result });
    }
  }
}

Tool Schema Best Practices

# Good tool schema — clear description, constrained parameters
{
    "name": "create_calendar_event",
    "description": "Create a calendar event. Use when the user wants to schedule a meeting, reminder, or appointment. Do NOT use for past events.",
    "parameters": {
        "type": "object",
        "properties": {
            "title": {
                "type": "string",
                "description": "Event title, max 100 chars"
            },
            "start_time": {
                "type": "string",
                "description": "ISO 8601 datetime, e.g. '2025-03-15T14:00:00Z'"
            },
            "duration_minutes": {
                "type": "integer",
                "description": "Duration in minutes (15-480)",
                "minimum": 15,
                "maximum": 480
            },
            "attendees": {
                "type": "array",
                "items": {"type": "string", "format": "email"},
                "description": "List of attendee email addresses"
            }
        },
        "required": ["title", "start_time", "duration_minutes"]
    }
}

Guidelines

  • Write tool descriptions as if explaining to a smart but uninformed colleague — be specific about when to use and when NOT to use a tool
  • Always handle the case where the model returns no tool calls (final answer)
  • Cap iterations (10 is usually enough; infinite loops waste tokens and money)
  • Log all tool calls and results for debugging
  • Return errors as JSON {"error": "message"} — don't throw exceptions in tool functions
  • For expensive tools (send email, delete record), add a confirmation step or dry-run mode
  • Use tool_choice: "required" when you need the model to use tools, "auto" otherwise
  • Keep tool functions idempotent when possible; agents may retry on failure