ストリーミング・Tool Use・構造化出力

AI Navigate Original / 2026/3/24

💬 オピニオンDeveloper Stack & Infrastructure
共有:

要点

  • SSEストリーミングはチャット/長文UIの体感速度を改善。DB/監査は断片でなく最終確定テキストを使い、厳密な構造化出力はストリーミング外で。
  • Tool Use:どのツールをどこまで許すかをアプリ側で制御。副作用には確認、引数はJSON Schemaで厳密化、検索/参照/更新ツールを分離。
  • JSON構造化出力:スキーマ固定、「JSONのみ」明記、temperature 0〜0.2、アプリ側バリデーション、説明用と構造化APIを分離。
  • Prompt Cachingは長い固定プロンプトのコスト削減、Batch APIは大量非同期向け。導入順は構造化出力→ストリーミング→Tool Use→Caching/Batch。

Claude API は、ただ文章を返すだけではなく、応答を少しずつ流す(ストリーミング)外部処理を呼び出す(Tool Use)決まった形のJSONで返す(構造化出力)共通の前置きを使い回す(プロンプトキャッシュ)大量処理をまとめて流す(Batch)といった、実運用で効く機能を備えています。チャット画面で試したプロンプトをそのままAPI化するより、速度・コスト・再現性を設計して組み込むのがコツです。

本記事は Python のコード例を中心に、各機能を「どう組み込むと実際に使いやすいか」を図とともに整理します。なお、モデル名・料金・SDKの細部は更新が速いので、導入時は必ず公式ドキュメント(platform.claude.com)で最新を確認してください。本記事の具体値は 2026年前半時点のものです。

Claude API ストリーミング 待たせない表示 Tool Use 構造化出力 壊れないJSON プロンプトキャッシュ Batch API

FIG.1 チャットUIの先にある、実運用向けの5機能

まず押さえたいのは、これらは用途で使い分けるもので、最初から全部入れる必要はないという点です。記事末で段階導入の順番も示します。

01まずモデルを選ぶ(名前は変わる前提で)

2026年前半時点の主なラインナップは、最上位の Claude Opus、バランス型の Claude Sonnet、高速・低コストの Claude Haiku の3系統です。世代番号(例:Sonnet 4.6、Haiku 4.5)は短い周期で更新されるため、コード中のモデルIDは定数として1か所にまとめ、差し替えやすくしておくのが実務的です。

Haiku

分類・抽出・大量処理など、速度とコストを重視する定型タスク向き。

Sonnet

コーディング支援やエージェントなど、日常の主力。性能とコストのバランス型。

Opus

難度の高い推論・設計・調査など、最大の知能が要る場面に絞って使う。

正確なモデルID・対応機能・価格は更新されます。使う前に公式の Models / Pricing ページを確認してください。本記事の例では、説明用に claude-sonnet-4-5 等のIDを示しますが、利用時点の最新IDに置き換えてください。

02ストリーミング:まず「待たせない体験」を作る

長めの回答や要約では、全文の完成を待つよりサーバー送信イベント(SSE)で逐次表示したほうが体感速度が上がります。チャット、レビュー支援、議事録生成などで特に有効です。Anthropic SDK では messages.stream を使い、テキストの断片を順に受け取ります。

from anthropic import Anthropic

client = Anthropic(api_key="YOUR_API_KEY")

with client.messages.stream(
    model="claude-sonnet-4-5",   # 利用時点の最新モデルIDに置換
    max_tokens=1200,
    temperature=0.2,
    messages=[
        {"role": "user", "content": "SSEストリーミング実装の要点を3つ教えて"}
    ],
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)

    final_message = stream.get_final_message()

実装の勘所は、途中の断片をそのまま保存しないこと。逐次出力には言い直しや未完の文が混ざるため、DB保存や監査ログには get_final_message() で得る最終確定テキストを使うほうが安全です。あわせて、テキスト断片だけでなく完了イベント・エラーイベントも扱い、ユーザーのキャンセル操作で接続を閉じられるようにしておきます。

Claude 断片を逐次 画面に逐次表示 UI専用・体感速度↑ 最終確定テキスト DB保存・監査ログ 確定後に処理 表示と処理を分離

FIG.2 ストリーミングは「見せる」用、業務処理は「確定後」に分ける

向くケース・注意するケース

向く注意
チャットUI(体感速度が大きく改善)JSON構造化出力(途中断片は不完全JSONになりやすい)
長文要約(途中から読み始められる)バッチ集計(逐次表示の利点が薄い)

構造化出力を厳密に扱う処理では、逐次表示はUI専用、業務処理は最終レスポンス確定後に行う、という分離が実践的です。

03Tool Use:外部処理を「モデル任せにしすぎない」

Tool Use は、Claudeが「どの関数を、どんな引数で呼ぶべきか」を判断して構造化された呼び出し要求を返す仕組みです。実際の処理(社内検索・在庫照会・天気取得・RAG検索・DB問い合わせなど)はあなたのアプリ側が実行し、結果をClaudeに戻します。重要なのは自由実行させることではなく、どのツールを・どの条件で・どこまで許可するかをアプリ側で制御することです。

