アプリにAIを組み込むとき、本当に欲しいのは「読み物としての文章」ではなく、そのままプログラムが処理できるデータです。`{"name":"…","amount":1200}` のような決まった形で返ってくれば、画面に表示したり、DBに保存したり、次の処理へ渡したりできます。これを実現するのが構造化出力(Structured Output)とFunction / Tool Calling。本稿では、2026年時点の仕組みと、実務で壊れない設計の勘所を整理します。
FIG.1 スキーマ(型の設計図)を渡すと、出力の「形」を固定できる
01「自由文」と「構造化出力」は別物
チャット画面で人間が読む答えは、文章として自然であれば十分です。ところがアプリの中でAIを使うときは、答えの一部を確実に取り出せることが必要になります。たとえば領収書の写真から「店名」「金額」「日付」を抜き出して経費精算フォームに入れる場面では、AIが「だいたい1,200円くらいでした」と書いてくれても困ります。プログラムが読むのは "amount": 1200 のような決まった形です。
そこで使うのが、出力の型(スキーマ)をあらかじめ定義し、その形で返させる仕組みです。何を必須にするか、各項目は文字列か数値か、選べる値は何か——これを設計図として渡します。
022つの代表的な手段
構造化を実現する道具は、大きく次の2つに整理できます。役割が違うので、目的で選びます。
| JSON 構造化出力 | Function / Tool Calling |
|---|---|
| 欲しいのは「整ったデータ」 | 欲しいのは「どの操作を・どんな引数で呼ぶか」の意図 |
| 抽出・分類・要約をJSONで受け取る | 外部API・DB・社内関数を呼ぶ前段に使う |
| 例:領収書→{店名, 金額, 日付} | 例:天気を聞かれたら get_weather(city="東京") を提案 |
| 返ってくるのはデータそのもの | 返ってくるのは「呼び出しの提案」。実行は自前のコード |
大事なのは、Function Calling はAIが関数を実行するわけではないという点です。モデルは「この関数を、この引数で呼ぶとよさそう」という意図を返すだけ。実際に呼ぶかどうか、その引数が安全かは、受け取ったあなたのコードが判断します。
FIG.2 モデルは「呼びたい」と言うだけ。検証して実行するのは人/コード
032026年の現在地:形は「ほぼ保証」できる
かつては「JSONで返して」とお願いしても、前置きの文章が混じったり、途中で壊れたJSONになったりして、後処理が大変でした。2026年現在、状況は大きく変わっています。主要なAPIがスキーマで生成を拘束する機能を正式提供しているからです。
- OpenAI:関数定義や応答フォーマットに
strict: true+ JSON Schema を指定すると、文法(CFG)でトークン生成を制約し、スキーマに違反する出力をそもそも作れなくする。旧来の「JSON モード」はレガシー扱い。 - Anthropic(Claude):Structured Outputs が Claude Opus 4.5 / Sonnet 4.5 / Haiku 4.5 で一般提供。スキーマを文法にコンパイルして生成を制約し、「JSON 出力」と、ツール引数を厳密に一致させる「strict tool use」の2パターンを使える。
つまり出力の「形」は、かなり確実に守らせられる時代になりました。「壊れたJSONを直すコード」を主役にする必要は薄れています。
スキーマで保証できるのは「形」であって、「中身の正しさ」ではない。
04形が正しくても、中身は嘘をつく
ここが最重要です。スキーマ拘束は「数値の項目に文字列が来る」「必須項目が欠ける」といった構造の崩れを防ぎます。しかし、その数値が事実として正しいかは保証しません。
たとえば入力に答えが含まれないとき、モデルは「分からない」と言う代わりに、もっともらしい嘘を正しい形で埋めてきます。"price": -500(負の価格)や、存在しない注文ID、根拠のない "confidence": 0.97 のように。JSONとしては完璧でも、業務としてはゴミです。
FIG.3 構文(形)と意味(中身)は別レイヤー。両方を検証する
だからスキーマ拘束があっても、受け取った後の意味の検証(業務ルール)は省けません。価格は0以上か、注文IDは実在するか、日付は妥当な範囲か——これらは自分のコードでチェックします。
05壊れにくくする設計の勘所
「形はAPIが守る/中身は自分で守る」を前提に、成功率を上げる具体策を挙げます。
選べる値は enum で固定する
ステータスのように候補が決まっている項目は、自由記述にせず enum: ["active","inactive","pending"] と列挙する。型を string にするより圧倒的に安定し、表記ゆれも消える。
「不明」を表現できる形にする
答えが入力に無いときに嘘で埋めさせないため、null 許容や "unknown" といった逃げ道をスキーマに用意し、根拠が無ければそれを選ぶよう指示する。
受け取ったら業務ルールで検証
範囲・整合性・実在性をコードでチェック。失敗したらリトライやフォールバック(既定値・人手確認)へ。Pydantic(Python)や Zod(TypeScript)が定番。
関数の引数は実行前に必ず検証
Function Calling では、モデルの提案を信用せず引数を検査。返金・送信・削除のような重要操作は承認を挟む・権限を最小化する。
06知っておくべきトレードオフ
便利な反面、運用上の注意点もあります。誇張せず正しく押さえておきます。
- 遅延とコスト:スキーマは入力トークンを消費し、生成中も妥当なトークンを追跡するためレイテンシが増えることがある。特に深いネスト・長い説明文・巨大な enum で顕著。スキーマは必要十分にとどめる。
- 複雑なスキーマは失敗しやすい:拘束は厳密になる一方、過度に複雑な構造では生成が破綻する場合がある。まずシンプルな形から始める。
- 拒否(refusal)への対応:安全方針に反する要求では、モデルがスキーマに沿った出力ではなく拒否を返すことがある。OpenAI は refusal を判別できる仕組みを持つので、拒否時の分岐も実装する。
- 提供状況は変わる:対応モデルや料金・パラメータ名は更新が早い(例:Claude の
output_format→output_config.formatへの移行)。実装前に必ず公式ドキュメントで最新仕様を確認する。
07勘所
構造化出力と Function Calling は、LLMをプログラムに組み込むための接着剤です。2026年現在、出力の「形」はAPIのスキーマ拘束でほぼ保証できます。残る仕事は中身の正しさ——形はAPIに、意味は自分のコードに守らせる、という役割分担が安定運用の前提です。enumで選択肢を縛り、「不明」を表現でき、業務ルールで検証してから実行する。この型を押さえれば、AIをアプリの一部として安心して動かせます。