diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index ead3a0149b4..ebb913261a1 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -1039,6 +1039,7 @@ export namespace Config { .array(z.string()) .optional() .describe("Tools that should only be available to primary agents."), + subagent_tools: z.array(z.string()).optional().describe("Tools that should only be available to subagents."), continue_loop_on_deny: z.boolean().optional().describe("Continue the agent loop when a tool call is denied"), mcp_timeout: z .number() diff --git a/packages/opencode/src/tool/registry.ts b/packages/opencode/src/tool/registry.ts index eb76681ded4..86f0ec8c22b 100644 --- a/packages/opencode/src/tool/registry.ts +++ b/packages/opencode/src/tool/registry.ts @@ -119,6 +119,10 @@ export namespace ToolRegistry { export async function tools(providerID: string, agent?: Agent.Info) { const tools = await all() + const config = await Config.get() + const primaryTools = new Set(config.experimental?.primary_tools ?? []) + const subagentTools = new Set(config.experimental?.subagent_tools ?? []) + const result = await Promise.all( tools .filter((t) => { @@ -126,6 +130,10 @@ export namespace ToolRegistry { if (t.id === "codesearch" || t.id === "websearch") { return providerID === "opencode" || Flag.OPENCODE_ENABLE_EXA } + + if (agent?.mode === "subagent" && primaryTools.has(t.id)) return false + if (agent?.mode === "primary" && subagentTools.has(t.id)) return false + return true }) .map(async (t) => { diff --git a/packages/opencode/src/tool/task.ts b/packages/opencode/src/tool/task.ts index 53b501ba91a..bda96410954 100644 --- a/packages/opencode/src/tool/task.ts +++ b/packages/opencode/src/tool/task.ts @@ -81,11 +81,6 @@ export const TaskTool = Tool.define("task", async (ctx) => { pattern: "*", action: "deny", }, - ...(config.experimental?.primary_tools?.map((t) => ({ - pattern: "*", - action: "allow" as const, - permission: t, - })) ?? []), ], }) }) @@ -147,7 +142,6 @@ export const TaskTool = Tool.define("task", async (ctx) => { todowrite: false, todoread: false, task: false, - ...Object.fromEntries((config.experimental?.primary_tools ?? []).map((t) => [t, false])), }, parts: promptParts, }) diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index e423fecea42..735567e037f 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -1746,6 +1746,10 @@ export type Config = { * Tools that should only be available to primary agents. */ primary_tools?: Array + /** + * Tools that should only be available to subagents. + */ + subagent_tools?: Array /** * Continue the agent loop when a tool call is denied */