OpenCode einen benutzerdefinierten OpenAI-kompatiblen Provider hinzufügen.

Updated 2026-07-29

OpenCode liest benutzerdefinierte Provider direkt aus opencode.json. Deklariere einen Provider-Block mit dem Package @ai-sdk/openai-compatible, richte options.baseURL auf https://api.apisrouter.com/v1, und jedes von dir gelistete Modell wird im /models-Picker unter einem Key auswählbar.

Kurzantwort: ein Provider-Block in opencode.json.

OpenCode unterstützt benutzerdefinierte OpenAI-kompatible Provider nativ. Füge opencode.json einen Provider-Eintrag hinzu, bei dem npm auf „@ai-sdk/openai-compatible" gesetzt ist, setze options.baseURL auf https://api.apisrouter.com/v1, lies den Key aus einer Umgebungsvariable über das {env:...}-Template, und liste die gewünschten Modell-IDs unter models auf. Setze dann das Top-Level-Feld model auf „apisrouter/<model-id>", und OpenCode routet die gesamte Agent-Schleife über das Gateway. Das ist der dokumentierte Custom-Provider-Pfad in den OpenCode-Docs, kein Wrapper und kein Fork. Die Config-Datei liegt entweder im Projekt-Root (opencode.json) oder global unter ~/.config/opencode/opencode.json, und beide werden zusammengeführt, sodass der Provider-Block einmal deklariert und in jedem Repo wiederverwendet werden kann.

{
  "$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"
}

Wie OpenCode Provider und Modelle auflöst.

OpenCode (anomalyco auf GitHub, mit rund 186K Stars einer der meistgestarrten Terminal-Coding-Agenten) baut seine Provider-Schicht auf dem Vercel AI SDK auf. Das npm-Feld in einem Provider-Block benennt, welches SDK-Package OpenCode lädt, um mit diesem Provider zu sprechen: „@ai-sdk/openai-compatible" spricht das Standard-/v1/chat/completions-Protokoll, während „@ai-sdk/openai" OpenAIs /v1/responses-Protokoll spricht. Ein Multi-Vendor-Gateway serviert Chat Completions, openai-compatible ist also das richtige Package; „@ai-sdk/openai" gegen einen Chat-Completions-Endpoint zu wählen, ist die häufigste Art, wie dieses Setup kaputtgeht. Modelle werden als Provider/Modell-Paare adressiert. Die Provider-ID ist der Key, den du im Provider-Block gewählt hast (oben „apisrouter"), und die Modell-ID ist der Key innerhalb der models-Map, sodass das Default-Modell zu „apisrouter/claude-sonnet-4-6" wird. Alles, was du deklarierst, taucht im /models-Picker in der TUI auf, mitten in der Session wechselbar. Ein Verhalten, das sich zu verinnerlichen lohnt: Bei benutzerdefinierten Providern ist die models-Map eine Allowlist. Eingebaute Provider kommen mit einem bekannten Katalog, aber OpenCode kann die Modelle eines Custom-Endpoints nicht selbst auflisten, also sind nur explizit deklarierte IDs adressierbar. Serviert der Endpoint hinter baseURL Claude-, GPT-, DeepSeek- und Kimi-IDs nebeneinander, macht ein Eintrag pro Modell den Picker zu einer vendor-übergreifenden Schaltzentrale hinter einem einzigen Key.

Vollständiges Setup: globale Config, Projekt-Config, Limits pro Modell.

Die saubere Struktur ist, den Provider einmal in der globalen Config unter ~/.config/opencode/opencode.json zu deklarieren und nur Pro-Repo-Entscheidungen (welches Modell, welche Agents) in der opencode.json jedes Projekts zu halten. OpenCode führt Config-Dateien zusammen statt sie zu ersetzen, sodass die Projekt-Datei winzig bleibt und der Provider-Block nie dupliziert wird. Das {env:APISROUTER_API_KEY}-Template wird beim Laden aus der Umgebung aufgelöst, was den Key aus jeder Datei heraushält, die eventuell committet wird. Exportiere ihn aus deinem Shell-Profil, damit jede Terminal-Session, die OpenCode startet, ihn sehen kann. Jeder Modell-Eintrag akzeptiert außerdem ein limit-Objekt mit Obergrenzen für Context- und Output-Tokens. Sie zu deklarieren ist wichtiger, als es aussieht: OpenCode nutzt den Context-Wert, um zu entscheiden, wann eine Session zusammengefasst werden muss, sodass ein Long-Context-Modell ohne deklarierte Limits konservativer behandelt wird, als es sollte. Setze limit.context auf das, was das Modell tatsächlich unterstützt, und lange Sessions werden später statt früher komprimiert.

