本文へスキップ
やす研究所 AI Lab
戻る

Claude Structured Outputs実践2026:output_configでJSONを壊さない実装手順

Claude Structured Outputs実践2026:output_configでJSONを壊さない実装手順

Claude で JSON を吐かせるとき、いまだに「JSON だけで返して」とプロンプトに書いていませんか。私も去年まではそうでした。ところが Structured Outputs が Claude API と Agent SDK に載ってから、この書き方は明確に古くなりました。

この記事では、output_config.format に JSON Schema を渡してサンプリング時点で構造を強制する実装手順を、Python の最小コードで解説します。読み終える頃には、あなたのパイプラインから json.loads() の try/except を1つ剥がせるはずです。

プロンプトで JSON を頼むのを今日でやめる理由

結論から書きます。2026年8月時点で、Claude に構造化データを返させる正解は Structured Outputs です。プロンプトで「JSON だけで返して」と書く方式ではありません。

理由は単純で、プロンプトはあくまで依頼で、生成自体は自由なため、モデルが「はい、JSON です:」と前置きを付けたり、末尾カンマや未エスケープの引用符を混ぜたりすることを止められないからです。私も以前は正規表現で無理やり中身を取り出していましたが、Sonnet 4.6 でも数百件に1件は壊れます。本番のバッチ処理では、その1件がジョブ全体を落とします。

Structured Outputs はこの問題を根っこから消します。JSON Schema をリクエストと一緒に渡すと、レスポンスがそのスキーマに厳密に従うようになるのがポイントです。プロンプトで祈るのではなく、サンプラー側で構造を強制する。ここが決定的に違います。

output_config.format の最小実装(Python)

動くコードを先に置きます。旅行プランを構造化して返す例です。

from anthropic import Anthropic

client = Anthropic()

response = client.messages.create(
    model="claude-opus-5",
    max_tokens=1024,
    messages=[
        {
            "role": "user",
            "content": "パリ旅行の計画を立てて。出発は2026年5月15日。",
        }
    ],
    output_config={
        "format": {
            "type": "json_schema",
            "schema": {
                "type": "object",
                "properties": {
                    "summary": {"type": "string"},
                    "next_steps": {
                        "type": "array",
                        "items": {"type": "string"},
                    },
                },
                "required": ["summary", "next_steps"],
                "additionalProperties": False,
            },
        }
    },
)

output_config.formattype: "json_schema"schema を渡すだけです。追加するのは実質1フィールド。機能そのものは、いつも送っているリクエストにフィールドを1つ足すだけという設計になっています。

additionalProperties: false は最初から入れておくのを勧めます。あとから余計なキーが混ざる事故を潰せます。私が最初にハマったのはここでした。スキーマは通ったのに、下流の Pydantic モデルが未知フィールドで落ちる、というやつです。

Agent SDK の場合は output_format を使う

Claude Code Agent SDK から呼び出す場合、パラメータ名だけ違います。TypeScript は outputFormat、Python は output_formatquery() に渡すと、エージェント完了時に result メッセージの structured_output フィールドに検証済みデータが入る仕組みです。

マルチターンのツール利用を挟んでも、最終的に返ってくる形は保証されます。エージェントが Web 検索や Bash を走らせて情報を集め、最後にあなたのスキーマに合わせて成形して返す。この分業がキレイに書けるようになりました。

もう一つ地味に効くのが、SDK がスキーマ検証に失敗したら自動で再プロンプトしてくれ、リトライ上限内で通らなければ構造化データではなくエラーが返る点です。自分でリトライループを書かなくていい。以前は for attempt in range(3) を全ハンドラに埋め込んでいた身としては、これだけで数十行のボイラープレートが消えました。

Pydantic を使うと型がそのまま降ってくる

私が普段使っている書き方はこれです。

from pydantic import BaseModel
from claude_agent_sdk import query

class Company(BaseModel):
    name: str
    founded_year: int
    headquarters: str

result = await query(
    prompt="Anthropic の会社情報を調べて",
    output_format=Company,
)

company: Company = result.structured_output
print(company.founded_year)  # int で受け取れる

完全な型安全のためには、TypeScript なら Zod、Python なら Pydantic でスキーマを定義すると強く型付けされたオブジェクトが返るので、IDE の補完がそのまま効きます。生 JSON をパースして手動でキャストする作業がなくなります。

ツール利用と Structured Outputs の使い分け

ここが誤解されやすいところです。「JSON を返させたい=tool use を使う」と覚えている人がまだ多い。実は2026年時点では役割が分かれています。

用途使う機能ポイント
最終レスポンスを固定フォーマットで返したいStructured Outputs (output_config.format)サンプリング時点でスキーマ強制
モデルに関数を呼ばせたいTool useClaude が関数側を呼び出す
関数の引数を厳密にしたいTool use + strict: true引数が必ずスキーマ準拠になる
ツール実行後に最終形を固定したい両方を組み合わせるツール完了後に構造化出力

