diff --git a/agentscope-harness/src/main/java/io/agentscope/harness/agent/HarnessAgent.java b/agentscope-harness/src/main/java/io/agentscope/harness/agent/HarnessAgent.java index fd1a40f0c0..08b32dee24 100644 --- a/agentscope-harness/src/main/java/io/agentscope/harness/agent/HarnessAgent.java +++ b/agentscope-harness/src/main/java/io/agentscope/harness/agent/HarnessAgent.java @@ -1096,6 +1096,7 @@ public static class Builder { boolean disableWorkspaceContext = false; boolean disableAtPathExpansion = false; boolean disableSubagents = false; + boolean disableGeneralPurposeSubagent = false; boolean disableDynamicSkills = false; boolean disableDefaultWorkspaceSkills = false; boolean disableDynamicSubagents = false; @@ -1937,6 +1938,17 @@ public Builder disableSubagents() { return this; } + /** + * Disables the built-in {@code general-purpose} subagent while keeping declared and custom + * subagents available. + * + * @return this builder + */ + public Builder disableGeneralPurposeSubagent() { + this.disableGeneralPurposeSubagent = true; + return this; + } + public Builder disableToolsConfig() { this.disableToolsConfig = true; return this; diff --git a/agentscope-harness/src/main/java/io/agentscope/harness/agent/HarnessAgentBuilderSupport.java b/agentscope-harness/src/main/java/io/agentscope/harness/agent/HarnessAgentBuilderSupport.java index f8eb5a8c43..26425f0694 100644 --- a/agentscope-harness/src/main/java/io/agentscope/harness/agent/HarnessAgentBuilderSupport.java +++ b/agentscope-harness/src/main/java/io/agentscope/harness/agent/HarnessAgentBuilderSupport.java @@ -197,13 +197,15 @@ static List buildSubagentEntries( List entries = new ArrayList<>(); - entries.add( - new SubagentEntry( - "general-purpose", - "General-purpose subagent with same capabilities as the main agent." - + " Use for any isolated task that can be fully delegated.", - buildGeneralPurposeFactory(b, resolvedWorkspace, sandboxFs), - null)); + if (!b.disableGeneralPurposeSubagent) { + entries.add( + new SubagentEntry( + "general-purpose", + "General-purpose subagent with same capabilities as the main agent." + + " Use for any isolated task that can be fully delegated.", + buildGeneralPurposeFactory(b, resolvedWorkspace, sandboxFs), + null)); + } for (SubagentDeclaration decl : allDeclarations) { entries.add( @@ -240,13 +242,15 @@ static List buildStaticSubagentEntries( HarnessAgent.Builder b, Path resolvedWorkspace, SandboxBackedFilesystem sandboxFs) { List entries = new ArrayList<>(); - entries.add( - new SubagentEntry( - "general-purpose", - "General-purpose subagent with same capabilities as the main agent." - + " Use for any isolated task that can be fully delegated.", - buildGeneralPurposeFactory(b, resolvedWorkspace, sandboxFs), - null)); + if (!b.disableGeneralPurposeSubagent) { + entries.add( + new SubagentEntry( + "general-purpose", + "General-purpose subagent with same capabilities as the main agent." + + " Use for any isolated task that can be fully delegated.", + buildGeneralPurposeFactory(b, resolvedWorkspace, sandboxFs), + null)); + } for (SubagentDeclaration decl : b.subagentDeclarations) { entries.add( diff --git a/agentscope-harness/src/test/java/io/agentscope/harness/agent/HarnessAgentTest.java b/agentscope-harness/src/test/java/io/agentscope/harness/agent/HarnessAgentTest.java index 510a9c295d..16a6e6846f 100644 --- a/agentscope-harness/src/test/java/io/agentscope/harness/agent/HarnessAgentTest.java +++ b/agentscope-harness/src/test/java/io/agentscope/harness/agent/HarnessAgentTest.java @@ -479,6 +479,53 @@ void subagentMarkdown_registersIdsAndSubagentTools() throws Exception { "built-in general-purpose entry should be listed"); } + @Test + void disableGeneralPurposeSubagent_keepsDeclaredSubagentsAvailable() throws Exception { + Files.createDirectories(workspace); + Files.writeString(workspace.resolve(WorkspaceConstants.AGENTS_MD), "# workspace\n"); + Path subagents = workspace.resolve("subagents"); + Files.createDirectories(subagents); + Files.writeString( + subagents.resolve("specialist.md"), + """ + --- + description: A custom specialist subagent + --- + You only reply OK. + """); + + Model model = stubModel("done"); + HarnessAgent.Builder builder = + HarnessAgent.builder() + .name("main") + .model(model) + .workspace(workspace) + .abstractFilesystem(new LocalFilesystem(workspace)) + .disableGeneralPurposeSubagent(); + + List entryNames = + builder.buildSubagentEntries(workspace).stream() + .map(SubagentEntry::name) + .collect(Collectors.toList()); + assertFalse(entryNames.contains("general-purpose")); + assertTrue(entryNames.contains("specialist")); + + HarnessAgent agent = builder.build(); + agent.call(userText("go"), RuntimeContext.builder().sessionId("s2").build()).block(); + + @SuppressWarnings("unchecked") + ArgumentCaptor> captor = ArgumentCaptor.forClass(List.class); + verify(model, atLeast(1)).stream(captor.capture(), any(), any()); + String combined = + captor.getAllValues().stream() + .map(HarnessAgentTest::joinAllText) + .filter(s -> s.contains("## Subagents")) + .findFirst() + .orElse(""); + assertTrue(combined.contains("`specialist`")); + assertFalse(combined.contains("general-purpose")); + } + @Test void subagentsDir_loadsMarkdownDeclarations() throws Exception { Files.createDirectories(workspace);