You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Server (1.18.31): Free tier zen models fail - User-Agent not forwarded to zen API #49756
Versión: opencode 1.18.31 (latest) Plataforma: Linux (Ubuntu 22.04)
Descripción
El servidor opencode (opencode serve / puerto 4096) no reenvía el header User-Agent cuando hace peticiones a la API zen (https://opencode.ai/zen/v1/...). Esto hace que el tier gratuito de modelos zen falle con error 403:
Error from provider (Console): OpenCode's free tier can only be used from within OpenCode
Impacto
TUI (opencode / iago-opencode) → Fallan modelos zen gratuitos
CLI run (opencode run -m muse-spark-1.3-contributor-free) → Fallan modelos zen gratuitos
openchamber (web UI) → Fallan modelos zen gratuitos
Cualquier cliente que use la API del servidor (opencode serve) → Fallan modelos zen gratuitos
Comportamiento esperado vs actual
Componente
Esperado
Actual
Servidor opencode → zen API
Incluye User-Agent: opencode/1.18.31
No incluye User-Agent
Tier gratuito zen
Funciona
403 Forbidden
Root Cause
El servidor opencode actúa como proxy hacia la API zen. Cuando recibe una petición de /api/session/{id}/message con modelo zen, hace la petición a https://opencode.ai/zen/v1/chat/completionssin incluir el header User-Agent que la API zen ahora requiere para el tier gratuito.
Workaround parcial (openchamber)
En openchamber 1.24.1 agregué el header en el proxy:
Esto hace que openchamber → servidor opencode funcione, pero el servidor → zen API sigue fallando porque el binario no reenvía el header.
Bug adicional relacionado
El endpoint POST /api/session/{id}/message del servidor devuelve HTML (página web UI) en lugar de JSON cuando falla, rompiendo todos los clientes API.
Request
Que el servidor opencode incluya automáticamente User-Agent: opencode/<version> en todas las peticiones salientes a la API zen (y idealmente a todos los proveedores que lo requieran).
Logs relevantes
# Petición que falla (desde servidor opencode a zen API)
POST https://opencode.ai/zen/v1/chat/completions
# Headers faltantes: User-Agent: opencode/1.18.31
# Respuesta:
403 Forbidden
{\"type\":\"error\",\"error\":{\"type\":\"FreeTierError\",\"message\":\"Error from provider (Console): OpenCode's free tier can only be used from within OpenCode\"}}
Tested same prompt + same zen model (opencode/big-pickle, correct model: {providerID, modelID} body) against local opencode serve, fresh session each time:
opencode auth login --provider opencode (credential present, server restarted, new session) does not fix it.
Removing custom provider/models overrides from the profile does not fix it.
The failing agent doesn't matter for routing: request reaches https://opencode.ai/zen/v1/responses and Cloudflare returns the 403 — so the Console-side "within OpenCode" check seems to key off the agent's permission footprint (fully tool-denied agents like build/background agents fail; agents with any tool access pass).
Related: POST /session/:id/message with top-level modelID (instead of model: {providerID, modelID}) is silently ignored and falls back to the default model — worth a validation error instead.
This matches @Hdiaktoros's report in #49680 (custom subagent with permission block fails, same prompt without it works).
Useful data point that narrows the scope of this one: on the direct client path the User-Agentis forwarded, in both the desktop app and the standalone CLI.
Measured on Desktop 1.18.34 (Windows) and opencode-ai1.18.32 (npm), by pointing the built-in opencode provider at a local listener and dumping req.headers:
1. This looks specific to the opencode serve proxy path. Your report is about clients going through the server. When opencode itself talks to Zen, the header is present — so the "server does not re-forward" mechanism you describe doesn't appear to apply to the in-process/direct path. That makes your repro (and the openchamber workaround) look like a genuinely separate bug rather than a general one.
2. The wire value is not exactly opencode/<semver>. The client defines two UA constants:
`opencode/${InstallationVersion}` — this is the one attached to the request carrying the x-opencode-* headers
I want to be clear that this is not the cause of the 403 I hit — a passing request and a failing request carried byte-identical user-agent, x-opencode-client and x-opencode-project. So whatever the gateway matches on, it is not distinguishing those two requests by UA here.
I'm raising it only because if the gate ever moves to a strict match on opencode/<semver>, the extra suffixes would break it independently — and a config-level provider.opencode.headers.User-Agent override (which you already found ineffective on the server path) would be the obvious thing to try pinning the value exactly.
For the 403 itself, my captured evidence suggests the differentiator is the request body (system prompt + tool definitions) rather than any header — see #53347, where a passing and a failing request in the same session are header-identical.
Thanks for the report! OpenCode 2.0 is now out and development is focused on V2, so we're closing issues filed against OpenCode 1. Please upgrade (opencode upgrade --major, details: https://anoma.ly/notes/opencode-2-0), and if this is still relevant on 2.0, reopen this issue or open a new one with your 2.0 version.
Activity
iagorobo24-hub commentedon Sep 24, 2026
Bisection results (opencode 1.18.32, server mode)
Tested same prompt + same zen model (
opencode/big-pickle, correctmodel: {providerID, modelID}body) against localopencode serve, fresh session each time:bash/glob/grep/read: allow, no profiletask/bash/read: denyFreeTierErrortask: denyFreeTierErrortask: allow, tooldenys, custom agents)edit/write/bash: deny)bash *, edit, write)Additional notes:
opencode auth login --provider opencode(credential present, server restarted, new session) does not fix it.provider/modelsoverrides from the profile does not fix it.https://opencode.ai/zen/v1/responsesand Cloudflare returns the 403 — so the Console-side "within OpenCode" check seems to key off the agent's permission footprint (fully tool-denied agents likebuild/background agents fail; agents with any tool access pass).POST /session/:id/messagewith top-levelmodelID(instead ofmodel: {providerID, modelID}) is silently ignored and falls back to the default model — worth a validation error instead.This matches @Hdiaktoros's report in #49680 (custom subagent with
permissionblock fails, same prompt without it works).l7feng commentedon Oct 5, 2026
Useful data point that narrows the scope of this one: on the direct client path the
User-Agentis forwarded, in both the desktop app and the standalone CLI.Measured on Desktop
1.18.34(Windows) andopencode-ai1.18.32(npm), by pointing the built-inopencodeprovider at a local listener and dumpingreq.headers:Two things worth separating here:
1. This looks specific to the
opencode serveproxy path. Your report is about clients going through the server. When opencode itself talks to Zen, the header is present — so the "server does not re-forward" mechanism you describe doesn't appear to apply to the in-process/direct path. That makes your repro (and the openchamber workaround) look like a genuinely separate bug rather than a general one.2. The wire value is not exactly
opencode/<semver>. The client defines two UA constants:`opencode/${InstallationVersion}`— this is the one attached to the request carrying thex-opencode-*headers`opencode/${InstallationChannel}/${InstallationVersion}/${Flag.OPENCODE_CLIENT}`but on the wire the AI SDK
provider-utilsand the Bun runtime append extra tokens, so what actually goes out is:I want to be clear that this is not the cause of the 403 I hit — a passing request and a failing request carried byte-identical
user-agent,x-opencode-clientandx-opencode-project. So whatever the gateway matches on, it is not distinguishing those two requests by UA here.I'm raising it only because if the gate ever moves to a strict match on
opencode/<semver>, the extra suffixes would break it independently — and a config-levelprovider.opencode.headers.User-Agentoverride (which you already found ineffective on the server path) would be the obvious thing to try pinning the value exactly.For the 403 itself, my captured evidence suggests the differentiator is the request body (system prompt + tool definitions) rather than any header — see #53347, where a passing and a failing request in the same session are header-identical.
thdxr commentedon Oct 11, 2026
Thanks for the report! OpenCode 2.0 is now out and development is focused on V2, so we're closing issues filed against OpenCode 1. Please upgrade (
opencode upgrade --major, details: https://anoma.ly/notes/opencode-2-0), and if this is still relevant on 2.0, reopen this issue or open a new one with your 2.0 version.— from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