#!/usr/bin/env python3 """Stream a tool call and print every input_json_delta fragment. eager_input_streaming=True enables fine-grained streaming (no buffering / JSON validation) for that tool; guard the final json.loads. STATUS: LIVE_VERIFIED 2026-09-18 (b1 buffered 6 fragments, b2 eager 4 fragments). Run: .venv/bin/python examples/anthropic/tools/fine-grained-streaming/basic.py [--buffered] """ import json, sys from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parents[3])) from scripts.live import anthropic_request eager = "--buffered" not in sys.argv tool = {"name": "get_weather", "description": "Get the current weather for a city.", "eager_input_streaming": eager, "input_schema": {"type": "object", "properties": {"location": {"type": "string"}}, "required": ["location"]}} st, lines, _ = anthropic_request("POST", "/v1/messages", {"model": "claude-haiku-4-5-20251001", "max_tokens": 150, "stream": True, "tools": [tool], "tool_choice": {"type": "any"}, "messages": [{"role": "user", "content": "Weather in San Francisco, CA?"}]}, stream=True, note=f"fine-grained-streaming eager={eager}") buf = "" for ln in lines: if not ln.startswith("data: "): continue ev = json.loads(ln[6:]) if ev["type"] == "content_block_start": print("start:", ev["content_block"]) elif ev["type"] == "content_block_delta" and ev["delta"]["type"] == "input_json_delta": frag = ev["delta"]["partial_json"]; buf += frag; print("fragment:", repr(frag)) elif ev["type"] == "content_block_stop": try: print("parsed input:", json.loads(buf)) except json.JSONDecodeError: # possible with eager streaming / max_tokens cut-off -> return {"INVALID_JSON": buf} as is_error tool_result print("INVALID_JSON:", buf)