本記事では、Claude API(Anthropic)とOpenAI APIを「Function Calling」「ストリーミング」「コスト」という3つの実装上の観点から比較します。両APIはインターフェースこそ似ていますが、実際にプロダクションコードに組み込むと細かな仕様差が開発体験やコストに大きく影響します。これからどちらかを採用する、あるいは両方を併用するアーキテクチャを検討しているエンジニア向けに、具体的な差分をまとめました。

Function Callingの仕様差

両APIとも「ツール(関数)をモデルに定義し、必要に応じて呼び出させる」という基本思想は共通していますが、レスポンス構造とツール定義の柔軟性に違いがあります。

OpenAI APIの場合

OpenAIはtoolsパラメータにJSON Schemaベースの関数定義を渡し、モデルがtool_callsを返す形式です。並列ツール呼び出し(parallel tool calls)に対応しており、1回のレスポンスで複数の関数呼び出しが返ってくることがあります。

response = client.chat.completions.create(
  model="gpt-4o",
  messages=messages,
  tools=tools,
  tool_choice="auto"
)
for call in response.choices[0].message.tool_calls:
    print(call.function.name, call.function.arguments)

Claude APIの場合

ClaudeはAnthropic独自のtool_useブロックとしてコンテンツ内に埋め込まれる形式です。会話履歴(messages)の中にツール実行結果をtool_resultとして戻す必要があり、OpenAIより一手間多いですが、その分「思考過程(thinking)」と実行結果の紐付けが明確になり、デバッグ時にモデルの意図を追いやすいという利点があります。

for block in response.content:
    if block.type == "tool_use":
        print(block.name, block.input)
実装上の注意点:Claudeはツール呼び出し後に必ずtool_resultを含むユーザーメッセージを送り返す必要があり、これを忘れると会話が破綻します。OpenAIはrole: toolのメッセージを追加するだけで比較的緩やかです。

ストリーミング処理の違い

両APIともServer-Sent Events(SSE)ベースのストリーミングを提供しますが、イベントの粒度が異なります。

Claudeのイベント設計は冗長に見えますが、Function Callingとテキスト生成が混在するレスポンスでも、どのブロックがどの型かを厳密に判定できるため、複雑なエージェント実装では扱いやすい面もあります。

# Claudeストリーミングの典型的な処理
with client.messages.stream(
    model="claude-3-5-sonnet-20241022",
    messages=messages,
    tools=tools
) as stream:
    for event in stream:
        if event.type == "content_block_delta":
            print(event.delta.text, end="")

コスト面の実装者視点

コストはモデルグレードによって大きく変わるため単純比較は難しいですが、実装時に意識すべきポイントを整理します。

実装上の使い分け指針

厳密なツール実行順序やモデルの思考過程を追跡したいエージェント設計にはClaudeの構造化されたレスポンスが有利です。一方、シンプルな並列ツール呼び出しや、既存のOpenAI SDKエコシステム(LangChainなどの豊富な統合実績)を活用したい場合はOpenAI APIの方が学習コストが低く導入しやすいでしょう。

両APIとも仕様変更が頻繁なため、抽象化レイヤーを自作するか、LiteLLMのような統一インターフェースライブラリを挟んでおくと、将来的なモデル切り替えや併用がスムーズになります。