Lesson 12 | Agent Collaboration: Multi-Agent Communication & Delegation

20 MIN READ | UPDATED: 2026-05-07

title: "Lesson 12 | Agent Collaboration: Multi-Agent Communication & Delegation" summary: "Explore Hermes' multi-agent collaboration patterns—agent-to-agent communication protocols, task delegation mechanisms, and how to build a 'team' of multiple specialized agents." sortOrder: 120 status: "published"

Explore Hermes' multi-agent collaboration patterns—agent-to-agent communication protocols, task delegation mechanisms, and how to build a "team" of multiple specialized agents.


🎯 Learning Objectives

  • Understand the importance and core advantages of multi-agent collaboration in solving complex problems.
  • Master the basic mechanisms and design patterns for communication and task delegation between Hermes Agents.
  • Learn how to build a team of specialized Agents by defining their roles (Persona) and capabilities (Skills).
  • Practice setting up a simple multi-agent workflow to achieve task decomposition, execution, and result aggregation.

📖 Core Concepts Explained

12.1 Why Agent Collaboration?

In complex real-world scenarios, a single AI Agent often faces numerous limitations. These limitations include, but are not limited to: restricted knowledge breadth, insufficient domain-specific expertise, limited context window length, and efficiency bottlenecks when handling multi-step, multi-modal tasks. To overcome these challenges, drawing inspiration from human team collaboration, introducing multi-agent collaboration has become a natural solution.

Limitations of a Single Agent: Imagine a task that requires designing, developing, and testing a new software product. If there's only one Agent, it would need the requirements analysis capabilities of a product manager, the coding and architectural skills of a software engineer, and the quality assurance expertise of a test engineer. This not only places extremely high demands on a single Agent's capabilities but also easily leads to generalized knowledge and low efficiency. More importantly, even the most powerful Large Language Models (LLMs) have finite context windows, making it difficult to encompass all task details, historical records, and various specialized knowledge within a single conversation.

Advantages of Multi-Agent Collaboration: The core idea of multi-agent collaboration is to decompose a complex overall task into multiple smaller, more specialized subtasks, and then delegate these subtasks to different Agents, each with specific roles and capabilities, for parallel or sequential processing. This pattern brings significant advantages:

  1. Specialization and Efficiency Improvement: Each Agent can be trained or configured as an expert in a specific domain (revisit the concept of custom Persona in Lesson 11). For example, a "Code Generator Agent" focuses on writing high-quality code, while a "Test Agent" focuses on finding potential defects. This division of labor allows each Agent to maximize its effectiveness in its area of expertise, thereby improving the overall efficiency and quality of task completion.
  2. Overcoming Context Limitations: Complex tasks often require a large amount of contextual information. By decomposing tasks, each sub-Agent only needs to focus on the context relevant to its own task, effectively avoiding the problem of context overflow for a single Agent and improving LLM utilization efficiency.
  3. Task Decomposition and Robustness: Complex tasks can be broken down into manageable modules, reducing the risk of overall task failure. If a sub-Agent encounters difficulties, the Orchestrator Agent can attempt to re-delegate, provide more information, or seek help from other Agents, enhancing system robustness.
  4. Simulating Human Team Collaboration: This pattern closely mimics how human teams work, such as a project team comprising product managers, designers, developers, and testers. Each role assumes specific responsibilities and collaborates through communication to complete the project. This enables AI Agent systems to handle more complex, real-world problems.

Hermes Agent, as an evolving AI agent, its modular design and powerful Skills system (Lesson 3) as well as Persona definition capabilities (Lesson 11), naturally provide a solid foundation for multi-agent collaboration. Through these mechanisms, we can configure unique identities, specialized knowledge, and callable tools (MCP tool ecosystem, Lesson 6) for different Hermes Agents, enabling them to work together like a well-trained team of experts.

12.2 Hermes Agent Communication Mechanisms

In the Hermes Agent collaboration framework, inter-agent communication is key to achieving task delegation and information sharing. While Hermes does not have an explicit "inter-agent message queue" or "publish/subscribe" system, we can leverage its existing features cleverly to build efficient communication mechanisms. The core idea is to allow one Agent to trigger another Agent's behavior or share necessary information.

