diff --git a/docs/reference/configuration.md b/docs/reference/configuration.md index a3b4788026..8982ead4e4 100644 --- a/docs/reference/configuration.md +++ b/docs/reference/configuration.md @@ -1159,7 +1159,7 @@ their corresponding top-level category object in your `settings.json` file. - **`experimental.enableAgents`** (boolean): - **Description:** Enable local and remote subagents. - - **Default:** `true` + - **Default:** `false` - **Requires restart:** Yes - **`experimental.extensionManagement`** (boolean): diff --git a/packages/a2a-server/src/config/config.test.ts b/packages/a2a-server/src/config/config.test.ts index bd8771d1b5..fd137d567e 100644 --- a/packages/a2a-server/src/config/config.test.ts +++ b/packages/a2a-server/src/config/config.test.ts @@ -325,6 +325,28 @@ describe('loadConfig', () => { ); }); + it('should pass enableAgents to Config constructor', async () => { + const settings: Settings = { + experimental: { + enableAgents: false, + }, + }; + await loadConfig(settings, mockExtensionLoader, taskId); + expect(Config).toHaveBeenCalledWith( + expect.objectContaining({ + enableAgents: false, + }), + ); + }); + + it('should default enableAgents to false when not provided', async () => { + await loadConfig(mockSettings, mockExtensionLoader, taskId); + expect(Config).toHaveBeenCalledWith( + expect.objectContaining({ + enableAgents: false, + }), + ); + }); describe('interactivity', () => { it('should set interactive true when not headless', async () => { vi.mocked(isHeadlessMode).mockReturnValue(false); diff --git a/packages/a2a-server/src/config/config.ts b/packages/a2a-server/src/config/config.ts index 607695f173..4844bc3677 100644 --- a/packages/a2a-server/src/config/config.ts +++ b/packages/a2a-server/src/config/config.ts @@ -110,6 +110,7 @@ export async function loadConfig( interactive: !isHeadlessMode(), enableInteractiveShell: !isHeadlessMode(), ptyInfo: 'auto', + enableAgents: settings.experimental?.enableAgents ?? false, }; const fileService = new FileDiscoveryService(workspaceDir, { diff --git a/packages/a2a-server/src/config/settings.ts b/packages/a2a-server/src/config/settings.ts index da9db4e069..ced11a4daa 100644 --- a/packages/a2a-server/src/config/settings.ts +++ b/packages/a2a-server/src/config/settings.ts @@ -48,6 +48,9 @@ export interface Settings { enableRecursiveFileSearch?: boolean; customIgnoreFilePaths?: string[]; }; + experimental?: { + enableAgents?: boolean; + }; } export interface SettingsError { diff --git a/packages/cli/src/config/settingsSchema.test.ts b/packages/cli/src/config/settingsSchema.test.ts index 37ddf87642..5859dd0773 100644 --- a/packages/cli/src/config/settingsSchema.test.ts +++ b/packages/cli/src/config/settingsSchema.test.ts @@ -400,7 +400,7 @@ describe('SettingsSchema', () => { expect(setting).toBeDefined(); expect(setting.type).toBe('boolean'); expect(setting.category).toBe('Experimental'); - expect(setting.default).toBe(true); + expect(setting.default).toBe(false); expect(setting.requiresRestart).toBe(true); expect(setting.showInDialog).toBe(false); expect(setting.description).toBe('Enable local and remote subagents.'); diff --git a/packages/cli/src/config/settingsSchema.ts b/packages/cli/src/config/settingsSchema.ts index b06df48bc3..0e99eb44c0 100644 --- a/packages/cli/src/config/settingsSchema.ts +++ b/packages/cli/src/config/settingsSchema.ts @@ -1838,7 +1838,7 @@ const SETTINGS_SCHEMA = { label: 'Enable Agents', category: 'Experimental', requiresRestart: true, - default: true, + default: false, description: 'Enable local and remote subagents.', showInDialog: false, }, diff --git a/packages/core/src/agents/registry.ts b/packages/core/src/agents/registry.ts index 3a815aa012..fb085c3b44 100644 --- a/packages/core/src/agents/registry.ts +++ b/packages/core/src/agents/registry.ts @@ -44,6 +44,7 @@ export class AgentRegistry { private readonly agents = new Map>(); // eslint-disable-next-line @typescript-eslint/no-explicit-any private readonly allDefinitions = new Map>(); + private readonly builtInAgents = new Set(); constructor(private readonly config: Config) {} @@ -56,6 +57,13 @@ export class AgentRegistry { await this.loadAgents(); } + /** + * Returns true if the agent is a built-in agent. + */ + isBuiltIn(name: string): boolean { + return this.builtInAgents.has(name); + } + private onModelChanged = () => { this.refreshAgents().catch((e) => { debugLogger.error( @@ -240,15 +248,25 @@ export class AgentRegistry { } private loadBuiltInAgents(): void { - this.registerLocalAgent(CodebaseInvestigatorAgent(this.config)); - this.registerLocalAgent(CliHelpAgent(this.config)); - this.registerLocalAgent(GeneralistAgent(this.config)); + const codebaseAgent = CodebaseInvestigatorAgent(this.config); + this.builtInAgents.add(codebaseAgent.name); + this.registerLocalAgent(codebaseAgent); + + const helpAgent = CliHelpAgent(this.config); + this.builtInAgents.add(helpAgent.name); + this.registerLocalAgent(helpAgent); + + const generalistAgent = GeneralistAgent(this.config); + this.builtInAgents.add(generalistAgent.name); + this.registerLocalAgent(generalistAgent); // Register the browser agent if enabled in settings. // Tools are configured dynamically at invocation time via browserAgentFactory. const browserConfig = this.config.getBrowserAgentConfig(); if (browserConfig.enabled) { - this.registerLocalAgent(BrowserAgentDefinition(this.config)); + const browserAgent = BrowserAgentDefinition(this.config); + this.builtInAgents.add(browserAgent.name); + this.registerLocalAgent(browserAgent); } } diff --git a/packages/core/src/config/config.test.ts b/packages/core/src/config/config.test.ts index a4ef0cbaac..de7d225d7c 100644 --- a/packages/core/src/config/config.test.ts +++ b/packages/core/src/config/config.test.ts @@ -185,6 +185,7 @@ vi.mock('../agents/registry.js', () => { AgentRegistryMock.prototype.initialize = vi.fn(); AgentRegistryMock.prototype.getAllDefinitions = vi.fn(() => []); AgentRegistryMock.prototype.getDefinition = vi.fn(); + AgentRegistryMock.prototype.isBuiltIn = vi.fn(); return { AgentRegistry: AgentRegistryMock }; }); @@ -1262,6 +1263,9 @@ describe('Server Config (config.ts)', () => { AgentRegistryMock.prototype.getAllDefinitions.mockReturnValue([ mockAgentDefinition, ]); + AgentRegistryMock.prototype.isBuiltIn.mockImplementation( + (name: string) => name === 'codebase_investigator', + ); const SubAgentToolMock = ( (await vi.importMock('../agents/subagent-tool.js')) as { @@ -1317,6 +1321,9 @@ describe('Server Config (config.ts)', () => { AgentRegistryMock.prototype.getAllDefinitions.mockReturnValue([ mockAgentDefinition, ]); + AgentRegistryMock.prototype.isBuiltIn.mockImplementation( + (name: string) => name === 'codebase_investigator', + ); const SubAgentToolMock = ( (await vi.importMock('../agents/subagent-tool.js')) as { diff --git a/packages/core/src/config/config.ts b/packages/core/src/config/config.ts index 64e78c1776..8699433ce9 100644 --- a/packages/core/src/config/config.ts +++ b/packages/core/src/config/config.ts @@ -951,7 +951,7 @@ export class Config implements McpContext, AgentLoopContext { this.model = params.model; this.disableLoopDetection = params.disableLoopDetection ?? false; this._activeModel = params.model; - this.enableAgents = params.enableAgents ?? true; + this.enableAgents = params.enableAgents ?? false; this.agents = params.agents ?? {}; this.disableLLMCorrection = params.disableLLMCorrection ?? true; this.planEnabled = params.plan ?? true; @@ -3196,7 +3196,8 @@ export class Config implements McpContext, AgentLoopContext { for (const definition of definitions) { try { if ( - !this.isAgentsEnabled() || + (!this.isAgentsEnabled() && + !this.agentRegistry.isBuiltIn(definition.name)) || agentsOverrides[definition.name]?.enabled === false ) { continue; diff --git a/schemas/settings.schema.json b/schemas/settings.schema.json index 1f180ac6dd..6e7c92d0d2 100644 --- a/schemas/settings.schema.json +++ b/schemas/settings.schema.json @@ -1971,8 +1971,8 @@ "enableAgents": { "title": "Enable Agents", "description": "Enable local and remote subagents.", - "markdownDescription": "Enable local and remote subagents.\n\n- Category: `Experimental`\n- Requires restart: `yes`\n- Default: `true`", - "default": true, + "markdownDescription": "Enable local and remote subagents.\n\n- Category: `Experimental`\n- Requires restart: `yes`\n- Default: `false`", + "default": false, "type": "boolean" }, "extensionManagement": {