AI 開発

OpenAI Agents API + JSON Schema 実践:安定し、検証でき、実行できる JSON をどう出すか(2026)

約 16 分

一般の Schema 稿は、なぜ契約が要るかを書いた。本稿は Agents API にだけ落とす:モデルが埋める JSON は、門を通ってから実行する。ツール引数、MCP 入力、自分の台帳は三つの門であり、「JSON を出して」という一文ではない。

読む前の一覧

門 何を鎖すか 誰が実行するか
Function parameters order_id、真偽、列挙 additionalProperties: false
宿主の検証 required_actions の arguments 通らねば関数を走らせない
最終カード 利用者に見せるオブジェクト 別 Schema。text.format ではない
MCP 別ツール表の inputSchema subagent は継承しうる

Schema は門であり、礼儀ではない。広い object はもう一枚の門を開けたままにする。

安定、検証、実行は三つの手続きであり、一つのスイッチではない

Agents API でもモデルは JSON を埋めるだけ。公式の function には parameters Schema が要る。required、additionalProperties: false、必要なら pattern / enum。これで埋めが安定する。検証とは、実行前に同じ Schema で arguments を走らせること。実行とは、門のあとで宿主が副作用を出すこと。

  • 安定:ツール引数を厳しい Schema にする。広い object は鍵の発明を招く。
  • 検証:required_actions の呼び出しを手元で検証する。履歴の function_call では足りない。
  • 実行:門を通らねば lookup_order を走らせない。success: false と理由を返す。黙って庫を触らない。

ツールの呼び方は OpenAI Agents API 完全解説。四つの対象を ID で留める話は Agents API の JSON データ構造。Schema / Function Calling / Structured Output の一般の分け方は AI に JSON Schema が必要な理由。本稿は定義を繰り返さない。Agents session への落とし方だけを書く。

第一の門:agent.tools の parameters

公式の function は name、description、JSON Schema。session 作成時に agent.tools へ書く。架空の注文。実鍵は貼らない:

{
  "type": "function",
  "name": "lookup_order",
  "description": "Look up an order by ID. Confirm before any refund.",
  "parameters": {
    "type": "object",
    "properties": {
      "order_id": { "type": "string", "pattern": "^[A-Z]-\\d{4}$" },
      "include_lines": { "type": "boolean" }
    },
    "required": ["order_id", "include_lines"],
    "additionalProperties": false
  }
}

要点は少ない。すべての欄を required に入れる。オブジェクトは余分な鍵を閉じる。番号は pattern であり、裸の string ではない。関数は既定で先行読み込み。遅らせるなら defer_loading: true と tool_search。門そのものは変わらない。

門を通らない引数は実行しない

session が agent.session.requires_action で止まると、required_actions に function_call が出る。次の例は照会に見えるが、すでに越境している。番号は pattern に合わず、refund が増えている:

{
  "type": "function_call",
  "turn_id": "turn_2",
  "call_id": "call_3c91",
  "name": "lookup_order",
  "arguments": {
    "order_id": "1042",
    "include_lines": true,
    "refund": true
  }
}

同じ turn_id / call_id。通る形はこうなる。余分な鍵、欠けた required、漂った pattern。どれも実行してはならない:

{
  "type": "function_call",
  "turn_id": "turn_2",
  "call_id": "call_3c91",
  "name": "lookup_order",
  "arguments": {
    "order_id": "A-1042",
    "include_lines": true
  }
}

第二の門:宿主が同じ Schema をもう一度走る

公式 Schema は埋めの質を上げる。副作用は引き受けない。実行前に手元で検証する。失敗は見直せるオブジェクトにする:

{
  "check": "lookup_order",
  "schema": "parameters",
  "pass": ["order_id", "include_lines"],
  "fail": [
    { "path": "/order_id", "reason": "pattern" },
    { "path": "/refund", "reason": "additionalProperties" }
  ],
  "execute": false
}

失敗なら events 端点へ agent.session.input.tool_result を送り、success: false と読める error。成功なら output を文字列化する。新しい session で「再試行」しない。

{
  "type": "agent.session.input.tool_result",
  "turn_id": "turn_2",
  "call_id": "call_3c91",
  "success": false,
  "error": "order_id failed schema: expected ^[A-Z]-\\d{4}$"
}