1. Skill-Based Communication and Delegation: This is the most aligned communication method with the Hermes Agent design philosophy. We can encapsulate an Agent's core capabilities into one or more Skills (or integrate them as tools via MCP) for other Agents to call.

  • Scenario: Agent A (Orchestrator Agent) needs Agent B (Specialized Agent) to complete a specific task.
  • Implementation: Agent B can expose a Skill like execute_task or process_data. Agent A, during its reasoning process, identifies the need for Agent B's capability and then calls use_tool('agent_b_skill_name', args={'task_description': '...' }).
  • Advantages: Highly modular, clear capability boundaries, conforms to the tool-calling paradigm.
  • Example Skill Pseudocode:
    # agent_b_skills.py
    from hermes_agent.skills import Skill
    
    class AgentBSkill(Skill):
        name = "agent_b_task_processor"
        description = "Processes specific tasks that Agent B excels at, such as data analysis or code generation."
        parameters = {
            "type": "object",
            "properties": {
                "task_description": {
                    "type": "string",
                    "description": "A detailed description of the task Agent B needs to process."
                },
                "input_data": {
                    "type": "string",
                    "description": "Input data that the task might require, can be JSON or text."
                }
            },
            "required": ["task_description"]
        }
    
        def execute(self, task_description: str, input_data: str = None) -> str:
            # This can trigger Agent B's internal logic, or directly call Agent B's run interface
            # Assuming Agent B is already configured, we can start it in some way and pass the task
            # Actual implementation might involve calling hermes run command or an internal API
            print(f"Agent B received task: {task_description}")
            print(f"Input data: {input_data}")
            
            # Simulate Agent B processing the task
            result = f"Agent B has completed task: '{task_description}'. Processing result: [Simulated result based on input data]"
            return result
    
    # In Agent A's configuration file, AgentBSkill can be registered as an available tool.
    
    The Orchestrator Agent A's reasoning process will guide it to call this Skill when needed.

2. File System/Shared Context-Based Communication: Agents can pass information by sharing a working directory or specific files. One Agent writes its task results to a file, and another Agent reads that file as its input.

  • Scenario: Agent A generates a report, and Agent B needs to analyze that report.
  • Implementation: Agent A saves the report to the context_files directory (revisit Lesson 8), and Agent B is instructed to read that file at the start of its task.
  • Advantages: Simple and direct, suitable for structured or unstructured data transfer.
  • Disadvantages: Requires coordination of file naming and paths, potential concurrency issues.

3. Orchestrator Agent-Based Indirect Communication: In this mode, all communication between Agents is relayed through an Orchestrator Agent. The Orchestrator Agent receives user requests, decomposes tasks, delegates them to sub-Agents, and collects the results from sub-Agents for aggregation.

  • Scenario: A user submits a complex request to the Orchestrator Agent.
  • Implementation: The Orchestrator Agent uses its LLM-driven reasoning capabilities to break down the request, generate an independent Prompt for each sub-Agent, and then runs each sub-Agent sequentially. The output of the sub-Agent serves as input for the Orchestrator Agent's next step of reasoning.
  • Advantages: Easy to understand and implement, the Orchestrator Agent has a global view.
  • Disadvantages: The Orchestrator Agent can become a bottleneck, increasing the number of LLM calls.

ASCII Diagram: Orchestrator Agent-Based Communication Flow

User
  ↓
[ Orchestrator Agent ]
  ├─── Task Decomposition & Delegation
  │      ↓                 ↓                 ↓
  │ [ Sub Agent A ]       [ Sub Agent B ]       [ Sub Agent C ]
  │      ↓                 ↓                 ↓
  ├─── Result Collection & Aggregation
  ↓
User (Final Result)

Mermaid Flowchart Example: Skill-Based Agent Collaboration

