Claude Platform Docs
Messages使用 Claude 构建

回退抵扣

当您在另一个模型上重试被拒绝的请求时,避免重复支付提示缓存费用。

提示缓存是按模型划分的。当某个模型拒绝了一个请求,而您在另一个模型上重试时,已为第一个模型缓存的对话前缀必须从头写入新模型的缓存。缓存写入的费用高于缓存读取。"Fallback credit"(回退抵扣)消除了这部分额外费用。拒绝响应会携带一个抵扣令牌,您在重试时回传该令牌,重试的计费方式就如同该对话一直在新模型上进行一样。

只有当您自行构建重试逻辑时才需要阅读本页:通过原始 HTTP 或使用自定义重试逻辑。服务端回退SDK 中间件会自动应用回退抵扣。如果您使用其中任一种,请跳过本页。

拒绝与回退介绍了如何检测拒绝以及如何选择回退方式。如果您对缓存读取和缓存写入这些术语不熟悉,提示缓存对其进行了解释。

基本流程

  1. 通过 beta 标头选择启用

    发送可能被拒绝的请求时,附带 anthropic-beta: fallback-credit-2026-07-01 标头。server-side-fallback-2026-07-01 标头也会提供相同的字段,较早的 fallback-credit-2026-06-01 标头仍然被接受并提供相同的字段。

  2. 从拒绝响应中读取两个字段

    发生拒绝时,stop_details 包含两个字段:

    • fallback_credit_token 一个表示抵扣的不透明字符串。
    • fallback_has_prefill_claim 一个布尔值,告诉您应使用哪种重试请求体形态。

    当该拒绝没有可用抵扣时,两者均为 null

  3. 构建重试请求

    从被拒绝的请求体开始。将 model 设置为回退模型,并将令牌作为顶层 fallback_credit_token 参数添加。根据下表选择请求体形态。

  4. 使用相同的标头发送重试

    使用相同的 fallback-credit-2026-07-01 beta 标头发送重试。重试需要该标头才能兑换令牌。

fallback_has_prefill_claim 字段告诉您重试是否可以接续被拒绝模型的部分输出,而不是从头开始:

fallback_has_prefill_claim重试请求体
true被拒绝的请求体保持不变,再追加一条 assistant 消息,其 content 回传被拒绝响应的 content。重试模型从被拒绝模型停止的位置继续生成响应,已完成的服务端工具调用不会被重新执行。
false被拒绝的请求体,保持不变。

示例

以下示例发出一个可能被拒绝的请求,并在针对 Claude Opus 4.8 的重试中兑换抵扣令牌。当某次重试尝试被拒绝时,该示例会沿着拒绝阶梯逐级降级:即当重试被拒绝时中介绍的一系列逐步简化的重试形态。

client = Anthropic()

request = {
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "Hello, Claude"}],
}


def send(model: str, body: dict[str, object]) -> BetaMessage:
    return client.beta.messages.create(
        model=model, betas=["fallback-credit-2026-07-01"], **body
    )


response = send("claude-fable-5", request)

if (
    response.stop_reason == "refusal"
    and (details := response.stop_details)
    and (token := details.fallback_credit_token)
):
    exact_body = request | {"fallback_credit_token": token}
    # 优先使用 continuation 形式,除非 claim 为 False
    if details.fallback_has_prefill_claim is not False:
        echoed = [block.model_dump() for block in response.content]
        match echoed:
            case [*_, {"type": "text"} as final_block]:
                final_block["text"] = final_block["text"].rstrip()
        attempt = exact_body | {
            "messages": [
                *request["messages"],
                {"role": "assistant", "content": echoed},
            ]
        }
    else:
        attempt = exact_body

    try:
        response = send("claude-opus-4-8", attempt)
    except BadRequestError as error:
        if "redemption temporarily unavailable" in error.message:
            raise  # Transient: retry with the token within its five-minute window
        try:
            # 回退到未更改的 body,仍携带令牌
            response = send("claude-opus-4-8", exact_body)
        except BadRequestError as retry_error:
            if "redemption temporarily unavailable" in retry_error.message:
                raise  # Transient: retry with the token within its five-minute window
            # 令牌本身被拒绝:放弃该令牌并在不携带它的情况下重试。
            response = send("claude-opus-4-8", request)

print(json.dumps({"stop_reason": response.stop_reason, "model": response.model}))

适用范围

回退抵扣在 Claude API、Amazon Bedrock、Claude Platform on AWS、Google Cloud 和 Microsoft Foundry 上处于 beta 阶段。Message Batches 中的拒绝不会生成抵扣令牌,且兑换仅适用于直接的 Messages API 请求:在批处理请求中传递的令牌会被接受但会被忽略。

重试模型必须是被拒绝模型所允许的回退目标之一。对于 Claude Fable 5.1 和 Claude Fable 5,允许的目标是 Claude Opus 4.8(claude-opus-4-8)和 Claude Opus 5(claude-opus-5)。

检查抵扣是否已生效

退款体现在重试的 usage 中。与同一请求在不带令牌时报告的数值相比,cache_creation_input_tokens 更低,而 cache_read_input_tokens 则高出相同的数量。变化为零意味着令牌已被接受,但没有需要重新定价的内容,例如因为重试模型的缓存已经是热的。

当重试被拒绝时

大多数重试在第一次尝试时即可兑换。如果未能兑换,API 会返回一个 400 错误,告诉您接下来该尝试什么。

  1. 接续被拒绝:重新发送未更改的请求体

    如果追加了 assistant 消息的重试被 400 错误拒绝,请重新发送未更改的被拒绝请求体,仍然附带令牌。

  2. 令牌被拒绝:去掉令牌

    如果未更改的请求体也被 400 错误拒绝,且错误消息中提到了 fallback_credit_token,请在不带令牌的情况下重试。抵扣将被放弃,但重试本身可以成功。

参考

以下各节介绍边缘情况和完整的兑换规则。大多数集成不需要这些内容。

后续步骤

检测拒绝,并在服务端回退、SDK 中间件和手动重试之间进行选择。

缓存读取和缓存写入的计费方式。

每个 stop_reason 值及其处理方式。

自动应用回退抵扣的 SDK 辅助工具。

Was this page helpful?