OpenCode Go a changé ses règles d'API : comment j'ai adapté le wrapper LiteLLM de Podlet
Jusqu'à récemment, l'abonnement OpenCode Go me donnait accès, dans Podlet, à des modèles open source très compétitifs — comme GLM-5.3 — pour 10 $ par mois. Puis OpenCode Go a changé ses règles de communication. Du jour au lendemain, les requêtes qui ne respectent pas la nouvelle règle sont rejetées.
Un opérateur de leur API, sur un ticket GitHub, indique de 635 utilisateurs et organisations qui appellent l'API via LiteLLM et se sont retrouvés bloqués. Près d'un mois plus tard, pas de correctif officiel côté LiteLLM. Plutôt que d'attendre, j'ai adapté le wrapper LiteLLM de Podlet moi-même — avec l'aide de ...Podlet , qui a changé son propre code.
Le contexte : des bon modèles open-weights pour 10 $/mois
Pour ceux qui ne connaissent pas Podlet : c'est une application auto-hébergée d'orchestration d'agents spécialisés que j'ai codé (j'en ai déjà parlé sur ce post : Présentation de Podlet). Toutes ses requêtes LLM passent par un wrapper construit autour LiteLLM, qui traduit un format unique — le format OpenAI — vers plus de 100 APIs de fournisseurs. C'est cette couche qui nous intéressera ici, car c'est elle qu'on a dû adapter.
Côté modèles, l'abonnement OpenCode Go (10 $/mois, formule Go Plus à 40 $/mois avec des limites supérieures) sert des modèles open source via une API compatible OpenAI, avec des limites généreuses. Le lineup inclut notamment GLM-5.3 et GLM-5.3-Flash, Kimi K3, DeepSeek V4.x, Grok 4.7 ou encore Qwen3.8 — avec l'avertissement officiel que la liste peut évoluer.
Et ces modèles ne sont plus si loin de la frontière avec des modèles propriétaire comme Sonnet 5.5 ou gpt sol. D'après les propres benchmarks de Z.ai (source éditeur, donc à prendre avec recul), GLM-5.3 est « le modèle open-weights le plus capable pour le code », avec un état de l'art open source sur Terminal Bench 3.0 et Agents' Last Exam. Son prédécesseur GLM-5.2 arrivait déjà à quelques points de Claude Opus 4.8 sur Terminal-Bench 2.1 (81.0 contre 85.0). Bref : pour 10 $ par mois, on touche à des modèles crédibles face à OpenAI ou Anthropic.
La règle qui a changé : un header, 635 utilisateurs bloqués
OpenCode Go a durci les règles que doit respecter un client pour communiquer avec sa passerelle. Règles documentées, officielles, dans la section Where can I use it? de la doc :
- Envoyer du trafic typique d'un agent de codage ;
- S'identifier avec son propre user-agent (ex.
my-coding-agent/1.0) plutôt qu'avec le nom générique d'un SDK ; - Envoyer un ID de session stable dans le header
x-opencode-session, une ID par conversation, pour optimiser le routage et le prompt caching.
Le trafic est surveillé pour détecter les abus. Autrement dit : ces règles existent très probablement pour contrer les bots qui exploitent massivement l'abonnement.
Le problème ? LiteLLM n'envoie aucun de ces headers. Le 3 septembre 2026, thdxr ouvre le ticket BerriAI/litellm #39503, intitulé « Send x-opencode-session header on API requests (required by OpenCode Go from 09/05) ». La citation clé :
« we operate the OpenCode Go managed-inference API, and 635 of your users' orgs call it through LiteLLM (UA litellm/1.98.0). Starting 09/05, requests without an
x-opencode-sessionheader will error on our side — we need a stable per-conversation ID for routing/optimization. LiteLLM doesn't send it in any version we've seen. »— thdxr, opérateur de l'API OpenCode Go, dans le ticket BerriAI/litellm #39503 (3 septembre 2026)
Au moment où j'écris ces lignes (fin septembre 2026), le ticket #39503 est toujours ouvert, avec une issue liée (#39549) tout aussi ouverte — soit environ quatre semaines sans correctif fusionné visible.
Pourquoi je n'ai pas attendu le fix officiel
Si votre application route ses requêtes via LiteLLM vers OpenCode Go, vous êtes concerné, directement ou indirectement. Attendre un fix, ça veut dire une app cassée en attendant ou alors perdre son abonnement pendant ce temps pour un fix qui ne va peut être jamais arriver. Moi, j'avais deux objectifs précis :
- Matcher la documentation OpenCode Go — injecter ce qu'elle exige ;
- En profiter pour suivre la documentation OpenRouter — pour que mon application apparaisse comme « Podlet », et non plus « litellm », dans les logs OpenRouter.
Deux changements, un seul endroit à toucher : le wrapper.
Étape 1 : apparaître comme « Podlet » dans les logs OpenRouter
Pour OpenRouter, c'est allé vite. La doc d'OpenRouter documente deux headers optionnels d'attribution : HTTP-Referer (identifie votre app sur openrouter.ai) et X-OpenRouter-Title (définit le titre de votre app — l'alias X-Title est aussi accepté, mais X-OpenRouter-Title est le nom principal actuel).
fetch('https://openrouter.ai/api/v1/chat/completions', {
method: 'POST',
headers: {
Authorization: 'Bearer <OPENROUTER_API_KEY>',
'HTTP-Referer': '<YOUR_SITE_URL>', // identifie l'app sur openrouter.ai
'X-OpenRouter-Title': '<YOUR_SITE_NAME>', // titre de l'app (X-Title accepté aussi)
'Content-Type': 'application/json',
},
body: JSON.stringify({ model: 'openai/gpt-5.2', messages: [ /* … */ ] }),
});
J'ai demandé à l'agent IA de la documentation OpenRouter comment afficher le nom de son app dans les logs, copié-collé le résultat dans le chat Podlet, et quelques secondes plus tard l'agent me répondait que les changements sont minimes — et il les a faits lui-même : un switch sur le provider OpenRouter, qui ajoute les headers d'identification à chaque requête dans le cas ou le provider est indiqué "openrouter" dans les paramètres du modèle.
Restait à vérifier en conditions réelles : push des modifications vers le dépôt, mise à jour de la version locale de Podlet, relance du container, nouvelle conversation, message de test. Direction les logs OpenRouter, quelques refreshs… et « Podlet » apparaît bien à la place de « LiteLLM ». Premier objectif atteint.