graph TD
    A[User Request] --> B{Orchestrator Agent Receives Request};
    B --> C{Identify Task Type};
    C -- Complex Task --> D{Task Decomposition};
    D --> E[Generate Subtask for Agent A];
    D --> F[Generate Subtask for Agent B];
    E --> G{Orchestrator Agent Calls AgentA_Skill};
    F --> H{Orchestrator Agent Calls AgentB_Skill};
    G --> I[Agent A Executes Task & Returns Result];
    H --> J[Agent B Executes Task & Returns Result];
    I --> K{Orchestrator Agent Aggregates Results};
    J --> K;
    K --> L[Generate Final Response];
    L --> M[Return to User];

In practice, we typically combine these mechanisms. For example, the Orchestrator Agent, through its Persona, possesses task decomposition capabilities, then uses predefined Skills to call specific specialized Agents, and these specialized Agents may read and write shared files to pass intermediate data.

12.3 Task Delegation and Role Definition

Successful multi-agent collaboration relies on clear task delegation strategies and well-defined roles. Each Agent should have a unique identity (Persona) and a set of capabilities (Skills) that match its responsibilities.

1. Importance of Persona: Recalling Lesson 11, Persona is the "soul" of an Agent, defining its background, goals, behavior patterns, areas of expertise, and tone. In multi-agent collaboration, defining a unique, professional Persona for each Agent is crucial.

  • Examples:
    • Project Manager Agent (ProjectManagerAgent): Persona description might include: "You are an experienced project manager, skilled in task decomposition, progress tracking, and team coordination. Your primary goal is to break down complex project requirements into executable subtasks, delegate them to appropriate team members (other Agents), then collect their deliverables and summarize them."
    • Code Generator Agent (CodeGeneratorAgent): Persona description might include: "You are a senior software engineer, proficient in multiple programming languages like Python and JavaScript, and skilled at generating high-quality, runnable code based on requirement documents. You focus on writing code and are not responsible for requirements analysis or testing."
    • Test Engineer Agent (TestEngineerAgent): Persona description might include: "You are a meticulous test engineer, skilled in writing test cases, executing tests, and reporting defects. Your goal is to ensure software quality and discover potential issues."

Through these Personas, LLM-driven Agents can better understand their position and responsibilities within the team, thereby making decisions and behaviors that are more aligned with expectations.

2. Task Delegation Strategy:

  • Orchestrator Agent:

    • Responsibilities: Receives initial user requests, analyzes and understands the task.
    • Core Capabilities: Task Decomposition, breaking down complex tasks into multiple interrelated subtasks.
    • Delegation Decisions: Determines which specialized Agent is best suited to handle a subtask based on its nature. This is typically achieved through the Orchestrator Agent's reasoning capabilities and its "awareness" of other Agents' capabilities.
    • Progress Management: Tracks the execution status of subtasks.
    • Result Aggregation: Collects outputs from all sub-Agents, integrates and refines them, and generates the final response.
    • Error Handling: When a sub-Agent fails, the Orchestrator Agent can detect it and attempt to re-delegate, provide additional information, or seek alternative solutions.
  • Specialized Agent:

    • Responsibilities: Receives specific subtasks delegated by the Orchestrator Agent, and completes them using its specialized knowledge and Skills.
    • Core Capabilities: Domain-specific expertise, execution of specific Skills (e.g., calling external APIs, executing code, accessing databases).
    • Feedback Mechanism: Clearly returns task execution results (including success or failure information) to the Orchestrator Agent.

3. Workflow Design and Orchestration: Multi-agent collaboration workflows can be implemented in two main ways:

  • Dynamic Orchestration Based on Prompt Engineering: The Orchestrator Agent's Persona and system Prompt are carefully designed to allow it to dynamically decide how to decompose tasks, which Agent to call, and how to process results during its reasoning process. This approach offers high flexibility but requires sophisticated Prompt design.
  • Structured Orchestration Based on Predefined Skills: We can create specialized Skills for Hermes Agents, where the execute method of these Skills contains the logic for calling other Agents or executing specific workflows. For example, a Skill named project_workflow_skill might sequentially call code_generator_skill and test_engineer_skill. This approach is more structured and suitable for repetitive tasks with fixed processes.

Configuration Example: Defining Multiple Agents and Their Associated Personas and Skills

