-
Notifications
You must be signed in to change notification settings - Fork 14.2k
Description
Description
Description
The documentation states that todowrite and todoread are "disabled for subagents by default, but you can enable it manually" via the agent's permission field. However, setting todowrite: allow and todoread: allow in a custom subagent's permission config has no effect — the tools remain unavailable at runtime.
Steps to Reproduce
- Create a custom subagent markdown file (e.g.,
~/.config/opencode/agents/executor.md):
---
description: Executes markdown plans iteratively
mode: subagent
permission:
edit: deny
bash:
"*": deny
task:
"*": deny
"build": allow
webfetch: deny
todowrite: allow
todoread: allow
---
You are a plan executor agent. Use todowrite and todoread to track tasks.- Invoke the agent via
@executoror have a primary agent delegate to it via the Task tool. - The agent attempts to call
todowrite.
Expected Behavior
The todowrite and todoread tools should be available to the subagent, as configured in the agent's permission block.
Actual Behavior
⚙ invalid [tool=todowrite, error=Model tried to call unavailable tool 'todowrite'. Available tools: invalid, read, glob, grep, task, skill.]
Root Cause
The Task tool implementation in packages/opencode/src/tool/task.ts hardcodes todowrite and todoread as denied in two places, overriding the agent's permission config:
1. Session creation — hardcoded deny permissions on the child session:
return await Session.create({
// ...
permission: [
{ permission: "todowrite", pattern: "*", action: "deny" },
{ permission: "todoread", pattern: "*", action: "deny" },
// ...
],
})2. SessionPrompt.prompt call — hardcoded false in the tools object:
const result = await SessionPrompt.prompt({
// ...
tools: {
todowrite: false,
todoread: false,
// ...
},
})In prompt.ts, the deprecated tools parameter is converted to session-level permissions and applied via Session.setPermission, which overwrites the session permissions set during creation. Since Permission.merge(agent.permission, session.permission) is used at evaluation time, the session-level deny always wins over the agent-level allow.
There is an existing pattern for conditionally skipping this override — the task permission uses a hasTaskPermission check:
const hasTaskPermission = agent.permission.some((rule) => rule.permission === "task")
// ...
permission: [
// ...
...(hasTaskPermission
? []
: [{ permission: "task", pattern: "*", action: "deny" }]),
],But no equivalent check exists for todowrite/todoread.
Suggested Fix
Add a similar check for todowrite and todoread that respects the agent's permission config:
const hasTodoWritePermission = agent.permission.some(
(rule) => rule.permission === "todowrite" && rule.action === "allow"
)
const hasTodoReadPermission = agent.permission.some(
(rule) => rule.permission === "todoread" && rule.action === "allow"
)Then conditionally include the deny rules in session creation:
permission: [
...(hasTodoWritePermission
? []
: [{ permission: "todowrite", pattern: "*", action: "deny" }]),
...(hasTodoReadPermission
? []
: [{ permission: "todoread", pattern: "*", action: "deny" }]),
// ...
],And similarly for the tools object passed to SessionPrompt.prompt:
tools: {
todowrite: hasTodoWritePermission ? undefined : false,
todoread: hasTodoReadPermission ? undefined : false,
// ...
},Environment
- OpenCode version: latest (dev branch as of 2025-03-25)
- OS: Linux
- Relevant files:
packages/opencode/src/tool/task.ts,packages/opencode/src/session/prompt.ts
Plugins
no plugins
OpenCode version
1.3.0
Steps to reproduce
- Create a custom subagent markdown file (e.g.,
~/.config/opencode/agents/executor.md):
---
description: Executes markdown plans iteratively
mode: subagent
permission:
edit: deny
bash:
"*": deny
task:
"*": deny
"build": allow
webfetch: deny
todowrite: allow
todoread: allow
---
You are a plan executor agent. Use todowrite and todoread to track tasks.- Invoke the agent via
@executoror have a primary agent delegate to it via the Task tool. - The agent attempts to call
todowrite.
Screenshot and/or share link
No response
Operating System
Ubuntu 25.10
Terminal
Alacritty