eager_input_streamingの設定でツール入力を高速表示する
Anthropic APIのeager_input_streamingフィールドで、ツール入力をバッファリングなしに配信する設定方法をまとめます。旧betaヘッダーとの互換関係と、効果が出る場面も扱います。
eager_input_streamingで何ができるか
eager_input_streaming は、ツール定義に1つboolean値を足すだけで、そのツールの入力をサーバー側のバッファリングとJSON検証なしに配信させるフィールドです。長いコードやドキュメントをツール引数として書かせるとき、生成の完了を待たずに断片が届き始めます。
fine-grained tool streamingとは、Claudeが生成しているツール入力をリアルタイムで配信するAnthropic APIの仕組みです。標準のストリーミングは各パラメータをサーバー側で一度バッファリングし、値として妥当だと確認してから返します。この検証ステップを飛ばすのが eager_input_streaming の役割です。大きなパラメータ(ドキュメント全文やコードブロックなど)の最初の断片が届くまでの時間が短くなります。断片は標準のツール利用と同じストリーミングイベントで届くため、受け取り側のコードを大きく変える必要もありません。
想定される用途はレイテンシに敏感なアプリケーションです。コーディングエージェントが生成中のファイル内容を画面に流し込みたい場合や、長い記事の下書きをツール引数として書かせて執筆過程を見せたい場合に向きます。
設定でeager_input_streamingを有効にする
設定は tools 配列の各ツール定義に eager_input_streaming: true を1つ足すだけです。有効化はツール単位で、リクエスト全体を切り替えるオプションはありません。加えてリクエスト側で stream: true を指定しておく必要があります。
curl https://api.anthropic.com/v1/messages \
-H "content-type: application/json" \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-d '{
"model": "claude-opus-5",
"max_tokens": 65536,
"tools": [
{
"name": "make_file",
"description": "Write text to a file",
"eager_input_streaming": true,
"input_schema": {
"type": "object",
"properties": {
"filename": { "type": "string" },
"lines_of_text": { "type": "array" }
},
"required": ["filename", "lines_of_text"]
}
}
],
"messages": [
{ "role": "user", "content": "長い詩を書いてpoem.txtに保存して" }
],
"stream": true
}'このリクエストを流すと、filename と lines_of_text の断片が content_block_delta イベントとして生成の途中から届きます。eager_input_streaming を付けなかった場合、filename や lines_of_text はそれぞれの値が確定するまで画面に表示されません。フィールドは省略可能で、省略時は標準のバッファリングされたストリーミング(各パラメータ値を検証してから返す挙動)のままです。全モデルがClaude API・Amazon Bedrock・Claude Platform on AWS・Google Cloud・Microsoft Foundryで対応しています。
対象はユーザー定義ツールのみです。Web検索やコード実行のようなサーバーツールには適用されません。
変わるのは配信のタイミングだけで、届くイベントの種類自体は標準のtool useストリーミングと同じです。
旧betaヘッダーとの互換関係
以前は fine-grained-tool-streaming-2025-05-14 というbetaヘッダーをリクエストに付けることで、全ツールの入力ストリーミングを一括で切り替えていました。このヘッダーは現在も動きますが、ツールごとのフィールドがヘッダーを置き換える設計に変わっています。
具体的な優先順位は次のとおりです。ヘッダーを送ったリクエストでも、eager_input_streaming フィールドを明示的に設定していないツールにだけヘッダーの効果が及びます。逆にツールごとに eager_input_streaming: false を明示すれば、ヘッダーを送っていてもそのツールだけはバッファリングされたストリーミングのまま動きます。判断が割れるのはフィールドを明示していないツールだけです。
以前のヘッダー方式は「リクエスト全体でオン/オフを切り替える」設計でした。複数のツールを1リクエストに並べているとき、大きな入力を返すツールと小さな入力を返すツールが混在していても、全部まとめて同じ挙動になっていたということです。ツールごとのフィールドへの移行で、個別の判断ができるようになりました。マイグレーションの実務としては、ヘッダーを外して該当ツールに eager_input_streaming: true を移すだけで済み、他のツールの挙動は変わりません。
受け取った入力の組み立て方と注意点
断片の組み立て方自体は、eager_input_streaming の有無にかかわらず共通です。content_block_start イベントで空オブジェクト input: {} が届き、以降の input_json_delta イベントが運ぶ partial_json 文字列を連結していき、content_block_stop の時点でパースします。
違うのはここからで、eager_input_streaming を有効にしたツールではサーバーがJSONの妥当性を検証しないまま断片を流します。したがって連結した文字列が有効なJSONにならないケースが起こり得ます。応答が stop_reason: max_tokens で終わった場合も、パラメータが生成の途中で切れて同じ状態になります。検証をスキップして配信速度を優先する設計の代償が、まさにここに表れています。パースを必ずtry/catchで守ることが前提になります。この状態ではツールを実行できないので、受け取った文字列を{"INVALID_JSON": "..."}のように1つのキーで包み、is_error: trueを立てたtool_resultとして返します。生の文字列をそのまま返すより、何が起きたのかがClaudeに伝わります。包む処理は文字列連結ではなくJSONライブラリで組み立てます。壊れた入力に含まれる引用符などが正しくエスケープされるためです。差し戻しの具体的な形はストリーミング中に壊れたJSONが来たときの対処で詳しく扱っています。
組み立て処理そのものをSDKに任せられるかどうかは言語によって差があります。Python・TypeScript・Go・Java・Rubyの公式SDKは、断片を自動で連結して最終的な入力を返すアキュムレータヘルパーを提供しています。C#とPHPにはこのヘルパーが無く、content_block_start から content_block_stop までのイベントを自分で拾って文字列を連結する手動パターンが必要です。届いた断片をその場でUIに反映する処理と、最終的な入力として組み立てる処理は別の関心事として扱えます。アキュムレータヘルパーを使っていても、届いた断片をリアルタイムで画面に流し込む処理は自分で書く必要があります。手動パターンはヘルパーが無いSDKのための代替手段であるだけでなく、連結とパースのタイミングを自分で握りたいときの選択肢でもあります。ヘルパーがある言語でも、組み立ての途中で独自の検証を挟みたい場合は手動で組めます。
効果が出るツールの見分け方
すべてのツールで有効化する意味があるわけではありません。効果が体感できるかどうかは、パラメータの生成にかかる時間で決まります。
| ツールの性質 | 効果 | 理由 |
|---|---|---|
| 長文・大きなドキュメントを出力するツール(コード全文の生成、記事の下書き作成など) | 効果◎ | 理由生成に数十秒かかる大きなパラメータほど、先頭断片が早く届く恩恵が大きい |
短い文字列・数値1つを受け取るツール(get_weather のcityなど) | 効果ほぼ変化なし | 理由生成が一瞬で終わるため、バッファリングの有無を体感しにくい |
| サーバーツール(Web検索・コード実行など) | 効果対象外 | 理由フィールド自体がユーザー定義ツールにしか適用されない |
| Computer use / Browser useのツールセット | 効果対象外 | 理由ツールセットエントリ自体には設定できず、旧ヘッダーとの併用も拒否される |
自分のツールが表の上段に当たるかどうかは、実際にストリーミングなしで動かして生成にかかる秒数を測るのが早いです。最初の input_json_delta イベントが届くまでの時間と、content_block_stop までの合計時間を記録し、その差が数秒以上あるツールだけに絞って有効化すれば、無駄な検証コストを削減しつつ体感速度を改善できます。逆に差がほぼ無いツールにまで一律で設定を広げても、得られる恩恵より不正JSONを処理するコードの複雑化のほうが上回ります。
複数ツールを抱えるエージェントでは、この計測を1回で終わらせず、ツールを追加するたびに同じ手順を繰り返すのが実務的です。生成にかかる時間はツールの入力スキーマや用途によって変わるため、一度計測してeager_input_streamingを有効化したツールでも、スキーマを変更したタイミングで恩恵の有無を測り直す価値があります。
大量ツールを扱う設計全般で参照する価値があるのが、Anthropic Advanced Tool Useで解説したToolSearch ToolやProgrammatic Tool Callingです。こちらはツール定義そのものの数を絞る施策で、eager_input_streaming の配信速度改善とは直交する軸ですが、両方を組み合わせると大規模なツール構成でも待ち時間を抑えやすくなります。ツール呼び出しの往復自体を自動化したい場合はTool Runnerでツール呼び出しループを自動化するも参考になります。
導入時によくあるつまずき
設定自体は1行なので、つまずくのは大抵このあたりです。導入前に一通り目を通しておくと、実装後のデバッグ時間を減らせます。
stream: trueを忘れる:eager_input_streamingはツール側の設定で、リクエスト全体をストリーミングモードにするのは別のパラメータです。片方だけ設定しても効果が出ません。- ヘッダーを送ったのに一部のツールだけ速くならない: 旧betaヘッダーは
eager_input_streamingを明示していないツールにしか及びません。あるツールだけfalseを明示していないか確認します。 - JSONをパースしてからツールを実行しようとする実装で、パースエラーをキャッチしていない: バッファリングされたストリーミングに慣れていると、届いた入力は常に有効なJSONだという前提でコードを書きがちです。
eager_input_streamingを有効にした瞬間、この前提が崩れます。 max_tokens由来の途中切れと、フォーマットエラー由来の不正JSONを区別しない: 両方とも症状は「パースできない」で同じですが、前者は生成トークン数を増やして再試行する対応、後者はClaudeにもう一度書き直させる対応が基本です。stop_reasonを見て切り分けます。
まとめ
eager_input_streaming: true をツール定義に足すだけで、そのツールの入力がバッファリングと検証なしに配信されるようになります。旧betaヘッダーはツールごとのフィールドが未設定のツールにだけ効くフォールバックとして残ります。検証を飛ばす代償として不完全なJSONを受け取る可能性が生まれるため、組み立て処理は必ずパースエラーを想定して書きます。設定自体は1行ですが、効果が出るツールを見極めてから適用する運用にすると、実装コストに見合った改善を得やすくなります。