Claude API modelsのcapabilitiesを判定する方法
GET /v1/modelsのcapabilitiesオブジェクトから、effort・thinking・context_managementの対応状況をプログラムで判定する実装パターン。
capabilitiesオブジェクトで何が分かるか
Claude APIの GET /v1/models は、利用可能なモデルの一覧を返します。各モデルには capabilities オブジェクトが付き、effort=xhigh への対応、思考モード(thinking)で受け付ける type、使えるコンテキスト管理の戦略まで分かります。モデル一覧ページの比較表を目でコピーする代わりに、APIレスポンスから機能対応を判定する実装を組みます。
前提として必要なのはAPIキーだけです。エンドポイントはGETのみで、リクエストボディは不要です。SDKを使わず生のHTTPリクエストで完結するので、CI上の起動前チェックやシェルスクリプトからも呼び出せます。
モデルの世代交代のたびに困るのは、対応表のハードコードです。effortの対応レベルやthinkingのtype対応をコード側のif文に書いていると、モデルが増えるたびに書き換えとデプロイが要ります。capabilities を起動時に1回取得して判定に使えば、その更新作業をAPI呼び出し1本に置き換えられます。
ステップ1: モデル一覧を取得する
まず GET /v1/models を叩いて、利用できる全モデルの ModelInfo 配列を取得します。
curl https://api.anthropic.com/v1/models \
-H "anthropic-version: 2023-06-01" \
-H "x-api-key: $ANTHROPIC_API_KEY"レスポンスは新しく公開されたモデルほど先頭に並びます。ページネーションは after_id / before_id / limit のクエリパラメーターで行い、limit はデフォルト20、最大1000です。レスポンスには has_more と last_id も入るので、has_more が false になるまで after_id=<last_id> で続きを取れば、モデル数が増えても取りこぼしません。
複数のWorkspaceを操作できる認証情報を使う場合は、anthropic-workspace-id ヘッダーでWorkspaceを選びます。特定のWorkspaceに属する認証情報なら省略でき、送るなら一致している必要があります。
各モデルの capabilities フィールドには、次の項目が入ります。
| フィールド | 内容 |
|---|---|
batch | 内容Batch APIに対応するか |
citations | 内容引用生成に対応するか |
code_execution | 内容コード実行ツールに対応するか |
context_management | 内容コンテキスト管理の対応可否と、clear_thinking_20251015 / clear_tool_uses_20250919 / compact_20260112 各戦略の対応状況 |
effort | 内容low / medium / high / max / xhigh 各レベルの対応状況 |
image_input / pdf_input | 内容画像・PDF入力への対応 |
structured_outputs | 内容構造化出力(JSONモード・厳格なツールスキーマ)への対応 |
thinking | 内容thinking対応可否と、adaptive / enabled 各typeの対応状況 |
型定義では capabilities 自体が ModelCapabilities or null で、null のモデルがあり得ます。capabilities がオブジェクトのときは、既知の機能のキーが必ず揃っています。
ただし例外があります。effort.xhigh と、context_management の個別戦略3つは CapabilitySupport or null です。capabilities.effort.xhigh.supported のように無条件で降りるコードは、どこかが null のモデルに当たった時点で例外になります。
レスポンスの例は次の形です(claude-opus-5)。
{
"id": "claude-opus-5",
"capabilities": {
"batch": { "supported": true },
"citations": { "supported": true },
"code_execution": { "supported": true },
"context_management": {
"clear_thinking_20251015": { "supported": true },
"clear_tool_uses_20250919": { "supported": true },
"compact_20260112": { "supported": true },
"supported": true
},
"effort": {
"high": { "supported": true },
"low": { "supported": true },
"max": { "supported": true },
"medium": { "supported": true },
"supported": true,
"xhigh": { "supported": true }
},
"image_input": { "supported": true },
"pdf_input": { "supported": true },
"structured_outputs": { "supported": true },
"thinking": {
"supported": true,
"types": {
"adaptive": { "supported": true },
"enabled": { "supported": true }
}
}
},
"created_at": "2026-07-24T00:00:00Z",
"display_name": "Claude Opus 5",
"max_input_tokens": 0,
"max_tokens": 0,
"type": "model"
}リファレンスの例では、max_input_tokens と max_tokens が 0 のプレースホルダです。型は number or null なので、0 や null を上限値として扱わない分岐を入れておきます。
created_at はRFC 3339形式で、リリース日時が不明なモデルにはエポック値が入ることがあります。新しさで並べ替えるとエポック値が「最古」に落ちるので、順序はレスポンスの並び(新しいモデルが先頭)をそのまま使うのが手堅い選択です。
ステップ2: capabilitiesから対応表を作る
一覧取得したレスポンスから、effort=xhigh に対応するモデルIDだけを抽出する処理は次のようになります。?. と === true の組み合わせが、null のキーをすべて「非対応」として扱う書き方です。
const res = await fetch("https://api.anthropic.com/v1/models?limit=1000", {
headers: {
"anthropic-version": "2023-06-01",
"x-api-key": process.env.ANTHROPIC_API_KEY!,
},
});
const { data } = await res.json();
const xhighModels = data
.filter((m: any) => m.capabilities?.effort?.xhigh?.supported === true)
.map((m: any) => m.id);同じ形で thinking.types.adaptive.supported を見れば、アダプティブ思考(モデルが思考量を決め、effortで方向づける方式)に対応するモデルだけを絞り込めます。context_management.compact_20260112.supported を見れば、compaction戦略が使えるモデルの一覧になります。
複数のcapabilityを同時に満たすモデルを選ぶ処理も、フィルタを重ねるだけです。
const eligible = data.filter((m: any) =>
m.capabilities?.effort?.xhigh?.supported === true &&
m.capabilities?.code_execution?.supported === true &&
m.capabilities?.pdf_input?.supported === true
);この条件式を1箇所の関数にまとめ、モデル選定ロジックの入口にしておくと、条件の追加が1行で済みます。
ドキュメントの記述とレスポンスの例が合わないとき
公式ページ同士で、同じ事柄の書き方が揃っていない箇所があります。モデル一覧のリファレンスにある claude-opus-5 のレスポンス例では、thinking.types.enabled.supported が true です。一方、モデル概要ページには、手動の thinking.type: "enabled" と budget_tokens による拡張思考は「Claude Opus 4.6とSonnet 4.6で非推奨、以降のモデルでは受け付けない」と書かれています。
リファレンスの例は説明用のサンプルなので、どちらが実機の返り値と一致するかは、読む側では決められません。だからこそ、enabled を送る前にはサンプルや比較表でなく、自分のキーで取得した capabilities を見る意味があります。
もう1つは xhigh です。effortのページには、max に対応していても xhigh に対応しないモデルがある、と明記されています。max の対応リストにはOpus 4.6、Sonnet 4.6、Mythos Previewが入る一方、xhigh のリストにはこの3つが入っていません。effort.max.supported が true でも、xhigh の可否はその場で別に判定します。
既定値もモデルで揃っていません。effort を省略したときの既定は、Opus 5.5が medium、effortに対応するほかのモデルは high です。capabilities は「どのレベルを送れるか」を教えますが、省略時にどのレベルで動くかまでは返さないため、既定値はeffortのページの表で押さえます。
ステップ3: モデルIDとエイリアスを解決する
GET /v1/models/{model_id} は単体のモデル情報を返すエンドポイントで、モデルエイリアスをモデルIDに解決する用途にも使えます。パスパラメーターは「モデルIDまたはエイリアス」です。
curl https://api.anthropic.com/v1/models/claude-opus-5 \
-H "anthropic-version: 2023-06-01" \
-H "x-api-key: $ANTHROPIC_API_KEY"4.6世代以降は、claude-opus-5 のような日付なしIDがそのまま固定されたスナップショットで、エイリアスではありません。4.6より前の世代では、claude-sonnet-4-5 のような日付なしの名前が、その時点で最新の日付付きスナップショットを指すポインタです。
エイリアスでデプロイしている場合は、起動時に GET /v1/models/{model_id} を呼び、返ってきた id をログに残しておきます。どのスナップショットで動いていたかを後から追えます。
GET /v1/models と GET /v1/models/{model_id} は、id / capabilities / created_at / display_name / max_input_tokens / max_tokens / type を持つ同じ ModelInfo 型を返します。1モデルだけ知りたいときに、一覧全体を取ってクライアント側で絞る必要はありません。
ベータ側のモデル一覧で増える項目
両エンドポイントの anthropic-beta ヘッダーは、非推奨として扱われています。リファレンスには「このメソッドからいずれ削除する。ベータ機能を使うときはベータ版のモデルAPI(SDKでは client.beta.models)を呼ぶこと」と書かれています。ヘッダーの書式そのものはClaude APIでanthropic-betaヘッダーを使う方法にまとめています。
ベータ側のレスポンス型には、通常版にない項目が2つあります。
allowed_fallback_models: そのモデルをプライマリにしたとき、Messages APIのfallbacks[i].modelに指定できるモデルIDの配列です。空配列は、そのモデルをプライマリとするfallbacksに対応しないことを表しますcapabilities.compaction: サーバー側compaction(トップレベルのcompactionパラメーター)への対応と、受け付けるcompaction.typeです。現状の型にはsummarizeがあります
通常版の capabilities.context_management.compact_20260112 と、ベータ側の capabilities.compaction は別の項目です。どちらを見るかは、使うcompactionのAPIで決まります。フォールバックの組み方はサーバー側フォールバックの実装、compactionの閾値はcompactionのトークン閾値の決め方で扱っています。
フォールバック先の候補をコードで選ぶなら、次の形です。
const canBePrimary = data.filter(
(m: any) => (m.allowed_fallback_models ?? []).length > 0
);よくあるつまずき
capabilities はネストしたオブジェクトで、フラットな真偽値ではありません。effort は supported(effort自体への対応)と、low / medium / high / max / xhigh それぞれの CapabilitySupport を持ちます。capabilities.effort.supported だけ見て、実際には xhigh だけ非対応のモデルを見落とす例が典型です。特定のレベルを送る前に、そのレベルのキーまで降りて確認します。
context_management の個別戦略キーは null になり得ます。clear_thinking_20251015 や compact_20260112 は CapabilitySupport or null です。context_management.supported が true でも、全戦略が使えるとは限りません。
Batch APIに投げる前に batch を見ていない構成も、つまずきの元です。Batch APIにモデルを渡す構成では、capabilities.batch.supported が使えます。Claude Batch APIの使い方のように非同期で処理する構成は、キューに入ってから失敗に気づくより、投入前に弾く方が手戻りが小さくなります。
会話の途中でeffortを切り替える構成では、切り替え先のモデルを見ていないことがつまずきになります。mid-conversation effortの切り替えでオーケストレーションモードを作るのような実装では、切り替え先のモデルが対象レベルに対応しているかを、切り替えロジックの中で参照します。モデルを固定している間は表に出ず、モデルの切り替えを組み込んだときに初めて表面化します。
対応しているのに400になる組み合わせがあります。capabilities が教えるのは各機能の対応可否で、組み合わせの制約までは表しません。effortのページには、Opus 5で xhigh か max のときに thinking: {"type": "disabled"} を送ると400になる、という記述があります。Sonnet 5.5で thinking: {"type": "between_tools"} を xhigh か max と併用した場合も、同じく400です。
静的な比較表とAPIレスポンスの使い分け
どちらを見るか
比較表(公式ページ)
Fable 5.1 / Opus 5.5 / Sonnet 5.5 / Haiku 4.5を横並びにして、価格・コンテキストウィンドウ・退役時期まで一目で比べられます。どのモデルを使うかを決める場面向きです。
capabilities(API)
リクエストを送る直前に、対象モデルが effort.xhigh や thinking.types.adaptive を受け付けるかを返します。判定をif文に埋め込まずに済みます。
モデル概要ページの比較表では、Haiku 4.5のコンテキストウィンドウは200K tokens、最大出力は64K tokensです。ほかの3モデルは1M tokensと128K tokensなので、max_input_tokens と max_tokens の値でモデルを使い分けるコードは、この差を前提にできます。
GET /v1/models の結果を起動時に1回キャッシュする方法は、複数のモデルを切り替えて使うアプリケーションほど効果が大きくなります。単一モデル固定の小さな実装では、起動時チェックのコストが見合わないこともあります。
起動時チェックと再取得の組み込み方
起動時チェックの流れ
- 1
起動処理の先頭で一覧を取得する
limit=1000でGET /v1/modelsを呼び、has_moreがfalseであることを確かめて、結果をプロセス内メモリに置きます。 - 2
リクエスト前に対応可否で弾く
送ろうとしているeffortレベルやthinkingのtypeが、キャッシュしたモデルのcapabilitiesに入っているかを見ます。入っていなければ、APIを呼ばずにエラーを返すか、別モデルへ切り替えます。
- 3
CIのデプロイ前に同じ問い合わせをする
本番で使う全モデルが
effort.highに対応しているか、といった想定をアサーションに書きます。コード側でモデルIDを固定しているチームでは、モデルが一覧から消えていないかの検知も兼ねます。
キャッシュの有効期限は、プロセスを再起動しない長時間稼働のサーバーで設計しておく価値があります。新モデルの追加は、再起動なしには反映されないためです。再取得のポーリングを組み込めば、新モデルを見逃し続けることを避けられます。1時間から1日程度という間隔は目安で、新モデルをどれだけ早く拾いたいかで決めます。
キャッシュを持たず、リクエストごとに GET /v1/models/{model_id} を呼ぶ構成も選べます。レイテンシは1リクエスト分増えますが、実装が単純で、常に最新の状態を参照できます。リクエスト数の少ない管理系のバッチ処理やCLIツールでは、こちらのほうがコードの見通しがよくなります。
まとめ
つまずきの多くは、モデルを1つに固定している間は表に出ず、切り替えを組み込んだときに現れます。モデルが固定なら、CIのアサーションだけで足ります。複数のモデルを切り替える構成になった段階で、起動時キャッシュまで入れるかを考えます。