ライブ機能カタログでドキュメントのずれを減らすには:宣言、ランタイム、納品時の確認を分ける
プラットフォーム識別子、パラメータの宣言、MCPのディスカバリーで実際に起きた不一致を出発点に、カタログのスナップショット、パラメータの差分、サンプルのチェックを設計します。キャッシュ、欠落したフィールド、リリースゲートの扱いを明確にし、カタログが一致していることをサービス全体の可用性と取り違えないようにします。
APIドキュメントを書くとき、最も危険な誤りは一見まったく妥当に見えることがよくあります。レビューのプラットフォームをgoogle_maps_reviewsではなくgoogle_mapsと名付けたほうが覚えやすく感じるかもしれません。すべてのレビュー用エンドポイントにsinceパラメータを追加するのは、増分取り込みの直感に合っています。しかし、もっともらしいことと実際にサポートされていることは別です。こうした例をコピーした読者は、最初のステップでつまずきます。
今回EveryInfraでコンテンツをレビューする際、記事中で言及した機能を公開カタログと照合し、あわせて読み取り専用の実装チェックを行いました。この作業で改めてわかったのは、ライブカタログは役立つものの、正しさを万能に証明するものではないということです。ドキュメントの保守では、1つの緑色のステータスに頼るのではなく、サービスが何を宣言しているか、リクエストで何が起きたか、業務側が何を受け取ったかに答える必要があります。
3つの具体的な不一致から見るカタログの価値
1つ目はプラットフォームの識別子です。2026-09-04 20:46(北京時間)に公開カタログでgoogle_mapsを照会したところ、HTTP 400 unknown_capabilityが返され、google_maps_reviewsを提案するヒントが示されました。カタログは誤った名前を特定できますが、対象が本当に場所のレビューであるかは編集者が確認する必要があります。似た候補を自動的に採用することはできません。
2つ目はAmazonレビューのパラメータです。同日の公開エントリーにはurlとdomainしか記載されておらず、default_limitとmax_limitの具体的な値はありませんでした。ローカル実装のパラメータ注記はより詳細ですが、デプロイ済みの機能として引用することはできません。本文では厳密に検証可能な範囲のみを使用する必要があります。上限が宣言されていない場合は、無制限ではなく不明として記録するしかありません。
3つ目はMCPのディスカバリーです。20:43のプローブでは6つのツールを読み取りましたが、初期化完了通知に想定外のレスポンスボディが含まれていました。ツール名と数が一致していても、プロトコルに完全に準拠していることの証明にはならず、ましてやすべてのクライアントが認証と実際の呼び出しを完了したことの証明にもなりません。この不一致は、正常なカタログステータスの陰に隠したままにせず、独立した受け入れ項目として扱う必要があります。
2026-09-08に同じ経路で再検証した際は、この履歴を残したうえで、公開カタログのツールが8つに増え、初期化完了通知に対して、0バイトのレスポンスボディでHTTP 202が返されることを確認しました。以前の不一致は再発しませんでしたが、業務用のツールは実行しておらず、ホスト認証、実際の結果、長期的な互換性はまだ検証済みとしていません。
これら3つのケースは、識別子、宣言の範囲、プロトコルの挙動に関わるものです。いずれも連携に影響しますが、必要な対応は異なり、それぞれ誤った名前の修正、ドキュメントで約束する範囲の縮小、プロトコル再検証の基準の維持が求められます。すべての不一致を一律にドキュメントの陳腐化として扱うと、責任の所在や検証方法に関する情報が失われます。
構造・ランタイム・提供の3層への分割
- 構造上の根拠:現在のカタログには、リクエストの組み立てや解析方針の設計に使うアクション、必須パラメータ、許容値、返却フィールドが定義されています。
- 実行時の根拠:特定のGETリクエスト、HTTPリクエスト、またはプロトコル探索が正常に完了し、その入力、レスポンスの型、ステータス、観測時刻が記録されています。
- 提供の根拠:承認された業務目標に対してドキュメント記載の形式でコンテンツが得られ、空の結果、部分的な完了、失敗、課金を検証します。別途、業務上の受け入れ確認が必要です。
カタログにowner_responseがあっても、すべてのレビューに店舗からの返信があるとは限りません。200を受け取っても、すべてのページネーションが完了したとは限りません。業務サンプルが1件成功しても、カタログのすべての項目が動作するとは限りません。記事では、弱い確認で強い約束を裏付けることがないよう、各主張のそばに対応する根拠のレベルを示す必要があります。
説明の重複を避けた単一の機械可読API定義の再利用
同じ機能が、HTTPドキュメント、機能カタログ、フィールドの説明、MCPスキーマ、記事の例に登場することがあります。保守の際は、識別子、入力、フィールド定義を再利用可能な1つのAPI定義から取り出し、出力ごとに役割を分けられます。カタログは目的の機能を見つけるため、フィールドページは意味を説明するため、例は読者のタスクを示すため、テストは実行時の動作を確認するためのものです。
EveryInfraの現在のコードでは、機能リファレンスの生成とパラメータ検証がこの再利用に対応しています。ただし、共通の関数があるからといって、公開中のすべてのページやデプロイ済みのインスタンスが同期されているとは限りません。人が書いた文章は、同じカタログを参照するだけで、正しいユースケース、認可の範囲、失敗の説明を自動的に備えるわけではありません。
OpenAPIはHTTPインターフェースとその構造を記述するもので、この保守方法の一部を担います。アクションの意味、欠落するフィールド、サンプルの範囲、利用制限は、実際の業務の文脈で引き続き明示的に記述する必要があります。自動生成によってフィールドのコピー&ペーストによる誤りは減りますが、ある記述が機能を実際より広く見せていないかという編集上の判断は、人が行う必要があります。
構造の比較では、properties、必須フィールド、null値も区別する必要があります。JSON Schemaの公式ガイドには、propertiesに列挙したフィールドはデフォルトでは必須ではないと明記されています。フィールド名の集合だけを比較すると、任意フィールドが必須に変わるような連携上の変更を見逃すおそれがあります。逆に、フィールドの欠落を許容していても、明示的なnull値が許可されるとは限りません。
各チュートリアルに必要なリファレンスのみの照会
連携時は、まずプラットフォームと対象オブジェクトを特定し、次にアクションまで絞り込みます。以下の手順では、レビューの取得やAPIキーの使用は行わず、公開カタログを読み取ります。jqは選択したプロパティが返されていない場合にnullと表示するため、元のレスポンスにフィールドが存在しない場合と、レスポンスに明示的にnull値が含まれる場合を区別する必要があります。どちらも勝手に0と解釈してはいけません。
curl -fsS --max-time 30 \
'https://api.everyinfra.com/api/v1/social/catalog?platform=amazon' \
| jq -e '.capabilities[] | select(.action == "reviews") | {
platform, action, required_params, optional_params, param_meanings,
mode, returns_list, default_limit, max_limit, response_fields
}'これらの観測結果には、取得元URL、取得時刻、実際のレスポンスの要約を添えてください。リクエストや解析が失敗した場合は、古いスナップショットを空のカタログで上書きしないでください。以前の内容と失敗の状態を残しておけば、保守担当者は、サービスがすべての機能を削除したと誤解せず、新しい宣言を取得できなかったことを把握できます。
アプリケーション側でも、どのパラメータと返却フィールドを使用しているかを登録しておく必要があります。無関係なアクションにフィールドが追加されても、現在の作業を止める必要があるとは限りません。一方、使用中の必須パラメータや出力の形が変わった場合は、担当者を決めて対応する必要があります。差分検出は、項目数の増減を報告するだけでなく、実際の利用側を対象に行う必要があります。
JSONの生テキストではなく意味上の差分を対象とする比較
オブジェクトのキーの順序、リストの表示順、説明文の調整によって、呼び出し方法は変わらないのにファイルが大きく変更されたように見えることがあります。逆に、returns_listをtrueからfalseに変えるという1つの値の変更だけで、パーサーが壊れることもあります。まず確認するフィールドを選び、それに沿って差分を分類してください。
function contractDiff(before, after) {
if (before.platform !== after.platform || before.action !== after.action) {
throw new Error("compare the same capability");
}
const normalize = row => {
const names = key => {
const values = row[key];
if (!Array.isArray(values)
|| values.some(v => typeof v !== "string" || !v.trim())
|| new Set(values).size !== values.length) {
throw new Error("explicit unique field list required");
}
return [...values].sort();
};
if (typeof row.mode !== "string" || !row.mode
|| typeof row.returns_list !== "boolean") {
throw new Error("explicit mode and result shape required");
}
return {
required_params: names("required_params"),
response_fields: names("response_fields"),
mode: row.mode, returns_list: row.returns_list
};
};
const left = normalize(before), right = normalize(after);
return Object.keys(left).filter(key =>
JSON.stringify(left[key]) !== JSON.stringify(right[key]));
}
const baseline = {
platform: "synthetic", action: "comments",
required_params: ["url"], response_fields: ["id", "text"],
mode: "sync", returns_list: true
};
console.log(contractDiff(baseline, {
...baseline, response_fields: ["text", "id"]
}));
console.log(contractDiff(baseline, {
...baseline, required_params: ["url", "region"]
}));2つの合成結果は、それぞれ差分なしとrequired_paramsの変更に対応します。この仕組みは明示的な4つの構造だけを比較するもので、完全な互換性チェックは実装していません。任意パラメータ、列挙値、フィールドの型、数量の上限、可用性、課金に関する宣言は、引き続き個別に確認する必要があります。構造が欠落している場合は、暗黙に空のリストとして扱わず、エラーにします。
必須入力の追加、使用中フィールドの削除、列挙値や数量範囲の縮小、実行モードの変更は、慎重な確認が必要です。返却フィールドが追加されただけでも、下流のコンポーネントが未知のフィールドを予期せず拒否しないか確認する必要があります。検出ツールは変更を指摘するだけで、互換性の結論を自動的に出すことはありません。影響は保守担当者が実際の利用側に照らして確認します。
恒久的な保証ではなく観測結果を保存するキャッシュ
キャッシュキーは、少なくともサービスのエンドポイント、プラットフォーム、アクションを区別し、取得時刻とプロトコルまたはAPIのバージョンを記録する必要があります。複数の環境でキャッシュキーを共有すると、テスト用の宣言が本番環境に漏れるおそれがあります。可用性、パラメータ、記事の出典では確認の頻度も異なる場合があり、1つの期間ですべてのリスクをカバーすることはできません。
たとえば、編集者が1日後に確認を予定するのはチームのワークフローの都合であり、カタログが変わらないことをサーバー側が保証しているわけではありません。未知のパラメータであることが明示された場合や、返却形式の変化、デプロイの更新に遭遇した場合は、決まった時刻を待たずに対象を絞って更新してください。期限切れの内容は引き続き閲覧できますが、影響の大きい操作では、確認されていない古い宣言に頼り続けてはいけません。
古いスナップショットには、それぞれの取得時刻を残しておく必要があります。新しいリクエストが失敗したときに古い日付を今日に書き換えると、検証済みであるかのような錯覚を生みます。過去の観測結果を最新の確認状態と併せて保存しておけば、あるチュートリアルがどのサービス状態に基づいていたかを正確に説明できます。
サービスが対応するレスポンスヘッダーを提供している場合、RFC 9111の条件付きリクエストと再検証の仕組みで、キャッシュを再利用できるかを判断できます。本記事では、カタログがETagや304に対応しているかは検証していません。サービスが明示的に対応していない限り、ローカルの要約をサーバーのバリデーターとして扱うことはできず、確認サイクルをサーバー側のキャッシュ保証とみなすこともできません。
記事中の例をクライアントとして扱う
サンプルの確認では、見た目が同じテストリクエストを別途作成するのではなく、実際の記事からコードを直接抽出してください。無料のカタログコマンドはそのまま検証できます。承認済みサンプルがない業務用POSTリクエストは、まず構文、リクエストの組み立て、オフラインでのレスポンス分岐を確認し、サービスの結果は未検証であると明記してください。テスト用コピーは正しくても、読者が記事からコピーするコードでは制限が誤った階層に置かれる、といった事態を防いでください。
リンクもその目的に照らして確認する必要があります。サイト内の機能ページは連携作業を進めるのに役立ち、公式ドキュメントは対応する製品やプロトコルの本来の定義を裏付けます。あるプラットフォームの公式リンクを掲載しても、そのプラットフォームがEveryInfraのあらゆる用途を承認していることにはなりません。未公開の記事には、404になるおそれのある詳細ページへのリンクを先行して掲載しないでください。
ドリフトを検出した後の対応順序
- 読み取り失敗:障害の状態を残し、新しいパラメータ定義として上書きしないでください。必要に応じて、その宣言に依存する操作を一時停止します。
- パラメータまたはフィールドの変更:影響を受けるパラメータ、フィールド、利用側を列挙し、例を更新するか、コードを修正するか、ブロックを維持するかを決めます。
- ローカルと公開環境の状態の差:別々に記録します。ローカルで修正しても、デプロイが完了したことにはなりません。
- 公開されている宣言と実際の提供内容の食い違い:承認済みの最小限のサンプルを保持し、サービスの保守担当者にエスカレーションしたうえで、関連する記事の記載範囲を狭めます。
- 完全に一致:確認した範囲内で差分が見つからなかったことだけを報告します。記事を自動的に公開したり、すべての連携が成功したと宣言したりはしません。
まずは最も利用頻度の高い業務アクションから始め、カタログの観測、例の確認、提供内容の受け入れ確認について、相互に関連付けた記録を作成します。これにより、ドキュメントの更新は古いスクリーンショットを新しいものに差し替える作業ではなく、どの事実が変わり、誰に影響し、どの根拠で引き続き使用できるかを説明する作業になります。
参考資料 LF-13