Claude Fable 5.1のrefusal誤検知を防ぐプロンプトの書き方
無害なコーディング依頼がstop_reason: refusalで止まる3つの典型パターンと、プロンプト側で誤検知を減らす具体的な書き方をまとめます。
Claude Fable 5.1のrefusal誤検知とは
脆弱性診断やマイナー言語のコーディング依頼を送ったのに、応答が空で返ってくることがあります。これはエラーではなく、Claude Fable 5.1の安全分類器が誤って発火した状態です。応答はHTTP 200で返り、stop_reason が "refusal" になります。
Fable 5.1の安全分類器はFable 5の発売時点より誤検知が少なく、ソースコードの脆弱性を見つける作業自体は許可されています。それでも誤検知はゼロではありません。公式ドキュメントは、無害なコーディング依頼が誤って拒否されやすい状況を3つ挙げ、それぞれにプロンプト側の回避策を示しています。API・Claude Code・claude.aiのいずれで使う場合でも、拒否そのものが起きる仕組みは共通なので、以下の対処はどの利用形態でも当てはまります。
誤検知が起きたときの中身を確認する
対処法の前に、何が起きているかをstop_detailsで確認します。拒否はエラーではなく通常のレスポンスとして返るため、HTTPステータスコードの監視では検知できません。
{
"stop_reason": "refusal",
"stop_details": {
"type": "refusal",
"category": "cyber",
"explanation": "This request was declined because it could enable cyber harm."
}
}コーディング関連の依頼で誤って発火するのは主にcategory: "cyber"です。公式ドキュメントはこのカテゴリーを「サイバー被害を助長しうる依頼」と説明したうえで、「無害なサイバーセキュリティ関連の作業もこのカテゴリーを発火させうる」と明記しています。脆弱性診断やセキュリティレビューがこの説明に該当するケースです。explanationは表示用の文言でテキストが変わりうるため、分岐条件には使わずstop_reasonまたはstop_details.typeが"refusal"かどうかで判定します。
categoryにはコーディング以外の文脈で発火する値もあります。
category | 発火する領域 |
|---|---|
cyber | 発火する領域マルウェアやエクスプロイト開発を助長しうる依頼。無害なセキュリティ業務も対象になりうる |
bio | 発火する領域危険な実験手法など生物学的被害を助長しうる依頼 |
frontier_llm | 発火する領域競合AIモデルの開発を助長しうる依頼。無害な機械学習の作業も対象になりうる |
reasoning_extraction | 発火する領域モデルの内部推論をそのまま応答本文に再現させる依頼 |
general_harms | 発火する領域上記4つに当てはまらない利用ポリシー領域 |
エージェント構築やモデル評価パイプラインの実装依頼ではfrontier_llmが発火することもあります。コーディング作業だからといってcyberだけを想定してエラーハンドリングを書くと、他のカテゴリーで返ってきた拒否を取りこぼします。stop_details.categoryがnullになるケースもあり、これは名前の付いたカテゴリーに当てはまらない拒否を示す正常な値であって、実装の不具合ではありません。
誤検知を招く3つの言い回しと直し方
公式ドキュメントが挙げる誤検知の典型パターンは3つです。いずれもリクエストの中身ではなく、聞き方・渡し方を変えるだけで発火率が下がります。
コンパイル確認の言い回しを変える
「このプログラムはエラーなくコンパイルできますか」という聞き方は、分類器が脆弱性探索や攻撃コードの検証と誤認しやすい表現です。同じ目的でも「このプログラムにバグはありますか」と言い換えると誤検知が減ります。
| 誤検知を招きやすい聞き方 | 推奨される言い換え |
|---|---|
| Does this program compile without errors? | 推奨される言い換えAre there any bugs in this program? |
コードレビューやCIのプロンプトテンプレートに「コンパイルの可否」を尋ねる定型文を組み込んでいる場合は、この言い換えに直すだけで対処できます。
マイナー言語には言語のコンテキストを渡す
知名度の低いプログラミング言語を扱うコーディング依頼も誤検知が起きやすいパターンです。モデルがその言語の一般的な用途や構文を十分に把握できていないと、通常の実装作業を不審なコードとして扱うことがあります。
対処法は、その言語のドキュメントへのアクセスを与えるなど、言語がどういうもので何に使われるかの文脈を先にモデルへ渡すことです。ツールの検索結果やCLAUDE.mdへの言語仕様の記載、システムプロンプトでの一言説明のいずれでも構いません。文脈が増えるほど、モデルは依頼の意図を実装作業として正しく解釈しやすくなります。
ツール出力のBase64データを取り除く
ツールがBase64エンコードされたデータをモデルのコンテキストに返す構成も、誤検知の原因になります。画像・バイナリ・シリアライズ済みデータをBase64のまま渡すツール連携は、この種の誤検知が起きやすい典型例です。
公式ドキュメントが推奨する対処は、Base64データをツール出力から取り除くことです。デコード済みの構造化データや要約に差し替え、モデルのコンテキストにBase64文字列そのものを渡さない設計にします。
// 誤検知を招きやすい: ツール出力にBase64をそのまま含める
const toolResult = {
content: [{ type: "text", text: fileBase64 }],
};
// 推奨: デコード後の内容や要約に差し替える
const toolResult = {
content: [
{ type: "text", text: `file: ${fileName} (${fileSizeBytes} bytes, ${mimeType})` },
],
};画像やバイナリを直接扱うツール連携ほどこの対処の効果が出やすい傾向です。ファイルの中身をモデルに読ませる必要がある場合は、Base64の生データそのものではなく、テキスト抽出やメタデータの要約に変換してから渡すようにします。
3つの対処を比較する
| 発火パターン | 対処 | 直す場所 |
|---|---|---|
| コンパイル確認の言い回し | 対処「バグはあるか」に言い換える | 直す場所プロンプトの文言 |
| マイナー言語のコーディング | 対処言語のドキュメントや説明を文脈として渡す | 直す場所プロンプトの文脈 |
| ツール出力のBase64 | 対処デコード済みデータや要約に差し替える | 直す場所ツール連携の実装 |
前者2つはプロンプトの書き方だけで完結し、コードの変更は不要です。3つ目だけはツール側の実装を変える必要があるため、対処のコストが異なります。手を付けやすい順に、まずコンパイル確認の言い回しとマイナー言語への文脈追加を試し、それでも拒否が残るならツール出力の設計を見直すのが現実的な進め方です。
誤検知でも課金されるのか
出力が始まる前に拒否された場合、その呼び出しは課金されません。contentは空で返り、usageにトークン数は表示されますが請求対象にはなりません。ただし、レート制限の消費分にはこのリクエストもカウントされます。誤検知が多いプロンプトを無自覚に繰り返し送っていると、費用は発生しなくてもレート制限を圧迫することになります。
一方、途中まで出力が進んでからストリーミング中に拒否された場合は扱いが変わります。この場合は入力トークンと、そこまでに出力された分の出力トークンが通常料金で課金されます。コンパイル確認の言い回しやマイナー言語の文脈不足のように依頼の冒頭から誤検知が起きやすいパターンは出力前に止まりやすく、課金の影響は比較的小さくなります。
対処を反映したら同じ依頼で確認する
言い回しを変えたり文脈を足したりしたあとは、同じ依頼を再送してstop_reasonが"refusal"から変わったかを確かめます。単発の手動確認であれば会話をやり直すだけで十分ですが、CIやエージェントのパイプラインに組み込んでいる場合は、誤検知が起きていたプロンプトのセットを手元に残しておき、プロンプトテンプレートを変更するたびに同じセットで再実行すると回帰を見つけやすくなります。
この対処が効かない場合の切り分け
上記3パターンに当てはまらないのに拒否が続く場合、それはプロンプトの言い回しで避けられる誤検知ではなく、実際に利用ポリシーの対象領域に触れている可能性があります。ペネトレーションテスト・エクスプロイト生成・バイナリベースの脆弱性スキャンのような両用(dual-use)作業は、脆弱性発見の許可対象には含まれず、Fable 5.1でも拒否されます。
プロンプトの書き方を変えても解決しない拒否については、発生後にコード側でどう検出し、どのモデルへ再試行するか(fallbacksパラメータやSDKミドルウェアでのフォールバック設定)をClaude Fable 5.1の解説記事の「安全装置とデータ保持」で扱っています。ストリーミング応答での検出とコンテキストのリセット手順はClaude APIのrefusal stop_reasonを検出してリセットする方法にまとめています。
Claude Codeでの誤検知との違い
Claude Codeを使っていて「safety measures flagged」のような表示でセッションが止まる現象も、根っこにあるのは同じ安全分類器です。ただし出てくる場所と直し方は異なります。API呼び出しの場合、レスポンスは常にHTTP 200で返り、stop_reason: "refusal"をコード側で検知して分岐させる設計です。Claude Codeの場合は対話セッションの途中でエラーメッセージとして表示され、モデル名と「意図的に広くとった安全機構」である旨の説明文が付きます。
対処の経路も分かれます。API側は本記事で扱った言い回しの調整やツール出力の設計変更で誤検知そのものを減らすアプローチが中心です。Claude Code側はCyber Verification Programという専用の申請窓口があり、防御目的の正当なセキュリティ業務であることを申請して認められると、以降のセッションでフラグの発生自体を抑えられます。単発の誤検知であれば、Claude Codeは/rewindでフラグが立つ前のチェックポイントまで戻り、別の言い回しで続ける対処も使えます。Claude Codeでの誤検知の見分け方と解除手順は「safety measures flagged」とは — Claude Codeのセキュリティ誤検知の対処で扱っています。
誤検知の見落としを防ぐエラーハンドリングの設計
通信障害やレート制限のエラーだけを監視する作りになっていると、誤検知による拒否には気づけず、空の応答をそのままユーザーに返してしまいます。ここまでの対処を実装に反映するには、stop_reasonの値をレスポンスごとに分岐条件として確認する設計が前提になります。この分岐をAPIのエラーレスポンスとどう区別して組むかは、stop_reasonとエラーの違い — Claude APIの成功と失敗を混同しない設計に整理しています。
まとめ
Claude Fable 5.1の安全分類器はFable 5より誤検知が少なくなっていますが、コンパイル確認の言い回し・マイナー言語・ツール出力のBase64データという3つの状況では依然として無害なコーディング依頼がstop_reason: "refusal"で止まります。対処はいずれもプロンプト側の書き方の調整で完結し、コードの変更を必要としません。それでも拒否が続く場合は、dual-useに触れる依頼でないかをまず確認したうえで、fallbacksパラメータによるAPI側のリカバリを検討する流れが現実的です。