没有启用提示词缓存的 Claude API 集成,等于在重复为已付过的 Token 买单。仅凭缓存一项,通常就能将费用削减一半。本教程带你走完 Anthropic SDK 的标准调用范式,以及真正影响账单的优化手段——并说明新模型发布时,哪些地方需要改、哪些不用动。
文档里最短的 Anthropic SDK 示例确实能运行——但它默认带着三个软性缺陷,在任何有真实流量的场景下都会烧钱:
SEARCH(...) 就执行搜索"这类逻辑,是一条充满痛苦的路——脆弱、没有 Schema 校验、不支持并行工具调用。SDK 提供了完善的 tools 结构,直接用它就好。LingCode 理解 Anthropic SDK 的调用范式,生成的集成代码默认包含缓存、工具调用和模型常量——让它来构建功能,你第一次拿到的就是优化后的版本。
.env 文件,变量名为 ANTHROPIC_API_KEY。@anthropic-ai/sdk),因为它覆盖了最完整的 API 形态;Python 版 anthropic SDK 与之方法一一对应。让 LingCode 帮你搭建 SDK 的初始结构。它生成的代码形态如下:
// src/claude.ts
import Anthropic from "@anthropic-ai/sdk";
const MODEL = "claude-sonnet-4-7-20260101"; // one place to bump
const client = new Anthropic(); // reads ANTHROPIC_API_KEY from env
export async function ask(userText: string) {
const res = await client.messages.create({
model: MODEL,
max_tokens: 1024,
messages: [{ role: "user", content: userText }],
});
return res.content[0].type === "text" ? res.content[0].text : "";
}
有三点值得注意:MODEL 是一个常量——所有调用都通过它路由。max_tokens 是显式指定的——SDK 要求必须提供。响应体是一个内容块数组,而不是字符串;模型可能返回多个块(文本、工具调用、思考过程),所以要始终检查类型。
from anthropic import Anthropic; client = Anthropic(); client.messages.create(...)。选你后端使用的语言即可,API 接口是一致的。
如果每次请求的系统提示都相同——通常都是——就把它标记为可缓存,第一次调用之后只需支付基础价格的 10%。五分钟的改动,有时能省下一半账单。
const SYSTEM_PROMPT = `You are a support agent for Acme Widgets.
Your knowledge base:
${KNOWLEDGE_BASE_TEXT}
Always cite the section number when answering.`;
const res = await client.messages.create({
model: MODEL,
max_tokens: 1024,
system: [
{
type: "text",
text: SYSTEM_PROMPT,
cache_control: { type: "ephemeral" },
},
],
messages: [{ role: "user", content: userText }],
});
有两条规则需要牢记:
res.usage.cache_creation_input_tokens 和 cache_read_input_tokens 来确认缓存是否真正命中。工具调用是一个三步协议:你声明工具,模型返回 tool_use 块,你回复 tool_result。SDK 提供了类型化的结构;不要把它退化成字符串解析。
const tools = [
{
name: "get_weather",
description: "Get current weather for a city.",
input_schema: {
type: "object",
properties: {
city: { type: "string", description: "City name, e.g. 'Paris'." },
},
required: ["city"],
},
},
];
let messages = [{ role: "user", content: "What's the weather in Tokyo?" }];
while (true) {
const res = await client.messages.create({
model: MODEL,
max_tokens: 1024,
tools,
messages,
});
if (res.stop_reason !== "tool_use") {
// Plain answer — done.
return res.content;
}
// The model wants a tool. Run it, reply, loop.
const toolUse = res.content.find((b) => b.type === "tool_use");
const result = await runTool(toolUse.name, toolUse.input);
messages.push({ role: "assistant", content: res.content });
messages.push({
role: "user",
content: [
{
type: "tool_result",
tool_use_id: toolUse.id,
content: JSON.stringify(result),
},
],
});
}
当 stop_reason 不是 tool_use 时(通常是 end_turn),循环结束。模型可能在一次响应中返回多个 tool_use 块(即并行工具调用);把它们全部执行,然后在一条用户消息中返回所有 tool_result。
cache_control: { type: "ephemeral" },即可将整个工具块标记为可缓存。工具数组越大,效果和缓存大型系统提示一样显著。
同样的调用,改为流式:
const stream = client.messages.stream({
model: MODEL,
max_tokens: 1024,
messages: [{ role: "user", content: userText }],
});
for await (const event of stream) {
if (event.type === "content_block_delta" &&
event.delta.type === "text_delta") {
process.stdout.write(event.delta.text);
}
}
const final = await stream.finalMessage();
console.log("usage:", final.usage);
流式事件包括 message_start、content_block_start、content_block_delta、content_block_stop、message_delta、message_stop。大多数 UI 场景只需要渲染 text_delta 增量;其余的是内务事件。finalMessage() 会返回完整响应——用量统计和停止原因都在里面。
LingCode 可以帮你接入以下任何一项,但它们不是随意的选择——每个都有特定的适用场景:
citations: { enabled: true },模型会返回指向源文本片段的引用对象。这是真实的溯源,不是模型凭感觉给出的答案。thinking: { type: "enabled", budget_tokens: 5000 }。模型会生成一个 thinking 内容块(在工具调用间保持,不会重新推理)。代价是这些思考 Token 会计费。适合数学、代码、多步骤规划;对"总结这段话"这类任务则是大材小用。memory 工具让模型能在多个会话间写入持久笔记。适合长期运行的智能体;在依赖它之前,先确认该模型的训练数据中确实包含此工具(查看模型说明页)。新的 Sonnet 或 Opus 发布时,迁移通常只需改一行——但回归检测是你的责任。API 在这些版本间是稳定的;模型的行为却不一定。
// Before
const MODEL = "claude-sonnet-4-6-20251022";
// After
const MODEL = "claude-sonnet-4-7-20260101";
替换后需要检查以下几点:
cache_read_input_tokens > 0)。max_tokens。废弃模型的迁移流程相同——Anthropic 会公布下线日期,在此之前更新常量即可。当你问 LingCode "当前 Sonnet 模型字符串是什么"时,它会读取模型废弃页面,并生成带回归测试的迁移代码。
claude-3-5-sonnet-latest 这类别名。它们会在你不知情的情况下漂移。请固定到带日期的快照版本(如 claude-sonnet-4-7-20260101),并有计划地进行迁移。
每次 Anthropic 响应都携带用量统计。记录它们:
console.log({
input: res.usage.input_tokens,
output: res.usage.output_tokens,
cache_create: res.usage.cache_creation_input_tokens,
cache_read: res.usage.cache_read_input_tokens,
});
有两个数字值得重点关注:cache_read_input_tokens / (cache_read + input + cache_create) 是你的缓存命中率——对于聊天机器人来说,超过 50% 意味着缓存正在发挥作用。output_tokens / input_tokens 是你的冗余比——如果它在数周内持续上升,说明你的提示词在悄悄引导模型输出更长的回答,账单也在跟着涨。
将整套工作流封装成一个 Skill,这样每次让 LingCode 接入 Claude 时,它都能自动选择正确的 API 结构、缓存策略和模型常量:
---
name: claude-api
description: Build, debug, and optimize Claude API / Anthropic SDK apps in TypeScript or Python. Apps built with this skill should include prompt caching. Also handles migrating between Claude model versions (Sonnet/Opus/Haiku 4.5 → 4.6 → 4.7, retired-model replacements). Triggers: anthropic SDK import, @anthropic-ai/sdk usage, prompt caching questions, tool use loops, streaming, batch API, files API, citations, memory, thinking. Actions: build Claude app, add prompt caching, migrate model version, fix Anthropic API error, optimize tokens, wire tool use. Skip if: code imports openai or other-provider SDK.
---
When wiring or modifying Claude API code:
1. Use @anthropic-ai/sdk (TS) or anthropic (Python). Same shape.
2. Centralize the model string in one constant — never inline.
Pin to dated snapshots, not -latest aliases.
3. Mark stable prefixes cacheable with
cache_control: { type: "ephemeral" }: system prompt, tools
array, large reused documents. Verify cache hits via
res.usage.cache_read_input_tokens.
4. Use the SDK tool-use shape (tools: [...], tool_use block,
tool_result reply). Never string-parse tool calls.
5. Handle parallel tool calls — a single response may contain
multiple tool_use blocks; run all, reply with all tool_results
in one user message.
6. For chat UIs, stream content_block_delta events. Use
finalMessage() for the assembled response.
7. Log usage stats on every call. Watch cache hit rate and
output/input ratio over time.
8. On model migrations: change the constant, re-run the eval
suite, verify cache still hits, check tool-call shape didn't
regress.
Prefer Batch API for offline enrichment (50% cheaper, 24h SLA).
Prefer Files API + caching for repeated queries against the same
document. Use extended thinking only when the problem warrants it
(math, code, multi-step planning).
保存为 ~/.lingcode/skills/claude-api/SKILL.md — 具体路径和 Skill 的发现机制,请参阅 安装 Skill。