Suppose we have three Agents: project_manager, code_generator, and tester.

First, ensure each Agent has its own configuration file. For example, create project_manager.yaml, code_generator.yaml, tester.yaml in the ~/.hermes/agents/ directory.

~/.hermes/agents/project_manager.yaml

name: project_manager
description: "An Agent responsible for project management, task decomposition, and coordinating other Agents."
persona: |
  You are an experienced project manager, skilled at breaking down complex project requirements into executable subtasks,
  and delegating them to appropriate expert Agents. You track task progress and aggregate the results from all Agents,
  ultimately providing a complete solution to the user. Your goal is to ensure projects run smoothly and are completed with high quality.
llm_model: openrouter/mistralai/mistral-large
llm_provider: openrouter
skills:
  - name: code_generator_skill # The Orchestrator Agent knows how to call the code generator
    description: "Calls the Code Generator Agent to generate code. Requires a detailed description of requirements and programming language."
    parameters:
      type: object
      properties:
        requirements:
          type: string
          description: "Detailed functional requirements for the code."
        language:
          type: string
          description: "The programming language for code generation, e.g., 'python' or 'javascript'."
      required:
        - requirements
        - language
    # The execute method here will simulate calling the CodeGeneratorAgent
    # In a real scenario, this might be implemented via an internal API or by running another hermes command
    execute: |
      import subprocess
      import json
      
      requirements = args['requirements']
      language = args['language']
      
      print(f"Project Manager is delegating code generation task to CodeGeneratorAgent...")
      
      # Simulate calling CodeGeneratorAgent.
      # The actual implementation might be more complex, e.g., through a shared service or more advanced inter-process communication.
      # Here we simulate by running a shell command, which requires CodeGeneratorAgent to be able to receive command-line arguments.
      # A better approach is for CodeGeneratorAgent to expose an internal API or an MCP tool.
      
      # For simplicity, we assume CodeGeneratorAgent can run itself and receive a prompt
      # An actual Skill might look like this:
      # command = f"hermes run code_generator --prompt \"Please generate {language} code based on the following requirements: {requirements}\""
      # result = subprocess.run(command, shell=True, capture_output=True, text=True)
      # return result.stdout + result.stderr

      # A more consistent way with Skill encapsulation is for CodeGeneratorAgent itself to have a Skill,
      # and ProjectManagerAgent calls this Skill of CodeGeneratorAgent.
      # For now, we'll return a simulated result; it will be more concrete in the hands-on demo.
      
      return f"CodeGeneratorAgent has received the task: Generate code for '{language}', requirements: '{requirements}'. Awaiting result..."
  - name: test_engineer_skill # The Orchestrator Agent knows how to call the test engineer
    description: "Calls the Test Engineer Agent to test code. Requires code content and testing requirements."
    parameters:
      type: object
      properties:
        code:
          type: string
          description: "The code content to be tested."
        test_requirements:
          type: string
          description: "Specific testing requirements, such as testing boundary conditions, error handling, etc."
      required:
        - code
        - test_requirements
    execute: |
      # Similar implementation to code_generator_skill
      code = args['code']
      test_requirements = args['test_requirements']
      print(f"Project Manager is delegating testing task to TestEngineerAgent...")
      return f"TestEngineerAgent has received the task: Test code. Testing requirements: '{test_requirements}'. Awaiting result..."

~/.hermes/agents/code_generator.yaml

name: code_generator
description: "An Agent specifically responsible for generating code based on requirements."
persona: |
  You are a senior software engineer, proficient in multiple programming languages like Python and JavaScript,
  and skilled at generating high-quality, runnable code based on detailed requirement documents.
  You focus on writing code and are not responsible for requirements analysis or testing.