最終カードは第三の門であり、Responses の text.format ではない

利用者に見せる注文カードは、ツール引数の Schema ではない。Agents session は Responses の text.format.json_schema を自動では掛けない。三つを分けて書く:

  • ツール引数:副作用の入口を鎖す。照会と書き込みはここ。
  • 最終カード:items からオブジェクトを抜き、別 Schema で検証してから見せる。
  • 最終形を Structured Outputs で鎖すなら:それは Responses の層。同じ session 資源に混ぜない。

ループを預けるかは Agents API vs Responses API。MCP の行は別のツール表。inputSchema も additionalProperties: false が要る。境界は MCP Tool Schema vs Function Calling。subagent は MCP Schema を継ぎ、function は継がない。

実行できる JSON への五手順

「JSON を出して」から始めない。門を歩く:

  1. まずツール Schema を書く。pattern、enum、required、additionalProperties: false を一度締める。
  2. 同じ Schema を宿主の検証器へ入れる。公式 parameters と別稿にしない。
  3. required_actions では検証してから実行する。通らねば success: false。
  4. 最終カードは別 Schema。items から抜いたあと検証する。散文をカードにしない。
  5. 台帳の欄は自分で持つ。compact は細部を落とす。金額と承認を会話にだけ置かない。

ワークフローを Schema に収める話は JSON Schema と Agent ワークフロー。本稿が求めるのは、Agents session の門がすべて対象であること。

安定した出力を見直すなら、二つの JSON を広げる

漂いの多くは、門が揃っていないことだ。モデルが愚かになったことではない。

  • parameters と arguments を 整形 し、余分な鍵と欠けを見る。
  • JSONPath 抽出 で order_id と $.parameters.required を抜く。
  • 門を通らなかった呼び出しと通った呼び出しを JSON Diff。pattern が漂ったら Schema を先に見る。
  • カードの Schema とツールの Schema は分けて審る。カードだけ鎖しても、入口は開いたまま。
  • 注文、session、社内 MCP を公開フォーマッタに貼らない。JSONSort はブラウザ内で動く。

二つの軌跡が Schema で再建できて初めて、JSON を集めている。そうでなければ散文を集めている。

よくある落とし穴

  • instructions に「JSON を出して」とだけ書く。それは門ではない。門は parameters と宿主の検証器。
  • required に一部の欄だけ列ぶ。載らない鍵は空のままになり、次の跳躍に穴が開く。
  • additionalProperties を書かない、または true にする。公式例は余分な鍵を閉じる。refund が一つ増えると副作用が傾く。
  • Responses の text.format を Agents session に写す。資源は二つ。最終カードは自分で検証する。
  • 検証に落ちても関数を走らせる。実行の前提は門を通ること。先に error を返す。
  • subagent に function を走らせる。下位エージェントは function ツールを持たない。厳しい Schema は主 Agent に残す。

FAQ

Agents API に Structured Outputs はあるか?

ツール引数は JSON Schema で締める。利用者に見せる最終オブジェクトに、session は Responses の text.format を自動では掛けない。最終形を鎖すなら自分で検証するか、その跳躍を Responses に置く。

公式 Schema があるのに、また検証するのか?

する。公式の門は埋めの質を上げる。副作用はあなたのプロセス。required_actions の arguments を同じ Schema に通し、失敗なら success: false。

pattern と enum は要るか?

要る。裸の string では 1042 が入り、A-1042 にならない。金額と状態は enum か明示形式。広い型は最も多い越境。

MCP ツールも同じ規律か?

同じ。inputSchema も余分な鍵を閉じ、required を列べきる。subagent は MCP を継ぎ、function は継がない。自社注文の門は主 Agent に残す。

検証失敗で session は固まるか?

同じ turn_id / call_id の対で tool_result を返せばよい。error を明確に書けば、モデルは引数を変えて再呼びできる。新しい session を再試行にしない。

結論

Agents API の安定した JSON は、より長い指示ではない。三つの門だ。ツール parameters、宿主の再検証、最終カードの別 Schema。実行は門のあと。

A-1042 がどの規則で落ちるかを先に書く。経路を指せれば、データは検証できる。モデルは変わる。門を先に安定させる。

続きを読む

更新記録: 初回公開