ツール入力の初動を速くする eager_input_streaming — 引き換えに失うものを把握する
Claude API でツールを使うとき、標準のストリーミングは各パラメータの値をサーバ側でいったんバッファし、JSONとして妥当かを検証してからクライアントへ返す。安全だが、パラメータが大きいほど最初の1文字が届くまで待たされる。
ファイル1本ぶんのテキストやコードブロックをツール入力として生成させる場合、この待ち時間がそのまま体感の遅さになる。eager_input_streaming はこのバッファと検証を省く。
有効化はツール単位
Claude API、Amazon Bedrock、Claude Platform on AWS、Google Cloud、Microsoft Foundry のいずれでも、全モデルが対応している。使いたいツール定義に eager_input_streaming: true を足し、リクエスト側でストリーミングを有効にするだけだ。
1 | |
ツール単位で指定できるのが実務上は効く。全ツールで有効にする必要はない。大きなパラメータを生成するものだけに付け、他は既定のバッファ付きのままにしておけば、検証を失う範囲を最小限にできる。
省略すれば従来どおりのバッファ付き。例外として、旧来の fine-grained-tool-streaming-2025-05-14 ベータヘッダを送り続けているリクエストでは、フィールド未設定のツールも有効になる。この場合、明示的に false を指定したツールだけがバッファ付きのまま残る。ヘッダからの移行中なら、ここは意識しておいたほうがいい。
失うもの
公式ドキュメントの警告が本質だ。
Because the API does not buffer or validate a tool’s input before streaming it, you might receive partial or invalid JSON.
蓄積した文字列が妥当なJSONである保証がなくなる。 加えて、レスポンスが max_tokens に達してパラメータの途中で切れることもある。
したがって、有効にするなら次の3つがセットで必要になる。
1. パースのガード
蓄積の手順自体は標準のツールストリーミングと同じだ。content_block_start で空文字列を初期化し、input_json_delta のたびに partial_json を追記し、content_block_stop でパースする。
1 | |
Python、TypeScript、Go、Java、Ruby のSDKにはアキュムレータのヘルパがあり、組み立ては任せられる。手動パターンが要るのは、ヘルパの無いSDKか、組み立てを自分で制御したい場合だ。なお「断片に反応すること」と「組み立てること」は別の関心事で、届くたびに画面へ流しつつ組み立てはヘルパに任せる、という構成もできる。
2. 停止理由の確認
stop_reason が max_tokens なら、最後のブロックが不完全な tool_use になっている可能性がある。max_tokens を上げて再試行するか、部分入力を修復するかを決める必要がある。
3. 不正入力をClaudeへ返す経路
パースできなかったとき、ツールは実行できない。黙って落とすのではなく失敗を伝える。公式が示す形はこうだ。
1 | |
生の文字列を単一キーのオブジェクトで包むと、「不正なJSONを受け取った」ことがClaudeに曖昧でなく伝わり、元の入力もデバッグ用に残る。このラッパーは文字列連結ではなくJSONライブラリで組み立てること。 不正入力に引用符が混ざっていたときに壊れる。
使いどころ
得るのは初動のレイテンシ、失うのは入力の妥当性保証。この交換が見合うのは、入力が大きく、かつ最初の断片が早く届くことに意味がある場面に限られる。
- 向く: ファイルの中身やコードを生成させ、そのまま画面へ流す
- 向かない: 都市名を1つ渡すだけのような小さい入力(差を体感できない)
上の3つを用意しないまま有効にすると、稀に出る不正JSONでアプリケーションが落ちる。逆に言えば、3つ揃っているなら副作用なく速くなる。
eager_input_streaming の詳細と各言語のコード例は きめ細かいツールストリーミング に日本語でまとめた。あわせて stop_reason の7種類と対処を整理した stop_reasonの扱い方 も置いてある。とくに「tool_result ブロックの後にテキストを足してはいけない」理由は、知らないと踏む類の落とし穴なので一読をおすすめする。