"""Extended thinking + tool use round trip (Python SDK): turn 1 returns [thinking, tool_use]; turn 2 passes the assistant content back UNCHANGED (thinking block + signature) with the tool_result. Also streams a request to show thinking_delta / signature_delta events. STATUS: LIVE_VERIFIED 2026-09-18 (claude-haiku-4-5-20251001): turn1 stop_reason tool_use (47 thinking tokens), turn2 200 text answer; stream: 10 thinking_delta + 1 signature_delta. ≈$0.002. Run: .venv/bin/python examples/anthropic/thinking/thinking_tool_roundtrip.py """ from __future__ import annotations import os import sys from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parents[3])) from scripts import live # noqa: E402 import anthropic # noqa: E402 MODEL = os.environ.get("ANTHROPIC_MODEL", "claude-haiku-4-5-20251001") client = anthropic.Anthropic(max_retries=1) THINKING = {"type": "enabled", "budget_tokens": 1024} TOOL = {"name": "get_time", "description": "Returns the current UTC time.", "input_schema": {"type": "object", "properties": {}}} ask = "Use the get_time tool, then tell me the time in one short sentence." turn1 = client.messages.create(model=MODEL, max_tokens=1500, thinking=THINKING, tools=[TOOL], messages=[{"role": "user", "content": ask}]) print("turn1:", [b.type for b in turn1.content], turn1.stop_reason, turn1.usage.output_tokens_details) live.log_request("anthropic", "POST", "/v1/messages", 200, 0.001, f"example thinking/thinking_tool_roundtrip.py turn1 {MODEL}") tool_use = next((b for b in turn1.content if b.type == "tool_use"), None) if tool_use: turn2 = client.messages.create(model=MODEL, max_tokens=1500, thinking=THINKING, tools=[TOOL], messages=[ {"role": "user", "content": ask}, {"role": "assistant", "content": turn1.content}, # thinking + tool_use blocks, verbatim (required) {"role": "user", "content": [{"type": "tool_result", "tool_use_id": tool_use.id, "content": "12:00:00 UTC"}]}, ]) print("turn2:", [b.type for b in turn2.content], turn2.content[-1].text if turn2.content[-1].type == "text" else "") live.log_request("anthropic", "POST", "/v1/messages", 200, 0.001, f"example thinking/thinking_tool_roundtrip.py turn2 {MODEL}") # Streaming: thinking_delta events then a single signature_delta before content_block_stop. kinds: list[str] = [] with client.messages.stream(model=MODEL, max_tokens=1200, thinking=THINKING, messages=[{"role": "user", "content": "What is 2+2? Reply with the number."}]) as stream: for ev in stream: if ev.type == "content_block_delta": kinds.append(ev.delta.type) final = stream.get_final_message() print("stream deltas:", kinds, "| final:", [b.type for b in final.content], final.usage.output_tokens_details) live.log_request("anthropic", "POST", "/v1/messages", 200, 0.0003, f"example thinking/thinking_tool_roundtrip.py stream {MODEL}")