Claude Platform Docs
MessagesInfrastruktur alat

Streaming alat fine-grained

Lakukan streaming input alat tanpa buffering JSON di sisi server untuk aplikasi yang sensitif terhadap latensi.

"Fine-grained tool streaming" (streaming alat fine-grained) mengirimkan input alat ke klien Anda saat Claude menghasilkannya, tanpa buffering atau validasi JSON di sisi server. Melewati langkah buffering mengurangi waktu hingga fragmen pertama dari parameter besar, seperti dokumen atau blok kode, dan fragmen-fragmen tersebut tiba melalui event Streaming pesan yang sama seperti penggunaan alat standar.

Cara menggunakan streaming alat fine-grained

Semua model mendukung streaming alat fine-grained di Claude API, Amazon Bedrock, Claude Platform on AWS, Google Cloud, dan Microsoft Foundry. Untuk menggunakannya, atur eager_input_streaming ke true pada alat buatan pengguna mana pun yang Anda inginkan streaming fine-grained-nya diaktifkan, dan aktifkan streaming pada permintaan Anda.

Field eager_input_streaming bersifat opsional. Mengaturnya ke true mengaktifkan streaming fine-grained untuk alat tersebut, dan menghilangkannya memberi Anda streaming ter-buffer standar, di mana API melakukan buffering dan memvalidasi setiap nilai parameter sebelum melakukan streaming kembali. Pengecualiannya adalah permintaan yang masih mengirim header beta lama fine-grained-tool-streaming-2025-05-14, yang mengaktifkan streaming fine-grained untuk alat yang membiarkan field tersebut tidak diatur. Field per-alat menggantikan header tersebut, dan nilai false eksplisit mempertahankan streaming ter-buffer untuk suatu alat bahkan ketika permintaan masih mengirim header itu. Header lama tidak dapat digabungkan dengan entri toolset computer use atau browser use: API menolak permintaan yang mengirim keduanya, jadi hapus header tersebut dan atur eager_input_streaming pada alat buatan pengguna yang membutuhkannya. Lihat Referensi alat untuk definisi field tersebut.

Contoh berikut mengaktifkan streaming fine-grained untuk alat make_file dan meminta Claude membuat puisi panjang, sehingga input alat cukup besar untuk diamati saat di-streaming:

client = anthropic.Anthropic()

with client.messages.stream(
    max_tokens=65536,
    model="claude-opus-5-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}")

Setiap tab mengaktifkan streaming fine-grained untuk alat make_file. Tab SDK mencetak setiap fragmen input begitu fragmen itu tiba, lalu mencetak input terakumulasi lengkap setelah stream berakhir. Tab cURL menampilkan stream event mentah, dan tab CLI menggunakan jq untuk mencetak hanya fragmen-fragmennya. Karena fragmen yang dicetak bergabung menjadi input alat lengkap, puisi tersebut memenuhi terminal Anda saat Claude menulisnya:

{"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", ...]}

Tanpa eager_input_streaming, API melakukan buffering dan memvalidasi setiap nilai parameter sebelum melakukan streaming kembali, sehingga tidak ada yang tercetak untuk parameter besar sampai Claude selesai menghasilkannya. Dengan field tersebut, fragmen mulai tiba segera setelah Claude memulai parameter, dan fragmen-fragmen itu biasanya lebih panjang, dengan lebih sedikit pemotongan di tengah kata.

Mengakumulasi delta input alat

Kontrak akumulasinya sama seperti untuk streaming penggunaan alat standar, jadi bagian ini berlaku dengan maupun tanpa eager_input_streaming. Lihat Input JSON delta di Streaming pesan untuk format event-nya. Streaming alat fine-grained mengubah apa yang dapat Anda asumsikan tentang hasilnya: server melakukan streaming fragmen tanpa memvalidasinya, sehingga string terakumulasi mungkin bukan JSON yang valid.

Ketika blok konten tool_use di-streaming, event content_block_start awal berisi input: {} (objek kosong). Ini adalah placeholder. Input sebenarnya tiba sebagai serangkaian event input_json_delta, masing-masing membawa fragmen string partial_json. Untuk menyusun input lengkap, gabungkan fragmen-fragmen ini dan parse hasilnya ketika blok ditutup.

Jika SDK Anda menyediakan helper akumulator (seperti yang dilakukan tab Python, TypeScript, Go, Java, dan Ruby pada contoh sebelumnya), helper tersebut menanganinya untuk Anda. Pola manual ditujukan untuk SDK tanpa helper, atau ketika Anda menginginkan kendali penuh atas cara input disusun.

Kontrak akumulasinya:

  1. Pada content_block_start dengan type: "tool_use", inisialisasi string kosong: input_json = ""
  2. Untuk setiap content_block_delta dengan type: "input_json_delta", tambahkan: input_json += event.delta.partial_json
  3. Pada content_block_stop, parse string terakumulasi

Lindungi proses parse, seperti yang dilakukan contoh SDK berikut. Respons juga dapat berhenti pada max_tokens di tengah parameter. Periksa stop reason dan putuskan apakah akan mencoba ulang permintaan dengan max_tokens yang lebih tinggi atau memperbaiki input parsial tersebut.

Ketidakcocokan tipe antara input: {} awal (objek) dan partial_json (string) memang disengaja. Objek kosong menandai slot dalam array konten. String delta membangun nilai sebenarnya.

client = anthropic.Anthropic()

tool_inputs: dict[int, str] = {}  # index -> accumulated JSON string

with client.messages.stream(
    model="claude-opus-5-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:
                    # String yang terakumulasi tidak dijamin merupakan JSON yang valid.
                    # Lihat "Handling invalid JSON in tool responses" di halaman ini.
                    print(f"Invalid tool input: {raw_input}")
                else:
                    print(f"Tool input: {parsed}")

Menangani JSON tidak valid dalam respons alat

Dengan streaming alat fine-grained, input terakumulasi untuk pemanggilan alat mungkin berupa JSON yang tidak valid atau tidak lengkap. Jika demikian, Anda tidak dapat menjalankan alat tersebut, jadi laporkan kegagalan itu kembali ke Claude. content dari hasil alat tidak harus berupa JSON, tetapi membungkus string mentah dalam objek JSON di bawah satu kunci membuatnya jelas bagi Claude bahwa Anda menerima JSON yang tidak valid, dan mempertahankan input asli untuk debugging:

{
  "INVALID_JSON": "<the unparseable input you received>"
}

Kembalikan pembungkus tersebut, yang diserialisasi menjadi string, sebagai content dari blok konten tool result dengan is_error diatur ke true:

{
  "type": "tool_result",
  "tool_use_id": "toolu_01A09q90qw90lq917835lq9",
  "is_error": true,
  "content": "{\"INVALID_JSON\": \"<the unparseable input you received>\"}"
}

Langkah selanjutnya

Pahami cara kerja jendela konteks, bagaimana pemikiran diperpanjang dan penggunaan alat diperhitungkan di dalamnya, dan cara mengelola konteks seiring percakapan bertambah panjang.

Lakukan streaming respons Messages API secara bertahap dengan server-sent events, termasuk delta teks, penggunaan alat, dan pemikiran diperpanjang.

Parse blok tool_use, format respons tool_result, dan tangani error dengan is_error.

Direktori alat yang disediakan Anthropic dan referensi untuk properti definisi alat opsional.

Was this page helpful?