llm_model: openrouter/mistralai/mixtral-8x7b-instruct # Can choose a model more suitable for code generation
llm_provider: openrouter
# code_generator can also have its own Skills, such as run_code, debug_code, etc.
skills:
  - name: generate_code
    description: "Generates code based on given requirements and language."
    parameters:
      type: object
      properties:
        requirements:
          type: string
          description: "Functional requirements description for the code."
        language:
          type: string
          description: "Programming language."
      required:
        - requirements
        - language
    execute: |
      # The execute method here will directly call the LLM's capability to generate code
      # In actual operation, this Agent will directly receive a Prompt and generate code
      requirements = args['requirements']
      language = args['language']
      return f"```python\n# This is simulated {language} code to meet the requirements: {requirements}\ndef hello_world():\n    print('Hello from CodeGeneratorAgent!')\n```"

~/.hermes/agents/tester.yaml

name: tester
description: "An Agent specifically responsible for testing code and reporting issues."
persona: |
  You are a meticulous test engineer, skilled in writing test cases, executing tests, and reporting defects.
  Your goal is to ensure software quality, discover potential issues, and provide detailed test reports.
llm_model: openrouter/mistralai/mistral-large
llm_provider: openrouter
skills:
  - name: analyze_and_test_code
    description: "Receives code and testing requirements, then generates test cases and analyzes code quality."
    parameters:
      type: object
      properties:
        code_content:
          type: string
          description: "The code content to be tested."
        test_instructions:
          type: string
          description: "Specific testing instructions and expectations."
      required:
        - code_content
        - test_instructions
    execute: |
      code = args['code_content']
      instructions = args['test_instructions']
      
      # Simulate testing process
      report = f"Testing the code...\n"
      report += f"Test instructions: {instructions}\n"
      report += f"Code content:\n{code}\n"
      report += f"--- Test Report ---\n"
      report += f"Potential issues found: None (simulated)\n"
      report += f"Suggested improvements: Add more edge test cases.\n"
      report += f"Test passed: Yes."
      return report

In this way, the project_manager Agent "knows" how to interact with the code_generator and tester Agents through Skills. The actual Skill implementation needs to be able to truly trigger the execution of other Agents or call their internal functions, which typically involves Hermes' internal AgentManager or calling hermes run <agent_name> ... via external commands. In the upcoming hands-on demo, we will show more concretely how to implement this cross-agent calling.

12.4 Practical Considerations for Building a Multi-Agent Team

When designing and implementing a multi-agent collaboration system, in addition to communication and delegation mechanisms, several important practical issues need to be considered to ensure system stability, efficiency, and maintainability.

1. Agent Discovery and Capability Registration: How does an Orchestrator Agent know which specialized Agents exist and what capabilities each possesses?

  • Explicit Configuration: The most direct way is to explicitly define the names of other Agents it can call and their provided Skills in the Orchestrator Agent's configuration file or its available Skills (as in code_generator_skill and test_engineer_skill in project_manager.yaml above).
  • Shared Registry (Future Possibility): More advanced systems might have a shared Agent registry where Agents register their capabilities upon startup, and other Agents can query it. Currently in Hermes, this is primarily achieved through configuration and Skill definitions.

2. Error Handling and Retry Mechanisms: In distributed or multi-agent systems, a sub-Agent failing is common. The Orchestrator Agent must be capable of handling these failures:

  • Error Capture: When a sub-Agent returns an error or an unexpected result, the Orchestrator Agent needs to be able to capture this information.
  • Retry Strategy: For transient errors, the Orchestrator Agent can attempt to retry the subtask.
  • Alternative Solutions: If a sub-Agent consistently fails, can the Orchestrator Agent delegate the task to another Agent with similar capabilities, or take other remedial measures?
  • User Feedback: Provide clear error messages to the user when a problem cannot be resolved.

3. Context Management and Information Transfer: How to efficiently and accurately transfer necessary information between Agents, while avoiding redundancy and context overflow?

  • Streamlined Input: The input received by each sub-Agent should only contain the minimum information required to complete its task, avoiding irrelevant distractions.
  • Structured Data: Whenever possible, use structured data formats like JSON or YAML for information transfer, making it easier to parse and process.
  • Shared Workspace: Utilize the context_files directory (Lesson 8) as a shared storage area for transferring large files or intermediate results.
  • History Logging: The Orchestrator Agent needs to maintain the session history of the entire task (Lesson 4) to provide to sub-Agents or for summarization when necessary.

