From a476e557c9cbdddb987c3bc2488c745945e2857f Mon Sep 17 00:00:00 2001 From: MoerAI Date: Fri, 27 Mar 2026 10:35:48 +0900 Subject: [PATCH 1/2] fix(delegate-task): reject when both category and subagent_type provided (fixes #2847) --- src/tools/delegate-task/tools.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/tools/delegate-task/tools.ts b/src/tools/delegate-task/tools.ts index c149f8025..a1d69d228 100644 --- a/src/tools/delegate-task/tools.ts +++ b/src/tools/delegate-task/tools.ts @@ -102,20 +102,23 @@ export function createDelegateTask(options: DelegateTaskToolOptions): ToolDefini prompt: tool.schema.string().describe("Full detailed prompt for the agent"), run_in_background: tool.schema.boolean().describe("REQUIRED. true=async (returns task_id), false=sync (waits). Use false for task delegation, true ONLY for parallel exploration."), category: tool.schema.string().optional().describe(`REQUIRED if subagent_type not provided. Do NOT provide both category and subagent_type.`), - subagent_type: tool.schema.string().optional().describe("REQUIRED if category not provided. Do NOT provide both category and subagent_type."), + subagent_type: tool.schema.string().optional().describe("REQUIRED if category not provided. Do NOT provide both category and subagent_type. Valid values: explore, librarian, oracle, metis, momus"), session_id: tool.schema.string().optional().describe("Existing Task session to continue"), command: tool.schema.string().optional().describe("The command that triggered this task"), }, async execute(args: DelegateTaskArgs, toolContext) { const ctx = toolContext as ToolContextWithMetadata + if (args.category && args.subagent_type) { + throw new Error( + `Invalid arguments: 'category' and 'subagent_type' are mutually exclusive. Provide EXACTLY ONE.\n` + + ` - You provided: category="${args.category}", subagent_type="${args.subagent_type}"\n` + + ` - Use category for task delegation (e.g., category="${categoryExamples.split(", ")[0]}")\n` + + ` - Use subagent_type for direct agent invocation (e.g., subagent_type="explore")\n` + + ` - Valid subagent_type values: explore, librarian, oracle, metis, momus` + ) + } if (args.category) { - if (args.subagent_type && args.subagent_type !== SISYPHUS_JUNIOR_AGENT) { - log("[task] category provided - overriding subagent_type to sisyphus-junior", { - category: args.category, - subagent_type: args.subagent_type, - }) - } args.subagent_type = SISYPHUS_JUNIOR_AGENT } await ctx.metadata?.({ From 8136679b1cc10ea24d5a535594cda18a53044781 Mon Sep 17 00:00:00 2001 From: MoerAI Date: Fri, 27 Mar 2026 11:53:54 +0900 Subject: [PATCH 2/2] test: update test to expect mutual exclusion error for category+subagent_type --- src/tools/delegate-task/tools.test.ts | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/src/tools/delegate-task/tools.test.ts b/src/tools/delegate-task/tools.test.ts index 550e87b78..b56096493 100644 --- a/src/tools/delegate-task/tools.test.ts +++ b/src/tools/delegate-task/tools.test.ts @@ -465,7 +465,7 @@ describe("sisyphus-task", () => { expect(args.subagent_type).toBe("Sisyphus-Junior") }, { timeout: 10000 }) - test("category overrides subagent_type and still maps to sisyphus-junior", async () => { + test("rejects when both category and subagent_type are provided", async () => { //#given const { createDelegateTask } = require("./tools") @@ -507,14 +507,7 @@ describe("sisyphus-task", () => { abort: new AbortController().signal, } - const args: { - description: string - prompt: string - category: string - subagent_type: string - run_in_background: boolean - load_skills: string[] - } = { + const args = { description: "Override test", prompt: "Do something", category: "quick", @@ -523,12 +516,8 @@ describe("sisyphus-task", () => { load_skills: [], } - //#when - const result = await tool.execute(args, toolContext) - - //#then - expect(args.subagent_type).toBe("Sisyphus-Junior") - expect(result).toContain("Background task launched") + //#when + #then + await expect(tool.execute(args, toolContext)).rejects.toThrow("mutually exclusive") }, { timeout: 10000 }) test("proceeds without error when systemDefaultModel is undefined", async () => {