Claude API には「出力形式をスキーマで固定する」構造化出力と「どのソース文書の何番目の文を根拠にしているか明示する」引用機能の2つがあります。

構造化出力:パースエラーをなくす

output_config.format に JSON スキーマを渡すと、Claude の応答が必ずスキーマに準拠した JSON になります。スキーマに違反した出力が生成されなくなるため、json.loads() のエラーハンドリングや手動バリデーションが不要になります。

additionalProperties: False の指定は必須です。これがないとスキーマに存在しないフィールドが生成される場合があります。スキーマは自動的に24時間キャッシュされるため、繰り返し送信してもコストは増えません。

response = client.messages.create(
    model="claude-opus-4-8",
    max_tokens=1024,
    messages=[{"role": "user", "content": "田中太郎(taro@example.com)がエンタープライズプランに興味を持っています。"}],
    output_config={
        "format": {
            "type": "json_schema",
            "schema": {
                "type": "object",
                "properties": {
                    "name": {"type": "string"},
                    "email": {"type": "string"},
                    "plan_interest": {"type": "string"},
                },
                "required": ["name", "email", "plan_interest"],
                "additionalProperties": False,
            },
        }
    },
)
import json
data = json.loads(response.content[0].text)
# data は {"name": "田中太郎", "email": "taro@example.com", "plan_interest": "エンタープライズ"} のような形

Python SDK では Pydantic モデルを直接渡せる client.messages.parse() も使えます。Pydantic の BaseModel をそのまま渡すと、スキーマ変換とレスポンスのデシリアライズを自動で行ってくれます。

引用機能:ハルシネーション対策と RAG

ドキュメントに citations: {"enabled": True} を設定すると、Claude の回答内の各主張がどのソース文書のどの箇所に基づくかが明示されます。

response = client.messages.create(
    model="claude-opus-4-8",
    max_tokens=1024,
    messages=[{
        "role": "user",
        "content": [
            {
                "type": "document",
                "source": {"type": "text", "media_type": "text/plain",
                           "data": "草は緑色です。空は青色です。"},
                "citations": {"enabled": True},
            },
            {"type": "text", "text": "草と空の色は何ですか?"},
        ],
    }],
)

レスポンスには複数のテキストブロックが返ってきます。各ブロックに citations 配列が付き、cited_text(引用テキスト)・document_index(ドキュメント番号)・start_char_index / end_char_index(文字位置)が含まれます。cited_text は出力トークンにカウントされないため、長いドキュメントに対して多くの引用がある場合でもコスト効率が良いです。

2つを組み合わせる:注意点

引用と構造化出力は同時に使えません。引用は本文テキストと引用ブロックを交互に生成する必要があり、厳密な JSON スキーマ制約と競合するためです。両方を有効にすると 400 エラーが返ります。

「引用付きの JSON」が必要な場合は2段階の処理が現実的です。

  1. 第1リクエスト:引用を有効にしてドキュメントから回答を生成する
  2. 第2リクエスト:第1リクエストの回答(引用情報を含むテキスト)を入力として、構造化出力で JSON に変換する

これにより引用の根拠と構造化データの両方を得られます。

まとめ

  • 構造化出力:output_config.format でスキーマを指定。パースエラー・バリデーション不要
  • additionalProperties: False は必須。スキーマは自動で24時間キャッシュされる
  • 引用:ドキュメントに citations: {"enabled": True} を付けると根拠箇所が明示される。RAG システムでのハルシネーション対策に有効
  • cited_text は出力トークンにカウントされないのでコスト効率が良い
  • 引用と構造化出力は同時に使用できない(400 エラー)。2段階処理で組み合わせる