tools = [
    {
        "name": "get_weather",
        "description": "指定都市の現在天気を取得する",
        "input_schema": {
            "type": "object",
            "properties": {
                "city": {"type": "string", "description": "都市名。例: Tokyo"}
            },
            "required": ["city"],
        },
        # 引数を必ずスキーマ通りにしたい場合(対応モデル)
        "strict": True,
    }
]

response = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=800,
    tools=tools,
    messages=[
        {"role": "user", "content": "東京の天気を調べて、服装の目安も教えて"}
    ],
)

レスポンスに tool_use ブロックが含まれていたら、アプリ側で実関数を実行し、その結果を tool_result として同じ tool_use_id で返します。Claudeはそれを踏まえて最終回答を作ります。

def get_weather(city: str):
    return {"city": city, "weather": "sunny", "temp_c": 27}

# response.content から tool_use ブロックを取り出し、id と input を得る(疑似コード)
tool_use_id = "toolu_123"
tool_result = get_weather("Tokyo")

followup = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=800,
    tools=tools,
    messages=[
        {"role": "user", "content": "東京の天気を調べて、服装の目安も教えて"},
        {"role": "assistant", "content": response.content},
        {
            "role": "user",
            "content": [{
                "type": "tool_result",
                "tool_use_id": tool_use_id,
                "content": str(tool_result),
            }],
        },
    ],
)
Claude どの関数か判断 tool_use(呼び出し要求) アプリ側 実関数を実行 tool_result(結果) Claude 最終回答

FIG.3 判断はClaude、実行はアプリ。結果を返して回答を仕上げる往復

設計の実務ポイント

  • 副作用のある処理(送信・更新・削除)は、実行前に確認ステップを入れる。
  • ツール引数は JSON Schema で厳密化する。引数を確実にスキーマ通りにしたい場合は、対応モデルで strict: true(厳密ツール使用)を使うと取りこぼしを減らせる。
  • 検索結果はそのまま渡さず、必要最小限に整形してから戻す。
  • 失敗時は「とにかく再試行」より、失敗理由を結果として返すほうが安定する。

初心者がやりがちなのは、1つの万能ツールに何でも詰め込むこと。実際は検索・参照・更新を別ツールに分けるほうが、誤呼び出しと権限事故を減らせる。

04構造化出力:JSONを「お願い」ではなく「保証」で受け取る

業務システム連携では、自然文より安定したJSONが要です。以前はプロンプトで「必ずJSONだけ返して」と頼む方法が中心でしたが、頼むだけでは前置きや説明文が混ざる崩れが起きえます。現在の Claude API には、JSON Schema を渡して出力がそのスキーマに必ず適合する「構造化出力」が用意されています(2026年に一般提供化)。プロンプト頼みではなく、デコード自体をスキーマで制約するのが違いです。

プロンプトで「JSONで」と頼む 了解しました。以下です: { "category": "billing" } 前置きが混ざり崩れることがある JSON Schema で制約する { "category": "billing", "priority": 1 } 常にスキーマ通りに適合

FIG.4 「JSONでお願い」から「スキーマで保証」へ

使い分けの目安は次の通りです。データ抽出・分類・レポート生成のように最終出力をJSONで欲しい場合は構造化出力(出力フォーマット指定)、Claudeが関数を呼ぶときの引数を固めたい場合は前節の厳密ツール使用、という整理になります。なお具体的なパラメータ名(出力フォーマットの指定方法)や対応モデルは更新が入るため、導入時は公式の Structured outputs ページを確認してください。

import json
from pydantic import BaseModel, ValidationError

class TicketResult(BaseModel):
    category: str   # billing | technical | sales | other
    priority: int
    summary: str

# 構造化出力(JSON Schema 指定)で受け取る。指定方法は公式ドキュメントの最新に従う。
resp = client.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=300,
    temperature=0,
    messages=[{"role": "user", "content": "次の問い合わせを分類して: 請求金額が先月と違います"}],
)

text = "".join(
    block.text for block in resp.content if getattr(block, "type", "") == "text"
)

# スキーマ制約があっても、アプリ側の検証は省かない(多層防御)
try:
    result = TicketResult(**json.loads(text))
except (json.JSONDecodeError, ValidationError) as e:
    # 失敗時のフォールバック(再試行・人手確認など)
    raise

ポイントは3つ。temperature は低め(0〜0.2)にして形式ぶれを抑える、列挙値・数値範囲・必須項目をスキーマで明示する、そしてAPI側の保証があってもアプリ側で再検証する(外部からの値は信用しない、の原則)。説明文とJSONを同時に返させると崩れやすいので、説明用APIと構造化APIは分けるのが定石です。

05プロンプトキャッシュ:長い共通前置きのコストを下げる