Logs OpenRouter, septembre 2026 — Podlet apparaît à la place de LiteLLM grâce aux headers d'attribution HTTP-Referer et X-OpenRouter-Title (capture issue de la vidéo de l'épisode).
Étape 2 : le fix OpenCode Go — et le piège du provider
Même démarche pour OpenCode Go : je passe à l'agent le passage pertinent de la documentation, et je lui demande de faire la mise à jour en fonction. Ce que la passerelle attend, c'est ceci :
User-Agent: my-coding-agent/1.0 # pas un nom de SDK générique (ex. "litellm/1.98.0")
x-opencode-session: <uuid-stable> # un ID stable PAR CONVERSATION
L'agent fait sa modification, je déploie comme précédemment, je teste avec un modèle d'OpenCode Go… et toujours la même erreur.
Je lui envoie simplement : « corrige l'erreur, c'est toujours pareil ». En quelques secondes, il trouve le problème tout seul. Son premier réflexe avait été de faire un switch sur le provider, comme pour OpenRouter. Logique en apparence — mais faux ici.
Provider vs URL : la mécanique LiteLLM qui a piégé l'agent
Dans LiteLLM, un provider est un fournisseur officiellement pris en charge, routé par préfixe (openrouter/…, anthropic/…). OpenRouter est dans la liste. OpenCode, non : « OpenCode » est absent de la liste des providers de la doc LiteLLM. Impossible donc de router vers un provider opencode/….
Pour un endpoint non pris en charge, le chemin documenté est différent : on passe par un endpoint OpenAI-compatible (préfixe openai) avec sa propre api_base, et on discrimine sur l'URL. C'est la correction que l'agent a trouvée seul : si OpenCode est dans l'URL fournie, appliquer les headers de la documentation. Le mécanisme d'injection est le paramètre extra_headers du SDK LiteLLM :
litellm.completion(
model="openai/<modele-opencode>", # endpoint OpenAI-compatible, pas de préfixe "opencode/"
api_base="https://<passerelle-opencode>/v1",
api_key="...",
extra_headers={"x-opencode-session": "<uuid-par-conversation>"},
messages=[...],
)
Précision honnête : ce snippet est illustratif. Le paramètre extra_headers est documenté côté LiteLLM, mais la façon exacte dont le wrapper de Podlet l'utilise mérite d'être lue directement dans le code du dépôt.
Au passage, l'agent a lu la documentation, patché, déployé, testé, puis autodébogué à partir d'un simple message d'erreur — sans que je le guide.
La limite qui reste : reasoning_effort rejeté par la passerelle
Une fois les headers en place, il restait un autre problème — et celui-là, je ne peux pas le corriger.
Récemment, j'ai ajouté à Podlet la possibilité pour l'utilisateur de choisir le niveau de raisonnement du modèle. Côté OpenAI, ce paramètre existe sous deux noms selon l'API : reasoning.effort (Responses API, recommandée) et reasoning_effort (Chat Completions), avec des valeurs dépendant du modèle (low, medium, high) :
# Responses API (recommandée)
from openai import OpenAI
client = OpenAI()
response = client.responses.create(
model="gpt-6-astra",
reasoning={"effort": "low"},
input=[{"role": "user", "content": prompt}],
)
# Chat Completions
response = client.chat.completions.create(
model="gpt-6-astra",
reasoning_effort="low",
messages=[{"role": "user", "content": prompt}],
)
Or, d'après mes tests, la passerelle OpenCode Go rejette ce paramètre — alors même qu'elle expose une API compatible OpenAI et communique avec les modèles via le SDK OpenAI, de ce que j'en observe. Point important : ce rejet est un constat empirique, non documenté. Les docs OpenCode Go (consultées fin septembre 2026) décrivent les règles d'identification (user-agent, session), mais ne disent rien d'un rejet de paramètres.
Le contraste avec OpenRouter est parlant : leur doc indique que si un modèle ne supporte pas un paramètre, « the parameter is ignored. The rest are forwarded ». OpenRouter ignore silencieusement ce qu'il ne connaît pas ; OpenCode Go rejette. (Nuance pour être juste : OpenAI rejette aussi certaines combinaisons — reasoning.effort: none sur GPT-6 Astra retourne un HTTP 400. Mais là, c'est le paramètre entier que la passerelle refuse.)
Ce choix est sûrement là, encore, pour limiter les abus — et c'est un comportement assez commun sur les formules par abonnement. La conséquence concrète : côté OpenCode Go, on ne peut pas contrôler la profondeur de réflexion du modèle. C'est une vraie limitation, à connaître avant de s'engager.
Ce que je retiens de cet épisode
Pour résumer, trois leçons qui dépassent ce cas précis :
- **Un abonnement à 10 $ : les modèles sont excellents, mais la passerelle impose ses règles — identification, sessions, paramètres rejetés — et peut les changer du jour au lendemain.
- Une couche d'abstraction absorbe les changements : quand un fournisseur change ses règles, on adapte le wrapper, pas l'application entière.
- Le vrai coût d'un « changement de règle » dépend de votre outillage : ici, quelques minutes avec Podlet — patch, déploiement, vérification dans les logs d'un tiers, autodébogage — là où le ticket amont dort depuis près d'un mois.
FAQ
OpenCode Go supporte-t-il LiteLLM ?
Pas nativement. « OpenCode » est absent de la liste des providers pris en charge par LiteLLM ; le chemin documenté est un endpoint OpenAI-compatible (préfixe openai) avec sa propre api_base. LiteLLM n'envoie pas non plus le header x-opencode-session exigé — l'objet du ticket #39503, ouvert le 3 septembre 2026 et toujours ouvert fin septembre 2026.
Pourquoi ma requête OpenCode Go est-elle rejetée ?
La passerelle exige un user-agent identifiable (ex. my-coding-agent/1.0, pas un nom de SDK) et un header x-opencode-session avec un ID stable par conversation. Depuis le 5 septembre 2026, les requêtes sans ce header sont rejetées : « requests without an x-opencode-session header will error », annonce l'opérateur. Si vos requêtes partent avec l'user-agent litellm/1.98.0, vous êtes dans le cas visé.
Comment identifier son application dans les logs OpenRouter ?
Deux headers optionnels documentés : HTTP-Referer, qui identifie votre application sur openrouter.ai, et X-OpenRouter-Title, qui définit son titre (X-Title est un alias accepté, mais X-OpenRouter-Title est le nom principal actuel). Sans eux, votre application apparaît sous le nom du SDK — Podlet s'affichait comme « litellm » avant l'ajout de ces headers.
Pour aller plus loin
- Le ticket BerriAI/litellm #39503 — l'annonce de l'opérateur :
x-opencode-sessionobligatoire, 635 organisations concernées - La documentation OpenCode Go — les règles de communication d'un client et les modèles de l'abonnement
- La documentation OpenRouter — les headers d'attribution
HTTP-RefereretX-OpenRouter-Title - Gérer la mémoire des agents IA —
x-opencode-sessionsert à optimiser le routage et le prompt caching - Présentation de Podlet — l'application derrière ce wrapper
Je vous invite à tester Podlet par vous-même : github.com/HellKaiser45/Podlet