細粒度工具串流
針對對延遲敏感的應用程式,在不經伺服器端 JSON 緩衝的情況下串流工具輸入。
「Fine-grained tool streaming」(細粒度工具串流)會在 Claude 生成工具輸入的同時將其傳送至您的用戶端,而不經過伺服器端緩衝或 JSON 驗證。省略緩衝步驟可縮短大型參數(例如一份文件或一段程式碼)第一個片段到達的時間,而這些片段會透過與標準工具使用相同的串流訊息事件送達。
如何使用細粒度工具串流
所有模型皆在 Claude API、Amazon Bedrock、Claude Platform on AWS、Google Cloud 以及 Microsoft Foundry 上支援細粒度工具串流。若要使用它,請在任何您想啟用細粒度串流的使用者定義工具上將 eager_input_streaming 設為 true,並在您的請求中啟用串流(streaming)。
eager_input_streaming 欄位是選用的。將其設為 true 會為該工具開啟細粒度串流;省略它則會得到標準的緩衝串流,此時 API 會在將每個參數值串流回傳之前先對其進行緩衝與驗證。例外情況是仍然傳送舊版 fine-grained-tool-streaming-2025-05-14 beta 標頭的請求,該標頭會為未設定此欄位的工具開啟細粒度串流。這個逐工具設定的欄位取代了該標頭,而明確設為 false 則會讓工具維持緩衝串流,即使請求仍然傳送該標頭亦然。舊版標頭不能與電腦使用或瀏覽器使用工具集項目合併使用:API 會拒絕同時傳送兩者的請求,因此請移除該標頭,並在需要的使用者定義工具上設定 eager_input_streaming。欄位定義請參閱工具參考。
以下範例為 make_file 工具開啟細粒度串流,並要求 Claude 寫一首長詩,使工具輸入大到足以觀察其串流過程:
client = anthropic.Anthropic()
with client.messages.stream(
max_tokens=65536,
model="claude-opus-5",
tools=[
{
"name": "make_file",
"description": "Write text to a file",
"eager_input_streaming": True,
"input_schema": {
"type": "object",
"properties": {
"filename": {
"type": "string",
"description": "The filename to write text to",
},
"lines_of_text": {
"type": "array",
"description": "An array of lines of text to write to the file",
},
},
"required": ["filename", "lines_of_text"],
},
}
],
messages=[
{
"role": "user",
"content": "Can you write a long poem and make a file called poem.txt?",
}
],
) as stream:
for event in stream:
if event.type == "input_json":
print(event.partial_json, end="", flush=True)
final_message = stream.get_final_message()
print()
for block in final_message.content:
if block.type == "tool_use":
print(f"Complete tool input: {block.input}")每個分頁都為 make_file 工具開啟了細粒度串流。SDK 分頁會在每個輸入片段到達的當下將其印出,然後在串流結束後印出完整累積的輸入。cURL 分頁顯示原始事件串流,而 CLI 分頁使用 jq 僅印出片段。由於印出的片段會拼接成完整的工具輸入,這首詩會隨著 Claude 的書寫逐漸填滿您的終端機:
{"filename": "poem.txt", "lines_of_text": ["The Wanderer's Journey", "", "I.", "", "Beneath the vast and star-strewn sky,", "Where silver moonbeams softly lie,", ...
Complete tool input: {"filename": "poem.txt", "lines_of_text": ["The Wanderer's Journey", ...]}若沒有 eager_input_streaming,API 會在將每個參數值串流回傳之前先對其進行緩衝與驗證,因此對於大型參數,在 Claude 完成生成之前不會印出任何內容。啟用後,片段會在 Claude 開始生成該參數時立即開始到達,而且它們通常較長、較少在單字中間斷開。
累積工具輸入增量
累積的約定與標準工具使用串流相同,因此本節無論是否使用 eager_input_streaming 皆適用。事件格式請參閱串流訊息中的輸入 JSON 增量。細粒度工具串流改變的是您對結果所能做的假設:伺服器在不驗證的情況下串流片段,因此累積的字串可能不是有效的 JSON。
當 tool_use 內容區塊進行串流時,初始的 content_block_start 事件包含 input: {}(一個空物件)。這是一個佔位符。實際的輸入會以一系列 input_json_delta 事件送達,每個事件攜帶一個 partial_json 字串片段。若要組合完整的輸入,請串接這些片段,並在區塊關閉時解析結果。
若您的 SDK 提供累積器輔助工具(如前一個範例中的 Python、TypeScript、Go、Java 和 Ruby 分頁所示),它會為您處理這件事。手動模式適用於沒有輔助工具的 SDK,或是當您想完全掌控輸入的組合方式時。
累積的約定:
- 在
type: "tool_use"的content_block_start時,初始化一個空字串:input_json = "" - 對於每個
type: "input_json_delta"的content_block_delta,進行附加:input_json += event.delta.partial_json - 在
content_block_stop時,解析累積的字串
請如以下 SDK 範例一樣對解析加以防護。回應也可能在參數中途因 max_tokens 而停止。請檢查停止原因,並決定是要以更高的 max_tokens 重試請求,還是修復不完整的輸入。
初始的 input: {}(物件)與 partial_json(字串)之間的型別不一致是刻意設計的。空物件標記了內容陣列中的位置,而增量字串則建構出真正的值。
client = anthropic.Anthropic()
tool_inputs: dict[int, str] = {} # index -> accumulated JSON string
with client.messages.stream(
model="claude-opus-5",
max_tokens=1024,
tools=[
{
"name": "get_weather",
"description": "Get current weather for a city",
"eager_input_streaming": True,
"input_schema": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
},
}
],
messages=[{"role": "user", "content": "Weather in Paris?"}],
) as stream:
for event in stream:
match event.type:
case "content_block_start" if event.content_block.type == "tool_use":
tool_inputs[event.index] = ""
case "content_block_delta" if event.delta.type == "input_json_delta":
tool_inputs[event.index] += event.delta.partial_json
case "content_block_stop" if event.index in tool_inputs:
raw_input = tool_inputs[event.index]
try:
parsed = json.loads(raw_input)
except json.JSONDecodeError:
# 累積的字串不保證是有效的 JSON。
# 請參閱本頁的「處理工具回應中的無效 JSON」。
print(f"Invalid tool input: {raw_input}")
else:
print(f"Tool input: {parsed}")處理工具回應中的無效 JSON
使用細粒度工具串流時,工具呼叫所累積的輸入可能是無效或不完整的 JSON。發生這種情況時,您無法執行該工具,因此請改為將失敗回報給 Claude。工具結果的 content 不一定要是 JSON,但將原始字串包裝在單一鍵的 JSON 物件中,可以讓 Claude 明確知道您收到了無效的 JSON,並保留原始輸入以供除錯:
{
"INVALID_JSON": "<the unparseable input you received>"
}將此包裝物件序列化為字串後,作為 is_error 設為 true 的工具結果內容區塊的 content 回傳:
{
"type": "tool_result",
"tool_use_id": "toolu_01A09q90qw90lq917835lq9",
"is_error": true,
"content": "{\"INVALID_JSON\": \"<the unparseable input you received>\"}"
}後續步驟
Was this page helpful?