4. Performance and Cost Optimization: Multi-agent collaboration implies more LLM calls, which directly impacts system response speed and operational costs.

  • LLM Model Selection: Choose appropriate LLM models for different Agents based on task complexity and importance (Lesson 2). For example, the Orchestrator Agent might require a more powerful reasoning model, while some specialized Agents can use smaller, faster models.
  • Parallel Processing: If subtasks have no strong dependencies, consider executing them in parallel to shorten the total task time.
  • Caching Mechanism: For repetitive queries or calculation results, consider introducing caching.
  • Token Economics: Carefully design Prompts to avoid unnecessary redundant information and reduce token consumption (Lesson 16).

5. Observability and Debugging: Tracking inter-agent interactions, task progress, and potential issues is crucial for debugging and optimizing the system.

  • Detailed Logging: Configure detailed logging (Lesson 17) to record each Agent's decisions, inputs, outputs, and tool calls.
  • Task Status Monitoring: Establish mechanisms to monitor the current status of each subtask, such as "pending," "in progress," "completed," "failed."
  • Visualization Tools (Future Possibility): More advanced systems might provide visual interfaces to display inter-agent communication flows and task dependency graphs.

By carefully considering these practical factors, we can build more robust, efficient, and manageable multi-agent collaboration systems to address increasingly complex AI application scenarios.


💻 Hands-on Demo

In this hands-on demo, we will build a simplified multi-agent team: a project_manager Agent responsible for receiving user requirements and delegating tasks, and a code_generator Agent responsible for generating code. We will demonstrate how the project_manager triggers the code_generator Agent to perform a task by calling a custom Skill.

Prerequisites:

  • Hermes Agent installed (refer to Lesson 1).
  • OpenRouter or another LLM Provider configured (refer to Lesson 2).
  • Ensure the ~/.hermes/agents/ directory exists.

Scenario 1: Creating and Configuring the Agent Team

We will create configuration files for two Agents: project_manager and code_generator.

Step 1: Create the project_manager Agent configuration file ~/.hermes/agents/project_manager.yaml

We will define a Skill named delegate_code_generation for the project_manager Agent. The execute method of this Skill will simulate calling the code_generator Agent.

# ~/.hermes/agents/project_manager.yaml
name: project_manager
description: "An Agent responsible for project management, task decomposition, and coordinating other Agents."
persona: |
  You are an experienced project manager, skilled at breaking down complex project requirements into executable subtasks,
  and delegating them to appropriate expert Agents. You track task progress and aggregate the results from all Agents,
  ultimately providing a complete solution to the user. Your goal is to ensure projects run smoothly and are completed with high quality.
llm_model: openrouter/mistralai/mistral-large # Recommended to use a more capable model as the Orchestrator Agent
llm_provider: openrouter
skills:
  - name: delegate_code_generation
    description: "Delegates a code generation task to the CodeGeneratorAgent. Requires a detailed description of requirements and programming language."
    parameters:
      type: object
      properties:
        requirements:
          type: string
          description: "Detailed functional requirements for the code."
        language:
          type: string
          description: "The programming language for code generation, e.g., 'python' or 'javascript'."
      required:
        - requirements
        - language
    execute: |
      import subprocess
      import json
      import os

      requirements = args['requirements']
      language = args['language']
      
      # Construct the command to call CodeGeneratorAgent
      # We assume CodeGeneratorAgent is set up and can be called directly via the hermes run command
      # To ensure CodeGeneratorAgent receives structured tasks, we package the requirements as a JSON string
      task_payload = json.dumps({"requirements": requirements, "language": language})
      
      # Note: The `hermes run` here is a blocking call; actual production environments might require asynchronous handling
      # For demonstration purposes, we directly run a subprocess
      
      # Get the path to the hermes command, ensuring it can be found
      hermes_bin = os.environ.get("HERMES_CLI_PATH", "hermes") # Assume hermes is in PATH or specified by environment variable
      
      command = [
          hermes_bin, 'run', 'code_generator',
          '--prompt', f"Please generate code based on the following JSON-formatted task: {task_payload}",
          '--no-interaction' # Ensure the sub-Agent does not wait for user input
      ]
      
      print(f"\n[ProjectManager] Delegating task to CodeGeneratorAgent...")
      try:
          # Use subprocess.run to execute the command and capture output
          result = subprocess.run(command, capture_output=True, text=True, check=True)
          code_output = result.stdout.strip()
          error_output = result.stderr.strip()
          
          if error_output:
              print(f"[CodeGeneratorAgent] Error output:\n{error_output}")
              return f"CodeGeneratorAgent execution failed: {error_output}"
          
          print(f"\n[ProjectManager] Received response from CodeGeneratorAgent:\n{code_output}")
          return f"CodeGeneratorAgent has completed the code generation task. Code is as follows:\n{code_output}"
      except subprocess.CalledProcessError as e:
          print(f"[ProjectManager] Failed to call CodeGeneratorAgent: {e}")
          print(f"STDOUT: {e.stdout}")
          print(f"STDERR: {e.stderr}")
          return f"Failed to call CodeGeneratorAgent: {e.stderr}"
      except FileNotFoundError:
          return "Error: 'hermes' command not found. Please ensure Hermes CLI is correctly installed and configured in PATH."

