从 Anthropic 直连迁移到 BUZZ
如果你的代码现在调用 https://api.anthropic.com/v1/messages,迁移到 BUZZ 只需要改一个 URL。请求结构、响应结构、流式、Tool Use、Prompt Cache 全部字节级一致。
base_url(Python)或 baseURL(Node)改成 https://buzzai.cc,换一个 BUZZ API key。常规路径上你需要做的就是这两件事,本文剩下的内容都是"你不需要做什么"。
一行替换
Python SDK
修改前 — Anthropic 直连
from anthropic import Anthropic
client = Anthropic(
api_key=os.environ["ANTHROPIC_API_KEY"],
)
msg = client.messages.create(
model="claude-haiku-4-5-20251001",
max_tokens=200,
messages=[
{"role": "user", "content": "ping"}
],
)
修改后 — BUZZ
from anthropic import Anthropic
client = Anthropic(
base_url="https://buzzai.cc",
api_key=os.environ["BUZZ_API_KEY"],
)
msg = client.messages.create(
model="claude-haiku-4-5-20251001",
max_tokens=200,
messages=[
{"role": "user", "content": "ping"}
],
)
Node.js SDK
修改前 — Anthropic 直连
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
});
const msg = await client.messages.create({
model: "claude-haiku-4-5-20251001",
max_tokens: 200,
messages: [
{ role: "user", content: "ping" },
],
});
修改后 — BUZZ
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({
baseURL: "https://buzzai.cc",
apiKey: process.env.BUZZ_API_KEY,
});
const msg = await client.messages.create({
model: "claude-haiku-4-5-20251001",
max_tokens: 200,
messages: [
{ role: "user", content: "ping" },
],
});
curl
修改前
curl https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{...}'
修改后
curl https://buzzai.cc/v1/messages \
-H "Authorization: Bearer $BUZZ_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{...}'
三种鉴权 header 都支持
Anthropic 只接受 x-api-key。BUZZ 三种都接 —— 你现有代码已经在发的任何一种都能用。
| Header | 说明 |
|---|---|
Authorization: Bearer <KEY> | 推荐。与 OpenAI SDK 默认约定一致,也是 BUZZ 各接口的统一鉴权风格。 |
Authorization: Bearer sk-<KEY> | 接受。sk- 前缀会在服务端自动剥离。 |
x-api-key: <KEY> | 与 Anthropic SDK 默认行为一致。如果你的代码用 Anthropic SDK 且没改 header,发出去的就是这个。 |
anthropic-version 在 Anthropic 那边必填,在 BUZZ 上是可选的(缺失时默认 2023-06-01)。建议显式发送,这样同一份代码在两边都能用。
字节级一致的部分
BUZZ 做透明转发。你发的字节就是上游收到的字节,响应字节也是上游返回的字节。下面这些字段在 BUZZ 和 Anthropic 直连下行为完全一致。
请求字段
| 字段 | 状态 |
|---|---|
| model | 一致。直连用什么 model id,在 BUZZ 也用什么。claude-opus-4-7、claude-sonnet-4-6,以及带日期的 claude-haiku-4-5-20251001、claude-sonnet-4-5-20250929、claude-opus-4-5-20251101 都接受。 |
| messages | 一致。同样的 role 交替,同样的内容块(字符串或 text / image / tool_use / tool_result 数组)。 |
| system | 一致,包括带 cache_control 的数组形式。 |
| max_tokens / temperature / top_p / top_k / stop_sequences | 原样透传。 |
| stream | 一致,SSE wire 格式相同。详见流式处理指南。 |
| tools / tool_choice | 一致。已实测端到端:Tokyo 天气工具定义、多轮 tool_use / tool_result round-trip 都能直接跑通。 |
| thinking | 原样透传(Opus 4.7 Extended Thinking)。 |
| cache_control | 一致。字节级透传是 Prompt Cache 端到端可用的前提。实测:同一 payload 第一次 cache_creation_input_tokens=1200,第二次 cache_read_input_tokens=1200。 |
| metadata | 透传。Anthropic 主要用 {"user_id": "..."},BUZZ 不解释这个字段。 |
响应字段
| 字段 | 状态 |
|---|---|
| id, type, role, model, content, stop_reason, stop_sequence | 与 Anthropic 一致。stop_reason 枚举值相同:end_turn、max_tokens、stop_sequence、tool_use、pause_turn、refusal。 |
| usage.input_tokens / output_tokens / cache_creation_input_tokens / cache_read_input_tokens / cache_creation / service_tier | schema 与语义都一致。 |
| SSE 事件序列 | 一致:message_start、content_block_start、content_block_delta、content_block_stop、message_delta、message_stop、ping、error。 |
需要知道的差异
实战中只有以下几处差异。任何一个能容忍未知字段的 JSON 解析器都不需要改代码。
BUZZ 可能附加的响应字段
BUZZ 可能在响应中附加 Anthropic 不返回的计费透明化字段:
usage.iterations[]— 逐迭代 token 拆分context_management.applied_edits— 通常是空数组
BUZZ 永远不会删字段。你的解析器应该接受未知键并忽略。
HTTP 503 buzz_error · model_not_found
Anthropic 对未知模型返回 404。BUZZ 在你 group 下没有可用 channel 服务该模型时返回 503,error.type 为 "buzz_error",message 含 model_not_found。这是路由问题,不是上游故障。建议添加 503 处理,失败时拉取 GET /v1/models 实时列表。详见错误处理指南。
BUZZ 网关侧错误包络
Anthropic 直传错误保留官方形态 {"type":"error","error":{...},"request_id":"req_..."}。BUZZ 自身产生的错误(鉴权、schema 校验、channel 路由失败)使用:
{"error":{"type":"buzz_error","message":"... (request id: 202605260713...)"}}
如果你的错误处理只看 Anthropic 的 error.type 枚举,需要补一个 buzz_error 分支。BUZZ request id 拼在 error.message 末尾,不是独立字段。
通道级开关字段
三个可选字段在 channel 没开权限时会被静默丢弃:inference_geo、speed、service_tier。如果你的代码确实在用这些并依赖其效果,联系支持开通对应 allow flag。大多数调用方不用这三个。
用环境变量切换
最干净的做法是代码不动,仅通过环境变量切换。Anthropic SDK 会自动读取 ANTHROPIC_BASE_URL 和 ANTHROPIC_API_KEY。
# .env(直连时)
ANTHROPIC_API_KEY=sk-ant-...
# .env(切到 BUZZ)
ANTHROPIC_BASE_URL=https://buzzai.cc
ANTHROPIC_API_KEY=<YOUR_BUZZ_KEY>
同一份代码,不同环境变量。Claude Code 也是同样的套路:用环境变量把 CLI 指向 BUZZ,你现有的 prompt 和工程链都不用动。
并行对比测试
正式切流之前,先用代表性样本同时跑两个端点。目标是确认响应字节匹配,不是做 A/B benchmark。
import os, json
from anthropic import Anthropic
direct = Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])
buzz = Anthropic(base_url="https://buzzai.cc", api_key=os.environ["BUZZ_API_KEY"])
prompt = [{"role": "user", "content": "Say the word 'hello' and nothing else."}]
common = dict(model="claude-haiku-4-5-20251001", max_tokens=20, messages=prompt)
a = direct.messages.create(**common)
b = buzz.messages.create(**common)
print("direct text:", a.content[0].text)
print("buzz text:", b.content[0].text)
print("direct stop:", a.stop_reason)
print("buzz stop:", b.stop_reason)
# 期望:content text 相同、stop_reason 相同。
# usage token 数可能略有差异(每次调用独立),但 schema 完全一致。
同样的对比再跑一次 stream=True、Tool Use round-trip、长 system + cache_control。这四种场景字段形状都对得上,你其余的接口面也就稳了。
切换日核对清单
- 申请 BUZZ API key。dev / staging / prod 各用独立 key,可单独吊销。
- 用环境变量设 base URL。SDK 构造参数或
ANTHROPIC_BASE_URL=https://buzzai.cc。不要把 URL 硬编码在源码里。 - 显式发送
anthropic-version: 2023-06-01。BUZZ 可选、Anthropic 必填,显式发送让代码两边都能跑。 - 对最热的 prompt 做并行调用对比。比较非流式的
content[0].text和stop_reason,应当一致。 - 跑一次流式校验。确认收到一致的 6 个事件序列、以
message_stop结尾。详见流式处理指南。 - 跑一次 Tool Use 校验。发带 tool 定义的 prompt,响应应该带
tool_use内容块,补tool_result完成 round-trip。 - 跑一次 Prompt Cache 校验。同一 payload 带
cache_control:{type:"ephemeral"}的 system 块发两次。第一次cache_creation_input_tokens应非零,第二次cache_read_input_tokens应非零。 - 更新 503 与 BUZZ 错误包络的处理。详见错误处理指南。
- 拉一次实时模型列表。用新 key 请求
GET /v1/models,这是你 group 当前能路由的权威列表。 - 保留 Anthropic key。第一周作为回退目标和并行测试 harness 备用。
- 监控:HTTP 状态码分布、p50/p95 延迟、
cache_read命中率。切换后三项应当持平或更好(命中率上)。
回滚
切换是一行 URL 加一个 key,回滚也是。把 BUZZ_API_KEY 和 ANTHROPIC_API_KEY 都放在密钥仓里,翻一下生效中的 ANTHROPIC_BASE_URL 即可,不用改代码也不用发版。