{
  "$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 und small_model wählen.

Der praktische Workflow ist, den Main-Slot auf dem Modell zu halten, dem du für Edits vertraust, und Kandidaten durch echte Sessions statt Benchmarks rotieren zu lassen: Ein Nachmittag echter Diffs an deiner eigenen Codebase sagt dir mehr als ein Leaderboard. Das Routing über einen Endpoint macht jeden Kandidaten zu einer Ein-Zeilen-Änderung, und die Usage-Ansicht pro Key zeigt, was jedes Experiment tatsächlich gekostet hat.

  • model treibt die Haupt-Agent-Schleife an: Dateien lesen, Edits planen, Diffs schreiben, Tools ausführen. Dieser Slot sieht die längsten Kontexte und erledigt die eigentliche Engineering-Arbeit, hier gehört also ein Frontier-Coding-Modell (claude-sonnet-4-6, claude-opus-4-7, gpt-5.5) hin.
  • small_model übernimmt leichte Aufgaben wie die Generierung von Session-Titeln. Es feuert oft, trägt aber nie die Coding-Arbeit, eine schnelle, günstige ID ist also die richtige Form; es gibt keinen Grund, Frontier-Tokens für Titel zu verbrennen.
  • Codespezifische IDs wie gpt-5.6-sol und kimi-k2.7-code lohnen sich zu deklarieren, auch wenn sie nicht dein Default sind: Für eine refactor-lastige Session zu ihnen zu wechseln ist eine /models-Auswahl, keine Config-Änderung.
  • Da beide Slots Provider/Modell-Strings gegen denselben Provider-Block akzeptieren, können Main- und Small-Slot in derselben Session von unterschiedlichen Vendors kommen — etwas, das kein Single-Vendor-Key erlaubt.

Nutzungsbasiert · unter offiziellem Preis

Selected models are priced below official list prices. Exact input, output, cache, and per-request prices are shown for each model.

ModellOffizieller PreisUnser Preis
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

Die Fehlerbilder speziell bei OpenCode-Custom-Providern.

Falsches SDK-Package. „@ai-sdk/openai" postet an /v1/responses; ein Chat-Completions-Gateway beantwortet diese Route mit einem Fehler. Scheitert deine erste Anfrage mit einem protokoll- oder routen-förmigen Fehler statt einem Auth-Fehler, prüfe, ob das npm-Feld exakt „@ai-sdk/openai-compatible" sagt. Modell fehlt im Picker. Custom-Provider-Modelle existieren nur, wenn deklariert; ein Tippfehler in einem models-Key oder eine ID, die du angenommen, aber nie hinzugefügt hast, taucht schlicht nicht in /models auf. IDs sind exakte Strings inklusive Versions-Suffixen, und die /v1/models-Liste des Gateways ist die Quelle der Wahrheit zum Abschreiben. Nicht aufgelöstes {env:...}. Das Template löst sich aus der Umgebung des Prozesses auf, der OpenCode gestartet hat. Ein in einem Terminal exportierter Key erreicht keine OpenCode-Instanz, die aus einem anderen Terminal oder einem Desktop-Launcher gestartet wurde, der dein Profil nie geladen hat. Setze den Export ins Shell-Profil, nicht in eine Einmal-Session. Überraschungen beim Config-Merge. Weil globale und Projekt-Configs zusammengeführt werden, überschreibt eine Projekt-opencode.json, die model auf einen anderen Provider setzt, still deinen globalen Default, und ein übrig gebliebener Provider-Block in einem alten Projekt kann Erwartungen verschatten. Sieht das Routing falsch aus, lies beide Dateien, bevor du annimmst, das Gateway habe sich falsch verhalten. baseURL ohne /v1. Das SDK hängt Routenpfade wie /chat/completions an die Base an, die du angibst, https://api.apisrouter.com/v1 ist also korrekt und der bloße Host nicht. Ein Verbindungs- oder 404-förmiger Fehler bei einer ansonsten korrekten Config ist fast immer das.

Wer OpenCode über ein Gateway routet.

  • Entwickler, die den ganzen Tag in der TUI leben und Claude, GPT und Kimi in einem /models-Picker haben wollen, statt separate Provider-Credentials pro Vendor zu pflegen.
  • Engineers, die Coding-Modelle an echter Arbeit vergleichen. Jeder Kandidat ist ein deklarierter Eintrag und eine Picker-Auswahl; Session-für-Session-Vergleich braucht keine neuen Konten.
  • Teams, die sich auf ein Secret standardisieren. Ein einziger APISROUTER_API_KEY in den Onboarding-Docs ersetzt eine Vendor-Key-Checkliste, und Per-Key-Usage zeigt, wer was ausgibt.
  • Nutzer, die ein Frontier-Main-Modell mit einem günstigen small_model von einem anderen Vendor kombinieren — etwas, das Single-Vendor-Configs nicht abbilden können.
  • Entwickler ohne Zugang zum Billing eines bestimmten Vendors. Guthabenbasierter Zugang ohne Kartenpflicht entfernt die Sign-up-Abhängigkeit pro Provider.

Den Endpoint verifizieren und die erste Session debuggen.

Liste vor dem Start einer Session, was das Gateway serviert. Die von /v1/models zurückgegebenen IDs sind exakt die Strings, denen deine models-Map-Keys entsprechen müssen. Fehler in der ersten Session sind konsistent. Ein 401 heißt, dass APISROUTER_API_KEY für den OpenCode-Prozess nicht sichtbar war; echoe die Variable im selben Terminal, aus dem du startest. Ein Model-not-found-Fehler vom Gateway heißt, dass der deklarierte Key nicht zu einer servierten ID passt, Versions-Suffixe eingeschlossen. Taucht der Provider gar nicht auf, validiere das JSON, denn ein überzähliges Komma oder eine falsch platzierte Klammer macht die ganze Datei unlesbar, und OpenCode fällt auf Defaults zurück. Sobald Anfragen laufen, zeigt die APIsRouter-Konsole Modell, Token-Zahlen und Ausgaben pro Anfrage. Coding-Agents sind Long-Context-, Many-Turn-Workloads, und zu sehen, welche Sessions und welche Modelle die Tokens verbrauchen, zeigt dir, ob sich der Main-Slot seinen Preis verdient.

curl -s https://api.apisrouter.com/v1/models \
  -H "Authorization: Bearer $APISROUTER_API_KEY" | head -50

Häufige Fragen

Kann OpenCode Claude-, GPT- und Kimi-Modelle über einen Custom-Provider nutzen?

Ja. Ein Custom-Provider ist nur eine baseURL plus eine models-Allowlist. Serviert der Endpoint mehrere Vendors, deklariere einen Eintrag pro ID, und jedes deklarierte Modell erscheint im /models-Picker unter demselben Provider und Key, mitten in der Session wechselbar.

Wo kommt der API-Key in opencode.json hin?

In options.apiKey über das Environment-Template, zum Beispiel „{env:APISROUTER_API_KEY}". Das Template löst sich beim Laden auf, sodass der wörtliche Key nie in der Config-Datei steht. Exportiere die Variable aus deinem Shell-Profil, damit jedes Terminal, das OpenCode startet, sie erbt.

Sollte der Provider-Block in der globalen oder der Projekt-Config liegen?

Global, unter ~/.config/opencode/opencode.json. OpenCode führt Config-Dateien zusammen, den Provider einmal global zu deklarieren und nur die Modellwahl pro Projekt zu setzen hält Repos frei von Credentials-Verdrahtung und vermeidet auseinanderdriftende duplizierte Blöcke.

Warum taucht mein Modell nicht im /models-Picker auf?

Custom-Provider-Modelle müssen explizit deklariert werden; OpenCode kann einen Custom-Endpoint nicht selbst auflisten. Prüfe, ob die models-Map den exakten ID-String enthält, Versions-Suffixe eingeschlossen, und kopiere IDs aus der /v1/models-Antwort des Gateways, statt sie aus dem Gedächtnis zu tippen.

Was ist hier der Unterschied zwischen @ai-sdk/openai-compatible und @ai-sdk/openai?

@ai-sdk/openai-compatible spricht /v1/chat/completions, das Protokoll, das Multi-Vendor-Gateways servieren. @ai-sdk/openai spricht OpenAIs /v1/responses-Protokoll. Für APIsRouter nutze @ai-sdk/openai-compatible; das andere Package postet an eine Route, die das Gateway für diesen Zweck nicht bedient.

Machen deklarierte Context-Limits tatsächlich einen Unterschied?

Ja. OpenCode nutzt limit.context, um zu entscheiden, wann eine Session komprimiert werden muss. Bleiben Limits bei einem Long-Context-Modell undeklariert, werden Sessions früher als nötig zusammengefasst, setze also limit.context und limit.output auf das, was das Modell wirklich unterstützt.