はじめに
ここ2週間くらい、OpenAI 互換の AI API ルーターまわりで、key、base URL、model 名、streaming、quota、integration などを細かく見直していました。
最初は「base URL を差し替えれば終わりでは」と思っていたのですが、実際に触ると、それだけでは運用レビューとしてかなり薄いです。SDK は動くけれど model catalog と pricing がずれている、stream=True だけ timeout が足りない、Dify や n8n では UI 上の入力欄名と実際の request が微妙に違う、みたいな小さい段差が残ります。
この記事では、私が AI API ルーターをチームに入れる前に見るようになったチェックリストをまとめます。Flatkey AI を題材にしていますが、ほかの OpenAI 互換 gateway や自前 proxy でもそこそこ使える観点だと思います。
3行まとめ
- AI API ルーターは「1つの key と base URL」だけでなく、model catalog、usage、quota、routing、ログ設計まで見てから使う。
- retry や fallback は便利ですが、quota 超過、model 名ミス、endpoint family の混在まで retry で吸収しようとすると事故りやすい。
- 導入レビューでは、curl での疎通、SDK 設定、利用可能 model、streaming、連携ツール、監査用ログを同じ表にしておくと後で楽です。
前提
この記事でいう AI API ルーターは、アプリ側からは OpenAI 互換の API として呼び出し、裏側では Claude、GPT、Gemini、DeepSeek など複数 provider や model へ振り分ける層を指しています。
Flatkey AI の公開資料では、https://router.flatkey.ai/v1 を OpenAI 互換 base URL として使い、1つの API key、model access、usage と billing、keys と routing の dashboard、quota limits をまとめて扱う形になっています。この記事ではそこを前提にします。
私の観点は backend owner 寄りです。新しい model を最速で試すというより、チームのアプリに入れた後に「誰が、どの key で、どの model を、いくら使って、落ちたときにどこを見るのか」を潰すためのメモです。
チェックリスト 1. key と base URL を分けて管理する
最初に見るのは key と base URL です。ここを雑にすると、後ろの調査が全部怪しくなります。
私は最低限、この3つを分けます。
- provider 直 API の key
- router の key
- local、staging、production の base URL
たとえば env はこのくらい素朴でよいと思います。
OPENAI_BASE_URL=https://router.flatkey.ai/v1
FLATKEY_API_KEY=sk-fk-redacted
AI_MODEL=your-model
Python SDK 側では、base URL を明示しておくとレビューしやすいです。
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["FLATKEY_API_KEY"],
base_url=os.environ["OPENAI_BASE_URL"],
)
response = client.chat.completions.create(
model=os.environ["AI_MODEL"],
messages=[{"role": "user", "content": "ping"}],
)
print(response.choices[0].message.content)
ここで大事なのは「OpenAI SDK を使っているから OpenAI にだけ行く」と思い込まないことです。OpenAI 互換 API では、SDK の client 設定、base URL、model 名、認証 header の組み合わせで行き先が決まります。私は一度ここを雑に読んで、model 名の問題なのか、key の問題なのか、endpoint の問題なのかを切り分けにくくしました。
チェックリスト 2. model catalog を信用しすぎない
次に model catalog です。
ルーターを使うと「使える model が増える」ことに目が行きます。ただ、運用では「今この key で見えている model」と「pricing 画面に載っている model」と「コードに書いた model」が一致しているかを見る方が大事でした。
私はまず /models を叩きます。
curl -sS "$OPENAI_BASE_URL/models" \
-H "Authorization: Bearer $FLATKEY_API_KEY" \
| jq -r '.data[]?.id' \
| sort
この結果を、そのまま allowlist に近い扱いで見ます。特に本番では「たぶんあるはず」の model 名をコードに直接書かない方がよさそうです。
見る項目はこのあたりです。
- app が指定する model 名は
/modelsに出ているか - pricing catalog に載っている単価と、実際に使う group や route が合っているか
- text、image、embedding など endpoint family ごとの model を混ぜていないか
- fallback 先の model も同じ品質要件を満たすか
- deprecated や実験用 model を production default にしていないか
私は以前、model 比較表を作ったときに、性能や好みだけでなく「この model 名をチームが毎週確認できるか」を見た方がよいと感じました。比較は一回やって終わりではなく、catalog の変化に追従する仕組みも含めて運用だと思います。
チェックリスト 3. endpoint family を混ぜない
OpenAI 互換 API といっても、/v1/chat/completions、/v1/responses、/v1/embeddings、画像生成系の endpoint では request shape が違います。
私がレビューで見るのは、model 名より先に endpoint family です。
| 見るもの | 確認すること |
|---|---|
| Chat Completions |
messages 配列を送っているか |
| Responses |
input、tool、stateful な扱いを混ぜていないか |
| Embeddings | chat 用 model を指定していないか |
| Images | pricing と status を別に見ているか |
| Streaming | SSE と通常 response を同じ parser で読んでいないか |
特に Responses API と Chat Completions を同じ wrapper に押し込むと、後からつらくなります。どちらが新しいかではなく、今の app の責務に合っているか、ルーター側でその endpoint がどう扱われるかを分けて見る方が安全でした。
チェックリスト 4. usage、quota、billing を同じ画面で見る
API ルーターを入れる理由の一つは、usage と billing をまとめて見たいからです。ただ、dashboard があるだけでは足りません。
私は次を確認します。
- request ごとに input、output、total token が取れるか
- model ごとの cost が後で追えるか
- team、project、key 単位の quota を分けられるか
- quota 超過と rate limit を別の扱いにできるか
- recharge や invoice を見る人と、実装する人の責任境界が決まっているか
ここを決めないまま導入すると、障害時に「誰が見ればよいのか」が曖昧になります。開発者は request log を見て、finance は billing を見て、support は user impact を見る、という分断が起きやすいです。
小さく始めるなら、私は key の命名だけでも決めます。
keys:
production_backend:
owner: platform
quota: monthly_budget
allowed_models:
- your-default-model
- your-fallback-model
staging_sandbox:
owner: backend
quota: small_daily_limit
allowed_models:
- cheap-test-model
この程度でも、あとで「あの key は誰が使っているのか」を聞かれたときの説明がかなり楽になります。
チェックリスト 5. streaming と timeout を先に決める
streaming は体感速度に効きますが、運用では timeout と parser の方が先に問題になります。
私は次を分けて見ます。
- connect timeout
- read timeout
- total timeout
- upstream timeout
- client 側の abort
- SSE chunk の parse error
- 最後の usage が取れないケース
stream=True で途中まで返っていると、UI 的には「動いていそう」に見えます。ただ、最後まで完了したのか、途中で切れたのか、usage を取れたのかは別です。
ここを曖昧にしたまま fallback を入れると、同じ user request に対して二重に model call する危険があります。私は streaming はまず 1 model で timeout と retry を固定し、それから fallback を考える順番がよいと思いました。
チェックリスト 6. fallback は成功率だけで決めない
fallback は便利ですが、雑に入れるとコストと品質の説明が難しくなります。
見る項目は成功率だけでは足りません。
| 項目 | 見る理由 |
|---|---|
| latency | user 体験に直結する |
| cost | fallback 先が高いと障害時に費用が跳ねる |
| output quality | model が変わると回答の癖が変わる |
| context length | 長い入力でだけ落ちることがある |
| tool support | function calling や structured output の差が出る |
| safety policy | provider 差で refusal や filtering が変わる |
| observability | どの route に行ったか後で追えるか |
私は「primary が失敗したら secondary に投げる」だけだと怖いです。せめて、どの error code なら fallback するのか、どの error code は設定ミスとして止めるのかを決めたいです。
たとえば model_not_found や quota exceeded は、retry や fallback の前に設定を見直すべきことが多いと思います。逆に一時的な upstream timeout なら、短い backoff と上限付き retry の方が自然です。
チェックリスト 7. integration は UI 名ではなく request で見る
Dify、n8n、Cherry Studio、CC Switch、NewAPI などの連携は、UI で入力欄が用意されていると安心しがちです。
ただ、最終的には request を見ます。
- base URL が
/v1まで含まれているか - model name が UI の provider name と混ざっていないか
- Authorization header が期待通りか
- streaming の on/off が UI と request で一致しているか
- retry や timeout の default が強すぎないか
- error body を UI が潰していないか
特に no-code や automation tool では、画面上は「OpenAI」と書いてあっても、実際には OpenAI 互換 API として別の base URL に向けるだけ、という構成があります。ここを理解しておくと、Dify や n8n での model 名ミスをかなり早く見つけられます。
チェックリスト 8. ログに残すものと残さないものを決める
最後にログです。これは後回しにするとだいたい困ります。
私は残すものをこのくらいにしています。
- timestamp
- app request ID
- router request ID
- endpoint
- model
- route または provider group
- status code
- error code
- latency
- input token、output token、total token
- cost estimate
- retry count
- fallback used
逆に、prompt、user input、response body は何も考えずに残さない方がよいと思います。debug したい気持ちはありますが、個人情報、社内情報、customer data が混ざりやすいです。
どうしても必要なら、短期 retention、masking、sampling、review 権限を先に決めます。ここは技術だけでなく、security と support の合意も必要でした。
そのまま貼れるレビュー表
自分のチームで使うなら、私はこの表を issue に貼ります。
| 項目 | 未確認なら見るもの | OK の目安 |
|---|---|---|
| key | env、dashboard、owner | production と staging が分離されている |
| base URL | SDK config、curl |
https://router.flatkey.ai/v1 のように明示されている |
| model catalog |
/models、pricing |
app の default と fallback が存在する |
| endpoint | request path、SDK method | Chat、Responses、Embeddings、Images が混ざっていない |
| usage | response usage、dashboard | token と cost を後で追える |
| quota | key/project/team limit | quota 超過時の担当者が決まっている |
| streaming | SSE parser、timeout | 途中切断と完了を区別できる |
| retry | error code、backoff | retry する error としない error が分かれている |
| fallback | route、cost、quality | fallback 先の品質と費用を説明できる |
| integration | Dify、n8n、CC Switch など | UI ではなく実 request で確認している |
| log | request ID、model、usage | prompt/body を無条件保存していない |
| support | request ID、再現 curl | サポートに渡す最小情報が揃う |
この表を全部埋めるのは少し面倒です。ただ、面倒な部分はだいたい本番後に聞かれる部分でもあります。先に潰しておく方が、障害時の説明がかなり短くなります。
公開済みの関連記事
今回のチェックリストを書く前に、公開済みの検証記事はこのあたりです。未公開またはレビュー中の下書きは、この記事では公開リンクとして扱っていません。
| 観点 | 記事 |
|---|---|
| base URL | CC Switch / NewAPI の設定を OpenAI 互換 base URL に寄せてみた |
| model 比較 | Claude・GPT・Gemini を同じ評価表で比べるためのスクリプト |
| streaming | stream=True の応答が途中で切れるときに SSE とタイムアウトを疑う |
| key と quota | API キーを直書きしそうになったので、env と quota で守る形にした |
| curl 疎通 | curl だけで OpenAI 互換ルーターの疎通確認をする |
| model catalog | /v1/models と pricing catalog を突き合わせて、使えるモデル名だけ残す |
| timeout/retry | OpenAI SDK の timeout/retry を API ルーター前提で見直す |
| Dify | Dify の OpenAI 互換モデル設定で base URL と model name を分けて持つ |
| n8n | n8n の HTTP Request から OpenAI 互換 chat/completions を叩いてみた |
| endpoint family | Responses API と Chat Completions の endpoint を混ぜないためのメモ |
まとめ
AI API ルーターは、使い始めだけなら key と base URL の差し替えで進むことが多いです。ただ、チーム運用に入れるなら、見るべきものはもう少し広いです。
私なら、導入前レビューでは次の順番で見ます。
- key と base URL
- model catalog と pricing
- endpoint family
- usage、quota、billing
- streaming、timeout、retry
- fallback と routing
- Dify、n8n、NewAPI などの integration
- request ID、model、usage を中心にした logging
ここまで見ておくと、障害時に「provider が悪いのか、ルーターが悪いのか、自分の設定が悪いのか」を少し落ち着いて切り分けられます。私はまだ何度も表を見返しているので、完璧な運用というより、迷ったときの地図として持っておくのがよさそうです。
おわりに
API ルーターは便利ですが、便利な層が1つ増えるぶん、責任境界も1つ増えます。導入時にこのチェックリストを貼って、未確認項目を1つずつ潰すだけでも、後からかなり助かると思います。
間違いあったらコメントください。よろしくお願いします。