Step 2: Create the code_generator Agent configuration file ~/.hermes/agents/code_generator.yaml

The code_generator Agent's persona will guide it to focus on code generation. Its main task is to receive a Prompt and generate code.

# ~/.hermes/agents/code_generator.yaml
name: code_generator
description: "An Agent specifically responsible for generating code based on requirements."
persona: |
  You are a senior software engineer, proficient in multiple programming languages like Python and JavaScript,
  and skilled at generating high-quality, runnable code based on detailed requirement documents or JSON-formatted task descriptions.
  You focus on writing code and are not responsible for requirements analysis or testing. You will directly return complete code blocks,
  without additional explanations or dialogue. If the input is JSON, please parse it to extract the requirements.
llm_model: openrouter/mistralai/mixtral-8x7b-instruct # Can choose a model more suitable for code generation
llm_provider: openrouter
# code_generator does not currently need additional Skills, as it primarily responds to Prompts using its LLM capabilities

Step 3: Initialize Agent Configuration

Use the hermes setup command to ensure Hermes recognizes these Agents.

hermes setup

Expected Output: Hermes will scan the ~/.hermes/agents/ directory and load the configurations. If everything is normal, there won't be much output, or it will show messages indicating successful Agent loading.

Scenario 2: Task Decomposition-Based Agent Collaboration

Now we will have the project_manager Agent receive a complex task, and it will use its delegate_code_generation Skill to delegate the code generation part to the code_generator Agent.

Step 1: Interact with the project_manager Agent

We will start the project_manager Agent using the hermes run command and give it a task.

hermes run project_manager --prompt "I need a Python function to calculate the sum of all even numbers in a list. Please write this function."

Expected Output (simplified, actual output will be more detailed):

The Orchestrator Agent's (project_manager) reasoning process will guide it to use the delegate_code_generation Skill.

[ProjectManager] Thinking...
[ProjectManager] I received a task to write a Python function. This falls under code generation, so I need to delegate it to the CodeGeneratorAgent.
[ProjectManager] Calling delegate_code_generation Skill...
[ProjectManager] Delegating task to CodeGeneratorAgent...

