stop_reason: refusal

Claude Fable 5 的 stop_reason: refusal

安全分类器拒绝了这个请求。它是一个成功的 HTTP 200 响应,这正是大多数集成完全察觉不到它的原因。

30 秒版本

Fable 5 跑着能拒绝请求的安全分类器。拒答是 HTTP 200,stop_reason 为 refusal,content 数组为空,并带一个标明类别的 stop_details 对象,不会抛任何异常。请在每次调用后判断 stop_reason,读出类别,然后改发给另一个 Claude 模型。reasoning_extraction 这个类别最容易让团队措手不及,因为要求模型「复述推理过程」的提示词就会命中它。

五种拒答类别

stop_details.category 指明命中的策略领域。当拒答不对应任何具名类别时,category 和 explanation 都会是 null,这个 null 是永久值,不是占位符。

  • bio

    请求可能助长生物危害,例如危险的实验方法。有益的生命科学工作也可能命中。在 Claude Code 里,Fable 5 上的 bio 命中会把会话切到 Opus 5;而 Opus 5 自己也跑生物学分类器且没有下一级回退,所以之后再被 bio 命中就直接以拒答收场。

  • cyber

    请求可能助长网络危害,例如恶意软件或漏洞利用开发。良性的网络安全工作同样会命中。渗透测试、CTF 练习和安全工具类代码库经常触发,往往在第一个请求就中,这属于预期内的路由行为,不是你的账号被标记了。

  • frontier_llm

    请求可能协助开发竞争性 AI 模型,这在 Anthropic 的商业条款中受限制。良性的机器学习工作也可能命中,所以评测流水线和模型对比工具有时会意外落到这个类别里。

  • general_harms

    请求触及了被判定为有害的领域,但不对应更具体的类别。良性工作偶尔也会命中,而这个类别也是最有可能通过重新措辞、或补充说明使用意图来解决的。

  • reasoning_extraction

    请求要求模型在响应文本里复现其内部推理。提示词、skill 或 harness 指令里出现「展示你的思考过程」「一步一步想」「解释你的推理」之类的说法,就会命中这个类别,并导致大量回退到 Opus 4.8。这是 Fable 5 上最常见的自找型拒答。

按这个顺序修

先能检测,再谈缓解。数不清自己有多少次拒答,就无法判断回退到底有没有生效。

  1. 1

    2. 审查提示词里的推理复述类表述

    在系统提示、skill 和 harness 指令里搜索所有要求模型把内部推理作为响应文本回显、转述或解释的内容,然后删掉。如果确实需要看到推理,改成读自适应思考返回的结构化 thinking block。

  2. 2

    1. 判断 stop_reason,而不是判断 content

    每次调用后直接检查 stop_reason 是否等于 refusal,或者检查 stop_details.type。不要用 content 数组为空来推断拒答,也不要解析 stop_details.explanation,它的文本不稳定,是给人看的而不是给逻辑用的。

  3. 3

    3. 在每一条请求路径上都配置回退

    服务端回退需要 fallbacks 参数加上 server-side-fallback-2026-07-01 beta 头,且在 Claude API 上仍是 beta。SDK 中间件则在任何平台都能用。无论选哪种,重试处理器和后台 worker 里也要加上;子代理调用要单独配置,因为这个参数不会传递到工具执行内部发起的模型调用。

  4. 4

    5. 把拒答做成独立指标

    拒答是 200,所以基于错误率或 5xx 的监控永远看不见它。为每次拒答、以及每次由回退模型服务的响应各打一个事件(后者以 usage.iterations 里的 fallback_message 条目识别),然后对两者的差值告警。

  5. 5

    4. 给回退模型留足速率限制余量

    如果回退模型本身被限流或过载,回退尝试会被跳过,返回的仍然是原来的拒答。按你预期的拒答量给回退模型配足限额,否则恰恰在负载最高的时候,回退会悄悄退化成拒答。

不是拒答?

如果你拿到的是真正的 HTTP 错误而不是 200,请从状态码开始排查。处理方式完全不同。

常见问题