/** * Prompt caching on tool definitions with the Node SDK (@anthropic-ai/sdk 0.126): cache_control on the LAST tool * caches the whole tools[] prefix. Two calls: write then read. * STATUS: LIVE_VERIFIED 2026-09-18 (claude-haiku-4-5-20251001): creation 6902 → read 6902 (probe with longer descriptions: 7484) (~$0.011). * Run: node --env-file=.env --experimental-strip-types examples/anthropic/prompt-caching/cache_tools.ts */ import Anthropic from "@anthropic-ai/sdk"; import { appendFileSync } from "node:fs"; const MODEL = process.env.ANTHROPIC_MODEL ?? "claude-haiku-4-5-20251001"; const client = new Anthropic({ maxRetries: 1 }); const log = (status: number, note: string) => appendFileSync("reports/live-requests.jsonl", JSON.stringify({ ts: new Date().toISOString(), provider: "anthropic", method: "POST", path: "/v1/messages", status, est_cost_usd: 0.005, note }) + "\n"); const filler = (seed: string, n: number) => Array.from({ length: n }, (_, i) => `Section ${seed}-${i}: The quarterly logistics review covers warehouse throughput, carrier performance, customs documentation, cold-chain compliance, and regional demand forecasting for the coming period.`).join(" "); const tools: Anthropic.Tool[] = Array.from({ length: 6 }, (_, i) => ({ name: `tool_${i}`, description: filler(`T${i}`, 30), input_schema: { type: "object" as const, properties: { q: { type: "string" } } }, })); tools[tools.length - 1].cache_control = { type: "ephemeral" }; // breakpoint on the last tool caches all tools for (const label of ["write", "read"]) { const msg = await client.messages.create({ model: MODEL, max_tokens: 8, tools, messages: [{ role: "user", content: "Reply with OK. Do not call tools." }] }); const u = msg.usage; console.log(`${label}: input=${u.input_tokens} creation=${u.cache_creation_input_tokens} read=${u.cache_read_input_tokens}`, u.cache_creation); log(200, `example prompt-caching/cache_tools.ts ${label} ${MODEL}`); }