Skip to main content
Glama

run_agent

Delegate complex multi-step tasks to specialized autonomous agents for independent execution with dedicated context, maintaining conversation continuity across sessions.

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). Returns session_id in response metadata - reuse it in subsequent calls to maintain conversation context continuity across multiple agent executions.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
agentYesAgent name exactly as listed in list_agents resource.
promptYesUser's direct request content. Agent context is separately provided via agent parameter.
cwdYesWorking directory path for agent execution context. Must be an absolute path to a valid directory.
extra_argsNoAdditional configuration parameters for agent execution (optional)
session_idNoSession 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.

Implementation Reference

  • The `execute` method is the main handler that performs parameter validation, agent lookup, execution via AgentExecutor, session management, and formats the MCP-compliant response. It handles errors gracefully and provides structured logging.
    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 and load agent definition once
        let agentDefinition: AgentDefinition | undefined
        if (this.agentManager) {
          agentDefinition = await this.agentManager.getAgent(validatedParams.agent)
          if (!agentDefinition) {
            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: agentDefinition.name,
            agentDescription: agentDefinition.description,
          })
        }
    
        // Execute agent if executor is available
        if (this.agentExecutor) {
          // Report progress: Starting agent execution
    
          // Use agent definition content if available (already loaded above)
          const agentContext = agentDefinition?.content ?? validatedParams.agent
    
          // 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
        )
      }
    }
  • Defines the input schema for the run_agent tool, specifying required parameters (agent, prompt, cwd) and optional ones (extra_args, session_id) with descriptions.
    public readonly inputSchema: RunAgentInputSchema = {
      type: 'object',
      properties: {
        agent: {
          type: 'string',
          description: 'Agent name exactly as listed in list_agents resource.',
        },
        prompt: {
          type: 'string',
          description:
            "User's direct request content. Agent context is separately provided via agent parameter.",
        },
        cwd: {
          type: 'string',
          description:
            'Working directory path for agent execution context. Must be an absolute path to a valid directory.',
        },
        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', 'cwd'],
    }
  • Registers the run_agent tool in the MCP server's list_tools handler by including its name, description, and inputSchema in the returned tools list.
    tools: [
      {
        name: this.runAgentTool.name,
        description: this.runAgentTool.description,
        inputSchema: this.runAgentTool.inputSchema,
      },
  • Dispatches calls to the run_agent tool in the MCP server's call_tool handler by checking the tool name and invoking the RunAgentTool's execute method.
    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
    }
  • Instantiates the RunAgentTool instance in the McpServer constructor, injecting required dependencies for agent execution and management.
    this.runAgentTool = new RunAgentTool(this.agentExecutor, this.agentManager, this.sessionManager)
Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/shinpr/sub-agents-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server