BUZZ AI Gateway
文档 · 指南 · 从 Anthropic 迁移

从 Anthropic 直连迁移到 BUZZ

如果你的代码现在调用 https://api.anthropic.com/v1/messages,迁移到 BUZZ 只需要改一个 URL。请求结构、响应结构、流式、Tool Use、Prompt Cache 全部字节级一致。

POST https://buzzai.cc/v1/messages
迁移就是一行。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-7claude-sonnet-4-6,以及带日期的 claude-haiku-4-5-20251001claude-sonnet-4-5-20250929claude-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_turnmax_tokensstop_sequencetool_usepause_turnrefusal
usage.input_tokens / output_tokens / cache_creation_input_tokens / cache_read_input_tokens / cache_creation / service_tierschema 与语义都一致。
SSE 事件序列一致:message_startcontent_block_startcontent_block_deltacontent_block_stopmessage_deltamessage_stoppingerror

需要知道的差异

实战中只有以下几处差异。任何一个能容忍未知字段的 JSON 解析器都不需要改代码。

BUZZ 可能附加的响应字段

BUZZ 可能在响应中附加 Anthropic 不返回的计费透明化字段:

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_geospeedservice_tier。如果你的代码确实在用这些并依赖其效果,联系支持开通对应 allow flag。大多数调用方不用这三个。

用环境变量切换

最干净的做法是代码不动,仅通过环境变量切换。Anthropic SDK 会自动读取 ANTHROPIC_BASE_URLANTHROPIC_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。这四种场景字段形状都对得上,你其余的接口面也就稳了。

切换日核对清单

回滚

切换是一行 URL 加一个 key,回滚也是。把 BUZZ_API_KEYANTHROPIC_API_KEY 都放在密钥仓里,翻一下生效中的 ANTHROPIC_BASE_URL 即可,不用改代码也不用发版。

相关链接