各 SDK が構造化出力を扱いやすくするヘルパーを提供しているので、ドキュメントの SDK ページを一度眺めておくと迷いません。

両者を組み合わせるパターンは特に強力です。Claude がツールを呼んで情報収集し、最後にあなたが定義したスキーマ通りの JSON を返す。バックエンドの JSON バリデーションを一段減らせます。

スキーマコンパイルのキャッシュを味方につける

初回リクエストが妙に遅い、と感じたら仕様通りの挙動です。特定のスキーマを初めて使うときは文法コンパイルの追加レイテンシが発生し、コンパイル済み文法は最終使用から24時間キャッシュされ、以降のリクエストは大幅に速くなるという設計になっています。

実測はしていませんが、私の環境だと初回だけ体感で500msくらい遅い印象があります。2回目以降は普通のレスポンス速度。バッチ処理で数千件流すなら、最初の1件を捨てリクエストにして本番を回すのが安全です。

キャッシュはスキーマ内容を変えると無効化されます。プロパティを1つ足しただけでも別スキーマ扱いになるので、A/B テストでスキーマを頻繁に切り替えるとレイテンシが安定しません。本番用スキーマは早めに固めましょう。

prefilling が使えなくなった件と代替

以前 Claude で JSON を安定させるテクとして流行った prefilling(assistant メッセージの頭に { を差し込む手法)は、新しいモデルでは使えません。

Claude 4.6 以降のモデルと Claude Mythos Preview では prefilling がサポートされておらず、代わりに structured outputs か system prompt での指示を使うよう案内されている状況です。古い記事のコピペで messages の末尾に空の assistant を積んでいる実装を見かけたら、Structured Outputs に置き換えるサインです。

公式ドキュメントの表現も明確で、特定スキーマに準拠する有効な JSON を常に返させたいなら、プロンプトエンジニアリングではなく Structured Outputs を使うべきで、プロンプト側の技法は「厳格な JSON スキーマを超える柔軟性が欲しいとき」用とされています。優先順位が逆転したんですね。

Bedrock / Vertex での対応状況を先に確認する

本番投入前に必ず確認したいのが、実行基盤側の対応状況です。Anthropic 本家 API では動いても、AWS Bedrock や Google Cloud で使えるかは別問題。

幸い、Structured Outputs は Google Cloud 側でも公式にサポートされています。Google Cloud のドキュメントでは、Claude モデルの生成出力を特定の JSON スキーマに厳密に準拠させることができ、下流のアプリケーション・データベース・処理パイプラインに常に必要な形式で応答させたい場合に有用と説明されています。

Bedrock についてはリリースノートを都度確認するのが安全です。私は新機能を業務で入れる前に、必ず platform.claude.com のリリースノートを見にいく癖をつけています。バージョン境界をまたぐと動作が変わることが Claude では珍しくないので。

失敗しやすいのはスキーマの書き方、API ではない

3週間ほど社内ツールで Structured Outputs を回してみて、詰まったポイントはほぼ全部スキーマ側でした。API の使い方で困ったことは1回もありません。

よくやらかす失敗を3つだけ書いておきます。

  1. required を書き忘れる: プロパティを定義しても required に入れないと、モデルは省略していいと解釈します。省略されたキーで下流が落ちる典型パターン。
  2. enum を使わずに文字列で受ける: ステータスや分類名は必ず enum で列挙する。自由文字列で受けると「進行中」「進行中です」「in_progress」が混ざります。
  3. 深すぎるネストを一気に書く: 5階層以上のネストはコンパイル時間が伸びるうえ、モデルが埋めきれずに再プロンプトが増えます。フラット寄りに設計して、必要ならクライアント側で組み直すほうが速い。

この3つを潰しておくだけで、体感エラー率は肌感で1/10以下になりました。

Structured Outputs は「後付けの検証」を消す機能

この機能の本質は、Pydantic や zod で書いていた「返ってきた JSON を検証するコード」を、リクエスト側に前倒しできることです。バリデーションが失敗する未来を、そもそも発生させない設計に変える。

もし今あなたのコードベースに、Claude のレスポンスをパースしてから型検証している箇所が3つ以上あるなら、そこは全部 output_config.format に置き換える候補です。まずは一番エラーログが多いエンドポイントから試してみてください。

次の一手としては、Agent SDK の output_format と Pydantic を組み合わせて、マルチターンのツール実行を挟むエージェントを構造化出力で締める形が強力です。私の手元ではここが一番投資対効果が高い置き換えでした。

参考リンク


この記事をシェア:

次の記事
Cursor vs Windsurf 2026:$20並列時代の選び分け6軸