🚀Transform your business with AI-powered process optimization
Architecture
💡 Design Patterns
Agent Design Patterns
Hierarchical Agent Pattern

Hierarchical Agent Pattern

The Hierarchical Agent Pattern organizes AI agents in a tree-like structure where higher-level agents coordinate and manage lower-level specialized agents.

Pattern Overview

This pattern creates a multi-level agent architecture where management agents delegate tasks to specialized worker agents, enabling scalable and organized problem-solving.

Structure

use std::collections::HashMap;
 
// Agent levels in hierarchy
#[derive(Debug, Clone)]
pub enum AgentLevel {
    Executive,
    Manager,
    Worker,
}
 
// Task types for different agent levels
#[derive(Debug, Clone)]
pub struct Task {
    pub id: String,
    pub task_type: String,
    pub complexity: u8,
    pub data: String,
}
 
// Base agent trait
pub trait HierarchicalAgent {
    fn get_level(&self) -> AgentLevel;
    fn can_handle(&self, task: &Task) -> bool;
    fn execute(&self, task: &Task) -> Result<String, String>;
    fn delegate(&self, task: &Task, subordinates: &[Box<dyn HierarchicalAgent>]) -> Result<String, String>;
}
 
// Executive agent - highest level
pub struct ExecutiveAgent {
    id: String,
}
 
impl ExecutiveAgent {
    pub fn new(id: &str) -> Self {
        Self { id: id.to_string() }
    }
}
 
impl HierarchicalAgent for ExecutiveAgent {
    fn get_level(&self) -> AgentLevel {
        AgentLevel::Executive
    }
 
    fn can_handle(&self, task: &Task) -> bool {
        task.complexity >= 8
    }
 
    fn execute(&self, task: &Task) -> Result<String, String> {
        Ok(format!("Executive {} analyzing strategic task: {}", self.id, task.id))
    }
 
    fn delegate(&self, task: &Task, subordinates: &[Box<dyn HierarchicalAgent>]) -> Result<String, String> {
        // Find appropriate manager
        for subordinate in subordinates {
            if subordinate.can_handle(task) {
                return subordinate.execute(task);
            }
        }
        Err("No suitable subordinate found".to_string())
    }
}
 
// Manager agent - middle level
pub struct ManagerAgent {
    id: String,
    department: String,
}
 
impl ManagerAgent {
    pub fn new(id: &str, department: &str) -> Self {
        Self {
            id: id.to_string(),
            department: department.to_string(),
        }
    }
}
 
impl HierarchicalAgent for ManagerAgent {
    fn get_level(&self) -> AgentLevel {
        AgentLevel::Manager
    }
 
    fn can_handle(&self, task: &Task) -> bool {
        task.complexity >= 4 && task.complexity < 8
    }
 
    fn execute(&self, task: &Task) -> Result<String, String> {
        Ok(format!("Manager {} in {} handling task: {}", self.id, self.department, task.id))
    }
 
    fn delegate(&self, task: &Task, subordinates: &[Box<dyn HierarchicalAgent>]) -> Result<String, String> {
        // Break down task and delegate to workers
        for subordinate in subordinates {
            if subordinate.can_handle(task) {
                return subordinate.execute(task);
            }
        }
        self.execute(task)
    }
}
 
// Worker agent - lowest level
pub struct WorkerAgent {
    id: String,
    specialty: String,
}
 
impl WorkerAgent {
    pub fn new(id: &str, specialty: &str) -> Self {
        Self {
            id: id.to_string(),
            specialty: specialty.to_string(),
        }
    }
}
 
impl HierarchicalAgent for WorkerAgent {
    fn get_level(&self) -> AgentLevel {
        AgentLevel::Worker
    }
 
    fn can_handle(&self, task: &Task) -> bool {
        task.complexity < 4 && task.task_type == self.specialty
    }
 
    fn execute(&self, task: &Task) -> Result<String, String> {
        Ok(format!("Worker {} executing {} task: {}", self.id, self.specialty, task.id))
    }
 
    fn delegate(&self, _task: &Task, _subordinates: &[Box<dyn HierarchicalAgent>]) -> Result<String, String> {
        Err("Worker agents cannot delegate".to_string())
    }
}

Usage Example

let executive = ExecutiveAgent::new("CEO");
let manager = ManagerAgent::new("PM1", "Analytics");
let worker = WorkerAgent::new("W1", "data_processing");
 
let task = Task {
    id: "T001".to_string(),
    task_type: "data_processing".to_string(),
    complexity: 3,
    data: "customer_data.csv".to_string(),
};
 
let subordinates: Vec<Box<dyn HierarchicalAgent>> = vec![
    Box::new(manager),
    Box::new(worker),
];
 
let result = executive.delegate(&task, &subordinates);

Benefits

  • Scalability: Handle complex problems through decomposition
  • Specialization: Agents focus on their expertise areas
  • Clear Authority: Well-defined chain of command
  • Load Distribution: Efficient task allocation across levels

Use Cases

  • Complex business process automation
  • Multi-stage data analysis pipelines
  • Organizational workflow modeling
  • Resource allocation and management