システムプロンプト・長い業務ルール・製品仕様書を毎回送ると、レイテンシも料金も増えます。そこで効くのがプロンプトキャッシュです。共通で使う長い前提部分をキャッシュ対象に印cache_control)し、繰り返し呼ぶ構成にすると、高頻度のAPIで効果が出ます。

2026年前半時点の目安として、キャッシュにヒットした入力は通常入力の約10%(およそ90%引き)。最初の書き込みは追加コストがかかり、5分有効なら約1.25倍、1時間有効なら約2倍の入力単価です。つまり同じ前置きを繰り返し使うほど元が取れる仕組みです(料金は変動するため公式 Pricing で確認)。

共通の前置き(固定) cache_control で印 2回目以降 入力 約10% 可変の入力だけ送る 回答

FIG.5 固定の前置きはキャッシュ再利用、可変部分だけ毎回送る

  • 向いている:長いガイドライン、共通ナレッジ、固定テンプレート、出力ルール、分類基準
  • 向かない:毎回ほぼ内容が変わるプロンプト(再利用率が低くキャッシュ書き込み分が無駄になる)

実装では「どこまでを固定部分にするか」が肝です。社内規程・出力ルール・分類基準などを固定化し、ユーザー入力だけを可変にすると、キャッシュの再利用率が上がります。長時間にわたる繰り返し処理では、1時間有効のほうがヒット率を稼げる場面があります。

06Batch API:大量処理は同期APIと分けて考える

レビューコメント要約、問い合わせ自動分類、商品説明文の一括生成など、数百〜数万件の非同期処理には Batch API が向きます。即時性は下がりますが、運用しやすく、レート制御もしやすいのが利点です。2026年前半時点では、入力・出力ともに約50%割引で、コスト面のメリットも大きいです(割引率・上限は公式で確認)。

即時性が要る即時性が不要
通常API/ストリーミングBatch API
チャット、長文生成UI夜間処理、大量分類・要約
1件ずつリアルタイムまとめて投入し後で回収(約50%割引)

現場では、ユーザーが待つ処理はストリーミング社内バックオフィスの大量処理はBatchと分けると設計しやすくなります。Batchは1件あたりの処理が5分を超えることもあるため、共通の前置きをキャッシュするなら1時間有効のキャッシュを選ぶとヒット率が上がります。Batchの割引とキャッシュ割引は併用でき、共有コンテキストの大量処理ではコストをさらに圧縮できます。

Reliability & Safety

高機能ほど「制御層」を厚くする

上級機能は便利な一方、外部処理や自動判断が絡むほど事故の余地も増えます。Tool Use の引数、構造化出力の妥当性、APIの一時失敗──いずれもアプリ側の検証・権限・ログで受け止めます。下図のように、生成結果を素通しせず、必ず検証層を1枚はさむのが安全設計の基本です。

Claude 検証層 スキーマ検証 / 権限 / ログ 合格→業務処理 不合格→再試行/人手 業務処理

FIG.6 生成結果は素通しせず、検証層を1枚はさんでから業務へ

とくに副作用のある操作(送信・更新・削除)は要承認・最小権限を徹底し、ハルシネーション対策として引用や一次情報で裏取りする経路を用意します。料金・モデル名・APIパラメータは変わるので、本番投入前に公式ドキュメントで再確認するのを運用フローに組み込みましょう。

07おすすめの全体構成

機能が増えるほど、責務を層に分けておくと後の変更が楽になります。モデルやプロンプトを差し替えても、アプリ全体への波及を抑えられます。

  • UI層:ストリーミング表示、キャンセル操作
  • API層:Claude呼び出し、リトライ、レート制御、モデルIDの一元管理
  • Tool層:検索・参照・更新を分離し、それぞれ権限を設定
  • 検証層:JSON/スキーマ検証、監査ログ、権限確認、要承認フロー

08段階導入のロードマップ

最初から全部入れる必要はありません。失敗しにくく効果が見えやすい順に、小さく入れていくのが堅実です。

01

構造化出力

分類・抽出など「後工程が決まっている」処理から。JSON Schemaで出力を固定し、アプリ側でも検証する。

02

ストリーミング

チャットや長文生成のUXを底上げ。表示はUI専用、保存は最終確定テキストで分離。

03

Tool Use

外部処理が必要になったら導入。ツールを役割別に分け、副作用には承認・最小権限を設定。

04

キャッシュ / Batch

規模とコストが見えてきたら最適化。共通前置きをキャッシュ、大量処理はBatchへ。割引は併用可。

09まとめ

Claude API の上級機能は、用途で使い分ける道具箱です。待たせないストリーミング、外部処理をつなぐTool Use、壊れないJSONを保証する構造化出力、長い前置きを安くするキャッシュ、大量処理をまとめるBatch──どれも「全部入れる」より「必要なものから段階導入」が成功の近道です。共通する設計原則は、生成結果を素通しせず検証層をはさむことと、モデル名・料金・パラメータは変わる前提で公式ドキュメントを確認すること。この2点を守れば、変化の速いAPIでも安定した実装を保てます。