From c958da8c22ca7b66af27d697aaa172fbd45381f2 Mon Sep 17 00:00:00 2001 From: Paul Wang Date: Tue, 6 Jan 2026 15:25:05 -0800 Subject: [PATCH] exp --- .../contrib/chat/browser/chat.contribution.ts | 3 ++ .../tools/builtinTools/runSubagentTool.ts | 38 +++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/src/vs/workbench/contrib/chat/browser/chat.contribution.ts b/src/vs/workbench/contrib/chat/browser/chat.contribution.ts index fac472cb5be90..1f4096b3d885e 100644 --- a/src/vs/workbench/contrib/chat/browser/chat.contribution.ts +++ b/src/vs/workbench/contrib/chat/browser/chat.contribution.ts @@ -841,6 +841,9 @@ configurationRegistry.registerConfiguration({ description: nls.localize('chat.subagentTool.customAgents', "Whether the runSubagent tool is able to use custom agents. When enabled, the tool can take the name of a custom agent, but it must be given the exact name of the agent."), default: false, tags: ['experimental'], + experiment: { + mode: 'auto' + } } } }); diff --git a/src/vs/workbench/contrib/chat/common/tools/builtinTools/runSubagentTool.ts b/src/vs/workbench/contrib/chat/common/tools/builtinTools/runSubagentTool.ts index e9001142f866c..ae3e38c560dec 100644 --- a/src/vs/workbench/contrib/chat/common/tools/builtinTools/runSubagentTool.ts +++ b/src/vs/workbench/contrib/chat/common/tools/builtinTools/runSubagentTool.ts @@ -6,6 +6,7 @@ import { CancellationToken } from '../../../../../../base/common/cancellation.js'; import { Codicon } from '../../../../../../base/common/codicons.js'; import { Event } from '../../../../../../base/common/event.js'; +import { StringSHA1 } from '../../../../../../base/common/hash.js'; import { MarkdownString } from '../../../../../../base/common/htmlContent.js'; import { IJSONSchema, IJSONSchemaMap } from '../../../../../../base/common/jsonSchema.js'; import { Disposable } from '../../../../../../base/common/lifecycle.js'; @@ -14,6 +15,7 @@ import { localize } from '../../../../../../nls.js'; import { IConfigurationChangeEvent, IConfigurationService } from '../../../../../../platform/configuration/common/configuration.js'; import { IInstantiationService } from '../../../../../../platform/instantiation/common/instantiation.js'; import { ILogService } from '../../../../../../platform/log/common/log.js'; +import { ITelemetryService } from '../../../../../../platform/telemetry/common/telemetry.js'; import { IChatAgentRequest, IChatAgentService, UserSelectedTools } from '../../participants/chatAgents.js'; import { ChatModel, IChatRequestModeInstructions } from '../../model/chatModel.js'; import { IChatModeService } from '../../chatModes.js'; @@ -42,6 +44,12 @@ import { createToolSimpleTextResult } from './toolHelpers.js'; export const RunSubagentToolId = 'runSubagent'; +function hashAgentName(agentName: string): string { + const sha1 = new StringSHA1(); + sha1.update(agentName); + return sha1.digest(); +} + const BaseModelDescription = `Launch a new agent to handle complex, multi-step tasks autonomously. This tool is good at researching complex questions, searching for code, and executing multi-step tasks. When you are searching for a keyword or file and are not confident that you will find the right match in the first few tries, use this agent to perform the search for you. - Agents do not run async or in the background, you will wait for the agent\'s result. @@ -56,6 +64,26 @@ interface IRunSubagentToolInputParams { agentName?: string; } +type ChatSubagentInvokedEvent = { + hashedAgentName: string | undefined; + usingCustomAgent: boolean; + modelId: string | undefined; + requestId: string | undefined; + chatSessionId: string | undefined; + fromSubAgent: boolean | undefined; +}; + +type ChatSubagentInvokedClassification = { + hashedAgentName: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The hashed name of the specific agent invoked.' }; + usingCustomAgent: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Whether a specific agent was requested.' }; + modelId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The model that invoked the subagent tool.' }; + requestId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The request that invoked the subagent tool.' }; + chatSessionId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The session that invoked the subagent tool.' }; + fromSubAgent: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'Whether the tool was invoked by a subagent.' }; + owner: 'roblourens'; + comment: 'Provides insight into the usage of subagent tool specific agent invocation.'; +}; + export class RunSubagentTool extends Disposable implements IToolImpl { readonly onDidUpdateToolData: Event; @@ -70,6 +98,7 @@ export class RunSubagentTool extends Disposable implements IToolImpl { @ILanguageModelToolsService private readonly toolsService: ILanguageModelToolsService, @IConfigurationService private readonly configurationService: IConfigurationService, @IInstantiationService private readonly instantiationService: IInstantiationService, + @ITelemetryService private readonly telemetryService: ITelemetryService, ) { super(); this.onDidUpdateToolData = Event.filter(this.configurationService.onDidChangeConfiguration, e => e.affectsConfiguration(ChatConfiguration.SubagentToolCustomAgents)); @@ -117,6 +146,15 @@ export class RunSubagentTool extends Disposable implements IToolImpl { this.logService.debug(`RunSubagentTool: Invoking with prompt: ${args.prompt.substring(0, 100)}...`); + this.telemetryService.publicLog2('chatSubagentInvoked', { + hashedAgentName: args.agentName ? hashAgentName(args.agentName) : undefined, + usingCustomAgent: !!args.agentName, + modelId: invocation.modelId, + requestId: invocation.chatRequestId, + chatSessionId: invocation.context?.sessionId, + fromSubAgent: invocation.fromSubAgent + }); + if (!invocation.context) { throw new Error('toolInvocationToken is required for this tool'); }