run_agent
Delegate complex multi-step tasks to specialized autonomous agents for independent execution, handling operations like code refactoring, test fixes, and systematic codebase analysis.
Instructions
Delegate complex, multi-step, or specialized tasks to an autonomous agent for independent execution with dedicated context (e.g., refactoring across multiple files, fixing all test failures, systematic codebase analysis, batch operations)
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| agent | Yes | Identifier of the specialized agent to delegate the task to | |
| prompt | Yes | Task description or instructions for the agent to execute. When referencing file paths, use absolute paths to ensure proper file access. | |
| cwd | No | Working directory path for agent execution context (optional) | |
| extra_args | No | Additional configuration parameters for agent execution (optional) |
Implementation Reference
- src/tools/RunAgentTool.ts:164-373 (handler)The execute method is the core handler for the 'run_agent' tool. It validates input parameters, checks agent availability, executes the agent using AgentExecutor, manages sessions if enabled, formats the MCP-compliant response, and handles all errors.async execute(params: unknown): Promise<McpToolResponse> { const startTime = Date.now() const requestId = this.generateRequestId() this.logger.info('Run agent tool execution started', { requestId, timestamp: new Date().toISOString(), }) // Best-effort cleanup: old session files (ADR-0002) // Non-blocking execution - does not affect main processing flow if (this.sessionManager) { Promise.resolve() .then(() => this.sessionManager!.cleanupOldSessions()) .catch((error) => { this.logger.warn('Session cleanup failed (best-effort)', { requestId, error: error instanceof Error ? error.message : String(error), }) }) } try { // Validate parameters with enhanced validation const validatedParams = this.validateParams(params) // Auto-generate session_id if not provided and SessionManager is available const sessionId = validatedParams.session_id || (this.sessionManager ? randomUUID() : undefined) this.logger.debug('Parameters validated successfully', { requestId, agent: validatedParams.agent, promptLength: validatedParams.prompt.length, cwd: validatedParams.cwd, extraArgsCount: validatedParams.extra_args?.length || 0, sessionId: sessionId, sessionIdGenerated: !validatedParams.session_id && !!sessionId, }) // Check if agent exists if (this.agentManager) { const agent = await this.agentManager.getAgent(validatedParams.agent) if (!agent) { this.logger.warn('Agent not found', { requestId, requestedAgent: validatedParams.agent, }) return this.createErrorResponse( `Agent '${validatedParams.agent}' not found`, await this.getAvailableAgentsList() ) } this.logger.debug('Agent found and validated', { requestId, agentName: agent.name, agentDescription: agent.description, }) } // Execute agent if executor is available if (this.agentExecutor) { // Report progress: Starting agent execution // Get agent definition content if available let agentContext = validatedParams.agent if (this.agentManager) { const agent = await this.agentManager.getAgent(validatedParams.agent) if (agent?.content) { // Include full agent definition content as system context agentContext = agent.content } } // Load session history if session_id is provided and SessionManager is available let promptWithHistory = validatedParams.prompt if (sessionId && this.sessionManager) { try { // CRITICAL: Pass agent_type to enforce sub-agent isolation const sessionData = await this.sessionManager.loadSession( sessionId, validatedParams.agent ) if (sessionData && sessionData.history.length > 0) { // Convert session history to Markdown format for token efficiency and LLM comprehension const historyMarkdown = formatSessionHistory(sessionData) promptWithHistory = `Previous conversation history:\n\n${historyMarkdown}\n\n---\n\nCurrent request:\n${validatedParams.prompt}` this.logger.info('Session history loaded and merged', { requestId, sessionId: sessionId, historyEntries: sessionData.history.length, }) } else { this.logger.debug('No session history found', { requestId, sessionId: sessionId, }) } } catch (error) { // Log error but continue - session loading failure should not break main flow this.logger.warn('Failed to load session history', { requestId, sessionId: sessionId, error: error instanceof Error ? error.message : String(error), }) } } const executionParams: ExecutionParams = { agent: agentContext, prompt: promptWithHistory, ...(validatedParams.cwd !== undefined && { cwd: validatedParams.cwd }), ...(validatedParams.extra_args !== undefined && { extra_args: validatedParams.extra_args, }), } // Report progress: Executing agent // Execute agent (this has its own timeout: MCP -> AI) const result = await this.agentExecutor.executeAgent(executionParams) // Report progress: Execution completed // Update execution statistics this.updateExecutionStats(validatedParams.agent, result.executionTime) this.logger.info('Agent execution completed successfully', { requestId, agent: validatedParams.agent, exitCode: result.exitCode, executionTime: result.executionTime, totalTime: Date.now() - startTime, }) // Save session if session_id is available and SessionManager is available if (sessionId && this.sessionManager) { try { // Build request object with only defined properties const sessionRequest: { agent: string prompt: string cwd?: string extra_args?: string[] } = { agent: validatedParams.agent, prompt: validatedParams.prompt, } if (validatedParams.cwd !== undefined) { sessionRequest.cwd = validatedParams.cwd } if (validatedParams.extra_args !== undefined) { sessionRequest.extra_args = validatedParams.extra_args } await this.sessionManager.saveSession(sessionId, sessionRequest, { stdout: result.stdout, stderr: result.stderr, exitCode: result.exitCode, executionTime: result.executionTime, }) this.logger.info('Session saved successfully', { requestId, sessionId: sessionId, }) } catch (error) { // Log error but continue - session save failure should not break main flow this.logger.warn('Failed to save session', { requestId, sessionId: sessionId, error: error instanceof Error ? error.message : String(error), }) } } // Mark MCP request as completed return this.formatExecutionResponse(result, validatedParams.agent, requestId, sessionId) } // Fallback response if executor is not available this.logger.warn('Agent executor not available', { requestId }) return { content: [ { type: 'text', text: `Agent execution request received for '${validatedParams.agent}' with prompt: "${validatedParams.prompt}"\n\nNote: Agent executor not initialized.`, }, ], } } catch (error) { const totalTime = Date.now() - startTime this.logger.error('Agent execution failed', error instanceof Error ? error : undefined, { requestId, totalTime, errorType: error instanceof Error ? error.constructor.name : 'Unknown', }) return this.createErrorResponse( `Agent execution failed: ${error instanceof Error ? error.message : 'Unknown error'}`, null ) } }
- src/tools/RunAgentTool.ts:117-145 (schema)The inputSchema property defines the JSON schema for the run_agent tool parameters, including required fields (agent, prompt) and optional fields (cwd, extra_args, session_id).public readonly inputSchema: RunAgentInputSchema = { type: 'object', properties: { agent: { type: 'string', description: 'Identifier of the specialized agent to delegate the task to', }, prompt: { type: 'string', description: 'Task description or instructions for the agent to execute. When referencing file paths, use absolute paths to ensure proper file access.', }, cwd: { type: 'string', description: 'Working directory path for agent execution context (optional)', }, extra_args: { type: 'array', items: { type: 'string' }, description: 'Additional configuration parameters for agent execution (optional)', }, session_id: { type: 'string', description: 'Session ID for continuing previous conversation context (optional). If omitted, a new session will be auto-generated and returned in response metadata. Reuse the returned session_id in subsequent calls to maintain context continuity.', }, }, required: ['agent', 'prompt'], }
- src/server/McpServer.ts:105-106 (registration)Instantiation of RunAgentTool in McpServer constructor, passing dependencies (AgentExecutor, AgentManager, SessionManager).this.runAgentTool = new RunAgentTool(this.agentExecutor, this.agentManager, this.sessionManager) this.agentResources = new AgentResources(this.agentManager)
- src/server/McpServer.ts:196-212 (registration)Registration in list_tools handler: returns the run_agent tool definition (name, description, inputSchema).const result: ListToolsResult = { tools: [ { name: this.runAgentTool.name, description: this.runAgentTool.description, inputSchema: this.runAgentTool.inputSchema, }, ], } this.log('debug', 'List tools request completed', { responseTime: Date.now() - startTime, toolCount: result.tools.length, }) return result } catch (error) {
- src/server/McpServer.ts:230-240 (registration)Dispatch in call_tool handler: executes runAgentTool.execute when tool name is 'run_agent'.if (params.name === 'run_agent') { const result = await this.runAgentTool.execute(params.arguments) this.log('info', 'Tool execution completed', { tool: params.name, responseTime: Date.now() - startTime, success: true, }) return result as CallToolResult }