約 4 分で読めます

Claude構造化出力の失敗設計と再試行の実装

Claude API構造化出力JSON Schema中小企業

請求書や問い合わせメールからJSONを取り出して基幹システムに流す。この処理でJSONが一度でも壊れると、夜間バッチが止まり、翌朝に担当者が手で直すことになります。構造化出力はこの問題を大きく減らしますが、「絶対に壊れない」わけではありません。失敗する条件を先に知っておくことが、運用の手間を決めます。

構造化出力は何を保証し、何を保証しないのか

構造化出力はJSON Schemaへの準拠を文法制約で強制する機能です。内容の正しさは保証せず、refusalやmax_tokensでは準拠が崩れます。

Claude APIの構造化出力には2つの機能があります。output_config.format に json_schema を渡す JSON outputs は、回答そのものの形を縛ります。ツール定義に strict: true を付ける strict tool use は、ツール呼び出しの引数を縛ります。両者は独立して使え、同じリクエストで併用もできます。ツール定義の基本はFunction callingのツール定義で扱っています。

保証されるのは形式です。たとえば金額欄に数値が入ることは保証されますが、その数値が請求書と合っているかは別問題です。金額の突合や必須項目の業務ルール検証は、アプリ側に残ります。

どのスキーマ記法が使えないのか

数値範囲や文字数の制約は使えず、使うと400エラーになります。上限や桁数の検証はアプリ側のバリデーションで行います。

対応しているのは、object・array・string・integer・number・boolean・null、enum、const、anyOf、$ref などです。object には additionalProperties: false が必須です。対応していないものの代表は次のとおりです。

  • 再帰的なスキーマ
  • minimum / maximum / multipleOf といった数値制約
  • minLength / maxLength といった文字列制約
  • 0または1以外の minItems

「金額は0以上」「品名は50字以内」のような条件は、スキーマに書かず description で伝え、受信後にコードで検証します。公式SDKのヘルパー(Pythonの messages.parse() など)は、未対応の制約を説明文に移しつつ、返却後にローカルで元の制約を検証します。小規模な内製開発では、このヘルパーを使うのが最短です。

出力が壊れるのはどんな時か

壊れる主因は2つです。stop_reasonがrefusalまたはmax_tokensの場合、出力はスキーマに合わない可能性があります。

  • stop_reason: "refusal": HTTPステータスは200で返り、生成されたトークンには課金されます。拒否が優先されるため、スキーマ準拠は保証されません。
  • stop_reason: "max_tokens": 出力が途中で切れ、不正なJSONになりえます。max_tokens を引き上げて再試行します。

もう一つ、見落としやすい挙動があります。enum や const の値は、先頭の大文字・小文字が変わって返ることがあります。エラーにはならないため、比較は大文字小文字を区別せずに行い、大小文字だけが違う enum 値は作らないでください。また、推論過程をスキーマのプロパティに出させる設計は reasoning_extraction の拒否を招くことがあるため、理由欄は短い説明にとどめます。

最小限の受け口をどう実装するか

受信側で行うのは、stop_reasonの確認、スキーマ外の業務検証、再試行の上限設定の3点です。この3点が運用の安全網になります。

  1. stop_reason が end_turn 以外ならパースせず、max_tokens なら上限を上げて1回だけ再試行する
  2. パース後に金額の突合や日付の妥当性など業務ルールを検証し、不合格なら人間の確認キューに回す
  3. 再試行は上限を決め、超えたら失敗として記録する。無限再試行は費用の暴走につながる

互換性にも制限があります。引用機能(Citations)を有効にしたまま output_config.format を使うと400エラーになります。メッセージのプリフィルも使えません。出典付きの回答と構造化抽出は、別のリクエストに分けてください。

運用コストと情報管理で押さえる点は何か

初回リクエストは文法のコンパイルで遅くなり、スキーマ構造を変えるとキャッシュが無効になります。スキーマは頻繁に変えない運用が前提です。

  • コンパイル済みの文法は最終利用から24時間キャッシュされます。スキーマ構造やツール構成を変えると再コンパイルされ、name や description だけの変更では無効になりません
  • output_config.format を変えると、その会話のプロンプトキャッシュが無効になります
  • 出力形式を伝える追加のシステムプロンプトが入るため、入力トークンがわずかに増えます。単価は公式の料金表で確認してください
  • 大量の帳票はバッチAPIと組み合わせられ、構造化出力でもバッチの割引が使えます
  • スキーマは文法としてプロンプトとは別に最大24時間保持されます。医療情報などの機微な値を、プロパティ名・enum値・patternに書いてはいけません。保持の扱いはデータ保持とZDRの解説も参照してください

参考

まとめ

構造化出力は形式を保証し、業務上の正しさと失敗時の挙動は実装側の責任として残ります。stop_reasonの確認、スキーマ外の検証、再試行の上限という3点を入れるだけで、夜間バッチが止まるリスクは大きく下がります。

Kuu株式会社のAI Opsでは、帳票抽出などのAI処理を、検証と例外処理まで含めて導入から定着まで伴走します。まずは自社の処理に合う設計を相談してください。

関連記事

Claudeの並列ツール呼び出し、結果の返し方と実行設計Claude Task Budgets設計——エージェントの費用上限Haiku 5.5移行の400エラーと長文課金の落とし穴Claude Vision APIの画像コスト設計手順