free models: subagent fails with "free tier can only be used from within OpenCode" when deny-first permissions leave the agent with no allowed actions · Issue #54882 · anomalyco/opencode · GitHub
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
free models: subagent fails with "free tier can only be used from within OpenCode" when deny-first permissions leave the agent with no allowed actions #54882
With a deny-first permissions policy in project config, a subagent running on a free OpenCode model that has no permissions: exceptions cannot be spawned: the call fails with OpenCode's free tier can only be used from within OpenCode. Adding a single narrow allow rule to the same agent makes the identical call succeed. The error points at the free-tier gate, but the only thing that changed is the agent's permission set.
A free model launched as a subagent from a session that is already inside OpenCode should authenticate the same way the primary session does. The agent's permissions: set should gate tool calls; it should not change whether the free-tier gate considers the call to be "from within OpenCode". At minimum, a permission problem should be reported as a permission error rather than as a free-tier eligibility error.
Actual Behavior
Every free-model subagent with no allow rules fails with OpenCode's free tier can only be used from within OpenCode. The same agent definition succeeds as soon as at least one narrow allow rule exists - observed with a single shell allow (git log *) and previously with read on .opencode/opencode.jsonc. Four free-model agents in this project are affected: technical-writer, qa-engineer, documentation-auditor, product-manager.
Additional Context
Suspected cause: the free-tier gate inspects the tool/permission surface of the session. An agent whose actions are all denied ends up with an empty or near-empty tool set, which the gate appears to misread as "not inside OpenCode". Possibly related to tool-set gating in console: free-tier 403 rejects restricted subagents even with bash allowed #54744.
Observed additionally: identical probes against the permitted control agent occasionally returned the same free-tier error under unchanged config until an opencode service restart, so the check may also be intermittent.
Workaround in use: give each free-model agent at least one narrow allow rule. This forces a permission rule that exists only to satisfy the gateway, which is exactly what a deny-first policy is meant to avoid.
Thanks for the detailed report and the control experiment! I think this is a duplicate of #50627. The free-tier check rejects requests whose tool list has no shell (bash) tool, and a deny rule removes tools from that list. Your { "action": "*", "resource": "*", "effect": "deny" } with no agent exceptions removes every tool, shell included. That fits your control agent working: its shell allow for git log * brings the shell tool back.
Possible duplicates and closely related issues, ordered by likelihood:
Until this is fixed, people in those threads get past it by keeping the shell tool in the request: set the base shell rule to ask instead of deny, or add a narrow shell allow as you did. If you have results that differ from that (for example, a read-only allow working consistently), it would help to add them to #50627.
The bot will close this issue as a duplicate in 1 day unless you reply explaining how your problem is different.
Same agent (mode: subagent, model: opencode/mimo-v2.6-flash-free), same prompt ("Reply with exactly PROBE-OK and nothing else. Do not call tools or modify files."), no other config change between the two.
Config A - read on the project config + one shell rule:
{"error":{"type":"tool.execution","message":"Subagent failed (sessionID: ses_...): OpenCode's free tier can only be used from within OpenCode"}}
So under a deny-first policy a single shell allow is not sufficient. The agent also needs a read allow covering the project's opencode.json(c). That points at the gate needing the session to be able to read the project config file - plausibly the "am I inside OpenCode?" check resolves the project configuration through the agent's own permission surface, so a deny-first policy makes the check fail.
Caveat on reliability: even with Config A, some later runs of the same probe returned the free-tier error with no config change, so the check also appears intermittent independently of the rule set.
Thanks for running the A/B test, that's a useful data point. I still think this is the same bug as #50627, and your result fits what was found there.
The free-tier check happens on the server, not in OpenCode itself, and it looks at which tools are listed in the model request. It doesn't check whether OpenCode can read your config file. When a tool is denied outright (every rule for it is deny), OpenCode leaves it out of the request completely. A narrow allow puts the tool back in the list, even if the agent never uses it.
The check seems to want more than just bash. A data point posted on #50627 (from #54744) shows an agent with bash and read allowed, but other tools left out, still being rejected. So under { "action": "*", "resource": "*", "effect": "deny" }, your Config B leaves the request with only the shell tool, which isn't enough. Config A also keeps read, which happens to be enough for this check. The .opencode/opencode.jsonc path itself shouldn't matter. If you want to confirm, replace that resource with an unrelated file (e.g. README.md) and the probe should still pass. Others there also report the check being inconsistent, which fits the occasional failures you saw with Config A.
The most useful next step would be to add your Config A/B results (and that check, if you try it) to #50627, where the fix is being tracked. Related issues: #51193 (a "*" deny removes every tool) and #54744 (restricted allowlists still rejected).
Unless you see something that doesn't fit this explanation, the bot will still close this issue as a duplicate of #50627 at the scheduled time.
Confirmed the prediction: swapping the read resource from .opencode/opencode.jsonc to an unrelated README.md still returns PROBE-OK, with the same shell: "echo 'Hello!'" allow alongside it. So the config file path is irrelevant and does not need to be readable — my earlier comment's conclusion was wrong on that point, and no secrets need to be exposed to the agent for the workaround to work.
Full matrix (deny-first project policy, subagent on opencode/mimo-v2.6-flash-free, v2.0.26, same trivial probe throughout):
Agent permissions:
Result
none
fails
shell only
4/4 failures
read + shell (config file)
PROBE-OK repeatedly, some later failures
read (README.md) + shell
PROBE-OK
Nothing here contradicts the explanation, so agreed this belongs with #50627. I've posted the matrix there, along with two caveats that may matter for the fix: the two-rule allowlist that passes here sits oddly next to the 8-tool allowlist that reportedly still 403s in #54744, and the intermittency observed with an unchanged allowlist looks like a separate behaviour from the "denied tools are dropped from the request" one.
Thanks for checking. Good to know the README.md read rule works just as well, so the workaround doesn't need the agent to read your config or anything sensitive. And thanks for posting the full matrix and the two caveats on #50627. The odd contrast with the 8-tool allowlist in #54744, and the failures with no config change, are useful for whoever picks up the fix there.
The bot will close this issue as a duplicate of #50627 at the scheduled time. Please follow that issue for updates.
Closing this as a duplicate of #50627, as agreed above. Your tests matched the cause found there: the free-tier check rejects requests that leave out some of the default tools, and a deny-first policy takes them out. Thanks for posting your results on #50627. Please follow that issue for updates. For now, adding a narrow read allow (any file) plus a narrow shell allow to the agent gets past the error, as your tests showed.
Activity
opencode-agent commentedon Oct 12, 2026
Thanks for the detailed report and the control experiment! I think this is a duplicate of #50627. The free-tier check rejects requests whose tool list has no shell (
bash) tool, and adenyrule removes tools from that list. Your{ "action": "*", "resource": "*", "effect": "deny" }with no agent exceptions removes every tool, shell included. That fits your control agent working: itsshellallow forgit log *brings the shell tool back.Possible duplicates and closely related issues, ordered by likelihood:
denyrule on a custom agent breaks free-tier models with this same error. This is where the tool-list cause was worked out."*"deny strips every tool from the agent.explore,plan) hit the same error when shell is denied.Until this is fixed, people in those threads get past it by keeping the shell tool in the request: set the base shell rule to
askinstead ofdeny, or add a narrow shellallowas you did. If you have results that differ from that (for example, aread-only allow working consistently), it would help to add them to #50627.The bot will close this issue as a duplicate in 1 day unless you reply explaining how your problem is different.
gelnuro commentedon Oct 12, 2026
Follow-up with a controlled test of which allow rule is actually required.
Both configs use the same deny-first project policy:
Same agent (
mode: subagent,model: opencode/mimo-v2.6-flash-free), same prompt ("Reply with exactly PROBE-OK and nothing else. Do not call tools or modify files."), no other config change between the two.Config A - read on the project config + one shell rule:
Result:
PROBE-OK, repeated several times across the session.Config B - one shell rule only, the read rule commented out:
Result: 4 consecutive attempts all failed:
So under a deny-first policy a single
shellallow is not sufficient. The agent also needs areadallow covering the project'sopencode.json(c). That points at the gate needing the session to be able to read the project config file - plausibly the "am I inside OpenCode?" check resolves the project configuration through the agent's own permission surface, so a deny-first policy makes the check fail.Caveat on reliability: even with Config A, some later runs of the same probe returned the free-tier error with no config change, so the check also appears intermittent independently of the rule set.
opencode-agent commentedon Oct 12, 2026
Thanks for running the A/B test, that's a useful data point. I still think this is the same bug as #50627, and your result fits what was found there.
The free-tier check happens on the server, not in OpenCode itself, and it looks at which tools are listed in the model request. It doesn't check whether OpenCode can read your config file. When a tool is denied outright (every rule for it is
deny), OpenCode leaves it out of the request completely. A narrowallowputs the tool back in the list, even if the agent never uses it.The check seems to want more than just
bash. A data point posted on #50627 (from #54744) shows an agent withbashandreadallowed, but other tools left out, still being rejected. So under{ "action": "*", "resource": "*", "effect": "deny" }, your Config B leaves the request with only the shell tool, which isn't enough. Config A also keepsread, which happens to be enough for this check. The.opencode/opencode.jsoncpath itself shouldn't matter. If you want to confirm, replace that resource with an unrelated file (e.g.README.md) and the probe should still pass. Others there also report the check being inconsistent, which fits the occasional failures you saw with Config A.The most useful next step would be to add your Config A/B results (and that check, if you try it) to #50627, where the fix is being tracked. Related issues: #51193 (a
"*"deny removes every tool) and #54744 (restricted allowlists still rejected).Unless you see something that doesn't fit this explanation, the bot will still close this issue as a duplicate of #50627 at the scheduled time.
gelnuro commentedon Oct 12, 2026
Confirmed the prediction: swapping the read resource from
.opencode/opencode.jsoncto an unrelatedREADME.mdstill returnsPROBE-OK, with the sameshell: "echo 'Hello!'"allow alongside it. So the config file path is irrelevant and does not need to be readable — my earlier comment's conclusion was wrong on that point, and no secrets need to be exposed to the agent for the workaround to work.Full matrix (deny-first project policy, subagent on
opencode/mimo-v2.6-flash-free, v2.0.26, same trivial probe throughout):permissions:shellonlyread+shell(config file)PROBE-OKrepeatedly, some later failuresread(README.md) +shellPROBE-OKNothing here contradicts the explanation, so agreed this belongs with #50627. I've posted the matrix there, along with two caveats that may matter for the fix: the two-rule allowlist that passes here sits oddly next to the 8-tool allowlist that reportedly still 403s in #54744, and the intermittency observed with an unchanged allowlist looks like a separate behaviour from the "denied tools are dropped from the request" one.
Happy for this to be closed as a duplicate.
opencode-agent commentedon Oct 12, 2026
Thanks for checking. Good to know the
README.mdread rule works just as well, so the workaround doesn't need the agent to read your config or anything sensitive. And thanks for posting the full matrix and the two caveats on #50627. The odd contrast with the 8-tool allowlist in #54744, and the failures with no config change, are useful for whoever picks up the fix there.The bot will close this issue as a duplicate of #50627 at the scheduled time. Please follow that issue for updates.
opencode-agent commentedon Oct 13, 2026
Closing this as a duplicate of #50627, as agreed above. Your tests matched the cause found there: the free-tier check rejects requests that leave out some of the default tools, and a deny-first policy takes them out. Thanks for posting your results on #50627. Please follow that issue for updates. For now, adding a narrow
readallow (any file) plus a narrowshellallow to the agent gets past the error, as your tests showed.