OpenCode に、カスタムの OpenAI 互換プロバイダーを追加する。
Updated 2026-07-29
OpenCode はカスタムプロバイダーを opencode.json からそのまま読み込みます。@ai-sdk/openai-compatible パッケージで provider ブロックを宣言し、options.baseURL を https://api.apisrouter.com/v1 に向ければ、記載したすべてのモデルが /models ピッカーの中でキー1つを通じて選べるようになります。
早わかり: opencode.json に provider ブロックを1つ。
OpenCode はカスタムの OpenAI 互換プロバイダーにネイティブ対応しています。opencode.json に npm を "@ai-sdk/openai-compatible" とした provider エントリを追加し、options.baseURL を https://api.apisrouter.com/v1 に設定し、キーは {env:...} テンプレートで環境変数から読み込み、models の下に使いたいモデル id を並べます。そのうえでトップレベルの model フィールドを "apisrouter/<model-id>" にすれば、OpenCode はエージェントループ全体をゲートウェイ経由でルーティングします。 これは OpenCode のドキュメントに記載されているカスタムプロバイダーの正規の経路であり、ラッパーでもフォークでもありません。設定ファイルはプロジェクトルート(opencode.json)か、あるいはグローバルな ~/.config/opencode/opencode.json に置け、両者はマージされるため、provider ブロックは1回宣言してすべてのリポジトリで使い回せます。
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"apisrouter": {
"npm": "@ai-sdk/openai-compatible",
"name": "APIsRouter",
"options": {
"baseURL": "https://api.apisrouter.com/v1",
"apiKey": "{env:APISROUTER_API_KEY}"
},
"models": {
"claude-sonnet-4-6": { "name": "Claude Sonnet 4.6" }
}
}
},
"model": "apisrouter/claude-sonnet-4-6"
}OpenCode がプロバイダーとモデルをどう解決するか。
OpenCode(GitHub 上では anomalyco、スター数はおよそ186K でターミナル型コーディングエージェントの中でも屈指の人気)は、Vercel AI SDK の上にプロバイダー層を構築しています。provider ブロックの npm フィールドは、OpenCode がそのプロバイダーと話すために読み込む SDK パッケージを指定します。"@ai-sdk/openai-compatible" は標準の /v1/chat/completions プロトコルを話し、一方 "@ai-sdk/openai" は OpenAI の /v1/responses プロトコルを話します。マルチベンダーのゲートウェイはチャット補完を提供するので、正しいのは openai-compatible の方です。"@ai-sdk/openai" をチャット補完エンドポイントに対して選んでしまうのが、このセットアップが壊れる最もよくある原因です。 モデルは provider/model のペアとしてアドレスされます。プロバイダー id は provider ブロックで選んだキー(上の例では "apisrouter")、モデル id は models マップの中のキーで、既定のモデルは "apisrouter/claude-sonnet-4-6" になります。宣言したものはすべて TUI 内の /models ピッカーに現れ、セッションの途中でも切り替えられます。 身につけておく価値のある挙動が一つあります。カスタムプロバイダーにとって models マップはアローリストです。組み込みのプロバイダーは既知のカタログを最初から備えていますが、OpenCode はカスタムエンドポイントのモデルを自力で列挙できないため、明示的に宣言した id だけがアドレス可能になります。baseURL の背後にあるエンドポイントが Claude・GPT・DeepSeek・Kimi の id を横並びで提供している場合、モデルごとに1エントリ宣言しておけば、ピッカーはベンダーをまたいだ切り替え盤になります。
フルセットアップ: グローバル設定・プロジェクト設定・モデルごとの上限。
きれいな構成は、~/.config/opencode/opencode.json のグローバル設定にプロバイダーを1回だけ宣言し、各プロジェクトの opencode.json にはプロジェクトごとの選択(どのモデルか、どのエージェントか)だけを残すことです。OpenCode は設定ファイルを置き換えるのではなくマージするため、プロジェクトファイルは小さく保たれ、provider ブロックが重複することもありません。 {env:APISROUTER_API_KEY} テンプレートは読み込み時に環境変数から解決されるため、リテラルなキーがコミットされ得るファイルに残ることはありません。シェルのプロファイルから export しておけば、OpenCode を起動するすべてのターミナルセッションから見えるようになります。 各モデルエントリには、コンテキストと出力トークンの上限を示す limit オブジェクトも設定できます。これを宣言しておくことは見た目以上に重要です。OpenCode はコンテキストの数値を使ってセッションがいつ要約を必要とするか判断するため、上限を宣言せずに長文脈モデルを登録すると、本来より控えめに扱われてしまいます。limit.context をそのモデルが実際にサポートする値に設定しておけば、長いセッションはより本来のタイミングで圧縮されます。
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"apisrouter": {
"npm": "@ai-sdk/openai-compatible",
"name": "APIsRouter",
"options": {
"baseURL": "https://api.apisrouter.com/v1",
"apiKey": "{env:APISROUTER_API_KEY}"
},
"models": {
"claude-opus-4-7": { "name": "Claude Opus 4.7", "limit": { "context": 200000, "output": 32000 } },
"claude-sonnet-4-6": { "name": "Claude Sonnet 4.6", "limit": { "context": 200000, "output": 64000 } },
"gpt-5.5": { "name": "GPT-5.5" },
"gpt-5.6-sol": { "name": "GPT-5.6 Sol" },
"kimi-k2.7-code": { "name": "Kimi K2.7 Code" }
}
}
},
"model": "apisrouter/claude-sonnet-4-6",
"small_model": "apisrouter/kimi-k2.7-code"
}model と small_model の選び方。
実務上のワークフローは、信頼しているモデルをメインスロットに保ちつつ、ベンチマークではなく実セッションで候補をローテーションすることです。あなた自身のコードベースに対する実際の diff を1日試すほうが、リーダーボードより多くを教えてくれます。1つのエンドポイントに集約しておけば、候補ごとの切り替えは1行の変更で済み、キーごとの利用状況ビューが各実験の実際のコストを示してくれます。
- model はメインのエージェントループを動かします。ファイルを読み、編集を計画し、diff を書き、ツールを実行します。このスロットは最も長い文脈を見て実際のエンジニアリング作業をこなすので、フロンティア級のコーディングモデル(claude-sonnet-4-6、claude-opus-4-7、gpt-5.5)がふさわしい場所です。
- small_model はセッションタイトルの生成のような軽量なタスクを担当します。頻繁に実行される一方、コーディング作業を担うことは決してないので、速く安価な id が適切な形であり、タイトルのためにフロンティア級のトークンを消費する理由はありません。
- gpt-5.6-sol や kimi-k2.7-code のようなコーディング特化の id は、デフォルトにしていなくても宣言しておく価値があります。リファクタリングの多いセッション向けに切り替えるのも /models での選択1つで済み、設定変更は不要です。
- メインと small のどちらのスロットも同じ provider ブロックに対して provider/model 文字列を取るため、両者を同じセッション内で異なるベンダーから選ぶこともできます。これは単一ベンダーのキーでは不可能なことです。
従量課金 · 公式価格より安い
Selected models are priced below official list prices. Exact input, output, cache, and per-request prices are shown for each model.
| モデル | 公式価格 | 当社価格 |
|---|---|---|
| Claude Sonnet 4.6 | $3.00 / $15.00 per M | $2.40 / $12.00 per M |
| Claude Opus 4.7 | $5.00 / $25.00 per M | $4.00 / $20.00 per M |
| GPT-5.5 | $5.00 / $30.00 per M | $4.00 / $24.00 per M |
| GPT-5.6 Sol | $5.00 / $30.00 per M | $4.00 / $24.00 per M |
| Kimi K2.7 Code | $0.95 / $4.00 per M | $1.00 / $4.00 per M |
OpenCode のカスタムプロバイダーに特有の失敗パターン。
SDK パッケージの取り違え。"@ai-sdk/openai" は /v1/responses に POST しますが、チャット補完のゲートウェイはそのルートに対してエラーを返します。最初のリクエストが認証エラーではなくプロトコルやルート絡みの形で失敗する場合は、npm フィールドが正確に "@ai-sdk/openai-compatible" になっているか確認してください。 ピッカーにモデルが出てこない。カスタムプロバイダーのモデルは宣言されて初めて存在します。models のキーのタイプミスや、想定はしていたのに追加し忘れた id は、単に /models に現れません。id はバージョンサフィックスも含めた正確な文字列であり、ゲートウェイの /v1/models 一覧がコピー元として信頼できる情報源です。 解決されない {env:...}。このテンプレートは、OpenCode を起動したプロセスの環境変数から解決されます。あるターミナルで export したキーは、別のターミナルから、あるいはプロファイルを読み込んだことのないデスクトップランチャーから起動した OpenCode インスタンスには届きません。export はワンオフのセッションではなく、シェルのプロファイルに置いてください。 設定マージによる意外な結果。グローバル設定とプロジェクト設定はマージされるため、別のプロバイダーに model を設定しているプロジェクトの opencode.json は、あなたのグローバルなデフォルトを黙って上書きします。古いプロジェクトに残った provider ブロックが、期待と食い違う挙動の影となることもあります。ルーティングがおかしいと感じたら、ゲートウェイの不調を疑う前に両方のファイルを読んでください。 /v1 のない baseURL。SDK は与えられたベースに /chat/completions のようなルートパスを付け足すので、https://api.apisrouter.com/v1 が正しく、素のホストでは動きません。それ以外は正しそうな設定での接続失敗や 404 らしき失敗は、ほぼ常にこれが原因です。
ゲートウェイ経由で OpenCode を使うのは誰か。
- 1日中 TUI で作業し、ベンダーごとに別々の認証情報を維持するのではなく、Claude・GPT・Kimi を1つの /models ピッカーにまとめたい開発者。
- 実際の作業でコーディングモデルを比較するエンジニア。候補ごとに宣言を1つ追加してピッカーで選ぶだけで、セッションごとの比較に新しいアカウントは要りません。
- 1つのシークレットに標準化したいチーム。オンボーディング資料の APISROUTER_API_KEY 1つがベンダーごとの鍵チェックリストを置き換え、キーごとの利用状況が誰が何を使っているかを示します。
- フロンティア級のメインモデルと、別ベンダーの低価格な small_model をペアで使いたいユーザー。単一ベンダー構成では表現できません。
- 特定ベンダーの請求手段にアクセスできない開発者。チャージ制でカード不要のアクセスなら、プロバイダーごとのサインアップという依存を取り除けます。
エンドポイントを検証し、最初のセッションをデバッグする。
セッションを始める前に、ゲートウェイが何を提供しているかを一覧してください。/v1/models が返す id は、models マップのキーと一致させるべき文字列そのものです。 初回セッションの失敗は一貫しています。401 は APISROUTER_API_KEY が OpenCode のプロセスから見えていないことを意味します。起動するのと同じターミナルで変数を echo してみてください。ゲートウェイからのモデル未検出エラーは、宣言したキーがバージョンサフィックスも含めて提供されている id と一致していないことを意味します。プロバイダーがまったく現れない場合は JSON を検証してください。末尾のカンマや位置のずれた波括弧はファイル全体を読めなくし、OpenCode はデフォルトにフォールバックします。 リクエストが流れ始めたら、APIsRouter コンソールがリクエストごとのモデル、トークン数、支出を表示します。コーディングエージェントは長い文脈で多ターンのワークロードなので、どのセッションとどのモデルがトークンを消費しているかを見ることが、メインスロットがその価格に見合っているかを判断する手立てになります。
curl -s https://api.apisrouter.com/v1/models \
-H "Authorization: Bearer $APISROUTER_API_KEY" | head -50よくある質問
OpenCode で Claude・GPT・Kimi モデルを1つのカスタムプロバイダー経由で使えますか?
はい。カスタムプロバイダーは baseURL とモデルのアローリストにすぎません。エンドポイントが複数ベンダーを提供している場合、id ごとに1エントリ宣言すれば、宣言したすべてのモデルが同じプロバイダー・同じキーのもとで /models ピッカーに現れ、セッションの途中でも切り替えられます。
API キーは opencode.json のどこに書きますか?
options.apiKey に環境変数テンプレート、例えば "{env:APISROUTER_API_KEY}" を使って指定します。このテンプレートは読み込み時に解決されるため、リテラルなキーが設定ファイルに残ることはありません。OpenCode を起動するすべてのターミナルが変数を継承できるよう、シェルのプロファイルから export してください。
provider ブロックはグローバル設定とプロジェクト設定のどちらに置くべきですか?
グローバル設定、~/.config/opencode/opencode.json です。OpenCode は設定ファイルをマージするので、プロバイダーをグローバルに1回宣言し、プロジェクトごとにはモデルの選択だけを設定すれば、リポジトリを認証情報の配管から解放でき、重複したブロックが食い違っていく事態も避けられます。
自分のモデルが /models ピッカーに出てこないのはなぜですか?
カスタムプロバイダーのモデルは明示的に宣言する必要があり、OpenCode はカスタムエンドポイントを列挙できません。models マップにバージョンサフィックスも含めた正確な id 文字列が含まれているか確認し、記憶で入力するのではなくゲートウェイの /v1/models のレスポンスから id をコピーしてください。
@ai-sdk/openai-compatible と @ai-sdk/openai の違いは何ですか?
@ai-sdk/openai-compatible は /v1/chat/completions を話し、これはマルチベンダーのゲートウェイが提供するプロトコルです。@ai-sdk/openai は OpenAI の /v1/responses プロトコルを話します。APIsRouter には @ai-sdk/openai-compatible を使ってください。もう一方のパッケージは、この用途でゲートウェイが提供していないルートに POST してしまいます。
宣言したコンテキスト上限は実際に意味がありますか?
はい。OpenCode は limit.context を使ってセッションがいつ圧縮を必要とするか判断します。長文脈モデルで上限を宣言しないままにしておくと、必要以上に早くセッションが要約されてしまうため、limit.context と limit.output は、そのモデルが本当にサポートする値に設定してください。