Claude Platform Docs
Messages工具基礎架構

細粒度工具串流

針對對延遲敏感的應用程式,在不經伺服器端 JSON 緩衝的情況下串流工具輸入。

「Fine-grained tool streaming」(細粒度工具串流)會在 Claude 生成工具輸入的同時將其傳送至您的用戶端,而不經過伺服器端緩衝或 JSON 驗證。省略緩衝步驟可縮短大型參數(例如一份文件或一段程式碼)第一個片段到達的時間,而這些片段會透過與標準工具使用相同的串流訊息事件送達。

如何使用細粒度工具串流

所有模型皆在 Claude API、Amazon BedrockClaude Platform on AWSGoogle 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,或是當您想完全掌控輸入的組合方式時。

累積的約定:

  1. type: "tool_use"content_block_start 時,初始化一個空字串:input_json = ""
  2. 對於每個 type: "input_json_delta"content_block_delta,進行附加:input_json += event.delta.partial_json
  3. 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>\"}"
}

後續步驟

了解上下文視窗的運作方式、擴展思考與工具使用如何計入其中,以及如何隨著對話增長管理上下文。

透過伺服器傳送事件以增量方式串流 Messages API 回應,包括文字、工具使用與擴展思考增量。

解析 tool_use 區塊、格式化 tool_result 回應,並使用 is_error 處理錯誤。

Anthropic 提供之工具的目錄,以及選用工具定義屬性的參考。

Was this page helpful?