A
AIエージェントの仕組み
ch4-s2 · JSON Schema

JSON Schema 入門

約 12 分

この回のゴール

1. なぜスキーマが必要か

前回までの Claude とのやり取りは 自然言語 でした:

User: 明日のランチの予定を教えて
Claude: 明日は 12 時にアリスとイタリアンレストランです。

でも、LLM に 機械が解釈できる構造 で返してほしい場面があります:

そこで:

この形式の JSON で返してね」と形式を指定する = JSON Schema

2. JSON Schema の基本

JSON Schema は「JSON の を記述する JSON」です。

最小の例

{
  "type": "object",
  "properties": {
    "name": {"type": "string"},
    "age":  {"type": "integer"}
  },
  "required": ["name", "age"]
}

これは「オブジェクトで、name(文字列)と age(整数)が必須」という意味。

マッチする JSON 例

{"name": "Alice", "age": 30}    
{"name": "Alice"}                age 欠けている
{"name": "Alice", "age": "三十"}  age が文字列

3. 使える型(type)

"string" "hello"
"integer" 42
"number" 3.14
"boolean" true
"array" [1, 2, 3]
"object" {"key": "val"}
"null" null

4. よく使う追加属性

description — LLM が一番見るところ

{
  "type": "string",
  "description": "ユーザーの氏名。姓と名のあいだは半角スペース。"
}

LLM は description を頼りに何を入れるか判断 します。これが一番大事。

enum — 有限の選択肢

{
  "type": "string",
  "enum": ["positive", "negative", "neutral"]
}

array + items

{
  "type": "array",
  "items": {"type": "string"}
}

ネスト(object の中の object)

{
  "type": "object",
  "properties": {
    "user": {
      "type": "object",
      "properties": {
        "name":  {"type": "string"},
        "email": {"type": "string", "format": "email"}
      },
      "required": ["name", "email"]
    }
  },
  "required": ["user"]
}

5. Claude での使い道 その 1 — 構造化出力

output_config.format を使えば、Claude の 応答全体 を JSON に強制できます:

response = client.messages.create(
    model="claude-haiku-4-5",
    max_tokens=512,
    messages=[{"role": "user", "content": "Jane Doe (jane@co.com) は 30 歳です。情報を抽出して。"}],
    output_config={
        "format": {
            "type": "json_schema",
            "schema": {
                "type": "object",
                "properties": {
                    "name":  {"type": "string"},
                    "email": {"type": "string"},
                    "age":   {"type": "integer"},
                },
                "required": ["name", "email", "age"],
                "additionalProperties": False,
            }
        }
    }
)

応答の content[0].text必ず有効な JSON になる。

Pydantic でもっと楽に

from pydantic import BaseModel

class Contact(BaseModel):
    name: str
    email: str
    age: int

response = client.messages.parse(  # .parse を使うと自動 validate
    model="claude-haiku-4-5",
    max_tokens=512,
    messages=[{"role": "user", "content": "..."}],
    output_format=Contact,
)
contact: Contact = response.parsed_output  # 👈 Pydantic インスタンスで返る

Python では Pydantic が定番です。スキーマとパースが 1 つのクラスで済む。

6. Claude での使い道 その 2 — ツール入力(次回!)

Claude API のツール定義:

tools = [{
    "name": "calculator",
    "description": "数式を評価する。電卓として使える。",
    "input_schema": {   # 👈 JSON Schema をここに書く
        "type": "object",
        "properties": {
            "expression": {
                "type": "string",
                "description": "評価する数式。Python eval 互換。例: '3 * (4 + 5)'"
            }
        },
        "required": ["expression"]
    }
}]

input_schemaJSON Schema そのもの。Claude はここから:

  1. いつこのツールを使うべきか(description を見て)
  2. 何を渡すべきか(properties と各フィールドの説明)

を判断します。

7. スキーマ設計のコツ

悪い例 良い例
description: "名前" description: "ユーザーの氏名。フルネームを推奨。日本語可。"
型が曖昧 (string だけ) enum で選択肢を絞る
余計な field タスクに必要な最小限 のフィールド
required なしで全部 optional 本当に必須 のものは required

👉 スキーマは LLM に読ませるドキュメント。明確に、具体的に書く。


まとめ

この回の限界(次への動機)

スキーマを書けるようになった。次は実際に Claude にツールを呼ばせる ループを動かす番。 👉 次回「電卓ツールを作る」で、tool_use / tool_result の 2 往復メッセージングを完全に実装します。

参考文献

📝 理解度クイズ (3 問) 💡 ログインすると進捗が保存されます

💬 このサブステップの Q&A

まだ質問はありません。最初の質問を投稿してみましょう。

質問の投稿にはログインが必要です。