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)
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden and does well by disclosing key behavioral traits: it's a delegation tool that returns a session_id for maintaining conversation context across executions, and it handles autonomous agent execution. It doesn't mention permissions, rate limits, or error handling, but covers the core operation and continuity mechanism adequately for a tool without annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is appropriately sized and front-loaded, starting with the core purpose and examples, then detailing the session_id mechanism. Every sentence adds value, but it could be slightly more streamlined by integrating the session_id explanation more tightly with the initial delegation concept.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (delegation to autonomous agents) and lack of annotations and output schema, the description is moderately complete. It covers the purpose, usage context, and behavioral aspects like session_id, but doesn't explain return values beyond session_id or potential errors, leaving gaps in full contextual understanding for an agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description adds some meaning beyond the schema by explaining the purpose of session_id for context continuity, but it doesn't detail the semantics of other parameters like agent, prompt, cwd, or extra_args. With 100% schema description coverage, the baseline is 3, and the description provides marginal value by clarifying session_id usage without fully compensating for lack of deeper param insights.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose with specific verbs ('delegate', 'returns session_id') and resources ('autonomous agent', 'complex multi-step tasks'), providing concrete examples like refactoring across multiple files and fixing test failures. It distinguishes this as a delegation tool for specialized execution, which is unambiguous even without sibling tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states when to use this tool: for 'complex, multi-step, or specialized tasks' with examples like refactoring and batch operations. It provides guidance on context continuity via session_id reuse. However, it lacks explicit exclusions or alternatives (e.g., when not to use it), and with no sibling tools, this is less critical but still a minor gap.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

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