# The output of CodeGeneratorAgent will be displayed here, as it runs in a subprocess
# CodeGeneratorAgent might output its thought process, then generate code
[CodeGeneratorAgent] Thinking... Received task: {"requirements": "calculate the sum of all even numbers in a list", "language": "python"}
[CodeGeneratorAgent] Generating Python code...
[CodeGeneratorAgent] Response:
```python
def sum_even_numbers(numbers):
    """
    Calculates the sum of all even numbers in a list.

    Args:
        numbers (list): A list containing integers.

    Returns:
        int: The sum of all even numbers in the list.
    """
    total = 0
    for num in numbers:
        if num % 2 == 0:
            total += num
    return total

# Example usage:
# my_list = [1, 2, 3, 4, 5, 6]
# result = sum_even_numbers(my_list)
# print(f"The sum of even numbers in the list is: {result}") # Output: The sum of even numbers in the list is: 12

[ProjectManager] Received response from CodeGeneratorAgent: CodeGeneratorAgent has completed the code generation task. Code is as follows:

def sum_even_numbers(numbers):
    """
    Calculates the sum of all even numbers in a list.

    Args:
        numbers (list): A list containing integers.

    Returns:
        int: The sum of all even numbers in the list.
    """
    total = 0
    for num in numbers:
        if num % 2 == 0:
            total += num
    return total

# Example usage:
# my_list = [1, 2, 3, 4, 5, 6]
# result = sum_even_numbers(my_list)
# print(f"The sum of even numbers in the list is: {result}") # Output: The sum of even numbers in the list is: 12

Explanation:

  1. The user presented a code generation requirement to the project_manager Agent.
  2. Upon receiving the Prompt, the project_manager Agent's internal LLM, combined with its Persona (project manager, skilled in delegation) and available Skills (delegate_code_generation), performs reasoning.
  3. It determines this is a code generation task and decides to call the delegate_code_generation Skill.
  4. The execute method of the delegate_code_generation Skill is triggered. It constructs a hermes run code_generator command and passes the original requirement as a Prompt to the code_generator Agent.
  5. The code_generator Agent starts in a new subprocess. Upon receiving the Prompt, it uses its own LLM capabilities and Persona (senior software engineer, focused on code generation) to generate Python code.
  6. The code_generator Agent outputs the generated code to standard output.
  7. The project_manager Agent's delegate_code_generation Skill captures the output from the code_generator Agent.
  8. Finally, the project_manager Agent returns the captured code as its final response to the user.

This demo clearly illustrates how an Orchestrator Agent can delegate tasks to specialized sub-Agents via Skills and integrate their results, achieving simple multi-agent collaboration.


🔧 Commands and Tools Involved

Command/Tool Description Notes
hermes setup Initializes Hermes Agent configuration, including loading Agent definitions. Ensures new Agent configurations are recognized by the system.
hermes run <agent_name> --prompt "..." Runs the specified Agent and provides it with an initial Prompt. This is the core method for inter-agent communication (Orchestrator Agent launching sub-Agents). The --no-interaction parameter is important when sub-Agents run.
hermes config set agent.<agent_name>.persona Sets or updates the Persona for a specific Agent. Used to define an Agent's role and behavior patterns, fundamental for collaboration.
hermes config set agent.<agent_name>.skills Adds or modifies Skills for an Agent. Encapsulates an Agent's capabilities and serves as the mechanism for inter-agent calls.
YAML configuration files Used to define an Agent's name, description, Persona, LLM model, and Skills. .yaml files in the ~/.hermes/agents/ directory are the carriers of Agent definitions.
subprocess.run (Python) Used in Python Skills to execute external commands, such as launching another Hermes Agent process. Key for implementing inter-agent calls within a Skill's execute method.
json (Python) Used to transfer structured data between Agents, such as task parameters. Ensures accuracy and parsability of information transfer.

📝 Key Takeaways from This Lesson

  • Necessity of Agent Collaboration: A single Agent has limitations when handling complex, multi-domain tasks. Multi-agent collaboration significantly enhances efficiency and robustness through specialization and task decomposition.
  • Diverse Communication Mechanisms: Hermes Agents primarily communicate and transfer information through Skill-based calls, shared file systems, and Orchestrator Agent orchestration.
  • Role Definition and Task Delegation: Defining clear Personas (roles) and capabilities (Skills) for each Agent is fundamental for successful collaboration; the Orchestrator Agent is responsible for task decomposition, delegation, and result aggregation, while specialized Agents execute specific subtasks.
  • Practical Considerations: Building a multi-agent team requires considering key factors such as Agent discovery, error handling, context management, performance optimization, and observability.
  • Skill-Driven Delegation: Implementing logic within an Orchestrator Agent's Skill to trigger the execution of sub-Agents is an effective way for Hermes to achieve agent collaboration.

🔗 References