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
custom primary agent denied free-tier (can only be used from within OpenCode) while built-in plan works with identical model #53347
Custom primary agent (orchestrator, mode: primary) gets Error from provider (Console): OpenCode's free tier can only be used from within OpenCode on its own requests, while built-in plan works with the identical free model in the same run — before any subagent is spawned. Log shows agent=orchestrator mode=primary → 403 vs agent=plan mode=primary → success, same provider/model/session mode. Even the small/title model fails under the custom agent.
Plugins
none
OpenCode version
Desktop v1.18.34
Steps to reproduce
Define a custom primary agent in opencode.json (no model override, inherits free model).
Select muse-spark-1.3-contributor-free and send any message with that agent.
Updated the body to follow the Bug report template (Description / Plugins / OpenCode version / Steps to reproduce / Screenshot / OS / Terminal). Please re-check compliance.
Same symptom, same version (Desktop v1.18.34). I captured the actual outgoing headers for both a passing and a failing request, and I can rule out the User-Agent / client-identity explanations for this path.
How I captured them (no MITM)
The x-opencode-* headers are only attached when providerID.startsWith("opencode"), so a custom provider never receives them. Instead, override the built-inopencode provider and point it at a local listener — providerID stays opencode, so the branch still fires:
All four documented identity headers (User-Agent, x-opencode-client, x-opencode-session, x-opencode-request) are present and well-formed on both. The only differences are the session/message IDs, which necessarily differ.
⇒ For the direct client path, neither the User-Agent nor the client identity can explain a pass/fail split. A "missing header" explanation does not fit here.
The only substantive difference is the request body — 43413 B vs 2444 B, i.e. the system prompt plus tool definitions.
That points at the tool/permission cluster instead
This lines up with the other open reports where the trigger correlates with agent-level tool configuration rather than model or session:
My failing agent is a custom agent with no model override and permission entries denying bash, webfetch, websearch and task. Its title/small request in the same session also went through, which matches the "even the small/title model fails under the custom agent" observation here.
Caveats, stated honestly
I cannot prove causality. Body size is a confounded signal: my "passing" capture was the small/title request, so the 43413 B vs 2444 B gap conflates agent identity with request size.
What is conclusive is the negative result: identity headers are identical, so they are not the discriminator.
Confirming from the reporter's side: this matches the tool/permission-cluster theory. The failing custom primary agent (orchestrator) has edit: deny, �ash: deny, a ask allowlist (5 subagents), and emperature: 0.2 — no model override. The built-in plan agent that succeeds in the same run has no such custom permission block. So the discriminator here correlates with custom agent permissions, not the agent name or identity headers. Happy to provide the full agent definition or a minimal repro (custom primary with �ash: deny only) if it helps isolate the trigger.
Correction to my earlier findings: the 'agent name is the trigger' conclusion was WRONG. Root cause of my misleading ladder test: the Desktop client caches agent definitions — none of my permission edits took effect until a full app quit/reopen, so every probe ran against the original config. Confirmed result after proper restarts: �ash: deny on ANY custom agent (primary or subagent) triggers the FreeTierError; flipping to �ash: allow fixes it (verified on the orchestrator itself). Currently testing �ash: ask as the safe middle ground. Two takeaways for the fix: (1) the gate correlates with bash-deny on custom agents, and (2) agent-definition caching until restart makes this painful to diagnose — a 'reload agents' action or a startup log line would help.
Confirmed root cause + workaround (verified with restarts)
Root cause is \�ash: deny\ on ANY custom agent (primary or subagent) — flipping to \�ash: allow\ fixes it, confirming @l7feng's permission-cluster theory. My earlier 'agent name is the trigger' conclusion was wrong (see below).
Safe middle ground (tested live): \�ash: ask\ also passes the gate AND shows a real approval prompt before each command — applied to orchestrator, docs-keeper and reviewer in our repo, all green, safety preserved.
Diagnostic note (verified by repeated testing, not documented)
The client caches agent definitions — permission edits had zero effect until a full app quit/reopen (this silently invalidated my whole first test ladder: 6 permission variants, all run against stale config). The docs state nothing about this; related open requests: #8751 (hot-reload agents/skills/commands), #6815 (reload-config action), #39987 (config changes need full restart). Suggest either honoring agent edits without restart, or at minimum a reload-agents action + a log line when cached defs are used.
Leaving this open for a proper upstream fix (clearer error, documented restriction) — this comment is only the client-side workaround.
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
Redaessa7 commentedon Oct 5, 2026
Updated the body to follow the Bug report template (Description / Plugins / OpenCode version / Steps to reproduce / Screenshot / OS / Terminal). Please re-check compliance.
github-actions commentedon Oct 5, 2026
Thanks for updating the issue to use the Bug Report template and adding reproduction details. It now meets the issue requirements.
l7feng commentedon Oct 5, 2026
Same symptom, same version (Desktop v1.18.34). I captured the actual outgoing headers for both a passing and a failing request, and I can rule out the
User-Agent/ client-identity explanations for this path.How I captured them (no MITM)
The
x-opencode-*headers are only attached whenproviderID.startsWith("opencode"), so a custom provider never receives them. Instead, override the built-inopencodeprovider and point it at a local listener —providerIDstaysopencode, so the branch still fires:{ "$schema": "https://opencode.ai/config.json", "provider": { "opencode": { "options": { "baseURL": "http://127.0.0.1:8787/v1" } } } }Then dump
req.headersin the listener. No TLS interception, no config change to the real install.Result: byte-identical identity headers
user-agentopencode/1.18.32 ai-sdk/provider-utils/4.0.23 runtime/bun/1.3.14x-opencode-clientdesktopx-opencode-projectglobalx-opencode-sessionses_ef2d56ee…ses_ef2db43e…x-opencode-requestmsg_10d2a91a…msg_10d24bcb…All four documented identity headers (
User-Agent,x-opencode-client,x-opencode-session,x-opencode-request) are present and well-formed on both. The only differences are the session/message IDs, which necessarily differ.⇒ For the direct client path, neither the
User-Agentnor the client identity can explain a pass/fail split. A "missing header" explanation does not fit here.The only substantive difference is the request body — 43413 B vs 2444 B, i.e. the system prompt plus tool definitions.
That points at the tool/permission cluster instead
This lines up with the other open reports where the trigger correlates with agent-level tool configuration rather than model or session:
deny shell *on a custom agenttools.read = falsebreaks all zen free-tier modelsexploredenied whilegeneralworks with identical modelsMy failing agent is a custom agent with no
modeloverride andpermissionentries denyingbash,webfetch,websearchandtask. Itstitle/smallrequest in the same session also went through, which matches the "even the small/title model fails under the custom agent" observation here.Caveats, stated honestly
opencode-ai1.18.32 via npm), independently of the desktop app — consistent with Zen free models fail with FreeTierError in official CLI 1.18.34 (Linux) #52907.Client-side, this looks unfixable from config; the heuristic is server-side and not published.
Redaessa7 commentedon Oct 6, 2026
Confirming from the reporter's side: this matches the tool/permission-cluster theory. The failing custom primary agent (orchestrator) has edit: deny, �ash: deny, a ask allowlist (5 subagents), and emperature: 0.2 — no model override. The built-in plan agent that succeeds in the same run has no such custom permission block. So the discriminator here correlates with custom agent permissions, not the agent name or identity headers. Happy to provide the full agent definition or a minimal repro (custom primary with �ash: deny only) if it helps isolate the trigger.
Redaessa7 commentedon Oct 7, 2026
Correction to my earlier findings: the 'agent name is the trigger' conclusion was WRONG. Root cause of my misleading ladder test: the Desktop client caches agent definitions — none of my permission edits took effect until a full app quit/reopen, so every probe ran against the original config. Confirmed result after proper restarts: �ash: deny on ANY custom agent (primary or subagent) triggers the FreeTierError; flipping to �ash: allow fixes it (verified on the orchestrator itself). Currently testing �ash: ask as the safe middle ground. Two takeaways for the fix: (1) the gate correlates with bash-deny on custom agents, and (2) agent-definition caching until restart makes this painful to diagnose — a 'reload agents' action or a startup log line would help.
Redaessa7 commentedon Oct 7, 2026
Confirmed root cause + workaround (verified with restarts)
Root cause is \�ash: deny\ on ANY custom agent (primary or subagent) — flipping to \�ash: allow\ fixes it, confirming @l7feng's permission-cluster theory. My earlier 'agent name is the trigger' conclusion was wrong (see below).
Safe middle ground (tested live): \�ash: ask\ also passes the gate AND shows a real approval prompt before each command — applied to orchestrator, docs-keeper and reviewer in our repo, all green, safety preserved.
Diagnostic note (verified by repeated testing, not documented)
The client caches agent definitions — permission edits had zero effect until a full app quit/reopen (this silently invalidated my whole first test ladder: 6 permission variants, all run against stale config). The docs state nothing about this; related open requests: #8751 (hot-reload agents/skills/commands), #6815 (reload-config action), #39987 (config changes need full restart). Suggest either honoring agent edits without restart, or at minimum a reload-agents action + a log line when cached defs are used.
Leaving this open for a proper upstream fix (clearer error, documented restriction) — this comment is only the client-side workaround.
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 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